bootsect: Do not assume 512-byte sectors

This commit is contained in:
mintsuki 2020-11-05 17:00:15 +01:00
parent dbb88b5928
commit 1ead86ef70
4 changed files with 43 additions and 31 deletions

View File

@ -54,11 +54,11 @@ start:
; make sure that is the case now.
mov esp, 0x7c00
push 0x7000
push 0x6fe0
pop es
mov eax, dword [stage2_sector]
xor bx, bx
mov cx, 63
mov ecx, 32768
call read_sectors
jc err
@ -112,7 +112,7 @@ vector:
bits 16
times 0x1b0-($-$$) db 0
stage2_sector: dd 1
stage2_sector: dd 0
times 0x1b8-($-$$) db 0
times 510-($-$$) db 0

View File

@ -7,7 +7,7 @@
; DL = Drive number
; ES = Buffer segment
; BX = Buffer offset
; CX = Sectors count
; ECX = Byte count
; OUT:
; Carry if error
@ -15,40 +15,49 @@
read_sectors:
pusha
push es
pop word [.target_segment]
mov word [.target_offset], bx
mov dword [.lba_address_low], eax
mov esi, .da_struct
mov word [.countdown], cx
mov word [si], 16
mov word [si+2], 1
mov word [si+4], bx
mov word [si+6], es
mov dword [si+8], eax
mov dword [si+12], 0
; Get bytes per sector
push dx
push si
mov ah, 0x48
mov si, .drive_params
mov word [si], 30 ; buf_size
int 0x13
jc .done
mov bp, word [si+24] ; bytes_per_sect
mov ax, cx
shr ecx, 16
mov dx, cx
xor cx, cx
div bp
test dx, dx
adc cx, ax
pop si
pop dx
.loop:
mov esi, .da_struct
mov ah, 0x42
clc
int 0x13
jc .done
add word [.target_offset], 512
inc dword [.lba_address_low]
add word [si+4], bp
inc dword [si+8]
dec word [.countdown]
jnz .loop
loop .loop
.done:
popa
ret
align 2
.countdown: dw 0
align 4
.da_struct:
.packet_size db 16
.unused db 0
.count dw 1
.target_offset dw 0
.target_segment dw 0
.lba_address_low dd 0
.lba_address_high dd 0
.da_struct: equ 0x8000
.drive_params: equ 0x8010

View File

@ -8,10 +8,10 @@ int main(int argc, char *argv[]) {
FILE *bootloader_file, *device;
uint8_t *bootloader_img;
uint8_t orig_mbr[70], timestamp[6];
uint32_t stage2_sect;
uint32_t stage2_sect, sect_size;
if (argc < 3) {
printf("Usage: %s <bootloader image> <device> [stage2 start sector]\n", argv[0]);
printf("Usage: %s <bootloader image> <device> [<stage2 start sector> <sector size>]\n", argv[0]);
return 1;
}
@ -41,9 +41,12 @@ int main(int argc, char *argv[]) {
return 1;
}
stage2_sect = 1;
stage2_sect = 0;
sect_size = 512;
if (argc >= 4)
sscanf(argv[3], "%" SCNu32, &stage2_sect);
if (argc >= 5)
sscanf(argv[4], "%" SCNu32, &sect_size);
// Save original timestamp
fseek(device, 218, SEEK_SET);
@ -58,8 +61,8 @@ int main(int argc, char *argv[]) {
fwrite(&bootloader_img[0], 1, 512, device);
// Write the rest of stage 2 to the device
fseek(device, stage2_sect * 512, SEEK_SET);
fwrite(&bootloader_img[512], 63, 512, device);
fseek(device, stage2_sect * sect_size, SEEK_SET);
fwrite(&bootloader_img[0], 64, 512, device);
// Hardcode in the bootsector the location of stage 2
fseek(device, 0x1b0, SEEK_SET);

Binary file not shown.