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:
Bart Oldeman 2003-08-08 15:01:15 +00:00
parent 3229fe3fc4
commit 9a3da2b737
6 changed files with 755 additions and 438 deletions

View File

@ -26,31 +26,24 @@
; Cambridge, MA 02139, USA.
;
;
; +--------+
; | |
; | |
; |--------| 4000:0000
; | |
; | FAT |
; | |
; |--------| 2000:0000
; +--------+ 1FE0:7E00
; |BOOT SEC|
; |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|
; |ORIGIN | 07C0:0000
; |--------|
; | |
; | |
; | |
; |--------|
; |KERNEL |
; |LOADED |
; |KERNEL | also used as max 128k FAT buffer
; |LOADED | before kernel loading starts
; |--------| 0060:0000
; | |
; +--------+
@ -58,8 +51,6 @@
;%define ISFAT12 1
;%define ISFAT16 1
;%define CALCPARAMS 1
;%define MULTI_SEC_READ 1
segment .text
@ -118,7 +109,7 @@ Entry: jmp short real_start
mov word [fat_start+2], di
mov al, [bsFATs]
xor ah, ah
cbw
mul word [sectPerFat] ; DX:AX = total number of FAT sectors
add si, ax
@ -148,49 +139,50 @@ Entry: jmp short real_start
times 0x3E-$+$$ db 0
%define tempbuf bp+0x3E
%define loadsegoff_60 bp+0x3E
dw 0
%define loadseg_60 bp+0x40
dw LOADSEG
%ifdef CALCPARAMS
%define RootDirSecs bp+0x27 ; # of sectors root dir uses
;%define LBA_PACKET bp+0x42
; 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 RootDirSecs bp+0x40 ; # of sectors root dir uses
dw 0
%define fat_start PARAMS+0x2 ; first FAT sector
%define fat_start bp+0x42 ; first FAT sector
dd 0
%define root_dir_start PARAMS+0x6 ; first root directory sector
%define root_dir_start bp+0x46 ; first root directory sector
dd 0
%define data_start PARAMS+0x0a ; first data sector
%define data_start bp+0x4A ; first data sector
dd 0
%endif
;-----------------------------------------------------------------------
; ENTRY
;-----------------------------------------------------------------------
real_start: cli
real_start:
cli
cld
xor ax, ax
mov ss, ax ; initialize stack
mov ds, ax
mov bp, 0x7c00
lea sp, [bp-0x20]
sti
cmp byte [drive], 0xff ; BIOS bug ??
jne dont_use_dl
mov [drive], dl ; BIOS passes drive number in DL
; a reset should not be needed here
dont_use_dl:
; a reset should not be needed here
; int 0x13 ; reset drive
; int 0x12 ; get memory available in AX
@ -207,15 +199,26 @@ dont_use_dl:
rep movsw
jmp word 0x1FE0:cont
cont: mov ds, ax
cont:
mov ds, 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
db "FreeDOS",0
%ifdef CALCPARAMS
GETDRIVEPARMS
%endif
; FINDFILE: Searches for the file in the root directory.
@ -229,13 +232,12 @@ cont: mov ds, ax
mov ax, word [root_dir_start]
mov dx, word [root_dir_start+2]
mov di, word [RootDirSecs]
xor bx, bx
mov word [tempbuf], LOADSEG
mov es, [tempbuf]
les bx, [loadsegoff_60] ; es:bx = 60:0
call readDisk
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.
@ -255,8 +257,8 @@ next_entry: mov cx, 11
ffDone:
push ax ; store first cluster number
call print
db " FAT",0
; call print
; db " FAT",0
@ -275,8 +277,7 @@ ffDone:
; Load the complete FAT into memory. The FAT can't be larger
; than 128 kb, so it should fit in the temporary buffer.
mov es, [tempbuf]
xor bx, bx
les bx, [loadsegoff_60] ; es:bx=60:0
mov di, [sectPerFat]
mov ax, word [fat_start]
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.
push ds
push es
pop ds
pop es
mov ds, [loadseg_60]
mov di, FATBUF
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.
jnc fat_even
mov cl, 4
shr ax, cl ; shift the cluster number
div word[LBA_PACKET]; luckily 16 !! -- divide the cluster number
fat_even: and ah, 0x0f ; mask off the highest 4 bits
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
; 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
jnc first_half ; if overflow...
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
pop ds
call print
db " Kernel",0 ; "KERNEL"
;call print
;db " Kernel",0 ; "KERNEL"
; loadFile: Loads the file into memory, one cluster at a time.
mov es, [tempbuf] ; set ES:BX to load address
xor bx, bx
les bx, [loadsegoff_60] ; set ES:BX to load address 60:0
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
db 13,10,"BOOT err!",0
db " err",0
xor ah,ah
int 0x16 ; wait for a key
int 0x19 ; reboot the machine
boot_success: call print
db " GO! ",0
boot_success:
;call print
;db " GO! ",0
mov bl, [drive]
jmp word LOADSEG:0
jmp far [loadsegoff_60]
; 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.
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 *******************************
; check for LBA support
push bx
mov ah,041h ;
mov bx,055aah ;
@ -424,51 +427,30 @@ read_next: push dx
int 0x13
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
shr cx,1 ; CX must have 1 bit set
jnc read_normal_BIOS
; OK, drive seems to support LBA addressing
lea si,[LBA_DISK_PARAMETER_BLOCK]
lea si,[LBA_PACKET]
; setup LBA disk block
mov [si+12],bx
mov [si+14],bx
mov LBA_SECTOR_32,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
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:
pop bx
pop ax
pop dx
push dx
push ax
;******************** 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
or cl, ah ; merge sector into cylinder
%ifdef MULTI_SEC_READ
; 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
les bx,[LBA_OFF]
mov ax, 0x0201
do_int13_read:
mov dl, [drive]
int 0x13
%endif
read_finished:
jnc read_ok ; jump if no error
xor ah, ah ; else, reset floppy
int 0x13
pop ax
pop dx ; and...
read_next_chained:
jmp short read_next ; read the same sector again
read_ok:
%ifdef MULTI_SEC_READ
mul word [bsBytesPerSec] ; add number of bytes read to BX
add bx, ax
%else
add bx, word [bsBytesPerSec]
%endif
jnc no_incr_es ; if overflow...
mov ax, word [bsBytesPerSec]
div byte[LBA_PACKET] ; luckily 16 !!
add word [LBA_SEG], ax
mov ax, es
add ah, 0x10 ; ...add 1000h to ES
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
add LBA_SECTOR_0, byte 1
adc LBA_SECTOR_16, byte 0 ; DX:AX = next sector to read
dec di ; if there is anything left to read,
jnz read_next_chained ; continue
%endif
clc
mov es,word [LBA_SEG]
; clear carry: unnecessary since adc clears it
pop si
ret
filename db "KERNEL SYS"
times 0x01fe-$+$$ db 0
sign dw 0xAA55

