65 lines
1.7 KiB
NASM
65 lines
1.7 KiB
NASM
sectalign off
|
|
|
|
; The following code expects two external macros:
|
|
; STAGE3, a path to the stage3 binary
|
|
; STAGE2_SECTOR, the location of stage 2
|
|
; on the disk, in 512-byte sectors.
|
|
;
|
|
; Both of these are set in the makefile.
|
|
|
|
; BIOS loads stage 1 at 0x7C00
|
|
ORG 0x7C00
|
|
SECTION .text
|
|
|
|
; Stage 1 is MBR code, and should fit in LBA 0
|
|
; (i.e, in the first 512 bytes).
|
|
%include "stage1.asm"
|
|
|
|
; Stage 1 is at most 440 bytes
|
|
; This limit is set by the GPT spec.
|
|
; See https://uefi.org/specs/UEFI/2.10/05_GUID_Partition_Table_Format.html
|
|
;
|
|
; This `times` will throw an error if the subtraction is negative.
|
|
times 440-($-$$) db 0
|
|
db 0xee
|
|
|
|
; Pad until 512
|
|
times 510-($-$$) db 0
|
|
|
|
; MBR signature.
|
|
; This tells the BIOS that this disk is bootable.
|
|
db 0x55
|
|
db 0xaa
|
|
|
|
|
|
; Include stage 2. This is loaded into memory by stage 1.
|
|
; (stage 1 loads both stage 2 and stage 3)
|
|
;
|
|
; Stage 2 sets up protected mode, sets up the GDT,
|
|
; and initializes a minimal environment for stage 3.
|
|
;
|
|
; On a "real" boot disk, this data will not immediately follow stage 1.
|
|
; It would be stored in a special disk partition.
|
|
;
|
|
; We don't need this kind of complexity here, though, so we store
|
|
; stage 2 right after stage 1. (This is why STAGE2_SECTOR is 1.)
|
|
;
|
|
; This is nice, because the layout of the code on our boot disk
|
|
; matches the layout of the code in memory. THIS IS NOT USUALLY THE CASE.
|
|
stage2:
|
|
%include "stage2.asm"
|
|
align 512, db 0
|
|
stage2.end:
|
|
|
|
; Pad to 0x3000.
|
|
; This makes sure that state3 is loaded at the address
|
|
; the linker expects. Must match the value in `tetros/linkers/x86-unknown-none.ld`.
|
|
times (0x8000 - 0x7c00)-($-$$) db 0
|
|
|
|
; Include stage 3, the binary compiled from Rust sources.
|
|
stage3:
|
|
%defstr STAGE3_STR %[STAGE3]
|
|
incbin STAGE3_STR
|
|
align 512, db 0
|
|
.end:
|