<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: BENKAY THE FIRST</title>
    <description>The latest articles on DEV Community by BENKAY THE FIRST (@benkaythe1st).</description>
    <link>https://dev.to/benkaythe1st</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F239145%2Ffda52511-e10d-45ce-87e9-55add72086d5.jpg</url>
      <title>DEV Community: BENKAY THE FIRST</title>
      <link>https://dev.to/benkaythe1st</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/benkaythe1st"/>
    <language>en</language>
    <item>
      <title>Building an Operating System In Rust Part 2</title>
      <dc:creator>BENKAY THE FIRST</dc:creator>
      <pubDate>Fri, 24 Jul 2026 10:12:51 +0000</pubDate>
      <link>https://dev.to/benkaythe1st/building-an-operating-system-in-rust-part-2-30ci</link>
      <guid>https://dev.to/benkaythe1st/building-an-operating-system-in-rust-part-2-30ci</guid>
      <description>&lt;p&gt;In &lt;a href="https://iambenkay.com/building-an-operating-system-in-rust-part-1/" rel="noopener noreferrer"&gt;Part 1 we built the foundation of our operating system using Rust&lt;/a&gt;, dove deep into murky low level waters and broke free from the shackles of stdlib while still keeping the compiler happy. Now we are going into the meat of it all - the entry point.&lt;/p&gt;

&lt;p&gt;Feel free to clone the &lt;a href="https://github.com/iambenkay/kluster/tree/part-2" rel="noopener noreferrer"&gt;source code for part 2&lt;/a&gt; from Github and follow along.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prepare for Entry
&lt;/h2&gt;

&lt;p&gt;When running programs on an operating system, there are a lot of things that are handled under the hood for us by the operating system. They are invisible to us and we take them for granted, we expect them to just work. In kernel space however, there are no training wheels, no invisible cogs turning in the background, everything is laid bare for us to see. Everything that works does so because we made it happen. It may sound overwhelming but it's this kind of foundational control that makes you truly appreciate how computers work at the lowest level.&lt;/p&gt;

&lt;p&gt;At the lowest level, the way a CPU executes instructions is very different from the mental model that high level languages try to paint. If you are familiar with assembly then you already know this. Let's look at some core concepts you need to know in order to fully get into the vibe of low level program execution:&lt;/p&gt;

&lt;h3&gt;
  
  
  Register
&lt;/h3&gt;

&lt;p&gt;Registers are ultra-fast, small-capacity temporary storage locations built directly into the CPU. They hold the exact data, instructions, or memory addresses the processor is currently working with, acting as the CPU’s immediate "scratchpad" before calculations are sent to the cache or main memory (RAM). There are general purpose registers and registers designed to perform a specific task.&lt;/p&gt;

&lt;h3&gt;
  
  
  Execution stack
&lt;/h3&gt;

&lt;p&gt;As instructions execute, the stack is a LIFO data structure used to keep track of the execution context which may include local variables, function parameters or return addresses.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stack pointer
&lt;/h3&gt;

&lt;p&gt;The stack pointer is a special CPU register that automatically tracks the top of the execution stack. In Aarch64, the stack grows downward, so logically it tracks the bottom of the stack pointer but the idea remains the same. When the CPU pushes into the stack, the stack pointer gets decremented and the entry is written to that address where the stack is pointing to. When the CPU pops from the stack, it reads the entry at the current stack pointer and then increments the stack pointer effectively freeing the previous memory slot.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://iambenkay.com/building-an-operating-system-in-rust-part-2/#:~:text=freeing%20the%20previous%20memory%20slot" rel="noopener noreferrer"&gt;See illustration here&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Instruction
&lt;/h3&gt;

&lt;p&gt;An instruction is the smallest unit of work that can be performed by a CPU. It takes one or more operands and stores it's result in a register depending on the operation. There are tons of instructions built into a CPU to perform almost any operation you can think of and it varies from CPU to CPU so you have to learn the Instruction Set of the CPU you are working with if you want to write Assembly for it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Program Counter
&lt;/h3&gt;

&lt;p&gt;The program counter is a special CPU register that always contains the memory location of the next instruction to execute. As soon as the CPU finishes executing an instruction it checks the program counter and goes on to execute the instruction at the location stored in the program counter. After the CPU reads the program counter, the program counter gets incremented to point to the next instruction and the cycle continues.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementing the boot image
&lt;/h2&gt;

&lt;p&gt;Now that we have a foundational understanding of the building blocks, let's write some assembly code for booting into our kernel. I know I promised we will write as much Rust as possible but this is one of those scenarios where Rust does not cut it. This part of the process cannot be handled by Rust because Rust expects a stack pointer to have already been set up so it is a chicken and egg problem. Remember, the training wheels are off and everything is being done manually so this is one time when we will have to drop down to Assembly in order to configure our entrypoint. This is a delicate point so I want you to pay as much attention as you can afford to.&lt;/p&gt;

&lt;p&gt;For your information, any code related to the entrypoint of a kernel is called the boot code. We will be writing the our boot code, or as I prefer to call it "boot image", in a bit but let us first structure our crate.&lt;/p&gt;

&lt;p&gt;Let's create a main function for our kernel in a new file &lt;code&gt;src/kernel.rs&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;loop&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This function will be called from our entrypoint and will handle all our kernel code but for now it just runs an infinite loop. Load this module in &lt;code&gt;src/main.rs&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;mod&lt;/span&gt; &lt;span class="n"&gt;kernel&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a file &lt;code&gt;src/processors/aarch64/bootimage.rs&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;core&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;arch&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;global_asm&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;global_asm!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nd"&gt;include_str!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"boot.S"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;CONST_CORE_ID_MASK&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="mi"&gt;0b11&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nd"&gt;#[unsafe(no_mangle)]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;_start_rust&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;crate&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;kernel&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is processor specific code. In this case it is expected to run only on aarch64 cpus. We load some assembly from the file &lt;code&gt;boot.S&lt;/code&gt; substituting a variable &lt;code&gt;CONST_CORE_ID_MASK&lt;/code&gt; in the assembly with the value &lt;code&gt;0b11&lt;/code&gt;. Then we define &lt;code&gt;fn _start_rust()&lt;/code&gt; which will serve as the first point of contact between assembly land and rust land. It calls our kernel main which we defined earlier. Note the &lt;code&gt;no_mangle&lt;/code&gt; directive. It is required in order for the name of the function to not become scrambled during compilation since we will be calling the function from Assembly.&lt;/p&gt;

&lt;p&gt;Then load the module in &lt;code&gt;src/processors/aarch64/mod.rs&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;mod&lt;/span&gt; &lt;span class="n"&gt;bootimage&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add the following content to &lt;code&gt;src/processors/aarch64/boot.S&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight actionscript"&gt;&lt;code&gt;&lt;span class="c1"&gt;//--------------------------------------------------------------------------------------------------&lt;/span&gt;
&lt;span class="c1"&gt;// Definitions&lt;/span&gt;
&lt;span class="c1"&gt;//--------------------------------------------------------------------------------------------------&lt;/span&gt;

&lt;span class="c1"&gt;// Load the address of a symbol into a register, PC-relative.&lt;/span&gt;
&lt;span class="c1"&gt;//&lt;/span&gt;
&lt;span class="c1"&gt;// The symbol must lie within +/- 4 GiB of the Program Counter.&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;macro&lt;/span&gt; &lt;span class="nx"&gt;ADR_REL&lt;/span&gt; &lt;span class="nx"&gt;register&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;symbol&lt;/span&gt;
    &lt;span class="nx"&gt;adrp&lt;/span&gt;    &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;register&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;symbol&lt;/span&gt;
    &lt;span class="nx"&gt;add&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;register&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;register&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;lo12&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;symbol&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;endm&lt;/span&gt;

&lt;span class="c1"&gt;//--------------------------------------------------------------------------------------------------&lt;/span&gt;
&lt;span class="c1"&gt;// Public Code&lt;/span&gt;
&lt;span class="c1"&gt;//--------------------------------------------------------------------------------------------------&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;section&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_start&lt;/span&gt;

&lt;span class="c1"&gt;//------------------------------------------------------------------------------&lt;/span&gt;
&lt;span class="c1"&gt;// fn _start()&lt;/span&gt;
&lt;span class="c1"&gt;//------------------------------------------------------------------------------&lt;/span&gt;
&lt;span class="nl"&gt;_start&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;// Only proceed on the boot core. Park it otherwise.&lt;/span&gt;
    &lt;span class="nx"&gt;mrs&lt;/span&gt; &lt;span class="nx"&gt;x0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;MPIDR_EL1&lt;/span&gt;
    &lt;span class="nx"&gt;and&lt;/span&gt; &lt;span class="nx"&gt;x0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;x0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;CONST_CORE_ID_MASK&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;ldr&lt;/span&gt; &lt;span class="nx"&gt;x1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;BOOT_CORE_ID&lt;/span&gt;      &lt;span class="c1"&gt;// provided by __board__/&amp;lt;board_name&amp;gt;/cpu.rs&lt;/span&gt;
    &lt;span class="nx"&gt;cmp&lt;/span&gt; &lt;span class="nx"&gt;x0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;x1&lt;/span&gt;
    &lt;span class="nx"&gt;bne&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;L_parking_loop&lt;/span&gt;

    &lt;span class="c1"&gt;// If execution reaches here, it is the boot core.&lt;/span&gt;

    &lt;span class="c1"&gt;// Initialize DRAM.&lt;/span&gt;
    &lt;span class="nx"&gt;ADR_REL&lt;/span&gt; &lt;span class="nx"&gt;x0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;__bss_start&lt;/span&gt;
    &lt;span class="nx"&gt;ADR_REL&lt;/span&gt; &lt;span class="nx"&gt;x1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;__bss_end_exclusive&lt;/span&gt;