View File

@ -57,34 +57,33 @@ Entry: jmp short real_start
%define xrootClst bp+0x2c ; Starting cluster of root directory
%define drive bp+0x40 ; Drive number
times 0x5a-$+$$ db 0
%define LOADSEG 0x0060
%define FATSEG 0x2000
%define fat_sector bp+0x48 ; last accessed sector of the FAT
dd 0
times 0x5a-$+$$ db 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
%define loadsegoff_60 bp+0x5a ; FAR pointer = 60: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
;-----------------------------------------------------------------------
real_start: cld
cli
sub ax, ax
mov ds, ax
mov bp, 0x7c00
mov ss, ax ; initialize stack
lea sp, [bp-0x20]
int 0x13 ; reset drive
mov ax, 0x1FE0
mov es, ax
@ -95,18 +94,59 @@ real_start: cld
jmp word 0x1FE0:cont
cont: mov ds, ax
mov ss, ax
mov ss, ax
lea sp, [bp-0x20]
sti
mov [drive], dl ; BIOS passes drive number in DL
call print
db "Loading FreeDOS ",0
; call print
; 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.
;
; Returns:
; 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 ax, word [xrootClst]
@ -120,9 +160,7 @@ ff_next_cluster:
ff_next_sector:
push bx ; save sector count
mov bx, LOADSEG
mov es, bx
sub bx, bx
les bx, [loadsegoff_60]
call readDisk
push dx ; save sector
push ax
@ -171,10 +209,7 @@ c6:
call next_cluster
jmp c5
boot_error: call print
db 13,10,"BOOT error!",13,10,0
boot_error:
xor ah,ah
int 0x16 ; wait for a key
int 0x19 ; reboot the machine
@ -230,7 +265,7 @@ cn_exit:
boot_success:
mov bl, [drive]
jmp word LOADSEG:0
jmp far [loadsegoff_60]
; Convert cluster to the absolute sector
;input:
@ -263,7 +298,7 @@ c3:
add ax, [data_start]
adc dx, [data_start + 2]
ret
; prints text after call to this function.
print_1char:
@ -276,8 +311,7 @@ print1: lodsb ; get token
cmp al, 0 ; end of string?
jne print_1char ; until done
ret ; and jump to it
;input:
; DX:AX - 32-bit DOS sector number
; ES:BX - destination buffer

