Compare commits

11 Commits
master ... dev

Author SHA1 Message Date
andromeda
e1822da600 load 16 sectors instead of 1 2026-03-06 23:02:09 +01:00
andromeda
444e85e30c clarify doc 2026-03-06 22:36:47 +01:00
andromeda
00be2cc545 reformat, add copy_token and test, fix bug 2026-03-06 22:16:26 +01:00
andromeda
e5c715d54f change rdme 2026-03-06 20:56:03 +01:00
andromeda
42003df415 merge new changes 2026-03-06 20:38:32 +01:00
andromeda
9c65697dd8 bunch of stuff idek 2026-03-06 20:33:51 +01:00
andromeda
d35463e195 reorganise 2026-03-06 16:53:18 +01:00
andromeda
fdf5bb9daf remove redundant compile flag 2026-03-05 22:26:54 +01:00
andromeda
0d739522a0 copy libs also 2026-03-05 21:08:44 +01:00
andromeda
846c54653b change dev env, format rust 2026-03-05 21:00:18 +01:00
andromeda
f52da82650 add footer 2026-03-05 20:48:30 +01:00
20 changed files with 415 additions and 112 deletions

View File

@@ -2,50 +2,18 @@ Call me Terry Davis because... actually please don't. I have visions: aspiration
# bootle # bootle
hobby kernel written in rust. It's just for playing around... for now :p hobby kernel
run with `nix run git+https://git.mtgmonkey.net/andromeda/bootler#bootle` status: basically nothing, come back later
# bootler # bootler
hobby bootloader written in asm. It's just for playing around... for now :p hobby 1-stage legacy mode bootloader
run with `nix run git+https://git.mtgmonkey.net/andromeda/bootler#bootler` status: gets to long mode, loads+jumps to kernel, starts idt and gdt... :)
### memory map # twasm
``` hobby self-hosted assembler
+------ 0x00100000 ------+
| hardware, bios stuff | status: basically nothing, come back later
+------ 0x00080000 ------+
| |
| |
+------ 0x00010200 ------+
| x86_64 kernel |
+------ 0x00010000 ------+
| |
| |
+------ 0x00009000 ------+
| IDT |
+------ 0x00008000 ------+
| |
| |
+------ 0x00007E00 ------+
| bootloader (boot.asm) |
+------ 0x00007C00 ------+
| stack | TODO get real stack
+------ 0x00005000 ------+
| PT |
+------ 0x00004000 ------+
| PDT |
+------ 0x00003000 ------+
| PDPT |
+------ 0x00002000 ------+
| PML4T |
+------ 0x00001000 ------+
| |
| |
+------ 0x00000500 ------+
| bios stuff |
+------ 0x00000000 ------+
```

View File

28
bootle/README.md Normal file
View File

