diff --git a/Makefile b/Makefile index ead41f7..baf15ff 100755 --- a/Makefile +++ b/Makefile @@ -25,6 +25,7 @@ stage2: $(stage2_binary_files) boottest: $(boottest_binary_files) clean: + @rm -rvf *.map @rm -rvf $(build_dir)/* @rm -rvf $(iso) @rm -rvf $(isoz) diff --git a/include/BIOS/func/E820_memory_map.nasm b/include/BIOS/func/E820_memory_map.nasm index 6752bf3..abc944a 100644 --- a/include/BIOS/func/E820_memory_map.nasm +++ b/include/BIOS/func/E820_memory_map.nasm @@ -48,7 +48,8 @@ GetMemoryMap: mov eax, 0xE820 ; select 0xE820 function xor ebx, ebx ; Continuation value, 0 for the first call - mov dx, (BIOSMemoryMap >> 4) + lea dx, [BIOSMemoryMap] + shr dx, 4 mov es, dx xor di, di ; (BIOSMemoryMap >> 4):0 makes di an index into BIOSMemoryMap diff --git a/include/BIOS/func/ext_read.nasm b/include/BIOS/func/ext_read.nasm index 42d1cdc..826729a 100644 --- a/include/BIOS/func/ext_read.nasm +++ b/include/BIOS/func/ext_read.nasm @@ -36,6 +36,29 @@ struc LBAPkt_t .lower_lba resd 1 .upper_lba resd 1 endstruc +; call_read_disk_raw +%macro call_read_disk_raw 5 + movzx ax, %5 + push ax ; drive_num + + movzx ax, %4 + push ax ; count + + movzx dword eax, %3 + push dword eax ; lba + + movzx ax, %2 + push ax ; offset + + movzx ax, %1 + push ax ; segment = 0 + + ; 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 +%endmacro ; Wrapper for AH=0x42 INT13h (Extended Read) ; diff --git a/include/config.inc b/include/config.inc index db74252..ea4bbd7 100755 --- a/include/config.inc +++ b/include/config.inc @@ -21,7 +21,7 @@ %ifndef __INC_STEVIA_CONFIG %define SECTOR_SIZE 512 -%define STAGE2_SECTOR_COUNT 0x40 +%define STAGE2_SECTOR_COUNT 0x30 ; 32 KiB %define MAX_STAGE2_BYTES (SECTOR_SIZE * STAGE2_SECTOR_COUNT) diff --git a/include/mem.inc b/include/early_mem.inc similarity index 67% rename from include/mem.inc rename to include/early_mem.inc index ca8ac77..bce18d9 100755 --- a/include/mem.inc +++ b/include/early_mem.inc @@ -18,7 +18,7 @@ ; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ; SOFTWARE. -%ifndef __INC_MEM +%ifndef __INC_EARLY_MEM ; ## Generic Low mem map (from osdev wiki) ## @@ -43,54 +43,6 @@ ; 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) @@ -100,17 +52,5 @@ ; 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 \ No newline at end of file +%define __INC_EARLY_MEM \ No newline at end of file diff --git a/include/entry.inc b/include/entry.inc index fa5e710..0d276ee 100755 --- a/include/entry.inc +++ b/include/entry.inc @@ -21,10 +21,10 @@ %ifndef __INC_ENTRY ; 8KiB from 0x2500 -> 0x500 -%define EARLY_STACK_START 0x2500 -%define MBR_ENTRY 0x7A00 +%define EARLY_STACK_START 0xFFFF +%define MBR_ENTRY 0x0600 %define VBR_ENTRY 0x7C00 -%define STAGE2_ENTRY 0x7E00 +%define STAGE2_ENTRY 0x0500 %endif %define __INC_ENTRY \ No newline at end of file diff --git a/include/fat32/FAT32_SYS.inc b/include/fat32/FAT32_SYS.inc index 9c8d01b..9f00869 100644 --- a/include/fat32/FAT32_SYS.inc +++ b/include/fat32/FAT32_SYS.inc @@ -28,7 +28,7 @@ ALIGN 4, db 0x90 InitFATDriver: __CDECL16_ENTRY .func: - mov ax, fat32_state_SIZE + mov ax, FAT32_State_t_size push ax ; length of fat32_state structure xor ax, ax push ax ; init fat32_state with zero diff --git a/include/fat32/fat32_structures.inc b/include/fat32/fat32_structures.inc index 0bba2a5..7fb0289 100755 --- a/include/fat32/fat32_structures.inc +++ b/include/fat32/fat32_structures.inc @@ -63,6 +63,7 @@ ; resulting in a value which does not fit in the Number of Sectors entry at 0x13. struc FAT32_bpb_t + .reserved_init resb 3 .ident_8 resb 8 .bytes_per_sector_16 resb 2 .sectors_per_cluster_8 resb 1 diff --git a/include/partition_table.inc b/include/partition_table.inc index ddd9ab6..abd895a 100755 --- a/include/partition_table.inc +++ b/include/partition_table.inc @@ -34,15 +34,15 @@ struc PartEntry_t .chs_start resb 3 .part_type resb 1 .chs_end resb 3 - .lba_start resb 4 - .lba_length resb 4 + .lba_start resd 1 + .lba_length resd 1 endstruc struc PartTable_t - .partition1 resb 16 - .partition2 resb 16 - .partition3 resb 16 - .partition4 resb 16 + .partition1 resb PartEntry_t_size + .partition2 resb PartEntry_t_size + .partition3 resb PartEntry_t_size + .partition4 resb PartEntry_t_size endstruc %endif diff --git a/include/util/error_func.nasm b/include/util/error_func.nasm index 6c2aa92..5682266 100644 --- a/include/util/error_func.nasm +++ b/include/util/error_func.nasm @@ -22,9 +22,7 @@ %macro ERROR 1 mov al, %1 ; al = 1 byte error code mapped to ascii values - db 0xEA ; jmp far imm16:imm16 - dw error ; error_far_seg - dw 0x0000 ; error_far_ptr + jmp error %endmacro ; pass error as ascii character in al, errors a-zA-Z or 0-9 diff --git a/include/util/kmemcpy5_func.nasm b/include/util/kmemcpy5_func.nasm new file mode 100644 index 0000000..d3c698e --- /dev/null +++ b/include/util/kmemcpy5_func.nasm @@ -0,0 +1,53 @@ +; 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_KMEMCPY5_FUNC +%include 'cdecl16.inc' + +; uint8_t* kmemset(word dest_segment, word dest, word src_segment, word src, byte len); +; not overlap safe, only for +ALIGN 4, db 0x90 +kmemcpy5: + __CDECL16_ENTRY + push ds + push es +.setup_segments: + mov ax, [bp + 4] + mov ds, ax ; destination segment + + mov ax, [ bp + 8] + mov es, ax ; source segment +.func: + mov cx, [bp + 12] ; len + mov si, [bp + 10] ; src + mov di, [bp + 6] ; dest + + cld ; ensure we are incrementing + rep movsb ; move ds:si -> es:di + mov ax, di ; return pointer to dest +.restore_segments: + pop es + pop ds +.endf: + __CDECL16_EXIT + ret + +%define __INC_KMEMCPY5_FUNC +%endif \ No newline at end of file diff --git a/include/util/kmemset4_func.nasm b/include/util/kmemset4_func.nasm new file mode 100644 index 0000000..9f0a734 --- /dev/null +++ b/include/util/kmemset4_func.nasm @@ -0,0 +1,47 @@ +; 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_KMEMSET4_FUNC +%include 'cdecl16.inc' + +; word kmemset_byte(word segment, word dst, byte val, word len); +ALIGN 4, db 0x90 +kmemset4: + __CDECL16_ENTRY +.setup_segment: + push es + mov ax, [bp + 4] + mov es, ax + .func: + mov cx, [bp + 10] ; size_t len + mov al, [bp + 8] ; uint8_t val + mov di, [bp + 6] ; word dst + + cld + rep stosb ; move al -> es:di + mov ax, di ; return pointer to dest +.restore_segments: + pop es +.endf: + __CDECL16_EXIT + ret + +%endif +%define __INC_KMEMSET4_FUNC \ No newline at end of file diff --git a/src/mbr/mbr.nasm b/src/mbr/mbr.nasm index cfec883..02f61e4 100755 --- a/src/mbr/mbr.nasm +++ b/src/mbr/mbr.nasm @@ -19,46 +19,51 @@ ; SOFTWARE. [BITS 16] -[ORG 0x7A00] +[ORG 0x0600] [CPU KATMAI] [WARNING -reloc-abs-byte] [WARNING -reloc-abs-word] ; Yes, we use absolute addresses. surpress these warnings. [map all mbr.map] %define __STEVIA_MBR - jmp short (init - $$) nop ; ############### -; ; Headers/Includes/Definitions -; ; ############### %include "util/bochs_magic.inc" %include "cdecl16.inc" %include "entry.inc" %include "config.inc" -%include "mem.inc" %include "error_codes.inc" %include "partition_table.inc" +%include "fat32/fat32_structures.inc" -; ############### -; End Section -; ############### - -ALIGN 4, db 0x90 +ALIGN 4 init: - cli ; We do not want to be interrupted + cli ; We do not want to be interrupted + xor ax, ax + mov ds, ax ; Set segment registers to 0x0000 + mov es, ax + mov fs, ax + mov gs, ax - xor ax, ax ; 0 AX - mov ds, ax ; Set segment registers to 0 + ; + ; Zero BSS section + mov cx, (end_bss - begin_bss) ; count = bss length + mov ax, begin_bss + mov di, ax ; es:di is dest + xor ax, ax + cld + rep stosb ; zero bss section - 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 ss, ax ; Set Stack Segment to 0 + mov sp, stack_top ; Setup stack + mov bp, sp ; base ptr = stack ptr + sub sp, 0x10 ; local varible space + xor cx, cx mov ch, 0x01 ; 256 WORDs in MBR (512 bytes), 0x0100 in cx mov si, 0x7C00 ; Current MBR Address (loaded here by BIOS) mov di, MBR_ENTRY ; New MBR Address (our new relocation address) @@ -69,23 +74,15 @@ init: jmp 0:main ; ############### -; ; Extra/Shared Functions -; ; ############### %include "util/kmem_func.nasm" %include "util/error_func.nasm" -; ############### -; End Section -; ############### - ; ; bp - 2 : uint8_t boot_drive ; bp - 4 : uint16_t part_offset -; - ALIGN 4, db 0x90 main: mov byte [bp - 2], dl ; BIOS passes drive number in DL @@ -130,12 +127,11 @@ main: mov dword eax, dword [bx + PartEntry_t.lba_start] push dword eax ; lba - xor ax, ax - push ax ; offset = 0 - mov ax, VBR_ENTRY - shr ax, 4 - push ax ; segment = 7C0 + push ax ; offset = 0x7c00 + + xor ax, ax + push ax ; segment = 0 ; uint8_t read_stage2_raw(uint16_t buf_segment, uint16_t buf_offset, ; uint32_t lba, @@ -147,18 +143,19 @@ main: je main.sig_ok ERROR MBR_ERROR_NO_VBR_SIG ; no signature present .sig_ok: - mov ax, partition_table_SIZE ; 72 bytes of data + mov ax, PartTable_t_size push ax mov ax, DiskSig ; start of partition table push ax - mov ax, partition_table ; defined in memory.inc + mov ax, partition_table push ax - call kmemcpy ; copy partition table to memory + call kmemcpy ; copy partition table to bss add sp, 0x6 mov si, word [bp - 4] mov dl, byte [bp - 2] - jmp 0:0x7C00 + mov bx, partition_table + jmp word 0x0000:0x7C00 ; ############### ; @@ -168,10 +165,6 @@ main: %include 'BIOS/func/ext_read.nasm' -; ############### -; End Section -; ############### - %assign bytes_remaining (440 - ($ - $$)) %warning MBR has bytes_remaining bytes remaining for code (MAX: 440 bytes) times ((512 - 72) - ($ - $$)) nop ; Fill the rest of sector with nop @@ -192,4 +185,27 @@ PartEntry3: PartEntry4: times 16 db 0x00 BootSig: - dw 0xAA55 ; Add boot signature at the end of bootloader \ No newline at end of file + dw 0xAA55 ; Add boot signature at the end of bootloader +; this should mark the 512 byte mark...if not, something has gone wrong. +section .bss follows=.text +begin_bss: + +align 16, resb 1 +partition_table resb PartTable_t_size + +align 16, resb 1 +fat32_bpb resb FAT32_bpb_t_size +fat32_ebpb resb FAT32_ebpb_t_size + +align 16, resb 1 +fat32_nc_data resb 16 + +align 16, resb 1 +lba_packet resb LBAPkt_t_size + +align 512, resb 1 +stack_bottom resb 1024 ; 1Kib stack early on + +stack_top: +mbr_redzone resb 32 +end_bss: \ No newline at end of file diff --git a/src/stage2/stage2.nasm b/src/stage2/stage2.nasm index ca7484b..fb4e88a 100755 --- a/src/stage2/stage2.nasm +++ b/src/stage2/stage2.nasm @@ -19,27 +19,24 @@ ; SOFTWARE. [BITS 16] -[ORG 0X7E00] +[ORG 0x0500] ; IF YOU CHANGE ORG CHANGE THE SIGN OFFSET AT THE END [CPU KATMAI] [map all stage2.map] [WARNING -reloc-abs-byte] [WARNING -reloc-abs-word] [WARNING -reloc-abs-dword] ; Yes, we use absolute addresses. surpress these warnings. %define __STEVIA_STAGE2 - - +%define __STAGE2_SEGMENT 0x0000 ; ############### -; ; Headers/Includes/Definitions -; ; ############### %include "util/bochs_magic.inc" %include "cdecl16.inc" %include "entry.inc" %include "config.inc" -%include "mem.inc" +%include "early_mem.inc" %include "error_codes.inc" %macro print_string 1 @@ -50,57 +47,130 @@ %endmacro section .text -org 0x7E00 +org 0x0500 + begin_text: jmp short (init - $$) nop +; dl = byte boot_drive +; si = word part_offset (active partition offset) +; bx = ptr PartTable_t partition_table +; dx = ptr FAT32_bpb_t fat32_bpb ALIGN 4, db 0x90 init: - cli ; We do not want to be interrupted + 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 fs, ax ; * - mov gs, ax ; * + ; + ; Zero BSS section + ; + mov cx, (end_bss - begin_bss) ; count = bss length + + mov ax, begin_bss + shr ax, 4 + mov es, ax ; es = begining of bss section + + xor ax, ax + mov di, ax ; dst = 0 + + cld + rep stosb ; zero bss section + ; done zeroing BSS + + mov ax, __STAGE2_SEGMENT ; set all our segments to the configured segment + mov ds, ax ; * + mov es, ax ; * + mov fs, ax ; * + mov gs, ax ; * + + mov ss, ax ; Set Stack Segment to data segment + mov sp, stack_top ; Set Stack Pointer - 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 + jmp word __STAGE2_SEGMENT:main ; ############### -; -; Extra/Shared Functions -; +; Functions ; ############### %include "util/kmem_func.nasm" +%include "util/kmemcpy5_func.nasm" +%include "util/kmemset4_func.nasm" %include "util/error_func.nasm" -; bp - 2 : uint8_t boot_drive -; bp - 4 : uint16_t part_offset +; ############### +; FAT32 Driver +; ############### + +boot_drive_ptr: + dw 0x0000 +partition_offset_ptr: + dw 0x0000 + +%include 'fat32/FAT32_SYS.inc' + +; ############### +; BIOS functions +; ############### + +%include 'BIOS/BIOS_SYS.inc' + +; structures + +struc SteviaInfoStruct_t + .MemoryMapPtr resd 1 + .MemoryMapEntries resd 1 +endstruc + +struc EarlyBootStruct_t + .partition_table resb PartTable_t_size + .fat32_bpb resb FAT32_bpb_t_size + .fat32_ebpb resb FAT32_ebpb_t_size +endstruc + +; bp - 2 : byte boot_drive +; bp - 4 : word part_offset +; bp - 6 : ptr PartTable_t partition_table +; bp - 8 : ptr FAT32_bpb_t fat32_bpb ALIGN 4, db 0x90 main: lea ax, [bp - 2] mov [boot_drive_ptr], ax + lea ax, [bp - 4] mov [partition_offset_ptr], ax ; setup pointers to boot_drive and partition offset on stack mov byte [bp - 2], dl ; boot_drive (probably 0x80) mov word [bp - 4], si ; partition_offset - + mov word [bp - 6], bx ; partition_table + mov word [bp - 8], dx ; fat32_bpb +.check_sig: mov eax, dword [STAGE2_SIG] cmp eax, 0xDEADBEEF - je main.signature_present + je main.stage2_main ERROR STAGE2_SIGNATURE_MISSING +.stage2_main: + mov ax, PartTable_t_size + push ax + mov ax, [bp - 6] ; ptr partition_table + mov ax, partition_table + push ax + call kmemcpy ; copy partition table data + add sp, 0x6 + + mov ax, (FAT32_bpb_t_size + FAT32_ebpb_t_size) ; size in byte + push ax + mov ax, [bp - 8] ; 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 & ebpb to memory + add sp, 0x6 -.signature_present: call SetTextMode call disable_cursor print_string HelloPrompt_cstr @@ -121,6 +191,7 @@ main: call InitFATDriver print_string InitFATSYS_OK_cstr + ERROR STEVIA_DEBUG_HALT ; ; Find first cluster of bootable file ; @@ -136,27 +207,6 @@ hcf: hlt jmp short (hcf - $$) -; ############### -; -; FAT32 Driver -; -; ############### - -boot_drive_ptr: - dw 0x0000 -partition_offset_ptr: - dw 0x0000 - -%include 'fat32/FAT32_SYS.inc' - -; ############### -; -; BIOS functions -; -; ############### - -%include 'BIOS/BIOS_SYS.inc' - ; ############################## ; ; SYSTEM CONFIGURATION FUNCTIONS @@ -280,14 +330,16 @@ EnterUnrealMode: push ss push cs ; save real mode code selector + xor ax, ax ; pop ax ; save cs to ax to setup far jump - mov word [ds:__UNREAL_SEGMENT], ax + mov word [__UNREAL_SEGMENT], ax + + lgdt [((__STAGE2_SEGMENT << 4) + unreal_gdt_info)] ; load unreal gdt - lgdt [unreal_gdt_info] mov eax, cr0 or al,1 ; set pmode bit mov cr0, eax ; switch to pmode - jmp $+2 ; clear instruction cache + jmp short $+2 ;jmp far 0x0008:EnterUnrealMode.load_cs db 0xEA ; jmp far imm16:imm16 @@ -302,10 +354,10 @@ EnterUnrealMode: mov fs, bx mov gs, bx ; other data/stack to index 2 (off 0x10) - and al,0xFE ; toggle bit 1 of cr0 - mov cr0, eax ; back to realmode - jmp $+2 ; clear instruction cache again - + and al,0xFE ; toggle bit 1 of cr0 + mov cr0, eax ; back to realmode + jmp short $+2 + ;jmp far 0x0008:EnterUnrealMode.unload_cs db 0xEA ; jmp far imm16:imm16 dw EnterUnrealMode.unload_cs ; error_far_ptr @@ -367,58 +419,33 @@ IntToHex_table: db '0123456789ABCDEF' ; see docs/gdt.txt for a quick refresher on GDT -ALIGN 4, db 0 +ALIGN 16, db 0 unreal_gdt_info: unreal_gdt_size: dw (unreal_gdt_end - unreal_gdt_start) - 1 - unreal_gdt_ptr: dd unreal_gdt_start - + unreal_gdt_ptr: dd ((__STAGE2_SEGMENT << 4) + unreal_gdt_start) unreal_gdt_start: - ; entry 0 + ; entry 0 (null descriptor) dq 0 ; first entry is null - ; entry 1 (4 GiB flat code map) - dw 0xFFFF ; Segment Limit 15:0 (Same large limit as data segment) - dw 0x0000 ; Base Address 15:0 + ; entry 1 (16bit code 64KiB limit) + dd 0x0000FFFF ; Base Address(15:0) 31:16, Segment Limit(15:0) 15:0 db 0x00 ; Base Address 23:16 - db 1001_1010b ; Access Byte: 1001_1010b for executable code - db 1000_1111b ; Flags and Segment Limit 19:16 (Same as data segment) + db 1001_1010b ; Access Byte: Present, ring0, S = 1, executable (1), non-conforming, readable, Accessed + db 0000_0000b ; Flags: GR = 4KiB, attr = , Granularity = 4KiB & 16:19 of limit db 0x00 ; Base Address 31:24 - ; entry 2 (4 GiB flat data map) - dw 0xFFFF ; 0:15 limit - dw 0x0000 ; 0:15 base - db 0x00 ; 16:23 base - db 1001_0010b ; bit 0:4 = S/Type, [1, DC, RW, Ac] or [0, E, RW, Ac] - ; bit 5:6 = Privl - ; bit 7 = Present - - db 1000_1111b ; bit 0:3 = 16:19 of Limit - ; bit 4 = Availible to software bit - ; bit 5 = Reserved (?) - ; bit 6 = D/B bit, depending on if this is code/data 1 = 32 bit operands or stack size - ; bit 7 = Granularity bit. 1 = multiply limit by 4096 - db 0x00 ; base 24:31 - ; at the end of the day... - ; base = 0x00000000 - ; limit = 0xFFFFF - ; Accessed = 0, ignore this field - ; RW = 1, data is Read/Write - ; E = 0, Expand up, valid data is from base -> limit, if 1 valid data is from (limit + 1) -> base - ; C/D = 0, Segment is a data segment - ; S = 1, Segment is a system segment - ; Privl = 00b, Ring0 segment - ; Pr = 1, segment is present - ; AVL = 0, ignore this field - ; D/B bit = 0, 16bit code/stack - ; Gr = 1, multiply limit by 4096 + ; entry 2 (16bit data segment with 4 GiB flat mapping) + dd 0x0000FFFF ; Base Address(15:0) 31:16, Segment Limit(15:0) 15:0 + db 0x00 ; Base Address(23:16) + db 1001_0010b ; Access Byte: Present, ring0, S = 1, data (0), non-confirming, writable, present + db 1000_1111b ; Flags: GR = 4KiB, attr = <16-bit/?/?>, Granularity = 4KiB & 16:19 of limit + db 0x00 ; Base Address(31:24) unreal_gdt_end: -ALIGN 4, db 0 +ALIGN 16, db 0 gdt32_info: gdt32_size: dw (gdt32_end - gdt32_start) - 1 - gdt32_ptr: dd gdt32_start - -; check above for detailed information + gdt32_ptr: dd ((__STAGE2_SEGMENT << 4) + gdt32_start) gdt32_start: dq 0 .gdt32_code: @@ -465,15 +492,58 @@ end_data: ; section start location needs to be a 'critical expression' ; i.e resolvable at build time, we are setting 0x7E00 as the offset since -section .sign start=((MAX_STAGE2_BYTES - 512) + 0x7E00) -times ( (512 - 4) - ($ -$$)) db 0x90 ; nop -STAGE2_SIG: dd 0xDEADBEEF ; Signature to mark the end of the stage2 +section .sign start=((MAX_STAGE2_BYTES - 512) + 0x0500) +times ((512 - 4) - ($ -$$) ) db 0x90 ; nop +STAGE2_SIG: dd 0xDEADBEEF ; Signature to mark the end of the stage2 section .bss follows=.sign -align 512 +align 512, resb 1 begin_bss: -buffer1 resb 512 -buffer2 resb 512 -buffer3 resb 512 -buffer4 resb 512 +stack_bottom: + resb 4096 +stack_top: +stage2_main_redzone: + resb 32 + +align 16, resb 1 +partition_table resb PartTable_t_size + +align 16, resb 1 +fat32_bpb resb FAT32_bpb_t_size +fat32_ebpb resb FAT32_ebpb_t_size + +align 16, resb 1 +fat32_nc_data resb 16 + +align 16, resb 1 +lba_packet resb LBAPkt_t_size + +align 16, resb 1 +SteviaInfo: + resd 4 +align 16, resb 1 +fat32_state: + resb FAT32_State_t_size + +align 16, resb 1 +mbr_sector_data: + resb 512 +vbr_sector_data: + resb 512 + +align 16, resb 1 +disk_buffer: + resb 512 +fat_buffer: + resb 512 +dir_buffer: + resb 512 +fat_fsinfo: + resb 512 + +align 16, resb 1 +%define BIOSMemoryMap_SIZE 2048 +BIOSMemoryMap: + resb 2048 + end_bss: \ No newline at end of file diff --git a/src/vbr/vbr.nasm b/src/vbr/vbr.nasm index 009f7ae..f17c041 100755 --- a/src/vbr/vbr.nasm +++ b/src/vbr/vbr.nasm @@ -24,12 +24,11 @@ [WARNING -reloc-abs-word] [map all vbr.map] ; Yes, we use absolute addresses. surpress these warnings. %define __STEVIA_VBR - +section .text __ENTRY: jmp short (init - $$) nop -phy_bpb_start: ; fill BPB area with 0x00 since we skip writing this part to disk ; but we need it for the 'jmp short entry; nop' above times 33 db 0x00 @@ -47,35 +46,43 @@ times 54 db 0x00 %include "cdecl16.inc" %include "entry.inc" %include "config.inc" -%include "mem.inc" +%include "early_mem.inc" %include "error_codes.inc" +%include "partition_table.inc" +%include "fat32/fat32_structures.inc" %include "fat32/bpb_offset_bx.inc" - -; ############### -; End Section -; ############### - -ALIGN 4, db 0x90 +; +; dl = boot_drive +; si = part_offset +; bx = partition_table location from mbr +ALIGN 4 init: - cli ; We do not want to be interrupted + cli ; We do not want to be interrupted + xor ax, ax + mov ds, ax ; Set segment registers to 0x0000 + mov es, ax - xor ax, ax ; 0 AX - mov ds, ax ; Set segment registers to 0 + ; zero bss section + mov cx, (end_bss - begin_bss) ; count = bss length + mov ax, begin_bss + mov di, ax ; es:di is dest + xor ax, ax + cld + rep stosb - 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 + xor ax, ax + mov ss, ax ; Set Stack Segment to 0 + mov sp, stack_top ; Setup stack + mov bp, sp ; base ptr = stack ptr + sub sp, 0x10 ; 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 + mov cx, bx ; mov partition_table locaiton to cx + 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 + jmp 0:main ; fix up cs:ip just in case and jump to relocated code ; ############### -; ; Extra/Shared Functions -; ; ############### %include "util/kmem_func.nasm" @@ -85,27 +92,41 @@ init: ; End Section ; ############### +; +; byte boot_drive @ bp - 2 +; word part_offset @ bp - 4 +; ptr partition_table ALIGN 4, db 0x90 main: - mov byte [bp - 2], dl ; boot_drive - mov [bp - 4], si ; part_offset + mov byte [bp - 2], dl ; boot_drive + mov word [bp - 4], si ; part_offset + mov word [bp - 6], cx ; partition_table +.load_fs_data: + mov ax, PartTable_t_size + push ax + mov ax, [bp - 6] ; ptr partition_table + mov ax, partition_table + push ax + call kmemcpy ; copy partition table data + add sp, 0x6 + + mov ax, (FAT32_bpb_t_size + FAT32_ebpb_t_size) ; size in byte + push ax + mov ax, __ENTRY + push ax + mov ax, fat32_bpb ; + push ax + call kmemcpy ; copy bpb & ebpb to memory + add sp, 0x6 + + mov bx, fat32_bpb ; bx now points to aligned memory structure .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 - - mov bx, fat32_bpb ; bx now points to aligned memory structure - +.load_stage2: + ; read sectors 1-(MAX_STAGE2_BYTES / 512) to stage2 entry point movzx ax, byte [bp - 2] push ax ; drive_num @@ -115,32 +136,23 @@ main: mov dword eax, 0x1 push dword eax ; lba - xor ax, ax - push ax ; offset = 0 - - ; 07E0:0 = 0x00007e00 mov ax, STAGE2_ENTRY - shr ax, 4 - push ax ; segment = 7E0 + push ax ; offset + + xor ax, ax + push ax ; segment = 0 ; 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 - mov fs, ax - cmp dword [fs:0x7FFC], 0xDEADBEEF - je main.sig_ok - - ERROR VBR_ERROR_NO_SIGNATURE ; no signature present in stage2 - -.sig_ok: - mov si, word [bp - 4] - mov dl, byte [bp - 2] - jmp 0:0x7E00 +.enter_stage2: + mov dl, byte [bp - 2] ; boot_drive + mov si, word [bp - 4] ; part_offset + mov bx, partition_table + mov dx, fat32_bpb + jmp word 0x0000:STAGE2_ENTRY ; ############### ; Required BIOS function(s) @@ -154,4 +166,27 @@ main: times (510 - ($ - $$)) nop ; Fill the rest of sector with nop BootSig: - dw 0xAA55 ; Add boot signature at the end of bootloader \ No newline at end of file + dw 0xAA55 ; Add boot signature at the end of bootloader + +section .bss follows=.text +begin_bss: + +align 16, resb 1 +partition_table resb PartTable_t_size + +align 16, resb 1 +fat32_bpb resb FAT32_bpb_t_size +fat32_ebpb resb FAT32_ebpb_t_size + +align 16, resb 1 +fat32_nc_data resb 16 + +align 16, resb 1 +lba_packet resb LBAPkt_t_size + +align 512, resb 1 +stack_bottom resb 1024 ; 1Kib stack early on + +stack_top: +vbr_redzone resb 32 +end_bss: \ No newline at end of file