|
|
|
@ -20,6 +20,8 @@
|
|
|
|
; bp - 0x08: partition array starting LBA
|
|
|
|
; bp - 0x08: partition array starting LBA
|
|
|
|
; bp - 0x0a: number of GPT partitions (saturated to 16-bits)
|
|
|
|
; bp - 0x0a: number of GPT partitions (saturated to 16-bits)
|
|
|
|
; bp - 0x0c: sector stride when loading GPT entries
|
|
|
|
; bp - 0x0c: sector stride when loading GPT entries
|
|
|
|
|
|
|
|
; bp - 0x0e: byte stride when loading GPT entries
|
|
|
|
|
|
|
|
; bp - 0x10: entries per sector when loding GPT entries
|
|
|
|
|
|
|
|
|
|
|
|
; BIOS puts our boot sector at 0000:7c00
|
|
|
|
; BIOS puts our boot sector at 0000:7c00
|
|
|
|
org 0x7c00
|
|
|
|
org 0x7c00
|
|
|
|
@ -114,29 +116,55 @@ bits 16
|
|
|
|
mov bx, [di + 0x52]
|
|
|
|
mov bx, [di + 0x52]
|
|
|
|
or bx, bx
|
|
|
|
or bx, bx
|
|
|
|
jz .gpt_n_partitions_loaded
|
|
|
|
jz .gpt_n_partitions_loaded
|
|
|
|
mov ax, 0xff ; Number of partitions overflows 16 bits
|
|
|
|
; Number of partitions overflows 16 bits, so we just concern ourselves with the first 65535.
|
|
|
|
|
|
|
|
; That's an awful lot of partitions anyway.
|
|
|
|
|
|
|
|
mov ax, 0xffff
|
|
|
|
.gpt_n_partitions_loaded:
|
|
|
|
.gpt_n_partitions_loaded:
|
|
|
|
push ax
|
|
|
|
push ax
|
|
|
|
|
|
|
|
|
|
|
|
; Load GPT entry size
|
|
|
|
; Load GPT entry size
|
|
|
|
mov ax, [di + 0x54]
|
|
|
|
mov eax, [di + 0x54] ; Operand size override otherwise this is going to be painful
|
|
|
|
mov bx, [di + 0x56]
|
|
|
|
mov ebx, eax
|
|
|
|
mov cx, ax
|
|
|
|
; Assert that the entry size is 128 * 2^n for some integer n>=0. This is required for a valid GPT
|
|
|
|
mov dx, bx
|
|
|
|
; and has the nice properties that:
|
|
|
|
; Find number of sectors per entry
|
|
|
|
; - If each entry is larger than a sector (512 bytes), they'll be sector-aligned.
|
|
|
|
shr ax, 9
|
|
|
|
; - If each entry is smaller than a sector, an integer number of them will fit into a sector.
|
|
|
|
shr bx, 9
|
|
|
|
or eax, eax ; Test size != 0 because 128 * 2^n != 0
|
|
|
|
or bx, bx
|
|
|
|
jz .panic
|
|
|
|
jnz .panic ; Sectors per entry overflows 16 bits
|
|
|
|
and eax, 127 ; Test size is a multiple of 128
|
|
|
|
mov bx, ax
|
|
|
|
jnz .panic
|
|
|
|
cmp bx, 1
|
|
|
|
mov eax, ebx
|
|
|
|
|
|
|
|
shr eax, 7 ; Divide by 128
|
|
|
|
|
|
|
|
mov ecx, eax
|
|
|
|
|
|
|
|
dec eax
|
|
|
|
|
|
|
|
and eax, ecx ; Test size/128 is a power of 2. popcnt gives an exception for some reason...
|
|
|
|
|
|
|
|
jnz .panic
|
|
|
|
|
|
|
|
mov eax, ebx
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
; Find the "sector stride", which is the number of sectors we increment by each time we want to
|
|
|
|
|
|
|
|
; load a new entry.
|
|
|
|
|
|
|
|
shr eax, 9 ; Divide by sector size to get sectors per entry
|
|
|
|
|
|
|
|
cmp eax, 0xffff ; Make sure sectors per entry fits in 16 bits
|
|
|
|
|
|
|
|
ja .panic
|
|
|
|
|
|
|
|
or ax, ax
|
|
|
|
jnz .gpt_sector_stride_loaded
|
|
|
|
jnz .gpt_sector_stride_loaded
|
|
|
|
inc bx ; Sector stride must be at least one or we'll load the same sector forever!
|
|
|
|
; Sector stride must be at least one or we'll load the same sector each time!
|
|
|
|
|
|
|
|
inc ax
|
|
|
|
.gpt_sector_stride_loaded:
|
|
|
|
.gpt_sector_stride_loaded:
|
|
|
|
push bx
|
|
|
|
push ax
|
|
|
|
|
|
|
|
|
|
|
|
; ax stores sectors per entry
|
|
|
|
cmp ebx, 512
|
|
|
|
; FIXME: if sectors per entry > 1, then entry size must be a multiple of sector size
|
|
|
|
jb .gpt_find_entries_per_sector
|
|
|
|
|
|
|
|
push word 0 ; Arbitrary byte stride since there's only one entry per sector
|
|
|
|
|
|
|
|
push word 1 ; 1 entry per sector, since an entry is larger than a sector
|
|
|
|
|
|
|
|
jmp .gpt_found_entries_per_sector
|
|
|
|
|
|
|
|
.gpt_find_entries_per_sector:
|
|
|
|
|
|
|
|
push bx ; Store byte stride = entry length in this case
|
|
|
|
|
|
|
|
xor dx, dx
|
|
|
|
|
|
|
|
mov ax, 512
|
|
|
|
|
|
|
|
div bx ; Find entries per sector
|
|
|
|
|
|
|
|
push ax
|
|
|
|
|
|
|
|
.gpt_found_entries_per_sector:
|
|
|
|
|
|
|
|
|
|
|
|
mov al, [0x7e00]
|
|
|
|
mov al, [0x7e00]
|
|
|
|
mov byte fs:[0x0000], al
|
|
|
|
mov byte fs:[0x0000], al
|
|
|
|
|