PageSourceSearch

https://0xc0ffee.netlify.app/assets/09-loading-the-kernel-p2.html-BQxll9jI.js

js 0xc0ffee.netlify.app collected 2026-10-03 10:23:25 UTC 44,897 bytes, 203 lines download raw bytes

1import{_ as n,c as a,e,o as i}from"./app-CjUkjRdW.js";const t="/assets/boot-closefiles-CE9W-vXS.png",l="/assets/boot-getmemorymap-DN4ymQIU.png",p="/assets/boot-exitbootserviceserror-DZhz2qY6.png",o="/assets/boot-exitbootservices-Dt2Rlx1o.png",c={};function r(d,s){return i(),a("div",null,s[0]||(s[0]=[e(`<h1 id="loading-the-kernel-part-2" tabindex="-1"><a class="header-anchor" href="#loading-the-kernel-part-2"><span>Loading the Kernel (Part 2)</span></a></h1><p>In the previous section, we located the kernel image and determined its size. In this section, we&#39;ll continue with our plan. We&#39;ll allocate memory for the kernel image, read it into memory, exit the Boot Services, and jump to the kernel image.</p><h2 id="allocate-memory" tabindex="-1"><a class="header-anchor" href="#allocate-memory"><span>Allocate memory</span></a></h2><p>We&#39;ll use the Boot Services <code>AllocatePages</code> function to allocate enough pages, starting at address <code>0x100000</code> (1 MiB), to hold the kernel image. We&#39;ll also allocate a region of memory for the kernel stack. Let&#39;s define the <code>AllocatePages</code> function, which also requires defining the <code>EfiAllocateType</code> and <code>EfiPhysicalAddress</code> types.</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/common/uefi.nim</span></span>
2<span class="line"></span>
3<span class="line"><span class="token keyword">type</span></span>
4<span class="line">  EfiBootServices<span class="token operator">*</span> <span class="token operator">=</span> <span class="token keyword">object</span></span>
5<span class="line">    <span class="token operator">...</span></span>
6<span class="line highlighted">    allocatePages<span class="token operator">*:</span> <span class="token function">proc</span> <span class="token punctuation">(</span></span>
7<span class="line highlighted">        allocateType<span class="token operator">:</span> EfiAllocateType<span class="token punctuation">,</span></span>
8<span class="line highlighted">        memoryType<span class="token operator">:</span> EfiMemoryType<span class="token punctuation">,</span></span>
9<span class="line highlighted">        pages<span class="token operator">:</span> uint<span class="token punctuation">,</span></span>
10<span class="line highlighted">        memory<span class="token operator">:</span> <span class="token keyword">ptr</span> EfiPhysicalAddress</span>
11<span class="line highlighted">      <span class="token punctuation">)</span><span class="token operator">:</span> EfiStatus <span class="token punctuation">{.</span>cdecl<span class="token punctuation">.}</span></span>
12<span class="line">    <span class="token operator">...</span></span>
13<span class="line"></span>
14<span class="line highlighted">  EfiAllocateType<span class="token operator">*</span> <span class="token operator">=</span> <span class="token keyword">enum</span></span>
15<span class="line highlighted">    AllocateAnyPages<span class="token punctuation">,</span></span>
16<span class="line highlighted">    AllocateMaxAddress<span class="token punctuation">,</span></span>
17<span class="line highlighted">    AllocateAddress<span class="token punctuation">,</span></span>
18<span class="line highlighted">    MaxAllocateType</span>
19<span class="line highlighted"></span>
20<span class="line highlighted">  EfiPhysicalAddress<span class="token operator">*</span> <span class="token operator">=</span> uint64</span>
21<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></div><p>The <code>EfiAllocateType</code> enum is used to specify the type of allocation. We&#39;ll use <code>AllocateAddress</code> to allocate pages for the kernel image, starting at a specific address (in our case, <code>0x100000</code>). The <code>EfiMemoryType</code> enum is used to specify the type of memory to allocate, which we&#39;ll set to <code>OsvKernelCode</code>. For the kernel stack, we&#39;ll use <code>AllocateAnyPages</code> to allocate any pages, and set the memory type to <code>OsvKernelStack</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/boot/bootx64.nim</span></span>
22<span class="line"></span>
23<span class="line highlighted"><span class="token keyword">const</span></span>
24<span class="line highlighted">  PageSize <span class="token operator">=</span> <span class="token number">4096</span></span>
25<span class="line highlighted">  KernelPhysicalBase <span class="token operator">=</span> <span class="token number">0x100000</span></span>
26<span class="line highlighted">
26  KernelStackSize <span class="token operator">=</span> <span class="token number">128</span> <span class="token operator">*</span> <span class="token number">1024&#39;u64</span></span>
27<span class="line"></span>
28<span class="line"><span class="token keyword">proc</span> <span class="token function">EfiMainInner</span><span class="token punctuation">(</span>imgHandle<span class="token operator">:</span> EfiHandle<span class="token punctuation">,</span> sysTable<span class="token operator">:</span> <span class="token keyword">ptr</span> EFiSystemTable<span class="token punctuation">)</span><span class="token operator">:</span> EfiStatus <span class="token operator">=</span></span>
29<span class="line">  <span class="token operator">...</span></span>
30<span class="line"></span>
31<span class="line highlighted">  consoleOut <span class="token operator">&amp;</span><span class="token string">&quot;boot: Allocating memory for kernel image &quot;</span></span>
32<span class="line highlighted">  <span class="token keyword">let</span> kernelImageBase <span class="token operator">=</span> <span class="token function">cast[pointer]</span><span class="token punctuation">(</span>KernelPhysicalBase<span class="token punctuation">)</span></span>
33<span class="line highlighted">  <span class="token keyword">let</span> kernelImagePages <span class="token operator">=</span> <span class="token punctuation">(</span>kernelInfo<span class="token operator">.</span>fileSize <span class="token operator">+</span> <span class="token number">0xFFF</span><span class="token punctuation">)</span><span class="token operator">.</span>uint <span class="token operator">div</span> PageSize<span class="token operator">.</span>uint <span class="token comment"># round up to nearest page</span></span>
34<span class="line highlighted">  checkStatus uefi<span class="token operator">.</span>sysTable<span class="token operator">.</span>bootServices<span class="token operator">.</span><span class="token function">allocatePages</span><span class="token punctuation">(</span></span>
35<span class="line highlighted">    AllocateAddress<span class="token punctuation">,</span></span>
36<span class="line highlighted">    OsvKernelCode<span class="token punctuation">,</span></span>
37<span class="line highlighted">    kernelImagePages<span class="token punctuation">,</span></span>
38<span class="line highlighted">    <span class="token function">cast[ptr EfiPhysicalAddress]</span><span class="token punctuation">(</span><span class="token keyword">addr</span> kernelImageBase<span class="token punctuation">)</span></span>
39<span class="line highlighted">  <span class="token punctuation">)</span></span>
40<span class="line highlighted"></span>
41<span class="line highlighted">  consoleOut <span class="token operator">&amp;</span><span class="token string">&quot;boot: Allocating memory for kernel stack (16 KiB) &quot;</span></span>
42<span class="line highlighted">  <span class="token keyword">var</span> kernelStackBase<span class="token operator">:</span> uint64</span>
43<span class="line highlighted">  <span class="token keyword">let</span> kernelStackPages <span class="token operator">=</span> KernelStackSize <span class="token operator">div</span> PageSize</span>
44<span class="line highlighted">  checkStatus uefi<span class="token operator">.</span>sysTable<span class="token operator">.</span>bootServices<span class="token operator">.</span><span class="token function">allocatePages</span><span class="token punctuation">(</span></span>
45<span class="line highlighted">    AllocateAnyPages<span class="token punctuation">,</span></span>
46<span class="line highlighted">    OsvKernelStack<span class="token punctuation">,</span></span>
47<span class="line highlighted">    kernelStackPages<span class="token punctuation">,</span></span>
48<span class="line highlighted">    kernelStackBase<span class="token operator">.</span><span class="token keyword">addr</span><span class="token punctuation">,</span></span>
49<span class="line highlighted">  <span class="token punctuation">)</span></span>
50<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 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><h2 id="read-kernel-image" tabindex="-1"><a class="header-anchor" href="#read-kernel-image"><span>Read kernel image</span></a></h2><p>The next step is to use the <code>read</code> function of the <code>EfiFileProtocol</code> to read the kernel image into memory. Let&#39;s define the <code>read</code> function.</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/common/uefi.nim</span></span>
51<span class="line"></span>
52<span class="line"><span class="token keyword">type</span></span>
53<span class="line">  EfiFileProtocol<span class="token operator">*</span> <span class="token operator">=</span> <span class="token keyword">object</span></span>
54<span class="line">    <span class="token operator">...</span></span>
55<span class="line highlighted">    read<span class="token operator">*:</span> <span class="token function">proc</span> <span class="token punctuation">(</span></span>
56<span class="line highlighted">        this<span class="token operator">:</span> <span class="token keyword">ptr</span> EfiFileProtocol<span class="token punctuation">,</span></span>
57<span class="line highlighted">        bufferSize<span class="token operator">:</span> <span class="token keyword">ptr</span>
57 uint<span class="token punctuation">,</span></span>
58<span class="line highlighted">        buffer<span class="token operator">:</span> pointer</span>
59<span class="line highlighted">      <span class="token punctuation">)</span><span class="token operator">:</span> EfiStatus <span class="token punctuation">{.</span>cdecl<span class="token punctuation">.}</span></span>
60<span class="line highlighted">  <span class="token operator">...</span></span>
61<span class="line highlighted"></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></div><p>We&#39;ll use the <code>read</code> function to read the kernel image into the memory we allocated earlier.</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/boot/bootx64.nim</span></span>
62<span class="line"></span>
63<span class="line"><span class="token keyword">proc</span> <span class="token function">EfiMainInner</span><span class="token punctuation">(</span>imgHandle<span class="token operator">:</span> EfiHandle<span class="token punctuation">,</span> sysTable<span class="token operator">:</span> <span class="token keyword">ptr</span> EFiSystemTable<span class="token punctuation">)</span><span class="token operator">:</span> EfiStatus <span class="token operator">=</span></span>
64<span class="line">  <span class="token operator">...</span></span>
65<span class="line"></span>
66<span class="line highlighted">  <span class="token comment"># read the kernel into memory</span></span>
67<span class="line highlighted">  consoleOut <span class="token string">&quot;boot: Reading kernel into memory&quot;</span></span>
68<span class="line highlighted">  checkStatus kernelFile<span class="token operator">.</span><span class="token function">read</span><span class="token punctuation">(</span>kernelFile<span class="token punctuation">,</span> <span class="token function">cast[ptr uint]</span><span class="token punctuation">(</span><span class="token keyword">addr</span> kernelInfo<span class="token operator">.</span>fileSize<span class="token punctuation">)</span><span class="token punctuation">,</span> kernelImageBase<span class="token punctuation">)</span></span>
69<span class="line highlighted"></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><h2 id="close-open-files" tabindex="-1"><a class="header-anchor" href="#close-open-files"><span>Close open files</span></a></h2><p>We&#39;re done with the kernel file and the root directory, so we can close them. It&#39;
69s not strictly needed, but I got in the habit of closing resources when I&#39;m done with them. Let&#39;s define the <code>close</code> function of the <code>EfiFileProtocol</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/common/uefi.nim</span></span>
70<span class="line"></span>
71<span class="line"><span class="token keyword">type</span></span>
72<span class="line">  EfiFileProtocol<span class="token operator">*</span> <span class="token operator">=</span> <span class="token keyword">object</span></span>
73<span class="line">    <span class="token operator">...</span></span>
74<span class="line highlighted">    close<span class="token operator">*:</span> <span class="token function">proc</span> <span class="token punctuation">(</span>this<span class="token operator">:</span> <span class="token keyword">ptr</span> EfiFileProtocol<span class="token punctuation">)</span><span class="token operator">:</span> EfiStatus <span class="token punctuation">{.</span>cdecl<span class="token punctuation">.}</span></span>
75<span class="line">    <span class="token operator">...</span></span>
76<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></div><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/boot/bootx64.nim</span></span>
77<span class="line"></span>
78<span class="line"><span class="token keyword">proc</span> <span class="token function">EfiMainInner</span><span class="token punctuation">(</span>imgHandle<span class="token operator">:</span> EfiHandle<span class="token punctuation">,</span> sysTable<span class="token operator">:</span> <span class="token keyword">ptr</span> EFiSystemTable<span class="token punctuation">)</span><span class="token operator">:</span> EfiStatus <span class="token operator">=</span></span>
79<span class="line">  <span class="token operator">...</span></span>
80<span class="line"></span>
81<span class="line highlighted">  <span class="token comment"># close the kernel file</span></span>
82<span class="line highlighted">  consoleOut <span class="token string">&quot;boot: Closing kernel file&quot;</span></span>
83<span class="line highlighted">  checkStatus kernelFile<span class="token operator">.</span><span class="token function">close</span><span class="token punctuation">(</span>kernelFile<span class="token punctuation">)</span></span>
84<span class="line highlighted"></span>
85<span class="line highlighted">  <span class="token comment"># close the root directory</span></span>
86<span class="line highlighted">  consoleOut <span class="token string">&quot;boot: Closing root directory&quot;</span></span>
87<span class="line highlighted">  checkStatus rootDir<span class="token operator">.</span><span class="token function">close</span><span class="token punctuation">(</span>rootDir<span class="token punctuation">)</span></span>
88<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></div><p><img src="`+t+`" alt="Boot - Close files"></p><h2 id="get-memory-map" tabindex="-1"><a class="header-anchor" href="#get-memory-map"><span>Get memory map</span></a></h2><p>In order to get the memory map, we have to allocate memory for the map itself. But how do we know how much memory to allocate? Calling <code>getMemoryMap</code> with a buffer size of <code>0</code> will return the required buffer size in the <code>memoryMapSize</code> output parameter. We can then allocate the required memory and call <code>getMemoryMap</code> again to get the actual memory map.</p><p>Let&#39;s define the <code>getMemoryMap</code> function first (and the associated <code>EfiMemoryDescriptor</code> and <code>EfiVirtualAddress</code> types). We&#39;ll also define the <code>allocatePool</code> function of the <code>EfiBootServices</code> type, which we&#39;ll use to allocate the memory for the memory map. (The difference between <code>allocatePages</code> and <code>allocatePool</code> is that <code>allocatePages</code> allocates memory in page-sized chunks, whereas <code>allocatePool</code> allocates memory in byte-sized chunks. <code>allocatePool</code> also provides more control over the address of the allocated memory, which is why we used it to allocate memory for the kernel.)</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/common/uefi.nim</span></span>
89<span class="line"></span>
90<span class="line"><span class="token keyword">type</span></span>
91<span class="line">  EfiBootServices<span class="token operator">*</span> <span class="token operator">=</span> <span class="token keyword">object</span></span>
92<span class="line">    <span class="token operator">...</span></span>
93<span class="line highlighted">    getMemoryMap<span class="token operator">*:</span> <span class="token function">proc</span> <span class="token punctuation">(</span></span>
94<span class="line highlighted">
94        memoryMapSize<span class="token operator">:</span> <span class="token keyword">ptr</span> uint<span class="token punctuation">,</span></span>
95<span class="line highlighted">        memoryMap<span class="token operator">:</span> <span class="token keyword">ptr</span> EfiMemoryDescriptor<span class="token punctuation">,</span></span>
96<span class="line highlighted">        mapKey<span class="token operator">:</span> <span class="token keyword">ptr</span> uint<span class="token punctuation">,</span></span>
97<span class="line highlighted">        descriptorSize<span class="token operator">:</span> <span class="token keyword">ptr</span> uint<span class="token punctuation">,</span></span>
98<span class="line highlighted">        descriptorVersion<span class="token operator">:</span> <span class="token keyword">ptr</span> uint32</span>
99<span class="line highlighted">      <span class="token punctuation">)</span><span class="token operator">:</span> EfiStatus <span class="token punctuation">{.</span>cdecl<span class="token punctuation">.}</span></span>
100<span class="line highlighted">    allocatePool<span class="token operator">*:</span> <span class="token function">proc</span> <span class="token punctuation">(</span></span>
101<span class="line highlighted">        poolType<span class="token operator">:</span> EfiMemoryType<span class="token punctuation">,</span></span>
102<span class="line highlighted">        size<span class="token operator">:</span> uint<span class="token punctuation">,</span></span>
103<span class="line highlighted">        buffer<span class="token operator">:</span> <span class="token keyword">ptr</span> pointer</span>
104<span class="line highlighted">      <span class="token punctuation">)</span><span class="token operator">:</span> EfiStatus <span class="token punctuation">{.</span>cdecl<span class="token punctuation">.}</span></span>
105<span class="line">    <span class="token operator">...</span></span>
106<span class="line"></span>
107<span class="line highlighted">  EfiMemoryDescriptor<span class="token operator">*</span> <span class="token operator">=</span> <span class="token keyword">object</span></span>
108<span class="line highlighted">    <span class="token identifier"><span class="token punctuation">\`</span>type<span class="token punctuation">\`</span></span><span class="token operator">*:</span> EfiMemoryType</span>
109<span class="line highlighted">    physicalStart<span class="token operator">*:</span> EfiPhysicalAddress</span>
110<span class="line highlighted">    virtualStart<span class="token operator">*:</span> EfiVirtualAddress</span>
111<span class="line highlighted">    numberOfPages<span class="token operator">*:</span> uint64</span>
112<span class="line highlighted">    attribute<span class="token operator">*:</span> uint64</span>
113<span class="line">  <span class="token operator">...</span></span>
114<span class="line"></span>
115<span class="line">  EfiPhysicalAddress<span class="token operator">*</span> <span class="token operator">=</span> uint64</span>
116<span class="line highlighted">  EfiVirtualAddress<span class="token operator">*</span> <span class="token operator">=</span> uint64</span>
117<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 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>Now we&#39;re ready to get the memory map.</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/boot/bootx64.nim</span></span>
118<span class="line"></span>
119<span class="line"><span class="token keyword">proc</span> <span class="token function">EfiMainInner</span><span class="token punctuation">(</span>imgHandle<span class="token operator">:</span> EfiHandle<span class="token punctuation">,</span> sysTable<span class="token operator">:</span> <span class="token keyword">ptr</span>
119 EFiSystemTable<span class="token punctuation">)</span><span class="token operator">:</span> EfiStatus <span class="token operator">=</span></span>
120<span class="line">  <span class="token operator">...</span></span>
121<span class="line"></span>
122<span class="line highlighted">  <span class="token comment"># memory map</span></span>
123<span class="line highlighted">  <span class="token keyword">var</span> memoryMapSize <span class="token operator">=</span> <span class="token number">0.u</span>int</span>
124<span class="line highlighted">  <span class="token keyword">var</span> memoryMap<span class="token operator">:</span> <span class="token keyword">ptr</span> UncheckedArray<span class="token punctuation">[</span>EfiMemoryDescriptor<span class="token punctuation">]</span></span>
125<span class="line highlighted">  <span class="token keyword">var</span> memoryMapKey<span class="token operator">:</span> uint</span>
126<span class="line highlighted">  <span class="token keyword">var</span> memoryMapDescriptorSize<span class="token operator">:</span> uint</span>
127<span class="line highlighted">  <span class="token keyword">var</span> memoryMapDescriptorVersion<span class="token operator">:</span> uint32</span>
128<span class="line highlighted"></span>
129<span class="line highlighted">  <span class="token comment"># get memory map size</span></span>
130<span class="line highlighted">  status <span class="token operator">=</span> uefi<span class="token operator">.</span>sysTable<span class="token operator">.</span>bootServices<span class="token operator">.</span><span class="token function">getMemoryMap</span><span class="token punctuation">(</span></span>
131<span class="line highlighted">    <span class="token keyword">addr</span> memoryMapSize<span class="token punctuation">,</span></span>
132<span class="line highlighted">    <span class="token function">cast[ptr EfiMemoryDescriptor]</span><span class="token punctuation">(</span><span class="token keyword">nil</span><span class="token punctuation">)</span><span class="token punctuation">,</span></span>
133<span class="line highlighted">    <span class="token function">cast[ptr uint]</span><span class="token punctuation">(</span><span class="token keyword">nil</span><span class="token punctuation">)</span><span class="token punctuation">,</span></span>
134<span class="line highlighted">    <span class="token function">cast[ptr uint]</span><span class="token punctuation">(</span><span class="token keyword">addr</span> memoryMapDescriptorSize<span class="token punctuation">)</span><span class="token punctuation">,</span></span>
135<span class="line highlighted">    <span class="token function">cast[ptr uint32]</span><span class="token punctuation">(</span><span class="token keyword">nil</span><span class="token punctuation">)</span></span>
136<span class="line highlighted">  <span class="token punctuation">)</span></span>
137<span class="line highlighted">  <span class="token comment"># increase memory map size to account for the next call to allocatePool</span></span>
138<span class="line highlighted">  inc memoryMapSize<span class="token punctuation">,</span> memoryMapDescriptorSize</span>
139<span class="line highlighted"></span>
140<span class="line highlighted">  <span class="token comment"># allocate pool for memory map (this changes the memory map size, hence the previous step)</span></span>
141<span class="line highlighted">  consoleOut <span class="token string">&quot;boot: Allocating pool for memory map&quot;</span></span>
142<span class="line highlighted">  checkStatus uefi<span class="token operator">.</span>sysTable<span class="token operator">.</span>bootServices<span class="token operator">.</span><span class="token function">allocatePool</span><span class="token punctuation">(</span></span>
143<span class="line highlighted">    EfiLoaderData<span class="token punctuation">,</span> memoryMapSize<span class="token punctuation">,</span> <span class="token function">cast[ptr pointer]</span><span class="token punctuation">(</span><span class="token keyword">addr</span> memoryMap<span class="token punctuation">)</span></span>
144<span class="line highlighted">  <span class="token punctuation">)</span></span>
145<span class="line highlighted"></span>
146<span class="line highlighted">  <span class="token comment"># now get the memory map</span></span>
147<span class="line highlighted">  consoleOut <span class="token string">&quot;boot: Getting memory map&quot;</span></span>
148<span class="line highlighted">  checkStatus uefi<span class="token operator">.</span>sysTable<span class="token operator">.</span>bootServices<span class="token operator">.</span><span class="token function">getMemoryMap</span><span class="token punctuation">(</span></span>
149<span class="line highlighted">    <span class="token keyword">addr</span>
149 memoryMapSize<span class="token punctuation">,</span></span>
150<span class="line highlighted">    <span class="token function">cast[ptr EfiMemoryDescriptor]</span><span class="token punctuation">(</span>memoryMap<span class="token punctuation">)</span><span class="token punctuation">,</span></span>
151<span class="line highlighted">    <span class="token keyword">addr</span> memoryMapKey<span class="token punctuation">,</span></span>
152<span class="line highlighted">    <span class="token keyword">addr</span> memoryMapDescriptorSize<span class="token punctuation">,</span></span>
153<span class="line highlighted">    <span class="token keyword">addr</span> memoryMapDescriptorVersion</span>
154<span class="line highlighted">  <span class="token punctuation">)</span></span>
155<span class="line highlighted"></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 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><img src="`+l+`" alt="Boot - Get memory map"></p><h2 id="exit-boot-services" tabindex="-1"><a class="header-anchor" href="#exit-boot-services"><span>Exit boot services</span></a></h2><p>We have all the information we need to exit the Boot Services. Let&#39;s define the <code>exitBootServices</code> function.</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/common/uefi.nim</span></span>
156<span class="line"></span>
157<span class="line"><span class="token keyword">type</span></span>
158<span class="line">  EfiBootServices<span class="token operator">*</span> <span class="token operator">=</span> <span class="token keyword">object</span></span>
159<span class="line">    <span class="token operator">...</span></span>
160<span class="line">    exitBootServices<span class="token operator">*:</span> <span class="token function">proc</span> <span class="token punctuation">(</span></span>
161<span class="line">        imageHandle<span class="token operator">:</span> EfiHandle<span class="token punctuation">,</span></span>
162<span class="line">        mapKey<span class="token operator">:</span> uint</span>
163<span class="line">      <span class="token punctuation">)</span><span class="token operator">:</span> EfiStatus <span class="token punctuation">{.</span>cdecl<span class="token punctuation">.}</span></span>
164<span class="line">    <span class="token operator">...</span></span>
165<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></div><p>The call to <code>exitBootServices</code> requires passing the <code>mapKey</code> that we got from <code>getMemoryMap</code>. This ensures that the memory map hasn&#39;t changed since we got it, otherwise the call will fail.</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/boot/bootx64.nim</span></span>
166<span class="line"></span>
167<span class="line"><span class="token keyword">proc</span> <span class="token function">EfiMainInner</span><span class="token punctuation">(</span>imgHandle<span class="token operator">:</span> EfiHandle<span class="token punctuation">,</span> sysTable<span class="token operator">:</span> <span class="token keyword">ptr</span>
167 EFiSystemTable<span class="token punctuation">)</span><span class="token operator">:</span> EfiStatus <span class="token operator">=</span></span>
168<span class="line">  <span class="token operator">...</span></span>
169<span class="line"></span>
170<span class="line">  <span class="token comment"># exit boot services</span></span>
171<span class="line">  consoleOut <span class="token string">&quot;boot: Exiting boot services&quot;</span></span>
172<span class="line">  checkStatus uefi<span class="token operator">.</span>sysTable<span class="token operator">.</span>bootServices<span class="token operator">.</span><span class="token function">exitBootServices</span><span class="token punctuation">(</span>imgHandle<span class="token punctuation">,</span> memoryMapKey<span class="token punctuation">)</span></span>
173<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><p>If we compile and run now, we are faced with the following error:</p><p><img src="`+p+`" alt="Boot - Exit boot services error"></p><p>Status code 2 is <code>EfiInvalidParameter</code>, which means that the <code>mapKey</code> we passed to <code>exitBootServices</code> is invalid. How can the <code>mapKey</code> be invalid if we just got it from <code>getMemoryMap</code>? This took me a while to figure out, but it turns out that merely printing to the console (or any other boot service call) may allocate memory, which changes the memory map. So basically we have to call <code>exitBootServices</code> immediately after getting the memory map, without calling any other boot service function in between. So, unfortunately, we&#39;ll have to give up printing to the console from that point on, until we transfer control to the kernel.</p><p>Let&#39;s change the call to <code>checkStatus</code> to avoid printing to the console (we&#39;ll only print to the console in case of an error).</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/boot/bootx64.nim</span></span>
174<span class="line"></span>
175<span class="line"><span class="token keyword">proc</span> <span class="token function">EfiMainInner</span><span class="token punctuation">(</span>imgHandle<span class="token operator">:</span> EfiHandle<span class="token punctuation">,</span> sysTable<span class="token operator">:</span> <span class="token keyword">ptr</span> EFiSystemTable<span class="token punctuation">)</span><span class="token operator">:</span> EfiStatus <span class="token operator">=</span></span>
176<span class="line">  <span class="token operator">...</span></span>
177<span class="line"></span>
178<span class="line">  <span class="token comment"># get memory map</span></span>
179<span class="line">  echo <span class="token string">&quot;boot: Getting memory map and exiting boot services&quot;</span></span>
180<span class="line highlighted">  status <span class="token operator">=</span> uefi<span class="token operator">.</span>sysTable<span class="token operator">.</span>bootServices<span class="token operator">.</span><span class="token function">getMemoryMap</span><span class="token punctuation">(</span></span>
181<span class="line">    <span class="token keyword">addr</span> memoryMapSize<span class="token punctuation">,</span></span>
182<span class="line">    <span class="token function">cast[ptr EfiMemoryDescriptor]</span><span class="token punctuation">(</span>memoryMap<span class="token punctuation">)</span><span class="token punctuation">,</span></span>
183<span class="line">    <span class="token keyword">addr</span>
183 memoryMapKey<span class="token punctuation">,</span></span>
184<span class="line">    <span class="token keyword">addr</span> memoryMapDescriptorSize<span class="token punctuation">,</span></span>
185<span class="line">    <span class="token keyword">addr</span> memoryMapDescriptorVersion</span>
186<span class="line">  <span class="token punctuation">)</span></span>
187<span class="line highlighted"></span>
188<span class="line highlighted">  <span class="token comment"># IMPORTANT: After this point we cannot output anything to the console, since doing</span></span>
189<span class="line highlighted">  <span class="token comment"># so may allocate memory and change the memory map, invalidating our map key. We can</span></span>
190<span class="line highlighted">  <span class="token comment"># only output to the console in case of an error (since we quit anyway).</span></span>
191<span class="line highlighted"></span>
192<span class="line highlighted">  <span class="token keyword">if</span> status <span class="token operator">!=</span> EfiSuccess<span class="token operator">:</span></span>
193<span class="line highlighted">    echo <span class="token operator">&amp;</span><span class="token string">&quot;boot: Failed to get memory map: {status:#x}&quot;</span></span>
194<span class="line highlighted">    <span class="token function">quit</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
195<span class="line highlighted"></span>
196<span class="line highlighted">  status <span class="token operator">=</span> uefi<span class="token operator">.</span>sysTable<span class="token operator">.</span>bootServices<span class="token operator">.</span><span class="token function">exitBootServices</span><span class="token punctuation">(</span>imgHandle<span class="token punctuation">,</span>
196 memoryMapKey<span class="token punctuation">)</span></span>
197<span class="line highlighted">  <span class="token keyword">if</span> status <span class="token operator">!=</span> EfiSuccess<span class="token operator">:</span></span>
198<span class="line highlighted">    echo <span class="token operator">&amp;</span><span class="token string">&quot;boot: Failed to exit boot services: {status:#x}&quot;</span></span>
199<span class="line highlighted">    <span class="token function">quit</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
200<span class="line highlighted"></span>
201<span class="line highlighted">  <span class="token comment"># ======= NO MORE UEFI BOOT SERVICES =======</span></span>
202<span class="line">  <span class="token operator">...</span></span>
203<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 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 time the call to <code>exitBootServices</code> should succeed, but we won&#39;t see a <code>[success]</code> message in the console. We&#39;ll know that it succeeded if no error messages are printed.</p><p><img src="`+o+'" alt="Boot - Exit boot services"></p><p>Great! We&#39;re done with the UEFI Boot Services. Now we&#39;re ready to jump to the kernel image. We&#39;ll do this in the next section.</p>',37)]))}const m=n(c,[["render",r],["__file","09-loading-the-kernel-p2.html.vue"]]),h=JSON.parse(`{"path":"/osdev/09-loading-the-kernel-p2.html","title":"Loading the Kernel (Part 2)","lang":"en-US","frontmatter":{},"headers":[{"level":2,"title":"Allocate memory","slug":"allocate-memory","link":"#allocate-memory","children":[]},{"level":2,"title":"Read kernel image","slug":"read-kernel-image","link":"#read-kernel-image","children":[]},{"level":2,"title":"Close open files","slug":"close-open-files","link":"#close-open-files","children":[]},{"level":2,"title":"Get memory map","slug":"get-memory-map","link":"#get-memory-map","children":[]},{"level":2,"title":"Exit boot services","slug":"exit-boot-services","link":"#exit-boot-services","children":[]}],"git":{"updatedTime":1744638230000},"filePathRelative":"osdev/09-loading-the-kernel-p2.md","excerpt":"\\n<p>In the previous section, we located the kernel image and determined its size. In this\\nsection, we'll continue with our plan. We'll allocate memory for the kernel image, read it\\ninto memory, exit the Boot Services, and jump to the kernel image.</p>\\n<h2>Allocate memory</h2>\\n<p>We'll use the Boot Services <code>AllocatePages</code> function to allocate enough pages, starting at\\naddress <code>0x100000</code> (1 MiB), to hold the kernel image. We'll also allocate a region of\\nmemory for the kernel stack. Let's define the <code>AllocatePages</code> function, which also\\nrequires defining the <code>EfiAllocateType</code> and <code>EfiPhysicalAddress</code> types.</p>"}`);export{m as comp,h 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.