@@ -0,0 +1,28 @@
# bootle
hobby kernel written in rust. It's just for playing around... for now :p
run with `nix run git+https://git.mtgmonkey.net/andromeda/bootler#bootle`
### memory map
```
+------ 0x00100000 ------+
| hardware, bios stuff |
+------ 0x00080000 ------+
| |
| |
+------ 0x00010200 ------+
| kernel |
+------ 0x00010000 ------+
| bootloader stuff |
| includes stack, gdt, |
| idt for the time being |
+------ 0x00000500 ------+
| bios stuff |
+------ 0x00000000 ------+
```
---
this project follows [Common Changelog](https://common-changelog.org) guidelines

View File

@@ -6,27 +6,28 @@
qemu, qemu,
... ...
}: let }: let
rust-toolchain = rust-bin.fromRustupToolchainFile ../../rust-toolchain.toml; rust-toolchain = rust-bin.fromRustupToolchainFile ./rust-toolchain.toml;
naersk' = callPackage naersk { naersk' = callPackage naersk {
cargo = rust-toolchain; cargo = rust-toolchain;
rustc = rust-toolchain; rustc = rust-toolchain;
clippy = rust-toolchain; clippy = rust-toolchain;
}; };
in (naersk'.buildPackage { in (naersk'.buildPackage {
src = ../../.; src = ./.;
# deps for rust-src # deps for rust-src
additionalCargoLock = "${rust-toolchain.availableComponents.rust-src}/lib/rustlib/src/rust/library/Cargo.lock"; additionalCargoLock = "${rust-toolchain.availableComponents.rust-src}/lib/rustlib/src/rust/library/Cargo.lock";
# just library build # just library build
copyBins = false; copyBins = false;
copyLibs = true;
release = true; release = true;
# build std # build std
cargoBuildOptions = x: cargoBuildOptions = x:
x x
++ [ ++ [
"-Zbuild-std=core,compiler_builtins" "-Zbuild-std"
]; ];
postInstall = '' postInstall = ''
@@ -36,7 +37,7 @@ in (naersk'.buildPackage {
-e _start \ -e _start \
target/x86_64-unknown-none/release/libbootle.a target/x86_64-unknown-none/release/libbootle.a
dd if=/dev/zero of=disk bs=512 count=2 dd if=/dev/zero of=disk bs=512 count=2880
dd if=${bootler}/bin/boot.bin of=disk conv=notrunc dd if=${bootler}/bin/boot.bin of=disk conv=notrunc
dd if=kernel.bin of=disk bs=512 seek=1 conv=notrunc dd if=kernel.bin of=disk bs=512 seek=1 conv=notrunc

View File

@@ -12,11 +12,13 @@ pub extern "C" fn _start() -> ! {
fn print_serial(s: &str) { fn print_serial(s: &str) {
let mut bytes = s.bytes(); let mut bytes = s.bytes();
while let Some(b) = bytes.next() { while let Some(b) = bytes.next() {
unsafe {core::arch::asm!( unsafe {
"out dx, al" core::arch::asm!(
, in("al") b "out dx, al"
)}; , in("al") b
}; )
};
}
} }
fn println_serial(s: &str) { fn println_serial(s: &str) {
@@ -28,7 +30,11 @@ fn welcome_serial() {
print_serial(ANSI_PINK); print_serial(ANSI_PINK);
println_serial("\nWelcome to Bootle OS"); println_serial("\nWelcome to Bootle OS");
println_serial("All code GPL licensed and freely available on git.mtgmonkey.net"); println_serial("All code GPL licensed and freely available on git.mtgmonkey.net");
print_serial("Enjoy your time! Press "); print_serial(ANSI_RED); print_serial("ctrl+a x"); print_serial(ANSI_PINK); println_serial(" to escape Qemu"); print_serial("Enjoy your time! Press ");
print_serial(ANSI_RED);
print_serial("ctrl+a x");
print_serial(ANSI_PINK);
println_serial(" to escape Qemu");
print_serial(ANSI_CLEAR); print_serial(ANSI_CLEAR);
} }
@@ -39,9 +45,7 @@ fn panic(_: &PanicInfo) -> ! {
} }
fn halt() -> ! { fn halt() -> ! {
unsafe {core::arch::asm!( unsafe { core::arch::asm!("hlt") };
"hlt"
)};
halt() halt()
} }

7
bootler/CHANGELOG.md Normal file
View File

@@ -0,0 +1,7 @@
# Changelog
## [0.1.0] - 2026-03-06
### Added
- initialised CHANGELOG.md

43
bootler/README.md Normal file
View File

@@ -0,0 +1,43 @@
# bootler
hobby bootloader, 1-stage, legacy mode :p
run with `nix run git+https://git.mtgmonkey.net/andromeda/bootler#bootler`
### memory map
```
. .
: :
| longmode kernel |
+------ 0x00010000 ------+
| |
| |
+------ 0x00009000 ------+
| IDT |
+------ 0x00008000 ------+
| |
| |
+------ 0x00007E00 ------+
| bootloader (boot.asm) |
+------ 0x00007C00 ------+
| stack |
+------ 0x00005000 ------+
| PT |
+------ 0x00004000 ------+
| PDT |
+------ 0x00003000 ------+
| PDPT |
+------ 0x00002000 ------+
| PML4T |
+------ 0x00001000 ------+
| |
| |
+------ 0x00000500 ------+
| bios stuff |
+------ 0x00000000 ------+
```
---
this project follows [Common Changelog](https://common-changelog.org) guidelines

View File

@@ -6,7 +6,7 @@
LOAD_ADDR equ 0x7C00 LOAD_ADDR equ 0x7C00
KERNEL_START equ 2 ; first sector on disk to load kernel from; 1 indexed KERNEL_START equ 2 ; first sector on disk to load kernel from; 1 indexed
KERNEL_SIZE equ 1 ; length of kernel in sectors KERNEL_SIZE equ 16 ; length of kernel in sectors
KERNEL_LOAD_ADDR_ES equ 0x1000 ; kernel to be loaded at es * 0x10 + 0x0000 KERNEL_LOAD_ADDR_ES equ 0x1000 ; kernel to be loaded at es * 0x10 + 0x0000
PAGE_TABLE_LOAD_ADDR equ 0x1000 ; start of page table; 4 * pt size PAGE_TABLE_LOAD_ADDR equ 0x1000 ; start of page table; 4 * pt size

View File

@@ -9,19 +9,18 @@ in
stdenv.mkDerivation { stdenv.mkDerivation {
pname = "bootler"; pname = "bootler";
version = "0.1.0"; version = "0.1.0";
src = ../../.; src = ./.;
buildPhase = '' buildPhase = ''
${nasm}/bin/nasm asm/boot.asm -o boot.bin ${nasm}/bin/nasm asm/boot.asm -o boot.bin
${nasm}/bin/nasm asm/kernel.asm -o dummy.bin ${nasm}/bin/nasm asm/kernel.asm -o dummy.bin
dd if=/dev/zero of=${bootImg} bs=512 count=2 dd if=/dev/zero of=${bootImg} bs=512 count=2880
dd if=boot.bin of=${bootImg} conv=notrunc dd if=boot.bin of=${bootImg} conv=notrunc
dd if=dummy.bin of=${bootImg} bs=512 seek=1 conv=notrunc dd if=dummy.bin of=${bootImg} bs=512 seek=1 conv=notrunc
''; '';
installPhase = '' installPhase = ''
mkdir -p $out/bin mkdir -p $out/bin
cp boot.bin $out/bin cp boot.bin $out/bin
cp dummy.bin $out/bin
cp ${bootImg} $out/bin cp ${bootImg} $out/bin
# create emulation binary # create emulation binary

View File

@@ -18,20 +18,25 @@
... ...
}: let }: let
system = "x86_64-linux"; system = "x86_64-linux";
pkgs = import nixpkgs { pkgs = nixpkgs.legacyPackages.${system};
inherit system; pkgsWithRustOverlay = pkgs.extend (import rust-overlay);
overlays = [(import rust-overlay)];
};
in { in {
packages.${system} = { packages.${system} = {
bootler = pkgs.callPackage ./nix/pkgs/bootler.nix {}; bootler = pkgs.callPackage ./bootler/package.nix {};
bootle = pkgs.callPackage ./nix/pkgs/bootle.nix { bootle = pkgsWithRustOverlay.callPackage ./bootle/package.nix {
naersk = naersk; inherit naersk;
bootler = self.packages.${system}.bootler;
};
twasm = pkgs.callPackage ./twasm/package.nix {
bootler = self.packages.${system}.bootler; bootler = self.packages.${system}.bootler;
}; };
}; };
devShells.${system}.default = pkgs.mkShell { devShells.${system}.default = pkgs.mkShell {
inputsFrom = [self.packages.${system}.default]; inputsFrom = [
self.packages.${system}.bootle
self.packages.${system}.bootler
self.packages.${system}.twasm
];
}; };
}; };
} }

View File

@@ -1,47 +0,0 @@
{
stdenv,
nasm,
qemu,
...
}: let
bootImg = "boot";
in
stdenv.mkDerivation {
pname = "bootler";
version = "0.1.0";
src = ../.;
buildPhase = ''
${nasm}/bin/nasm asm/boot.asm -o boot.bin
${nasm}/bin/nasm asm/kernel.asm -o kernel.bin
dd if=/dev/zero of=${bootImg} bs=512 count=2
dd if=boot.bin of=${bootImg} conv=notrunc
dd if=kernel.bin of=${bootImg} bs=512 seek=1 conv=notrunc
'';
installPhase = ''
mkdir -p $out/bin
cp ${bootImg} $out/bin
# create emulation binary
cat<<EOF>$out/bin/bootler
#!/usr/bin/env bash
# create temp dir
mkdir -p ./.bootler
cp $(echo $out)/bin/${bootImg} ./.bootler/${bootImg}
chmod a+w ./.bootler/${bootImg}
# run image
${qemu}/bin/qemu-system-x86_64 \
-nographic \
-drive file=./.bootler/${bootImg},format=raw,index=0,media=disk
# clean up
rm ./.bootler -r
EOF
chmod +x $out/bin/${bootImg}
chmod +x $out/bin/bootler
'';
}

32
twasm/README.md Normal file
View File

@@ -0,0 +1,32 @@
# twasm
this will be a self hosted, very minimal subset of 64 bit asm
### goals
I want to compile Bootler and Twasm with the Twasm assembler
### memory map
```
+------ 0x00100000 ------+
| hardware, bios stuff |
+------ 0x00080000 ------+
| output binary |
+------ 0x00070000 ------+
| token table |
+------ 0x00060000 ------+
| |
| |
+------------------------+
| input |
+------------------------+ this is lined up to a sector
| | and this is less than a sector
+------------------------+
| assembler |
+------ 0x00010000 ------+
| bootloader, bios, etc. |
+------------------------+
```
each word represents a token on the token table.

221
twasm/asm/main.asm Normal file
View File

@@ -0,0 +1,221 @@
LOAD_ADDR equ 0x00010000 ; address this program is loaded at
TOKEN_TABLE_ADDR equ 0x00060000 ; address the token table is loaded at
TOKEN_TABLE_SIZE equ 0x1000 ; max length of table
TEST_ARENA_ADDR equ 0x00060000 ; address to run tests at
TEST_ARENA_SIZE equ 0x1000 ; maximum size tests can use
OUTPUT_ADDR equ 0x00070000 ; address of outputed binary
OUTPUT_SIZE equ 0x1000 ; max length of outputed binary
[bits 64]
[org LOAD_ADDR]
start:
mov rsi, msg_welcome
call print
call run_tests
jmp halt
; ------------------------------------------------------------------------------
; tokenising
; ------------------------------------------------------------------------------
; ------------------------------------------------------------------------------
; copy_token
;
; description:
; copies a token from one spot in memory to another
;
; parameters:
; rdi -> start of buffer to be read
; rsi -> start of buffer to be written
;
; returned:
; rax -> last byte read
; rdx -> last byte written
; ------------------------------------------------------------------------------
copy_token:
.loop:
mov al, [rdi] ; check if next char is a space
cmp al, " "
je .break
call copy_byte ; copy the next byte if not
inc rdi ; increment read- and write-pointers
inc rsi
jmp .loop ; and loop again
.break:
mov rax, rdi ; return values
mov rdx, rsi
ret
.msg db "yo loop copy_token", 0x0D, 0x0A, 0x00
; ------------------------------------------------------------------------------
; copy_byte
;
; description:
; copies a byte from one spot in memory to another
;
; parameters:
; rdi -> word to be read
; rsi -> word to be written
;
; returned:
; al = byte that was read; the rest of rax is zeroed
; ------------------------------------------------------------------------------
copy_byte:
xor rax, rax ; zero out so it returns fine
mov al, [rdi]
mov [rsi], al
ret
; ------------------------------------------------------------------------------
; utilities
; ------------------------------------------------------------------------------
; ------------------------------------------------------------------------------
; print
;
; description:
; prints a null-terminated string
;
; parameters:
; rsi -> start of null-terminated string
; ------------------------------------------------------------------------------
print:
push rdx
mov rdx, 0x3F8
.loop:
mov al, [rsi]
test al, al
jz .done
out dx, al
inc rsi
jmp .loop
.done:
pop rdx
ret
; ------------------------------------------------------------------------------
; halt
;
; description:
; halts the program, silly :)
; ------------------------------------------------------------------------------
halt:
mov rsi, msg_halt
call print
hlt
jmp halt
; ------------------------------------------------------------------------------
; tests
; ------------------------------------------------------------------------------
; ------------------------------------------------------------------------------
; run_tests
;
; description:
; runs all tests
; ------------------------------------------------------------------------------
run_tests:
mov rsi, .msg
call print
call test_copy_byte
call test_copy_token
ret
.msg db "running test suite...", 0x0D, 0x0A, 0x00
; ------------------------------------------------------------------------------
; test_copy_byte
;
; description:
; tests copy_byte's described functionality
; ------------------------------------------------------------------------------
test_copy_byte:
mov rsi, .msg
call print
mov rdi, test_byte ; byte to be copied
mov rsi, TEST_ARENA_ADDR ; location of test
call copy_byte
mov cx, [rsi]
and ax, 0xFF ; only compare bottom byte
and cx, 0xFF
cmp ax, cx ; compare returned byte to copied byte
jne .fail
cmp al, [test_byte] ; compare returned byte to expected byte
jne .fail
.pass:
mov rsi, msg_pass
call print
ret
.fail:
mov rsi, msg_fail
call print
ret
.msg db "test_copy_byte...", 0x00
; ------------------------------------------------------------------------------
; test_copy_token
;
; description:
; tests copy_token described functionality
; ------------------------------------------------------------------------------
test_copy_token:
mov rsi, .msg
call print
mov rdi, test_token ; read buffer
mov rsi, TEST_ARENA_ADDR ; write buffer
call copy_token
; check reported final indicies with the expected final indicies
cmp rax, test_token + 8 ; last byte read
jne .fail
cmp rdx, TEST_ARENA_ADDR + 8 ; last byte written
jne .fail
mov rsi, TEST_ARENA_ADDR
mov rcx, [rsi]
cmp rcx, [test_token] ; compare copied token to expected token
jne .fail
.pass:
mov rsi, msg_pass
call print
ret
.fail:
mov rsi, msg_fail
call print
ret
.msg db "test_copy_token...", 0x00
; ------------------------------------------------------------------------------
; data
; ------------------------------------------------------------------------------
msg_welcome db "Welcome to Twasm", 0x0D, 0x0A, 0x00
msg_halt db "halted.", 0x0D, 0x0A, 0x00
msg_pass db "passed.", 0x0D, 0x0A, 0x00
msg_fail db "failed.", 0x0D, 0x0A, 0x00
test_byte db "T"
test_token db "TestTokn " ; followed by space. Quad word

42
twasm/package.nix Normal file
View File

@@ -0,0 +1,42 @@
{
bootler,
stdenv,
nasm,
qemu,
...
}:
stdenv.mkDerivation {
pname = "twasm";
version = "0.1.0";
src = ./.;
buildPhase = ''
${nasm}/bin/nasm asm/main.asm -o out.bin
'';
installPhase = ''
dd if=/dev/zero of=disk bs=512 count=2880
dd if=${bootler}/bin/boot.bin of=disk conv=notrunc
dd if=out.bin of=disk bs=512 seek=1 conv=notrunc
mkdir -p $out/bin
cat<<EOF>$out/bin/twasm
#!/usr/bin/env bash
mkdir -p ./.bootle
cp $(echo $out)/bin/disk ./.bootle/disk
chmod a+w ./.bootle/disk
${qemu}/bin/qemu-system-x86_64 \
-nographic \
-s \
-drive file=./.bootle/disk,format=raw,index=0,media=disk
rm ./.bootle -r
EOF
chmod +x $out/bin/twasm
cp out.bin $out/bin
cp disk $out/bin
'';
}