1import{_ as s,c as a,e,o as p}from"./app-CjUkjRdW.js";const t="/assets/kernel-helloworld-CPO1pHK9.png",l="/assets/kernel-wrong-memory-map-len-DW_b-ho0.png",i="/assets/kernel-correct-memory-map-len-DWj7zp78.png",o="/assets/kernel-exceptionhandling-BY5_9ryA.png",c={};function r(d,n){return p(),a("div",null,n[0]||(n[0]=[e(`<h1 id="loading-the-kernel-part-3" tabindex="-1"><a class="header-anchor" href="#loading-the-kernel-part-3"><span>Loading the Kernel (Part 3)</span></a></h1><p>Now that the bootloader exited UEFI Boot Services, it's time to transfer control to the kernel. This part should be fairly straightforward. We'll define a <code>KernelEntryPoint</code> proc type that matches the signature of the <code>KernelMain</code> proc, and use it to call the kernel entry point. Remember that we cannot print to the console anymore, since we exited the Boot Services.</p><p>First let's recall the <code>KernelMain</code> proc definition:</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/kernel/main.nim</span></span> 2<span class="line"></span> 3<span class="line"><span class="token keyword">import</span> common<span class="token operator">/</span><span class="token punctuation">[</span>libc<span class="token punctuation">,</span> malloc<span class="token punctuation">]</span></span> 4<span class="line"><span class="token keyword">import</span> debugcon</span> 5<span class="line"></span> 6<span class="line"><span class="token keyword">proc</span> <span class="token function">NimMain</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{.</span>importc<span class="token punctuation">.}</span></span> 7<span class="line"></span> 8<span class="line"><span class="token keyword">proc</span> <span class="token function">KernelMain</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{.</span>exportc<span class="token punctuation">.}</span> <span class="token operator">=</span></span> 9<span class="line"> <span class="token function">NimMain</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span> 10<span class="line"></span> 11<span class="line"> debugln <span class="token string">"Hello, world!"</span></span> 12<span class="line"> <span class="token function">quit</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span> 13<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>It's a simple proc that doesn't take any arguments (for now) and doesn't return anything. Let's define its type, cast the kernel address to that type, and call it.</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> 14<span class="line"></span> 15<span class="line highlighted"><span class="token keyword">type</span></span> 16<span class="line highlighted"> KernelEntryPoint <span class="token operator">=</span> <span class="token function">proc</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{.</span>cdecl<span class="token punctuation">.}</span></span> 17<span class="line"></span> 18<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>
18 EFiSystemTable<span class="token punctuation">)</span><span class="token operator">:</span> EfiStatus <span class="token operator">=</span></span> 19<span class="line"> <span class="token operator">...</span></span> 20<span class="line"></span> 21<span class="line highlighted"> <span class="token comment"># jump to kernel</span></span> 22<span class="line highlighted"> <span class="token keyword">let</span> kernelMain <span class="token operator">=</span> <span class="token function">cast[KernelEntryPoint]</span><span class="token punctuation">(</span>kernelImageBase<span class="token punctuation">)</span></span> 23<span class="line highlighted"> <span class="token function">kernelMain</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span> 24<span class="line"></span> 25<span class="line"> <span class="token comment"># we should never get here</span></span> 26<span class="line"> <span class="token function">quit</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span> 27<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></div><p>If we compile and run now, we should see the following output in the terminal (not in the QEMU window, since the kernel is printing to the QEMU debug console):</p><p><img src="`+t+`" alt="Kernel - Hello world"></p><p>Great! Our kernel is running! This is a big milestone. But we're not done with the bootloader handover yet. We still need to pass the memory map from the bootloader to the kernel (and later a few other things). We'll use this memory map later to implement a physical memory manager in the kernel.</p><h2 id="convert-uefi-memory-map" tabindex="-1"><a class="header-anchor" href="#convert-uefi-memory-map"><span>Convert UEFI memory map</span></a></h2><p>Ideally we shouldn't pass the UEFI memory map as is to the kernel. The memory map is a UEFI-specific data structure, and we don't want to tie the kernel to UEFI. Instead, we'll create our own memory map data structure that is independent of UEFI, and pass that to the kernel. Since this is going to be a data structure used by both the bootloader and the kernel, let's put it under the <code>common</code> folder in a module called <code>bootinfo.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/common/bootinfo.nim</span></span> 28<span class="line"></span> 29<span class="line"><span class="token keyword">type</span></span> 30<span class="line"> MemoryType<span class="token operator">*</span> <span class="token operator">=</span> <span class="token keyword">enum</span></span> 31<span class="line"> Free</span> 32<span class="line"> KernelCode</span> 33<span class="line"> KernelData</span> 34<span class="line"> KernelStack</span> 35<span class="line"> Reserved</span> 36<span class="line"></span> 37<span class="line"> MemoryMapEntry<span class="token operator">*</span> <span class="token operator">=</span> <span class="token keyword">object</span></span> 38<span class="line"> <span class="token identifier"><span class="token punctuation">\`</span>type<span class="token punctuation">\`</span></span><span class="token operator">*:</span> MemoryType</span> 39<span class="line"> start<span class="token operator">*:</span> uint64</span> 40<span class="line"> nframes<span class="token operator">*:</span> uint64</span> 41<span class="line"></span> 42<span class="line"> MemoryMap<span class="token operator">*</span> <span class="token operator">=</span> <span class="token keyword">object</span></span> 43<span class="line"> len<span class="token operator">*:</span> uint</span> 44<span class="line"> entries<span class="token operator">*:</span> <span class="token keyword">ptr</span> UncheckedArray<span class="token punctuation">[</span>MemoryMapEntry<span class="token punctuation">]</span></span> 45<span class="line"></span> 46<span class="line"> BootInfo<span class="token operator">*</span> <span class="token operator">=</span> <span class="token keyword">object</span></span> 47<span class="line">
47 physicalMemoryMap<span class="token operator">*:</span> MemoryMap</span> 48<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></div><p>Let's also add a proc in the bootloader to convert the UEFI memory map to our boot info 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> 49<span class="line"></span> 50<span class="line"><span class="token keyword">import</span> std<span class="token operator">/</span>sets</span> 51<span class="line"><span class="token operator">...</span></span> 52<span class="line"></span> 53<span class="line"><span class="token comment"># We use a HashSet here because the \`EfiMemoryType\` has values greater than 64K,</span></span> 54<span class="line"><span class="token comment"># which is the maximum value supported by Nim sets.</span></span> 55<span class="line"><span class="token keyword">const</span></span> 56<span class="line"> FreeMemoryTypes <span class="token operator">=</span> <span class="token punctuation">[</span></span> 57<span class="line"> EfiConventionalMemory<span class="token punctuation">,</span></span> 58<span class="line"> EfiBootServicesCode<span class="token punctuation">,</span></span> 59<span class="line"> EfiBootServicesData<span class="token punctuation">,</span></span> 60<span class="line"> EfiLoaderCode<span class="token punctuation">,</span></span> 61<span class="line"> EfiLoaderData<span class="token punctuation">,</span></span> 62<span class="line"> <span class="token punctuation">]</span><span class="token operator">.</span>toHashSet</span> 63<span class="line"></span> 64<span class="line"><span class="token keyword">proc</span> <span class="token function">convertUefiMemoryMap</span><span class="token punctuation">(</span></span> 65<span class="line"> uefiMemoryMap<span class="token operator">:</span> <span class="token keyword">ptr</span> UncheckedArray<span class="token punctuation">[</span>EfiMemoryDescriptor<span class="token punctuation">]</span><span class="token punctuation">,</span></span> 66<span class="line"> uefiMemoryMapSize<span class="token operator">:</span> uint<span class="token punctuation">,</span></span> 67<span class="line"> uefiMemoryMapDescriptorSize<span class="token operator">:</span> uint<span class="token punctuation">,</span></span> 68<span class="line"><span class="token punctuation">)</span><span class="token operator">:</span> seq<span class="token punctuation">[</span>MemoryMapEntry<span class="token punctuation">]</span> <span class="token operator">=</span></span> 69<span class="line"> <span class="token keyword">let</span> uefiNumMemoryMapEntries <span class="token operator">=</span> uefiMemoryMapSize <span class="token operator">div</span> uefiMemoryMapDescriptorSize</span> 70<span class="line"></span> 71<span class="line"> <span class="token keyword">for</span> i <span class="token operator">in</span> <span class="token number">0</span> <span class="token operator">..<</span> uefiNumMemoryMapEntries<span class="token operator">:</span></span> 72<span class="line"> <span class="token keyword">let</span> uefiEntry <span class="token operator">=</span> <span class="token function">cast[ptr EfiMemoryDescriptor]</span><span class="token punctuation">(</span></span> 73<span class="line">
73 <span class="token function">cast[uint64]</span><span class="token punctuation">(</span>uefiMemoryMap<span class="token punctuation">)</span> <span class="token operator">+</span> i <span class="token operator">*</span> uefiMemoryMapDescriptorSize</span> 74<span class="line"> <span class="token punctuation">)</span></span> 75<span class="line"> <span class="token keyword">let</span> memoryType <span class="token operator">=</span></span> 76<span class="line"> <span class="token keyword">if</span> uefiEntry<span class="token operator">.</span><span class="token keyword">type</span> <span class="token operator">in</span> FreeMemoryTypes<span class="token operator">:</span></span> 77<span class="line"> Free</span> 78<span class="line"> <span class="token keyword">elif</span> uefiEntry<span class="token operator">.</span><span class="token keyword">type</span> <span class="token operator">==</span> OsvKernelCode<span class="token operator">:</span></span> 79<span class="line"> KernelCode</span> 80<span class="line"> <span class="token keyword">elif</span> uefiEntry<span class="token operator">.</span><span class="token keyword">type</span> <span class="token operator">==</span> OsvKernelData<span class="token operator">:</span></span> 81<span class="line"> KernelData</span> 82<span class="line"> <span class="token keyword">elif</span> uefiEntry<span class="token operator">.</span><span class="token keyword">type</span> <span class="token operator">==</span> OsvKernelStack<span class="token operator">:</span></span> 83<span class="line"> KernelStack</span> 84<span class="line"> <span class="token keyword">else</span><span class="token operator">:</span></span> 85<span class="line"> Reserved</span> 86<span class="line"> result<span class="token operator">.</span><span class="token function">add</span><span class="token punctuation">(</span><span class="token function">MemoryMapEntry</span><span class="token punctuation">(</span></span> 87<span class="line"> <span class="token keyword">type</span><span class="token operator">:</span> memoryType<span class="token punctuation">,</span></span> 88<span class="line"> start<span class="token operator">:</span> uefiEntry<span class="token operator">.</span>physicalStart<span class="token punctuation">,</span></span> 89<span class="line"> nframes<span class="token operator">:</span> uefiEntry<span class="token operator">.</span>numberOfPages</span> 90<span class="line"> <span class="token punctuation">)</span><span class="token punctuation">)</span></span> 91<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 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>In order to pass the memory map to the kernel, it may seem that we can just pass a <code>BootInfo</code> instance to the kernel entry point. But keep in mind that the boot memory map is currently allocated both on the stack and the heap (the <code>entries</code> array) of the bootloader. We don't want the kernel to depend on memory in the bootloader, as we'll consider this memory as available once we're in the kernel. So, what we can do is use the UEFI <code>AllocatePool</code> method to allocate a single page of memory, use it to initialize a <code>BootInfo</code> instance, and pass its address to the kernel. We'll use memory type <code>OsvKernelData</code> for this memory, since it's memory that will be used by the kernel.</p><p>Let's add this part to the <code>EfiMainInner</code> proc:</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> 92<span class="line"></span> 93<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>
93 EFiSystemTable<span class="token punctuation">)</span><span class="token operator">:</span> EfiStatus <span class="token operator">=</span></span> 94<span class="line"> <span class="token operator">...</span></span> 95<span class="line"></span> 96<span class="line"> consoleOut <span class="token operator">&</span><span class="token string">"boot: Allocating memory for kernel stack (16 KiB)"</span></span> 97<span class="line"> <span class="token operator">...</span></span> 98<span class="line"></span> 99<span class="line highlighted"> consoleOut <span class="token operator">&</span><span class="token string">"boot: Allocating memory for BootInfo"</span></span> 100<span class="line highlighted"> <span class="token keyword">var</span> bootInfoBase<span class="token operator">:</span> uint64</span> 101<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> 102<span class="line highlighted"> AllocateAnyPages<span class="token punctuation">,</span></span> 103<span class="line highlighted"> OsvKernelData<span class="token punctuation">,</span></span> 104<span class="line highlighted"> <span class="token number">1</span><span class="token punctuation">,</span></span> 105<span class="line highlighted"> bootInfoBase<span class="token operator">.</span><span class="token keyword">addr</span><span class="token punctuation">,</span></span> 106<span class="line highlighted"> <span class="token punctuation">)</span></span> 107<span class="line"></span> 108<span class="line"> consoleOut <span class="token string">"boot: Reading kernel into memory"</span></span> 109<span class="line"> <span class="token operator">...</span></span> 110<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></div><p>Now, let's convert the UEFI memory map to the boot memory map using the <code>convertUefiMemoryMap</code> proc, and manually copy it to the <code>BootInfo</code> memory we just allocated:</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> 111<span class="line"></span> 112<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> 113<span class="line"> <span class="token operator">...</span></span> 114<span class="line"></span> 115<span class="line"> <span class="token comment"># ======= NO MORE UEFI BOOT SERVICES =======</span></span> 116<span class="line"></span> 117<span class="line"> <span class="token keyword">let</span> physMemoryMap <span class="token operator">=</span> <span class="token function">convertUefiMemoryMap</span><span class="token punctuation">(</span>memoryMap<span class="token punctuation">,</span> memoryMapSize<span class="token punctuation">,</span> memoryMapDescriptorSize<span class="token punctuation">)</span></span> 118<span class="line"></span> 119<span class="line"> <span class="token keyword">var</span> bootInfo <span class="token operator">=</span> <span class="token function">cast[ptr BootInfo]</span><span class="token punctuation">(</span>bootInfoBase<span class="token punctuation">)</span></span> 120<span class="line"></span> 121<span class="line"> <span class="token comment"># copy physical memory map entries to boot info</span></span> 122<span class="line"> bootInfo<span class="token operator">.</span>physicalMemoryMap<span class="token operator">.</span>len <span class="token operator">=</span> physMemoryMap<span class="token operator">.</span>len<span class="token operator">.</span>uint</span> 123<span class="line"> bootInfo<span class="token operator">.</span>physicalMemoryMap<span class="token operator">.</span>entries <span class="token operator">=</span></span> 124<span class="line"> <span class="token keyword">cast</span><span class="token punctuation">[</span><span class="token keyword">ptr</span> UncheckedArray<span class="token punctuation">[</span>MemoryMapEntry<span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">(</span>bootInfoBase <span class="token operator">+</span> <span class="token function">sizeof</span><span class="token punctuation">(</span>BootInfo<span class="token punctuation">)</span><span class="token operator">.</span>
124uint64<span class="token punctuation">)</span></span> 125<span class="line"> <span class="token keyword">for</span> i <span class="token operator">in</span> <span class="token number">0</span> <span class="token operator">..<</span> physMemoryMap<span class="token operator">.</span>len<span class="token operator">:</span></span> 126<span class="line"> bootInfo<span class="token operator">.</span>physicalMemoryMap<span class="token operator">.</span>entries<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">=</span> physMemoryMap<span class="token punctuation">[</span>i<span class="token punctuation">]</span></span> 127<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></div><p>What we're doing here is treating the start of the boot info page as a <code>BootInfo</code> instance. On line 12 & 13, we're pointing the <code>entries</code> field of the boot info memory map to the memory right after the boot info instance (instead of to some arbitrary heap memory). The last part just copies the entries from the original memory map to the boot info memory map.</p><h2 id="pass-bootinfo-to-kernel" tabindex="-1"><a class="header-anchor" href="#pass-bootinfo-to-kernel"><span>Pass BootInfo to kernel</span></a></h2><p>We're now ready to pass our memory map to the kernel. We'll change the signature of the <code>KernelMain</code> proc to take a <code>ptr BootInfo</code>. Let's change the <code>KernelMain</code> proc signature, and print the memory map length to the debug console to verify that we're getting the correct info.</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/kernel/main.nim</span></span> 128<span class="line"></span> 129<span class="line"><span class="token keyword">import</span> debugcon</span> 130<span class="line highlighted"><span class="token keyword">import</span> common<span class="token operator">/</span><span class="token punctuation">[</span>bootinfo<span class="token punctuation">,</span> libc<span class="token punctuation">,</span> malloc<span class="token punctuation">]</span></span> 131<span class="line"></span> 132<span class="line"><span class="token keyword">proc</span> <span class="token function">NimMain</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{.</span>importc<span class="token punctuation">.}</span></span> 133<span class="line"></span> 134<span class="line highlighted"><span class="token keyword">proc</span> <span class="token function">KernelMain</span><span class="token punctuation">(</span>bootInfo<span class="token operator">:</span> <span class="token keyword">ptr</span> BootInfo<span class="token punctuation">)</span> <span class="token punctuation">{.</span>exportc<span class="token punctuation">.}</span> <span class="token operator">=</span></span> 135<span class="line"> <span class="token function">NimMain</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span> 136<span class="line"></span> 137<span class="line highlighted"> debugln <span class="token string">"kernel: Fusion Kernel"</span></span> 138<span class="line highlighted"> debugln <span class="token operator">&</span><span class="token string">"kernel: Memory map length: {bootInfo.physicalMemoryMap.len}"</span></span> 139<span class="line"></span> 140<span class="line"> <span class="token function">quit</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span> 141<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></div><p>In the bootloader, we'll change the <code>KernelEntryPoint</code> type to match the new signature, convert the memory map, and pass it to the kernel through the <code>bootinfo</code> argument.</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> 142<span class="line"></span> 143<span class="line highlighted"><span class="token keyword">
143import</span> common<span class="token operator">/</span>bootinfo</span> 144<span class="line"><span class="token operator">...</span></span> 145<span class="line"></span> 146<span class="line"><span class="token keyword">type</span></span> 147<span class="line highlighted"> KernelEntryPoint <span class="token operator">=</span> <span class="token function">proc</span> <span class="token punctuation">(</span>bootInfo<span class="token operator">:</span> <span class="token keyword">ptr</span> BootInfo<span class="token punctuation">)</span> <span class="token punctuation">{.</span>cdecl<span class="token punctuation">.}</span></span> 148<span class="line"></span> 149<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> 150<span class="line"> <span class="token operator">...</span></span> 151<span class="line"></span> 152<span class="line highlighted"> <span class="token comment"># jump to kernel</span></span> 153<span class="line highlighted"> <span class="token keyword">let</span> kernelMain <span class="token operator">=</span> <span class="token function">cast[KernelEntryPoint]</span><span class="token punctuation">(</span>kernelImageBase<span class="token punctuation">)</span></span> 154<span class="line highlighted"> <span class="token function">kernelMain</span><span class="token punctuation">(</span>bootInfo<span class="token punctuation">)</span></span> 155<span class="line highlighted"></span> 156<span class="line highlighted"> <span class="token comment"># we should never get here</span></span> 157<span class="line highlighted"> <span class="token function">quit</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span> 158<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></div><p>Let's compile and run:</p><p><img src="`+l+`" alt="Kernel - Wrong memory map length"></p><p>Well, that didn't work as expected. We're getting a memory map length of <code>0</code>. This one actually took me a long while to figure out. The problem, it turns out, is a difference in the calling convention between the bootloader and the kernel.</p><h2 id="calling-convention" tabindex="-1"><a class="header-anchor" href="#calling-convention"><span>Calling convention</span></a></h2><p>Remember that the bootloader is compiled for the target <code>x86_64-unknown-windows</code>, and the kernel is compiled for <code>x86_64-unknown-elf</code>. This basically means that the bootloader is using the Microsoft x64 ABI, and the kernel is using the System V x64 ABI. Those two ABIs have different calling conventions; they pass parameters in different registers. The Microsoft x64 ABI passes the first four parameters in <code>rcx</code>, <code>rdx</code>, <code>r8</code>, and <code>r9</code>, whereas the System V x64 ABI passes the first six parameters in <code>rdi</code>, <code>rsi</code>, <code>rdx</code>, <code>rcx</code>, <code>r8</code>, and <code>r9</code>. So the bootloader is passing the memory map size in <code>rdx</code> (second parameter), but the kernel is expecting it in <code>rsi</code>. This is why we're getting a memory map size of <code>0</code>.</p><p>So how do we fix this? Ideally we can annotate the <code>KernelEntryPoint</code> type with the proper calling convention, but unfortunately Nim doesn't define a calling convention for the System V x64 ABI. So we have to take matters in our hands. One solution is emit some C code from Nim that allows us to define the entry point function type with the proper calling convention. The C compiler supports the Sys V ABI by annotating a function with <code>__attribute__((sysv_abi))</code>. But that's a bit too much for something simple.</p><p>Keep in mind that we also need to set up the kernel stack and switch to it before jumping to the kernel, and in a future section we'll also need to set up the kernel page tables and switch to them. So we'll need to write some assembly code anyway. Let's go ahead and do that. We'll pass the boot info address in <code>rdi</code> (first parameter), and we'll change the <code>rsp</code>
158 register to point to the top of the kernel stack region. Finally we'll <code>jmp</code> to the kernel entry point.</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> 159<span class="line"></span> 160<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> 161<span class="line"> <span class="token operator">...</span></span> 162<span class="line"></span> 163<span class="line highlighted"> <span class="token comment"># switch stacks and jump to kernel</span></span> 164<span class="line highlighted"> <span class="token keyword">let</span> kernelStackTop <span class="token operator">=</span> kernelStackBase <span class="token operator">+</span> KernelStackSize</span> 165<span class="line highlighted"> <span class="token keyword">asm</span> <span class="token string">"""</span> 166<span class="line highlighted"> mov rdi, %0 # bootInfo</span> 167<span class="line highlighted"> mov rsp, %1 # kernel stack top</span> 168<span class="line highlighted"> jmp %2 # kernel entry point</span> 169<span class="line highlighted"> :</span> 170<span class="line highlighted"> : "r"(\`bootInfoBase\`),</span> 171<span class="line highlighted"> "r"(\`kernelStackTop\`),</span> 172<span class="line highlighted"> "r"(\`KernelPhysicalBase\`)</span> 173<span class="line highlighted"> """</span></span> 174<span class="line highlighted"></span> 175<span class="line highlighted"> <span class="token comment"># we should never get here</span></span> 176<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></div><p>Let's compile and run:</p><p><img src="`+i+`" alt="Kernel - Correct memory map length"></p><p>Success! This time we're getting the correct memory map length.</p><h2 id="print-memory-map" tabindex="-1"><a class="header-anchor" href="#print-memory-map"><span>Print memory map</span></a></h2><p>Just to be sure, let's iterate over the memory map and print the memory type, start address, and number of pages of each entry. We'll also print the total size of free memory.</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/kernel/main.nim</span></span> 177<span class="line"><span class="token operator">...</span></span> 178<span class="line"></span> 179<span class="line"><span class="token keyword">proc</span> <span class="token function">KernelMain</span><span class="token punctuation">(</span>bootInfo<span class="token operator">:</span> <span class="token keyword">ptr</span> BootInfo<span class="token punctuation">)</span> <span class="token punctuation">{.</span>exportc<span class="token punctuation">.}</span> <span class="token operator">=</span></span> 180<span class="line"> <span class="token function">NimMain</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span> 181<span class="line"></span> 182<span class="line"> debugln <span class="token string">"kernel: Fusion Kernel"</span></span> 183<span class="line"></span> 184<span class="line highlighted"> debugln <span class="token string">""</span></span> 185<span class="line highlighted"> debugln <span class="token operator">&</span><span class="token string">"Memory Map ({bootInfo.physicalMemoryMap.len} entries):"</span></span> 186<span class="line highlighted"> debug <span class="token operator">&</span><span class="token string">""" {"Entry"}"""</span></span> 187<span class="line highlighted"> debug <span class="token operator">&</span><span class="token string">""" {"Type":12}"""</span></span> 188<span class="line highlighted"> debug <span class="token operator">&</span><span class="token string">""" {"Start":>12}"""</span></span> 189<span class="line highlighted"> debug <span class="token operator">&</span><span class="token string">""" {"Start (KB)":>15}"""</span></span> 190<span class="line highlighted"> debug <span class="token operator">&</span><span class="token string">""" {"#Pages":>10}"""</span></span> 191<span class="line highlighted"> debugln <span class="token string">""</span></span> 192<span class="line highlighted"></span> 193<span class="line highlighted"> <span class="token keyword">var</span> totalFreePages <span class="token operator">=</span> <span class="token number">0</span></span> 194<span class="line highlighted"> <span class="token keyword">
194for</span> i <span class="token operator">in</span> <span class="token number">0</span> <span class="token operator">..<</span> bootInfo<span class="token operator">.</span>physicalMemoryMap<span class="token operator">.</span>len<span class="token operator">:</span></span> 195<span class="line highlighted"> <span class="token keyword">let</span> entry <span class="token operator">=</span> bootInfo<span class="token operator">.</span>physicalMemoryMap<span class="token operator">.</span>entries<span class="token punctuation">[</span>i<span class="token punctuation">]</span></span> 196<span class="line highlighted"> debug <span class="token operator">&</span><span class="token string">" {i:>5}"</span></span> 197<span class="line highlighted"> debug <span class="token operator">&</span><span class="token string">" {entry.type:12}"</span></span> 198<span class="line highlighted"> debug <span class="token operator">&</span><span class="token string">" {entry.start:>#12x}"</span></span> 199<span class="line highlighted"> debug <span class="token operator">&</span><span class="token string">" {entry.start div 1024:>#15}"</span></span> 200<span class="line highlighted"> debug <span class="token operator">&</span><span class="token string">" {entry.nframes:>#10}"</span></span> 201<span class="line highlighted"> debugln <span class="token string">""</span></span> 202<span class="line highlighted"> <span class="token keyword">if</span> entry<span class="token operator">.</span><span class="token keyword">type</span> <span class="token operator">==</span> MemoryType<span class="token operator">.</span>Free<span class="token operator">:</span></span> 203<span class="line highlighted"> totalFreePages <span class="token operator">+=</span> entry<span class="token operator">.</span>nframes</span> 204<span class="line highlighted"></span> 205<span class="line highlighted"> debugln <span class="token string">""</span></span> 206<span class="line highlighted"> debugln <span class="token operator">&</span><span class="token string">"Total free: {totalFreePages * 4} KiB ({totalFreePages * 4 div 1024} MiB)"</span></span> 207<span class="line"></span> 208<span class="line"> <span class="token function">quit</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span> 209<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 class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>We should see the following output in the debug console:</p><div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text" data-title="text"><pre><code><span class="line">kernel: Fusion Kernel</span> 210<span class="line"></span> 211<span class="line">Memory Map (109 entries):</span> 212<span class="line"> Entry Type Start Start (KB) #Pages</span> 213<span class="line"> 0 Free 0x0 0 1</span> 214<span class="line"> 1 Free 0x1000 4 159</span> 215<span class="line"> 2 KernelCode 0x100000 1024 290</span> 216<span class="line"> 3 Free 0x222000 2184 1502</span> 217<span class="line"> 4 Reserved 0x800000 8192 8</span> 218<span class="line"> 5 Free 0x808000 8224 3</span> 219<span class="line"> 6 Reserved 0x80b000 8236 1</span> 220<span class="line"> 7 Free 0x80c000 8240 4</span> 221<span class="line"> 8 Reserved 0x810000 8256 240</span> 222<span class="line"> 9 Free 0x900000 9216 3712</span> 223<span class="line"> 10 Free 0x1780000 24064 9205</span> 224<span class="line"> 11 Free 0x3b75000 60884 32</span> 225<span class="line"> 12 Free 0x3b95000 61012 9887</span> 226<span class="line"> 13 Free 0x6234000 100560 292</span> 227<span class="line"> 14 Free 0x6358000 101728 19</span> 228<span class="line"> 15 Free 0x636b000 101804 2</span> 229<span class="line"> 16 KernelData 0x636d000 101812 1</span> 230<span class="line"> 17 KernelStack 0x636e000 101816 4</span> 231<span class="line"> 18 Free 0x6372000 101832 1781</span> 232<span class="line"> 19 Free 0x6a67000 108956 25</span> 233<span class="line"> 20 Free 0x6a80000 109056 2</span> 234<span class="line"> ...</span> 235<span class="line"> 99 Free 0x7e00000 129024 135</span> 236<span class="line"> 100 Free 0x7e87000 129564 32</span> 237<span class="line"> 101 Free 0x7ea7000 129692 35</span> 238<span class="line"> 102 Free 0x7eca000 129832 17</span> 239<span class="line"> 103 Free 0x7edb000 129900 25</span> 240<span class="line"> 104 Reserved 0x7ef4000 130000 132</span> 241<span class="line"> 105 Reserved 0x7f78000 130528 136</span> 242<span class="line"> 106 Reserved 0xe0000000 3670016 65536</span> 243<span class="line"> 107 Reserved 0xffc00000 4190208 1024</span> 244<span class="line"> 108 Reserved 0xfd00000000 1061158912 3145728</span> 245<span class="line"></span> 246<span class="line">Total free: 124296 KiB (121 MiB)</span> 247<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 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 memory map looks good. Notice that the kernel memory regions are marked properly.</p><h2 id="handling-nim-exceptions" tabindex="-1"><a class="header-anchor" href="#handling-nim-exceptions"><span>Handling Nim exceptions</span></a></h2><p>Before we move on to the next section, let's make sure we handle Nim exceptions properly at the top level of the kernel, similar to what we did with the bootloader. Let's define an <code>unhandledException</code> proc that prints the exception and stack trace and quits, and move the code in <code>KernelMain</code> to a new <code>KernelMainInner</code> proc.</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/kernel/main.nim</span></span> 248<span class="line"><span class="token operator">...</span></span> 249<span class="line"></span> 250<span class="line"><span class="token comment"># forward declarations</span></span> 251<span class="line"><span class="token keyword">proc</span> <span class="token function">NimMain</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{.</span>importc<span class="token punctuation">.}</span></span> 252<span class="line highlighted"><span class="token keyword">proc</span> <span class="token function">KernelMainInner</span><span class="token punctuation">(</span>bootInfo<span class="token operator">:</span> <span class="token keyword">ptr</span> BootInfo<span class="token punctuation">)</span></span> 253<span class="line highlighted"><span class="token keyword">proc</span> <span class="token function">unhandledException<span class="token operator">*</span></span><span class="token punctuation">(</span>e<span class="token operator">:</span> <span class="token keyword">ref</span> Exception<span class="token punctuation">)</span></span> 254<span class="line"></span> 255<span class="line"><span class="token keyword">proc</span> <span class="token function">KernelMain</span><span class="token punctuation">(</span>bootInfo<span class="token operator">:</span> <span class="token keyword">ptr</span> BootInfo<span class="token punctuation">)</span> <span class="token punctuation">{.</span>exportc<span class="token punctuation">.}</span> <span class="token operator">=</span></span> 256<span class="line"> <span class="token function">NimMain</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span> 257<span class="line"></span> 258<span class="line highlighted"> <span class="token keyword">try</span><span class="token operator">:</span></span> 259<span class="line highlighted"> <span class="token function">KernelMainInner</span><span class="token punctuation">(</span>bootInfo<span class="token punctuation">)</span></span> 260<span class="line highlighted"> <span class="token keyword">except</span> Exception <span class="token keyword">as</span>
260 e<span class="token operator">:</span></span> 261<span class="line highlighted"> <span class="token function">unhandledException</span><span class="token punctuation">(</span>e<span class="token punctuation">)</span></span> 262<span class="line"></span> 263<span class="line"> <span class="token function">quit</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span> 264<span class="line"></span> 265<span class="line highlighted"><span class="token keyword">proc</span> <span class="token function">KernelMainInner</span><span class="token punctuation">(</span>bootInfo<span class="token operator">:</span> <span class="token keyword">ptr</span> BootInfo<span class="token punctuation">)</span> <span class="token operator">=</span></span> 266<span class="line highlighted"> debugln <span class="token string">"kernel: Fusion Kernel"</span></span> 267<span class="line highlighted"> <span class="token operator">...</span></span> 268<span class="line"></span> 269<span class="line highlighted"><span class="token keyword">proc</span> <span class="token function">unhandledException<span class="token operator">*</span></span><span class="token punctuation">(</span>e<span class="token operator">:</span> <span class="token keyword">ref</span> Exception<span class="token punctuation">)</span> <span class="token operator">=</span></span> 270<span class="line highlighted"> debugln <span class="token string">""</span></span> 271<span class="line highlighted"> debugln <span class="token operator">&</span><span class="token string">"Unhandled exception: {e.msg} [{e.name}]"</span></span> 272<span class="line highlighted"> <span class="token keyword">if</span> e<span class="token operator">.</span>trace<span class="token operator">.</span>len <span class="token operator">></span> <span class="token number">0</span><span class="token operator">:</span></span> 273<span class="line highlighted"> debugln <span class="token string">""</span></span> 274<span class="line highlighted"> debugln <span class="token string">"Stack trace:"</span></span> 275<span class="line highlighted"> debugln <span class="token function">getStackTrace</span><span class="token punctuation">(</span>e<span class="token punctuation">)</span></span> 276<span class="line highlighted"> <span class="token function">quit</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span> 277<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>Let's test this by forcing an exception in <code>KernelMainInner</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/kernel/main.nim</span></span> 278<span class="line"></span> 279<span class="line"><span class="token keyword">proc</span> <span class="token function">KernelMainInner</span><span class="token punctuation">(</span>bootInfo<span class="token operator">:</span> <span class="token keyword">ptr</span> BootInfo<span class="token punctuation">)</span> <span class="token operator">=</span></span> 280<span class="line"> <span class="token comment"># force an IndexDefect exception</span></span> 281<span class="line"> <span class="token keyword">let</span> a <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">]</span></span> 282<span class="line"> <span class="token keyword">let</span> n <span class="token operator">=</span> <span class="token number">5</span></span> 283<span class="line"> <span class="token keyword">discard</span> a<span class="token punctuation">[</span>n<span class="token punctuation">]</span></span> 284<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><p>We should see the following output in the debug console:</p><p><img src="`+o+'" alt="Kernel - Exception handling"></p><p>Great! We're in a great place now. We can now switch our focus to the kernel, assuming full control of the system.</p><p>So where do we go from here? Ultimately we want to be able to run user programs in user space. This requires virtual memory support (using paging), where we divide the address space into two parts: the kernel space and the user space. Virtual memory requires a physical memory manager in order to allocate (and free) physical memory frames to back virtual memory pages. We already have a physical memory map, so we can use that to implement a physical memory manager. We'll do that in the next section.</p>',51)]))}const m=s(c,[["render",r],["__file","10-loading-the-kernel-p3.html.vue"]]),k=JSON.parse(`{"path":"/osdev/10-loading-the-kernel-p3.html","title":"Loading the Kernel (Part 3)","lang":"en-US","frontmatter":{},"headers":[{"level":2,"title":"Convert UEFI memory map","slug":"convert-uefi-memory-map","link":"#convert-uefi-memory-map","children":[]},{"level":2,"title":"Pass BootInfo to kernel","slug":"pass-bootinfo-to-kernel","link":"#pass-bootinfo-to-kernel","children":[]},{"level":2,"title":"Calling convention","slug":"calling-convention","link":"#calling-convention","children":[]},{"level":2,"title":"Print memory map","slug":"print-memory-map","link":"#print-memory-map","children":[]},{"level":2,"title":"Handling Nim exceptions","slug":"handling-nim-exceptions","link":"#handling-nim-exceptions","children":[]}
284],"git":{"updatedTime":1744638230000},"filePathRelative":"osdev/10-loading-the-kernel-p3.md","excerpt":"\\n<p>Now that the bootloader exited UEFI Boot Services, it's time to transfer control to the\\nkernel. This part should be fairly straightforward. We'll define a <code>KernelEntryPoint</code> proc\\ntype that matches the signature of the <code>KernelMain</code> proc, and use it to call the kernel\\nentry point. Remember that we cannot print to the console anymore, since we exited the\\nBoot Services.</p>"}`);export{m as comp,k 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.