bztsrc--bootboot/x86_64-bios/boot.asm

247 lines
8.4 KiB
NASM

;*
;* x86_64-bios/boot.asm
;*
;* Copyright (C) 2017 - 2021 bzt (bztsrc@gitlab)
;*
;* 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.
;*
;* This file is part of the BOOTBOOT Protocol package.
;* @brief Stage1 loader, compatible with BIOS boot specification and
;* El Torito CD-ROM boot in "no emulation" mode
;*
;*********************************************************************
;* Macros *
;*********************************************************************
;LBA packet fields
lba_packet equ 07E00h
virtual at lba_packet
lbapacket.size: dw ?
lbapacket.count:dw ?
lbapacket.addr0:dw ?
lbapacket.addr1:dw ?
lbapacket.sect0:dw ?
lbapacket.sect1:dw ?
lbapacket.sect2:dw ?
lbapacket.sect3:dw ?
end virtual
;memory locations
ldr.header equ 800h ;position of 2nd stage loader
ldr.executor equ 804h ;ptr to init code
;Writes a message on screen.
macro print msg
{
if ~ msg eq si
push si
mov si, msg
end if
call printfunc
if ~ msg eq si
pop si
end if
}
;*********************************************************************
;* code *
;*********************************************************************
;-----------------ENTRY POINT called by BIOS--------------------
ORG 0600h
USE16
bootboot_record:
jmp short .skipid
nop
;skip BPB area so that we can use this
;boot code on a FAT / exFAT volume if needed
db 120-($-$$) dup 0
.skipid: ;relocate our code to offset 0h:600h
cli
cld
xor ax, ax
mov ss, ax
mov sp, 600h
push ax
pop es
push cs
pop ds
;find our position in memory.
call .getaddr
.getaddr: pop si
sub si, .getaddr-bootboot_record
mov di, sp
;clear data area 500h-600h
sub di, 100h
mov cx, 80h
repnz stosw
;and copy ourselves to 600h
mov cx, 100h
repnz movsw
;have to clear ds, because cs is set to 7c0 when booted from El Torito
push es
pop ds
jmp 0:.start
.start: ;save boot drive code
mov byte [drive], dl
;check for lba presistance - floppy not supported any more
;we use USB sticks as removable media for a long time
cmp dl, byte 80h
jl .nolba
.notfloppy: mov ah, byte 41h
mov bx, word 55AAh
int 13h
jc .nolba
cmp bx, word 0AA55h
jne .nolba
test cl, byte 1
jnz .lbaok
.nolba: mov si, lbanotf
jmp diefunc
.lbaok: ;get CDROM drive code
mov ax, word 4B01h
mov si, lba_packet
mov byte [si + 2], 0E0h
push si
int 13h
pop si
jc .read2stg
mov al, byte [si + 2]
mov byte [cdrom], al
;try to load stage2 - it's a continous area on disk
;started at given sector with maximum size of 7000h bytes
.read2stg: mov di, lba_packet
mov si, stage2_addr
;set up for hard-drive
xor ah, ah
mov al, 16 ; size
stosw
mov al, 56 ; count
stosw
xor al, al
mov ah, 8 ; addr0 to address 800h
stosw
xor ax, ax ; addr1
stosw
movsw ; sect0
movsw ; sect1
xor ax, ax
stosw ; sect2
stosw ; sect3
mov dl, byte [drive]
;if it's a CDROM with 2048 byte sectors
cmp dl, byte [cdrom]
jl @f
sub di, 8
;lba=lba/4
clc
rcr word [di+2], 1
rcr word [di], 1
clc
rcr word [di+2], 1
rcr word [di], 1
;count=count/4
shr word [lbapacket.count], 2
;load sectors
@@: mov ah, byte 42h
mov si, lba_packet
int 13h
;do we have a 2nd stage loader?
.chk: cmp word [ldr.header], 0AA55h
jne .nostage2
cmp byte [ldr.header+3], 0E9h
jne .nostage2
mov dl, byte [drive]
;invoke stage2 real mode code
mov ax, [ldr.executor]
add ax, ldr.executor+2
jmp ax
.nostage2: ;try to load stage2 from a RAID mirror
mov al, byte [drive]
inc al
cmp al, 87h
jle @f
mov al, 80h
@@: mov byte [drive], al
inc byte [cnt]
cmp byte [cnt], 8
jl .read2stg
.nostage2err:
mov si, stage2notf
;fall into the diefunc code
;*********************************************************************
;* functions *
;*********************************************************************
;writes the reason, waits for a key and reboots.
diefunc:
print panic
call printfunc
sti
xor ax, ax
int 16h
mov al, 0FEh
out 64h, al
jmp far 0FFFFh:0 ;invoke BIOS POST routine
;ds:si zero terminated string to write
printfunc:
lodsb
or al, al
jz .end
mov ah, byte 0Eh
mov bx, word 11
int 10h
jmp printfunc
.end: ret
;*********************************************************************
;* data area *
;*********************************************************************
panic: db "BOOTBOOT-PANIC: no ",0
lbanotf: db "LBA support",0
stage2notf: db "FS0:\BOOTBOOT.BIN",0
db 01B0h-($-$$) dup 0
;right before the partition table some data
stage2_addr:dd 0FFFFFFFFh ;1B0h 2nd stage loader address
;this should be set by mkfs
cnt: db 0
drive: db 0
cdrom: db 0
db 0
diskid: dd 0 ;1B8h WinNT expects it here
dw 0
;1BEh first partition entry
;padding and magic
db 01FEh-($-$$) dup 0
db 55h,0AAh
bootboot_record_end: