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: