Skip to content

Commit

Permalink
bootnorm.asm: do not relocate beyond 128k anymore, and...
Browse files Browse the repository at this point in the history
... fix invalid drive number provided by BIOS, further try to
make source more readable.
  • Loading branch information
boeckmann committed May 11, 2024
1 parent b106753 commit 611de5f
Showing 1 changed file with 128 additions and 165 deletions.
293 changes: 128 additions & 165 deletions source/fdisk/bootnorm.asm
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
;
; normal DOS boot sector
; MBR boot code installed by Free FDISK
; to assemble use Netwide Assembler (NASM)
;
;-----------------------------------------------------------------------
; ENTRY (copied from freedos bootsector)
Expand All @@ -9,180 +10,142 @@
;
;-----------------------------------------------------------------------

real_start: cli
cld
xor ax, ax
mov ss, ax ; initialize stack
mov ds, ax
mov bp, 0x7c00
lea sp, [bp-0x20]
sti
mov ax, 0x1FE0
mov es, ax
mov si, bp
mov di, bp
mov cx, 0x0100
rep movsw

jmp word 0x1FE0:0x7c00+ cont-real_start

cont: mov ds, ax
mov ss, ax
xor ax,ax
mov es,ax

; search for active partition
lea di, [bp+0x1be] ; start of partition table
test_next_for_active:
test byte [di],0x80
jne active_partition_found
add di,0x10 ; next table
cmp di, 07c00h+0x1fe; scanned beyond end of table ??
jb test_next_for_active

;*****************************************************************
call print
db 'no active partition found',0
WAIT_FOR_REBOOT:
jmp $


;*****************************************************************
trouble_reading_drive:
call print
db 'read error while reading drive',0
jmp WAIT_FOR_REBOOT

;*****************************************************************

invalid_partition_code:
call print
db 'partition signature != 55AA',0
jmp WAIT_FOR_REBOOT

;*****************************************************************

active_partition_found:
; call print
; db 'loading active partition',0

call read_boot_sector
jc trouble_reading_drive
cmp word [es:0x7c00+0x1fe],0xaa55
jne invalid_partition_code
; call print
; db '.jump DOS..',0
jmp word 0x0:0x7c00 ; and jump to boot sector code


;*****************************
RELOC_SEG equ 0x80
PARTTBL_OFFSET equ 0x1be
SIGNATURE_OFFSET equ 0x1fe


org 0x7c00

start:
cli
xor ax, ax
mov ss, ax ; initialize stack
mov sp, start - 0x20 ; SS:SP = 0:7be0
sti
cld
mov bp, start
mov ds, ax ; DS = 0
; move MBR code out of the way to make room for volume boot record
relocate:
mov ax, RELOC_SEG
mov es, ax
mov si, bp
mov di, bp
mov cx, 0x0100
rep movsw
jmp word RELOC_SEG:.cs_changed
; From now on, the code is located 0x800 bytes above 0x7c00
; at absolute address 0x8400, or more accurate 80:7c000.
.cs_changed:
mov ds, ax ; DS = RELOC_SEG
xor ax, ax
mov es, ax ; ES = 0

fix_bootdrive:
test dl, dl ; is boot drive in DL given by BIOS zero?
jnz .dl_good ; if yes this can be considered a BIOS bug,
mov dl, 0x80 ; because we know we boot from HD
.dl_good:

; Test if one of the four primary partitions is active by checkung
; for value 0x80 in the first byte of the entries.
scan_for_active_partition:
lea di, [bp + PARTTBL_OFFSET] ; start of partition table
.l: test byte [di], 0x80
jnz chainload_bootsect
add di, 0x10 ; next table entry
cmp di, start + SIGNATURE_OFFSET ; scanned beyond end of table?
jb .l
.no_active:
call print
db 'no active partition found', 0
jmp $

; We found an active partition. Load its boot sector to 0:7c00,
; test the signature and far jump to 0:7c00
chainload_bootsect:
call read_boot_sector
jc .read_error
cmp word [es:start + SIGNATURE_OFFSET], 0xaa55
jne .invalid_partition_code
;-----------------------------------------------------------------------------
jmp word 0x0:0x7c00 ; jump to volume boot code
;-----------------------------------------------------------------------------
.read_error:
call print
db 'read error while reading drive', 0
jmp $
.invalid_partition_code:
call print
db 'partition signature != 55AA', 0
jmp $


;-----------------------------------------------------------------------------
; BIOS disk access packet used by ext. INT13 LBA read function

