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.
|
||||
;
|
||||
;
|
||||
; +--------+
|
||||
; | |
|
||||
; | |
|
||||
; |--------| 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
|
||||
|
@ -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
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"
|
||||
|
||||
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
|
||||
|
19
sys/makefile
19
sys/makefile
@ -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
400
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 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(®s, ®s);
|
||||
*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);
|
||||
|
Loading…
Reference in New Issue
Block a user