1import{_ as s,c as a,e,o as t}from"./app-CjUkjRdW.js";const i={};function p(l,n){return t(),a("div",null,n[0]||(n[0]=[e(`<h1 id="targeting-uefi-part-2" tabindex="-1"><a class="header-anchor" href="#targeting-uefi-part-2"><span>Targeting UEFI (Part 2)</span></a></h1><p>In the previous section, we were faced with the need to implement a number of ANSI C library functions. Let's implement them now.</p><h2 id="c-library-functions" tabindex="-1"><a class="header-anchor" href="#c-library-functions"><span>C library functions</span></a></h2><h3 id="fwrite" tabindex="-1"><a class="header-anchor" href="#fwrite"><span><code>fwrite</code></span></a></h3><p>The <code>fwrite</code> function writes <code>count</code> elements of data, each <code>size</code> bytes long, to the stream pointed to by <code>stream</code>, obtaining them from the location given by <code>ptr</code>. It returns the number of elements successfully written.</p><div class="language-c line-numbers-mode" data-highlighter="prismjs" data-ext="c" data-title="c"><pre><code><span class="line"><span class="token class-name">size_t</span> <span class="token function">fwrite</span><span class="token punctuation">(</span><span class="token keyword">const</span> <span class="token keyword">void</span> <span class="token operator">*</span>ptr<span class="token punctuation">,</span> <span class="token class-name">size_t</span> size<span class="token punctuation">,</span> <span class="token class-name">size_t</span> count<span class="token punctuation">,</span> FILE <span class="token operator">*</span>stream<span class="token punctuation">)</span><span class="token punctuation">;</span></span> 2<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div></div></div><p>The <code>FILE *</code> struct pointer is already defined in Nim as <code>File</code>, so we can use that directly. <code>const void *</code>, however, has no equivalent type in Nim, so we'll define it by importing the C equivalent. Since we don't have something to write to yet, we'll just create a dummy implementation:</p><div class="language-nim line-numbers-mode" data-highlighter="prismjs" data-ext="nim" data-title="nim"><pre><code><span class="line"><span class="token comment"># src/libc.nim</span></span> 3<span class="line"></span> 4<span class="line"><span class="token keyword">type</span></span> 5<span class="line"> const_pointer <span class="token punctuation">{.</span>importc<span class="token operator">:</span> <span class="token string">"const void *"</span><span class="token punctuation">.}</span> <span class="token operator">=</span> pointer</span> 6<span class="line"></span> 7<span class="line"><span class="token keyword">proc</span> <span class="token function">fwrite<span class="token operator">*</span></span><span class="token punctuation">(</span><span class="token keyword">ptr</span><span class="token operator">:</span> const_pointer<span class="token punctuation">,</span> size<span class="token operator">:</span> csize_t<span class="token punctuation">,</span> count<span class="token operator">:</span> csize_t<span class="token punctuation">,</span> stream<span class="token operator">:</span> File<span class="token punctuation">)</span><span class="token operator">:</span></span> 8<span class="line"> csize_t <span class="token punctuation">{.</span>exportc<span class="token punctuation">.}</span> <span class="token operator">=</span></span> 9<span class="line"> <span class="token keyword">return</span> count</span> 10<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="fflush" tabindex="-1"><a class="header-anchor" href="#fflush"><span><code>fflush</code></span></a></h3><p>The <code>fflush</code> function flushes the stream pointed to by <code>stream</code>. It returns <code>0</code> on success, or <code>EOF</code> on error.</p><div class="language-c line-numbers-mode" data-highlighter="prismjs" data-ext="c" data-title="c"><pre><code><span class="line"><span class="token keyword">int</span> <span class="token function">fflush</span><span class="token punctuation">(</span>FILE <span class="token operator">*</span>stream<span class="token punctuation">)</span><span class="token punctuation">;</span></span> 11<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div></div></div><p>Again, we'll just create a dummy implementation for now:</p><div class="language-nim line-numbers-mode" data-highlighter="prismjs" data-ext="nim" data-title="nim"><pre><code><span class="line"><span class="token comment"># src/libc.nim</span></span> 12<span class="line"></span> 13<span class="line"><span class="token keyword">proc</span> <span class="token function">fflush<span class="token operator">*</span></span><span class="token punctuation">(</span>stream<span class="token operator">:</span> File<span class="token punctuation">)</span><span class="token operator">:</span> cint <span class="token punctuation">{.</span>exportc<span class="token punctuation">.}</span> <span class="token operator">=</span></span> 14<span class="line"> <span class="token keyword">return</span> <span class="token number">0.</span>cint</span> 15<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="stdout-stderr" tabindex="-1"><a class="header-anchor" href="#stdout-stderr"><span><code>stdout</code>/<code>stderr</code></span></a></h3><p>The <code>stdout</code> and <code>stderr</code> global variables are pointers to a <code>FILE</code> struct that represents the standard output and error streams.</p><div class="language-c line-numbers-mode" data-highlighter="prismjs" data-ext="c" data-title="c"><pre><code><span class="line">FILE <span class="token operator">*</span><span class="token constant">stdout</span><span class="token punctuation">;</span></span> 16<span class="line">FILE <span class="token operator">*</span><span class="token constant">stderr</span><span class="token punctuation">;</span></span> 17<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div></div></div><p>We can define them in Nim as a variable of type <code>File</code>, which will be initialized to <code>nil</code> by default:</p><div class="language-nim line-numbers-mode" data-highlighter="prismjs" data-ext="nim" data-title="nim"><pre><code><span class="line"><span class="token comment"># src/libc.nim</span></span> 18<span class="line"></span> 19<span class="line"><span class="token keyword">var</span></span> 20<span class="line"> stdout<span class="token operator">*</span> <span class="token punctuation">{.</span>exportc<span class="token punctuation">.}</span><span class="token operator">:</span> File</span> 21<span class="line"> stderr<span class="token operator">*</span> <span class="token punctuation">{.</span>exportc<span class="token punctuation">.}</span><span class="token operator">:</span> File</span> 22<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="exit" tabindex="-1"><a class="header-anchor" href="#exit"><span><code>exit</code></span></a></h3><p>The <code>exit</code> function causes normal process termination and the value of <code>status</code> is returned to the parent.</p><div class="language-c line-numbers-mode" data-highlighter="prismjs" data-ext="c" data-title="c"><pre><code><span class="line"><span class="token keyword">void</span> <span class="token function">exit</span><span class="token punctuation">(</span><span class="token keyword">int</span> status<span class="token punctuation">)</span><span class="token punctuation">;</span></span> 23<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div></div></div><p>Since we don't have an OS yet, there is nothing to return to, so we'll just halt the CPU using inline assembly:</p><div class="language-nim line-numbers-mode" data-highlighter="prismjs" data-ext="nim" data-title="nim"><pre><code><span class="line"><span class="token comment"># src/libc.nim</span></span> 24<span class="line"></span> 25<span class="line"><span class="token keyword">proc</span> <span class="token function">exit<span class="token operator">*</span></span><span class="token punctuation">(</span>status<span class="token operator">:</span> cint<span class="token punctuation">)</span> <span class="token punctuation">{.</span>exportc<span class="token punctuation">,</span> asmNoStackFrame<span class="token punctuation">.}</span> <span class="token operator">=</span></span> 26<span class="line"> <span class="token keyword">asm</span> <span class="token string">"""</span> 27<span class="line"> .loop:</span> 28<span class="line"> cli</span> 29<span class="line"> hlt</span> 30<span class="line"> jmp .loop</span> 31<span class="line"> """</span></span> 32<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>This clears the interrupt flag, then halts the CPU. The CPU can still be interrupted by NMI, SMI, or INIT interrupts, so that's why we have a loop to keep halting the CPU if this happens. The <code>
32asmNoStackFrame</code> pragma tells the compiler to not create a stack frame for this procedure, since it's pure assembly that we never return from.</p><h2 id="linking-the-c-library" tabindex="-1"><a class="header-anchor" href="#linking-the-c-library"><span>Linking the C library</span></a></h2><p>Now that we have implemented the missing library functions and exported them, we can link them into our executable. Let's import the <code>libc</code> module in <code>main.nim</code>:</p><div class="language-nim line-numbers-mode" data-highlighter="prismjs" data-ext="nim" data-title="nim"><pre><code><span class="line"><span class="token comment"># src/main.nim</span></span> 33<span class="line"></span> 34<span class="line"><span class="token keyword">import</span> libc</span> 35<span class="line"><span class="token operator">...</span></span> 36<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Since we don't directly use the <code>libc</code> module functions in <code>main.nim</code>, we'll get a warning that the module is unused. We can tell the compiler that the library will be used by adding the <code>{.used.}</code> pragma at the top of the <code>libc.nim</code> module.</p><p>Here's the complete <code>libc.nim</code> module:</p><div class="language-nim line-numbers-mode" data-highlighter="prismjs" data-ext="nim" data-title="nim"><pre><code><span class="line"><span class="token comment"># src/libc.nim</span></span> 37<span class="line"></span> 38<span class="line"><span class="token punctuation">{.</span>used<span class="token punctuation">.}</span></span> 39<span class="line"></span> 40<span class="line"><span class="token keyword">type</span></span> 41<span class="line"> const_pointer <span class="token punctuation">{.</span>importc<span class="token operator">:</span> <span class="token string">"const void *"</span><span class="token punctuation">.}</span> <span class="token operator">=</span> pointer</span> 42<span class="line"></span> 43<span class="line"><span class="token keyword">proc</span> <span class="token function">fwrite<span class="token operator">*</span></span><span class="token punctuation">(</span>buf<span class="token operator">:</span> const_pointer<span class="token punctuation">,</span> size<span class="token operator">:</span> csize_t<span class="token punctuation">,</span> count<span class="token operator">:</span> csize_t<span class="token punctuation">,</span> stream<span class="token operator">:</span> File<span class="token punctuation">)</span><span class="token operator">:</span> csize_t <span class="token punctuation">{.</span>exportc<span class="token punctuation">.}</span> <span class="token operator">=</span></span> 44<span class="line"> <span class="token keyword">return</span> <span class="token number">0.</span>csize_t</span> 45<span class="line"></span> 46<span class="line"><span class="token keyword">proc</span> <span class="token function">fflush<span class="token operator">*</span></span><span class="token punctuation">(</span>stream<span class="token operator">:</span> File<span class="token punctuation">)</span><span class="token operator">:</span> cint <span class="token punctuation">{.</span>exportc<span class="token punctuation">.}</span> <span class="token operator">=</span></span> 47<span class="line"> <span class="token keyword">return</span> <span class="token number">0.</span>cint</span> 48<span class="line"></span> 49<span class="line"><span class="token keyword">var</span></span> 50<span class="line"> stdout<span class="token operator">*</span> <span class="token punctuation">{.</span>exportc<span class="token punctuation">.}</span><span class="token operator">:</span> File</span> 51<span class="line"> stderr<span class="token operator">*</span> <span class="token punctuation">{.</span>exportc<span class="token punctuation">.}</span><span class="token operator">:</span> File</span> 52<span class="line"></span> 53<span class="line"><span class="token keyword">proc</span> <span class="token function">exit<span class="token operator">*</span></span><span class="token punctuation">(</span>status<span class="token operator">:</span> cint<span class="token punctuation">)</span> <span class="token punctuation">{.</span>exportc<span class="token punctuation">,</span> asmNoStackFrame<span class="token punctuation">.}</span> <span class="token operator">=</span></span> 54<span class="line"> <span class="token keyword">asm</span> <span class="token string">"""</span> 55<span class="line"> .loop:</span> 56<span class="line"> cli</span> 57<span class="line"> hlt</span> 58<span class="line"> jmp .loop</span> 59<span class="line"> """</span></span> 60<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Let'
60s compile and link our code:</p><div class="language-sh-session line-numbers-mode" data-highlighter="prismjs" data-ext="sh-session" data-title="sh-session"><pre><code><span class="line"><span class="token command"><span class="token shell-symbol important">$</span> <span class="token bash language-bash">nim c <span class="token parameter variable">--os:any</span> src/main.nim --out:build/main.exe</span></span></span> 61<span class="line"></span> 62<span class="line"><span class="token command"><span class="token shell-symbol important">$</span> <span class="token bash language-bash"><span class="token function">file</span> build/main.exe</span></span></span> 63<span class="line"><span class="token output">build/main.exe: PE32+ executable (EFI application) x86-64, for MS Windows, 4 sections</span> 64<span class="line"></span></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Great! We were able to compile and link our Nim code into a PE32+ executable that targets UEFI with no OS support. Now we're in good shape to start implementing our bootloader.</p>`,33)]))}const c=s(i,[["render",p],["__file","04-targeting-uefi-p2.html.vue"]]),r=JSON.parse(`{"path":"/osdev/04-targeting-uefi-p2.html","title":"Targeting UEFI (Part 2)","lang":"en-US","frontmatter":{},"headers":[{"level":2,"title":"C library functions","slug":"c-library-functions","link":"#c-library-functions","children":[{"level":3,"title":"fwrite","slug":"fwrite","link":"#fwrite","children":[]},{"level":3,"title":"fflush","slug":"fflush","link":"#fflush","children":[]},{"level":3,"title":"stdout/stderr","slug":"stdout-stderr","link":"#stdout-stderr","children":[]},{"level":3,"title":"exit","slug":"exit","link":"#exit","children":[]}]},{"level":2,"title":"Linking the C library","slug":"linking-the-c-library","link":"#linking-the-c-library","children":[]}],"git":{"updatedTime":1744638230000},"filePathRelative":"osdev/04-targeting-uefi-p2.md","excerpt":"\\n<p>In the previous section, we were faced with the need to implement a number of ANSI C\\nlibrary functions. Let's implement them now.</p>\\n<h2>C library functions</h2>\\n<h3><code>fwrite</code></h3>\\n<p>The <code>fwrite</code> function writes <code>count</code> elements of data, each <code>size</code> bytes long, to the\\nstream pointed to by <code>stream</code>, obtaining them from the location given by <code>ptr</code>. It returns\\nthe number of elements successfully written.</p>"}`);export{c as comp,r as data};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.