&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;L_bss_init_loop&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="nx"&gt;cmp&lt;/span&gt; &lt;span class="nx"&gt;x0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;x1&lt;/span&gt;
    &lt;span class="nx"&gt;beq&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;L_prepare_rust&lt;/span&gt;
    &lt;span class="nx"&gt;stp&lt;/span&gt; &lt;span class="nx"&gt;xzr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;xzr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;x0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;
    &lt;span class="nx"&gt;b&lt;/span&gt;   &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;L_bss_init_loop&lt;/span&gt;

    &lt;span class="c1"&gt;// Prepare the jump to Rust code.&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;L_prepare_rust&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;// Set the stack pointer.&lt;/span&gt;
    &lt;span class="nx"&gt;ADR_REL&lt;/span&gt; &lt;span class="nx"&gt;x0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;__boot_core_stack_end_exclusive&lt;/span&gt;
    &lt;span class="nx"&gt;mov&lt;/span&gt; &lt;span class="nx"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;x0&lt;/span&gt;

    &lt;span class="c1"&gt;// Jump to Rust code.&lt;/span&gt;
    &lt;span class="nx"&gt;b&lt;/span&gt;   &lt;span class="nx"&gt;_start_rust&lt;/span&gt;

    &lt;span class="c1"&gt;// Infinitely wait for events (aka "park the core").&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;L_parking_loop&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="nx"&gt;wfe&lt;/span&gt;
    &lt;span class="nx"&gt;b&lt;/span&gt;   &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;L_parking_loop&lt;/span&gt;

&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;   &lt;span class="nx"&gt;_start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="err"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;_start&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;   &lt;span class="nx"&gt;_start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;global&lt;/span&gt; &lt;span class="nx"&gt;_start&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Whoa! That's a huge chunk of foreign code. Lucky you, I can demystify what's going on there. Let's take it apart line by line.&lt;/p&gt;

&lt;h3&gt;
  
  
  Assembly Breakdown
&lt;/h3&gt;

