From 3aefeeb723b8822916fb39b7c32551c35c06e32f Mon Sep 17 00:00:00 2001 From: Alejandro Sior Date: Sat, 21 May 2022 14:04:42 +0200 Subject: boot: reorganize bios and drive modules --- bios/README | 2 ++ bios/bios.ha | 13 --------- bios/boot.ha | 12 ++++++++ bios/drive/+x86_64/drive.s | 7 ----- bios/drive/drive.ha | 71 ---------------------------------------------- drive/+bios/drive.ha | 69 ++++++++++++++++++++++++++++++++++++++++++++ drive/README | 4 +++ drive/drive.ha | 21 -------------- drive/errors.ha | 1 + main.ha | 4 +-- run.sh | 2 +- 11 files changed, 90 insertions(+), 116 deletions(-) create mode 100644 bios/README create mode 100644 bios/boot.ha delete mode 100644 bios/drive/+x86_64/drive.s delete mode 100644 bios/drive/drive.ha create mode 100644 drive/+bios/drive.ha create mode 100644 drive/README delete mode 100644 drive/drive.ha create mode 100644 drive/errors.ha diff --git a/bios/README b/bios/README new file mode 100644 index 0000000..1aa7f47 --- /dev/null +++ b/bios/README @@ -0,0 +1,2 @@ +bios is a facility to raise BIOS interrupts from long-mode and declares important boot constants. +It serves as a backend for various interface implementations. \ No newline at end of file diff --git a/bios/bios.ha b/bios/bios.ha index 5a3c1aa..caaa37f 100644 --- a/bios/bios.ha +++ b/bios/bios.ha @@ -13,19 +13,6 @@ export type state = struct { // The set real mode registers export let regs: state; -// The address of a 512 bytes workspace that is located below 0xFFFFF and can be used to store the results -// of various bios calls -export const @symbol("_ws") ws: [4096]u8; - -// The boot drive number as given by the BIOS at boot time -export const @symbol("drive_no") drive_number: u8; - -// The amount of sectors per track that the boot drive has -export const @symbol("drive_spt") drive_sectors_per_track: u8; - -// The amount of heads that the boot drive has -export const @symbol("drive_heads") drive_heads: u8; - // Clears the BIOS mode registers export fn clearregs() void = { regs = state { diff --git a/bios/boot.ha b/bios/boot.ha new file mode 100644 index 0000000..e165f5a --- /dev/null +++ b/bios/boot.ha @@ -0,0 +1,12 @@ +// Address of a 4096 bytes workspace that is located below 0xFFFFF and can be used to store the results +// of various bios calls +export const @symbol("_ws") ws: [4096]u8; + +// Boot drive number as given by the BIOS at boot time +export const @symbol("drive_no") drive_number: u8; + +// Amount of sectors per track that the boot drive has +export const @symbol("drive_spt") drive_sectors_per_track: u8; + +// Amount of heads that the boot drive has +export const @symbol("drive_heads") drive_heads: u8; diff --git a/bios/drive/+x86_64/drive.s b/bios/drive/+x86_64/drive.s deleted file mode 100644 index 1f3828e..0000000 --- a/bios/drive/+x86_64/drive.s +++ /dev/null @@ -1,7 +0,0 @@ -.code16 - -.globl bios.drive.read -bios.drive.read: - mov $0x2, %ah - int $0x13 - ret diff --git a/bios/drive/drive.ha b/bios/drive/drive.ha deleted file mode 100644 index a2992b8..0000000 --- a/bios/drive/drive.ha +++ /dev/null @@ -1,71 +0,0 @@ -use bios; - -def sector_size: u32 = 512; - -export type error = !void; - -// Converts lba to the CHS format -fn lbatochs(lba: u32) (u16, u16, u16) = { - const temp = lba / bios::drive_sectors_per_track; - const sector = (lba % bios::drive_sectors_per_track) + 1; - const head = temp % bios::drive_heads; - const cylinder = temp / bios::drive_heads; - - return (cylinder: u16, head: u16, sector: u16); -}; - -// Reads the sector at lba and place it into the workspace buffer -fn bios_read(lba: u32) (void | error) = { - const chs = lbatochs(lba); - const readcount = len(bios::ws): u32 / sector_size; - - // AH=0x2 (read disk) AL=1 (read 1 sector) - bios::regs.eax = 0x2 << 8 | readcount; - - // CH=cylinder CL=sector - bios::regs.ecx = chs.0 << 8 | chs.2; - - // DH=head DL=driveno - bios::regs.edx = chs.1 << 8 | bios::drive_number; - - let ws = (&bios::ws): uintptr; - bios::regs.es = (ws / 16): u16; - bios::regs.ebx = (ws % 16): u32; - - bios::call(0x13); - - if (bios::regs.eax != readcount) { - return error; - }; -}; - -export fn read(addr: u32, count: size, dest: *[*]u8) (void | error) = { - // the amount of sectors fitting in the workspace (cannot be make a global constant yet, an assertion fails) - const readcount = len(bios::ws): u32 / sector_size; - - // the starting lba - let lba = addr / sector_size; - // the reading head (for starting to read bytes not aligned with the sector) - let head = addr % len(bios::ws); - - let cursor = 0z; - - for (true) { - bios_read(lba)?; - - for (head < len(bios::ws)) { - // XXX: use memmove - dest[cursor] = bios::ws[head]; - - head += 1; - cursor += 1; - if (cursor >= count) { - return; - }; - }; - - head = 0; - lba += readcount; - }; - -}; diff --git a/drive/+bios/drive.ha b/drive/+bios/drive.ha new file mode 100644 index 0000000..da33740 --- /dev/null +++ b/drive/+bios/drive.ha @@ -0,0 +1,69 @@ +use bios; + +def sector_size: u32 = 512; + +// Converts lba to the CHS format +fn lbatochs(lba: u32) (u16, u16, u16) = { + const temp = lba / bios::drive_sectors_per_track; + const sector = (lba % bios::drive_sectors_per_track) + 1; + const head = temp % bios::drive_heads; + const cylinder = temp / bios::drive_heads; + + return (cylinder: u16, head: u16, sector: u16); +}; + +// Reads the sector at lba and place it into the workspace buffer +fn bios_read(lba: u32) (void | error) = { + const chs = lbatochs(lba); + const readcount = len(bios::ws): u32 / sector_size; + + // AH=0x2 (read disk) AL=1 (read 1 sector) + bios::regs.eax = 0x2 << 8 | readcount; + + // CH=cylinder CL=sector + bios::regs.ecx = chs.0 << 8 | chs.2; + + // DH=head DL=driveno + bios::regs.edx = chs.1 << 8 | bios::drive_number; + + let ws = (&bios::ws): uintptr; + bios::regs.es = (ws / 16): u16; + bios::regs.ebx = (ws % 16): u32; + + bios::call(0x13); + + if (bios::regs.eax != readcount) { + return error; + }; +}; + +export fn read(addr: u32, count: size, dest: *[*]u8) (void | error) = { + // the amount of sectors fitting in the workspace (cannot be make a global constant yet, an assertion fails) + const readcount = len(bios::ws): u32 / sector_size; + + // the starting lba + let lba = addr / sector_size; + // the reading head (for starting to read bytes not aligned with the sector) + let head = addr % len(bios::ws); + + let cursor = 0z; + + for (true) { + bios_read(lba)?; + + for (head < len(bios::ws)) { + // XXX: use memmove + dest[cursor] = bios::ws[head]; + + head += 1; + cursor += 1; + if (cursor >= count) { + return; + }; + }; + + head = 0; + lba += readcount; + }; + +}; diff --git a/drive/README b/drive/README new file mode 100644 index 0000000..cd7a6f8 --- /dev/null +++ b/drive/README @@ -0,0 +1,4 @@ +drive contains various implementations of the drive reading interface + +Currently, it supports: + - BIOS (via the bios module). \ No newline at end of file diff --git a/drive/drive.ha b/drive/drive.ha deleted file mode 100644 index 259e7f5..0000000 --- a/drive/drive.ha +++ /dev/null @@ -1,21 +0,0 @@ -use bios; -use bios::drive; - -fn lba_to_chs(lba: u16) (u16, u16, u16) = { - //let temp = lba / bios::drive::drive_spt; - //let sector = (lba % bios::drive::drive_spt) + 1; - //let head = temp % bios::drive::drive_heads; - //let cylinder = temp / bios::drive::drive_heads; - - //return (cylinder, head, sector); - return (0, 0, 0); -}; - -export fn read(sector: u16, dest: uintptr) void = { - let chs = lba_to_chs(sector); - - //bios::regs.eax = 1 | 0x2 << 8; - //bios::regs.ebx = ws; - //bios::regs.ecx = chs.2 | chs.0 << 8; - //bios::regs.edx = bios::drive::drive_no | chs.1 << 8; -}; diff --git a/drive/errors.ha b/drive/errors.ha new file mode 100644 index 0000000..58742fb --- /dev/null +++ b/drive/errors.ha @@ -0,0 +1 @@ +export type error = !void; diff --git a/main.ha b/main.ha index e26fb26..e640d04 100644 --- a/main.ha +++ b/main.ha @@ -2,7 +2,6 @@ use vga; use term; use rt; use bios; -use bios::drive; use drive; export fn main() void = { @@ -15,9 +14,8 @@ export fn main() void = { term::print(&text, "a"); }; - //bios::drive::read(0, 512, bios::ws: uintptr); let dest = 0x100000: uintptr: *[*]u8; - bios::drive::read(0, 512, dest)!; + drive::read(0, 512, dest)!; if (dest[511] == 0xaa) { term::print(&text, "\nnice!"); }; diff --git a/run.sh b/run.sh index 0e136e4..6b28de9 100755 --- a/run.sh +++ b/run.sh @@ -9,7 +9,7 @@ export HAREPATH=. export LDFLAGS="--gc-sections" # :Do the build -hare build -X^ -T+x86_64 +hare build -X^ -T+x86_64 -T+bios # :Create a flat binary out of the elf file # (while also removing the breaking gnu note) -- cgit v1.2.3