|
|
@ -12,43 +12,82 @@ |
|
|
|
; See the License for the specific language governing permissions and |
|
|
|
; limitations under the License. |
|
|
|
|
|
|
|
; Definition of the MBR (Master Boot Record). This is basically our bootloader and |
|
|
|
; is located in the first 512 bytes of the drive we're booting from. From here, we |
|
|
|
; do some basic setup and then call into the kernel |
|
|
|
; Welcome to TSBL: The Simple Bootloader |
|
|
|
|
|
|
|
[org 0x7c00] ; Address where the code expects to be loaded in. The BIOS always loads us here |
|
|
|
[bits 16] ; All x86 CPUs start in 16 bit (aka "real") mode, so we tell nasm to emit 16-bit code |
|
|
|
|
|
|
|
kernel_offset: equ 0x1000 |
|
|
|
reserved_sectors: equ 4 |
|
|
|
|
|
|
|
; This isn't needed inside the qemu emulator, but |
|
|
|
; real hardware is unlikely to start up with the |
|
|
|
; segment registers zeroed, so we do it here |
|
|
|
mov ax, 0 |
|
|
|
mov ds, ax |
|
|
|
mov ss, ax |
|
|
|
mov es, ax |
|
|
|
xor ax, ax |
|
|
|
|
|
|
|
; We save the value of the current boot drive |
|
|
|
mov [boot_drive], dl |
|
|
|
|
|
|
|
; Now we setup the stack by setting the |
|
|
|
; base pointer to a location that's far |
|
|
|
; enough from where the code for the BIOS |
|
|
|
; is located |
|
|
|
mov sp, 0x9000 |
|
|
|
mov bp, sp |
|
|
|
call bios_cls |
|
|
|
mov si, loading_stage2_msg |
|
|
|
call bios_println |
|
|
|
mov bx, stage2 |
|
|
|
mov cl, 2 |
|
|
|
mov dh, reserved_sectors |
|
|
|
mov dl, [boot_drive] |
|
|
|
call load_disk |
|
|
|
jmp stage2 |
|
|
|
; Code copied from the limine bootloader |
|
|
|
|
|
|
|
jmp skip_bpb ; Workaround for some BIOSes that require this stub |
|
|
|
nop |
|
|
|
|
|
|
|
; Some BIOSes will do a funny and decide to overwrite bytes of code in |
|
|
|
; the section where a FAT BPB would be, potentially overwriting |
|
|
|
; bootsector code. |
|
|
|
; Avoid that by filling the BPB area with dummy values. |
|
|
|
; Some of the values have to be set to certain values in order |
|
|
|
; to boot on even quirkier machines. |
|
|
|
; Source: https://github.com/freebsd/freebsd-src/blob/82a21151cf1d7a3e9e95b9edbbf74ac10f386d6a/stand/i386/boot2/boot1.S |
|
|
|
|
|
|
|
bpb: |
|
|
|
times 3-($-$$) db 0 |
|
|
|
bpb_oem_id: db "TSBL " |
|
|
|
bpb_sector_size: dw 512 |
|
|
|
bpb_sects_per_cluster: db 0 |
|
|
|
bpb_reserved_sects: dw 0 |
|
|
|
bpb_fat_count: db 0 |
|
|
|
bpb_root_dir_entries: dw 0 |
|
|
|
bpb_sector_count: dw 0 |
|
|
|
bpb_media_type: db 0 |
|
|
|
bpb_sects_per_fat: dw 0 |
|
|
|
bpb_sects_per_track: dw 18 |
|
|
|
bpb_heads_count: dw 2 |
|
|
|
bpb_hidden_sects: dd 0 |
|
|
|
bpb_sector_count_big: dd 0 |
|
|
|
bpb_drive_num: db 0 |
|
|
|
bpb_reserved: db 0 |
|
|
|
bpb_signature: db 0 |
|
|
|
bpb_volume_id: dd 0 |
|
|
|
bpb_volume_label: db "TSBL " |
|
|
|
bpb_filesystem_type: times 8 db 0 |
|
|
|
|
|
|
|
|
|
|
|
kernel_offset: equ 0x1000 ; Address in memory where kernel will be loaded |
|
|
|
reserved_sectors: equ 4 ; How many disk sectors we reserve for our second stage |
|
|
|
|
|
|
|
|
|
|
|
skip_bpb: |
|
|
|
cli |
|
|
|
cld |
|
|
|
; This isn't needed inside the qemu emulator, but |
|
|
|
; real hardware is unlikely to start up with the |
|
|
|
; segment registers zeroed, so we do it here |
|
|
|
xor si, si |
|
|
|
mov ds, si |
|
|
|
mov ss, si |
|
|
|
mov es, si |
|
|
|
|
|
|
|
|
|
|
|
; We save the value of the current boot drive |
|
|
|
mov [boot_drive], dl |
|
|
|
|
|
|
|
; Now we setup the stack by setting the |
|
|
|
; base pointer to a location that's far |
|
|
|
; enough from where the code for the BIOS |
|
|
|
; is located |
|
|
|
mov sp, 0x7c00 |
|
|
|
mov bp, sp |
|
|
|
sti |
|
|
|
call bios_cls |
|
|
|
mov si, loading_stage2_msg |
|
|
|
call bios_println |
|
|
|
mov bx, stage2 |
|
|
|
mov cl, 2 |
|
|
|
mov dh, reserved_sectors |
|
|
|
mov dl, [boot_drive] |
|
|
|
call load_disk |
|
|
|
jmp stage2 |
|
|
|
|
|
|
|
|
|
|
|
; Variables needed in the boot |
|
|
@ -66,6 +105,7 @@ times 510 - ($ - $$) db 0 |
|
|
|
dw 0xaa55 |
|
|
|
|
|
|
|
[bits 16] |
|
|
|
|
|
|
|
stage2: |
|
|
|
; Here we're no longer limited by the size of the |
|
|
|
; boot sector, so we can perform the more complex |
|
|
@ -76,7 +116,7 @@ stage2: |
|
|
|
call switch_to_protected_mode |
|
|
|
|
|
|
|
|
|
|
|
load_kernel: |
|
|
|
load_kernel: |
|
|
|
; Loads the kernel into memory |
|
|
|
mov bx, kernel_offset |
|
|
|
mov cl, reserved_sectors + 1 |
|
|
|