diff options
| author | Chloe M. <chloe@aptel.org> | 2026-09-03 01:22:45 +0000 |
|---|---|---|
| committer | Chloe M. <chloe@aptel.org> | 2026-09-03 02:49:49 +0000 |
| commit | e758e02f0781e45f91674aeb5c2259ce4add3b88 (patch) | |
| tree | e6ea80f93bbad0f93b6c859d126f144af12ad32f /boot/amd64/generic/mbr | |
initial commitmain
Signed-off-by: Chloe M. <chloe@aptel.org>
Diffstat (limited to 'boot/amd64/generic/mbr')
| -rw-r--r-- | boot/amd64/generic/mbr/Makefile | 15 | ||||
| -rw-r--r-- | boot/amd64/generic/mbr/link.ld | 26 | ||||
| -rw-r--r-- | boot/amd64/generic/mbr/mbr.S | 213 |
3 files changed, 254 insertions, 0 deletions
diff --git a/boot/amd64/generic/mbr/Makefile b/boot/amd64/generic/mbr/Makefile new file mode 100644 index 0000000..c9ae0dc --- /dev/null +++ b/boot/amd64/generic/mbr/Makefile @@ -0,0 +1,15 @@ +# +# Copyright (c) 2026, Apollo Telephone Laboratories. +# Provided under the BSD-3 clause. +# + +include ../mk/build.mk + +CFLAGS = $(INTERNAL_CFLAGS) + +.PHONY: all +all: mbr + +.PHONY: mbr +mbr: + $(CC) $(CFLAGS) -Tlink.ld mbr.S -o mbr.bin diff --git a/boot/amd64/generic/mbr/link.ld b/boot/amd64/generic/mbr/link.ld new file mode 100644 index 0000000..fbc3b21 --- /dev/null +++ b/boot/amd64/generic/mbr/link.ld @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2026, Apollo Telephone Laboratories. + * Provided under the BSD-3 clause. + */ + +OUTPUT_FORMAT(binary) + +SECTIONS { + . = 0x00; + + .text : { + *(.text) + } + + .data : { + *(.data) + } + + .rodata : { + *(.rodata) + } + + .bss : { + *(.bss) + } +} diff --git a/boot/amd64/generic/mbr/mbr.S b/boot/amd64/generic/mbr/mbr.S new file mode 100644 index 0000000..7cd7484 --- /dev/null +++ b/boot/amd64/generic/mbr/mbr.S @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2026, Apollo Telephone Laboratories. + * Provided under the BSD-3 clause. + */ + +#define BOOT_SEG 0x7C0 /* Segment we reside on startup */ +#define BOOT_RELOC_SEG 0x7A0 /* Relocation segment */ +#define RDAR_MAGIC ">RDAR!" +#define RDAR_MAGIC_LEN 6 +#define BOOT_PATH "s2.bin" +#define BOOT_PATH_LEN 6 + + .text + .code16 +_start: + ljmp $BOOT_SEG,$main +main: + cli + cld + + /* Set segment registers */ + xor %ax, %ax + mov %ax, %fs + mov %ax, %gs + mov %ax, %ss + mov %ax, %es + mov $BOOT_SEG, %ax + mov %ax, %ds + + /* Save the drive */ + mov %dl, drive_num + + /* + * The second stage bootloader expects to be loaded to 0x7C00 but since we are + * already executing at this address we'll need to relocate ourselves first before + * we clobber it. + */ + mov $BOOT_SEG, %ax + mov %ax, %ds + mov $BOOT_RELOC_SEG, %ax + mov %ax, %es + xor %si, %si + xor %di, %di + mov $0x200, %cx + cld + rep movsb + + jmp $BOOT_RELOC_SEG,$1f +1: mov $0x7C00, %sp + + /* Load two sectors */ + movw $2, dap_blkcnt + movl $1, dap_lba_low + call disk_read_lba + + mov $BOOT_RELOC_SEG, %ax + mov %ax, %ds + + /* Get stage2 */ + call find_stage2 + + /* Obtain the data offset */ + mov $BOOT_SEG, %ax + mov %ax, %ds + add $40, %si + movw (%si), %si + + mov $BOOT_SEG, %ax + mov %ax, %ds + mov %ax, %es + xor %di, %di + mov $0x200, %cx + cld + rep movsb + + /* Jump to stage 2 */ + xor %ax, %ax + mov %ax, %ds + ljmp $0x0000,$0x7C00 + +/* + * Write a character to the boot console + * + * %al: Character to write + */ +putc: + mov $0x0E, %ah + xor %bh, %bh + int $0x10 + ret + +/* + * Write a string to the boot console + * + * %si: Pointer to string to write + */ +puts: + lodsb + or %al, %al + jz 1f + call putc + jmp puts +1: ret + +/* + * Locate stage2 on the disk + * + * Stage 2 data descriptor is returned in %SI + */ +find_stage2: + push %ds + push %es + + /* Verify that magic is correct */ + mov $BOOT_SEG, %ax + mov %ax, %ds + xor %bx, %bx /* Tracks %SI */ + xor %si, %si + mov $BOOT_RELOC_SEG, %ax + mov %ax, %es + mov $rdar_magic, %di + mov $RDAR_MAGIC_LEN, %cx + rep cmpsb + jne .bad_magic + + /* Iterate every data descriptor */ + clc /* Carry set if found */ +1: movw %ds:6, %cx /* Add data descriptor size */ + mov %bx, %si + mov %si, %dx + add %cx, %bx + mov $rdar_magic, %di + mov $RDAR_MAGIC_LEN, %cx + rep cmpsb + jne .not_found + + /* Does the path match? */ + mov %dx, %si + add $8, %si + mov $stage2_path, %di + mov $BOOT_PATH_LEN, %cx + rep cmpsb + jne 1b + + mov %dx, %si + stc + pop %es + pop %ds + jnc .not_found + ret +.not_found: + pop %ds + mov $not_found_msg, %si + call puts +1: cli + hlt + jmp 1b + +.bad_magic: + /* Restore %DS */ + mov $BOOT_RELOC_SEG, %ax + mov %ax, %ds + + mov $bad_magic_msg, %si + call puts +1: cli + hlt + jmp 1b + +/* + * Read sectors from the disk + */ +disk_read_lba: + pusha + mov $dap, %si + mov $0x42, %ah + mov drive_num, %dl + int $0x13 + jc .error + popa + ret +.error: + mov $disk_err_msg, %si + call puts +1: cli + hlt + jmp 1b + +/* Global stores */ +rdar_magic: .ascii RDAR_MAGIC +bad_magic_msg: .ascii "bad RDAR magic\r\n\0" +not_found_msg: .ascii "stage 2 not found\r\n\0" +disk_err_msg: .ascii "\r\n!!!disk error!!!\r\n\0" +stage2_path: .ascii BOOT_PATH +drive_num: .byte 0 + +dap: + .byte 0x10 + .byte 0x00 +dap_blkcnt: + .word 0 +dap_destptr: + .word 0x7C00 +dap_destseg: + .word 0x0000 +dap_lba_low: + .long 0 +dap_lba_high: + .long 0 + + .org 510 + .byte 0x55 + .byte 0xAA |