405
boot/boot32lb.asm Normal file
View 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.

View File

@ -7,19 +7,22 @@
!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
$(NASM) -dISFAT12 boot.asm -ob_fat12.bin
fat12com.bin: boot.asm
$(NASM) -dISFAT12 boot.asm -ofat12com.bin
b_fat16.bin: boot.asm
$(NASM) -dISFAT16 boot.asm -ob_fat16.bin
fat16com.bin: boot.asm
$(NASM) -dISFAT16 boot.asm -ofat16com.bin
b_fat32.bin: boot32.asm
$(NASM) boot32.asm -ob_fat32.bin
fat32chs.bin: boot32.asm
$(NASM) boot32.asm -ofat32chs.bin
fat32lba.bin: boot32lb.asm
$(NASM) boot32lb.asm -ofat32lba.bin
clobber: clean
-$(RM) b_fat12.bin b_fat16.bin b_fat32.bin status.me
-$(RM) *.bin status.me
clean:
-$(RM) *.lst *.map *.bak *.obj

View File

@ -25,14 +25,17 @@ bin2c.com: bin2c.c
..\bin\sys.com: sys.com
copy sys.com ..\bin
b_fat12.h: ..\boot\b_fat12.bin bin2c.com
.\bin2c ..\boot\b_fat12.bin b_fat12.h b_fat12
fat12com.h: ..\boot\fat12com.bin bin2c.com
.\bin2c ..\boot\fat12com.bin fat12com.h fat12com
b_fat16.h: ..\boot\b_fat16.bin bin2c.com
.\bin2c ..\boot\b_fat16.bin b_fat16.h b_fat16
fat16com.h: ..\boot\fat16com.bin bin2c.com
.\bin2c ..\boot\fat16com.bin fat16com.h fat16com
b_fat32.h: ..\boot\b_fat32.bin bin2c.com
.\bin2c ..\boot\b_fat32.bin b_fat32.h b_fat32
fat32chs.h: ..\boot\fat32chs.bin bin2c.com
.\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
$(CC) $(CFLAGS) ..\kernel\prf.c
@ -43,12 +46,12 @@ sys.com: $(SYS_EXE_dependencies)
$(CL) $(CFLAGST) $(TINY) $(SYS_EXE_dependencies)
clobber: clean
-$(RM) bin2c.com sys.com b_fat12.h b_fat16.h b_fat32.h
-$(RM) bin2c.com sys.com fat*.h
clean:
-$(RM) *.obj *.bak *.crf *.xrf *.map *.lst *.las *.cod *.err status.me
# *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

400
sys/sys.c
View File

