215 lines
5.6 KiB
NASM
Executable File
215 lines
5.6 KiB
NASM
Executable File
; Copyright (c) 2023 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.
|
|
|
|
|
|
[BITS 16]
|
|
[ORG 0x7C00]
|
|
[CPU KATMAI]
|
|
jmp short init
|
|
nop
|
|
|
|
%include "fat32/bpb_reserve_area.inc"
|
|
%include "entry.inc"
|
|
|
|
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 bp, sp ; base ptr = stack ptr
|
|
|
|
mov bx, VBR_ENTRY ; move BP 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
|
|
|
|
%include "config.inc"
|
|
%include "memory.inc"
|
|
%include "kmem_func_OLD.inc"
|
|
%include "partition_table.inc"
|
|
%include "errors.inc"
|
|
|
|
%include "fat32/bpb.inc"
|
|
|
|
main:
|
|
mov [bsDriveNumber], dl ; BIOS passes drive number in DL
|
|
mov [partition_offset], si ; save passed partition entry 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
|
|
|
|
; read sectors 1-63 to stage2 entry point
|
|
.load_stage2:
|
|
push bp
|
|
mov bp, sp
|
|
|
|
;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)
|
|
|
|
xor ax, ax
|
|
push ax ; upper_lower_lba = 0
|
|
|
|
mov ax , 1
|
|
push ax ; lower_lower_lba = 1
|
|
|
|
xor ax, ax
|
|
push ax ; offset = 0
|
|
|
|
; 07E0:0
|
|
mov ax, STAGE2_ENTRY
|
|
shr ax, 4
|
|
push ax ; segment = 7E0
|
|
|
|
mov ax, STAGE2_SECTOR_COUNT
|
|
push ax
|
|
|
|
call read_disk_raw
|
|
leave
|
|
|
|
.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:
|
|
push bp
|
|
mov bp, sp
|
|
mov ax, fat32_bpb_SIZE ; size in byte
|
|
push ax
|
|
mov ax, bpb_start ; start of bpb
|
|
push ax
|
|
mov ax, fat32_bpb ; defined in memory.inc, destination
|
|
push ax
|
|
call kmemcpy ; copy bpb to memory
|
|
leave
|
|
|
|
push bp
|
|
mov bp, sp
|
|
mov ax, fat32_ebpb_SIZE ; 72 bytes of data
|
|
push ax
|
|
mov ax, ebpb_start ; start of ebpb
|
|
push ax
|
|
mov ax, fat32_ebpb ; defined in memory.inc, destination
|
|
push ax
|
|
call kmemcpy ; copy ebpb to memory
|
|
leave
|
|
|
|
mov si, [partition_offset]
|
|
mov dl, [bsDriveNumber]
|
|
jmp 0:0x7E00
|
|
|
|
stop:
|
|
hlt
|
|
jmp short stop
|
|
|
|
; 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)
|
|
; bp-0 = call frame
|
|
; bp-2 = upper_lower_lba
|
|
; bp-4 = lower_lower_lba
|
|
; bp-6 = offset
|
|
; bp-8 = segment
|
|
; bp-10 = count
|
|
; bp-12 = ret ptr
|
|
read_disk_raw:
|
|
push si
|
|
|
|
; uint8_t* kmemset(void* dest, uint8_t val, size_t len);
|
|
push bp
|
|
mov bp, sp
|
|
|
|
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
|
|
leave
|
|
|
|
mov byte [lba_packet + LBAPkt_t.size], 0x10
|
|
mov word [lba_packet + LBAPkt_t.xfer_size], STAGE2_SECTOR_COUNT
|
|
|
|
mov ax, [bp-2]
|
|
shl eax, 16
|
|
mov ax, [bp-4]
|
|
mov dword [lba_packet + LBAPkt_t.lower_lba], eax
|
|
|
|
mov ax, [bp-6]
|
|
mov word [lba_packet + LBAPkt_t.offset], ax
|
|
|
|
mov ax, [bp-8]
|
|
mov word [lba_packet + LBAPkt_t.segment], ax
|
|
|
|
mov si, lba_packet
|
|
mov ah, 0x42
|
|
mov dl, byte [bsDriveNumber]
|
|
int 0x13
|
|
jnc read_disk_raw.endf
|
|
|
|
ERROR VBR_ERROR_DISK_READ_ERR
|
|
.endf:
|
|
pop si
|
|
ret
|
|
; Data
|
|
|
|
; #############
|
|
;
|
|
; Locals
|
|
;
|
|
; #############
|
|
|
|
; offset from the begining of sector 0 to the active partition.
|
|
partition_offset:
|
|
dw 0x0000
|
|
|
|
%assign bytes_remaining (420 - ($ - $$))
|
|
%warning VBR has bytes_remaining bytes remaining for code (MAX: 420 bytes)
|
|
|
|
times (510 - ($ - $$)) nop ; Fill the rest of sector with nop
|
|
|
|
BootSig:
|
|
dw 0xAA55 ; Add boot signature at the end of bootloader |