{"id":18375702,"url":"https://github.com/videlanicolas/playing-with-bootloaders","last_synced_at":"2025-04-11T04:39:41.042Z","repository":{"id":224729209,"uuid":"764030694","full_name":"videlanicolas/playing-with-bootloaders","owner":"videlanicolas","description":"This is me playing with bootloaders for fun.","archived":false,"fork":false,"pushed_at":"2024-04-03T08:00:05.000Z","size":96,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-11T04:39:34.619Z","etag":null,"topics":["assembler-x86","asssembler","bootloader","bootloaders"],"latest_commit_sha":null,"homepage":"","language":"Assembly","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/videlanicolas.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-02-27T11:03:22.000Z","updated_at":"2024-03-17T07:37:09.000Z","dependencies_parsed_at":"2024-03-16T14:03:39.125Z","dependency_job_id":"b7ee948f-5d54-41cc-8107-21af71f2f6bc","html_url":"https://github.com/videlanicolas/playing-with-bootloaders","commit_stats":null,"previous_names":["videlanicolas/playing-with-bootloaders"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/videlanicolas%2Fplaying-with-bootloaders","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/videlanicolas%2Fplaying-with-bootloaders/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/videlanicolas%2Fplaying-with-bootloaders/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/videlanicolas%2Fplaying-with-bootloaders/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/videlanicolas","download_url":"https://codeload.github.com/videlanicolas/playing-with-bootloaders/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248345272,"owners_count":21088241,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["assembler-x86","asssembler","bootloader","bootloaders"],"created_at":"2024-11-06T00:19:55.356Z","updated_at":"2025-04-11T04:39:41.001Z","avatar_url":"https://github.com/videlanicolas.png","language":"Assembly","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Playing with Bootloaders\n\nIt's been a while since I've coded in assembler, so I figured I'd play with bootloaders to brush up my assembler knowledge and also do something fun along the way.\n\nI've been reading [Writing a Simple Operating System — from Scratch](https://www.cs.bham.ac.uk/~exr/lectures/opsys/10_11/lectures/os-dev.pdf) and seemed like a nice read to get started with bootloaders and transition to OS development. This book is not finished, so I've read [OS Dev Wiki](https://wiki.osdev.org) to complete my journey in OS development.\n\n## Helloworld\n\nSimple bootloader to get things started.\n\n```bash\n$ ./run.sh helloworld\n```\n\n```\nBooting from Hard Disk...\nBoot failed: could not read the boot disk\n\nBooting from Floppy...\nHello World!\n```\n\n## Print HEX\n\nNow the bootloader prints HEX numbers, fancy!\n\n```bash\n$ ./run.sh print_hex_addresses\n```\n\n```\nBooting from Hard Disk...\nBoot failed: could not read the boot disk\n\nBooting from Floppy...\n0x1fa5\n```\n\n## Reading from disk\n\nThis example reads sectors from disk to memory. The example writes 512 bytes of bootloader code and then appends 2 blobs of 512 bytes: one with `0xdead` word repeated all over and the other with `0xbeef` repeated all over.\n\nThe code tries to load 5 sectors and read the first word of the first 2 sectors (the other 3 sectors have garbage, which _should_ be all zeros), this is done to prove we actually read the disk and moved it to memory.\n\n```bash\n$ ./run.sh read_disk\n```\n\n```\nBooting from Floppy...\nLoaded 5 sectors to memory.\nWord at 0x9000: 0xdead\nWord at 0x9200: 0xbeef\n```\n\nA variation of this example shows how errors are handled. If we modfy line 18 of `bootloader.asm` to read more sectors, we'll find there's a hard limit reading more than 56 sectors (0x38). The explanation is that we're out of 16 bit addresses to address those extra sectors.\n\nIn 16 bit real mode we can address memory up to 0xffff = 64 KiB. We're loading at 0x9000, that means we only get 0x10000 - 0x9000 = 0x7000, or 28 KiB. 28KiB / 512 = 56 sectors left that we can load. Attempting to read 56 sectors will succeed (it'll say that it read 5 sectors, but that number is a hardcoded char), attempting to read 57 sectors will fail with a disk error message.\n\n```\nBooting from Floppy...\nDisk read error!\n```\n\nBut we could read that much segments if we move to the following segment. ES is 0 in the previous example, but we can change it to 1 and load 57 sectors of disk to memory at address 1:0x0000 (ES:BX). We can even load 128 sectors! But not 129, that'll cause a disk error, because we're at the end of the segment (64 KiB).\n\n## Switch to Protected Mode\n\nThis example switches from 16 bit Real Mode to 32 bit Protected mode. The code has a lot of comments on each step I take, explaining everything that happens in the middle.\n\n```bash\n$ ./run.sh switch_to_pm\n```\n\n![Text showing switch to protected mode](img/switch_to_pm.png)\n\nIn the example I focus on A20 a lot, not because it's required to do all the things I did here to switch to PM (bootloaders use BIOS functionality to check rather than the memory loop thing I did here) but because it's an interesting problem to look at. I created an assembler routine [check_a20.asm](src/common/check_a20.asm) to do a manual check by checking if two bytes coincide on different addresses (one that looped over the memory). This is educational only, if you need to check if A20 is enabled just use the BIOS (`ax = 2402h` and `int 15h`).\n\n## Hello Kernel\n\nThis example boots a simple Kernel that shows `!` at the top left of the screen (the start of the video memory, row 0 column 0). This example consists of a bootloader and a simple Kernel, the bootloader goes through all the steps we already know (load Kernel sectors from disk to memory, clear interrupts, enable A20, load GDT, set CR0 bit 0 and far jump to code segment), with the extra addition of calling the Kernel entrypoint at the end. The Kernel is a simple `main` function that sets `!` in `0xb8000` (i.e. the start of the video memory), to prove ourselves that our Kernel has been called.\n\nIn here we have 3 files: the [bootloader](src/hello_kernel/bootloader.asm) (which contains code we already know), [kernel.c](src/hello_kernel/kernel.c) (which contains our Kernel code), and a file where our boorloader lands and has the task of finding `main` in our Kernel and call it (this file is called [kernel_entry.asm](src/hello_kernel/kernel_entry.asm)). This is generally the correct and safe way to call our Kernel code.\n\n```bash\n$ make hello_kernel \u0026\u0026 \\\n    qemu-system-i386 -fda build/hello_kernel/os.img\n```\n\n![Text showing a Kernel booted correctly](img/hello_kernel.png)\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvidelanicolas%2Fplaying-with-bootloaders","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvidelanicolas%2Fplaying-with-bootloaders","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvidelanicolas%2Fplaying-with-bootloaders/lists"}