@ -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 DDEBUG */
#define SYS_VERSION "v2.6"
#define SYS_VERSION "v2.7"
#include <stdlib.h>
#include <dos.h>
@ -53,13 +47,25 @@
#endif
#define SYS_MAXPATH 260
#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 sprintf(BYTE * buff, CONST BYTE * fmt, ...);
#include "b_fat12.h"
#include "b_fat16.h"
#include "fat12com.h"
#include "fat16com.h"
#ifdef WITHFAT32
#include "b_fat32.h"
#include "fat32chs.h"
#include "fat32lba.h"
#endif
#ifndef __WATCOMC__
@ -68,7 +74,9 @@ extern WORD CDECL sprintf(BYTE * buff, CONST BYTE * fmt, ...);
#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 */
int open(const char *pathname, int flags, ...)
{
@ -134,18 +142,12 @@ char *getenv(const char *name)
BYTE pgm[] = "SYS";
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);
COUNT DiskRead(WORD, WORD, WORD, WORD, WORD, BYTE FAR *);
COUNT DiskWrite(WORD, WORD, WORD, WORD, WORD, BYTE FAR *);
#define SEC_SIZE 512
#define COPY_SIZE 0x7e00
#ifdef _MSC_VER
#pragma pack(1)
#endif
struct bootsectortype {
UBYTE bsJump[3];
char OemName[8];
@ -167,11 +169,6 @@ struct bootsectortype {
ULONG bsVolumeID;
char bsVolumeLabel[11];
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 {
@ -203,13 +200,14 @@ struct bootsectortype32 {
ULONG bsSerialNumber;
char bsVolumeLabel[11];
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 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 */
struct VerifyBootSectorSize {
char failure1[sizeof(struct bootsectortype) == 78 ? 1 : -1];
char failure2[sizeof(struct bootsectortype) == 78 ? 1 : 0];
char failure1[sizeof(struct bootsectortype) == 62 ? 1 : -1];
char failure2[sizeof(struct bootsectortype) == 62 ? 1 : 0];
/* (Watcom has a nice warning for this, by the way) */
};
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' */
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)
{
@ -263,18 +262,15 @@ int main(int argc, char **argv)
if (drivearg == 0)
{
printf("Usage: %s [source] drive: [bootsect [BOTH|BOOTONLY]]\n", pgm);
printf
(" source = A:,B:,C:\\KERNEL\\BIN\\,etc., or current directory if not given\n");
printf(" drive = A,B,etc.\n");
printf
(" bootsect = name of 512-byte boot sector file image for drive:\n");
printf(" to write to *instead* of real boot sector\n");
printf
(" 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");
printf("%s CONFIG /help\n", pgm);
printf(
"Usage: %s [source] drive: [bootsect [BOTH]] [BOOTONLY]\n"
" source = A:,B:,C:\\KERNEL\\BIN\\,etc., or current directory if not given\n"
" drive = A,B,etc.\n"
" bootsect = name of 512-byte boot sector file image for drive:\n"
" to write to *instead* of real boot sector\n"
" BOTH : write to *both* the real boot sector and the image file\n"
" BOOTONLY : do *not* copy kernel / shell, only update boot sector or image\n"
"%s CONFIG /help\n", pgm, pgm);
exit(1);
}
drive = toupper(argv[drivearg][0]) - 'A';
@ -307,34 +303,25 @@ int main(int argc, char **argv)
else
sprintf(rootPath, "%c:\\", 'A' + srcDrive);
if ((argc <= drivearg + 2)
|| (memicmp(argv[drivearg + 2], "BOOTONLY", 8) != 0))
{
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];
if (argc > drivearg + 1 && memicmp(argv[drivearg + 1], "BOOTONLY", 8) != 0)
bsFile = argv[drivearg + 1]; /* don't write to file "BOOTONLY" */
printf("\nWriting boot sector...\n");
put_boot(drive, bsFile,
(argc > drivearg + 2)
&& memicmp(argv[drivearg + 2], "BOTH", 4) == 0);
if ((argc <= drivearg + 2)
|| (memicmp(argv[drivearg + 2], "BOOTONLY", 8) != 0))
if (argc <= drivearg + (bsFile ? 2 : 1)
|| 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");
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);
exit(1);
}
}
} /* copy shell */
} /* copy shell */
}
printf("\nSystem transferred.\n");
return 0;
@ -372,7 +359,7 @@ VOID dump_sector(unsigned char far * sec)
}
for (y = 0; y < 16; y++)
{
c = oldboot[x * 16 + y];
c = sec[x * 16 + y];
if (isprint(c))
printf("%c", c);
else
@ -523,16 +510,6 @@ int MyAbsReadWrite(int DosDrive, int count, ULONG sector, void *buffer,
#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);
#pragma aux getextdrivespace = \
"mov ax, 0x7303" \
@ -542,18 +519,7 @@ unsigned getextdrivespace(void far *drivename, void *buf, unsigned buf_size);
parm [es dx] [di] [cx] \
value [ax];
#else
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(&regs, &regs);
*total_clusters = regs.x.dx;
return regs.x.ax;
} /* getdrivespace */
#else /* !defined __WATCOMC__ */
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;
} /* 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
VOID put_boot(COUNT drive, BYTE * bsFile, BOOL both)
{
ULONG temp;
struct bootsectortype *bs;
#ifdef WITHFAT32
struct bootsectortype32 *bs32;
#endif
int fs;
char *drivename = "A:\\";
static unsigned char x[0x40]; /* we make this static to be 0 by default -
this avoids FAT misdetections */
unsigned total_clusters;
struct bootsectortype *bs;
static unsigned char oldboot[SEC_SIZE], newboot[SEC_SIZE];
#ifdef DEBUG
printf("Reading old bootsector from drive %c:\n", drive + 'A');
@ -606,87 +599,58 @@ VOID put_boot(COUNT drive, BYTE * bsFile, BOOL both)
#endif
bs = (struct bootsectortype *)&oldboot;
if ((bs->bsFileSysType[4] == '6') && (bs->bsBootSignature == 0x29))
{
fs = 16;
}
else
{
fs = 12;
}
/* see "FAT: General Overview of On-Disk Format" v1.02, 5.V.1999
* (http://www.nondot.org/sabre/os/files/FileSystems/FatFormat.pdf)
*/
ULONG fatSize, totalSectors, dataSectors, clusters;
UCOUNT rootDirSectors;
/*
the above code is not save enough for me (TE), so we change the
FS detection method to GetFreeDiskSpace().
this should work, as the disk was writeable, so GetFreeDiskSpace should work.
*/
/* would work different when reading from an image */
if (getdrivespace(drive, &total_clusters) == 0xffff)
{
printf("can't get free disk space for %c:\n", drive + 'A');
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");
}
bs32 = (struct bootsectortype32 *)&oldboot;
rootDirSectors = (bs->bsRootDirEnts * DIRENT_SIZE /* 32 */
+ bs32->bsBytesPerSec - 1) / bs32->bsBytesPerSec;
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;
if (clusters < FAT_MAGIC) /* < 4085 */
fs = FAT12;
else if (clusters < FAT_MAGIC16) /* < 65525 */
fs = FAT16;
else
{
if (*(unsigned long *)(x + 0x10) /* total number of clusters */
> (unsigned)65526l)
{
fs = 32;
}
}
fs = FAT32;
}
if (fs == 16)
if (bs->bsBytesPerSec != SEC_SIZE)
{
memcpy(newboot, b_fat16, SEC_SIZE); /* copy FAT16 boot sector */
printf("FAT type: FAT16\n");
printf("Sector size is not 512 but %d bytes - not currently supported!\n",
bs->bsBytesPerSec);
exit(1); /* Japan?! */
}
else if (fs == 12)
{
memcpy(newboot, b_fat12, SEC_SIZE); /* copy FAT12 boot sector */
printf("FAT type: FAT12\n");
}
else
if (fs == FAT32)
{
printf("FAT type: FAT32\n");
#ifdef WITHFAT32
memcpy(newboot, b_fat32, SEC_SIZE); /* copy FAT32 boot sector */
#ifdef WITHFAT32 /* copy one of the FAT32 boot sectors */
memcpy(newboot, haveLBA() ? fat32lba : fat32chs, SEC_SIZE);
#else
printf("SYS hasn't been compiled with FAT32 support.");
printf("Consider using -DWITHFAT32 option.\n");
printf("SYS hasn't been compiled with FAT32 support.\n"
"Consider using -DWITHFAT32 option.\n");
exit(1);
#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 */
#ifdef WITHFAT32
if (fs == 32)
if (fs == FAT32)
memcpy(&newboot[SBOFFSET], &oldboot[SBOFFSET], SBSIZE32);
else
#endif
@ -697,70 +661,30 @@ VOID put_boot(COUNT drive, BYTE * bsFile, BOOL both)
memcpy(bs->OemName, "FreeDOS ", 8);
#ifdef WITHFAT32
if (fs == 32)
if (fs == FAT32)
{
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 */
bs32->bsDriveNumber = drive < 2 ? 0 : 0xff;
}
#ifdef DEBUG
if (fs == 32)
{
printf("FAT starts at sector %lx = (%lx + %x)\n", bs32->sysFatStart,
printf(" FAT starts at sector %lx + %x\n",
bs32->bsHiddenSecs, bs32->bsResSectors);
printf("DATA starts at sector %lx\n", bs32->sysDataStart);
}
#endif
}
else
#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 */
bs->bsDriveNumber = drive < 2 ? 0 : 0xff;
}
#ifdef DEBUG /* add an option to display this on user request? */
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);
printf("Root directory starts at sector %lu = (PREVIOUS + %u * %u)\n",
bs->sysRootDirStart, bs->bsFATsecs, bs->bsFATs);
printf("DATA starts at sector %lu = (PREVIOUS + %u)\n", bs->sysDataStart,
bs->sysRootDirSecs);
#endif
printf("Root directory starts at sector (PREVIOUS + %u * %u)\n",
bs->bsFATsecs, bs->bsFATs);
#endif
#ifdef DDEBUG
@ -812,15 +736,34 @@ VOID put_boot(COUNT drive, BYTE * bsFile, BOOL both)
} /* 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
to hold command.com+ kernel.sys */
UNREFERENCED_PARAMETER(drive);
UNREFERENCED_PARAMETER(BlkBuffer);
return TRUE;
#ifdef WITHFAT32
if (fs == FAT32)
{
char *drivename = "A:\\";
drivename[0] = 'A' + drive;
getextdrivespace(drivename, &x, sizeof(x));
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 */
@ -859,7 +802,7 @@ BOOL copy(COUNT drive, BYTE * srcPath, BYTE * rootPath, BYTE * file)
truename(dest, source);
strcpy(source, dest);
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",
pgm, source);
@ -872,6 +815,13 @@ BOOL copy(COUNT drive, BYTE * srcPath, BYTE * rootPath, BYTE * file)
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 =
open(dest, O_RDWR | O_TRUNC | O_CREAT | O_BINARY,
S_IREAD | S_IWRITE)) < 0)
@ -893,25 +843,22 @@ BOOL copy(COUNT drive, BYTE * srcPath, BYTE * rootPath, BYTE * file)
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;
_dos_getftime(fdin, &date, &time);
_dos_setftime(fdout, date, time);
#elif defined __TURBOC__
struct ftime ftime;
getftime(fdin, &ftime);
setftime(fdout, &ftime);
#endif
}
#endif
close(fdin);
close(fdout);
#ifdef _MSV_VER
#ifdef __SOME_OTHER_COMPILER__
{
#include <utime.h>
struct utimbuf utimb;
@ -920,7 +867,6 @@ BOOL copy(COUNT drive, BYTE * srcPath, BYTE * rootPath, BYTE * file)
utimb.modtime = fstatbuf.st_mtime; /* modification time */
utime(dest, &utimb);
};
#endif
printf("%lu Bytes transferred", copied);