From dfd5ca4a0f34f9346ff2decbd3cfc8e3f6fccc04 Mon Sep 17 00:00:00 2001 From: Jeremy Soller <jackpot51@gmail.com> Date: Tue, 6 Sep 2022 15:51:30 -0600 Subject: [PATCH] Use CHS to support CD boot --- asm/x86-unknown-none/stage1.asm | 90 ++++++++++++++++++++++++++++++--- src/os/bios/disk.rs | 85 +++++++++++++++++++++++++------ 2 files changed, 153 insertions(+), 22 deletions(-) diff --git a/asm/x86-unknown-none/stage1.asm b/asm/x86-unknown-none/stage1.asm index 26740c9..d2175e1 100644 --- a/asm/x86-unknown-none/stage1.asm +++ b/asm/x86-unknown-none/stage1.asm @@ -22,18 +22,42 @@ stage1: ; dl comes with disk ; save disk number mov [disk], dl - mov si, name + mov si, stage_msg call print + mov al, '1' + call print_char call print_line + ; read CHS gemotry + ; CL (bits 0-5) = maximum sector number + ; CL (bits 6-7) = high bits of max cylinder number + ; CH = low bits of maximum cylinder number + ; DH = maximum head number + mov ah, 0x08 + mov dl, [disk] + xor di, di + int 0x13 + jc error ; carry flag set on error + mov bl, ch + mov bh, cl + shr bh, 6 + mov [chs.c], bx + shr dx, 8 + inc dx ; returns heads - 1 + mov [chs.h], dx + and cl, 0x3f + mov [chs.s], cl + mov eax, (stage2 - stage1) / 512 mov bx, stage2 mov cx, (stage3.end - stage2) / 512 mov dx, 0 call load - mov si, finished + mov si, stage_msg call print + mov al, '2' + call print_char call print_line jmp stage2.entry @@ -70,11 +94,56 @@ load: call print_dapack + cmp byte [chs.s], 0 + jne .chs + ;INT 0x13 extended read does not work on CDROM! mov dl, [disk] mov si, DAPACK mov ah, 0x42 int 0x13 - jc error + jc error ; carry flag set on error + ret + +.chs: + ; calculate CHS + xor edx, edx + mov eax, [DAPACK.addr] + div dword [chs.s] ; divide by sectors + mov ecx, edx ; move sector remainder to ecx + xor edx, edx + div dword [chs.h] ; divide by heads + ; eax has cylinders, edx has heads, ecx has sectors + + ; Sector cannot be greater than 63 + inc ecx ; Sector is base 1 + cmp ecx, 63 + ja error_chs + + ; Head cannot be greater than 255 + cmp edx, 255 + ja error_chs + + ; Cylinder cannot be greater than 1023 + cmp eax, 1023 + ja error_chs + + ; Move CHS values to parameters + mov ch, al + shl ah, 6 + and cl, 0x3f + or cl, ah + shl dx, 8 + + ; read from disk using CHS + mov al, [DAPACK.count] + mov ah, 0x02 ; disk read (CHS) + mov bx, [DAPACK.buf] + mov dl, [disk] + push es ; save ES + mov es, [DAPACK.seg] + int 0x13 + pop es ; restore EC + jc error ; carry flag set on error ret print_dapack: @@ -106,6 +175,9 @@ print_dapack: ret +error_chs: + mov ah, 0 + error: call print_line @@ -116,7 +188,7 @@ error: mov al, ' ' call print_char - mov si, errored + mov si, error_msg call print call print_line .halt: @@ -126,12 +198,16 @@ error: %include "print.asm" -name: db "Redox Loader - Stage One",0 -errored: db "Could not read disk",0 -finished: db "Redox Loader - Stage Two",0 +stage_msg: db "Stage ",0 +error_msg: db "ERROR",0 disk: db 0 +chs: +.c: dd 0 +.h: dd 0 +.s: dd 0 + DAPACK: db 0x10 db 0 diff --git a/src/os/bios/disk.rs b/src/os/bios/disk.rs index 4f864f8..c24f48a 100644 --- a/src/os/bios/disk.rs +++ b/src/os/bios/disk.rs @@ -42,11 +42,33 @@ impl DiskAddressPacket { pub struct DiskBios { boot_disk: u8, thunk13: extern "C" fn(), + chs_opt: Option<(u32, u32, u32)>, } impl DiskBios { pub fn new(boot_disk: u8, thunk13: extern "C" fn()) -> Self { - Self { boot_disk, thunk13 } + let chs_opt = unsafe { + let mut data = ThunkData::new(); + data.eax = 0x0800; + data.edx = boot_disk as u32; + data.edi = 0; + + data.with(thunk13); + + let c = + (data.ecx >> 8) & 0xFF | + ((data.ecx >> 6) & 0x3) << 8; + let h = ((data.edx >> 8) & 0xFF) + 1; + let s = data.ecx & 0x3F; + + Some((c, h, s)) + }; + + Self { + boot_disk, + thunk13, + chs_opt, + } } } @@ -69,21 +91,54 @@ impl Disk for DiskBios { block + i as u64 * MAX_BLOCKS, chunk.len() as u64 / BLOCK_SIZE ); - ptr::write(DISK_ADDRESS_PACKET_ADDR as *mut DiskAddressPacket, dap); - - let mut data = ThunkData::new(); - data.eax = 0x4200; - data.edx = self.boot_disk as u32; - data.esi = DISK_ADDRESS_PACKET_ADDR as u32; - data.with(self.thunk13); - - //TODO: return result on error - let ah = ({ data.eax } >> 8) & 0xFF; - assert_eq!(ah, 0); - - //TODO: check blocks transferred - dap = ptr::read(DISK_ADDRESS_PACKET_ADDR as *mut DiskAddressPacket); + if let Some((c_max, h_max, s_max)) = self.chs_opt { + let s = (dap.address % s_max as u64) + 1; + assert!(s <= 63); + + let tmp = dap.address / s_max as u64; + let h = tmp % h_max as u64; + assert!(h <= 255); + + let c = tmp / h_max as u64; + assert!(c <= 1023); + + let mut data = ThunkData::new(); + data.eax = + 0x0200 | + (dap.sectors as u32); + data.ebx = dap.buffer as u32; + data.ecx = + (s as u32) | + (((c as u32) & 0xFF) << 8) | + ((((c as u32) >> 8) & 0x3) << 6); + data.edx = + (self.boot_disk as u32) | + ((h as u32) << 8); + data.es = dap.segment; + + data.with(self.thunk13); + + //TODO: return result on error + let ah = ({ data.eax } >> 8) & 0xFF; + assert_eq!(ah, 0); + } else { + ptr::write(DISK_ADDRESS_PACKET_ADDR as *mut DiskAddressPacket, dap); + + let mut data = ThunkData::new(); + data.eax = 0x4200; + data.edx = self.boot_disk as u32; + data.esi = DISK_ADDRESS_PACKET_ADDR as u32; + + data.with(self.thunk13); + + //TODO: return result on error + let ah = ({ data.eax } >> 8) & 0xFF; + assert_eq!(ah, 0); + + //TODO: check blocks transferred + dap = ptr::read(DISK_ADDRESS_PACKET_ADDR as *mut DiskAddressPacket); + } ptr::copy(DISK_BIOS_ADDR as *const u8, chunk.as_mut_ptr(), chunk.len()); } -- GitLab