Merge pull request #2 from Nivirx/FAT_Refactor
Full refactor for modularization
This commit is contained in:
@@ -10,7 +10,7 @@ floppy_bootsig_check: disabled=0
|
||||
floppya: type=1_44
|
||||
# no floppyb
|
||||
ata0: enabled=true, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
|
||||
ata0-master: type=disk, path=".\disk.img", mode=flat, cylinders=0, heads=0, spt=0, sect_size=512, model="Stevia Disk", biosdetect=auto, translation=auto
|
||||
ata0-master: type=disk, path=".\disk.img", mode=flat, cylinders=0, heads=0, spt=0, sect_size=512, model="Stevia Disk", biosdetect=auto, translation=lba
|
||||
ata0-slave: type=none
|
||||
ata1: type=none
|
||||
ata1-master: type=none
|
||||
|
||||
24
include/BIOS/BIOS_sys.inc
Normal file
24
include/BIOS/BIOS_sys.inc
Normal file
@@ -0,0 +1,24 @@
|
||||
; Copyright (c) 2024 Elaina Claus
|
||||
;
|
||||
; Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
; of this software and associated documentation files (the "Software"), to deal
|
||||
; in the Software without restriction, including without limitation the rights
|
||||
; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
; copies of the Software, and to permit persons to whom the Software is
|
||||
; furnished to do so, subject to the following conditions:
|
||||
;
|
||||
; The above copyright notice and this permission notice shall be included in all
|
||||
; copies or substantial portions of the Software.
|
||||
;
|
||||
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
; SOFTWARE.
|
||||
|
||||
%include 'BIOS/func/a20enable.inc'
|
||||
%include 'BIOS/func/E820_memory_map.inc'
|
||||
%include 'BIOS/func/ext_read.inc'
|
||||
%include 'BIOS/func/video.inc'
|
||||
146
include/memory.inc → include/BIOS/func/E820_memory_map.inc
Executable file → Normal file
146
include/memory.inc → include/BIOS/func/E820_memory_map.inc
Executable file → Normal file
@@ -1,4 +1,4 @@
|
||||
; Copyright (c) 2023 Elaina Claus
|
||||
; Copyright (c) 2024 Elaina Claus
|
||||
;
|
||||
; Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
; of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -18,97 +18,7 @@
|
||||
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
; SOFTWARE.
|
||||
|
||||
|
||||
; ## Generic Low mem map (from osdev wiki) ##
|
||||
; start end size type description
|
||||
; Low Memory (the first MiB)
|
||||
; 0x00000000 0x000003FF 1 KiB RAM - partially unusable Real Mode IVT (Interrupt Vector Table)
|
||||
; 0x00000400 0x000004FF 256 bytes RAM - partially unusable BDA (BIOS data area)
|
||||
; 0x00000500 0x00007BFF almost 30 KiB RAM - free for use Conventional memory
|
||||
; 0x00007C00 0x00007DFF 512 bytes RAM - partially unusable OS BootSector
|
||||
; 0x00007E00 0x0007FFFF 480.5 KiB RAM - free for use Conventional memory
|
||||
; 0x00080000 0x0009FFFF 128 KiB RAM - partially unusable EBDA (Extended BIOS Data Area)
|
||||
; 0x000A0000 0x000FFFFF 384 KiB various (unusable) Video memory, ROM Area
|
||||
|
||||
; ## A rough overview of high mem ##
|
||||
; Idealy this needs to be probed with the E820 functions
|
||||
; # Start # End # size # description
|
||||
;
|
||||
; 0x00100000 0x00EFFFFF 0x00E00000 (14 MiB) RAM -- free for use (if it exists) Extended memory
|
||||
; 0x00F00000 0x00FFFFFF 0x00100000 (1 MiB) Possible memory mapped hardware ISA Memory Hole 15-16MB
|
||||
; 0x01000000 ???????? ??? (whatever exists) RAM -- free for use More Extended memory
|
||||
; 0xC0000000 (sometimes) 0xFFFFFFFF 0x40000000 (1 GiB) Memory mapped PCI devices, PnP NVRAM?, IO APIC/s, local APIC/s, BIOS, ...
|
||||
; 0x0000000100000000 ??? ??? (whatever exists) RAM -- free for use (PAE/64bit)/More Extended memory
|
||||
; ???????????????? ??? ??? Potentially usable for memory mapped PCI devices in modern hardware (but typically not, due to backward compatibility)
|
||||
|
||||
; 0x2700 -> 0x28FF
|
||||
%define disk_buffer 0x2700
|
||||
; 0x2900 -> 0x2AFF
|
||||
%define fat_buffer 0x2900
|
||||
; 0x2B00 -> 0x2CFF
|
||||
%define dir_buffer 0x2B00
|
||||
|
||||
; copy of partition table, 72 bytes
|
||||
%define partition_table 0x3000
|
||||
%define partition_table_SIZE 72
|
||||
|
||||
; copy of FAT32 BPB, 33 bytes (+1 to the next value to align to uint16_t)
|
||||
;0x3048
|
||||
%define fat32_bpb 0x3050
|
||||
%define fat32_bpb_SIZE 33
|
||||
|
||||
; copy of FAT32 EBPB, 54 bytes
|
||||
;0x306A
|
||||
%define fat32_ebpb 0x30A0
|
||||
%define fat32_ebpb_SIZE 54
|
||||
|
||||
; FAT32 FSInfo, 512 bytes
|
||||
;0x30A2
|
||||
%define fat32_fsinfo 0x30B0
|
||||
%define fat32_fsinfo_SIZE 512
|
||||
|
||||
; some stored state for the fat32 driver
|
||||
;0x32A2
|
||||
%define fat32_state 0x32B0
|
||||
%define fat32_state_SIZE 32
|
||||
|
||||
; next free space is 0x32D0
|
||||
%define fat32_nc_data 0x32D0
|
||||
%define fat32_nc_data_size 16
|
||||
|
||||
; lba_packet for raw_disk_read
|
||||
%define lba_packet 0x4000
|
||||
|
||||
%define BIOSMemoryMap 0x4200
|
||||
%define SteviaInfo 0x4400
|
||||
|
||||
|
||||
; High memory addresses for loading kernel (for use with unreal mode and 32bit override)
|
||||
|
||||
; file load buffer at 16MB
|
||||
%define HMEM_load_buffer 0x1000000
|
||||
|
||||
|
||||
;PhysicalAddress = Segment * 16 + Offset
|
||||
%define SEG_TO_LINEAR(s,o) ((s << 4) + o)
|
||||
|
||||
; Offset = physical / (Segment * 16)
|
||||
%define LINEAR_TO_OFFSET(p,s) ((p / (s << 4)))
|
||||
|
||||
; Seg = (physical - offset) / 16
|
||||
%define LINEAR_TO_SEGMENT(p,o) ((p - o) >> 4)
|
||||
|
||||
; create normalized linear addres from seg:off (16:4)
|
||||
; Segement = linear >> 4 (top 16 bits)
|
||||
; offset = linear & 0x0F (low 4 bits)
|
||||
|
||||
; 20 bytes, passed to loaded kernel
|
||||
struc SteviaInfoStruct_t
|
||||
.MemoryMapPtr resd 1
|
||||
.MemoryMapEntries resd 1
|
||||
.BPBDataPtr resd 1
|
||||
.EBPBDataPtr resd 1
|
||||
endstruc
|
||||
%ifndef __INC_E820MEMORY_MAP
|
||||
|
||||
; Address Range Descriptor Structure
|
||||
;
|
||||
@@ -207,8 +117,50 @@ struc AddressRangeDescStruct_t
|
||||
.ExtType resd 1
|
||||
endstruc
|
||||
|
||||
%macro DEBUG_HCF 0
|
||||
DEBUG_LOOP:
|
||||
hlt
|
||||
jmp short DEBUG_LOOP
|
||||
%endmacro
|
||||
ALIGN 4, db 0x90
|
||||
GetMemoryMap:
|
||||
__CDECL16_ENTRY
|
||||
push es ; save segment register
|
||||
.func:
|
||||
mov dword [SteviaInfo + SteviaInfoStruct_t.MemoryMapEntries], 0
|
||||
|
||||
mov eax, 0xE820 ; select 0xE820 function
|
||||
xor ebx, ebx ; Continuation value, 0 for the first call
|
||||
|
||||
mov dx, (BIOSMemoryMap >> 4)
|
||||
mov es, dx
|
||||
xor di, di ; (BIOSMemoryMap >> 4):0 makes di an index into BIOSMemoryMap
|
||||
|
||||
mov ecx, AddressRangeDescStruct_t_size
|
||||
mov edx, 0x534D4150 ; 'SMAP' magic
|
||||
.loop_L1:
|
||||
int 0x15
|
||||
jc GetMemoryMap.error
|
||||
cmp eax, 0x534D4150
|
||||
jne GetMemoryMap.no_smap_returned
|
||||
.no_error:
|
||||
inc dword [SteviaInfo + SteviaInfoStruct_t.MemoryMapEntries]
|
||||
|
||||
cmp ecx, 20 ; TODO: maybe this could be handled better than just panicing
|
||||
jb GetMemoryMap.nonstandard_e820 ; non-standard entry found
|
||||
|
||||
cmp ebx, 0
|
||||
je GetMemoryMap.endp ; 0 in ebx means we have reached the end of memory ranges
|
||||
|
||||
add di, AddressRangeDescStruct_t_size ; increment di to next descriptor
|
||||
mov edx, eax ; 'SMAP' to edx
|
||||
mov eax, 0xE820 ; select E820 function
|
||||
jmp GetMemoryMap.loop_L1
|
||||
.error:
|
||||
ERROR STAGE2_MM_E820_MISC_ERR
|
||||
.nonstandard_e820:
|
||||
ERROR STAGE2_MM_E820_NONSTANDARD
|
||||
.no_smap_returned:
|
||||
ERROR STAGE2_MM_E820_NO_SMAP
|
||||
.endp:
|
||||
pop es
|
||||
__CDECL16_EXIT
|
||||
ret
|
||||
|
||||
%endif
|
||||
%define __INC_E820MEMORY_MAP
|
||||
144
include/BIOS/func/a20enable.inc
Normal file
144
include/BIOS/func/a20enable.inc
Normal file
@@ -0,0 +1,144 @@
|
||||
; Copyright (c) 2024 Elaina Claus
|
||||
;
|
||||
; Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
; of this software and associated documentation files (the "Software"), to deal
|
||||
; in the Software without restriction, including without limitation the rights
|
||||
; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
; copies of the Software, and to permit persons to whom the Software is
|
||||
; furnished to do so, subject to the following conditions:
|
||||
;
|
||||
; The above copyright notice and this permission notice shall be included in all
|
||||
; copies or substantial portions of the Software.
|
||||
;
|
||||
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
; SOFTWARE.
|
||||
|
||||
%ifndef __INC_A20ENABLE
|
||||
;
|
||||
;INT 0x15 Function 2400 - Disable A20
|
||||
;Returns:
|
||||
;
|
||||
; CF = clear if success
|
||||
; AH = 0
|
||||
; CF = set on error
|
||||
; AH = status (01=keyboard controller is in secure mode, 0x86=function not supported)
|
||||
;
|
||||
;INT 0x15 Function 2401 - Enable A20
|
||||
;Returns:
|
||||
;
|
||||
; CF = clear if success
|
||||
; AH = 0
|
||||
; CF = set on error
|
||||
; AH = status (01=keyboard controller is in secure mode, 0x86=function not supported)
|
||||
;
|
||||
;INT 0x15 Function 2402 - A20 Status
|
||||
; Returns:
|
||||
;
|
||||
; CF = clear if success
|
||||
; AH = status (01: keyboard controller is in secure mode; 0x86: function not supported)
|
||||
; AL = current state (00: disabled, 01: enabled)
|
||||
; CX = set to 0xffff is keyboard controller is no ready in 0xc000 read attempts
|
||||
; CF = set on error
|
||||
;
|
||||
;INT 0x15 Function 2403 - Query A20 support
|
||||
;Returns:
|
||||
;
|
||||
;CF = clear if success
|
||||
;AH = status (01: keyboard controller is in secure mode; 0x86: function not supported)
|
||||
;BX = status.
|
||||
;
|
||||
;BX contains a bit pattern:
|
||||
;
|
||||
; Bit 0 - supported on keyboard controller
|
||||
; Bit 1 - if supported on bit 1 of I/O port 0x92
|
||||
; Bits 2:14 - Reserved
|
||||
; Bit 15 - 1 if additional data is available.
|
||||
;
|
||||
; I/O Port 0x92 infomation:
|
||||
;
|
||||
; Bit 0 - Setting to 1 causes a fast reset
|
||||
; Bit 1 - 0: disable A20; 1: enable A20
|
||||
; Bit 2 - Manufacturer defined
|
||||
; Bit 3 - power on password bytes (CMOS bytes 0x38-0x3f or 0x36-0x3f). 0: accessible, 1: inaccessible
|
||||
; Bits 4-5 - Manufacturer defined
|
||||
; Bits 6-7 - 00: HDD activity LED off; any other value is "on"
|
||||
ALIGN 4, db 0x90
|
||||
EnableA20:
|
||||
__CDECL16_ENTRY
|
||||
push ds
|
||||
push es
|
||||
.a20_check:
|
||||
cli
|
||||
|
||||
xor ax, ax
|
||||
mov es, ax
|
||||
|
||||
not ax ; ax = 0xFFFF
|
||||
mov ds, ax
|
||||
|
||||
mov di, 0x0500 ; scratch location 1
|
||||
mov si, 0x0510 ; scratch location 2
|
||||
|
||||
mov al, byte [es:di]
|
||||
push ax ; save whatever is at 0x0000:0500, physical location 0x0500
|
||||
|
||||
mov al, byte [ds:si]
|
||||
push ax ; save whatever is at 0xFFFF:0510 [clarification: 0x100500 physical location (0x100500 - 1MB = 0x0500)]
|
||||
|
||||
mov byte [es:di], 0x00 ; zero non-wraped location and write 0xFF to it after (ab)using wrapping
|
||||
mov byte [ds:si], 0xFF ; if the non-wrapped location is 0xFF, then we wraped and A20 is disabled
|
||||
|
||||
cmp byte [es:di], 0xFF
|
||||
|
||||
pop ax
|
||||
mov byte [ds:si], al ; restore original contents of scratch location 2
|
||||
|
||||
pop ax
|
||||
mov byte [es:di], al ; restore original contents of scratch location 1
|
||||
|
||||
mov ax, 0 ; return 0 if es:di == ds:si (memory wraps)
|
||||
je EnableA20.end_check
|
||||
mov ax, 1 ; return 1 if es:di != ds:si (A20 is enabled)
|
||||
.end_check:
|
||||
sti
|
||||
cmp ax, 1
|
||||
je EnableA20.endp ; A20 is already enabled
|
||||
|
||||
mov ax, 0x2403
|
||||
int 0x15
|
||||
jc EnableA20.do_fallback_a20 ; carry = error...not supported?
|
||||
cmp ah, 0
|
||||
ja EnableA20.do_fallback_a20 ; non-zero return = error as well
|
||||
|
||||
mov al, bl
|
||||
and al, 0000_0010b
|
||||
cmp al, 0000_0010b
|
||||
je EnableA20.do_fast_a20 ; if fast a20 is supported use it
|
||||
|
||||
jmp EnableA20.do_bios_a20 ; else fall back to enabling via BIOS
|
||||
|
||||
.do_fallback_a20:
|
||||
ERROR STAGE2_A20_FAILED
|
||||
.do_bios_a20:
|
||||
mov ax, 0x2401
|
||||
int 0x15
|
||||
jmp EnableA20.a20_check
|
||||
.do_fast_a20:
|
||||
in al, 0x92 ; read from FAST A20 port
|
||||
or al, 2 ; bit 0 is a fast reset, bit 1 is fast A20
|
||||
and al, 0xFE ; make sure bit 0 is 0
|
||||
out 0x92, al ; enable A20
|
||||
jmp EnableA20.a20_check
|
||||
.endp:
|
||||
pop es
|
||||
pop ds
|
||||
__CDECL16_EXIT
|
||||
ret
|
||||
|
||||
%endif
|
||||
%define __INC_A20ENABLE
|
||||
110
include/BIOS/func/ext_read.inc
Normal file
110
include/BIOS/func/ext_read.inc
Normal file
@@ -0,0 +1,110 @@
|
||||
; Copyright (c) 2024 Elaina Claus
|
||||
;
|
||||
; Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
; of this software and associated documentation files (the "Software"), to deal
|
||||
; in the Software without restriction, including without limitation the rights
|
||||
; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
; copies of the Software, and to permit persons to whom the Software is
|
||||
; furnished to do so, subject to the following conditions:
|
||||
;
|
||||
; The above copyright notice and this permission notice shall be included in all
|
||||
; copies or substantial portions of the Software.
|
||||
;
|
||||
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
; SOFTWARE.
|
||||
|
||||
%ifndef __INC_EXT_READ
|
||||
;Offset Size Description
|
||||
; 0 1 size of packet (16 bytes)
|
||||
; 1 1 always 0
|
||||
; 2 2 number of sectors to transfer (max 127 on some BIOSes)
|
||||
; 4 4 transfer buffer (0xFFFF:0xFFFF)
|
||||
; 8 4 lower 32-bits of starting 48-bit LBA
|
||||
; 12 4 upper 32-bits of starting 48-bit LBA
|
||||
; needs to be aligned to a uint32_t
|
||||
struc LBAPkt_t
|
||||
.size resb 1
|
||||
.res0 resb 1
|
||||
.xfer_size resw 1
|
||||
.offset resw 1
|
||||
.segment resw 1
|
||||
.lower_lba resd 1
|
||||
.upper_lba resd 1
|
||||
endstruc
|
||||
|
||||
; Wrapper for AH=0x42 INT13h (Extended Read)
|
||||
;
|
||||
; BIOS call details
|
||||
; AH = 42h
|
||||
; DL = drive number
|
||||
; DS:SI -> disk address packet
|
||||
;
|
||||
; Return:
|
||||
; CF clear if successful
|
||||
; AH = 00h
|
||||
; CF set on error
|
||||
; AH = error code
|
||||
; disk address packet's block count field set to number of blocks
|
||||
; successfully transferred
|
||||
;
|
||||
;
|
||||
; uint8_t read_stage2_raw(uint16_t buf_segment, uint16_t buf_offset,
|
||||
; uint32_t lba,
|
||||
; uint16_t count, uint16_t drive_num)
|
||||
ALIGN 4, db 0x90
|
||||
read_disk_raw:
|
||||
__CDECL16_ENTRY
|
||||
.func:
|
||||
mov ax, 0x10
|
||||
push ax ; len = 16 bytes
|
||||
xor ax, ax
|
||||
push ax ; val = 0
|
||||
mov ax, lba_packet
|
||||
push ax ; dest = lba_packet address
|
||||
call kmemset
|
||||
add sp, 0x06
|
||||
|
||||
mov byte [lba_packet + LBAPkt_t.size], 0x10
|
||||
|
||||
mov ax, [bp + 12]
|
||||
mov word [lba_packet + LBAPkt_t.xfer_size], ax
|
||||
|
||||
mov eax, [bp + 8]
|
||||
mov dword [lba_packet + LBAPkt_t.lower_lba], eax
|
||||
|
||||
mov ax, [bp + 6]
|
||||
mov word [lba_packet + LBAPkt_t.offset], ax
|
||||
|
||||
mov ax, [bp + 4]
|
||||
mov word [lba_packet + LBAPkt_t.segment], ax
|
||||
|
||||
mov si, lba_packet
|
||||
mov ah, 0x42
|
||||
|
||||
;BUG: still working on getting this passed down correctly, going to hard set it for now.
|
||||
movzx dx, byte [bp + 14]
|
||||
and dx, 0x00ff
|
||||
;xor dl, dl
|
||||
;mov dl, 0x80
|
||||
|
||||
int 0x13
|
||||
jnc .endf
|
||||
|
||||
%ifdef __STEVIA_MBR
|
||||
ERROR MBR_ERROR_DISK_READ_ERR
|
||||
%elifdef __STEVIA_VBR
|
||||
ERROR VBR_ERROR_DISK_READ_ERR
|
||||
%else
|
||||
ERROR STAGE2_MBR_DISK_READ_ERROR
|
||||
%endif
|
||||
.endf:
|
||||
__CDECL16_EXIT
|
||||
ret
|
||||
|
||||
%endif
|
||||
%define __INC_EXT_READ
|
||||
60
include/BIOS/func/video.inc
Normal file
60
include/BIOS/func/video.inc
Normal file
@@ -0,0 +1,60 @@
|
||||
; Copyright (c) 2024 Elaina Claus
|
||||
;
|
||||
; Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
; of this software and associated documentation files (the "Software"), to deal
|
||||
; in the Software without restriction, including without limitation the rights
|
||||
; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
; copies of the Software, and to permit persons to whom the Software is
|
||||
; furnished to do so, subject to the following conditions:
|
||||
;
|
||||
; The above copyright notice and this permission notice shall be included in all
|
||||
; copies or substantial portions of the Software.
|
||||
;
|
||||
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
; SOFTWARE.
|
||||
|
||||
%ifndef __INC_VIDEO
|
||||
; Sets output to 80x25 16 color text mode via BIOS call
|
||||
; also clears screen
|
||||
; void SetTextMode(void)
|
||||
ALIGN 4, db 0x90
|
||||
SetTextMode:
|
||||
.prolog:
|
||||
__CDECL16_ENTRY
|
||||
pushf
|
||||
.func:
|
||||
xor ah, ah ; Set Video mode BIOS function
|
||||
mov al, 0x02 ; 16 color 80x25 Text mode
|
||||
int 0x10 ; Call video interrupt
|
||||
|
||||
mov ah, 0x05 ; Select active display page BIOS function
|
||||
xor al, al ; page 0
|
||||
int 0x10 ; call video interrupt
|
||||
.endp:
|
||||
popf
|
||||
__CDECL16_EXIT
|
||||
ret
|
||||
|
||||
; disables blinking text mode cursor
|
||||
ALIGN 4, db 0x90
|
||||
disable_cursor:
|
||||
__CDECL16_ENTRY
|
||||
.func:
|
||||
mov dx, 0x3D4
|
||||
mov al, 0xA ; low cursor shape register
|
||||
out dx, al
|
||||
|
||||
inc dx
|
||||
mov al, 0x20 ; bits 6-7 unused, bit 5 disables the cursor, bits 0-4 control the cursor shape
|
||||
out dx, al
|
||||
.endp:
|
||||
__CDECL16_EXIT
|
||||
ret
|
||||
|
||||
%endif
|
||||
%define __INC_VIDEO
|
||||
@@ -21,6 +21,7 @@
|
||||
%macro __CDECL16_ENTRY 0
|
||||
push bp
|
||||
mov bp, sp
|
||||
sub sp, 0x20
|
||||
|
||||
push si
|
||||
push di
|
||||
@@ -37,4 +38,4 @@
|
||||
mov sp, bp
|
||||
pop bp
|
||||
%endmacro
|
||||
%endif
|
||||
%endif
|
||||
@@ -1,4 +1,4 @@
|
||||
; Copyright (c) 2023 Elaina Claus
|
||||
; Copyright (c) 2024 Elaina Claus
|
||||
;
|
||||
; Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
; of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -18,8 +18,12 @@
|
||||
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
; SOFTWARE.
|
||||
|
||||
%ifndef __INC_STEVIA_CONFIG
|
||||
|
||||
%define SECTOR_SIZE 512
|
||||
%define STAGE2_SECTOR_COUNT 0x40
|
||||
; 32 KiB
|
||||
%define MAX_STAGE2_BYTES (SECTOR_SIZE * STAGE2_SECTOR_COUNT)
|
||||
%define MAX_STAGE2_BYTES (SECTOR_SIZE * STAGE2_SECTOR_COUNT)
|
||||
|
||||
%endif
|
||||
%define __INC_STEVIA_CONFIG
|
||||
@@ -1,4 +1,4 @@
|
||||
; Copyright (c) 2023 Elaina Claus
|
||||
; Copyright (c) 2024 Elaina Claus
|
||||
;
|
||||
; Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
; of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -18,9 +18,13 @@
|
||||
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
; SOFTWARE.
|
||||
|
||||
%ifndef __INC_ENTRY
|
||||
|
||||
; 8KiB from 0x2500 -> 0x500
|
||||
%define STACK_START 0x2500
|
||||
%define MBR_ENTRY 0x7A00
|
||||
%define VBR_ENTRY 0x7C00
|
||||
%define STAGE2_ENTRY 0x7E00
|
||||
%define EARLY_STACK_START 0x2500
|
||||
%define MBR_ENTRY 0x7A00
|
||||
%define VBR_ENTRY 0x7C00
|
||||
%define STAGE2_ENTRY 0x7E00
|
||||
|
||||
%endif
|
||||
%define __INC_ENTRY
|
||||
@@ -1,4 +1,4 @@
|
||||
; Copyright (c) 2023 Elaina Claus
|
||||
; Copyright (c) 2024 Elaina Claus
|
||||
;
|
||||
; Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
; of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -18,6 +18,7 @@
|
||||
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
; SOFTWARE.
|
||||
|
||||
%ifndef __INC_ERROR_CODES
|
||||
|
||||
; Errors
|
||||
; 12 Errors, 5 in use
|
||||
@@ -78,34 +79,5 @@
|
||||
%define STEVIA_DEBUG_UNIMPLEMENTED 'Y'
|
||||
%define STEVIA_DEBUG_HALT 'Z'
|
||||
|
||||
|
||||
%macro ERROR 1
|
||||
xor ax, ax
|
||||
mov al, %1
|
||||
jmp error
|
||||
%endmacro
|
||||
|
||||
; pass error as ascii character in al, errors a-zA-Z or 0-9
|
||||
error:
|
||||
; fs = 0xb800 => fs:0x0000 = 0xb8000
|
||||
mov dx, 0xB800
|
||||
mov fs, dx
|
||||
|
||||
mov dx, STEVIA_DEBUG_OK
|
||||
cmp ax, dx
|
||||
jge error.debug_err
|
||||
mov dh, 0x4F ; color 0x4F is white text/red background
|
||||
jmp error.print
|
||||
.debug_err:
|
||||
mov dh, 0x5F ; debug case is white text/purple background
|
||||
|
||||
; the characters are two bytes in the order of 0xb8000: byte c, byte attribute
|
||||
; since x86 is le, we store the attribute in the MSB of dx
|
||||
.print:
|
||||
mov dl, al
|
||||
mov word [fs:0x0000], dx
|
||||
jmp error.stop
|
||||
|
||||
.stop:
|
||||
hlt
|
||||
jmp short error.stop
|
||||
%endif
|
||||
%define __INC_ERROR_CODES
|
||||
@@ -1,4 +1,4 @@
|
||||
; Copyright (c) 2023 Elaina Claus
|
||||
; Copyright (c) 2024 Elaina Claus
|
||||
;
|
||||
; Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
; of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -18,6 +18,7 @@
|
||||
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
; SOFTWARE.
|
||||
|
||||
%ifndef __INC_BPD_OFFSET_BX
|
||||
|
||||
; BPB Information
|
||||
; Off. Hex Off. Size Description
|
||||
@@ -88,4 +89,7 @@
|
||||
%define bsVolumeSerial bx+0x43
|
||||
%define bsVolumeLabel bx+0x47
|
||||
%define bsSystemIdent bx+0x52
|
||||
;-- End EBPB
|
||||
;-- End EBPB
|
||||
|
||||
%endif
|
||||
%define __INC_BPD_OFFSET_BX
|
||||
@@ -18,6 +18,7 @@
|
||||
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
; SOFTWARE.
|
||||
|
||||
%ifndef __INC_FAT32_STRUCT
|
||||
|
||||
; ## FAT32 Info ##
|
||||
; total_sectors = bsSectorsHuge
|
||||
@@ -230,4 +231,5 @@ endstruc
|
||||
; LFN == RO | HIDDEN | SYSTEM | VOLID == 0x0F
|
||||
%define FAT32_ATTR_LFN 0x0F
|
||||
|
||||
|
||||
%endif
|
||||
%define __INC_FAT32_STRUCT
|
||||
312
include/fat32/fat32_sys.inc
Normal file
312
include/fat32/fat32_sys.inc
Normal file
@@ -0,0 +1,312 @@
|
||||
; Copyright (c) 2024 Elaina Claus
|
||||
;
|
||||
; Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
; of this software and associated documentation files (the "Software"), to deal
|
||||
; in the Software without restriction, including without limitation the rights
|
||||
; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
; copies of the Software, and to permit persons to whom the Software is
|
||||
; furnished to do so, subject to the following conditions:
|
||||
;
|
||||
; The above copyright notice and this permission notice shall be included in all
|
||||
; copies or substantial portions of the Software.
|
||||
;
|
||||
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
; SOFTWARE.
|
||||
|
||||
%ifndef __INC_FAT32_SYS
|
||||
|
||||
%include "partition_table.inc"
|
||||
%include "fat32/bpb_offset_bx.inc"
|
||||
%include "fat32/fat32_structures.inc"
|
||||
|
||||
ALIGN 4, db 0x90
|
||||
InitFATDriver:
|
||||
__CDECL16_ENTRY
|
||||
.func:
|
||||
xor eax, eax
|
||||
mov dword [fat32_state + FAT32_State_t.active_cluster_32], eax
|
||||
mov dword [fat32_state + FAT32_State_t.active_FAT_cluster_32], eax
|
||||
mov dword [fat32_state + FAT32_State_t.first_root_dir_sector_32], eax
|
||||
mov dword [fat32_state + FAT32_State_t.active_dir_cluster_32], eax
|
||||
|
||||
.calc_active_part:
|
||||
mov bx, [partition_offset_ptr]
|
||||
mov ax, [bx + 0]
|
||||
|
||||
mov dx, partition_table
|
||||
add dx, ax ; dx points to the partition that was booted from
|
||||
mov bx, dx ; set bx, should point at our partition
|
||||
|
||||
mov eax, dword [bx + PartEntry_t.lba_start]
|
||||
mov dword [fat32_state + FAT32_State_t.active_drive_lba_32], eax
|
||||
|
||||
.calc_first_fat:
|
||||
movzx eax, word [fat32_bpb + FAT32_bpb_t.reserved_sectors_16] ; first fat from start of partition
|
||||
add eax, dword [fat32_state + FAT32_State_t.active_drive_lba_32] ; calculate offset from start of drive
|
||||
|
||||
mov dword [fat32_state + FAT32_State_t.first_fat_sector_32], eax
|
||||
.calc_total_fat:
|
||||
mov ebx, dword [fat32_ebpb + FAT32_ebpb_t.sectors_per_fat_32]
|
||||
movzx eax, byte [fat32_bpb + FAT32_bpb_t.fat_count_8]
|
||||
mul ebx ; result in EDX:EAX, CF set on > 32bit return value
|
||||
jc InitFATDriver.error ; as a catch for unhandled overflow, just error if value is greater than 32bits
|
||||
|
||||
mov dword [fat32_state + FAT32_State_t.fat_size_32], eax
|
||||
.calc_first_data:
|
||||
mov edx, dword [fat32_state + FAT32_State_t.first_fat_sector_32]
|
||||
add eax, edx
|
||||
|
||||
mov dword [fat32_state + FAT32_State_t.first_data_sector_32], eax
|
||||
.get_first_root_dir:
|
||||
; TODO
|
||||
jmp InitFATDriver.endp
|
||||
.error:
|
||||
ERROR STAGE2_FAT32_INIT_ERROR
|
||||
.endp:
|
||||
__CDECL16_EXIT
|
||||
ret
|
||||
|
||||
; this involves using the low memory buffer for the bios call and moving the file sector by sector to high memory
|
||||
;
|
||||
; SFN is a 8.3 file name, all uppercase, and padded with spaces
|
||||
; do not add a null byte to the end of the string
|
||||
; eg. kernel.bin == "KERNEL BIN"
|
||||
;
|
||||
; returns first cluster of file if found
|
||||
; halts/errors if file is not found
|
||||
; uint32_t SearchFATDIR(uint8_t* SFN);
|
||||
ALIGN 4, db 0x90
|
||||
SearchFATDIR:
|
||||
__CDECL16_ENTRY
|
||||
.file_lookup:
|
||||
.load_first_dir:
|
||||
mov eax, [fat32_ebpb + FAT32_ebpb_t.root_dir_cluster_32]
|
||||
mov dword [fat32_state + FAT32_State_t.active_dir_cluster_32], eax
|
||||
|
||||
push dword eax ; cluster
|
||||
lea ax, [dir_buffer]
|
||||
push ax ; offset
|
||||
xor ax, ax
|
||||
push ax ; segment
|
||||
call ReadFATCluster ; uint8_t ReadFATCluster(uint16_t seg, uint16_t offset, uint32_t cluster)
|
||||
add sp, 0x8
|
||||
|
||||
lea si, [dir_buffer]
|
||||
jmp SearchFATDIR.empty_dir_entry
|
||||
|
||||
.load_next_dir:
|
||||
; if eax >= 0x0FFFFFF8 then there are no more clusters (end of chain)
|
||||
; if eax == 0x0FFFFFF7 then this is a cluster that is marked as bad
|
||||
mov eax, dword [fat32_state + FAT32_State_t.active_dir_cluster_32]
|
||||
push dword eax
|
||||
call NextCluster ; uint32_t NextCluster(uint32_t active_cluster);
|
||||
add sp, 0x4
|
||||
|
||||
cmp eax, 0x0fff_fff7
|
||||
jb SearchFATDIR.load_next_dir_next_OK
|
||||
ERROR STAGE2_FAT32_END_OF_CHAIN
|
||||
|
||||
.load_next_dir_next_OK:
|
||||
; load 512 bytes of directory entries from data sector
|
||||
mov eax, [fat32_state + FAT32_State_t.active_dir_cluster_32]
|
||||
|
||||
push dword eax
|
||||
lea ax, [dir_buffer] ; cluster
|
||||
push ax ; offset
|
||||
xor ax, ax
|
||||
push ax ; segment
|
||||
call ReadFATCluster ; uint8_t ReadFATCluster(uint16_t seg, uint16_t offset, uint32_t cluster)
|
||||
sub sp, 0x8
|
||||
|
||||
lea si, [dir_buffer]
|
||||
.empty_dir_entry:
|
||||
; check for 0x0 in first byte, if true then there are no more files
|
||||
; if true we did not find the file, we should error here
|
||||
cmp byte [si], 0
|
||||
jne SearchFATDIR.unused_dir_entry
|
||||
ERROR STAGE2_FAT32_NO_FILE
|
||||
|
||||
.unused_dir_entry:
|
||||
; check for 0xe5 and 0x05 in first byte, if true then this entry is unused, but it is not the last entry.
|
||||
cmp byte [si], 0xe5
|
||||
je SearchFATDIR.next_entry
|
||||
|
||||
cmp byte [si], 0x05
|
||||
je SearchFATDIR.next_entry
|
||||
jmp SearchFATDIR.parse_dir
|
||||
|
||||
.next_entry:
|
||||
; increment offset by 32 bytes to read the next entry in this set of dir entries
|
||||
; if we are at the end of the buffer, then load the next buffer
|
||||
add si, 0x20 ; 32 bytes
|
||||
|
||||
lea ax, [dir_buffer]
|
||||
add ax, 0x1FF ; 512 - 1 bytes
|
||||
cmp si, ax
|
||||
jae SearchFATDIR.load_next_dir
|
||||
jmp SearchFATDIR.empty_dir_entry
|
||||
|
||||
.parse_dir:
|
||||
.lfn_check:
|
||||
; check for ATTR_READ_ONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_VOLUME_ID (0x0F) in offset 11
|
||||
; TODO: going to skip LFN for now, since all valid volumes will have SFN's
|
||||
cmp byte [si+11], 0x0F
|
||||
je SearchFATDIR.next_entry
|
||||
.sfn_file_name_check:
|
||||
push si
|
||||
push di
|
||||
|
||||
mov cx, 0xA ; max of 11 filename length of 11 characters
|
||||
; si points to the start of the current directory entry
|
||||
lea di, [BootTarget_str] ; current memory location (8.3 name is at offset 0)
|
||||
repe cmpsb ; compare the strings
|
||||
|
||||
pop di
|
||||
pop si
|
||||
jne SearchFATDIR.next_entry
|
||||
|
||||
.sfn_entry_found:
|
||||
mov ax, [si + FAT32_SFN_t.cluster_16_high]
|
||||
shl eax, 16
|
||||
mov ax, [si + FAT32_SFN_t.cluster_16_low]
|
||||
; eax == first cluster of file
|
||||
.endp:
|
||||
__CDECL16_EXIT
|
||||
ret
|
||||
|
||||
; uint32_t NextCluster(uint32_t active_cluster);
|
||||
; if eax >= 0x0FFFFFF8 then there are no more clusters (end of chain)
|
||||
; if eax == 0x0FFFFFF7 then this is a cluster that is marked as bad
|
||||
ALIGN 4, db 0x90
|
||||
NextCluster:
|
||||
__CDECL16_ENTRY
|
||||
.func:
|
||||
mov bx, [boot_drive_ptr]
|
||||
mov ax, [bx + 0]
|
||||
mov bx, ax
|
||||
movzx ax, byte [bx + 0] ; 67h override would probably work but this is the 16bit way to do it
|
||||
mov byte [bp - 2], al ; save boot drive as a local for easy access
|
||||
|
||||
mov dword edx, [bp + 4]
|
||||
mov si, fat32_nc_data
|
||||
.calc_offset:
|
||||
; fat_offset = active_cluster * 4
|
||||
mov eax, 4
|
||||
mul edx
|
||||
mov dword [si + FAT32_NextClusterData_t.fat_offset], eax
|
||||
|
||||
.calc_fat_sector:
|
||||
; fat_sector = first_fat_sector + (fat_offset / sector_size)
|
||||
; entry_offset = fat_offset % sector_size
|
||||
mov edx, 0xffff_0000
|
||||
and edx, eax
|
||||
shr edx, 16
|
||||
|
||||
push si
|
||||
mov si, fat32_bpb
|
||||
mov cx, word [si + FAT32_bpb_t.bytes_per_sector_16]
|
||||
pop si
|
||||
|
||||
div cx ; DX:AX / cx = fat_sector - first_fat_sector in AX
|
||||
; DX = remainder (fat_offset mod sector_size)
|
||||
|
||||
mov ecx, 0x0000_ffff
|
||||
and edx, ecx
|
||||
mov dword [si + FAT32_NextClusterData_t.entry_offset], edx
|
||||
|
||||
push si
|
||||
mov si, fat32_state
|
||||
mov ecx, dword [si + FAT32_State_t.first_fat_sector_32]
|
||||
pop si
|
||||
|
||||
mov edx, 0x0000ffff
|
||||
and eax, edx
|
||||
add eax, ecx ; fat_sector + first_fat_sector
|
||||
mov dword [si + FAT32_NextClusterData_t.fat_sector], eax
|
||||
.load_fat_table:
|
||||
movzx ax, [bp - 2]
|
||||
push ax
|
||||
|
||||
mov ax, 0x1
|
||||
push ax
|
||||
|
||||
; load correct fat
|
||||
mov eax, dword [si + FAT32_NextClusterData_t.fat_sector]
|
||||
push dword eax
|
||||
|
||||
mov ax, fat_buffer
|
||||
push ax
|
||||
|
||||
xor ax, ax
|
||||
push ax
|
||||
call read_disk_raw
|
||||
add sp, 0xC
|
||||
; uint8_t read_stage2_raw(uint16_t buf_segment, uint16_t buf_offset,
|
||||
; uint32_t lba,
|
||||
; uint16_t count, uint16_t drive_num)
|
||||
.read_cluster:
|
||||
; next_cluster = fat_buffer[entry_offset]
|
||||
mov ebx, dword [si + FAT32_NextClusterData_t.entry_offset]
|
||||
mov si, fat_buffer
|
||||
mov eax, dword [bx+si+0]
|
||||
.endp:
|
||||
__CDECL16_EXIT
|
||||
ret
|
||||
|
||||
; uint32_t ClusterToLBA(uint32_t cluster)
|
||||
ALIGN 4, db 0x90
|
||||
ClusterToLBA:
|
||||
__CDECL16_ENTRY
|
||||
.func:
|
||||
mov dword eax, [bp + 4]
|
||||
sub eax, 2
|
||||
movzx edx, byte [fat32_bpb + FAT32_bpb_t.sectors_per_cluster_8]
|
||||
mul edx
|
||||
add eax, dword [fat32_state + FAT32_State_t.first_data_sector_32]
|
||||
; eax contains the LBA now
|
||||
.endp:
|
||||
__CDECL16_EXIT
|
||||
ret
|
||||
|
||||
; uint8_t ReadFATCluster(uint16_t seg, uint16_t offset, uint32_t cluster)
|
||||
ALIGN 4, db 0x90
|
||||
ReadFATCluster:
|
||||
__CDECL16_ENTRY
|
||||
.func:
|
||||
mov bx, [boot_drive_ptr]
|
||||
mov ax, [bx + 0]
|
||||
mov byte [bp - 2], al ; save boot drive as a local for easy access
|
||||
|
||||
mov dword eax, [bp + 8]
|
||||
push dword eax
|
||||
call ClusterToLBA ; uint32_t ClusterToLBA(uint32_t cluster)
|
||||
add sp, 0x4 ; eax == LBA
|
||||
mov dword [bp - 6], eax
|
||||
|
||||
movzx ax, [bp - 2]
|
||||
push ax
|
||||
|
||||
mov ax, 0x1
|
||||
push ax
|
||||
|
||||
mov eax, dword [bp + 6]
|
||||
push dword eax
|
||||
|
||||
mov ax, fat_buffer
|
||||
push ax
|
||||
|
||||
xor ax, ax
|
||||
push ax
|
||||
call read_disk_raw
|
||||
add sp, 0xC
|
||||
.endp:
|
||||
__CDECL16_EXIT
|
||||
ret
|
||||
|
||||
%endif
|
||||
%define __INC_FAT32_SYS
|
||||
@@ -17,15 +17,18 @@
|
||||
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
; SOFTWARE.
|
||||
|
||||
%ifndef __INC_KMEM_FUNC
|
||||
%include 'cdecl16.inc'
|
||||
|
||||
; uint8_t* kmemset(void* dest, uint8_t val, uint8_t len);
|
||||
; uint8_t* kmemset_byte(void* dst, uint8_t val, uint16_t len);
|
||||
ALIGN 4, db 0x90
|
||||
kmemset:
|
||||
__CDECL16_ENTRY
|
||||
.func:
|
||||
mov cx, [bp + 8] ; size_t len
|
||||
mov al, [bp + 6] ; uint8_t val
|
||||
mov di, [bp + 4] ; void * ptr
|
||||
mov di, [bp + 4] ; void * dst
|
||||
|
||||
cld
|
||||
rep stosb
|
||||
@@ -36,6 +39,7 @@ kmemset:
|
||||
|
||||
; uint8_t* kmemset(uint8_t* dest, uint8_t* src, uint8_t len);
|
||||
; not overlap safe
|
||||
ALIGN 4, db 0x90
|
||||
kmemcpy:
|
||||
__CDECL16_ENTRY
|
||||
.func:
|
||||
@@ -48,4 +52,7 @@ kmemcpy:
|
||||
mov ax, di ; return pointer to dest
|
||||
.endf:
|
||||
__CDECL16_EXIT
|
||||
ret
|
||||
ret
|
||||
|
||||
%endif
|
||||
%define __INC_KMEM_FUNC
|
||||
116
include/mem.inc
Executable file
116
include/mem.inc
Executable file
@@ -0,0 +1,116 @@
|
||||
; Copyright (c) 2024 Elaina Claus
|
||||
;
|
||||
; Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
; of this software and associated documentation files (the "Software"), to deal
|
||||
; in the Software without restriction, including without limitation the rights
|
||||
; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
; copies of the Software, and to permit persons to whom the Software is
|
||||
; furnished to do so, subject to the following conditions:
|
||||
;
|
||||
; The above copyright notice and this permission notice shall be included in all
|
||||
; copies or substantial portions of the Software.
|
||||
;
|
||||
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
; SOFTWARE.
|
||||
|
||||
%ifndef __INC_MEM
|
||||
|
||||
|
||||
; ## Generic Low mem map (from osdev wiki) ##
|
||||
; start end size type description
|
||||
; Low Memory (the first MiB)
|
||||
; 0x00000000 0x000003FF 1 KiB RAM - partially unusable Real Mode IVT (Interrupt Vector Table)
|
||||
; 0x00000400 0x000004FF 256 bytes RAM - partially unusable BDA (BIOS data area)
|
||||
; 0x00000500 0x00007BFF almost 30 KiB RAM - free for use Conventional memory
|
||||
; 0x00007C00 0x00007DFF 512 bytes RAM - partially unusable OS BootSector
|
||||
; 0x00007E00 0x0007FFFF 480.5 KiB RAM - free for use Conventional memory
|
||||
; 0x00080000 0x0009FFFF 128 KiB RAM - partially unusable EBDA (Extended BIOS Data Area)
|
||||
; 0x000A0000 0x000FFFFF 384 KiB various (unusable) Video memory, ROM Area
|
||||
|
||||
; ## A rough overview of high mem ##
|
||||
; Idealy this needs to be probed with the E820 functions
|
||||
; # Start # End # size # description
|
||||
;
|
||||
; 0x00100000 0x00EFFFFF 0x00E00000 (14 MiB) RAM -- free for use (if it exists) Extended memory
|
||||
; 0x00F00000 0x00FFFFFF 0x00100000 (1 MiB) Possible memory mapped hardware ISA Memory Hole 15-16MB
|
||||
; 0x01000000 ???????? ??? (whatever exists) RAM -- free for use More Extended memory
|
||||
; 0xC0000000 (sometimes) 0xFFFFFFFF 0x40000000 (1 GiB) Memory mapped PCI devices, PnP NVRAM?, IO APIC/s, local APIC/s, BIOS, ...
|
||||
; 0x0000000100000000 ??? ??? (whatever exists) RAM -- free for use (PAE/64bit)/More Extended memory
|
||||
; ???????????????? ??? ??? Potentially usable for memory mapped PCI devices in modern hardware (but typically not, due to backward compatibility)
|
||||
|
||||
; 0x2700 -> 0x28FF
|
||||
%define disk_buffer 0x2700
|
||||
; 0x2900 -> 0x2AFF
|
||||
%define fat_buffer 0x2900
|
||||
; 0x2B00 -> 0x2CFF
|
||||
%define dir_buffer 0x2B00
|
||||
|
||||
; copy of partition table, 72 bytes
|
||||
%define partition_table 0x3000
|
||||
%define partition_table_SIZE 72
|
||||
|
||||
; copy of FAT32 BPB, 33 bytes (+1 to the next value to align to uint16_t)
|
||||
;0x3048
|
||||
%define fat32_bpb 0x304A
|
||||
%define fat32_bpb_SIZE 36
|
||||
|
||||
; copy of FAT32 EBPB, 54 bytes
|
||||
;0x306A
|
||||
%define fat32_ebpb 0x306E
|
||||
%define fat32_ebpb_SIZE 54
|
||||
|
||||
; FAT32 FSInfo, 512 bytes
|
||||
;0x30A2
|
||||
%define fat32_fsinfo 0x30B0
|
||||
%define fat32_fsinfo_SIZE 512
|
||||
|
||||
; some stored state for the fat32 driver
|
||||
;0x32A2
|
||||
%define fat32_state 0x34B0
|
||||
%define fat32_state_SIZE 32
|
||||
|
||||
; next free space is 0x32D0
|
||||
%define fat32_nc_data 0x35D0
|
||||
%define fat32_nc_data_size 16
|
||||
|
||||
; lba_packet for raw_disk_read
|
||||
%define lba_packet 0x4000
|
||||
|
||||
%define BIOSMemoryMap 0x4200
|
||||
%define SteviaInfo 0x5200
|
||||
|
||||
|
||||
; High memory addresses for loading kernel (for use with unreal mode and 32bit override)
|
||||
|
||||
; file load buffer at 16MB
|
||||
%define HMEM_load_buffer 0x1000000
|
||||
|
||||
|
||||
;PhysicalAddress = Segment * 16 + Offset
|
||||
%define SEG_TO_LINEAR(s,o) ((s << 4) + o)
|
||||
|
||||
; Offset = physical / (Segment * 16)
|
||||
%define LINEAR_TO_OFFSET(p,s) ((p / (s << 4)))
|
||||
|
||||
; Seg = (physical - offset) / 16
|
||||
%define LINEAR_TO_SEGMENT(p,o) ((p - o) >> 4)
|
||||
|
||||
; create normalized linear addres from seg:off (16:4)
|
||||
; Segement = linear >> 4 (top 16 bits)
|
||||
; offset = linear & 0x0F (low 4 bits)
|
||||
|
||||
; 20 bytes, passed to loaded kernel
|
||||
struc SteviaInfoStruct_t
|
||||
.MemoryMapPtr resd 1
|
||||
.MemoryMapEntries resd 1
|
||||
.BPBDataPtr resd 1
|
||||
.EBPBDataPtr resd 1
|
||||
endstruc
|
||||
|
||||
%endif
|
||||
%define __INC_MEM
|
||||
@@ -1,4 +1,4 @@
|
||||
; Copyright (c) 2023 Elaina Claus
|
||||
; Copyright (c) 2024 Elaina Claus
|
||||
;
|
||||
; Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
; of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -18,6 +18,8 @@
|
||||
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
; SOFTWARE.
|
||||
|
||||
%ifndef __INC_PART_TABLE
|
||||
|
||||
; Partition table entry format
|
||||
; Off. Size. Description
|
||||
;0x00 1 Drive attributes (bit 7 set = active or bootable)
|
||||
@@ -43,21 +45,5 @@ struc PartTable_t
|
||||
.partition4 resb 16
|
||||
endstruc
|
||||
|
||||
|
||||
;Offset Size Description
|
||||
; 0 1 size of packet (16 bytes)
|
||||
; 1 1 always 0
|
||||
; 2 2 number of sectors to transfer (max 127 on some BIOSes)
|
||||
; 4 4 transfer buffer (0xFFFF:0xFFFF)
|
||||
; 8 4 lower 32-bits of starting 48-bit LBA
|
||||
; 12 4 upper 32-bits of starting 48-bit LBA
|
||||
; needs to be aligned to a uint32_t
|
||||
struc LBAPkt_t
|
||||
.size resb 1
|
||||
.res0 resb 1
|
||||
.xfer_size resw 1
|
||||
.offset resw 1
|
||||
.segment resw 1
|
||||
.lower_lba resd 1
|
||||
.upper_lba resd 1
|
||||
endstruc
|
||||
%endif
|
||||
%define __INC_PART_TABLE
|
||||
63
include/util/error_func.inc
Normal file
63
include/util/error_func.inc
Normal file
@@ -0,0 +1,63 @@
|
||||
; Copyright (c) 2024 Elaina Claus
|
||||
;
|
||||
; Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
; of this software and associated documentation files (the "Software"), to deal
|
||||
; in the Software without restriction, including without limitation the rights
|
||||
; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
; copies of the Software, and to permit persons to whom the Software is
|
||||
; furnished to do so, subject to the following conditions:
|
||||
;
|
||||
; The above copyright notice and this permission notice shall be included in all
|
||||
; copies or substantial portions of the Software.
|
||||
;
|
||||
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
; SOFTWARE.
|
||||
|
||||
%ifndef __INC_ERROR_FUNC
|
||||
|
||||
%macro ERROR 1
|
||||
xor ax, ax
|
||||
mov al, %1
|
||||
jmp error
|
||||
%endmacro
|
||||
|
||||
%macro DEBUG_HCF 0
|
||||
DEBUG_LOOP:
|
||||
cli
|
||||
hlt
|
||||
jmp short DEBUG_LOOP
|
||||
%endmacro
|
||||
|
||||
; pass error as ascii character in al, errors a-zA-Z or 0-9
|
||||
ALIGN 4, db 0x90
|
||||
error:
|
||||
; fs = 0xb800 => fs:0x0000 = 0xb8000
|
||||
mov dx, 0xB800
|
||||
mov fs, dx
|
||||
|
||||
mov dx, STEVIA_DEBUG_OK
|
||||
cmp ax, dx
|
||||
jge error.debug_err
|
||||
mov dh, 0x4F ; color 0x4F is white text/red background
|
||||
jmp error.print
|
||||
.debug_err:
|
||||
mov dh, 0x5F ; debug case is white text/purple background
|
||||
|
||||
; the characters are two bytes in the order of 0xb8000: byte c, byte attribute
|
||||
; since x86 is le, we store the attribute in the MSB of dx
|
||||
.print:
|
||||
mov dl, al
|
||||
mov word [fs:0x0000], dx
|
||||
jmp error.stop
|
||||
|
||||
.stop:
|
||||
hlt
|
||||
jmp short error.stop
|
||||
|
||||
%endif
|
||||
%define __INC_ERROR_FUNC
|
||||
181
src/mbr/mbr.nasm
181
src/mbr/mbr.nasm
@@ -23,17 +23,37 @@
|
||||
[CPU KATMAI]
|
||||
jmp short init
|
||||
nop
|
||||
%include "cdecl16.inc" ; include calling convention macros for cdecl16
|
||||
%include "entry.inc" ; defines with entry points for various stages & stack
|
||||
init:
|
||||
cli ; We do not want to be interrupted
|
||||
|
||||
xor ax, ax ; 0 AX
|
||||
mov ds, ax ; Set segment registers to 0
|
||||
mov es, ax ; *
|
||||
|
||||
mov ss, ax ; Set Stack Segment to 0
|
||||
mov sp, STACK_START
|
||||
; ###############
|
||||
;
|
||||
; Headers/Includes/Definitions
|
||||
;
|
||||
; ###############
|
||||
|
||||
%define __STEVIA_MBR
|
||||
|
||||
%include "cdecl16.inc"
|
||||
%include "entry.inc"
|
||||
%include "config.inc"
|
||||
%include "mem.inc"
|
||||
%include "error_codes.inc"
|
||||
%include "partition_table.inc"
|
||||
|
||||
; ###############
|
||||
; End Section
|
||||
; ###############
|
||||
|
||||
ALIGN 4, db 0x90
|
||||
init:
|
||||
cli ; We do not want to be interrupted
|
||||
|
||||
xor ax, ax ; 0 AX
|
||||
mov ds, ax ; Set segment registers to 0
|
||||
|
||||
mov ss, ax ; Set Stack Segment to 0
|
||||
mov sp, EARLY_STACK_START ; Setup stack
|
||||
mov bp, sp ; base ptr = stack ptr
|
||||
sub sp, 0x20 ; local varible space
|
||||
|
||||
mov ch, 0x01 ; 256 WORDs in MBR (512 bytes), 0x0100 in cx
|
||||
mov si, 0x7C00 ; Current MBR Address (loaded here by BIOS)
|
||||
@@ -43,16 +63,28 @@ init:
|
||||
sti
|
||||
|
||||
jmp 0:main
|
||||
nop
|
||||
|
||||
%include "config.inc"
|
||||
%include "memory.inc"
|
||||
; ###############
|
||||
;
|
||||
; Extra/Shared Functions
|
||||
;
|
||||
; ###############
|
||||
|
||||
%include "kmem_func.inc"
|
||||
%include "partition_table.inc"
|
||||
%include "errors.inc"
|
||||
%include "util/error_func.inc"
|
||||
|
||||
; ###############
|
||||
; End Section
|
||||
; ###############
|
||||
|
||||
;
|
||||
; bp - 2 : uint8_t boot_drive
|
||||
; bp - 4 : uint16_t part_offset
|
||||
;
|
||||
|
||||
ALIGN 4, db 0x90
|
||||
main:
|
||||
mov [boot_drive], dl ; BIOS passes drive number in DL
|
||||
mov byte [bp - 2], dl ; BIOS passes drive number in DL
|
||||
|
||||
.check_disk:
|
||||
cmp dl, 0x80
|
||||
@@ -62,7 +94,7 @@ main:
|
||||
.check_extentions:
|
||||
xor ax, ax
|
||||
mov bx, 0x55AA
|
||||
mov dl, byte [boot_drive]
|
||||
mov dl, byte [bp - 2]
|
||||
int 0x13
|
||||
jnc main.find_active
|
||||
ERROR MBR_ERROR_NO_INT32E ; no extended function support
|
||||
@@ -83,33 +115,33 @@ main:
|
||||
mov ax, bx
|
||||
sub ax, DiskSig ; leaves us with the offset relative from start of table
|
||||
; this gives us an offset from the begining of the partition table
|
||||
mov word [part_offset], ax ; update part_offset
|
||||
mov word [bp - 4], ax ; update part_offset
|
||||
.read_data:
|
||||
;uint8_t read_disk_raw(size_t count, uint16_t buf_segment, uint16_t buf_offset,
|
||||
; uint16_t lower_lower_lba, uint16_t upper_lower_lba)
|
||||
mov eax, dword [bx + PartEntry_t.lba_start]
|
||||
ror eax, 16
|
||||
push ax
|
||||
movzx ax, byte [bp - 2]
|
||||
push ax ; drive_num
|
||||
|
||||
ror eax, 16
|
||||
push ax
|
||||
mov ax, 0x1
|
||||
push ax ; count
|
||||
|
||||
mov ax, VBR_ENTRY
|
||||
push ax
|
||||
mov dword eax, dword [bx + PartEntry_t.lba_start]
|
||||
push dword eax ; lba
|
||||
|
||||
xor ax, ax
|
||||
push ax ; segment = 0
|
||||
push ax ; offset = 0
|
||||
|
||||
call read_vbr_raw
|
||||
add sp, 0x8
|
||||
mov ax, VBR_ENTRY
|
||||
shr ax, 4
|
||||
push ax ; segment = 7C0
|
||||
|
||||
jnc main.goto_vbr
|
||||
ERROR MBR_ERROR_DISK_READ_ERR ; error in LBA read
|
||||
; uint8_t read_stage2_raw(uint16_t buf_segment, uint16_t buf_offset,
|
||||
; uint32_t lba,
|
||||
; uint16_t count, uint16_t drive_num)
|
||||
call read_disk_raw
|
||||
add sp, 0xC
|
||||
.goto_vbr:
|
||||
cmp word [VBR_ENTRY + 0x1FE], 0xAA55
|
||||
je main.sig_ok
|
||||
ERROR MBR_ERROR_NO_VBR_SIG ; no signature present
|
||||
|
||||
.sig_ok:
|
||||
mov ax, partition_table_SIZE ; 72 bytes of data
|
||||
push ax
|
||||
@@ -120,86 +152,21 @@ main:
|
||||
call kmemcpy ; copy partition table to memory
|
||||
add sp, 0x6
|
||||
|
||||
xor ah, ah ; Set Video mode BIOS function
|
||||
mov al, 0x02 ; 16 color 80x25 Text mode
|
||||
int 0x10 ; Call video interrupt
|
||||
|
||||
mov ah, 0x05 ; Select active display page BIOS function
|
||||
xor al, al ; page 0
|
||||
int 0x10 ; call video interrupt
|
||||
|
||||
mov si, word [part_offset]
|
||||
mov dl, byte [boot_drive]
|
||||
mov si, word [bp - 4]
|
||||
mov dl, byte [bp - 2]
|
||||
jmp 0:0x7C00
|
||||
|
||||
; Wrapper for AH=0x42 INT13h (Extended Read)
|
||||
; ###############
|
||||
;
|
||||
; BIOS call details
|
||||
; AH = 42h
|
||||
; DL = drive number
|
||||
; DS:SI -> disk address packet
|
||||
; BIOS Functions
|
||||
;
|
||||
; Return:
|
||||
; CF clear if successful
|
||||
; AH = 00h
|
||||
; CF set on error
|
||||
; AH = error code
|
||||
; disk address packet's block count field set to number of blocks
|
||||
; successfully transferred
|
||||
;
|
||||
;
|
||||
; uint8_t read_disk_raw(uint16_t buf_segment, uint16_t buf_offset, uint16_t lower_lower_lba, uint16_t upper_lower_lba)
|
||||
read_vbr_raw:
|
||||
__CDECL16_ENTRY
|
||||
.func:
|
||||
mov ax, 0x10
|
||||
push ax ; len = 16 bytes
|
||||
xor ax, ax
|
||||
push ax ; val = 0
|
||||
mov ax, lba_packet
|
||||
push ax ; dest = lba_packet address
|
||||
call kmemset
|
||||
add sp, 0x06
|
||||
; ###############
|
||||
|
||||
mov byte [lba_packet + LBAPkt_t.size], 0x10
|
||||
mov word [lba_packet + LBAPkt_t.xfer_size], 0x0001
|
||||
%include 'BIOS/func/ext_read.inc'
|
||||
|
||||
mov ax, [bp + 10]
|
||||
shl eax, 16
|
||||
mov ax, [bp + 8]
|
||||
mov dword [lba_packet + LBAPkt_t.lower_lba], eax
|
||||
|
||||
mov ax, [bp + 6]
|
||||
mov word [lba_packet + LBAPkt_t.offset], ax
|
||||
|
||||
mov ax, [bp + 4]
|
||||
mov word [lba_packet + LBAPkt_t.segment], ax
|
||||
|
||||
mov si, lba_packet
|
||||
mov ah, 0x42
|
||||
mov dl, byte [boot_drive]
|
||||
int 0x13
|
||||
jnc .endf
|
||||
|
||||
ERROR MBR_ERROR_INT13h_EREAD_ERR
|
||||
.endf:
|
||||
__CDECL16_EXIT
|
||||
ret
|
||||
|
||||
; #############
|
||||
;
|
||||
; Locals
|
||||
;
|
||||
; #############
|
||||
|
||||
boot_drive:
|
||||
db 0x00
|
||||
mbr_reserved1:
|
||||
db 0x00
|
||||
|
||||
; OFFSET from BEGINING of partition table, ie. DiskSig (-6 from PartEntry1)
|
||||
part_offset:
|
||||
dw 0x0000
|
||||
; ###############
|
||||
; End Section
|
||||
; ###############
|
||||
|
||||
%assign bytes_remaining (440 - ($ - $$))
|
||||
%warning MBR has bytes_remaining bytes remaining for code (MAX: 440 bytes)
|
||||
|
||||
@@ -24,10 +24,25 @@
|
||||
jmp short init
|
||||
nop
|
||||
|
||||
; boot drive in dl
|
||||
; active partition offset in si
|
||||
; ###############
|
||||
;
|
||||
; Headers/Includes/Definitions
|
||||
;
|
||||
; ###############
|
||||
|
||||
%define __STEVIA_STAGE2
|
||||
|
||||
%include "cdecl16.inc"
|
||||
%include "entry.inc"
|
||||
%include "config.inc"
|
||||
%include "mem.inc"
|
||||
%include "error_codes.inc"
|
||||
|
||||
; ###############
|
||||
; End Section
|
||||
; ###############
|
||||
|
||||
ALIGN 4, db 0x90
|
||||
init:
|
||||
cli ; We do not want to be interrupted
|
||||
|
||||
@@ -37,32 +52,39 @@ init:
|
||||
mov fs, ax ; *
|
||||
mov gs, ax ; *
|
||||
|
||||
mov ss, ax ; Set Stack Segment to 0
|
||||
mov sp, STACK_START ; Set Stack Pointer
|
||||
|
||||
add sp, 0x4
|
||||
mov ax, 0xDEAD
|
||||
push word ax
|
||||
mov ax, 0xBEEF
|
||||
push word ax ; mark top of stack for debuging
|
||||
|
||||
mov ss, ax ; Set Stack Segment to 0
|
||||
mov sp, EARLY_STACK_START ; Set Stack Pointer
|
||||
mov bp, sp
|
||||
sub sp, 0x20 ; 32 bytes for local varibles
|
||||
|
||||
sti
|
||||
|
||||
jmp 0:main
|
||||
|
||||
%include "config.inc"
|
||||
%include "errors.inc"
|
||||
%include "memory.inc"
|
||||
; ###############
|
||||
;
|
||||
; Extra/Shared Functions
|
||||
;
|
||||
; ###############
|
||||
|
||||
%include "kmem_func.inc"
|
||||
%include "partition_table.inc"
|
||||
%include "util/error_func.inc"
|
||||
|
||||
%include "fat32/bpb.inc"
|
||||
%include "fat32/fat32_structures.inc"
|
||||
; ###############
|
||||
; End Section
|
||||
; ###############
|
||||
|
||||
;
|
||||
; bp - 2 : uint8_t boot_drive
|
||||
; bp - 4 : uint16_t part_offset
|
||||
;
|
||||
main:
|
||||
mov byte [fat32_ebpb + FAT32_ebpb_t.drive_number_8], dl
|
||||
mov word [partition_offset], si
|
||||
lea ax, [bp - 2]
|
||||
mov [boot_drive_ptr], ax
|
||||
lea ax, [bp - 4]
|
||||
mov [partition_offset_ptr], ax
|
||||
mov byte [bp - 2], dl ; boot_drive (probably 0x80)
|
||||
mov word [bp - 4], si ; partition_offset
|
||||
|
||||
mov eax, dword [STAGE2_SIG]
|
||||
cmp eax, 0xDEADBEEF
|
||||
@@ -127,7 +149,6 @@ main:
|
||||
add sp, 0x2
|
||||
|
||||
ERROR STEVIA_DEBUG_HALT
|
||||
|
||||
hcf:
|
||||
hlt
|
||||
jmp short hcf
|
||||
@@ -138,260 +159,7 @@ hcf:
|
||||
;
|
||||
; ###############
|
||||
|
||||
InitFATDriver:
|
||||
__CDECL16_ENTRY
|
||||
.func:
|
||||
xor eax, eax
|
||||
mov dword [fat32_state + FAT32_State_t.active_cluster_32], eax
|
||||
mov dword [fat32_state + FAT32_State_t.active_FAT_cluster_32], eax
|
||||
mov dword [fat32_state + FAT32_State_t.first_root_dir_sector_32], eax
|
||||
mov dword [fat32_state + FAT32_State_t.active_dir_cluster_32], eax
|
||||
|
||||
.calc_active_part:
|
||||
mov ax, word [partition_offset]
|
||||
mov bx, partition_table
|
||||
add bx, ax ; bx points to the partition that was booted from
|
||||
|
||||
mov eax, dword [bx + PartEntry_t.lba_start]
|
||||
mov dword [fat32_state + FAT32_State_t.active_drive_lba_32], eax
|
||||
|
||||
.calc_first_fat:
|
||||
movzx eax, word [fat32_bpb + FAT32_bpb_t.reserved_sectors_16] ; first fat from start of partition
|
||||
add eax, dword [fat32_state + FAT32_State_t.active_drive_lba_32] ; calculate offset from start of drive
|
||||
|
||||
mov dword [fat32_state + FAT32_State_t.first_fat_sector_32], eax
|
||||
.calc_total_fat:
|
||||
mov ebx, dword [fat32_ebpb + FAT32_ebpb_t.sectors_per_fat_32]
|
||||
movzx eax, byte [fat32_bpb + FAT32_bpb_t.fat_count_8]
|
||||
mul ebx ; result in EDX:EAX, CF set on > 32bit return value
|
||||
jc InitFATDriver.error ; as a catch for unhandled overflow, just error if value is greater than 32bits
|
||||
|
||||
mov dword [fat32_state + FAT32_State_t.fat_size_32], eax
|
||||
.calc_first_data:
|
||||
mov edx, dword [fat32_state + FAT32_State_t.first_fat_sector_32]
|
||||
add eax, edx
|
||||
|
||||
mov dword [fat32_state + FAT32_State_t.first_data_sector_32], eax
|
||||
.get_first_root_dir:
|
||||
; TODO
|
||||
|
||||
jmp InitFATDriver.endp
|
||||
.error:
|
||||
ERROR STAGE2_FAT32_INIT_ERROR
|
||||
.endp:
|
||||
__CDECL16_EXIT
|
||||
ret
|
||||
|
||||
; TODO: needs validation
|
||||
; load a file to the high memory buffer for the elf parser
|
||||
; this involves using the low memory buffer for the bios call and moving the file sector by sector to high memory
|
||||
;
|
||||
; SFN is a 8.3 file name, all uppercase, and padded with spaces
|
||||
; do not add a null byte to the end of the string
|
||||
; eg. kernel.bin == "KERNEL BIN"
|
||||
;
|
||||
; returns first cluster of file if found
|
||||
; halts/errors if file is not found
|
||||
; uint32_t SearchFATDIR(uint8_t* SFN);
|
||||
SearchFATDIR:
|
||||
__CDECL16_ENTRY
|
||||
.file_lookup:
|
||||
.load_first_dir:
|
||||
mov eax, [fat32_ebpb + FAT32_ebpb_t.root_dir_cluster_32]
|
||||
mov dword [fat32_state + FAT32_State_t.active_dir_cluster_32], eax
|
||||
|
||||
push dword eax ; cluster
|
||||
lea ax, [dir_buffer]
|
||||
push ax ; offset
|
||||
xor ax, ax
|
||||
push ax ; segment
|
||||
call ReadFATCluster ; uint8_t ReadFATCluster(uint16_t seg, uint16_t offset, uint32_t cluster)
|
||||
add sp, 0x8
|
||||
|
||||
lea si, [dir_buffer]
|
||||
jmp SearchFATDIR.empty_dir_entry
|
||||
|
||||
.load_next_dir:
|
||||
; if eax >= 0x0FFFFFF8 then there are no more clusters (end of chain)
|
||||
; if eax == 0x0FFFFFF7 then this is a cluster that is marked as bad
|
||||
mov eax, dword [fat32_state + FAT32_State_t.active_dir_cluster_32]
|
||||
push dword eax
|
||||
call NextCluster ; uint32_t NextCluster(uint32_t active_cluster);
|
||||
add sp, 0x4
|
||||
|
||||
cmp eax, 0x0fff_fff7
|
||||
jb SearchFATDIR.load_next_dir_next_OK
|
||||
ERROR STAGE2_FAT32_END_OF_CHAIN
|
||||
|
||||
.load_next_dir_next_OK:
|
||||
; load 512 bytes of directory entries from data sector
|
||||
mov eax, [fat32_state + FAT32_State_t.active_dir_cluster_32]
|
||||
|
||||
push dword eax
|
||||
lea ax, [dir_buffer] ; cluster
|
||||
push ax ; offset
|
||||
xor ax, ax
|
||||
push ax ; segment
|
||||
call ReadFATCluster ; uint8_t ReadFATCluster(uint16_t seg, uint16_t offset, uint32_t cluster)
|
||||
sub sp, 0x8
|
||||
|
||||
lea si, [dir_buffer]
|
||||
.empty_dir_entry:
|
||||
; check for 0x0 in first byte, if true then there are no more files
|
||||
; if true we did not find the file, we should error here
|
||||
cmp byte [si], 0
|
||||
jne SearchFATDIR.unused_dir_entry
|
||||
ERROR STAGE2_FAT32_NO_FILE
|
||||
|
||||
.unused_dir_entry:
|
||||
; check for 0xe5 and 0x05 in first byte, if true then this entry is unused, but it is not the last entry.
|
||||
cmp byte [si], 0xe5
|
||||
je SearchFATDIR.next_entry
|
||||
|
||||
cmp byte [si], 0x05
|
||||
je SearchFATDIR.next_entry
|
||||
jmp SearchFATDIR.parse_dir
|
||||
|
||||
.next_entry:
|
||||
; increment offset by 32 bytes to read the next entry in this set of dir entries
|
||||
; if we are at the end of the buffer, then load the next buffer
|
||||
add si, 0x20 ; 32 bytes
|
||||
|
||||
lea ax, [dir_buffer]
|
||||
add ax, 0x1FF ; 512 - 1 bytes
|
||||
cmp si, ax
|
||||
jae SearchFATDIR.load_next_dir
|
||||
jmp SearchFATDIR.empty_dir_entry
|
||||
|
||||
.parse_dir:
|
||||
.lfn_check:
|
||||
; check for ATTR_READ_ONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_VOLUME_ID (0x0F) in offset 11
|
||||
; TODO: going to skip LFN for now, since all valid volumes will have SFN's
|
||||
cmp byte [si+11], 0x0F
|
||||
je SearchFATDIR.next_entry
|
||||
.sfn_file_name_check:
|
||||
push si
|
||||
push di
|
||||
|
||||
mov cx, 0xA ; max of 11 filename length of 11 characters
|
||||
; si points to the start of the current directory entry
|
||||
lea di, [BootTarget_str] ; current memory location (8.3 name is at offset 0)
|
||||
repe cmpsb ; compare the strings
|
||||
|
||||
pop di
|
||||
pop si
|
||||
jne SearchFATDIR.next_entry
|
||||
|
||||
.sfn_entry_found:
|
||||
mov ax, [si + FAT32_SFN_t.cluster_16_high]
|
||||
shl eax, 16
|
||||
mov ax, [si + FAT32_SFN_t.cluster_16_low]
|
||||
; eax == first cluster of file
|
||||
.endp:
|
||||
__CDECL16_EXIT
|
||||
ret
|
||||
|
||||
; uint32_t NextCluster(uint32_t active_cluster);
|
||||
; if eax >= 0x0FFFFFF8 then there are no more clusters (end of chain)
|
||||
; if eax == 0x0FFFFFF7 then this is a cluster that is marked as bad
|
||||
NextCluster:
|
||||
__CDECL16_ENTRY
|
||||
.func:
|
||||
mov dword edx, [bp + 4]
|
||||
mov si, fat32_nc_data
|
||||
.calc_offset:
|
||||
; fat_offset = active_cluster * 4
|
||||
mov eax, 4
|
||||
mul edx
|
||||
mov dword [si + FAT32_NextClusterData_t.fat_offset], eax
|
||||
|
||||
.calc_fat_sector:
|
||||
; fat_sector = first_fat_sector + (fat_offset / sector_size)
|
||||
; entry_offset = fat_offset % sector_size
|
||||
mov edx, 0xffff_0000
|
||||
and edx, eax
|
||||
shr edx, 16
|
||||
|
||||
push si
|
||||
mov si, fat32_bpb
|
||||
mov cx, word [si + FAT32_bpb_t.bytes_per_sector_16]
|
||||
pop si
|
||||
|
||||
div cx ; DX:AX / cx = fat_sector - first_fat_sector in AX
|
||||
; DX = remainder (fat_offset mod sector_size)
|
||||
|
||||
mov ecx, 0x0000_ffff
|
||||
and edx, ecx
|
||||
mov dword [si + FAT32_NextClusterData_t.entry_offset], edx
|
||||
|
||||
push si
|
||||
mov si, fat32_state
|
||||
mov ecx, dword [si + FAT32_State_t.first_fat_sector_32]
|
||||
pop si
|
||||
|
||||
mov edx, 0x0000ffff
|
||||
and eax, edx
|
||||
add eax, ecx ; fat_sector + first_fat_sector
|
||||
mov dword [si + FAT32_NextClusterData_t.fat_sector], eax
|
||||
.load_fat_table:
|
||||
; load correct fat
|
||||
push dword eax
|
||||
|
||||
mov ax, fat_buffer
|
||||
push ax
|
||||
|
||||
xor ax, ax
|
||||
push ax
|
||||
; uint8_t read_disk_raw(uint16_t buf_segment, uint16_t buf_offset, uint16_t lower_lower_lba, uint16_t upper_lower_lba)
|
||||
call read_disk_raw ; read_disk_raw(0, fat_buffer, fat_sector)
|
||||
add sp, 0x8
|
||||
|
||||
.read_cluster:
|
||||
; next_cluster = fat_buffer[entry_offset]
|
||||
mov ebx, dword [si + FAT32_NextClusterData_t.entry_offset]
|
||||
mov si, fat_buffer
|
||||
mov eax, dword [bx+si+0]
|
||||
.endp:
|
||||
__CDECL16_EXIT
|
||||
ret
|
||||
|
||||
; uint32_t ClusterToLBA(uint32_t cluster)
|
||||
ClusterToLBA:
|
||||
__CDECL16_ENTRY
|
||||
.func:
|
||||
mov dword eax, [bp + 4]
|
||||
sub eax, 2
|
||||
movzx edx, byte [fat32_bpb + FAT32_bpb_t.sectors_per_cluster_8]
|
||||
mul edx
|
||||
add eax, dword [fat32_state + FAT32_State_t.first_data_sector_32]
|
||||
; eax contains the LBA now
|
||||
.endp:
|
||||
__CDECL16_EXIT
|
||||
ret
|
||||
|
||||
; uint8_t ReadFATCluster(uint16_t seg, uint16_t offset, uint32_t cluster)
|
||||
ReadFATCluster:
|
||||
__CDECL16_ENTRY
|
||||
.func:
|
||||
mov dword eax, [bp + 8]
|
||||
push dword eax
|
||||
call ClusterToLBA ; uint32_t ClusterToLBA(uint32_t cluster)
|
||||
add sp, 0x4 ; eax == LBA
|
||||
|
||||
|
||||
push dword eax ;uint32_t lba
|
||||
|
||||
mov dx, [bp + 4] ; seg
|
||||
push dx ; uint16_t buf_offset
|
||||
|
||||
mov dx, [bp + 6] ; offset
|
||||
push dx ; unit16_t segment
|
||||
|
||||
call read_disk_raw ; uint8_t read_disk_raw(uint16_t buf_segment, uint16_t buf_offset, uint32_t lba)
|
||||
add sp, 0x8
|
||||
.endp:
|
||||
__CDECL16_EXIT
|
||||
ret
|
||||
%include 'fat32/fat32_sys.inc'
|
||||
|
||||
; ###############
|
||||
;
|
||||
@@ -399,59 +167,13 @@ ReadFATCluster:
|
||||
;
|
||||
; ###############
|
||||
|
||||
%include 'BIOS/BIOS_sys.inc'
|
||||
|
||||
; Wrapper for AH=0x42 INT13h (Extended Read)
|
||||
; ##############################
|
||||
;
|
||||
; BIOS call details
|
||||
; AH = 42h
|
||||
; DL = drive number
|
||||
; DS:SI -> disk address packet
|
||||
; SYSTEM CONFIGURATION FUNCTIONS
|
||||
;
|
||||
; Return:
|
||||
; CF clear if successful
|
||||
; AH = 00h
|
||||
; CF set on error
|
||||
; AH = error code
|
||||
; disk address packet's block count field set to number of blocks
|
||||
; successfully transferred
|
||||
;
|
||||
;
|
||||
; uint8_t read_disk_raw(uint16_t buf_segment, uint16_t buf_offset, uint32_t lba)
|
||||
; TODO: this needs validation
|
||||
read_disk_raw:
|
||||
__CDECL16_ENTRY
|
||||
.func:
|
||||
mov ax, 0x10
|
||||
push ax ; len = 16 bytes
|
||||
xor ax, ax
|
||||
push ax ; val = 0
|
||||
mov ax, lba_packet
|
||||
push ax ; dest = lba_packet address
|
||||
|
||||
call kmemset ; uint8_t* kmemset(void* dest, uint8_t val, size_t len);
|
||||
add sp, 0x6
|
||||
|
||||
mov byte [lba_packet + LBAPkt_t.size], 0x10
|
||||
mov word [lba_packet + LBAPkt_t.xfer_size], 0x0001
|
||||
|
||||
mov dword eax, [bp + 8]
|
||||
mov dword [lba_packet + LBAPkt_t.lower_lba], eax
|
||||
|
||||
mov ax, [bp + 6]
|
||||
mov word [lba_packet + LBAPkt_t.offset], ax
|
||||
|
||||
mov ax, [bp + 4]
|
||||
mov word [lba_packet + LBAPkt_t.segment], ax
|
||||
|
||||
mov si, lba_packet
|
||||
mov ah, 0x42
|
||||
mov dl, byte [fat32_ebpb + FAT32_ebpb_t.drive_number_8]
|
||||
int 0x13
|
||||
jnc read_disk_raw.endp
|
||||
ERROR STAGE2_MBR_DISK_READ_ERROR
|
||||
.endp:
|
||||
__CDECL16_EXIT
|
||||
ret
|
||||
; ##############################
|
||||
|
||||
; Prints a C-Style string (null terminated) using BIOS vga teletype call
|
||||
; void PrintString(char* buf)
|
||||
@@ -550,217 +272,12 @@ PrintDWORD:
|
||||
__CDECL16_EXIT
|
||||
ret
|
||||
|
||||
; Sets output to 80x25 16 color text mode via BIOS call
|
||||
; also clears screen
|
||||
; void SetTextMode(void)
|
||||
SetTextMode:
|
||||
.prolog:
|
||||
__CDECL16_ENTRY
|
||||
pushf
|
||||
.func:
|
||||
xor ah, ah ; Set Video mode BIOS function
|
||||
mov al, 0x02 ; 16 color 80x25 Text mode
|
||||
int 0x10 ; Call video interrupt
|
||||
|
||||
mov ah, 0x05 ; Select active display page BIOS function
|
||||
xor al, al ; page 0
|
||||
int 0x10 ; call video interrupt
|
||||
.endp:
|
||||
popf
|
||||
__CDECL16_EXIT
|
||||
ret
|
||||
|
||||
; See memory.inc for a brief description of E820 mmap function
|
||||
GetMemoryMap:
|
||||
__CDECL16_ENTRY
|
||||
push es ; save segment register
|
||||
.func:
|
||||
mov dword [SteviaInfo + SteviaInfoStruct_t.MemoryMapEntries], 0
|
||||
|
||||
mov eax, 0xE820 ; select 0xE820 function
|
||||
xor ebx, ebx ; Continuation value, 0 for the first call
|
||||
|
||||
mov dx, (BIOSMemoryMap >> 4)
|
||||
mov es, dx
|
||||
xor di, di ; (BIOSMemoryMap >> 4):0 makes di an index into BIOSMemoryMap
|
||||
|
||||
mov ecx, AddressRangeDescStruct_t_size
|
||||
mov edx, 0x534D4150 ; 'SMAP' magic
|
||||
.loop_L1:
|
||||
int 0x15
|
||||
jc GetMemoryMap.error
|
||||
cmp eax, 0x534D4150
|
||||
jne GetMemoryMap.no_smap_returned
|
||||
.no_error:
|
||||
inc dword [SteviaInfo + SteviaInfoStruct_t.MemoryMapEntries]
|
||||
|
||||
cmp ecx, 20 ; TODO: maybe this could be handled better than just panicing
|
||||
jb GetMemoryMap.nonstandard_e820 ; non-standard entry found
|
||||
|
||||
cmp ebx, 0
|
||||
je GetMemoryMap.endp ; 0 in ebx means we have reached the end of memory ranges
|
||||
|
||||
add di, AddressRangeDescStruct_t_size ; increment di to next descriptor
|
||||
mov edx, eax ; 'SMAP' to edx
|
||||
mov eax, 0xE820 ; select E820 function
|
||||
jmp GetMemoryMap.loop_L1
|
||||
.error:
|
||||
ERROR STAGE2_MM_E820_MISC_ERR
|
||||
.nonstandard_e820:
|
||||
ERROR STAGE2_MM_E820_NONSTANDARD
|
||||
.no_smap_returned:
|
||||
ERROR STAGE2_MM_E820_NO_SMAP
|
||||
.endp:
|
||||
pop es
|
||||
__CDECL16_EXIT
|
||||
ret
|
||||
|
||||
; ##############################
|
||||
;
|
||||
; SYSTEM CONFIGURATION FUNCTIONS
|
||||
;
|
||||
; ##############################
|
||||
|
||||
; disables blinking text mode cursor
|
||||
disable_cursor:
|
||||
.prolog:
|
||||
__CDECL16_ENTRY
|
||||
pushf
|
||||
.func:
|
||||
mov dx, 0x3D4
|
||||
mov al, 0xA ; low cursor shape register
|
||||
out dx, al
|
||||
|
||||
inc dx
|
||||
mov al, 0x20 ; bits 6-7 unused, bit 5 disables the cursor, bits 0-4 control the cursor shape
|
||||
out dx, al
|
||||
.endp:
|
||||
popf
|
||||
__CDECL16_EXIT
|
||||
ret
|
||||
|
||||
;
|
||||
;NT 0x15 Function 2400 - Disable A20
|
||||
;Returns:
|
||||
;
|
||||
; CF = clear if success
|
||||
; AH = 0
|
||||
; CF = set on error
|
||||
; AH = status (01=keyboard controller is in secure mode, 0x86=function not supported)
|
||||
;
|
||||
;INT 0x15 Function 2401 - Enable A20
|
||||
;Returns:
|
||||
;
|
||||
; CF = clear if success
|
||||
; AH = 0
|
||||
; CF = set on error
|
||||
; AH = status (01=keyboard controller is in secure mode, 0x86=function not supported)
|
||||
;
|
||||
;INT 0x15 Function 2402 - A20 Status
|
||||
; Returns:
|
||||
;
|
||||
; CF = clear if success
|
||||
; AH = status (01: keyboard controller is in secure mode; 0x86: function not supported)
|
||||
; AL = current state (00: disabled, 01: enabled)
|
||||
; CX = set to 0xffff is keyboard controller is no ready in 0xc000 read attempts
|
||||
; CF = set on error
|
||||
;
|
||||
;INT 0x15 Function 2403 - Query A20 support
|
||||
;Returns:
|
||||
;
|
||||
;CF = clear if success
|
||||
;AH = status (01: keyboard controller is in secure mode; 0x86: function not supported)
|
||||
;BX = status.
|
||||
;
|
||||
;BX contains a bit pattern:
|
||||
;
|
||||
; Bit 0 - supported on keyboard controller
|
||||
; Bit 1 - if supported on bit 1 of I/O port 0x92
|
||||
; Bits 2:14 - Reserved
|
||||
; Bit 15 - 1 if additional data is available.
|
||||
;
|
||||
; I/O Port 0x92 infomation:
|
||||
;
|
||||
; Bit 0 - Setting to 1 causes a fast reset
|
||||
; Bit 1 - 0: disable A20; 1: enable A20
|
||||
; Bit 2 - Manufacturer defined
|
||||
; Bit 3 - power on password bytes (CMOS bytes 0x38-0x3f or 0x36-0x3f). 0: accessible, 1: inaccessible
|
||||
; Bits 4-5 - Manufacturer defined
|
||||
; Bits 6-7 - 00: HDD activity LED off; any other value is "on"
|
||||
EnableA20:
|
||||
__CDECL16_ENTRY
|
||||
push ds
|
||||
push es
|
||||
pushf ; save data and extra segment since we touch them and save flags
|
||||
.a20_check:
|
||||
cli
|
||||
|
||||
xor ax, ax
|
||||
mov es, ax
|
||||
|
||||
not ax ; ax = 0xFFFF
|
||||
mov ds, ax
|
||||
|
||||
mov di, 0x0500 ; scratch location 1
|
||||
mov si, 0x0510 ; scratch location 2
|
||||
|
||||
mov al, byte [es:di]
|
||||
push ax ; save whatever is at 0x0000:0500, physical location 0x0500
|
||||
|
||||
mov al, byte [ds:si]
|
||||
push ax ; save whatever is at 0xFFFF:0510 [clarification: 0x100500 physical location (0x100500 - 1MB = 0x0500)]
|
||||
|
||||
mov byte [es:di], 0x00 ; zero non-wraped location and write 0xFF to it after (ab)using wrapping
|
||||
mov byte [ds:si], 0xFF ; if the non-wrapped location is 0xFF, then we wraped and A20 is disabled
|
||||
|
||||
cmp byte [es:di], 0xFF
|
||||
|
||||
pop ax
|
||||
mov byte [ds:si], al ; restore original contents of scratch location 2
|
||||
|
||||
pop ax
|
||||
mov byte [es:di], al ; restore original contents of scratch location 1
|
||||
|
||||
mov ax, 0 ; return 0 if es:di == ds:si (memory wraps)
|
||||
je EnableA20.end_check
|
||||
mov ax, 1 ; return 1 if es:di != ds:si (A20 is enabled)
|
||||
.end_check:
|
||||
sti
|
||||
cmp ax, 1
|
||||
je EnableA20.endp ; A20 is already enabled
|
||||
|
||||
mov ax, 0x2403
|
||||
int 0x15
|
||||
jc EnableA20.do_fallback_a20 ; carry = error...not supported?
|
||||
cmp ah, 0
|
||||
ja EnableA20.do_fallback_a20 ; non-zero return = error as well
|
||||
|
||||
mov al, bl
|
||||
and al, 0000_0010b
|
||||
cmp al, 0000_0010b
|
||||
je EnableA20.do_fast_a20 ; if fast a20 is supported use it
|
||||
|
||||
jmp EnableA20.do_bios_a20 ; else fall back to enabling via BIOS
|
||||
|
||||
.do_fallback_a20:
|
||||
ERROR STAGE2_A20_FAILED
|
||||
.do_bios_a20:
|
||||
mov ax, 0x2401
|
||||
int 0x15
|
||||
jmp EnableA20.a20_check
|
||||
.do_fast_a20:
|
||||
in al, 0x92 ; read from FAST A20 port
|
||||
or al, 2 ; bit 0 is a fast reset, bit 1 is fast A20
|
||||
and al, 0xFE ; make sure bit 0 is 0
|
||||
out 0x92, al ; enable A20
|
||||
jmp EnableA20.a20_check
|
||||
.endp:
|
||||
popf
|
||||
pop es
|
||||
pop ds
|
||||
__CDECL16_EXIT
|
||||
ret
|
||||
|
||||
EnterUnrealMode:
|
||||
__CDECL16_ENTRY
|
||||
.func:
|
||||
@@ -810,18 +327,13 @@ NewLine_cstr:
|
||||
db StrCRLF_NUL
|
||||
BootTarget_str:
|
||||
db "BOOTI686BIN"
|
||||
|
||||
; #############
|
||||
;
|
||||
; Locals
|
||||
;
|
||||
; #############
|
||||
|
||||
partition_offset:
|
||||
boot_drive_ptr:
|
||||
db 0x00
|
||||
stage2_resb_1:
|
||||
db 0x00
|
||||
partition_offset_ptr:
|
||||
dw 0x0000
|
||||
|
||||
|
||||
|
||||
; GDT documentation below:
|
||||
;
|
||||
; Pr: Present bit. This must be 1 for all valid selectors.
|
||||
|
||||
176
src/vbr/vbr.nasm
176
src/vbr/vbr.nasm
@@ -30,63 +30,97 @@ phy_ebpb_start:
|
||||
; fill eBPB area with 0x00 since we skip writing this part to disk
|
||||
times 54 db 0x00
|
||||
|
||||
; ###############
|
||||
;
|
||||
; Headers/Includes/Definitions
|
||||
;
|
||||
; ###############
|
||||
%define __STEVIA_VBR
|
||||
|
||||
%include "cdecl16.inc"
|
||||
%include "entry.inc"
|
||||
%include "config.inc"
|
||||
%include "mem.inc"
|
||||
%include "error_codes.inc"
|
||||
%include "fat32/bpb_offset_bx.inc"
|
||||
|
||||
; ###############
|
||||
; End Section
|
||||
; ###############
|
||||
|
||||
ALIGN 4, db 0x90
|
||||
init:
|
||||
cli ; We do not want to be interrupted
|
||||
|
||||
xor ax, ax ; 0 AX
|
||||
mov ds, ax ; Set segment registers to 0
|
||||
mov es, ax ; *
|
||||
|
||||
mov ss, ax ; Set Stack Segment to 0
|
||||
mov sp, STACK_START ; Setup stack
|
||||
mov sp, EARLY_STACK_START ; Setup stack
|
||||
mov bp, sp ; base ptr = stack ptr
|
||||
sub sp, 0x20 ; local varible space
|
||||
|
||||
mov bx, VBR_ENTRY ; move Bx to the new start of the initial boot sector
|
||||
sti ; all done with inital setup and relocation, reenable interupts
|
||||
|
||||
jmp 0:main ; fix up cs:ip just in case and jump to relocated code
|
||||
nop
|
||||
|
||||
%include "config.inc"
|
||||
%include "memory.inc"
|
||||
; ###############
|
||||
;
|
||||
; Extra/Shared Functions
|
||||
;
|
||||
; ###############
|
||||
|
||||
%include "kmem_func.inc"
|
||||
%include "partition_table.inc"
|
||||
%include "errors.inc"
|
||||
%include "util/error_func.inc"
|
||||
|
||||
%include "fat32/bpb.inc"
|
||||
; ###############
|
||||
; End Section
|
||||
; ###############
|
||||
|
||||
ALIGN 4, db 0x90
|
||||
main:
|
||||
mov [bsDriveNumber], dl ; BIOS passes drive number in DL
|
||||
mov [partition_offset], si ; save passed partition entry offset
|
||||
mov byte [bp - 2], dl ; boot_drive
|
||||
mov [bp - 4], si ; part_offset
|
||||
|
||||
.check_FAT_size: ; we only support a very specific setup of FAT32
|
||||
cmp dword [bsSectorHuge], 0 ; SectorsHuge will not be set if FAT12/16
|
||||
ja main.load_stage2
|
||||
|
||||
ERROR VBR_ERROR_WRONG_FAT_SIZE
|
||||
.load_stage2: ; read sectors 1-63 to stage2 entry point
|
||||
mov ax, (fat32_bpb_SIZE + fat32_ebpb_SIZE) ; size in byte
|
||||
push ax
|
||||
mov ax, (phy_bpb_start - 0x3) ; start of bpb - 0x3 for the jump short main at the start
|
||||
push ax
|
||||
mov ax, fat32_bpb ; defined in memory.inc, destination
|
||||
push ax
|
||||
call kmemcpy ; copy bpb to memory
|
||||
add sp, 0x6
|
||||
|
||||
; read sectors 1-63 to stage2 entry point
|
||||
.load_stage2:
|
||||
xor ax, ax
|
||||
push ax ; upper_lower_lba = 0
|
||||
mov bx, fat32_bpb ; bx now points to aligned memory structure
|
||||
|
||||
mov ax , 1
|
||||
push ax ; lower_lower_lba = 1
|
||||
movzx ax, byte [bp - 2]
|
||||
push ax ; drive_num
|
||||
|
||||
mov ax, STAGE2_SECTOR_COUNT
|
||||
push ax ; count
|
||||
|
||||
mov dword eax, 0x1
|
||||
push dword eax ; lba
|
||||
|
||||
xor ax, ax
|
||||
push ax ; offset = 0
|
||||
push ax ; offset = 0
|
||||
|
||||
; 07E0:0
|
||||
; 07E0:0 = 0x00007e00
|
||||
mov ax, STAGE2_ENTRY
|
||||
shr ax, 4
|
||||
push ax ; segment = 7E0
|
||||
push ax ; segment = 7E0
|
||||
|
||||
;uint8_t read_stage2_raw(uint16_t buf_segment, uint16_t buf_offset,
|
||||
; uint16_t lower_lower_lba, uint16_t upper_lower_lba)
|
||||
call read_stage2_raw
|
||||
add sp, 0x8
|
||||
; uint8_t read_stage2_raw(uint16_t buf_segment, uint16_t buf_offset,
|
||||
; uint32_t lba,
|
||||
; uint16_t count, uint16_t drive_num)
|
||||
call read_disk_raw
|
||||
add sp, 0xC
|
||||
|
||||
.check_sig:
|
||||
mov ax, 0x7E0
|
||||
@@ -97,97 +131,15 @@ main:
|
||||
ERROR VBR_ERROR_NO_SIGNATURE ; no signature present in stage2
|
||||
|
||||
.sig_ok:
|
||||
mov ax, fat32_bpb_SIZE ; size in byte
|
||||
push ax
|
||||
mov ax, phy_bpb_start ; start of bpb
|
||||
push ax
|
||||
mov ax, fat32_bpb ; defined in memory.inc, destination
|
||||
push ax
|
||||
call kmemcpy ; copy bpb to memory
|
||||
add sp, 0x6
|
||||
|
||||
mov ax, fat32_ebpb_SIZE ; 72 bytes of data
|
||||
push ax
|
||||
mov ax, phy_ebpb_start ; start of ebpb
|
||||
push ax
|
||||
mov ax, fat32_ebpb ; defined in memory.inc, destination
|
||||
push ax
|
||||
call kmemcpy ; copy ebpb to memory
|
||||
add sp, 0x6
|
||||
|
||||
mov si, [partition_offset]
|
||||
mov dl, [bsDriveNumber]
|
||||
mov si, [bp - 4]
|
||||
mov dx, [bp - 2]
|
||||
jmp 0:0x7E00
|
||||
|
||||
stop:
|
||||
hlt
|
||||
jmp short stop
|
||||
; ###############
|
||||
; Required BIOS function(s)
|
||||
; ###############
|
||||
|
||||
; Wrapper for AH=0x42 INT13h (Extended Read)
|
||||
;
|
||||
; BIOS call details
|
||||
; AH = 42h
|
||||
; DL = drive number
|
||||
; DS:SI -> disk address packet
|
||||
;
|
||||
; Return:
|
||||
; CF clear if successful
|
||||
; AH = 00h
|
||||
; CF set on error
|
||||
; AH = error code
|
||||
; disk address packet's block count field set to number of blocks
|
||||
; successfully transferred
|
||||
;
|
||||
;
|
||||
; uint8_t read_disk_raw(uint16_t buf_segment, uint16_t buf_offset,
|
||||
; uint16_t lower_lower_lba, uint16_t upper_lower_lba)
|
||||
read_stage2_raw:
|
||||
__CDECL16_ENTRY
|
||||
.func:
|
||||
mov ax, 0x10
|
||||
push ax ; len = 16 bytes
|
||||
xor ax, ax
|
||||
push ax ; val = 0
|
||||
mov ax, lba_packet
|
||||
push ax ; dest = lba_packet address
|
||||
call kmemset
|
||||
add sp, 0x06
|
||||
|
||||
mov byte [lba_packet + LBAPkt_t.size], 0x10
|
||||
mov word [lba_packet + LBAPkt_t.xfer_size], STAGE2_SECTOR_COUNT
|
||||
|
||||
mov ax, [bp + 10]
|
||||
shl eax, 16
|
||||
mov ax, [bp + 8]
|
||||
mov dword [lba_packet + LBAPkt_t.lower_lba], eax
|
||||
|
||||
mov ax, [bp + 6]
|
||||
mov word [lba_packet + LBAPkt_t.offset], ax
|
||||
|
||||
mov ax, [bp + 4]
|
||||
mov word [lba_packet + LBAPkt_t.segment], ax
|
||||
|
||||
mov si, lba_packet
|
||||
mov ah, 0x42
|
||||
mov dl, byte [bsDriveNumber]
|
||||
int 0x13
|
||||
jnc .endf
|
||||
|
||||
ERROR VBR_ERROR_DISK_READ_ERR
|
||||
.endf:
|
||||
__CDECL16_EXIT
|
||||
ret
|
||||
; Data
|
||||
|
||||
; #############
|
||||
;
|
||||
; Locals
|
||||
;
|
||||
; #############
|
||||
|
||||
; offset from the begining of sector 0 to the active partition.
|
||||
partition_offset:
|
||||
dw 0x0000
|
||||
%include 'BIOS/func/ext_read.inc'
|
||||
|
||||
%assign bytes_remaining (420 - ($ - $$))
|
||||
%warning VBR has bytes_remaining bytes remaining for code (MAX: 420 bytes)
|
||||
|
||||
Reference in New Issue
Block a user