dap:
.packet_size db 0x10
.reserved1 db 0
.sector_count db 1
.reserved2 db 0
.buf_off dw 0x7c00
.buf_seg dw 0x0000
.lba_low dw 0
.lba_high dw 0
dw 0,0


;-----------------------------------------------------------------------------
; read_boot_sector
;
; IN: DI--> partition info
;OUT:CARRY
;*****************************
; IN : DI--> partition info
; OUT: CARRY

read_boot_sector:
; /* check for LBA support */
mov bx,0x55aa
mov ah,0x41
int 0x13

jc StandardBios ; if (regs.b.x != 0xaa55 || (regs.flags & 0x01))
cmp bx,0xaa55 ; goto StandardBios;
jne StandardBios

; /* if DAP cannot be used, don't use LBA */
; if ((regs.c.x & 1) == 0)
; goto StandardBios;
test cl,1
jz StandardBios
jmp short LBABios



;struct _bios_LBA_address_packet /* Used to access a hard disk via LBA */
;{
; unsigned char packet_size; /* size of this packet...set to 16 */
; unsigned char reserved_1; /* set to 0...unused */
; unsigned char number_of_blocks; /* 0 < number_of_blocks < 128 */
; unsigned char reserved_2; /* set to 0...unused */
; UBYTE far *buffer_address; /* addr of transfer buffer */
; unsigned long block_address; /* LBA address */
; unsigned long block_address_high; /* high bytes of LBA addr...unused */
;};

_bios_LBA_address_packet:
db 0x10
db 0
db 4 ; read four sectors - why not
db 0
dw 0x7c00 ; fixed boot address for DOS sector
dw 0x0000
_bios_LBA_low dw 0
_bios_LBA_high dw 0
dw 0,0


LBABios:
; copy start address of partition to DAP
mov ax,[di+8]
mov [0x7c00+ (_bios_LBA_low-real_start)],ax
mov ax,[di+8+2]
mov [0x7c00+ (_bios_LBA_high-real_start)],ax

mov ax,0x4200 ; regs.a.x = LBA_READ;
mov si,0x7c00+ (_bios_LBA_address_packet-real_start); regs.si = FP_OFF(&dap);

.check_lba:
mov bx, 0x55aa ; magic value changed after call
mov ah, 0x41
int 0x13 ; test for ext. INT13 LBA support
jc .read_chs ; no support if carry set
cmp bx, 0xaa55 ; no support if 55aa not swapped
jne .read_chs
test cl, 1 ; no support if LBA flag not set
jz .read_chs
.read_lba:
mov ax, [di + 8] ; copy start sector of partition to DAP
mov [dap.lba_low], ax
mov ax, [di + 10]
mov [dap.lba_high], ax
mov ax, 0x4200
mov si, dap
int 0x13
ret

;*****************************************************************
; read disk, using standard BIOS
;
StandardBios:
; call print
; db 'standard BIOS',0


mov ax,0x0204 ; regs.a.x = 0x0201;
mov bx,0x7c00 ; regs.b.x = FP_OFF(buffer);
mov cx,[di+2] ; regs.c.x =
; ((chs.Cylinder & 0xff) << 8) + ((chs.Cylinder & 0x300) >> 2) +
; chs.Sector;
; that was easy ;-)
mov dh,[di+1] ; regs.d.b.h = chs.Head;
; regs.es = FP_SEG(buffer);
.read_chs:
mov ax, 0x0201 ; read one sector
mov bx, 0x7c00 ; to 0:7c00
mov cx, [di + 2]
mov dh, [di + 1]
int 0x13
ret


;****** PRINT
;-----------------------------------------------------------------------------
; prints text after call to this function.

print_1char:
xor bx, bx ; video page 0
mov ah, 0x0E ; else print it
int 0x10 ; via TTY mode
print: pop si ; this is the first character
print1: lodsb ; get token
push si ; stack up potential return address
cmp al, 0 ; end of string?
jne print_1char ; until done
ret ; and jump to it



times 0x1fe-$+$$ db 0
db 0x55,0xaa
xor bx, bx ; video page 0
mov ah, 0x0E ; else print it
int 0x10 ; via TTY mode
print: pop si ; this is the first character
lodsb ; get token
push si ; stack up potential return address
cmp al, 0 ; end of string?
jne print_1char ; until done
ret ; and jump to it


; zero-fill rest of sector and put signature into place
times 0x1fe - $ + $$ db 0
db 0x55, 0xaa

0 comments on commit 611de5f

Please sign in to comment.