PageSourceSearch

https://0xc0ffee.netlify.app/assets/04-targeting-uefi-p2.html-D3YDc-Vq.js

js 0xc0ffee.netlify.app collected 2026-10-03 10:23:12 UTC 18,894 bytes, 64 lines download raw bytes

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&#39;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&#39;ll define it by importing the C equivalent. Since we don&#39;t have something to write to yet, we&#39;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">&quot;const void *&quot;</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&#39;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&#39;t have an OS yet, there is nothing to return to, so we&#39;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">&quot;&quot;&quot;</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">  &quot;&quot;&quot;</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&#39;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&#39;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&#39;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&#39;t directly use the <code>libc</code> module functions in <code>main.nim</code>, we&#39;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&#39;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">&quot;const void *&quot;</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">&quot;&quot;&quot;</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">  &quot;&quot;&quot;</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&#39;
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&#39;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.