mirror of
https://github.com/FDOS/kernel.git
synced 2025-07-24 22:34:29 +02:00
Version 2.7 luchezar, tomehlert, ericauer 2003/8/5
boot.asm modified to support non-512 byte sectors (e.g. 1.2 MB NEC diskettes) 512 byte sector size check removed (although Eric's boot32ea.asm does require 512-byte sectors, all LBA FAT32 volumes have 512-byte sectors anyway). boot.asm cleaned up and modified to support Metakern (by Tom, Eric and Lucho) bsDriveNumber updated by SYS even #ifndef STORE_BOOT_INFO (nothing in common) Version 2.7beta, Luchezar Georgiev, 1 August 2003 o Now supports and includes the following new boot sectors: 1) the combined CHS+LBA FAT12/FAT16 boot sector by Tom Ehlert (29 July) 2) the CHS-only FAT32 boot sector -- as patched by Jon Gentle (08 July) 3) the LBA-only FAT32 boot sector by Eric Auer and Jon Gentle (19 July) o The old combined (CHS+LBA), no-CALCPARAMS, no-resizable, non-Ghostable, non-standard FAT32 boot sector and STORE_BOOT_INFO is no longer used. o dump_sector() showed ASCII debug printout for the old sector only - fixed. o Put a boot sector only if sector size = 512 (may it not be so in Japan?!). If non-512 byte sectors encountered, report to the fd-kernel mailing list. o Now puts boot sector before copying kernel/shell so it works in WinNT now. o check_space() now implemented at last (required significant modifications) o New file system (FAT type) detection method according to a MS White Paper. o Now BOOTONLY works even without a preceding boot sector image file name. o Some minor code cleanups. Bart: some cleanups to the above; replaced 386 code for CHS FAT32 by 8088 code. use boot32lb.asm instead of boot32ea.asm git-svn-id: https://svn.code.sf.net/p/freedos/svn/kernel/trunk@652 6ac86273-5f31-0410-b378-82cca8765d1b
This commit is contained in:
parent
3229fe3fc4
commit
9a3da2b737
262
boot/boot.asm
262
boot/boot.asm
@ -26,31 +26,24 @@
|
|||||||
; Cambridge, MA 02139, USA.
|
; Cambridge, MA 02139, USA.
|
||||||
;
|
;
|
||||||
;
|
;
|
||||||
; +--------+
|
; +--------+ 1FE0:7E00
|
||||||
; | |
|
|
||||||
; | |
|
|
||||||
; |--------| 4000:0000
|
|
||||||
; | |
|
|
||||||
; | FAT |
|
|
||||||
; | |
|
|
||||||
; |--------| 2000:0000
|
|
||||||
; |BOOT SEC|
|
; |BOOT SEC|
|
||||||
; |RELOCATE|
|
; |RELOCATE|
|
||||||
; |--------| 1FE0:0000
|
; |--------| 1FE0:7C00
|
||||||
; | |
|
|
||||||
; | |
|
; | |
|
||||||
|
; |--------| 1FE0:3000
|
||||||
|
; | CLUSTER|
|
||||||
|
; | LIST |
|
||||||
|
; |--------| 1FE0:2000
|
||||||
; | |
|
; | |
|
||||||
|
; |--------| 0000:7E00
|
||||||
|
; |BOOT SEC| overwritten by max 128k FAT buffer
|
||||||
|
; |ORIGIN | and later by max 134k loaded kernel
|
||||||
|
; |--------| 0000:7C00
|
||||||
; | |
|
; | |
|
||||||
; |--------|
|
; |--------|
|
||||||
; |BOOT SEC|
|
; |KERNEL | also used as max 128k FAT buffer
|
||||||
; |ORIGIN | 07C0:0000
|
; |LOADED | before kernel loading starts
|
||||||
; |--------|
|
|
||||||
; | |
|
|
||||||
; | |
|
|
||||||
; | |
|
|
||||||
; |--------|
|
|
||||||
; |KERNEL |
|
|
||||||
; |LOADED |
|
|
||||||
; |--------| 0060:0000
|
; |--------| 0060:0000
|
||||||
; | |
|
; | |
|
||||||
; +--------+
|
; +--------+
|
||||||
@ -58,8 +51,6 @@
|
|||||||
|
|
||||||
;%define ISFAT12 1
|
;%define ISFAT12 1
|
||||||
;%define ISFAT16 1
|
;%define ISFAT16 1
|
||||||
;%define CALCPARAMS 1
|
|
||||||
;%define MULTI_SEC_READ 1
|
|
||||||
|
|
||||||
|
|
||||||
segment .text
|
segment .text
|
||||||
@ -118,7 +109,7 @@ Entry: jmp short real_start
|
|||||||
mov word [fat_start+2], di
|
mov word [fat_start+2], di
|
||||||
|
|
||||||
mov al, [bsFATs]
|
mov al, [bsFATs]
|
||||||
xor ah, ah
|
cbw
|
||||||
mul word [sectPerFat] ; DX:AX = total number of FAT sectors
|
mul word [sectPerFat] ; DX:AX = total number of FAT sectors
|
||||||
|
|
||||||
add si, ax
|
add si, ax
|
||||||
@ -148,49 +139,50 @@ Entry: jmp short real_start
|
|||||||
|
|
||||||
times 0x3E-$+$$ db 0
|
times 0x3E-$+$$ db 0
|
||||||
|
|
||||||
%define tempbuf bp+0x3E
|
%define loadsegoff_60 bp+0x3E
|
||||||
|
dw 0
|
||||||
|
%define loadseg_60 bp+0x40
|
||||||
dw LOADSEG
|
dw LOADSEG
|
||||||
|
|
||||||
%ifdef CALCPARAMS
|
;%define LBA_PACKET bp+0x42
|
||||||
%define RootDirSecs bp+0x27 ; # of sectors root dir uses
|
; db 10h ; size of packet
|
||||||
|
; db 0 ; const
|
||||||
|
; dw 1 ; number of sectors to read
|
||||||
|
%define LBA_PACKET bp-0x40
|
||||||
|
%define LBA_SIZE word [LBA_PACKET]
|
||||||
|
%define LBA_SECNUM word [LBA_PACKET+2]
|
||||||
|
%define LBA_OFF LBA_PACKET+4
|
||||||
|
%define LBA_SEG LBA_PACKET+6
|
||||||
|
%define LBA_SECTOR_0 word [LBA_PACKET+8 ]
|
||||||
|
%define LBA_SECTOR_16 word [LBA_PACKET+10]
|
||||||
|
%define LBA_SECTOR_32 word [LBA_PACKET+12]
|
||||||
|
%define LBA_SECTOR_48 word [LBA_PACKET+14]
|
||||||
|
|
||||||
%define fat_start bp+0x29 ; first FAT sector
|
|
||||||
|
|
||||||
%define root_dir_start bp+0x2D ; first root directory sector
|
|
||||||
|
|
||||||
%define data_start bp+0x31 ; first data sector
|
%define PARAMS LBA_PACKET+0x10
|
||||||
|
%define RootDirSecs PARAMS+0x0 ; # of sectors root dir uses
|
||||||
|
|
||||||
%else
|
%define fat_start PARAMS+0x2 ; first FAT sector
|
||||||
%define RootDirSecs bp+0x40 ; # of sectors root dir uses
|
|
||||||
dw 0
|
|
||||||
|
|
||||||
%define fat_start bp+0x42 ; first FAT sector
|
%define root_dir_start PARAMS+0x6 ; first root directory sector
|
||||||
dd 0
|
|
||||||
|
|
||||||
%define root_dir_start bp+0x46 ; first root directory sector
|
%define data_start PARAMS+0x0a ; first data sector
|
||||||
dd 0
|
|
||||||
|
|
||||||
%define data_start bp+0x4A ; first data sector
|
|
||||||
dd 0
|
|
||||||
%endif
|
|
||||||
|
|
||||||
;-----------------------------------------------------------------------
|
;-----------------------------------------------------------------------
|
||||||
; ENTRY
|
; ENTRY
|
||||||
;-----------------------------------------------------------------------
|
;-----------------------------------------------------------------------
|
||||||
|
|
||||||
real_start: cli
|
real_start:
|
||||||
|
cli
|
||||||
cld
|
cld
|
||||||
xor ax, ax
|
xor ax, ax
|
||||||
mov ss, ax ; initialize stack
|
|
||||||
mov ds, ax
|
mov ds, ax
|
||||||
mov bp, 0x7c00
|
mov bp, 0x7c00
|
||||||
lea sp, [bp-0x20]
|
|
||||||
sti
|
|
||||||
cmp byte [drive], 0xff ; BIOS bug ??
|
; a reset should not be needed here
|
||||||
jne dont_use_dl
|
|
||||||
mov [drive], dl ; BIOS passes drive number in DL
|
|
||||||
; a reset should not be needed here
|
|
||||||
dont_use_dl:
|
|
||||||
; int 0x13 ; reset drive
|
; int 0x13 ; reset drive
|
||||||
|
|
||||||
; int 0x12 ; get memory available in AX
|
; int 0x12 ; get memory available in AX
|
||||||
@ -207,15 +199,26 @@ dont_use_dl:
|
|||||||
rep movsw
|
rep movsw
|
||||||
jmp word 0x1FE0:cont
|
jmp word 0x1FE0:cont
|
||||||
|
|
||||||
cont: mov ds, ax
|
cont:
|
||||||
|
mov ds, ax
|
||||||
mov ss, ax
|
mov ss, ax
|
||||||
|
lea sp, [bp-0x60]
|
||||||
|
sti
|
||||||
|
;
|
||||||
|
; Some BIOS don't pass drive number in DL, so don't use it if [drive] is known
|
||||||
|
;
|
||||||
|
cmp byte [drive], 0xff ; impossible number written by SYS
|
||||||
|
jne dont_use_dl ; was SYS drive: other than A or B?
|
||||||
|
mov [drive], dl ; yes, rely on BIOS drive number in DL
|
||||||
|
dont_use_dl: ; no, rely on [drive] written by SYS
|
||||||
|
|
||||||
|
mov LBA_SIZE, 10h
|
||||||
|
mov LBA_SECNUM,1 ; initialise LBA packet constants
|
||||||
|
|
||||||
call print
|
call print
|
||||||
db "FreeDOS",0
|
db "FreeDOS",0
|
||||||
|
|
||||||
%ifdef CALCPARAMS
|
|
||||||
GETDRIVEPARMS
|
GETDRIVEPARMS
|
||||||
%endif
|
|
||||||
|
|
||||||
|
|
||||||
; FINDFILE: Searches for the file in the root directory.
|
; FINDFILE: Searches for the file in the root directory.
|
||||||
@ -229,13 +232,12 @@ cont: mov ds, ax
|
|||||||
mov ax, word [root_dir_start]
|
mov ax, word [root_dir_start]
|
||||||
mov dx, word [root_dir_start+2]
|
mov dx, word [root_dir_start+2]
|
||||||
mov di, word [RootDirSecs]
|
mov di, word [RootDirSecs]
|
||||||
xor bx, bx
|
les bx, [loadsegoff_60] ; es:bx = 60:0
|
||||||
mov word [tempbuf], LOADSEG
|
|
||||||
mov es, [tempbuf]
|
|
||||||
call readDisk
|
call readDisk
|
||||||
jc jmp_boot_error
|
jc jmp_boot_error
|
||||||
|
|
||||||
xor di, di
|
les di, [loadsegoff_60] ; es:di = 60:0
|
||||||
|
|
||||||
|
|
||||||
; Search for KERNEL.SYS file name, and find start cluster.
|
; Search for KERNEL.SYS file name, and find start cluster.
|
||||||
|
|
||||||
@ -255,8 +257,8 @@ next_entry: mov cx, 11
|
|||||||
ffDone:
|
ffDone:
|
||||||
push ax ; store first cluster number
|
push ax ; store first cluster number
|
||||||
|
|
||||||
call print
|
; call print
|
||||||
db " FAT",0
|
; db " FAT",0
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -275,8 +277,7 @@ ffDone:
|
|||||||
; Load the complete FAT into memory. The FAT can't be larger
|
; Load the complete FAT into memory. The FAT can't be larger
|
||||||
; than 128 kb, so it should fit in the temporary buffer.
|
; than 128 kb, so it should fit in the temporary buffer.
|
||||||
|
|
||||||
mov es, [tempbuf]
|
les bx, [loadsegoff_60] ; es:bx=60:0
|
||||||
xor bx, bx
|
|
||||||
mov di, [sectPerFat]
|
mov di, [sectPerFat]
|
||||||
mov ax, word [fat_start]
|
mov ax, word [fat_start]
|
||||||
mov dx, word [fat_start+2]
|
mov dx, word [fat_start+2]
|
||||||
@ -286,9 +287,8 @@ jmp_boot_error: jc boot_error
|
|||||||
|
|
||||||
; Set ES:DI to the temporary storage for the FAT chain.
|
; Set ES:DI to the temporary storage for the FAT chain.
|
||||||
push ds
|
push ds
|
||||||
push es
|
|
||||||
pop ds
|
|
||||||
pop es
|
pop es
|
||||||
|
mov ds, [loadseg_60]
|
||||||
mov di, FATBUF
|
mov di, FATBUF
|
||||||
|
|
||||||
next_clust: stosw ; store cluster number
|
next_clust: stosw ; store cluster number
|
||||||
@ -308,8 +308,7 @@ fat_12: add si, si ; multiply cluster number by 3...
|
|||||||
; the number was odd, CF was set in the last shift instruction.
|
; the number was odd, CF was set in the last shift instruction.
|
||||||
|
|
||||||
jnc fat_even
|
jnc fat_even
|
||||||
mov cl, 4
|
div word[LBA_PACKET]; luckily 16 !! -- divide the cluster number
|
||||||
shr ax, cl ; shift the cluster number
|
|
||||||
|
|
||||||
fat_even: and ah, 0x0f ; mask off the highest 4 bits
|
fat_even: and ah, 0x0f ; mask off the highest 4 bits
|
||||||
cmp ax, 0x0ff8 ; check for EOF
|
cmp ax, 0x0ff8 ; check for EOF
|
||||||
@ -320,7 +319,7 @@ fat_even: and ah, 0x0f ; mask off the highest 4 bits
|
|||||||
; This is a FAT-16 disk. The maximal size of a 16-bit FAT
|
; This is a FAT-16 disk. The maximal size of a 16-bit FAT
|
||||||
; is 128 kb, so it may not fit within a single 64 kb segment.
|
; is 128 kb, so it may not fit within a single 64 kb segment.
|
||||||
|
|
||||||
fat_16: mov dx, [tempbuf]
|
fat_16: mov dx, [loadseg_60]
|
||||||
add si, si ; multiply cluster number by two
|
add si, si ; multiply cluster number by two
|
||||||
jnc first_half ; if overflow...
|
jnc first_half ; if overflow...
|
||||||
add dh, 0x10 ; ...add 64 kb to segment value
|
add dh, 0x10 ; ...add 64 kb to segment value
|
||||||
@ -341,14 +340,13 @@ finished: ; Mark end of FAT chain with 0, so we have a single
|
|||||||
push cs
|
push cs
|
||||||
pop ds
|
pop ds
|
||||||
|
|
||||||
call print
|
;call print
|
||||||
db " Kernel",0 ; "KERNEL"
|
;db " Kernel",0 ; "KERNEL"
|
||||||
|
|
||||||
|
|
||||||
; loadFile: Loads the file into memory, one cluster at a time.
|
; loadFile: Loads the file into memory, one cluster at a time.
|
||||||
|
|
||||||
mov es, [tempbuf] ; set ES:BX to load address
|
les bx, [loadsegoff_60] ; set ES:BX to load address 60:0
|
||||||
xor bx, bx
|
|
||||||
|
|
||||||
mov si, FATBUF ; set DS:SI to the FAT chain
|
mov si, FATBUF ; set DS:SI to the FAT chain
|
||||||
|
|
||||||
@ -369,16 +367,17 @@ cluster_next: lodsw ; AX = next cluster to read
|
|||||||
|
|
||||||
|
|
||||||
boot_error: call print
|
boot_error: call print
|
||||||
db 13,10,"BOOT err!",0
|
db " err",0
|
||||||
|
|
||||||
xor ah,ah
|
xor ah,ah
|
||||||
int 0x16 ; wait for a key
|
int 0x16 ; wait for a key
|
||||||
int 0x19 ; reboot the machine
|
int 0x19 ; reboot the machine
|
||||||
|
|
||||||
boot_success: call print
|
boot_success:
|
||||||
db " GO! ",0
|
;call print
|
||||||
|
;db " GO! ",0
|
||||||
mov bl, [drive]
|
mov bl, [drive]
|
||||||
jmp word LOADSEG:0
|
jmp far [loadsegoff_60]
|
||||||
|
|
||||||
|
|
||||||
; prints text after call to this function.
|
; prints text after call to this function.
|
||||||
@ -406,13 +405,17 @@ print1: lodsb ; get token
|
|||||||
; ES:BX points one byte after the last byte read.
|
; ES:BX points one byte after the last byte read.
|
||||||
|
|
||||||
readDisk: push si
|
readDisk: push si
|
||||||
read_next: push dx
|
|
||||||
push ax
|
mov LBA_SECTOR_0,ax
|
||||||
|
mov LBA_SECTOR_16,dx
|
||||||
|
mov word [LBA_SEG],es
|
||||||
|
mov word [LBA_OFF],bx
|
||||||
|
|
||||||
|
read_next:
|
||||||
|
|
||||||
;******************** LBA_READ *******************************
|
;******************** LBA_READ *******************************
|
||||||
|
|
||||||
; check for LBA support
|
; check for LBA support
|
||||||
push bx
|
|
||||||
|
|
||||||
mov ah,041h ;
|
mov ah,041h ;
|
||||||
mov bx,055aah ;
|
mov bx,055aah ;
|
||||||
@ -424,51 +427,30 @@ read_next: push dx
|
|||||||
int 0x13
|
int 0x13
|
||||||
jc read_normal_BIOS
|
jc read_normal_BIOS
|
||||||
|
|
||||||
sub bx,0aa55h
|
shr cx,1 ; CX must have 1 bit set
|
||||||
|
|
||||||
|
sbb bx,0aa55h - 1 ; tests for carry (from shr) too!
|
||||||
jne read_normal_BIOS
|
jne read_normal_BIOS
|
||||||
|
|
||||||
shr cx,1 ; CX must have 1 bit set
|
|
||||||
jnc read_normal_BIOS
|
|
||||||
|
|
||||||
; OK, drive seems to support LBA addressing
|
; OK, drive seems to support LBA addressing
|
||||||
|
|
||||||
lea si,[LBA_DISK_PARAMETER_BLOCK]
|
lea si,[LBA_PACKET]
|
||||||
|
|
||||||
; setup LBA disk block
|
; setup LBA disk block
|
||||||
mov [si+12],bx
|
mov LBA_SECTOR_32,bx
|
||||||
mov [si+14],bx
|
mov LBA_SECTOR_48,bx
|
||||||
|
|
||||||
pop bx
|
|
||||||
|
|
||||||
pop ax
|
|
||||||
pop dx
|
|
||||||
push dx
|
|
||||||
push ax
|
|
||||||
mov [si+ 8],ax
|
|
||||||
mov [si+10],dx
|
|
||||||
mov [si+4],bx
|
|
||||||
mov [si+6],es
|
|
||||||
|
|
||||||
|
|
||||||
mov ah,042h
|
mov ah,042h
|
||||||
jmp short do_int13_read
|
jmp short do_int13_read
|
||||||
|
|
||||||
LBA_DISK_PARAMETER_BLOCK:
|
|
||||||
db 10h ; constant size of block
|
|
||||||
db 0
|
|
||||||
dw 1 ; 1 sector read
|
|
||||||
; and overflow into code !!!
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
read_normal_BIOS:
|
read_normal_BIOS:
|
||||||
pop bx
|
|
||||||
|
|
||||||
pop ax
|
|
||||||
pop dx
|
|
||||||
push dx
|
|
||||||
push ax
|
|
||||||
;******************** END OF LBA_READ ************************
|
;******************** END OF LBA_READ ************************
|
||||||
|
mov ax,LBA_SECTOR_0
|
||||||
|
mov dx,LBA_SECTOR_16
|
||||||
|
|
||||||
|
|
||||||
;
|
;
|
||||||
@ -509,93 +491,37 @@ read_normal_BIOS:
|
|||||||
inc ah ; sector offset from 1
|
inc ah ; sector offset from 1
|
||||||
or cl, ah ; merge sector into cylinder
|
or cl, ah ; merge sector into cylinder
|
||||||
|
|
||||||
%ifdef MULTI_SEC_READ
|
les bx,[LBA_OFF]
|
||||||
; Calculate how many sectors can be transfered in this read
|
|
||||||
; due to dma boundary conditions.
|
|
||||||
push dx
|
|
||||||
|
|
||||||
mov si, di ; temp register save
|
|
||||||
; this computes remaining bytes because of modulo 65536
|
|
||||||
; nature of dma boundary condition
|
|
||||||
mov ax, bx ; get offset pointer
|
|
||||||
neg ax ; and convert to bytes
|
|
||||||
jz ax_min_1 ; started at seg:0, skip ahead
|
|
||||||
|
|
||||||
xor dx, dx ; convert to sectors
|
|
||||||
div word [bsBytesPerSec]
|
|
||||||
|
|
||||||
cmp ax, di ; check remainder vs. asked
|
|
||||||
jb ax_min_1 ; less, skip ahead
|
|
||||||
mov si, ax ; transfer only what we can
|
|
||||||
|
|
||||||
ax_min_1: pop dx
|
|
||||||
|
|
||||||
; Check that request sectors do not exceed track boundary
|
|
||||||
mov si, [sectPerTrack]
|
|
||||||
inc si
|
|
||||||
mov ax, cx ; get the sector/cyl byte
|
|
||||||
and ax, 0x3f ; and mask out sector
|
|
||||||
sub si, ax ; si has how many we can read
|
|
||||||
mov ax, di
|
|
||||||
cmp si, di ; see if asked <= available
|
|
||||||
jge ax_min_2
|
|
||||||
mov ax, si ; get what can be xfered
|
|
||||||
|
|
||||||
ax_min_2: push ax
|
|
||||||
mov ah, 2
|
|
||||||
mov dl, [drive]
|
|
||||||
int 0x13
|
|
||||||
pop ax
|
|
||||||
%else
|
|
||||||
mov ax, 0x0201
|
mov ax, 0x0201
|
||||||
do_int13_read:
|
do_int13_read:
|
||||||
mov dl, [drive]
|
mov dl, [drive]
|
||||||
int 0x13
|
int 0x13
|
||||||
%endif
|
|
||||||
|
|
||||||
read_finished:
|
read_finished:
|
||||||
jnc read_ok ; jump if no error
|
jnc read_ok ; jump if no error
|
||||||
xor ah, ah ; else, reset floppy
|
xor ah, ah ; else, reset floppy
|
||||||
int 0x13
|
int 0x13
|
||||||
pop ax
|
|
||||||
pop dx ; and...
|
|
||||||
read_next_chained:
|
read_next_chained:
|
||||||
jmp short read_next ; read the same sector again
|
jmp short read_next ; read the same sector again
|
||||||
|
|
||||||
read_ok:
|
read_ok:
|
||||||
%ifdef MULTI_SEC_READ
|
mov ax, word [bsBytesPerSec]
|
||||||
mul word [bsBytesPerSec] ; add number of bytes read to BX
|
div byte[LBA_PACKET] ; luckily 16 !!
|
||||||
add bx, ax
|
add word [LBA_SEG], ax
|
||||||
%else
|
|
||||||
add bx, word [bsBytesPerSec]
|
|
||||||
%endif
|
|
||||||
jnc no_incr_es ; if overflow...
|
|
||||||
|
|
||||||
mov ax, es
|
add LBA_SECTOR_0, byte 1
|
||||||
add ah, 0x10 ; ...add 1000h to ES
|
adc LBA_SECTOR_16, byte 0 ; DX:AX = next sector to read
|
||||||
mov es, ax
|
|
||||||
|
|
||||||
no_incr_es: pop ax
|
|
||||||
pop dx ; DX:AX = last sector number
|
|
||||||
|
|
||||||
%ifdef MULTI_SEC_READ
|
|
||||||
add ax, si
|
|
||||||
adc dx, byte 0 ; DX:AX = next sector to read
|
|
||||||
sub di,si ; if there is anything left to read,
|
|
||||||
jg read_next ; continue
|
|
||||||
%else
|
|
||||||
add ax, byte 1
|
|
||||||
adc dx, byte 0 ; DX:AX = next sector to read
|
|
||||||
dec di ; if there is anything left to read,
|
dec di ; if there is anything left to read,
|
||||||
jnz read_next_chained ; continue
|
jnz read_next_chained ; continue
|
||||||
%endif
|
|
||||||
|
|
||||||
clc
|
mov es,word [LBA_SEG]
|
||||||
|
; clear carry: unnecessary since adc clears it
|
||||||
pop si
|
pop si
|
||||||
ret
|
ret
|
||||||
|
|
||||||
filename db "KERNEL SYS"
|
filename db "KERNEL SYS"
|
||||||
|
|
||||||
|
|
||||||
times 0x01fe-$+$$ db 0
|
times 0x01fe-$+$$ db 0
|
||||||
|
|
||||||
sign dw 0xAA55
|
sign dw 0xAA55
|
||||||
|
@ -57,34 +57,33 @@ Entry: jmp short real_start
|
|||||||
%define xrootClst bp+0x2c ; Starting cluster of root directory
|
%define xrootClst bp+0x2c ; Starting cluster of root directory
|
||||||
%define drive bp+0x40 ; Drive number
|
%define drive bp+0x40 ; Drive number
|
||||||
|
|
||||||
|
times 0x5a-$+$$ db 0
|
||||||
|
|
||||||
%define LOADSEG 0x0060
|
%define LOADSEG 0x0060
|
||||||
|
|
||||||
%define FATSEG 0x2000
|
%define FATSEG 0x2000
|
||||||
|
|
||||||
%define fat_sector bp+0x48 ; last accessed sector of the FAT
|
%define fat_sector bp+0x48 ; last accessed sector of the FAT
|
||||||
dd 0
|
|
||||||
|
|
||||||
times 0x5a-$+$$ db 0
|
%define loadsegoff_60 bp+0x5a ; FAR pointer = 60:0
|
||||||
%define fat_start bp+0x5a ; first FAT sector
|
|
||||||
dd 0
|
|
||||||
%define data_start bp+0x5e ; first data sector
|
|
||||||
dd 0
|
|
||||||
%define fat_secmask bp+0x62 ; number of clusters in a FAT sector - 1
|
|
||||||
dw 0
|
|
||||||
%define fat_secshift bp+0x64 ; fat_secmask+1 = 2^fat_secshift
|
|
||||||
dw 0
|
dw 0
|
||||||
|
%define loadseg_60 bp+0x5c
|
||||||
|
dw LOADSEG
|
||||||
|
|
||||||
|
%define fat_start bp+0x5e ; first FAT sector
|
||||||
|
%define data_start bp+0x62 ; first data sector
|
||||||
|
%define fat_secmask bp+0x66 ; number of clusters in a FAT sector - 1
|
||||||
|
%define fat_secshift bp+0x68 ; fat_secmask+1 = 2^fat_secshift
|
||||||
|
|
||||||
;-----------------------------------------------------------------------
|
;-----------------------------------------------------------------------
|
||||||
; ENTRY
|
; ENTRY
|
||||||
;-----------------------------------------------------------------------
|
;-----------------------------------------------------------------------
|
||||||
|
|
||||||
real_start: cld
|
real_start: cld
|
||||||
|
cli
|
||||||
sub ax, ax
|
sub ax, ax
|
||||||
mov ds, ax
|
mov ds, ax
|
||||||
mov bp, 0x7c00
|
mov bp, 0x7c00
|
||||||
mov ss, ax ; initialize stack
|
|
||||||
lea sp, [bp-0x20]
|
|
||||||
int 0x13 ; reset drive
|
|
||||||
|
|
||||||
mov ax, 0x1FE0
|
mov ax, 0x1FE0
|
||||||
mov es, ax
|
mov es, ax
|
||||||
@ -95,18 +94,59 @@ real_start: cld
|
|||||||
jmp word 0x1FE0:cont
|
jmp word 0x1FE0:cont
|
||||||
|
|
||||||
cont: mov ds, ax
|
cont: mov ds, ax
|
||||||
mov ss, ax
|
mov ss, ax
|
||||||
|
lea sp, [bp-0x20]
|
||||||
|
sti
|
||||||
mov [drive], dl ; BIOS passes drive number in DL
|
mov [drive], dl ; BIOS passes drive number in DL
|
||||||
|
|
||||||
call print
|
; call print
|
||||||
db "Loading FreeDOS ",0
|
; db "Loading ",0
|
||||||
|
|
||||||
|
; Calc Params
|
||||||
|
; Fat_Start
|
||||||
|
mov si, word [nHidden]
|
||||||
|
mov di, word [nHidden+2]
|
||||||
|
add si, word [bsResSectors]
|
||||||
|
adc di, byte 0
|
||||||
|
|
||||||
|
mov word [fat_start], si
|
||||||
|
mov word [fat_start+2], di
|
||||||
|
; Data_Start
|
||||||
|
mov al, [bsFATs]
|
||||||
|
cbw
|
||||||
|
push ax
|
||||||
|
mul word [xsectPerFat+2]
|
||||||
|
add di, ax
|
||||||
|
pop ax
|
||||||
|
mul word [xsectPerFat]
|
||||||
|
add ax, si
|
||||||
|
adc dx, di
|
||||||
|
mov word[data_start], ax
|
||||||
|
mov word[data_start+2], dx
|
||||||
|
; fat_secmask
|
||||||
|
mov ax, word[bsBytesPerSec]
|
||||||
|
shr ax, 1
|
||||||
|
shr ax, 1
|
||||||
|
dec ax
|
||||||
|
mov word [fat_secmask], ax
|
||||||
|
; fat_secshift
|
||||||
|
; cx = temp
|
||||||
|
; ax = fat_secshift
|
||||||
|
xchg ax, cx ; cx = 0 after movsw
|
||||||
|
inc cx
|
||||||
|
secshift: inc ax
|
||||||
|
shr cx, 1
|
||||||
|
cmp cx, 1
|
||||||
|
jne secshift
|
||||||
|
mov byte [fat_secshift], al
|
||||||
|
dec cx
|
||||||
|
|
||||||
; FINDFILE: Searches for the file in the root directory.
|
; FINDFILE: Searches for the file in the root directory.
|
||||||
;
|
;
|
||||||
; Returns:
|
; Returns:
|
||||||
; DX:AX = first cluster of file
|
; DX:AX = first cluster of file
|
||||||
|
|
||||||
mov word [fat_sector], cx ; CX is 0 after movsw
|
mov word [fat_sector], cx ; CX is 0 after "dec"
|
||||||
mov word [fat_sector + 2], cx
|
mov word [fat_sector + 2], cx
|
||||||
|
|
||||||
mov ax, word [xrootClst]
|
mov ax, word [xrootClst]
|
||||||
@ -120,9 +160,7 @@ ff_next_cluster:
|
|||||||
ff_next_sector:
|
ff_next_sector:
|
||||||
push bx ; save sector count
|
push bx ; save sector count
|
||||||
|
|
||||||
mov bx, LOADSEG
|
les bx, [loadsegoff_60]
|
||||||
mov es, bx
|
|
||||||
sub bx, bx
|
|
||||||
call readDisk
|
call readDisk
|
||||||
push dx ; save sector
|
push dx ; save sector
|
||||||
push ax
|
push ax
|
||||||
@ -171,10 +209,7 @@ c6:
|
|||||||
call next_cluster
|
call next_cluster
|
||||||
jmp c5
|
jmp c5
|
||||||
|
|
||||||
|
boot_error:
|
||||||
boot_error: call print
|
|
||||||
db 13,10,"BOOT error!",13,10,0
|
|
||||||
|
|
||||||
xor ah,ah
|
xor ah,ah
|
||||||
int 0x16 ; wait for a key
|
int 0x16 ; wait for a key
|
||||||
int 0x19 ; reboot the machine
|
int 0x19 ; reboot the machine
|
||||||
@ -230,7 +265,7 @@ cn_exit:
|
|||||||
|
|
||||||
boot_success:
|
boot_success:
|
||||||
mov bl, [drive]
|
mov bl, [drive]
|
||||||
jmp word LOADSEG:0
|
jmp far [loadsegoff_60]
|
||||||
|
|
||||||
; Convert cluster to the absolute sector
|
; Convert cluster to the absolute sector
|
||||||
;input:
|
;input:
|
||||||
@ -277,7 +312,6 @@ print1: lodsb ; get token
|
|||||||
jne print_1char ; until done
|
jne print_1char ; until done
|
||||||
ret ; and jump to it
|
ret ; and jump to it
|
||||||
|
|
||||||
|
|
||||||
;input:
|
;input:
|
||||||
; DX:AX - 32-bit DOS sector number
|
; DX:AX - 32-bit DOS sector number
|
||||||
; ES:BX - destination buffer
|
; ES:BX - destination buffer
|
||||||
|
405
boot/boot32lb.asm
Normal file
405
boot/boot32lb.asm
Normal file
@ -0,0 +1,405 @@
|
|||||||
|
; This is an LBA-enabled FreeDOS FAT32 boot sector (single sector!).
|
||||||
|
; You can use and copy source code and binaries under the terms of the
|
||||||
|
; GNU Public License (GPL), version 2 or newer. See www.gnu.org for more.
|
||||||
|
|
||||||
|
; Based on earlier work by FreeDOS kernel hackers, modified heavily by
|
||||||
|
; Eric Auer and Jon Gentle in 7 / 2003.
|
||||||
|
;
|
||||||
|
; Features: Uses LBA and calculates all variables from BPB/EBPB data,
|
||||||
|
; thus making partition move / resize / image-restore easier. FreeDOS
|
||||||
|
; can boot from FAT32 partitions which start > 8 GB boundary with this
|
||||||
|
; boot sector. Disk geometry knowledge is not needed for booting.
|
||||||
|
;
|
||||||
|
; Windows uses 2-3 sectors for booting (sector stage, statistics sector,
|
||||||
|
; filesystem stage). Only using 1 sector for FreeDOS makes multi-booting
|
||||||
|
; of FreeDOS and Windows on the same filesystem easier.
|
||||||
|
;
|
||||||
|
; Requirements: LBA BIOS and 386 or better CPU. Use the older CHS-only
|
||||||
|
; boot sector if you want FAT32 on really old PCs (problems: you cannot
|
||||||
|
; boot from > 8 GB boundary, cannot move / resize / ... without applying
|
||||||
|
; SYS again if you use the CHS-only FAT32 boot sector).
|
||||||
|
;
|
||||||
|
; FAT12 / FAT16 hints: Use the older CHS-only boot sector unless you
|
||||||
|
; have to boot from > 8 GB. The LBA-and-CHS FAT12 / FAT16 boot sector
|
||||||
|
; needs applying SYS again after move / resize / ... a variant of that
|
||||||
|
; boot sector without CHS support but with better move / resize / ...
|
||||||
|
; support would be good for use on LBA harddisks.
|
||||||
|
|
||||||
|
|
||||||
|
; Memory layout for the FreeDOS FAT32 single stage boot process:
|
||||||
|
|
||||||
|
; ...
|
||||||
|
; |-------| 1FE0:7E00
|
||||||
|
; |BOOTSEC|
|
||||||
|
; |RELOC. |
|
||||||
|
; |-------| 1FE0:7C00
|
||||||
|
; ...
|
||||||
|
; |-------| 2000:0200
|
||||||
|
; | FAT | (only 1 sector buffered)
|
||||||
|
; |-------| 2000:0000
|
||||||
|
; ...
|
||||||
|
; |-------| 0000:7E00
|
||||||
|
; |BOOTSEC| overwritten by the kernel, so the
|
||||||
|
; |ORIGIN | bootsector relocates itself up...
|
||||||
|
; |-------| 0000:7C00
|
||||||
|
; ...
|
||||||
|
; |-------|
|
||||||
|
; |KERNEL | maximum size 134k (overwrites bootsec origin)
|
||||||
|
; |LOADED | (holds 1 sector directory buffer before kernel load)
|
||||||
|
; |-------| 0060:0000
|
||||||
|
; ...
|
||||||
|
|
||||||
|
segment .text
|
||||||
|
|
||||||
|
org 0x7c00 ; this is a boot sector
|
||||||
|
|
||||||
|
Entry: jmp short real_start
|
||||||
|
nop
|
||||||
|
|
||||||
|
; bp is initialized to 7c00h
|
||||||
|
; %define bsOemName bp+0x03 ; OEM label (8)
|
||||||
|
%define bsBytesPerSec bp+0x0b ; bytes/sector (dw)
|
||||||
|
%define bsSecPerClust bp+0x0d ; sectors/allocation unit (db)
|
||||||
|
%define bsResSectors bp+0x0e ; # reserved sectors (dw)
|
||||||
|
%define bsFATs bp+0x10 ; # of fats (db)
|
||||||
|
; %define bsRootDirEnts bp+0x11 ; # of root dir entries (dw, 0 for FAT32)
|
||||||
|
; (FAT32 has root dir in a cluster chain)
|
||||||
|
; %define bsSectors bp+0x13 ; # sectors total in image (dw, 0 for FAT32)
|
||||||
|
; (if 0 use nSectorHuge even if FAT16)
|
||||||
|
; %define bsMedia bp+0x15 ; media descriptor: fd=2side9sec, etc... (db)
|
||||||
|
; %define sectPerFat bp+0x16 ; # sectors in a fat (dw, 0 for FAT32)
|
||||||
|
; (FAT32 always uses xsectPerFat)
|
||||||
|
%define sectPerTrack bp+0x18 ; # sectors/track
|
||||||
|
; %define nHeads bp+0x1a ; # heads (dw)
|
||||||
|
%define nHidden bp+0x1c ; # hidden sectors (dd)
|
||||||
|
; %define nSectorHuge bp+0x20 ; # sectors if > 65536 (dd)
|
||||||
|
%define xsectPerFat bp+0x24 ; Sectors/Fat (dd)
|
||||||
|
; +0x28 dw flags (for fat mirroring)
|
||||||
|
; +0x2a dw filesystem version (usually 0)
|
||||||
|
%define xrootClst bp+0x2c ; Starting cluster of root directory (dd)
|
||||||
|
; +0x30 dw -1 or sector number of fs.-info sector
|
||||||
|
; +0x32 dw -1 or sector number of boot sector backup
|
||||||
|
; (+0x34 .. +0x3f reserved)
|
||||||
|
%define drive bp+0x40 ; Drive number
|
||||||
|
|
||||||
|
%define LOADSEG 0x0060
|
||||||
|
|
||||||
|
%define FATSEG 0x2000
|
||||||
|
|
||||||
|
%define fat_secshift fat_afterss-1 ; each fat sector describes 2^??
|
||||||
|
; clusters (db) (selfmodifying)
|
||||||
|
%define fat_sector bp+0x44 ; last accessed FAT sector (dd)
|
||||||
|
; (overwriting unused bytes)
|
||||||
|
%define fat_start bp+0x48 ; first FAT sector (dd)
|
||||||
|
; (overwriting unused bytes)
|
||||||
|
%define data_start bp+0x4c ; first data sector (dd)
|
||||||
|
; (overwriting unused bytes)
|
||||||
|
|
||||||
|
times 0x5a-$+$$ db 0
|
||||||
|
; not used: [0x42] = byte 0x29 (ext boot param flag)
|
||||||
|
; [0x43] = dword serial
|
||||||
|
; [0x47] = label (padded with 00, 11 bytes)
|
||||||
|
; [0x52] = "FAT32",32,32,32 (not used by Windows)
|
||||||
|
; ([0x5a] is where FreeDOS parts start)
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------------
|
||||||
|
; ENTRY
|
||||||
|
;-----------------------------------------------------------------------
|
||||||
|
|
||||||
|
real_start: cld
|
||||||
|
sub ax, ax
|
||||||
|
mov ds, ax
|
||||||
|
lss sp, [mystack] ; initialize stack
|
||||||
|
int 0x13 ; reset drive
|
||||||
|
|
||||||
|
mov ax, 0x1FE0
|
||||||
|
mov es, ax
|
||||||
|
mov si, sp
|
||||||
|
mov di, sp
|
||||||
|
mov bp, sp ; bp-relative parameter addresses used
|
||||||
|
mov cx, 0x0100
|
||||||
|
rep movsw ; move boot code to the 0x1FE0:0x0000
|
||||||
|
jmp word 0x1FE0:cont
|
||||||
|
|
||||||
|
; -------------
|
||||||
|
|
||||||
|
cont: mov ds, ax
|
||||||
|
mov ss, ax ; stack and BP-relative moves up, too
|
||||||
|
mov [drive], dl ; BIOS passes drive number in DL
|
||||||
|
|
||||||
|
mov si, msg_LoadFreeDOS
|
||||||
|
call print ; modifies AX BX SI
|
||||||
|
|
||||||
|
|
||||||
|
; -------------
|
||||||
|
|
||||||
|
; CALCPARAMS: figure out where FAT and DATA area starts
|
||||||
|
; (modifies EAX EDX, sets fat_start and data_start variables)
|
||||||
|
|
||||||
|
calc_params: xor eax, eax
|
||||||
|
mov [fat_sector], eax ; init buffer status
|
||||||
|
|
||||||
|
; first, find fat_start:
|
||||||
|
mov ax, [bsResSectors] ; no movzx eax, word... needed
|
||||||
|
add eax, [nHidden]
|
||||||
|
mov [fat_start], eax ; first FAT sector
|
||||||
|
mov [data_start], eax ; (only first part of value)
|
||||||
|
|
||||||
|
; next, find data_start:
|
||||||
|
mov eax, [bsFATs] ; no movzx ... byte needed:
|
||||||
|
; the 2 dw after the bsFATs db are 0 by FAT32 definition :-).
|
||||||
|
imul dword [xsectPerFat] ; (also changes edx)
|
||||||
|
add [data_start], eax ; first DATA sector
|
||||||
|
; (adding in RAM is shorter!)
|
||||||
|
|
||||||
|
; finally, find fat_secshift:
|
||||||
|
mov ax, 512 ; default sector size (means default shift)
|
||||||
|
; shift = log2(secSize) - log2(fatEntrySize)
|
||||||
|
;--- mov cl, 9-2 ; shift is 7 for 512 bytes per sector
|
||||||
|
fatss_scan: cmp ax, [bsBytesPerSec]
|
||||||
|
jz fatss_found
|
||||||
|
add ax,ax
|
||||||
|
;--- inc cx
|
||||||
|
inc word [fat_secshift] ;XXX ; initially 9-2 (byte!)
|
||||||
|
jmp short fatss_scan ; try other sector sizes
|
||||||
|
fatss_found:
|
||||||
|
;--- mov [fat_secshift], cl
|
||||||
|
|
||||||
|
; -------------
|
||||||
|
|
||||||
|
; FINDFILE: Searches for the file in the root directory.
|
||||||
|
; Returns: EAX = first cluster of file
|
||||||
|
|
||||||
|
mov eax, [xrootClst] ; root dir cluster
|
||||||
|
|
||||||
|
ff_next_clust: push eax ; save cluster
|
||||||
|
call convert_cluster
|
||||||
|
jc boot_error ; EOC encountered
|
||||||
|
; EDX is clust/sector, EAX is sector
|
||||||
|
|
||||||
|
ff_next_sector: mov bx, LOADSEG
|
||||||
|
mov es, bx
|
||||||
|
sub bx, bx ; load to loadseg:0
|
||||||
|
call readDisk
|
||||||
|
;--- push eax ; save sector
|
||||||
|
|
||||||
|
;--- xor ax, ax ; first dir. entry in this sector
|
||||||
|
xor di, di ;XXX
|
||||||
|
|
||||||
|
; Search for KERNEL.SYS file name, and find start cluster.
|
||||||
|
ff_next_entry: mov cx, 11
|
||||||
|
mov si, filename
|
||||||
|
;--- mov di, ax
|
||||||
|
repe cmpsb
|
||||||
|
jz ff_done ; note that di now is at dirent+11
|
||||||
|
|
||||||
|
;--- add ax, 0x20 ; next directory entry
|
||||||
|
;--- cmp ax, [bsBytesPerSec] ; end of sector reached?
|
||||||
|
add di, byte 0x20 ;XXX
|
||||||
|
and di, byte -0x20 ; 0xffe0 ;XXX
|
||||||
|
cmp di, [bsBytesPerSec] ;XXX
|
||||||
|
jnz ff_next_entry
|
||||||
|
|
||||||
|
;--- pop eax ; restore sector
|
||||||
|
dec dx ; next sector in cluster
|
||||||
|
jnz ff_next_sector
|
||||||
|
|
||||||
|
ff_walk_fat: pop eax ; restore current cluster
|
||||||
|
call next_cluster ; find next cluster
|
||||||
|
jmp ff_next_clust
|
||||||
|
|
||||||
|
ff_done: push word [es:di+0x14-11] ; get cluster number HI
|
||||||
|
push word [es:di+0x1A-11] ; get cluster number LO
|
||||||
|
pop eax ; convert to 32bit
|
||||||
|
|
||||||
|
sub bx, bx ; ES points to LOADSEG
|
||||||
|
; (kernel -> ES:BX)
|
||||||
|
|
||||||
|
; -------------
|
||||||
|
|
||||||
|
read_kernel: push eax
|
||||||
|
call convert_cluster
|
||||||
|
jc boot_success ; EOC encountered - done
|
||||||
|
; EDX is sectors in cluster, EAX is sector
|
||||||
|
|
||||||
|
rk_in_cluster: call readDisk
|
||||||
|
dec dx
|
||||||
|
jnz rk_in_cluster ; loop over sect. in cluster
|
||||||
|
|
||||||
|
rk_walk_fat: pop eax
|
||||||
|
call next_cluster
|
||||||
|
jmp read_kernel
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------------
|
||||||
|
|
||||||
|
boot_success: mov bl, [drive]
|
||||||
|
jmp word LOADSEG:0
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------------
|
||||||
|
|
||||||
|
boot_error: mov si, msg_BootError
|
||||||
|
call print ; modifies AX BX SI
|
||||||
|
|
||||||
|
wait_key: xor ah,ah
|
||||||
|
int 0x16 ; wait for a key
|
||||||
|
reboot: int 0x19 ; reboot the machine
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------------
|
||||||
|
|
||||||
|
; given a cluster number, find the number of the next cluster in
|
||||||
|
; the FAT chain. Needs fat_secshift and fat_start.
|
||||||
|
; input: EAX - cluster
|
||||||
|
; output: EAX - next cluster
|
||||||
|
|
||||||
|
next_cluster: push es
|
||||||
|
push di
|
||||||
|
push bx
|
||||||
|
|
||||||
|
mov di, ax
|
||||||
|
shl di, 2 ; 32bit FAT
|
||||||
|
|
||||||
|
push ax
|
||||||
|
mov ax, [bsBytesPerSec]
|
||||||
|
dec ax
|
||||||
|
and di, ax ; mask to sector size
|
||||||
|
pop ax
|
||||||
|
|
||||||
|
shr eax, 7 ; e.g. 9-2 for 512 by/sect.
|
||||||
|
fat_afterss: ; selfmodifying code: previous byte is patched!
|
||||||
|
; (to hold the fat_secshift value)
|
||||||
|
|
||||||
|
add eax, [fat_start] ; absolute sector number now
|
||||||
|
|
||||||
|
mov bx, FATSEG
|
||||||
|
mov es, bx
|
||||||
|
sub bx, bx
|
||||||
|
|
||||||
|
cmp eax, [fat_sector] ; already buffered?
|
||||||
|
jz cn_buffered
|
||||||
|
mov [fat_sector],eax ; number of buffered sector
|
||||||
|
call readDisk
|
||||||
|
|
||||||
|
cn_buffered: and byte [es:di+3],0x0f ; mask out top 4 bits
|
||||||
|
mov eax, [es:di] ; read next cluster number
|
||||||
|
|
||||||
|
pop bx
|
||||||
|
pop di
|
||||||
|
pop es
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------------
|
||||||
|
|
||||||
|
; Convert cluster number to the absolute sector number
|
||||||
|
; ... or return carry if EndOfChain! Needs data_start.
|
||||||
|
; input: EAX - target cluster
|
||||||
|
; output: EAX - absolute sector
|
||||||
|
; EDX - [bsSectPerClust] (byte)
|
||||||
|
; carry clear
|
||||||
|
; (if carry set, EAX/EDX unchanged, end of chain)
|
||||||
|
|
||||||
|
convert_cluster:
|
||||||
|
cmp eax, 0x0ffffff8 ; if end of cluster chain...
|
||||||
|
jnb end_of_chain
|
||||||
|
|
||||||
|
; sector = (cluster-2) * clustersize + data_start
|
||||||
|
dec eax
|
||||||
|
dec eax
|
||||||
|
|
||||||
|
movzx edx, byte [bsSecPerClust]
|
||||||
|
push edx
|
||||||
|
mul edx
|
||||||
|
pop edx
|
||||||
|
add eax, [data_start]
|
||||||
|
; here, carry is unset (unless parameters are wrong)
|
||||||
|
ret
|
||||||
|
|
||||||
|
end_of_chain: stc ; indicate EOC by carry
|
||||||
|
ret
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------------
|
||||||
|
|
||||||
|
; PRINT - prints string DS:SI
|
||||||
|
; modifies AX BX SI
|
||||||
|
|
||||||
|
printchar: xor bx, bx ; video page 0
|
||||||
|
mov ah, 0x0e ; print it
|
||||||
|
int 0x10 ; via TTY mode
|
||||||
|
print: lodsb ; get token
|
||||||
|
cmp al, 0 ; end of string?
|
||||||
|
jne printchar ; until done
|
||||||
|
ret ; return to caller
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------------
|
||||||
|
|
||||||
|
; Read a sector from disk, using LBA
|
||||||
|
; input: EAX - 32-bit DOS sector number
|
||||||
|
; ES:BX - destination buffer
|
||||||
|
; (will be filled with 1 sector of data)
|
||||||
|
; output: ES:BX points one byte after the last byte read.
|
||||||
|
; EAX - next sector
|
||||||
|
|
||||||
|
readDisk: push dx
|
||||||
|
push si
|
||||||
|
push di
|
||||||
|
|
||||||
|
read_next: push eax ; would ax be enough?
|
||||||
|
mov di, sp ; remember parameter block end
|
||||||
|
|
||||||
|
;--- db 0x66 ; operand size override (push dword)
|
||||||
|
push byte 0 ;XXX ; other half of the 32 bits at [C]
|
||||||
|
; (did not trust "o32 push byte 0" opcode)
|
||||||
|
push byte 0 ; [C] sector number high 32bit
|
||||||
|
push eax ; [8] sector number low 32bit
|
||||||
|
push es ; [6] buffer segment
|
||||||
|
push bx ; [4] buffer offset
|
||||||
|
push byte 1 ; [2] 1 sector (word)
|
||||||
|
push byte 16 ; [0] size of parameter block (word)
|
||||||
|
mov si, sp
|
||||||
|
mov dl, [drive]
|
||||||
|
mov ah, 42h ; disk read
|
||||||
|
int 0x13
|
||||||
|
|
||||||
|
mov sp, di ; remove parameter block from stack
|
||||||
|
; (without changing flags!)
|
||||||
|
pop eax ; would ax be enough?
|
||||||
|
|
||||||
|
jnc read_ok ; jump if no error
|
||||||
|
|
||||||
|
push ax ; !!
|
||||||
|
xor ah, ah ; else, reset and retry
|
||||||
|
int 0x13
|
||||||
|
pop ax ; !!
|
||||||
|
jmp read_next
|
||||||
|
|
||||||
|
read_ok: inc eax ; next sector
|
||||||
|
add bx, word [bsBytesPerSec]
|
||||||
|
jnc no_incr_es ; if overflow...
|
||||||
|
|
||||||
|
mov dx, es
|
||||||
|
add dh, 0x10 ; ...add 1000h to ES
|
||||||
|
mov es, dx
|
||||||
|
|
||||||
|
no_incr_es: pop di
|
||||||
|
pop si
|
||||||
|
pop dx
|
||||||
|
ret
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------------
|
||||||
|
|
||||||
|
msg_LoadFreeDOS db "Loading FreeDOS ",0
|
||||||
|
msg_BootError db "No "
|
||||||
|
; currently, only "kernel.sys not found" gives a message,
|
||||||
|
; but read errors in data or root or fat sectors do not.
|
||||||
|
|
||||||
|
filename db "KERNEL SYS"
|
||||||
|
|
||||||
|
msg_BootErrorPart2:
|
||||||
|
db " ???",0
|
||||||
|
|
||||||
|
times 0x01fa-$+$$ db 0
|
||||||
|
|
||||||
|
mystack dw 0x7c00 ; the 0 for SS overlaps into sign!
|
||||||
|
; (so we can LSS SP to 0:7c00)
|
||||||
|
sign dw 0, 0xAA55
|
||||||
|
; Win9x uses all 4 bytes as magic value here.
|
@ -7,19 +7,22 @@
|
|||||||
|
|
||||||
!include "..\mkfiles\generic.mak"
|
!include "..\mkfiles\generic.mak"
|
||||||
|
|
||||||
production: b_fat12.bin b_fat16.bin b_fat32.bin
|
production: fat12com.bin fat16com.bin fat32chs.bin fat32lba.bin
|
||||||
|
|
||||||
b_fat12.bin: boot.asm
|
fat12com.bin: boot.asm
|
||||||
$(NASM) -dISFAT12 boot.asm -ob_fat12.bin
|
$(NASM) -dISFAT12 boot.asm -ofat12com.bin
|
||||||
|
|
||||||
b_fat16.bin: boot.asm
|
fat16com.bin: boot.asm
|
||||||
$(NASM) -dISFAT16 boot.asm -ob_fat16.bin
|
$(NASM) -dISFAT16 boot.asm -ofat16com.bin
|
||||||
|
|
||||||
b_fat32.bin: boot32.asm
|
fat32chs.bin: boot32.asm
|
||||||
$(NASM) boot32.asm -ob_fat32.bin
|
$(NASM) boot32.asm -ofat32chs.bin
|
||||||
|
|
||||||
|
fat32lba.bin: boot32lb.asm
|
||||||
|
$(NASM) boot32lb.asm -ofat32lba.bin
|
||||||
|
|
||||||
clobber: clean
|
clobber: clean
|
||||||
-$(RM) b_fat12.bin b_fat16.bin b_fat32.bin status.me
|
-$(RM) *.bin status.me
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
-$(RM) *.lst *.map *.bak *.obj
|
-$(RM) *.lst *.map *.bak *.obj
|
||||||
|
19
sys/makefile
19
sys/makefile
@ -25,14 +25,17 @@ bin2c.com: bin2c.c
|
|||||||
..\bin\sys.com: sys.com
|
..\bin\sys.com: sys.com
|
||||||
copy sys.com ..\bin
|
copy sys.com ..\bin
|
||||||
|
|
||||||
b_fat12.h: ..\boot\b_fat12.bin bin2c.com
|
fat12com.h: ..\boot\fat12com.bin bin2c.com
|
||||||
.\bin2c ..\boot\b_fat12.bin b_fat12.h b_fat12
|
.\bin2c ..\boot\fat12com.bin fat12com.h fat12com
|
||||||
|
|
||||||
b_fat16.h: ..\boot\b_fat16.bin bin2c.com
|
fat16com.h: ..\boot\fat16com.bin bin2c.com
|
||||||
.\bin2c ..\boot\b_fat16.bin b_fat16.h b_fat16
|
.\bin2c ..\boot\fat16com.bin fat16com.h fat16com
|
||||||
|
|
||||||
b_fat32.h: ..\boot\b_fat32.bin bin2c.com
|
fat32chs.h: ..\boot\fat32chs.bin bin2c.com
|
||||||
.\bin2c ..\boot\b_fat32.bin b_fat32.h b_fat32
|
.\bin2c ..\boot\fat32chs.bin fat32chs.h fat32chs
|
||||||
|
|
||||||
|
fat32lba.h: ..\boot\fat32lba.bin bin2c.com
|
||||||
|
.\bin2c ..\boot\fat32lba.bin fat32lba.h fat32lba
|
||||||
|
|
||||||
prf.obj: ..\kernel\prf.c
|
prf.obj: ..\kernel\prf.c
|
||||||
$(CC) $(CFLAGS) ..\kernel\prf.c
|
$(CC) $(CFLAGS) ..\kernel\prf.c
|
||||||
@ -43,12 +46,12 @@ sys.com: $(SYS_EXE_dependencies)
|
|||||||
$(CL) $(CFLAGST) $(TINY) $(SYS_EXE_dependencies)
|
$(CL) $(CFLAGST) $(TINY) $(SYS_EXE_dependencies)
|
||||||
|
|
||||||
clobber: clean
|
clobber: clean
|
||||||
-$(RM) bin2c.com sys.com b_fat12.h b_fat16.h b_fat32.h
|
-$(RM) bin2c.com sys.com fat*.h
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
-$(RM) *.obj *.bak *.crf *.xrf *.map *.lst *.las *.cod *.err status.me
|
-$(RM) *.obj *.bak *.crf *.xrf *.map *.lst *.las *.cod *.err status.me
|
||||||
|
|
||||||
# *Individual File Dependencies*
|
# *Individual File Dependencies*
|
||||||
sys.obj: sys.c ..\hdr\portab.h ..\hdr\device.h b_fat12.h b_fat16.h b_fat32.h
|
sys.obj: sys.c ..\hdr\portab.h ..\hdr\device.h fat12com.h fat16com.h fat32chs.h fat32lba.h
|
||||||
$(CC) $(CFLAGS) $*.c
|
$(CC) $(CFLAGS) $*.c
|
||||||
|
|
||||||
|
398
sys/sys.c
398
sys/sys.c
@ -26,16 +26,10 @@
|
|||||||
|
|
||||||
***************************************************************/
|
***************************************************************/
|
||||||
|
|
||||||
/*
|
|
||||||
TE thinks, that the boot info storage should be done by FORMAT, noone else
|
|
||||||
unfortunately, that doesn't work ???
|
|
||||||
*/
|
|
||||||
#define STORE_BOOT_INFO
|
|
||||||
|
|
||||||
#define DEBUG
|
#define DEBUG
|
||||||
/* #define DDEBUG */
|
/* #define DDEBUG */
|
||||||
|
|
||||||
#define SYS_VERSION "v2.6"
|
#define SYS_VERSION "v2.7"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <dos.h>
|
#include <dos.h>
|
||||||
@ -53,13 +47,25 @@
|
|||||||
#endif
|
#endif
|
||||||
#define SYS_MAXPATH 260
|
#define SYS_MAXPATH 260
|
||||||
#include "portab.h"
|
#include "portab.h"
|
||||||
|
#include "algnbyte.h"
|
||||||
|
#include "device.h"
|
||||||
|
#include "dcb.h"
|
||||||
|
#include "xstructs.h"
|
||||||
|
#include "date.h"
|
||||||
|
#include "../hdr/time.h"
|
||||||
|
#include "fat.h"
|
||||||
|
|
||||||
|
/* These definitions deliberately put here instead of
|
||||||
|
* #including <stdio.h> to make executable MUCH smaller
|
||||||
|
*/
|
||||||
extern WORD CDECL printf(CONST BYTE * fmt, ...);
|
extern WORD CDECL printf(CONST BYTE * fmt, ...);
|
||||||
extern WORD CDECL sprintf(BYTE * buff, CONST BYTE * fmt, ...);
|
extern WORD CDECL sprintf(BYTE * buff, CONST BYTE * fmt, ...);
|
||||||
|
|
||||||
#include "b_fat12.h"
|
#include "fat12com.h"
|
||||||
#include "b_fat16.h"
|
#include "fat16com.h"
|
||||||
#ifdef WITHFAT32
|
#ifdef WITHFAT32
|
||||||
#include "b_fat32.h"
|
#include "fat32chs.h"
|
||||||
|
#include "fat32lba.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef __WATCOMC__
|
#ifndef __WATCOMC__
|
||||||
@ -68,7 +74,9 @@ extern WORD CDECL sprintf(BYTE * buff, CONST BYTE * fmt, ...);
|
|||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
int unlink(const char *pathname);
|
extern long filelength(int __handle);
|
||||||
|
extern int unlink(const char *pathname);
|
||||||
|
|
||||||
/* some non-conforming functions to make the executable smaller */
|
/* some non-conforming functions to make the executable smaller */
|
||||||
int open(const char *pathname, int flags, ...)
|
int open(const char *pathname, int flags, ...)
|
||||||
{
|
{
|
||||||
@ -134,18 +142,12 @@ char *getenv(const char *name)
|
|||||||
BYTE pgm[] = "SYS";
|
BYTE pgm[] = "SYS";
|
||||||
|
|
||||||
void put_boot(COUNT, BYTE *, BOOL);
|
void put_boot(COUNT, BYTE *, BOOL);
|
||||||
BOOL check_space(COUNT, BYTE *);
|
BOOL check_space(COUNT, ULONG);
|
||||||
BOOL copy(COUNT drive, BYTE * srcPath, BYTE * rootPath, BYTE * file);
|
BOOL copy(COUNT drive, BYTE * srcPath, BYTE * rootPath, BYTE * file);
|
||||||
COUNT DiskRead(WORD, WORD, WORD, WORD, WORD, BYTE FAR *);
|
|
||||||
COUNT DiskWrite(WORD, WORD, WORD, WORD, WORD, BYTE FAR *);
|
|
||||||
|
|
||||||
#define SEC_SIZE 512
|
#define SEC_SIZE 512
|
||||||
#define COPY_SIZE 0x7e00
|
#define COPY_SIZE 0x7e00
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
#pragma pack(1)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct bootsectortype {
|
struct bootsectortype {
|
||||||
UBYTE bsJump[3];
|
UBYTE bsJump[3];
|
||||||
char OemName[8];
|
char OemName[8];
|
||||||
@ -167,11 +169,6 @@ struct bootsectortype {
|
|||||||
ULONG bsVolumeID;
|
ULONG bsVolumeID;
|
||||||
char bsVolumeLabel[11];
|
char bsVolumeLabel[11];
|
||||||
char bsFileSysType[8];
|
char bsFileSysType[8];
|
||||||
char unused[2];
|
|
||||||
UWORD sysRootDirSecs; /* of sectors root dir uses */
|
|
||||||
ULONG sysFatStart; /* first FAT sector */
|
|
||||||
ULONG sysRootDirStart; /* first root directory sector */
|
|
||||||
ULONG sysDataStart; /* first data sector */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct bootsectortype32 {
|
struct bootsectortype32 {
|
||||||
@ -203,13 +200,14 @@ struct bootsectortype32 {
|
|||||||
ULONG bsSerialNumber;
|
ULONG bsSerialNumber;
|
||||||
char bsVolumeLabel[11];
|
char bsVolumeLabel[11];
|
||||||
char bsFileSystemID[8];
|
char bsFileSystemID[8];
|
||||||
ULONG sysFatStart;
|
|
||||||
ULONG sysDataStart;
|
|
||||||
UWORD sysFatSecMask;
|
|
||||||
UWORD sysFatSecShift;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
UBYTE newboot[SEC_SIZE], oldboot[SEC_SIZE];
|
/*
|
||||||
|
* globals needed by put_boot & check_space
|
||||||
|
*/
|
||||||
|
enum {FAT12 = 12, FAT16 = 16, FAT32 = 32} fs; /* file system type */
|
||||||
|
/* static */ struct xfreespace x; /* we make this static to be 0 by default -
|
||||||
|
this avoids FAT misdetections */
|
||||||
|
|
||||||
#define SBOFFSET 11
|
#define SBOFFSET 11
|
||||||
#define SBSIZE (sizeof(struct bootsectortype) - SBOFFSET)
|
#define SBSIZE (sizeof(struct bootsectortype) - SBOFFSET)
|
||||||
@ -217,8 +215,9 @@ UBYTE newboot[SEC_SIZE], oldboot[SEC_SIZE];
|
|||||||
|
|
||||||
/* essentially - verify alignment on byte boundaries at compile time */
|
/* essentially - verify alignment on byte boundaries at compile time */
|
||||||
struct VerifyBootSectorSize {
|
struct VerifyBootSectorSize {
|
||||||
char failure1[sizeof(struct bootsectortype) == 78 ? 1 : -1];
|
char failure1[sizeof(struct bootsectortype) == 62 ? 1 : -1];
|
||||||
char failure2[sizeof(struct bootsectortype) == 78 ? 1 : 0];
|
char failure2[sizeof(struct bootsectortype) == 62 ? 1 : 0];
|
||||||
|
/* (Watcom has a nice warning for this, by the way) */
|
||||||
};
|
};
|
||||||
|
|
||||||
int FDKrnConfigMain(int argc, char **argv);
|
int FDKrnConfigMain(int argc, char **argv);
|
||||||
@ -233,7 +232,7 @@ int main(int argc, char **argv)
|
|||||||
BYTE rootPath[4]; /* alternate source path to try if not '\0' */
|
BYTE rootPath[4]; /* alternate source path to try if not '\0' */
|
||||||
WORD slen;
|
WORD slen;
|
||||||
|
|
||||||
printf("FreeDOS System Installer " SYS_VERSION "\n\n");
|
printf("FreeDOS System Installer " SYS_VERSION ", " __DATE__ "\n\n");
|
||||||
|
|
||||||
if (argc > 1 && memicmp(argv[1], "CONFIG", 6) == 0)
|
if (argc > 1 && memicmp(argv[1], "CONFIG", 6) == 0)
|
||||||
{
|
{
|
||||||
@ -263,18 +262,15 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
if (drivearg == 0)
|
if (drivearg == 0)
|
||||||
{
|
{
|
||||||
printf("Usage: %s [source] drive: [bootsect [BOTH|BOOTONLY]]\n", pgm);
|
printf(
|
||||||
printf
|
"Usage: %s [source] drive: [bootsect [BOTH]] [BOOTONLY]\n"
|
||||||
(" source = A:,B:,C:\\KERNEL\\BIN\\,etc., or current directory if not given\n");
|
" source = A:,B:,C:\\KERNEL\\BIN\\,etc., or current directory if not given\n"
|
||||||
printf(" drive = A,B,etc.\n");
|
" drive = A,B,etc.\n"
|
||||||
printf
|
" bootsect = name of 512-byte boot sector file image for drive:\n"
|
||||||
(" bootsect = name of 512-byte boot sector file image for drive:\n");
|
" to write to *instead* of real boot sector\n"
|
||||||
printf(" to write to *instead* of real boot sector\n");
|
" BOTH : write to *both* the real boot sector and the image file\n"
|
||||||
printf
|
" BOOTONLY : do *not* copy kernel / shell, only update boot sector or image\n"
|
||||||
(" BOTH : write to *both* the real boot sector and the image file\n");
|
"%s CONFIG /help\n", pgm, pgm);
|
||||||
printf
|
|
||||||
(" BOOTONLY : do *not* copy kernel / shell, only update boot sector or image\n");
|
|
||||||
printf("%s CONFIG /help\n", pgm);
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
drive = toupper(argv[drivearg][0]) - 'A';
|
drive = toupper(argv[drivearg][0]) - 'A';
|
||||||
@ -307,34 +303,25 @@ int main(int argc, char **argv)
|
|||||||
else
|
else
|
||||||
sprintf(rootPath, "%c:\\", 'A' + srcDrive);
|
sprintf(rootPath, "%c:\\", 'A' + srcDrive);
|
||||||
|
|
||||||
if ((argc <= drivearg + 2)
|
if (argc > drivearg + 1 && memicmp(argv[drivearg + 1], "BOOTONLY", 8) != 0)
|
||||||
|| (memicmp(argv[drivearg + 2], "BOOTONLY", 8) != 0))
|
bsFile = argv[drivearg + 1]; /* don't write to file "BOOTONLY" */
|
||||||
{
|
|
||||||
if (!check_space(drive, oldboot))
|
|
||||||
{
|
|
||||||
printf("%s: Not enough space to transfer system files\n", pgm);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("\nCopying KERNEL.SYS...\n");
|
|
||||||
if (!copy(drive, srcPath, rootPath, "KERNEL.SYS"))
|
|
||||||
{
|
|
||||||
printf("\n%s: cannot copy \"KERNEL.SYS\"\n", pgm);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
} /* copy kernel */
|
|
||||||
|
|
||||||
if (argc > drivearg + 1)
|
|
||||||
bsFile = argv[drivearg + 1];
|
|
||||||
|
|
||||||
printf("\nWriting boot sector...\n");
|
printf("\nWriting boot sector...\n");
|
||||||
put_boot(drive, bsFile,
|
put_boot(drive, bsFile,
|
||||||
(argc > drivearg + 2)
|
(argc > drivearg + 2)
|
||||||
&& memicmp(argv[drivearg + 2], "BOTH", 4) == 0);
|
&& memicmp(argv[drivearg + 2], "BOTH", 4) == 0);
|
||||||
|
|
||||||
if ((argc <= drivearg + 2)
|
if (argc <= drivearg + (bsFile ? 2 : 1)
|
||||||
|| (memicmp(argv[drivearg + 2], "BOOTONLY", 8) != 0))
|
|| memicmp(argv[drivearg + (bsFile ? 2 : 1)], "BOOTONLY", 8) != 0
|
||||||
|
&& memicmp(argv[drivearg + (bsFile ? 3 : 2)], "BOOTONLY", 8) != 0)
|
||||||
{
|
{
|
||||||
|
printf("\nCopying KERNEL.SYS...\n");
|
||||||
|
if (!copy(drive, srcPath, rootPath, "KERNEL.SYS"))
|
||||||
|
{
|
||||||
|
printf("\n%s: cannot copy \"KERNEL.SYS\"\n", pgm);
|
||||||
|
exit(1);
|
||||||
|
} /* copy kernel */
|
||||||
|
|
||||||
printf("\nCopying COMMAND.COM...\n");
|
printf("\nCopying COMMAND.COM...\n");
|
||||||
if (!copy(drive, srcPath, rootPath, "COMMAND.COM"))
|
if (!copy(drive, srcPath, rootPath, "COMMAND.COM"))
|
||||||
{
|
{
|
||||||
@ -350,8 +337,8 @@ int main(int argc, char **argv)
|
|||||||
printf("\n%s: cannot copy \"COMMAND.COM\"\n", pgm);
|
printf("\n%s: cannot copy \"COMMAND.COM\"\n", pgm);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
} /* copy shell */
|
||||||
} /* copy shell */
|
}
|
||||||
|
|
||||||
printf("\nSystem transferred.\n");
|
printf("\nSystem transferred.\n");
|
||||||
return 0;
|
return 0;
|
||||||
@ -372,7 +359,7 @@ VOID dump_sector(unsigned char far * sec)
|
|||||||
}
|
}
|
||||||
for (y = 0; y < 16; y++)
|
for (y = 0; y < 16; y++)
|
||||||
{
|
{
|
||||||
c = oldboot[x * 16 + y];
|
c = sec[x * 16 + y];
|
||||||
if (isprint(c))
|
if (isprint(c))
|
||||||
printf("%c", c);
|
printf("%c", c);
|
||||||
else
|
else
|
||||||
@ -523,16 +510,6 @@ int MyAbsReadWrite(int DosDrive, int count, ULONG sector, void *buffer,
|
|||||||
|
|
||||||
#ifdef __WATCOMC__
|
#ifdef __WATCOMC__
|
||||||
|
|
||||||
unsigned getdrivespace(COUNT drive, unsigned *total_clusters);
|
|
||||||
#pragma aux getdrivespace = \
|
|
||||||
"mov ah, 0x36" \
|
|
||||||
"inc dx" \
|
|
||||||
"int 0x21" \
|
|
||||||
"mov [si], dx" \
|
|
||||||
parm [dx] [si] \
|
|
||||||
modify [bx cx dx] \
|
|
||||||
value [ax];
|
|
||||||
|
|
||||||
unsigned getextdrivespace(void far *drivename, void *buf, unsigned buf_size);
|
unsigned getextdrivespace(void far *drivename, void *buf, unsigned buf_size);
|
||||||
#pragma aux getextdrivespace = \
|
#pragma aux getextdrivespace = \
|
||||||
"mov ax, 0x7303" \
|
"mov ax, 0x7303" \
|
||||||
@ -542,18 +519,7 @@ unsigned getextdrivespace(void far *drivename, void *buf, unsigned buf_size);
|
|||||||
parm [es dx] [di] [cx] \
|
parm [es dx] [di] [cx] \
|
||||||
value [ax];
|
value [ax];
|
||||||
|
|
||||||
#else
|
#else /* !defined __WATCOMC__ */
|
||||||
|
|
||||||
unsigned getdrivespace(COUNT drive, unsigned *total_clusters)
|
|
||||||
{
|
|
||||||
union REGS regs;
|
|
||||||
|
|
||||||
regs.h.ah = 0x36; /* get drive free space */
|
|
||||||
regs.h.dl = drive + 1; /* 1 = 'A',... */
|
|
||||||
intdos(®s, ®s);
|
|
||||||
*total_clusters = regs.x.dx;
|
|
||||||
return regs.x.ax;
|
|
||||||
} /* getdrivespace */
|
|
||||||
|
|
||||||
unsigned getextdrivespace(void *drivename, void *buf, unsigned buf_size)
|
unsigned getextdrivespace(void *drivename, void *buf, unsigned buf_size)
|
||||||
{
|
{
|
||||||
@ -573,20 +539,47 @@ unsigned getextdrivespace(void *drivename, void *buf, unsigned buf_size)
|
|||||||
return regs.x.ax == 0x7300 || regs.x.cflag;
|
return regs.x.ax == 0x7300 || regs.x.cflag;
|
||||||
} /* getextdrivespace */
|
} /* getextdrivespace */
|
||||||
|
|
||||||
|
#endif /* defined __WATCOMC__ */
|
||||||
|
|
||||||
|
#ifdef __WATCOMC__
|
||||||
|
/*
|
||||||
|
* If BIOS has got LBA extensions, after the Int 13h call BX will be 0xAA55.
|
||||||
|
* If extended disk access functions are supported, bit 0 of CX will be set.
|
||||||
|
*/
|
||||||
|
BOOL haveLBA(void); /* return TRUE if we have LBA BIOS, FALSE otherwise */
|
||||||
|
#pragma aux haveLBA = \
|
||||||
|
"mov ax, 0x4100" /* IBM/MS Int 13h Extensions - installation check */ \
|
||||||
|
"mov bx, 0x55AA" \
|
||||||
|
"mov dl, 0x80" \
|
||||||
|
"int 0x13" \
|
||||||
|
"xor ax, ax" \
|
||||||
|
"cmp bx, 0xAA55" \
|
||||||
|
"jne quit" \
|
||||||
|
"and cx, 1" \
|
||||||
|
"xchg cx, ax" \
|
||||||
|
"quit:" \
|
||||||
|
modify [bx cx] \
|
||||||
|
value [ax];
|
||||||
|
#else
|
||||||
|
|
||||||
|
BOOL haveLBA(void)
|
||||||
|
{
|
||||||
|
union REGS r;
|
||||||
|
r.x.ax = 0x4100;
|
||||||
|
r.x.bx = 0x55AA;
|
||||||
|
r.h.dl = 0x80;
|
||||||
|
int86(0x13, &r, &r);
|
||||||
|
return r.x.bx == 0xAA55 && r.x.cx & 1;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
VOID put_boot(COUNT drive, BYTE * bsFile, BOOL both)
|
VOID put_boot(COUNT drive, BYTE * bsFile, BOOL both)
|
||||||
{
|
{
|
||||||
ULONG temp;
|
|
||||||
struct bootsectortype *bs;
|
|
||||||
#ifdef WITHFAT32
|
#ifdef WITHFAT32
|
||||||
struct bootsectortype32 *bs32;
|
struct bootsectortype32 *bs32;
|
||||||
#endif
|
#endif
|
||||||
int fs;
|
struct bootsectortype *bs;
|
||||||
char *drivename = "A:\\";
|
static unsigned char oldboot[SEC_SIZE], newboot[SEC_SIZE];
|
||||||
static unsigned char x[0x40]; /* we make this static to be 0 by default -
|
|
||||||
this avoids FAT misdetections */
|
|
||||||
unsigned total_clusters;
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
printf("Reading old bootsector from drive %c:\n", drive + 'A');
|
printf("Reading old bootsector from drive %c:\n", drive + 'A');
|
||||||
@ -606,87 +599,58 @@ VOID put_boot(COUNT drive, BYTE * bsFile, BOOL both)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
bs = (struct bootsectortype *)&oldboot;
|
bs = (struct bootsectortype *)&oldboot;
|
||||||
if ((bs->bsFileSysType[4] == '6') && (bs->bsBootSignature == 0x29))
|
|
||||||
{
|
{
|
||||||
fs = 16;
|
/* see "FAT: General Overview of On-Disk Format" v1.02, 5.V.1999
|
||||||
}
|
* (http://www.nondot.org/sabre/os/files/FileSystems/FatFormat.pdf)
|
||||||
else
|
*/
|
||||||
{
|
ULONG fatSize, totalSectors, dataSectors, clusters;
|
||||||
fs = 12;
|
UCOUNT rootDirSectors;
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
bs32 = (struct bootsectortype32 *)&oldboot;
|
||||||
the above code is not save enough for me (TE), so we change the
|
rootDirSectors = (bs->bsRootDirEnts * DIRENT_SIZE /* 32 */
|
||||||
FS detection method to GetFreeDiskSpace().
|
+ bs32->bsBytesPerSec - 1) / bs32->bsBytesPerSec;
|
||||||
this should work, as the disk was writeable, so GetFreeDiskSpace should work.
|
fatSize = bs32->bsFATsecs ? bs32->bsFATsecs : bs32->bsBigFatSize;
|
||||||
*/
|
totalSectors = bs32->bsSectors ? bs32->bsSectors : bs32->bsHugeSectors;
|
||||||
|
dataSectors = totalSectors
|
||||||
|
- bs32->bsResSectors - (bs32->bsFATs * fatSize) - rootDirSectors;
|
||||||
|
clusters = dataSectors / bs32->bsSecPerClust;
|
||||||
|
|
||||||
/* would work different when reading from an image */
|
if (clusters < FAT_MAGIC) /* < 4085 */
|
||||||
if (getdrivespace(drive, &total_clusters) == 0xffff)
|
fs = FAT12;
|
||||||
{
|
else if (clusters < FAT_MAGIC16) /* < 65525 */
|
||||||
printf("can't get free disk space for %c:\n", drive + 'A');
|
fs = FAT16;
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (total_clusters <= 0xff6)
|
|
||||||
{
|
|
||||||
if (fs != 12)
|
|
||||||
printf("warning : new detection overrides old detection\a\n");
|
|
||||||
fs = 12;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
|
|
||||||
if (fs != 16)
|
|
||||||
printf("warning : new detection overrides old detection\a\n");
|
|
||||||
fs = 16;
|
|
||||||
|
|
||||||
/* fs = 16/32.
|
|
||||||
we don't want to crash a FAT32 drive
|
|
||||||
*/
|
|
||||||
|
|
||||||
drivename[0] = 'A' + drive;
|
|
||||||
/* would also work different when reading from an image */
|
|
||||||
if (getextdrivespace(drivename, x, sizeof(x)))
|
|
||||||
/* error --> no Win98 --> no FAT32 */
|
|
||||||
{
|
|
||||||
printf("get extended drive space not supported --> no FAT32\n");
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
fs = FAT32;
|
||||||
if (*(unsigned long *)(x + 0x10) /* total number of clusters */
|
|
||||||
> (unsigned)65526l)
|
|
||||||
{
|
|
||||||
fs = 32;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fs == 16)
|
if (bs->bsBytesPerSec != SEC_SIZE)
|
||||||
{
|
{
|
||||||
memcpy(newboot, b_fat16, SEC_SIZE); /* copy FAT16 boot sector */
|
printf("Sector size is not 512 but %d bytes - not currently supported!\n",
|
||||||
printf("FAT type: FAT16\n");
|
bs->bsBytesPerSec);
|
||||||
|
exit(1); /* Japan?! */
|
||||||
}
|
}
|
||||||
else if (fs == 12)
|
|
||||||
{
|
if (fs == FAT32)
|
||||||
memcpy(newboot, b_fat12, SEC_SIZE); /* copy FAT12 boot sector */
|
|
||||||
printf("FAT type: FAT12\n");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
printf("FAT type: FAT32\n");
|
printf("FAT type: FAT32\n");
|
||||||
#ifdef WITHFAT32
|
#ifdef WITHFAT32 /* copy one of the FAT32 boot sectors */
|
||||||
memcpy(newboot, b_fat32, SEC_SIZE); /* copy FAT32 boot sector */
|
memcpy(newboot, haveLBA() ? fat32lba : fat32chs, SEC_SIZE);
|
||||||
#else
|
#else
|
||||||
printf("SYS hasn't been compiled with FAT32 support.");
|
printf("SYS hasn't been compiled with FAT32 support.\n"
|
||||||
printf("Consider using -DWITHFAT32 option.\n");
|
"Consider using -DWITHFAT32 option.\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{ /* copy the FAT12/16 CHS+LBA boot sector */
|
||||||
|
printf("FAT type: FAT1%c\n", fs + '0' - 10);
|
||||||
|
memcpy(newboot, fs == FAT16 ? fat16com : fat12com, SEC_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
/* Copy disk parameter from old sector to new sector */
|
/* Copy disk parameter from old sector to new sector */
|
||||||
#ifdef WITHFAT32
|
#ifdef WITHFAT32
|
||||||
if (fs == 32)
|
if (fs == FAT32)
|
||||||
memcpy(&newboot[SBOFFSET], &oldboot[SBOFFSET], SBSIZE32);
|
memcpy(&newboot[SBOFFSET], &oldboot[SBOFFSET], SBSIZE32);
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
@ -697,70 +661,30 @@ VOID put_boot(COUNT drive, BYTE * bsFile, BOOL both)
|
|||||||
memcpy(bs->OemName, "FreeDOS ", 8);
|
memcpy(bs->OemName, "FreeDOS ", 8);
|
||||||
|
|
||||||
#ifdef WITHFAT32
|
#ifdef WITHFAT32
|
||||||
if (fs == 32)
|
if (fs == FAT32)
|
||||||
{
|
{
|
||||||
bs32 = (struct bootsectortype32 *)&newboot;
|
bs32 = (struct bootsectortype32 *)&newboot;
|
||||||
|
|
||||||
temp = bs32->bsHiddenSecs + bs32->bsResSectors;
|
|
||||||
bs32->sysFatStart = temp;
|
|
||||||
|
|
||||||
bs32->sysDataStart = temp + bs32->bsBigFatSize * bs32->bsFATs;
|
|
||||||
bs32->sysFatSecMask = bs32->bsBytesPerSec / 4 - 1;
|
|
||||||
|
|
||||||
temp = bs32->sysFatSecMask + 1;
|
|
||||||
for (bs32->sysFatSecShift = 0; temp != 1;
|
|
||||||
bs32->sysFatSecShift++, temp >>= 1) ;
|
|
||||||
/* put 0 for A: or B: (force booting from A:), otherwise use DL */
|
/* put 0 for A: or B: (force booting from A:), otherwise use DL */
|
||||||
bs32->bsDriveNumber = drive < 2 ? 0 : 0xff;
|
bs32->bsDriveNumber = drive < 2 ? 0 : 0xff;
|
||||||
}
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (fs == 32)
|
printf(" FAT starts at sector %lx + %x\n",
|
||||||
{
|
|
||||||
printf("FAT starts at sector %lx = (%lx + %x)\n", bs32->sysFatStart,
|
|
||||||
bs32->bsHiddenSecs, bs32->bsResSectors);
|
bs32->bsHiddenSecs, bs32->bsResSectors);
|
||||||
printf("DATA starts at sector %lx\n", bs32->sysDataStart);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
#ifdef STORE_BOOT_INFO
|
|
||||||
/* TE thinks : never, see above */
|
|
||||||
/* temporary HACK for the load segment (0x0060): it is in unused */
|
|
||||||
/* only needed for older kernels */
|
|
||||||
*((UWORD *) (bs->unused)) =
|
|
||||||
*((UWORD *) (((struct bootsectortype *)&b_fat16)->unused));
|
|
||||||
/* end of HACK */
|
|
||||||
/* root directory sectors */
|
|
||||||
|
|
||||||
bs->sysRootDirSecs = bs->bsRootDirEnts / 16;
|
|
||||||
|
|
||||||
/* sector FAT starts on */
|
|
||||||
temp = bs->bsHiddenSecs + bs->bsResSectors;
|
|
||||||
bs->sysFatStart = temp;
|
|
||||||
|
|
||||||
/* sector root directory starts on */
|
|
||||||
temp = temp + bs->bsFATsecs * bs->bsFATs;
|
|
||||||
bs->sysRootDirStart = temp;
|
|
||||||
|
|
||||||
/* sector data starts on */
|
|
||||||
temp = temp + bs->sysRootDirSecs;
|
|
||||||
bs->sysDataStart = temp;
|
|
||||||
/* put 0 for A: or B: (force booting from A:), otherwise use DL */
|
/* put 0 for A: or B: (force booting from A:), otherwise use DL */
|
||||||
bs->bsDriveNumber = drive < 2 ? 0 : 0xff;
|
bs->bsDriveNumber = drive < 2 ? 0 : 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG /* add an option to display this on user request? */
|
#ifdef DEBUG /* add an option to display this on user request? */
|
||||||
printf("Root dir entries = %u\n", bs->bsRootDirEnts);
|
printf("Root dir entries = %u\n", bs->bsRootDirEnts);
|
||||||
printf("Root dir sectors = %u\n", bs->sysRootDirSecs);
|
|
||||||
|
|
||||||
printf("FAT starts at sector %lu = (%lu + %u)\n", bs->sysFatStart,
|
printf("FAT starts at sector (%lu + %u)\n",
|
||||||
bs->bsHiddenSecs, bs->bsResSectors);
|
bs->bsHiddenSecs, bs->bsResSectors);
|
||||||
printf("Root directory starts at sector %lu = (PREVIOUS + %u * %u)\n",
|
printf("Root directory starts at sector (PREVIOUS + %u * %u)\n",
|
||||||
bs->sysRootDirStart, bs->bsFATsecs, bs->bsFATs);
|
bs->bsFATsecs, bs->bsFATs);
|
||||||
printf("DATA starts at sector %lu = (PREVIOUS + %u)\n", bs->sysDataStart,
|
|
||||||
bs->sysRootDirSecs);
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef DDEBUG
|
#ifdef DDEBUG
|
||||||
@ -812,15 +736,34 @@ VOID put_boot(COUNT drive, BYTE * bsFile, BOOL both)
|
|||||||
} /* put_boot */
|
} /* put_boot */
|
||||||
|
|
||||||
|
|
||||||
BOOL check_space(COUNT drive, BYTE * BlkBuffer)
|
/*
|
||||||
|
* Returns TRUE if `drive` has at least `bytes` free space, FALSE otherwise.
|
||||||
|
* put_sector() must have been already called to determine file system type.
|
||||||
|
*/
|
||||||
|
BOOL check_space(COUNT drive, ULONG bytes)
|
||||||
{
|
{
|
||||||
/* this should check, if on destination is enough space
|
#ifdef WITHFAT32
|
||||||
to hold command.com+ kernel.sys */
|
if (fs == FAT32)
|
||||||
|
{
|
||||||
UNREFERENCED_PARAMETER(drive);
|
char *drivename = "A:\\";
|
||||||
UNREFERENCED_PARAMETER(BlkBuffer);
|
drivename[0] = 'A' + drive;
|
||||||
|
getextdrivespace(drivename, &x, sizeof(x));
|
||||||
return TRUE;
|
return x.xfs_freeclusters > (bytes / (x.xfs_clussize * x.xfs_secsize));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
#ifdef __TURBOC__
|
||||||
|
struct dfree df;
|
||||||
|
getdfree(drive + 1, &df);
|
||||||
|
return (ULONG)df.df_avail * df.df_sclus * df.df_bsec >= bytes;
|
||||||
|
#else
|
||||||
|
struct _diskfree_t df;
|
||||||
|
_dos_getdiskfree(drive + 1, &df);
|
||||||
|
return (ULONG)df.avail_clusters * df.sectors_per_cluster
|
||||||
|
* df.bytes_per_sector >= bytes;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
} /* check_space */
|
} /* check_space */
|
||||||
|
|
||||||
|
|
||||||
@ -859,7 +802,7 @@ BOOL copy(COUNT drive, BYTE * srcPath, BYTE * rootPath, BYTE * file)
|
|||||||
truename(dest, source);
|
truename(dest, source);
|
||||||
strcpy(source, dest);
|
strcpy(source, dest);
|
||||||
sprintf(dest, "%c:\\%s", 'A' + drive, file);
|
sprintf(dest, "%c:\\%s", 'A' + drive, file);
|
||||||
if (strcmp(source, dest) == 0)
|
if (stricmp(source, dest) == 0)
|
||||||
{
|
{
|
||||||
printf("%s: source and destination are identical: skipping \"%s\"\n",
|
printf("%s: source and destination are identical: skipping \"%s\"\n",
|
||||||
pgm, source);
|
pgm, source);
|
||||||
@ -872,6 +815,13 @@ BOOL copy(COUNT drive, BYTE * srcPath, BYTE * rootPath, BYTE * file)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!check_space(drive, filelength(fdin)))
|
||||||
|
{
|
||||||
|
printf("%s: Not enough space to transfer %s\n", pgm, file);
|
||||||
|
close(fdin);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
if ((fdout =
|
if ((fdout =
|
||||||
open(dest, O_RDWR | O_TRUNC | O_CREAT | O_BINARY,
|
open(dest, O_RDWR | O_TRUNC | O_CREAT | O_BINARY,
|
||||||
S_IREAD | S_IWRITE)) < 0)
|
S_IREAD | S_IWRITE)) < 0)
|
||||||
@ -893,25 +843,22 @@ BOOL copy(COUNT drive, BYTE * srcPath, BYTE * rootPath, BYTE * file)
|
|||||||
copied += ret;
|
copied += ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __TURBOC__
|
|
||||||
{
|
|
||||||
struct ftime ftime;
|
|
||||||
getftime(fdin, &ftime);
|
|
||||||
setftime(fdout, &ftime);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#ifdef __WATCOMC__
|
|
||||||
{
|
{
|
||||||
|
#if defined __WATCOMC__ || defined _MSC_VER /* || defined __BORLANDC__ */
|
||||||
unsigned short date, time;
|
unsigned short date, time;
|
||||||
_dos_getftime(fdin, &date, &time);
|
_dos_getftime(fdin, &date, &time);
|
||||||
_dos_setftime(fdout, date, time);
|
_dos_setftime(fdout, date, time);
|
||||||
}
|
#elif defined __TURBOC__
|
||||||
|
struct ftime ftime;
|
||||||
|
getftime(fdin, &ftime);
|
||||||
|
setftime(fdout, &ftime);
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
close(fdin);
|
close(fdin);
|
||||||
close(fdout);
|
close(fdout);
|
||||||
|
|
||||||
#ifdef _MSV_VER
|
#ifdef __SOME_OTHER_COMPILER__
|
||||||
{
|
{
|
||||||
#include <utime.h>
|
#include <utime.h>
|
||||||
struct utimbuf utimb;
|
struct utimbuf utimb;
|
||||||
@ -920,7 +867,6 @@ BOOL copy(COUNT drive, BYTE * srcPath, BYTE * rootPath, BYTE * file)
|
|||||||
utimb.modtime = fstatbuf.st_mtime; /* modification time */
|
utimb.modtime = fstatbuf.st_mtime; /* modification time */
|
||||||
utime(dest, &utimb);
|
utime(dest, &utimb);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
printf("%lu Bytes transferred", copied);
|
printf("%lu Bytes transferred", copied);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user