commit b6b4854f715beed7bdac4f37fb4735435d2a3dd3 Author: Mathieu Strypsteen Date: Sat Jun 29 20:50:08 2024 +0200 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..887f18b --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +img +target diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..b3dbff0 --- /dev/null +++ b/LICENSE @@ -0,0 +1,22 @@ +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..e1f329d --- /dev/null +++ b/build.sh @@ -0,0 +1,16 @@ +#!/bin/sh +set -e +rm -rf img +mkdir -p img/boot/efi/boot +cd kernel && cargo build --release && cd .. +cd loader && cargo build --release && cd .. +cp loader/target/x86_64-unknown-uefi/release/loader.efi img/boot/efi/boot/bootx64.efi +cd img +dd if=/dev/zero of=boot.img bs=1M count=16 status=none +mformat -i boot.img +mcopy -si boot.img boot/* :: +dd if=/dev/zero of=os.img bs=1M count=32 status=none +parted -s os.img mklabel gpt +parted -s os.img mkpart primary fat32 2048s 100% +parted -s os.img set 1 esp on +dd if=boot.img of=os.img bs=1M seek=1 conv=notrunc status=none diff --git a/kernel/.cargo/config.toml b/kernel/.cargo/config.toml new file mode 100644 index 0000000..98ee5ed --- /dev/null +++ b/kernel/.cargo/config.toml @@ -0,0 +1,3 @@ +[build] +target = "x86_64-unknown-none" +rustflags = ["-C", "link-arg=link.ld"] diff --git a/kernel/Cargo.lock b/kernel/Cargo.lock new file mode 100644 index 0000000..97c0833 --- /dev/null +++ b/kernel/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "kernel" +version = "0.0.1" diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml new file mode 100644 index 0000000..831a26b --- /dev/null +++ b/kernel/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "kernel" +version = "0.0.1" +edition = "2021" + +[dependencies] diff --git a/kernel/link.ld b/kernel/link.ld new file mode 100644 index 0000000..7cb4add --- /dev/null +++ b/kernel/link.ld @@ -0,0 +1,15 @@ +SECTIONS { + . = 0xffffffff80000000; + .text ALIGN(0x1000) : { + *(.text*) + } + .rodata ALIGN(0x1000) : { + *(.rodata*) + } + .data ALIGN(0x1000) : { + *(.data*) + } + .bss ALIGN(0x1000) : { + *(.bss*) + } +} diff --git a/kernel/src/main.rs b/kernel/src/main.rs new file mode 100644 index 0000000..3289e15 --- /dev/null +++ b/kernel/src/main.rs @@ -0,0 +1,14 @@ +#![no_std] +#![no_main] + +use core::panic::PanicInfo; + +#[no_mangle] +fn _start() { + loop {} +} + +#[panic_handler] +fn panic(_info: &PanicInfo) -> ! { + loop {} +} diff --git a/loader/.cargo/config.toml b/loader/.cargo/config.toml new file mode 100644 index 0000000..85d49dc --- /dev/null +++ b/loader/.cargo/config.toml @@ -0,0 +1,2 @@ +[build] +target = "x86_64-unknown-uefi" diff --git a/loader/Cargo.lock b/loader/Cargo.lock new file mode 100644 index 0000000..dab2e87 --- /dev/null +++ b/loader/Cargo.lock @@ -0,0 +1,186 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "bit_field" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "elf" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4445909572dbd556c457c849c4ca58623d84b27c8fff1e74b0b4227d8b90d17b" + +[[package]] +name = "loader" +version = "0.0.1" +dependencies = [ + "elf", + "log", + "uefi", + "x86_64", +] + +[[package]] +name = "log" +version = "0.4.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "ptr_meta" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcada80daa06c42ed5f48c9a043865edea5dc44cbf9ac009fda3b89526e28607" +dependencies = [ + "ptr_meta_derive", +] + +[[package]] +name = "ptr_meta_derive" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bca9224df2e20e7c5548aeb5f110a0f3b77ef05f8585139b7148b59056168ed2" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rustversion" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "901fa70d88b9d6c98022e23b4136f9f3e54e4662c3bc1bd1d84a42a9a0f0c1e9" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "ucs2" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df79298e11f316400c57ec268f3c2c29ac3c4d4777687955cd3d4f3a35ce7eba" +dependencies = [ + "bit_field", +] + +[[package]] +name = "uefi" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9c0a56dc9fed2589aad6ddca11c2584968fc21f227b5d7083bb8961d26a69fa" +dependencies = [ + "bitflags", + "cfg-if", + "log", + "ptr_meta", + "ucs2", + "uefi-macros", + "uefi-raw", + "uguid", +] + +[[package]] +name = "uefi-macros" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26a7b1c2c808c3db854a54d5215e3f7e7aaf5dcfbce095598cba6af29895695d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", +] + +[[package]] +name = "uefi-raw" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efa8716f52e8cab8bcedfd5052388a0f263b69fe5cc2561548dc6a530678333c" +dependencies = [ + "bitflags", + "ptr_meta", + "uguid", +] + +[[package]] +name = "uguid" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab14ea9660d240e7865ce9d54ecdbd1cd9fa5802ae6f4512f093c7907e921533" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "volatile" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "442887c63f2c839b346c192d047a7c87e73d0689c9157b00b53dcc27dd5ea793" + +[[package]] +name = "x86_64" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bc79523af8abf92fb1a970c3e086c5a343f6bcc1a0eb890f575cbb3b45743df" +dependencies = [ + "bit_field", + "bitflags", + "rustversion", + "volatile", +] diff --git a/loader/Cargo.toml b/loader/Cargo.toml new file mode 100644 index 0000000..fa617ea --- /dev/null +++ b/loader/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "loader" +version = "0.0.1" +edition = "2021" + +[dependencies] +elf = {version = "0.7.4", default-features = false} +log = "0.4.21" +uefi = {version = "0.28.0", features = ["logger", "panic_handler"]} +x86_64 = {version = "0.15.1", default-features = false} diff --git a/loader/src/elf.rs b/loader/src/elf.rs new file mode 100644 index 0000000..c608257 --- /dev/null +++ b/loader/src/elf.rs @@ -0,0 +1,40 @@ +use core::ptr; + +use elf::{abi::PT_LOAD, endian::LittleEndian, ElfBytes}; +use uefi::table::{ + boot::{AllocateType, MemoryType}, + Boot, SystemTable, +}; + +const KERNEL_VIRT_START: u64 = 0xffffffff80000000; + +pub fn load_kernel(kernel: &[u8], system_table: &SystemTable) { + let file: ElfBytes = ElfBytes::minimal_parse(kernel).unwrap(); + let mut kernel_size = 0; + for i in file.segments().unwrap() { + if i.p_type != PT_LOAD { + continue; + } + if i.p_vaddr < KERNEL_VIRT_START { + panic!("Invalid kernel segments") + } + let end_addr = i.p_vaddr - KERNEL_VIRT_START + i.p_memsz; + if end_addr > kernel_size { + kernel_size = end_addr; + } + } + let phys_start = system_table + .boot_services() + .allocate_pages(AllocateType::AnyPages, MemoryType::LOADER_DATA, ((kernel_size + 0xfff) / 0x1000).try_into().unwrap()) + .unwrap(); + for i in file.segments().unwrap() { + if i.p_type != PT_LOAD { + continue; + } + let start_addr = i.p_vaddr - KERNEL_VIRT_START + phys_start; + unsafe { + ptr::write_bytes(start_addr as *mut u8, 0, i.p_memsz.try_into().unwrap()); + ptr::copy(kernel[i.p_offset.try_into().unwrap()..].as_ptr(), start_addr as *mut u8, i.p_filesz.try_into().unwrap()); + } + } +} diff --git a/loader/src/main.rs b/loader/src/main.rs new file mode 100644 index 0000000..abf6e84 --- /dev/null +++ b/loader/src/main.rs @@ -0,0 +1,23 @@ +#![no_main] +#![no_std] + +use elf::load_kernel; +use log::debug; +use uefi::{ + entry, + table::{boot::MemoryType, Boot, SystemTable}, + Handle, Status, +}; + +mod elf; + +const KERNEL: &[u8] = include_bytes!("../../kernel/target/x86_64-unknown-none/release/kernel"); + +#[entry] +fn main(image_handle: Handle, mut system_table: SystemTable) -> Status { + uefi::helpers::init(&mut system_table).unwrap(); + debug!("Starting bootloader..."); + load_kernel(KERNEL, &system_table); + let _memory_map = system_table.exit_boot_services(MemoryType::LOADER_DATA).1; + loop {} +} diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 0000000..860058f --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +targets = ["x86_64-unknown-none", "x86_64-unknown-uefi"] diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000..ffc467d --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1 @@ +max_width = 200