Files
stevia/include/BIOS/func/ext_read.nasm

129 lines
3.7 KiB
NASM

; Copyright (C) 2025 Elaina Claus
;
; This program is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation, either version 3 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program. If not, see <https://www.gnu.org/licenses/>.
%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
; call_read_disk_raw <word segment> <word offset> <dword lba> <word count> <word drive_num>
%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)
;
; 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, uint8_t drive_num)
ALIGN 4, db 0x90
read_disk_raw:
__CDECL16_ENTRY
.func:
mov ax, LBAPkt_t_size
push ax ; len
xor ax, ax
push ax ; val = 0
mov ax, lba_packet
push ax ; dest = lba_packet address
call kmemset
add sp, 0x06
mov bx, lba_packet
mov byte [bx + LBAPkt_t.size], LBAPkt_t_size
mov ax, [bp + 12]
mov word [bx + LBAPkt_t.xfer_size], ax
mov eax, dword [bp + 8]
mov dword [bx + LBAPkt_t.lower_lba], eax
; upper_lba is zero from kmemset
; TODO: possiblly support >32bit LBA addresses in the future, this limits us to 4GiB
mov ax, [bp + 6]
mov word [bx + LBAPkt_t.offset], ax
mov ax, [bp + 4]
mov word [bx + LBAPkt_t.segment], ax
xor ax, ax
xor dx, dx
mov si, bx ; ds:si LBAPkt_t
mov ah, 0x42 ; call #
mov dl, byte [bp + 14] ; drive #
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