&lt;h4&gt;
  
  
  The ADR_REL macro
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight actionscript"&gt;&lt;code&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;macro&lt;/span&gt; &lt;span class="nx"&gt;ADR_REL&lt;/span&gt; &lt;span class="nx"&gt;register&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;symbol&lt;/span&gt;
    &lt;span class="nx"&gt;adrp&lt;/span&gt;    &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;register&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;symbol&lt;/span&gt;
    &lt;span class="nx"&gt;add&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;register&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;register&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;lo12&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;symbol&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;endm&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a two-instruction helper that loads the address of a symbol into a register in a PC-relative way (relative to the program counter, no absolute addressing, so the code works regardless of where it's loaded as long as the symbol is within ±4 GiB).&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;adrp&lt;/strong&gt; ("Address of Page") computes the 4 KiB-aligned page address containing the symbol, relative to the PC. So it gets you within 4 KiB of the symbol.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;add&lt;/strong&gt; … &lt;code&gt;#:lo12:symbol&lt;/code&gt; adds the low 12 bits of the symbol's address (the offset within the page) to finish the address.
Together they materialize an arbitrary symbol address with two instructions and no memory load. This matters because the BSS hasn't been zeroed yet and the stack isn't set; we can't yet rely on memory loads of address tables.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's use a practical example, Assume the Program Counter is at &lt;code&gt;0x00BC3000&lt;/code&gt;. We want to get the PC relative address of a symbol &lt;code&gt;msg&lt;/code&gt; which for the sake of this example is stored at &lt;code&gt;0x00BC5B70&lt;/code&gt;. The question that this macro answers is how to get that symbol's address into a register. First we get the page address of the symbol relative to the program counter. The way this works is by finding which 4KiB slice (called a page) the symbol's address falls into:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://iambenkay.com/building-an-operating-system-in-rust-part-2/#:~:text=the%20symbol%27s%20address%20falls%20into%3A" rel="noopener noreferrer"&gt;See illustration here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So we know that the symbol is 3 pages away from the program counter. Next we get the lower 12 bits of the symbol's address using &lt;code&gt;#:lo12:\symbol&lt;/code&gt;. Under the hood, this operation does this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="mi"&gt;0x00BC5B70&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mi"&gt;0xFFF&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0xB70&lt;/span&gt; &lt;span class="c1"&gt;// retains only the lower 12 bits&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we add the result to the page address to get the symbol address:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="mi"&gt;0x00BC5000&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;0xB70&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0x00BC5B70&lt;/span&gt; &lt;span class="c1"&gt;// returned by ADR_REL macro&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Code section
&lt;/h4&gt;

&lt;p&gt;Assembly code is organized into sections. Each section contains a sequence of instructions and directives that define a logical unit of our program. The following labels a new section named &lt;code&gt;.text._start&lt;/code&gt; which is the start of our code for this module:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight actionscript"&gt;&lt;code&gt;&lt;span class="c1"&gt;//--------------------------------------------------------------------------------------------------&lt;/span&gt;
&lt;span class="c1"&gt;// Public Code&lt;/span&gt;
&lt;span class="c1"&gt;//--------------------------------------------------------------------------------------------------&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;section&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_start&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Boot into primary CPU core
&lt;/h4&gt;

&lt;p&gt;The next piece of code is responsible for selecting one of the available cores as our primary core and parking the remaining cores. By default all the CPU cores will pick up the kernel and try to run it so this is a crucial step to disqualify all but one, our primary core.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight actionscript"&gt;&lt;code&gt;&lt;span class="nx"&gt;_start&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="nx"&gt;mrs&lt;/span&gt;   &lt;span class="nx"&gt;x0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;MPIDR_EL1&lt;/span&gt;
    &lt;span class="nx"&gt;and&lt;/span&gt;   &lt;span class="nx"&gt;x0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;x0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;CONST_CORE_ID_MASK&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;ldr&lt;/span&gt;   &lt;span class="nx"&gt;x1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;BOOT_CORE_ID&lt;/span&gt;
    &lt;span class="nx"&gt;cmp&lt;/span&gt;   &lt;span class="nx"&gt;x0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;x1&lt;/span&gt;
    &lt;span class="nx"&gt;bne&lt;/span&gt;   &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;L_parking_loop&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It starts by reading the value of the Multiprocessor Affinity Register, &lt;code&gt;MPIDR_EL1&lt;/code&gt; into register &lt;code&gt;x0&lt;/code&gt;. The system register &lt;code&gt;MPIDR_EL1&lt;/code&gt; identifies which CPU we're on, specifically the low bits which contain the core number. Assuming we are on raspberry pi 4 or 5 then there are only 4 CPUs available which can be represented with two bits. So the value of &lt;code&gt;MPIDR_EL1&lt;/code&gt; may look like this on the different cores:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Core 1 - 01110000
Core 2 - 01110001
Core 3 - 01110010
Core 4 - 01110011
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;so we need a mask that can select only the last two bits of this register value and that mask is &lt;code&gt;0b11&lt;/code&gt; because we can take any of the values and &lt;code&gt;AND&lt;/code&gt; them with this mask to retrieve the last two bits:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="mi"&gt;0b01110000&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mi"&gt;0b11&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0b00&lt;/span&gt;
&lt;span class="mi"&gt;0b01110001&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mi"&gt;0b11&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0b01&lt;/span&gt;
&lt;span class="mi"&gt;0b01110010&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mi"&gt;0b11&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0b10&lt;/span&gt;
&lt;span class="mi"&gt;0b01110011&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mi"&gt;0b11&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0b11&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We defined the mask &lt;code&gt;CONST_CORE_ID_MASK&lt;/code&gt; a while ago in &lt;code&gt;src/processors/aarch64/bootimage.rs&lt;/code&gt; and this is where it gets used. Depending on the board we are running on we can change this mask to &lt;code&gt;0b111&lt;/code&gt; to support up to 7 cores or &lt;code&gt;0b1111&lt;/code&gt; to support up to 15 cores.&lt;/p&gt;

&lt;p&gt;Next, we load the value of the variable &lt;code&gt;BOOT_CORE_ID&lt;/code&gt; (which we will define soon in Rust) and store that in the register &lt;code&gt;x1&lt;/code&gt;. At this point &lt;code&gt;x0&lt;/code&gt; contains the CPU number which the code is currently executing on and &lt;code&gt;x1&lt;/code&gt; contains the target CPU we want to take control while parking the rest. We compare their values and branch to the parking logic if &lt;code&gt;x0&lt;/code&gt; is not equal to &lt;code&gt;x1&lt;/code&gt;, else we continue execution.&lt;/p&gt;

&lt;p&gt;Before we continue describing our startup logic, let's define the &lt;code&gt;BOOT_CORE_ID&lt;/code&gt; variable that we used above. Create a file &lt;code&gt;src/motherboards/raspberrypi/cpu.rs&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;#[cfg(target_arch&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"aarch64"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
&lt;span class="nd"&gt;#[unsafe(no_mangle)]&lt;/span&gt;
&lt;span class="nd"&gt;#[unsafe(link_section&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;".text._start_arguments"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;BOOT_CORE_ID&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u64&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;link_section = ".text._start_arguments"&lt;/code&gt; adds a new section labelled &lt;code&gt;.text._start_arguments&lt;/code&gt; and the variable &lt;code&gt;BOOT_CORE_ID&lt;/code&gt; in that section. We are keeping the value as &lt;code&gt;0&lt;/code&gt; because we want to boot into the first core as our primary core.&lt;/p&gt;

&lt;p&gt;Create another file &lt;code&gt;src/motherboards/raspberrypi/mod.rs&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;mod&lt;/span&gt; &lt;span class="n"&gt;cpu&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then another file &lt;code&gt;src/motherboards/mod.rs&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;mod&lt;/span&gt; &lt;span class="n"&gt;raspberrypi&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and then add the module to &lt;code&gt;src/main.rs&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;mod&lt;/span&gt; &lt;span class="n"&gt;motherboards&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Initialize BSS
&lt;/h4&gt;

&lt;p&gt;The BSS is a data segment that stores uninitialized global and static variables. At startup we need to zero all the addresses within the BSS in preparation for uninitialized variables that will be stored in this segment. The following segment handles this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight actionscript"&gt;&lt;code&gt;    &lt;span class="c1"&gt;// If execution reaches here, it is the boot core.&lt;/span&gt;

    &lt;span class="c1"&gt;// Initialize DRAM.&lt;/span&gt;
    &lt;span class="nx"&gt;ADR_REL&lt;/span&gt; &lt;span class="nx"&gt;x0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;__bss_start&lt;/span&gt;
    &lt;span class="nx"&gt;ADR_REL&lt;/span&gt; &lt;span class="nx"&gt;x1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;__bss_end_exclusive&lt;/span&gt;

&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;L_bss_init_loop&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="nx"&gt;cmp&lt;/span&gt; &lt;span class="nx"&gt;x0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;x1&lt;/span&gt;
    &lt;span class="nx"&gt;beq&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;L_prepare_rust&lt;/span&gt;
    &lt;span class="nx"&gt;stp&lt;/span&gt; &lt;span class="nx"&gt;xzr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;xzr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;x0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;
    &lt;span class="nx"&gt;b&lt;/span&gt;   &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;L_bss_init_loop&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a simple routine that loads the start and end of the BSS into &lt;code&gt;x0&lt;/code&gt; and &lt;code&gt;x1&lt;/code&gt; using the symbols &lt;code&gt;__bss_start&lt;/code&gt; and &lt;code&gt;__bss_end_exclusive&lt;/code&gt; (will be defined later in the linker script). Then we recursively store zeroes in the memory locations stored in &lt;code&gt;x0&lt;/code&gt; and increment the memory location stored in &lt;code&gt;x0&lt;/code&gt; by &lt;code&gt;16&lt;/code&gt;. This continues until the memory location in &lt;code&gt;x0&lt;/code&gt; matches the end of bss stored in &lt;code&gt;x1&lt;/code&gt; then we branch to &lt;code&gt;.L_prepare_rust&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Jumping into Rust land
&lt;/h4&gt;

&lt;p&gt;The next piece of code is the bridge into our Rust code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight actionscript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Prepare the jump to Rust code.&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;L_prepare_rust&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;// Set the stack pointer.&lt;/span&gt;
    &lt;span class="nx"&gt;ADR_REL&lt;/span&gt; &lt;span class="nx"&gt;x0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;__boot_core_stack_end_exclusive&lt;/span&gt;
    &lt;span class="nx"&gt;mov&lt;/span&gt; &lt;span class="nx"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;x0&lt;/span&gt;

    &lt;span class="c1"&gt;// Jump to Rust code.&lt;/span&gt;
    &lt;span class="nx"&gt;b&lt;/span&gt;   &lt;span class="nx"&gt;_start_rust&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First we store the address of the end of the stack (configured later in the linker script) in &lt;code&gt;x0&lt;/code&gt;. Then we set the value of the stack pointer register to that address. Finally we branch to the label for our Rust entry point (defined in &lt;code&gt;src/processors/aarch64/bootimage.rs&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;The next piece of code just defines the label for our parking loop so the other cores know what to do after being disqualified from running the kernel:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight actionscript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Infinitely wait for events (aka "park the core").&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;L_parking_loop&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="nx"&gt;wfe&lt;/span&gt;
    &lt;span class="nx"&gt;b&lt;/span&gt;   &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;L_parking_loop&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lastly, we define some metadata for this assembly module at the very end:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight actionscript"&gt;&lt;code&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;   &lt;span class="nx"&gt;_start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="err"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;_start&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;   &lt;span class="nx"&gt;_start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;global&lt;/span&gt; &lt;span class="nx"&gt;_start&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first directive &lt;code&gt;.size&lt;/code&gt; computes the size of the routine &lt;code&gt;_start&lt;/code&gt;. The second directive &lt;code&gt;.type&lt;/code&gt; specifies the type of &lt;code&gt;_start&lt;/code&gt; which is a function. The last directive &lt;code&gt;.global&lt;/code&gt; makes the &lt;code&gt;_start&lt;/code&gt; label a global entity which can be referenced by other libraries.&lt;/p&gt;

&lt;p&gt;Summarily, here is the boot flow:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://iambenkay.com/building-an-operating-system-in-rust-part-2/#:~:text=Summarily%2C%20here%20is%20the%20boot%20flow%3A" rel="noopener noreferrer"&gt;See illustration here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We have implemented our boot image in pure Assembly. I hope you enjoyed that! One last important step before we can run our kernel for the first time is Linking.&lt;/p&gt;

&lt;h3&gt;
  
  
  Writing the Linker Script
&lt;/h3&gt;

&lt;p&gt;Linking is the glue for everything we have done. A linker is responsible for taking both the assembly code and the Rust code and linking them into one binary but we have to explicitly tell the linker how we want our code to be organized; we have to define the memory layout for our binary!&lt;/p&gt;

&lt;p&gt;Create the file &lt;code&gt;src/motherboards/raspberrypi/kernel.ld&lt;/code&gt; and add the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;__rpi_phys_dram_start_addr = 0;

/* The physical address at which the the kernel binary will be loaded by the Raspberry's firmware */
__rpi_phys_binary_load_addr = 0x80000;


ENTRY(__rpi_phys_binary_load_addr)

/* Flags:
 *     4 == R
 *     5 == RX
 *     6 == RW
 *
 * Segments are marked PT_LOAD below so that the ELF file provides virtual and physical addresses.
 * It doesn't mean all of them need actually be loaded.
 */
PHDRS
{
    segment_boot_core_stack PT_LOAD FLAGS(6);
    segment_code            PT_LOAD FLAGS(5);
    segment_data            PT_LOAD FLAGS(6);
}

SECTIONS
{
    . =  __rpi_phys_dram_start_addr;

    /***********************************************************************************************
    * Boot Core Stack
    ***********************************************************************************************/
    .boot_core_stack (NOLOAD) :
    {
                                             /*   ^             */
                                             /*   | stack       */
        . += __rpi_phys_binary_load_addr;    /*   | growth      */
                                             /*   | direction   */
        __boot_core_stack_end_exclusive = .; /*   |             */
    } :segment_boot_core_stack

    /***********************************************************************************************
    * Code + RO Data + Global Offset Table
    ***********************************************************************************************/
    .text :
    {
        KEEP(*(.text._start))
        *(.text._start_arguments) /* Constants (or statics in Rust speak) read by _start(). */
        *(.text._start_rust)      /* The Rust entry point */
        *(.text*)                 /* Everything else */
    } :segment_code

    .rodata : ALIGN(8) { *(.rodata*) } :segment_code

    /***********************************************************************************************
    * Data + BSS
    ***********************************************************************************************/
    .data : { *(.data*) } :segment_data

    /* Section is zeroed in pairs of u64. Align start and end to 16 bytes */
    .bss (NOLOAD) : ALIGN(16)
    {
        __bss_start = .;
        *(.bss*);
        . = ALIGN(16);
        __bss_end_exclusive = .;
    } :segment_data

    /***********************************************************************************************
    * Misc
    ***********************************************************************************************/
    .got : { *(.got*) }
    ASSERT(SIZEOF(.got) == 0, "Relocation support not expected")

    /DISCARD/ : { *(.comment*) }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above linker script is a lot to digest but let's take it step by step and see what makes it tick.&lt;/p&gt;

&lt;p&gt;First, we are declaring some link time variables that will be used by the rest of the script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;__rpi_phys_dram_start_addr = 0;

/* The physical address at which the the kernel binary will be loaded by the Raspberry's firmware */
__rpi_phys_binary_load_addr = 0x80000;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In Raspberry Pi Aarch64, the kernel image will be loaded into the address &lt;code&gt;0x80000&lt;/code&gt;. This is standard for Raspberry Pi running in 64 bit mode and will be different for different motherboards so we store the value here for use later in the script.&lt;/p&gt;

&lt;p&gt;Next line is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ENTRY(__rpi_phys_binary_load_addr)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It sets the ELF header's entry-point field to &lt;code&gt;0x80000&lt;/code&gt;. Some loaders use that field to decide where to jump; the Pi firmware ignores it and just jumps to &lt;code&gt;0x80000&lt;/code&gt; regardless. Still good practice to set it right.&lt;/p&gt;

&lt;p&gt;Then we have the program-header segments:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PHDRS
{
    segment_boot_core_stack PT_LOAD FLAGS(6);
    segment_code            PT_LOAD FLAGS(5);
    segment_data            PT_LOAD FLAGS(6);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ELF binaries describe memory in two layers: small sections for the linker (.text, .data, …) and bigger segments that an actual loader maps. PHDRS declares those segments and their permissions.&lt;/p&gt;

&lt;p&gt;PT*LOAD = "an ELF loader should make this segment exist in memory."&lt;br&gt;
FLAGS(...) bits: 4 = R, 5 = R+X, 6 = R+W.&lt;br&gt;
So you end up with three logical regions: the stack (RW), the code+rodata (RX), and the mutable data + BSS (RW). Each section below is assigned to one of these via the trailing :segment*… syntax.&lt;/p&gt;

&lt;p&gt;The next part is the meat of the script; sections. It walks down memory address-by-address and places things. Describes start and endpoints for the different sections in our binary:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SECTIONS
{
    . =  __rpi_phys_dram_start_addr;

    /***********************************************************************************************
    * Boot Core Stack
    ***********************************************************************************************/
    .boot_core_stack (NOLOAD) :
    {
                                             /*   ^             */
                                             /*   | stack       */
        . += __rpi_phys_binary_load_addr;    /*   | growth      */
                                             /*   | direction   */
        __boot_core_stack_end_exclusive = .; /*   |             */
    } :segment_boot_core_stack

    /***********************************************************************************************
    * Code + RO Data + Global Offset Table
    ***********************************************************************************************/
    .text :
    {
        KEEP(*(.text._start))
        *(.text._start_arguments) /* Constants (or statics in Rust speak) read by _start(). */
        *(.text._start_rust)      /* The Rust entry point */
        *(.text*)                 /* Everything else */
    } :segment_code

    .rodata : ALIGN(8) { *(.rodata*) } :segment_code

    /***********************************************************************************************
    * Data + BSS
    ***********************************************************************************************/
    .data : { *(.data*) } :segment_data

    /* Section is zeroed in pairs of u64. Align start and end to 16 bytes */
    .bss (NOLOAD) : ALIGN(16)
    {
        __bss_start = .;
        *(.bss*);
        . = ALIGN(16);
        __bss_end_exclusive = .;
    } :segment_data

    /***********************************************************************************************
    * Misc
    ***********************************************************************************************/
    .got : { *(.got*) }
    ASSERT(SIZEOF(.got) == 0, "Relocation support not expected")

    /DISCARD/ : { *(.comment*) }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The summary of what is going on is it defines the bounds of the Execution Stack, the actual code segment, and the data and BSS segment. I don't want to go too deep into the details of the linker script because it is vanity to master it all but feel free to discuss the details with any LLM in order to fully understand what is going on here.&lt;/p&gt;

&lt;p&gt;We are done with our boot image and at this stage we can boot our kernel on either a physical device or the QEMU emulator.&lt;br&gt;
Before we build, add the following to your Cargo.toml so that our Make script can run happily:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[features]&lt;/span&gt;
&lt;span class="py"&gt;default&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"device"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"rpi5"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="py"&gt;emulator&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"ltr-rgb"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="py"&gt;device&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="py"&gt;rpi5&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="py"&gt;rpi4&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="py"&gt;ltr-rgb&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We aren't using some of the features listed here yet but in due time we will cover them.&lt;/p&gt;

&lt;p&gt;Let's build and run the kernel on QEMU using our emulator:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cargo make emulate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see a black QEMU screen pop up with no errors just like this one:&lt;br&gt;
{{ image(src="/images/os-part2-result.png", alt="operating system on qemu part2 result") }}&lt;/p&gt;

&lt;p&gt;In order to run on a physical Raspberry Pi 5 device there is also a convenient cargo make task:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cargo make &lt;span class="nb"&gt;sync&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It attempts to copy the binary into a memory stick containing an existing Raspbian installation. Alter the task in &lt;code&gt;Makefile.toml&lt;/code&gt; so it gets copied into the right path.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this part, we implemented a boot image and successfully booted our kernel on a raspberry pi environment but we still have a blank screen. In &lt;a href="https://iambenkay.com/building-an-operating-system-in-rust-part-3/" rel="noopener noreferrer"&gt;Part 3 we will be writing to the display&lt;/a&gt;; in QEMU that's the screen but on Raspberry Pi 5 that is the HDMI output.&lt;/p&gt;

</description>
      <category>lowlevel</category>
      <category>assembly</category>
      <category>rust</category>
      <category>operatingsystem</category>
    </item>
    <item>
      <title>Building an Operating System In Rust Part 1</title>
      <dc:creator>BENKAY THE FIRST</dc:creator>
      <pubDate>Fri, 24 Jul 2026 09:48:23 +0000</pubDate>
      <link>https://dev.to/benkaythe1st/building-an-operating-system-in-rust-part-1-1ol</link>
      <guid>https://dev.to/benkaythe1st/building-an-operating-system-in-rust-part-1-1ol</guid>
      <description>&lt;p&gt;Building an operating system is a project I have had my eyes set on ever since I discovered free will in the realm of programming. Years ago, I did a reasonable amount of research, paying extra attention to the subject during my computer science degree and I was able to understand &lt;strong&gt;Operating System Theory&lt;/strong&gt; and how it works from first principles but I never really got around to building one. I had only flimsy reasons for not embarking on it like &lt;em&gt;"why build one when there are tons of working ones out there? The theoretical knowledge is enough"&lt;/em&gt;. More recently, I am ignoring the need to not re-invent the wheel for the joy of programming. So if you are interested in also rebuilding stuff because you can, join me on this series as I document how I am going to be building kluster.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/iambenkay/kluster" rel="noopener noreferrer"&gt;kluster&lt;/a&gt; is in its infancy and the direction is not clear but the one certain thing is that I will be building it entirely in Rust, save some assembly instructions and a linker script and I will be explaining every single line of code along the way. It will also be designed to target the raspberrypi 4 &amp;amp; 5, on qemu and on real hardware respectively. This is an opportunity for anyone who wants to see how Rust works at the lowest of levels to hop on and join the ride.&lt;/p&gt;

&lt;p&gt;Note that this series will be your biggest lesson on delayed gratification because we will write a lot of code before we even get to see anything meaningful on screen but I will foreshadow what you can get by the end of part 3 if you are patient enough:&lt;br&gt;
{{ image(src="/images/os-part3-result.png", alt="Part 3 Results OS Dev") }}&lt;/p&gt;

&lt;p&gt;You can also clone the &lt;a href="https://github.com/iambenkay/kluster/tree/part-1" rel="noopener noreferrer"&gt;source code for part 1&lt;/a&gt; from Github and follow along.&lt;/p&gt;
&lt;h2&gt;
  
  
  Project Setup
&lt;/h2&gt;

&lt;p&gt;First things first, let us setup the foundation of the project. I'll be straight with you, I love Rust and I enjoy using the Rust ecosystem in its entirety so I will stay true to that and use it as obsessively as any true Rustacean; I won't hold back. Without doubt, all the dependencies we need are freely available as long as you have a working Rust/Cargo installation.&lt;/p&gt;
&lt;h3&gt;
  
  
  Installing Rust
&lt;/h3&gt;

&lt;p&gt;I should assume you have the runtime if you are even opening any page with this title but for the benefit of doubt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--proto&lt;/span&gt; &lt;span class="s1"&gt;'=https'&lt;/span&gt; &lt;span class="nt"&gt;--tlsv1&lt;/span&gt;.2 &lt;span class="nt"&gt;-sSf&lt;/span&gt; https://sh.rustup.rs | sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the above command to install the Rust toolchain. If you already have the Rust toolchain then update it to the latest version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="n"&gt;rustup&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a new Rust binary crate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="n"&gt;cargo&lt;/span&gt; &lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;bin&lt;/span&gt; &lt;span class="n"&gt;op&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's do some plumbing to setup the foundation for the project.&lt;/p&gt;

&lt;h3&gt;
  
  
  Let there be night
&lt;/h3&gt;

&lt;p&gt;I will explain in a couple paragraphs why, but we need the rust nightly toolchain for this project so go ahead and install it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rustup toolchain &lt;span class="nb"&gt;install &lt;/span&gt;nightly
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also configure it as the default for this project by creating a file &lt;code&gt;rust-toolchain.toml&lt;/code&gt; in the root and adding the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[toolchain]&lt;/span&gt;
&lt;span class="py"&gt;channel&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"nightly"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For our OS we are also going to be targetting the Aarch64 CPU barebones so first we install the target:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rustup target add aarch64-unknown-none-softfloat
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we configure it as the default compilation target for this project by creating a file &lt;code&gt;.cargo/config.toml&lt;/code&gt; in the root and adding the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[build]&lt;/span&gt;
&lt;span class="py"&gt;target&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"aarch64-unknown-none-softfloat"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Build tools
&lt;/h3&gt;

&lt;p&gt;We need to install &lt;code&gt;llvm-tools&lt;/code&gt; on the nightly toolchain because we make use of &lt;code&gt;llvm-objcopy&lt;/code&gt; during the build process to turn the ELF into a raw kernel image. &lt;code&gt;cargo-binutils&lt;/code&gt; is a wrapper around the tools installed by &lt;code&gt;llvm-tools&lt;/code&gt; that allow them to work well with our cargo project and we will also be installing that.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rustup component add llvm-tools &lt;span class="nt"&gt;--toolchain&lt;/span&gt; nightly
cargo &lt;span class="nb"&gt;install &lt;/span&gt;cargo-binutils
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next we need to install &lt;code&gt;cargo-make&lt;/code&gt;. It will help us organize our build harness into smaller manageable tasks.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cargo &lt;span class="nb"&gt;install &lt;/span&gt;cargo-make
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Install the Emulator
&lt;/h3&gt;

&lt;p&gt;We need to install the emulator on which we will be running our Operating System. We will be using QEMU. I won't go into platform specific details on how to install QEMU but feel free to dig through the &lt;a href="https://www.qemu.org/download/#macos" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; to get your installation up and running.&lt;br&gt;
After installing it run this command to make sure you have raspi4b emulator installed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;qemu-system-aarch64 &lt;span class="nt"&gt;-M&lt;/span&gt; &lt;span class="nb"&gt;help&lt;/span&gt; | &lt;span class="nb"&gt;grep &lt;/span&gt;raspi4b
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that this OS will also be designed to target Raspberry Pi 5 hardware so if you have that then you are in luck.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting up the Makefile.toml
&lt;/h3&gt;

&lt;p&gt;In the spirit of using Rust from top to bottom we have opted for using &lt;code&gt;cargo make&lt;/code&gt; a build tool reminiscient of &lt;code&gt;make&lt;/code&gt; the C build tool.&lt;br&gt;
Cargo make is more modern and has a better syntax, we would be crazy not to go with it. Cargo make is a very flexible tool that can achieve almost any kind of configuration you are looking for. It is not in our best interest to cover all of its capabilities in this series but we will cover as many features as we end up using.&lt;/p&gt;

&lt;p&gt;Let us set up our &lt;code&gt;Makefile.toml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[env]&lt;/span&gt;
&lt;span class="py"&gt;RUSTFLAGS&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"-C target-cpu=cortex-a76 -C link-arg=--library-path=src/motherboards/raspberrypi -C link-arg=--script=kernel.ld"&lt;/span&gt;
&lt;span class="py"&gt;RUSTFLAGS_PI4&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"-C target-cpu=cortex-a72 -C link-arg=--library-path=src/motherboards/raspberrypi -C link-arg=--script=kernel.ld"&lt;/span&gt;

&lt;span class="nn"&gt;[tasks.compile]&lt;/span&gt;
&lt;span class="py"&gt;script&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="py"&gt;"RUSTFLAGS&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="err"&gt;${RUSTFLAGS}&lt;/span&gt; &lt;span class="err"&gt;cargo&lt;/span&gt; &lt;span class="err"&gt;objcopy&lt;/span&gt; &lt;span class="err"&gt;--release&lt;/span&gt;  &lt;span class="err"&gt;--&lt;/span&gt; &lt;span class="err"&gt;--strip-all&lt;/span&gt; &lt;span class="err"&gt;-O&lt;/span&gt; &lt;span class="err"&gt;binary&lt;/span&gt; &lt;span class="err"&gt;target/kernel_&lt;/span&gt;&lt;span class="mi"&gt;2712&lt;/span&gt;&lt;span class="err"&gt;.img&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;
&lt;span class="nn"&gt;[tasks.compile-emulate]&lt;/span&gt;
&lt;span class="py"&gt;script&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="py"&gt;"RUSTFLAGS&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="err"&gt;${RUSTFLAGS_PI&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt; &lt;span class="err"&gt;cargo&lt;/span&gt; &lt;span class="err"&gt;objcopy&lt;/span&gt; &lt;span class="err"&gt;--release&lt;/span&gt; &lt;span class="err"&gt;--no-default-features&lt;/span&gt; &lt;span class="err"&gt;--features&lt;/span&gt; &lt;span class="err"&gt;emulator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="err"&gt;rpi&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;  &lt;span class="err"&gt;--&lt;/span&gt; &lt;span class="err"&gt;--strip-all&lt;/span&gt; &lt;span class="err"&gt;-O&lt;/span&gt; &lt;span class="err"&gt;binary&lt;/span&gt; &lt;span class="err"&gt;target/kernel_&lt;/span&gt;&lt;span class="mi"&gt;2712&lt;/span&gt;&lt;span class="err"&gt;.img&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;
&lt;span class="nn"&gt;[tasks.sync]&lt;/span&gt;
&lt;span class="py"&gt;dependencies&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"compile"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="py"&gt;command&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"cp"&lt;/span&gt;
&lt;span class="py"&gt;args&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"target/kernel_2712.img"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"/Volumes/bootfs/kernel_2712.img"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="nn"&gt;[tasks.emulate]&lt;/span&gt;
&lt;span class="py"&gt;dependencies&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"compile-emulate"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="py"&gt;command&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"qemu-system-aarch64"&lt;/span&gt;
&lt;span class="py"&gt;args&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s"&gt;"-machine"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"raspi4b"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"-kernel"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"target/kernel_2712.img"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"-serial"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"stdio"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"-display"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"cocoa"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's go over everything that's happening here section by section:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[env]&lt;/span&gt;
&lt;span class="py"&gt;RUSTFLAGS&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"-C target-cpu=cortex-a76 -C link-arg=--library-path=src/motherboards/raspberrypi -C link-arg=--script=kernel.ld"&lt;/span&gt;
&lt;span class="py"&gt;RUSTFLAGS_PI4&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"-C target-cpu=cortex-a72 -C link-arg=--library-path=src/motherboards/raspberrypi -C link-arg=--script=kernel.ld"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;[env]&lt;/code&gt; directive is used to setup environment variables that all make tasks can inherit from and pass into their execution scope.&lt;br&gt;
Here we define two variables called &lt;code&gt;RUSTFLAGS&lt;/code&gt;. They are used to pass special configuration options to rustc during compilation. One is used when compiling for the Pi 4 and the other is used for the Pi 5.&lt;br&gt;
Next we have the compile tasks. These tasks are responsible for compiling the kernel into a raw image for either Pi 4 or Pi 5.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[tasks.compile]&lt;/span&gt;
&lt;span class="py"&gt;script&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="py"&gt;"RUSTFLAGS&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="err"&gt;${RUSTFLAGS}&lt;/span&gt; &lt;span class="err"&gt;cargo&lt;/span&gt; &lt;span class="err"&gt;objcopy&lt;/span&gt; &lt;span class="err"&gt;--release&lt;/span&gt;  &lt;span class="err"&gt;--&lt;/span&gt; &lt;span class="err"&gt;--strip-all&lt;/span&gt; &lt;span class="err"&gt;-O&lt;/span&gt; &lt;span class="err"&gt;binary&lt;/span&gt; &lt;span class="err"&gt;target/kernel_&lt;/span&gt;&lt;span class="mi"&gt;2712&lt;/span&gt;&lt;span class="err"&gt;.img&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;
&lt;span class="nn"&gt;[tasks.compile-emulate]&lt;/span&gt;
&lt;span class="py"&gt;script&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="py"&gt;"RUSTFLAGS&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="err"&gt;${RUSTFLAGS_PI&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt; &lt;span class="err"&gt;cargo&lt;/span&gt; &lt;span class="err"&gt;objcopy&lt;/span&gt; &lt;span class="err"&gt;--release&lt;/span&gt; &lt;span class="err"&gt;--no-default-features&lt;/span&gt; &lt;span class="err"&gt;--features&lt;/span&gt; &lt;span class="err"&gt;emulator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="err"&gt;rpi&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;  &lt;span class="err"&gt;--&lt;/span&gt; &lt;span class="err"&gt;--strip-all&lt;/span&gt; &lt;span class="err"&gt;-O&lt;/span&gt; &lt;span class="err"&gt;binary&lt;/span&gt; &lt;span class="err"&gt;target/kernel_&lt;/span&gt;&lt;span class="mi"&gt;2712&lt;/span&gt;&lt;span class="err"&gt;.img&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In one pass, cargo will first build the project, then run objcopy on the output and store the binary at the path we have provided. In the second task &lt;code&gt;compile-emulate&lt;/code&gt;, we have added some features to customize the build output namely &lt;code&gt;emulator&lt;/code&gt; and &lt;code&gt;rpi4&lt;/code&gt;. You will see how we use these features later in the code but for now just understand that they allow us include or exclude some lines of code from the final output depending on which machine we are targeting. It is worth mentioning at this stage that this kernel was not tested on a physical raspberry pi 4 device, rather it was set up on QEMU raspi4. It was however tested on a physical raspberry pi 5 device.&lt;/p&gt;

&lt;p&gt;You can try to run it on a physical raspberry pi 4 without the &lt;code&gt;emulator&lt;/code&gt; feature but I can't guarantee the success of your experiments in this direction. Of course if you run into any issues, leave a comment and I will respond with some advice on how to resolve them.&lt;/p&gt;

&lt;p&gt;Next we have the actual execution instructions for our operating system:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[tasks.sync]&lt;/span&gt;
&lt;span class="py"&gt;dependencies&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"compile"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="py"&gt;command&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"cp"&lt;/span&gt;
&lt;span class="py"&gt;args&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"target/kernel_2712.img"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"/Volumes/bootfs/kernel_2712.img"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The task named &lt;code&gt;sync&lt;/code&gt; is used for copying the raw kernel image to a hard drive containing a raspberry pi installation. As you can see it depends on the &lt;code&gt;compile&lt;/code&gt; task which compiles the raspberrypi 5 variant of our kernel. The process is pretty straightforward, burn a regular raspbian OS image to a drive or memory stick using Raspberry Pi Imager as you normally would. then update the above command such that it copies &lt;code&gt;kernel_2712.img&lt;/code&gt; into the root of the drive. Afterwards all you need to do is stick it into a physical Raspberry Pi 5 device and voila! You have your OS running; obviously not at this stage because we have not written any actual OS code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[tasks.emulate]&lt;/span&gt;
&lt;span class="py"&gt;dependencies&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"compile-emulate"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="py"&gt;command&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"qemu-system-aarch64"&lt;/span&gt;
&lt;span class="py"&gt;args&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s"&gt;"-machine"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"raspi4b"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"-kernel"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"target/kernel_2712.img"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"-serial"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"stdio"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"-display"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"cocoa"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The task named &lt;code&gt;emulate&lt;/code&gt; is used for spinning up a QEMU emulator running our raw kernel image. As per our configuration, it depends on &lt;code&gt;compile-emulate&lt;/code&gt; task which compiles the raspberrypi4 variant of our kernel.&lt;/p&gt;

&lt;p&gt;For fast iterative development, using the emulator is preferred but if you think plugging and unplugging a memory stick every time you want to test your changes is exciting then I am not going to stop you. Either approach will work with this tutorial, I have made sure of that.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building the Foundation
&lt;/h2&gt;

&lt;p&gt;Okay now that we have our project setup, let us discuss one of the most fundamental concepts in building an operating system, the entry point. When writing any kind of program, Your code needs to be loaded into a particular memory location in order for the CPU to start executing it. This is true for any kind of program not just operating systems. In higher level Rust, we define &lt;code&gt;fn main()&lt;/code&gt; and that becomes the entry point of the program but the only reason this works is because the compiler is designed to output object code placing the start of the main function at a memory location where the CPU is expecting it to be. In lower level environments like the one we are currently working in, we have to do everything manually. We have to configure our kernel so that the entry point is located where the CPU will be looking for code to execute. If we don't do this then the CPU cannot run the kernel.&lt;/p&gt;

&lt;p&gt;So let's update &lt;code&gt;src/main.rs&lt;/code&gt; to something more befitting of a low level project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;#![no_std]&lt;/span&gt;
&lt;span class="nd"&gt;#![no_main]&lt;/span&gt;
&lt;span class="nd"&gt;#![allow(internal_features)]&lt;/span&gt;
&lt;span class="nd"&gt;#![feature(lang_items)]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first directive &lt;code&gt;no_std&lt;/code&gt; simply tells the compiler that we want to build a freestanding binary without linking in the Rust standard library. Then &lt;code&gt;no_main&lt;/code&gt; allows us compile code that does not explicitly define a &lt;code&gt;fn main()&lt;/code&gt;. Like I said we are taking full control so the training wheels come off at this point. The next directive &lt;code&gt;allow(internal_features)&lt;/code&gt; is just a lint ignore that allows us to use the last directive &lt;code&gt;feature(lang_items)&lt;/code&gt; which is a special nightly feature gate (hence the nightly toolchain we installed at the beginning) that allows us to supply important behavior (like error handling) needed by the compiler in specific scenarios now that we are abandoning the training wheels.&lt;/p&gt;

&lt;p&gt;You should be getting an annoying error from rust-analyzer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;can't find crate for `test`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To fix it, go into &lt;code&gt;Cargo.toml&lt;/code&gt; and add the following lines to what is already there:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[[bin]]&lt;/span&gt;
&lt;span class="py"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"op_sys"&lt;/span&gt;
&lt;span class="py"&gt;path&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"src/main.rs"&lt;/span&gt;
&lt;span class="py"&gt;test&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="py"&gt;bench&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;

&lt;span class="nn"&gt;[profile.dev]&lt;/span&gt;
&lt;span class="py"&gt;panic&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"abort"&lt;/span&gt;

&lt;span class="nn"&gt;[profile.release]&lt;/span&gt;
&lt;span class="py"&gt;lto&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="py"&gt;panic&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"abort"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You see what we have just done is configure an explicit binary for our low level needs. We disabled test and bench so the compiler doesn't bootstrap the testing and benchmarking harnesses into our binary. We won't be needing that for our kernel anyways. Let's run cargo check to see if the coast is clear!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;error: `#[panic_handler]` function required, but not found
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Well the error is quite descriptive. Our dear compiler dumped std and put all its faith in us. Now we need to provide it with all the language items that it needs to function properly.&lt;/p&gt;

&lt;p&gt;Create a new file &lt;code&gt;src/panic_cfg.rs&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;core&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;PanicInfo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;#[panic_handler]&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_info&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;PanicInfo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="nd"&gt;#[lang&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"eh_personality"&lt;/span&gt;&lt;span class="nd"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="s"&gt;"C"&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;eh_personality&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then add the module to &lt;code&gt;src/main.rs&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;mod&lt;/span&gt; &lt;span class="n"&gt;panic_cfg&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we need to implement the panic handler. remove the dependencies section in &lt;code&gt;Cargo.toml&lt;/code&gt; and replace it with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[target.'cfg(target_arch = "aarch64")'.dependencies]&lt;/span&gt;
&lt;span class="py"&gt;aarch64-cpu&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="py"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"9.x.x"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This adds a new crate with which we can conveniently run Aarch64 CPU instructions from Rust land in a rusty way. For the first time, we are going to write code which is expected to run on only one CPU architecture, aarch64. We will structure our code so that we can easily extend the operating system to work on a matrix of CPUs and Motherboards.&lt;/p&gt;

&lt;p&gt;Create a new file &lt;code&gt;src/processors/aarch64/cpu.rs&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;aarch64_cpu&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;asm&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;#[inline(always)]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;wait_forever&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;loop&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nn"&gt;asm&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;wfe&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This function is really simple, it loops forever but with an interesting twist; it calls the &lt;code&gt;Wait-For-Event&lt;/code&gt; instruction in ASM in order to optimize the forever loop so that the processor can go into a low power sleep mode until an event is received. Let's link this file into the rest of our crate and use it in our panic handler.&lt;/p&gt;

&lt;p&gt;Create a file &lt;code&gt;src/processors/aarch64/mod.rs&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;mod&lt;/span&gt; &lt;span class="n"&gt;cpu&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then create &lt;code&gt;src/processors/mod.rs&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;mod&lt;/span&gt; &lt;span class="n"&gt;aarch64&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;#[cfg(target_arch&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"aarch64"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;aarch64&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;cpu&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;wait_forever&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Most of the code we are going to write will be either specific to a CPU type or specific to a motherboard so we will be doing this kind of modularization from the start so that our code is well organized and maintainable.&lt;/p&gt;

&lt;p&gt;Finally, add the following content to &lt;code&gt;src/main.rs&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;mod&lt;/span&gt; &lt;span class="n"&gt;processors&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can go back to &lt;code&gt;panic_cfg.rs&lt;/code&gt; and update the implementation of &lt;code&gt;fn panic()&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;#[panic_handler]&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_info&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;PanicInfo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;crate&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;processors&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;wait_forever&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point, &lt;code&gt;cargo check&lt;/code&gt; is no longer failing and if we run &lt;code&gt;cargo build&lt;/code&gt; it succeeds with a warning:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;warning: linker stderr: rust-lld: cannot find entry symbol _start; not setting start address
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Bro is looking for a way in but we have not provided any.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The binary is pretty much useless without a recognizable entry point but we have one foot in the door now. In &lt;a href="https://iambenkay.com/building-an-operating-system-in-rust-part-2/" rel="noopener noreferrer"&gt;Part 2 we are going to be implementing an entry point for our kernel&lt;/a&gt;&lt;/p&gt;

</description>
      <category>rust</category>
      <category>assembly</category>
      <category>operatingsystems</category>
      <category>lowlevel</category>
    </item>
    <item>
      <title>Concurrency in Golang</title>
      <dc:creator>BENKAY THE FIRST</dc:creator>
      <pubDate>Sun, 20 Dec 2020 19:06:01 +0000</pubDate>
      <link>https://dev.to/benkaythe1st/concurrency-in-golang-42bm</link>
      <guid>https://dev.to/benkaythe1st/concurrency-in-golang-42bm</guid>
      <description>&lt;p&gt;In golang, concurrency is made possible through the use of goroutines and channels.&lt;br&gt;
goroutines are basically "thread-like" lightweight structures that complete activities without blocking the main thread. They are basically a "fire and forget" cause go cleans up when a goroutine is completed. If however, we want to get data out of our goroutine process when it is done then we can use channels.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"fmt"&lt;/span&gt;

&lt;span class="c"&gt;// Essentially this is how we fire a goroutine&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;runForAWhile&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
  &lt;span class="c"&gt;// do something pretty that takes 5 secs or 2 yrs&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
  &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;runForAWhile&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"I am not waiting for that..."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once we use the &lt;code&gt;go&lt;/code&gt; keyword, Go knows to send the operation of that function out of the main scope and continue executing the rest of the code. The program does not end however until the goroutine is complete.&lt;br&gt;
When you run the above example, you'd notice that the &lt;code&gt;Println&lt;/code&gt; statement runs almost instantly while the program itself ends after the goroutine has supposedly ended.&lt;br&gt;
Channels are an effective way to wait on output from our goroutine before ending the program. Let's say we made two API calls using two goroutines, we surely want to get that result back into the main scope. Here is an example code that describes how you could achieve that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"fmt"&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;apiRequest1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
  &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
  &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;makeApiCall1&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;apiRequest2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
  &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
  &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;makeApiCall2&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
  &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;channel1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;channel2&lt;/span&gt; &lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
  &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;apiRequest1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;channel1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;apiRequest2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;channel2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="n"&gt;result1&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;channel1&lt;/span&gt;
  &lt;span class="n"&gt;result2&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;channel2&lt;/span&gt;

  &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;result2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>go</category>
      <category>concurrency</category>
      <category>programming</category>
    </item>
    <item>
      <title>How to write quality time-based tests in Golang</title>
      <dc:creator>BENKAY THE FIRST</dc:creator>
      <pubDate>Sun, 20 Dec 2020 07:33:28 +0000</pubDate>
      <link>https://dev.to/benkaythe1st/how-to-write-quality-time-based-tests-in-golang-3e08</link>
      <guid>https://dev.to/benkaythe1st/how-to-write-quality-time-based-tests-in-golang-3e08</guid>
      <description>&lt;p&gt;A few days ago, I decided to make a Pull Request of a feature I wrote myself for use at my company, a Rate-Limiting Middleware. Unlike other conventional middlewares in the package, rate-limiting is a really tricky one to write tests for because it requires a strictly time-based testing suite in order to test that it works as intended. Didn't seem like much to me at first. I wrote the tests and hit a 100% coverage and they all passed on my computer.&lt;/p&gt;

&lt;p&gt;Opened a PR at &lt;a href="https://github.com/labstack/echo" rel="noopener noreferrer"&gt;Echo&lt;/a&gt; and noticed that on some environments, tests passed, while they failed on others. After trying to make sense of it I noticed that there was no pattern, the failure was totally random and unpredictable. I studied the source code and tried to pin the fault on a particular unit but every thing seemed flawless. That was when I tried to study the only variable factor, time. Since my tests depended on the clock of the host computer and the system ticks are subject to lags when the CPU undergoes strain, my tests will most likely fail on systems that have lower CPU power because of lags during each tick.&lt;br&gt;
Here is a link to the Updated PR incase you want to see what is going on yourself:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/labstack/echo/pull/1724" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        adds middleware for rate limiting
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#1724&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/iambenkay" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars2.githubusercontent.com%2Fu%2F36256097%3Fv%3D4" alt="iambenkay avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/iambenkay" rel="noopener noreferrer"&gt;iambenkay&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/labstack/echo/pull/1724" rel="noopener noreferrer"&gt;&lt;time&gt;Dec 17, 2020&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;h1&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;What's New?&lt;/h1&gt;
&lt;p&gt;This feature implements a store agnostic rate limiting middleware i.e configurable with any store of user's choice.&lt;/p&gt;
&lt;p&gt;Here is a dummy snippet of how a certain (unconventional) redis store might be integrated with the rate limiting middleware&lt;/p&gt;
&lt;div class="highlight highlight-source-go js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-k"&gt;type&lt;/span&gt; &lt;span class="pl-smi"&gt;RedisStore&lt;/span&gt; &lt;span class="pl-k"&gt;struct&lt;/span&gt; {
   &lt;span class="pl-c1"&gt;client&lt;/span&gt; redis.&lt;span class="pl-smi"&gt;Client&lt;/span&gt;
}

&lt;span class="pl-c"&gt;// Store config must implement Allow for rate limiting middleware&lt;/span&gt;
&lt;span class="pl-k"&gt;func&lt;/span&gt; (&lt;span class="pl-s1"&gt;store&lt;/span&gt; &lt;span class="pl-c1"&gt;*&lt;/span&gt;&lt;span class="pl-smi"&gt;RedisStore&lt;/span&gt;) &lt;span class="pl-en"&gt;Allow&lt;/span&gt;(&lt;span class="pl-smi"&gt;identifier&lt;/span&gt;) &lt;span class="pl-smi"&gt;bool&lt;/span&gt; {
   &lt;span class="pl-c"&gt;// run logic here that decides if user should be permitted&lt;/span&gt;
   &lt;span class="pl-k"&gt;return&lt;/span&gt; &lt;span class="pl-c1"&gt;true&lt;/span&gt;
}

&lt;span class="pl-k"&gt;func&lt;/span&gt; &lt;span class="pl-en"&gt;main&lt;/span&gt;(){
   &lt;span class="pl-s1"&gt;e&lt;/span&gt; &lt;span class="pl-c1"&gt;:=&lt;/span&gt; &lt;span class="pl-s1"&gt;echo&lt;/span&gt;.&lt;span class="pl-en"&gt;New&lt;/span&gt;()

   &lt;span class="pl-s1"&gt;redisStore&lt;/span&gt; &lt;span class="pl-c1"&gt;:=&lt;/span&gt; &lt;span class="pl-smi"&gt;RedisStore&lt;/span&gt;{
      &lt;span class="pl-c1"&gt;client&lt;/span&gt;: redis.&lt;span class="pl-smi"&gt;Client&lt;/span&gt;{}
   }
   
   &lt;span class="pl-s1"&gt;limiterMW&lt;/span&gt; &lt;span class="pl-c1"&gt;:=&lt;/span&gt; &lt;span class="pl-s1"&gt;middleware&lt;/span&gt;.&lt;span class="pl-en"&gt;RateLimiter&lt;/span&gt;(&lt;span class="pl-s1"&gt;redisStore&lt;/span&gt;)
   &lt;span class="pl-s1"&gt;e&lt;/span&gt;.&lt;span class="pl-en"&gt;Use&lt;/span&gt;(&lt;span class="pl-s1"&gt;limiterMW&lt;/span&gt;)
}&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;I threw in an InMemory implementation for people like me who want to get on the go fast.&lt;/p&gt;
&lt;div class="highlight highlight-source-go js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-k"&gt;func&lt;/span&gt; &lt;span class="pl-en"&gt;main&lt;/span&gt;(){
   &lt;span class="pl-s1"&gt;e&lt;/span&gt; &lt;span class="pl-c1"&gt;:=&lt;/span&gt; &lt;span class="pl-s1"&gt;echo&lt;/span&gt;.&lt;span class="pl-en"&gt;New&lt;/span&gt;()

   &lt;span class="pl-k"&gt;var&lt;/span&gt; &lt;span class="pl-s1"&gt;inMemoryStore&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; middleware.&lt;span class="pl-smi"&gt;RateLimiterMemoryStore&lt;/span&gt;{
      &lt;span class="pl-c1"&gt;rate&lt;/span&gt;: &lt;span class="pl-c1"&gt;1&lt;/span&gt;,
      &lt;span class="pl-c1"&gt;burst&lt;/span&gt;: &lt;span class="pl-c1"&gt;3&lt;/span&gt;,
   }
   
   &lt;span class="pl-s1"&gt;limiterMW&lt;/span&gt; &lt;span class="pl-c1"&gt;:=&lt;/span&gt; &lt;span class="pl-s1"&gt;middleware&lt;/span&gt;.&lt;span class="pl-en"&gt;RateLimiterWithConfig&lt;/span&gt;(&lt;span class="pl-smi"&gt;RateLimiterConfig&lt;/span&gt;{
      &lt;span class="pl-c1"&gt;Store&lt;/span&gt;: &lt;span class="pl-c1"&gt;&amp;amp;&lt;/span&gt;&lt;span class="pl-s1"&gt;inMemoryStore&lt;/span&gt;,
      &lt;span class="pl-c1"&gt;SourceFunc&lt;/span&gt;: &lt;span class="pl-k"&gt;func&lt;/span&gt;(&lt;span class="pl-s1"&gt;ctx&lt;/span&gt; echo.&lt;span class="pl-smi"&gt;Context&lt;/span&gt;) &lt;span class="pl-smi"&gt;string&lt;/span&gt; {
         &lt;span class="pl-k"&gt;return&lt;/span&gt; &lt;span class="pl-s1"&gt;ctx&lt;/span&gt;.&lt;span class="pl-en"&gt;RealIP&lt;/span&gt;()
      },
   })
   &lt;span class="pl-s1"&gt;e&lt;/span&gt;.&lt;span class="pl-en"&gt;Use&lt;/span&gt;(&lt;span class="pl-s1"&gt;limiterMW&lt;/span&gt;)
}&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;closes #1721&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/labstack/echo/pull/1724" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;br&gt;
So after I established that the system ticker cannot be trusted to provide a consistent tick rate enough to verify that my rate limiter works as intended, I set off to trick my tests by finding a stable time model that does not depend on the system ticker. The rest of this blog will cover the specifics.

&lt;p&gt;Firstly, you'd need to wrap all usages of standard time helpers with custom functions that resolve to them. In my case the only main helper I needed to wrap was &lt;code&gt;time.Now&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Time&lt;/span&gt;

&lt;span class="n"&gt;now&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Time&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now in your source code, replace all occurrences of the now wrapped helpers with your custom helpers. The goal of this is to be able to use the original helpers in the main source code but easily mock them in the corresponding tests.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;store&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;RateLimiterMemoryStore&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Allow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;identifier&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mutex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;limiter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exists&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;visitors&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;identifier&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;exists&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;limiter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Visitor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;limiter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Limiter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewLimiter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;burst&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;limiter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lastSeen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c"&gt;// instead of time.Now()&lt;/span&gt;
        &lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;visitors&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;identifier&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;limiter&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;limiter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lastSeen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c"&gt;// instead of time.Now()&lt;/span&gt;
    &lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mutex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unlock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lastCleanup&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;expiresIn&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cleanupStaleVisitors&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;limiter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AllowN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c"&gt;/* instead of time.Now() */&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now in the context of our tests we have to change what &lt;code&gt;now()&lt;/code&gt; returns from the standard time to our custom computed time:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;TestRateLimiterMemoryStore_Allow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;inMemoryStore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;NewRateLimiterMemoryStore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RateLimiterMemoryStoreConfig&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;rate&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;burst&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expiresIn&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Second&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="n"&gt;testCases&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt;      &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;allowed&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;
  &lt;span class="p"&gt;}{&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"127.0.0.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;  &lt;span class="c"&gt;// 0 ms&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"127.0.0.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;  &lt;span class="c"&gt;// 220 ms burst #2&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"127.0.0.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;  &lt;span class="c"&gt;// 440 ms burst #3&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"127.0.0.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="c"&gt;// 660 ms block&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"127.0.0.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="c"&gt;// 880 ms block&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"127.0.0.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;  &lt;span class="c"&gt;// 1100 ms next second #1&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"127.0.0.2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;  &lt;span class="c"&gt;// 1320 ms allow other ip&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"127.0.0.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="c"&gt;// 1540 ms no burst&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"127.0.0.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="c"&gt;// 1760 ms no burst&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"127.0.0.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="c"&gt;// 1980 ms no burst&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"127.0.0.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;  &lt;span class="c"&gt;// 2200 ms no burst&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"127.0.0.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="c"&gt;// 2420 ms no burst&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"127.0.0.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="c"&gt;// 2640 ms no burst&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"127.0.0.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="c"&gt;// 2860 ms no burst&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"127.0.0.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;  &lt;span class="c"&gt;// 3080 ms no burst&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"127.0.0.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="c"&gt;// 3300 ms no burst&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tc&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;testCases&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Logf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Running testcase #%d =&amp;gt; %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="m"&gt;220&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Millisecond&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c"&gt;// Should have been a time.Sleep here but we manually increase the value of the date that the now function returns using the iterator from the for loop.&lt;/span&gt;
    &lt;span class="n"&gt;now&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Time&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2009&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;November&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;23&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UTC&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="m"&gt;220&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Millisecond&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;allowed&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;inMemoryStore&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Allow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;assert&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;allowed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;allowed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'd notice I am not depending on &lt;code&gt;time.Sleep&lt;/code&gt; or the system ticker to simulate a change in time for my tests. I am flexibly computing the next time in the for loop based on the iteration count. This way tests don't have to literally wait for the system ticker to actually tick before working with it's value and since the time is computed, in reality the tests will not actually have to wait for the required number of real live seconds to complete. Brings speed back to your tests and CPU agnostic flexibility. Now you can write time-based tests that will pass regardless of the clock speed of the CPU.&lt;/p&gt;

</description>
      <category>go</category>
      <category>testing</category>
      <category>time</category>
      <category>tdd</category>
    </item>
    <item>
      <title>Setting up a git server on your Ubuntu Server for Continous Integration</title>
      <dc:creator>BENKAY THE FIRST</dc:creator>
      <pubDate>Sat, 14 Nov 2020 18:13:28 +0000</pubDate>
      <link>https://dev.to/benkaythe1st/setting-up-a-git-server-on-your-ubuntu-server-for-continous-integration-3f1e</link>
      <guid>https://dev.to/benkaythe1st/setting-up-a-git-server-on-your-ubuntu-server-for-continous-integration-3f1e</guid>
      <description>&lt;p&gt;Hey there! 👋 In the spirit of modern dev practices, I am writing this blog to highlight a life saver for me. When I started out as a backend developer,  I used Heroku (and still use it occasionally) which has this amazing way of automatically building and deploying your apps whenever you push to the connected git repositories. I was forced to learn how to do it myself when my work started driving me to use bare-bone machines on AWS or Digital Ocean and I would always have to SSH into the server just to manually pull from my git repo and build it on my server before deploying. Coming from a lazy perspective, this was crazy work that I wasn't ready to do each time I make a change to the app and the spirit of automation started ringing in my ears.&lt;br&gt;
The words that came into my head were "GIT SERVER"! I googled to see if it was a thing and luckily it was. I finally figured out how GitHub was able to do it. So I embarked on my own journey to make my own git server.&lt;br&gt;
The next few paragraphs detail how I conquered that beast;&lt;br&gt;
Well you do need git installed for starters so go do that first. This article assumes you have SSH set up on your ubuntu server.&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 1
&lt;/h3&gt;

&lt;p&gt;The first thing we need to do is create a git bare repository on our server.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# incase you already have a codebase&lt;/span&gt;
git clone &lt;span class="nt"&gt;--bare&lt;/span&gt; remote_repo_url.git server_repo.git

&lt;span class="c"&gt;# but if you wanna start from scratch you could just use init&lt;/span&gt;
&lt;span class="nb"&gt;mkdir &lt;/span&gt;server_repo.git &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;server_repo.git
git init &lt;span class="nt"&gt;--bare&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;A bare git repository isn't like a regular repository. It stores our git objects but not the actual source code. It's typically the &lt;code&gt;.git&lt;/code&gt; folder in a regular repository. After that we need to create a directory on the server to store the actual source code:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;server_source
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Step 2
&lt;/h3&gt;

&lt;p&gt;Now, from a machine that has SSH Access to your ubuntu server you'll add your bare repository as a git remote:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git remote add production &amp;lt;username&amp;gt;@&amp;lt;machine&amp;gt;:server_repo.git

&lt;span class="c"&gt;# You can now push to this remote&lt;/span&gt;
git push production master

&lt;span class="c"&gt;# Or pull from it&lt;/span&gt;
git pull production master
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;basically &lt;code&gt;server_repo.git&lt;/code&gt; has to be the location of your bare repo on the ubuntu server while &lt;code&gt;username&lt;/code&gt; and &lt;code&gt;machine&lt;/code&gt; are your login details just like when logging in with SSH.&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 3
&lt;/h3&gt;

&lt;p&gt;Next is the feature that makes all this possible. GIT HOOKS! I have written about them in the past here: &lt;/p&gt;
&lt;div class="ltag__link"&gt;
  &lt;a href="https://medium.com/faun/how-to-automate-tests-on-each-push-to-the-repository-378fdcca7f8e?sk=93593a45397474307b32ce67c46ba5ab" class="ltag__link__link" rel="noopener noreferrer"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fv2%2Fresize%3Afill%3A64%3A64%2F1%2Al4PLFrSjRBVT1kZFSuB_sw%402x.jpeg" alt="Benjamin Chibuzor-Orie"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://medium.com/faun/how-to-automate-tests-on-each-push-to-the-repository-378fdcca7f8e?sk=93593a45397474307b32ce67c46ba5ab" class="ltag__link__link" rel="noopener noreferrer"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;How to run tests automatically on each push to the repository | by Benjamin Chibuzor-Orie | FAUN — Developer Community 🐾&lt;/h2&gt;
      &lt;h3&gt;Benjamin Chibuzor-Orie ・ &lt;time&gt;Aug 29, 2020&lt;/time&gt; ・ 
      &lt;div class="ltag__link__servicename"&gt;
        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fmedium-f709f79cf29704f9f4c2a83f950b2964e95007a3e311b77f686915c71574fef2.svg" alt="Medium Logo"&gt;
        Medium
      &lt;/div&gt;
    &lt;/h3&gt;
&lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
Feel free to check it out. So essentially the hook we would be needing is the &lt;code&gt;post-receive&lt;/code&gt; hook.&lt;br&gt;&lt;br&gt;
As the name implies, It runs after (post-) git objects are received from a remote.&lt;br&gt;&lt;br&gt;
Below is a typical &lt;code&gt;post-receive&lt;/code&gt; file:&lt;br&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#! /bin/bash&lt;/span&gt;

&lt;span class="c"&gt;# we have to set GIT_DIR env var to the bare repo&lt;/span&gt;
&lt;span class="nv"&gt;WORK_TREE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;/server_source
&lt;span class="nv"&gt;GIT_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;/server_repo.git

&lt;span class="c"&gt;# next up we have to checkout from our bare repo&lt;/span&gt;
git &lt;span class="nt"&gt;--work-tree&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$WORKTREE&lt;/span&gt; &lt;span class="nt"&gt;--git-dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$GIT_DIR&lt;/span&gt; checkout &lt;span class="nt"&gt;-f&lt;/span&gt;

&lt;span class="c"&gt;# from here on we can do any other processes like building and &lt;/span&gt;
&lt;span class="c"&gt;# deploying the app&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="nv"&gt;$WORK_TREE&lt;/span&gt;
docker-compose up &lt;span class="nt"&gt;--build&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now all we need to do is add this file to our git hooks. In our bare repo &lt;code&gt;server_repo.git&lt;/code&gt; we need to create a new file &lt;code&gt;post-receive&lt;/code&gt; under the &lt;code&gt;hooks&lt;/code&gt; folder and then store the above in it.&lt;br&gt;
We also need to make it executable on linux using &lt;code&gt;chmod&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chmod &lt;/span&gt;a+x post-receive
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After this we are good to go! Anytime we push to our production remote from our local, it will run the &lt;code&gt;post-receive&lt;/code&gt; script and deploy our app.&lt;/p&gt;

&lt;p&gt;If you have any questions, I'll be waiting in the comment sections to deal with it 🏌️‍♂️🏌️‍♂️&lt;/p&gt;

</description>
      <category>backend</category>
      <category>ci</category>
      <category>git</category>
    </item>
  </channel>
</rss>
