update ldosboot from hg 798e0b02fedc
From https://hg.pushbx.org/ecm/ldosboot/file/798e0b02fedc
This commit is contained in:
parent
adbc31edea
commit
cba5ee259d
@ -30,7 +30,7 @@ Public domain by C. Masloch, 2012
|
||||
strdef LOAD_NAME, "LDOS"
|
||||
strdef LOAD_EXT, "COM" ; name of file to load
|
||||
numdef LOAD_ADR, 02000h ; where to load
|
||||
numdef LOAD_MIN_PARA, paras(1536)
|
||||
numdef LOAD_MIN_PARA, paras(4096)
|
||||
numdef LOAD_NON_FAT, 0, 2048 ; use FAT-less loading (value is amount bytes)
|
||||
numdef EXEC_SEG_ADJ, 0 ; how far cs will be from _LOAD_ADR
|
||||
numdef EXEC_OFS, 400h ; what value ip will be
|
||||
@ -41,12 +41,16 @@ Public domain by C. Masloch, 2012
|
||||
strdef ADD_NAME, ""
|
||||
strdef ADD_EXT, "" ; name of second file to search
|
||||
numdef ADD_DIR_SEG, 0 ; => where to store dir entry (0 if nowhere)
|
||||
numdef CHECK_ATTRIB, 0 ; check attribute for LFN, label, directory
|
||||
numdef ATTRIB_SAVE, _CHECK_ATTRIB
|
||||
|
||||
gendef _ADR_DIRBUF, end -start+7C00h ; 07E00h
|
||||
gendef _ADR_FATBUF, end -start+7C00h ; 07E00h
|
||||
|
||||
numdef QUERY_GEOMETRY, 1 ; query geometry via 13.08 (for CHS access)
|
||||
numdef QUERY_GEOMETRY_DISABLED, 0
|
||||
numdef USE_PART_INFO, 1 ; use ds:si-> partition info from MBR, if any
|
||||
numdef USE_PART_INFO_DISABLED, 0
|
||||
numdef USE_AUTO_UNIT, 1 ; use unit passed from ROM-BIOS in dl
|
||||
numdef RPL, 1 ; support RPL and do not overwrite it
|
||||
numdef RPL_GRACE_AREA, 130 * 1024
|
||||
@ -73,6 +77,7 @@ Public domain by C. Masloch, 2012
|
||||
numdef LBA_SET_TYPE, 0 ; if to set third byte to LBA partition type
|
||||
numdef SET_LOAD_SEG, 1 ; if to set load_seg (word [ss:bp - 6])
|
||||
numdef SET_FAT_SEG, 1 ; if to set fat_seg (word [ss:bp - 8])
|
||||
numdef SET_FAT_SEG_NORMAL, 1 ; do not use aggressive optimisation
|
||||
numdef SET_CLUSTER, 1 ; if to set first_cluster (word [ss:bp - 16])
|
||||
numdef ZERO_ES, 0 ; if to set es = 0 before jump
|
||||
numdef ZERO_DS, 0 ; if to set ds = 0 before jump
|
||||
@ -83,11 +88,18 @@ Public domain by C. Masloch, 2012
|
||||
numdef FIX_CLUSTER_SIZE_SKIP_CHECK, 0 ; don't check cluster size
|
||||
numdef NO_LIMIT, 0 ; allow using more memory than a boot sector
|
||||
; also will not write 0AA55h signature!
|
||||
numdef WARN_PART_SIZE, 0
|
||||
|
||||
numdef LBA_SKIP_CHECK, 1 ; don't use proper LBA extensions check
|
||||
numdef LBA_SKIP_CY, 1 ; skip check: set up CY before 13.42
|
||||
numdef LBA_SKIP_ANY, 0 ; skip check: try CHS on any error
|
||||
incdef _LBA_SKIP_ANY, LBA_SKIP_CY
|
||||
numdef LBA_RETRY, 0 ; retry LBA reads one time
|
||||
numdef CHS_RETRY, 1 ; retry CHS reads one time
|
||||
numdef CHS_RETRY_REPEAT,16 ; retry CHS reads multiple times
|
||||
; (value of the def is used as count)
|
||||
numdef CHS_RETRY_NORMAL,1 ; do not use aggressive optimisation
|
||||
numdef RETRY_RESET, 1 ; call reset disk system 13.00 on retries
|
||||
|
||||
numdef MEDIAID, 0F0h ; media ID
|
||||
numdef UNIT, 0 ; load unit in BPB
|
||||
@ -133,7 +145,7 @@ Public domain by C. Masloch, 2012
|
||||
|
||||
%if (!!_COMPAT_FREEDOS + !!_COMPAT_IBM + \
|
||||
!!_COMPAT_MS7 + !!_COMPAT_MS6 + \
|
||||
!!_COMPAT_LDOS || _COMPAT_KERNEL7E) > 1
|
||||
!!_COMPAT_LDOS + !!_COMPAT_KERNEL7E) > 1
|
||||
%error At most one set must be selected.
|
||||
%endif
|
||||
|
||||
@ -244,7 +256,7 @@ Public domain by C. Masloch, 2012
|
||||
strdef LOAD_NAME, "LDOS"
|
||||
strdef LOAD_EXT, "COM"
|
||||
numdef LOAD_ADR, 02000h
|
||||
numdef LOAD_MIN_PARA, paras(1536)
|
||||
numdef LOAD_MIN_PARA, paras(4096)
|
||||
numdef EXEC_SEG_ADJ, 0
|
||||
numdef EXEC_OFS, 400h
|
||||
numdef CHECKOFFSET, 1020
|
||||
@ -613,19 +625,73 @@ start:
|
||||
|
||||
ADR_STACK_START equ _LASTVARIABLE -start+POSITION
|
||||
|
||||
%ifn _FIX_CLUSTER_SIZE
|
||||
; (word) actual sectors per cluster
|
||||
nextvariable adj_sectors_per_cluster, 2, relocatestart
|
||||
%endif
|
||||
|
||||
%ifn _FIX_SECTOR_SIZE
|
||||
; (word) number of 16-byte paragraphs per sector
|
||||
nextvariable para_per_sector, 2, relocatestart
|
||||
%endif
|
||||
|
||||
%assign DIRSEARCHSTACK_CL_FIRST 0
|
||||
%assign DIRSEARCHSTACK_CL_SECOND 0
|
||||
%assign PLACEHOLDER 0
|
||||
|
||||
%if _ATTRIB_SAVE && ! (_ADD_SEARCH || _LOAD_DIR_SEG)
|
||||
%if _LASTVARIABLE == start - 12h
|
||||
%assign DIRSEARCHSTACK_CL_FIRST 1
|
||||
%elif _LASTVARIABLE == start - 10h
|
||||
%assign DIRSEARCHSTACK_CL_SECOND 1
|
||||
%endif
|
||||
%ifn _DIR_ENTRY_500
|
||||
; three words left on the stack after directory search
|
||||
nextvariable dirsearchstack, 6, relocatestart
|
||||
%else
|
||||
; two words left on the stack after directory search
|
||||
nextvariable dirsearchstack, 4, relocatestart
|
||||
%endif
|
||||
%elifn !_RELOCATE && _LOAD_ADR < ADR_FREE_UNTIL
|
||||
%if _LASTVARIABLE == start - 12h
|
||||
nextvariable cmdline_signature_placeholder, 2, relocatestart
|
||||
%assign PLACEHOLDER 1
|
||||
%elif _LASTVARIABLE == start - 10h
|
||||
%if _PUSH_DPT
|
||||
nextvariable cmdline_signature_placeholder, 4, relocatestart
|
||||
%assign PLACEHOLDER 2
|
||||
; In this case, part of the original DPT pointer may
|
||||
; overlap the CL signature word. Therefore allocate
|
||||
; two placeholder words to insure no CL match.
|
||||
%else
|
||||
; In this case the last_available_sector variable
|
||||
; will be at word [ss:bp - 12h] (or none) and the
|
||||
; stack pointer will be equal to bp - 12h (or - 10h)
|
||||
; at handover time. Thus no placeholder is needed.
|
||||
%endif
|
||||
%else
|
||||
%error Placeholder not placed
|
||||
%endif
|
||||
; This stack slot is used to insure that
|
||||
; the "CL" signature is not present at this
|
||||
; location. If not relocate and load address
|
||||
; is below loader then the next variable
|
||||
; (last_available_sector) will always receive
|
||||
; a value < 7C0h so cannot hold "CL".
|
||||
; If _ATTRIB_SAVE is in use and neither the
|
||||
; _ADD_SEARCH nor the _LOAD_DIR_SEG options
|
||||
; are set, the first word of dirsearchstack
|
||||
; will be at word [ss:bp - 14h].
|
||||
%endif
|
||||
|
||||
%ifn ! _RELOCATE && _LOAD_ADR < ADR_FREE_UNTIL && _FIX_SECTOR_SIZE
|
||||
; (word) segment of last available memory for sector
|
||||
nextvariable last_available_sector, 2
|
||||
%else
|
||||
%if _LASTVARIABLE == start - 12h
|
||||
nextvariable cmdline_signature_placeholder, 2, relocatestart
|
||||
%assign PLACEHOLDER 1
|
||||
%elif _LASTVARIABLE == start - 10h
|
||||
%if _PUSH_DPT
|
||||
nextvariable cmdline_signature_placeholder, 4, relocatestart
|
||||
%assign PLACEHOLDER 2
|
||||
%endif
|
||||
%endif
|
||||
%endif
|
||||
|
||||
lowest_variable equ _LASTVARIABLE
|
||||
@ -706,8 +772,6 @@ add_name:
|
||||
; This happens to be aligned anyway. But even if
|
||||
; it didn't, we'd rather save that byte than use
|
||||
; it to align these fields. So comment this out.
|
||||
filename:
|
||||
dw add_name
|
||||
dirseg:
|
||||
dw _ADD_DIR_SEG
|
||||
%endif
|
||||
@ -724,6 +788,8 @@ dirseg:
|
||||
[list -]
|
||||
%else
|
||||
; === error.tmp ===
|
||||
error_start:
|
||||
|
||||
read_sector.err:
|
||||
mov al, 'R' ; Disk 'R'ead error
|
||||
%if ! _MEMORY_CONTINUE || _RELOCATE || _LOAD_ADR >= ADR_FREE_FROM
|
||||
@ -751,6 +817,11 @@ error:
|
||||
int 16h
|
||||
|
||||
int 19h ; re-start the boot process
|
||||
|
||||
%if _WARN_PART_SIZE
|
||||
%assign num $ - error_start
|
||||
%warning error size is num bytes
|
||||
%endif
|
||||
; === eof ===
|
||||
%endif
|
||||
%if _TMPINC
|
||||
@ -765,6 +836,7 @@ error:
|
||||
[list -]
|
||||
%else
|
||||
; === read.tmp ===
|
||||
read_sector_start:
|
||||
; INP: dx:ax = sector
|
||||
; OUT: only if successful
|
||||
; dx:ax = incremented
|
||||
@ -775,8 +847,24 @@ error:
|
||||
%if ADR_DIRBUF == ADR_FATBUF
|
||||
read_sector_dirbuf:
|
||||
%endif
|
||||
%if _FAT16 && ! _LOAD_NON_FAT
|
||||
read_sector_fatbuf:
|
||||
%endif
|
||||
%if (ADR_DIRBUF == ADR_FATBUF) || (_FAT16 && ! _LOAD_NON_FAT)
|
||||
mov bx, ADR_FATBUF>>4
|
||||
%if _FAT16 && _SET_FAT_SEG && ! _LOAD_NON_FAT
|
||||
mov word [VAR(fat_seg)], bx
|
||||
; Optimisation: Set FAT buffer segment here where
|
||||
; we have it ready in a register, instead of
|
||||
; wasting a word immediate on it. If the FAT is
|
||||
; never read then we do not need to set the
|
||||
; variable anyway, only the sector variable has
|
||||
; to contain a -1 to indicate it's uninitialised.
|
||||
; If we get here from read_sector_dirbuf we will
|
||||
; also initialise this variable but that does not
|
||||
; cause any problems.
|
||||
%endif
|
||||
%endif
|
||||
%endif
|
||||
|
||||
; Read a sector using Int13.02 or Int13.42
|
||||
@ -797,7 +885,7 @@ read_sector:
|
||||
push ax
|
||||
push si
|
||||
|
||||
push bx
|
||||
mov es, bx ; => buffer
|
||||
|
||||
; DX:AX==LBA sector number
|
||||
; add partition start (= number of hidden sectors)
|
||||
@ -839,17 +927,22 @@ read_sector:
|
||||
jc .no_lba
|
||||
cmp bx, 0AA55h
|
||||
jne .no_lba
|
||||
test cl, 1 ; support bitmap bit 0
|
||||
jz .no_lba
|
||||
shr cl, 1 ; support bitmap bit 0
|
||||
jnc .no_lba
|
||||
%endif
|
||||
|
||||
%if _LBA_RETRY
|
||||
%if _LBA_SKIP_CHECK && _LBA_SKIP_CY
|
||||
stc
|
||||
%endif
|
||||
mov ah, 42h
|
||||
int 13h ; 13.42 extensions read
|
||||
jnc .lba_done
|
||||
|
||||
%if _RETRY_RESET
|
||||
xor ax, ax
|
||||
int 13h
|
||||
int 13h ; reset disk
|
||||
%endif
|
||||
|
||||
; have to reset the LBAPACKET's lpCount, as the handler may
|
||||
; set it to "the number of blocks successfully transferred".
|
||||
@ -857,10 +950,17 @@ read_sector:
|
||||
mov byte [si + 2], 1
|
||||
%endif
|
||||
|
||||
%if _LBA_SKIP_CHECK && _LBA_SKIP_CY
|
||||
stc
|
||||
%endif
|
||||
mov ah, 42h
|
||||
int 13h
|
||||
%if _LBA_SKIP_CHECK && _CHS
|
||||
%if _LBA_SKIP_ANY
|
||||
jc .no_lba
|
||||
%else
|
||||
jc .lba_check_error_1
|
||||
%endif
|
||||
%else
|
||||
.cy_err:
|
||||
jc .lba_error
|
||||
@ -871,10 +971,8 @@ read_sector:
|
||||
mov byte [bp + 2], 0Eh ; LBA-enabled FAT16 FS partition type
|
||||
%endif
|
||||
add sp, 10h
|
||||
pop bx
|
||||
mov es, bx
|
||||
%if _CHS
|
||||
jmp short .chs_done
|
||||
jmp short .done
|
||||
%endif
|
||||
|
||||
.lba_error: equ .err
|
||||
@ -883,10 +981,12 @@ read_sector:
|
||||
.no_lba: equ .err
|
||||
%else
|
||||
%if _LBA_SKIP_CHECK
|
||||
%if ! _LBA_SKIP_ANY
|
||||
.lba_check_error_1:
|
||||
cmp ah, 1 ; invalid function?
|
||||
jne .lba_error ; no, other error -->
|
||||
; try CHS instead
|
||||
%endif
|
||||
.cy_err: equ .err
|
||||
%endif
|
||||
.no_lba:
|
||||
@ -955,29 +1055,50 @@ read_sector:
|
||||
|
||||
; we call INT 13h AH=02h once for each sector. Multi-sector reads
|
||||
; may fail if we cross a track or 64K boundary
|
||||
pop es
|
||||
%if _CHS_RETRY_REPEAT
|
||||
mov si, _CHS_RETRY_REPEAT + 1
|
||||
%if _CHS_RETRY_NORMAL && _RETRY_RESET
|
||||
db __TEST_IMM16 ; (skip int 13h)
|
||||
.loop_chs_retry_repeat:
|
||||
int 13h ; reset disk
|
||||
%elif _RETRY_RESET
|
||||
.loop_chs_retry_repeat:
|
||||
mov ax, 0201h
|
||||
int 13h ; read one sector
|
||||
jnc .done
|
||||
xor ax, ax
|
||||
int 13h ; reset disk
|
||||
%else
|
||||
.loop_chs_retry_repeat:
|
||||
%endif
|
||||
dec si ; another attempt ?
|
||||
jnz .loop_chs_retry_repeat ; yes -->
|
||||
jmp .err
|
||||
%else
|
||||
%if _CHS_RETRY
|
||||
js .nz_err ; no -->
|
||||
mov ax, 0201h
|
||||
int 13h ; read one sector
|
||||
%if _CHS_RETRY_NORMAL && _RETRY_RESET
|
||||
mov ax, bx ; ax = 0
|
||||
%endif
|
||||
jc .loop_chs_retry_repeat
|
||||
; fall through to .done
|
||||
%else
|
||||
mov ax, 0201h
|
||||
%if _CHS_RETRY
|
||||
%if _RETRY_RESET
|
||||
; In this case we cannot store to the stack and
|
||||
; pop the value at the right moment for both
|
||||
; cases of the "jnc .done" branch. So use the
|
||||
; original code to re-init ax to 0201h.
|
||||
int 13h ; read one sector
|
||||
jnc .done
|
||||
; reset drive
|
||||
xor ax, ax
|
||||
int 13h
|
||||
mov ax, 0201h
|
||||
%else
|
||||
push ax
|
||||
int 13h ; read one sector
|
||||
pop ax ; restore ax = 0201h
|
||||
jnc .done
|
||||
%endif
|
||||
%endif
|
||||
; try read again
|
||||
mov ax, 0201h
|
||||
int 13h
|
||||
%if _LBA_SKIP_CHECK
|
||||
inc bx
|
||||
@ -987,12 +1108,11 @@ read_sector:
|
||||
%endif
|
||||
%endif
|
||||
|
||||
%endif ; _CHS
|
||||
|
||||
.done:
|
||||
; increment segment
|
||||
mov bx, es
|
||||
%endif
|
||||
|
||||
.chs_done:
|
||||
%if _FIX_SECTOR_SIZE
|
||||
add bx, _FIX_SECTOR_SIZE >> 4
|
||||
%else
|
||||
@ -1010,6 +1130,11 @@ read_sector:
|
||||
@@:
|
||||
|
||||
retn
|
||||
|
||||
%if _WARN_PART_SIZE
|
||||
%assign num $ - read_sector_start
|
||||
%warning read_sector size is num bytes
|
||||
%endif
|
||||
; === eof ===
|
||||
%endif
|
||||
%if _TMPINC
|
||||
@ -1020,6 +1145,11 @@ read_sector:
|
||||
[list +]
|
||||
%endif
|
||||
|
||||
%if _WARN_PART_SIZE
|
||||
%assign num $ - start
|
||||
%warning BPB + data size is num bytes
|
||||
%endif
|
||||
|
||||
|
||||
; Code
|
||||
|
||||
@ -1045,6 +1175,8 @@ skip_bpb:
|
||||
; FF FF FF FF 08 00 08 01 FF FF FF FF FF FF FF FF, which was detected
|
||||
; as a valid partition table entry by this handling. Therefore, we
|
||||
; only accept partition information when booting from a hard disk now.
|
||||
|
||||
; start of magic byte sequence for instsect
|
||||
test dl, dl ; floppy ?
|
||||
jns @F ; don't attempt detection -->
|
||||
; Check whether an MBR left us partition information.
|
||||
@ -1058,15 +1190,23 @@ skip_bpb:
|
||||
; Assume the movsw instructions won't run with si = FFFFh.
|
||||
mov di, hidden_sectors ; -> BPB field
|
||||
add si, 8 ; -> partition start sector in info
|
||||
%if _USE_PART_INFO_DISABLED
|
||||
nop
|
||||
nop ; size has to match enabled code
|
||||
%else
|
||||
movsw
|
||||
movsw ; overwrite BPB field with value from info
|
||||
%endif
|
||||
@@:
|
||||
; end of magic byte sequence for instsect
|
||||
%endif
|
||||
mov ds, cx
|
||||
sti
|
||||
|
||||
|
||||
%if _QUERY_GEOMETRY ; +27 bytes
|
||||
|
||||
; start of magic byte sequence for instsect
|
||||
; test dl, dl ; floppy?
|
||||
; jns @F ; don't attempt query, might fail -->
|
||||
; Note that while the original PC BIOS doesn't support this function
|
||||
@ -1076,7 +1216,12 @@ skip_bpb:
|
||||
; xor cx, cx ; initialise cl to 0
|
||||
; Already from prologue cx = 0.
|
||||
stc ; initialise to CY
|
||||
%if _QUERY_GEOMETRY_DISABLED
|
||||
nop
|
||||
nop ; size has to match enabled code
|
||||
%else
|
||||
int 13h ; query drive geometry
|
||||
%endif
|
||||
jc @F ; apparently failed -->
|
||||
and cx, 3Fh ; get sectors
|
||||
jz @F ; invalid (S is 1-based), don't use -->
|
||||
@ -1085,6 +1230,7 @@ skip_bpb:
|
||||
inc cx ; cx = number of heads (H is 0-based)
|
||||
mov [VAR(heads)], cx
|
||||
@@:
|
||||
; end of magic byte sequence for instsect
|
||||
%endif
|
||||
|
||||
%if _FIX_SECTOR_SIZE
|
||||
@ -1100,15 +1246,6 @@ skip_bpb:
|
||||
mov al, 'C'
|
||||
jne error
|
||||
%endif
|
||||
%else
|
||||
; calculate some values that we need:
|
||||
; adjusted sectors per cluster (store in a word,
|
||||
; and decode EDR-DOS's special value 0 meaning 256)
|
||||
xor ax, ax
|
||||
mov al, [VAR(sectors_per_cluster)]
|
||||
dec al
|
||||
inc ax
|
||||
push ax ; push into word [VAR(adj_sectors_per_cluster)]
|
||||
%endif
|
||||
mov ch, 0 ; ! ch = 0
|
||||
%else
|
||||
@ -1123,16 +1260,7 @@ skip_bpb:
|
||||
jne error
|
||||
%endif
|
||||
%else
|
||||
; calculate some values that we need:
|
||||
; adjusted sectors per cluster (store in a word,
|
||||
; and decode EDR-DOS's special value 0 meaning 256)
|
||||
; ! ch = 0
|
||||
mov cl, [VAR(sectors_per_cluster)]
|
||||
; therefore cx = sectors_per_cluster
|
||||
dec cl
|
||||
inc cx
|
||||
push cx ; push into word [VAR(adj_sectors_per_cluster)]
|
||||
dec cx ; ! ch = 0
|
||||
%endif
|
||||
push bx ; push into word [VAR(para_per_sector)]
|
||||
|
||||
@ -1140,6 +1268,14 @@ skip_bpb:
|
||||
shr bx, 1 ; /2 = 32-byte entries per sector
|
||||
%endif
|
||||
|
||||
%if _WARN_PART_SIZE
|
||||
%assign num $ - skip_bpb
|
||||
%warning init size is num bytes
|
||||
%endif
|
||||
|
||||
|
||||
dirsearch_start:
|
||||
|
||||
; number of sectors used for root directory (store in CX)
|
||||
mov si, [VAR(num_root_dir_ents)]
|
||||
mov ax, bx
|
||||
@ -1194,21 +1330,48 @@ next_sect:
|
||||
|
||||
xor di, di ; es:di-> first entry in this sector
|
||||
next_ent:
|
||||
%if DIRSEARCHSTACK_CL_FIRST
|
||||
push cx ; first dirsearchstack word = entries-in-sector
|
||||
push si ; other: entries total
|
||||
%else
|
||||
push si
|
||||
push di
|
||||
push cx
|
||||
push cx ; second dirsearchstack word = entries-in-sector
|
||||
%endif
|
||||
push di ; dirsearchstack
|
||||
%if _CHECK_ATTRIB && ! _ATTRIB_SAVE
|
||||
test byte [es:di + deAttrib], ATTR_DIRECTORY | ATTR_VOLLABEL
|
||||
jnz @F ; directory, label, or LFN entry --> (NZ)
|
||||
%endif
|
||||
%if _ADD_SEARCH
|
||||
mov si, [VAR(filename)]
|
||||
mov si, add_name
|
||||
filename equ $ - 2 ; SMC to update to load_name later
|
||||
%else
|
||||
mov si, load_name ; ds:si-> name to match
|
||||
%endif
|
||||
mov cx, 11 ; length of padded 8.3 FAT filename
|
||||
repe cmpsb ; check entry
|
||||
pop cx
|
||||
%if _ATTRIB_SAVE
|
||||
%if _CHECK_ATTRIB
|
||||
jnz @F
|
||||
; deAttrib == 11, right after the 11-byte name
|
||||
test byte [es:di], ATTR_DIRECTORY | ATTR_VOLLABEL
|
||||
; directory, label, or LFN entry ?
|
||||
%endif
|
||||
jz found_it ; found entry -->
|
||||
%endif
|
||||
@@:
|
||||
pop di
|
||||
%if DIRSEARCHSTACK_CL_FIRST
|
||||
pop si
|
||||
pop cx ; pop from dirsearchstack
|
||||
%else
|
||||
pop cx
|
||||
pop si ; pop from dirsearchstack
|
||||
%endif
|
||||
lea di, [di + DIRENTRY_size]
|
||||
je found_it ; found entry -->
|
||||
%if ! _ATTRIB_SAVE
|
||||
jz found_it ; found entry -->
|
||||
%endif
|
||||
|
||||
dec si ; count down entire root's entries
|
||||
loopnz next_ent ; count down sector's entries (jumps iff si >0 && cx >0)
|
||||
@ -1249,9 +1412,14 @@ Reference: https://bugs.launchpad.net/qemu/+bug/1888165
|
||||
|
||||
found_it:
|
||||
%if _ADD_SEARCH || _LOAD_DIR_SEG
|
||||
%if _ATTRIB_SAVE
|
||||
pop di ; es:di -> dir entry (pop from dirsearchstack)
|
||||
%endif
|
||||
mov cx, 32
|
||||
mov ax, _LOAD_DIR_SEG
|
||||
%if ! _ATTRIB_SAVE
|
||||
sub di, cx ; es:di -> dir entry
|
||||
%endif
|
||||
%if _ADD_SEARCH
|
||||
xchg ax, word [VAR(dirseg)]
|
||||
%endif
|
||||
@ -1281,12 +1449,18 @@ found_it:
|
||||
%else
|
||||
%error Must not store directory entries to same segment
|
||||
%endif
|
||||
%if _ATTRIB_SAVE
|
||||
pop si ; discard cx/si
|
||||
pop si ; discard si/cx (dirsearchstack)
|
||||
%endif
|
||||
pop si
|
||||
pop ax
|
||||
pop dx ; restore root start and count
|
||||
; (bx still holds entries per sector)
|
||||
je next_dir_search ; jump to search load file next -->
|
||||
%endif
|
||||
times PLACEHOLDER push bx
|
||||
; push into cmdline_signature_placeholder
|
||||
%if _RELOCATE
|
||||
push word [es:di + deClusterLow]
|
||||
; (word on stack) = first cluster number
|
||||
@ -1294,10 +1468,14 @@ found_it:
|
||||
%else
|
||||
%if _DIR_ENTRY_500 ; +24 bytes, probably
|
||||
mov cx, 32
|
||||
push ds
|
||||
push es
|
||||
%if _ATTRIB_SAVE
|
||||
pop si ; es:si -> dir entry (pop from dirsearchstack)
|
||||
%else
|
||||
xchg si, di
|
||||
sub si, cx
|
||||
%endif
|
||||
push ds
|
||||
push es
|
||||
push es
|
||||
pop ds ; ds:si -> directory entry
|
||||
xor ax, ax
|
||||
@ -1312,14 +1490,30 @@ found_it:
|
||||
pop ds
|
||||
xchg si, di ; es:di -> behind (second) directory entry
|
||||
%endif
|
||||
times PLACEHOLDER push bx
|
||||
; push into cmdline_signature_placeholder
|
||||
; Push the entries per sector value into this
|
||||
; stack slot to ensure that it does not hold "CL".
|
||||
%if _RELOCATE
|
||||
%if _DIR_ENTRY_500 || !_ATTRIB_SAVE
|
||||
push word [es:di + deClusterLow - DIRENTRY_size \
|
||||
- (DIRENTRY_size * !!_DIR_ENTRY_520)]
|
||||
; (word on stack) = first cluster number
|
||||
%else
|
||||
push word [es:di + deClusterLow - (deName + 11)]
|
||||
; (word on stack) = first cluster number
|
||||
%endif
|
||||
%endif
|
||||
%endif
|
||||
|
||||
%if _WARN_PART_SIZE
|
||||
%assign num $ - dirsearch_start
|
||||
%warning dirsearch size is num bytes
|
||||
%endif
|
||||
|
||||
|
||||
%if _RELOCATE || _LOAD_ADR >= ADR_FREE_FROM
|
||||
memory_start:
|
||||
; Get conventional memory size and store it
|
||||
int 12h
|
||||
mov cl, 6
|
||||
@ -1406,6 +1600,11 @@ found_it:
|
||||
rep movsw ; relocate stack, sector
|
||||
retf ; jump to relocated code
|
||||
|
||||
%if _WARN_PART_SIZE
|
||||
%assign num $ - memory_start
|
||||
%warning memory size is num bytes
|
||||
%endif
|
||||
|
||||
|
||||
readhandler
|
||||
|
||||
@ -1442,10 +1641,13 @@ relocated:
|
||||
push ax ; push into word [VAR(last_available_sector)]
|
||||
%endif
|
||||
|
||||
read_fat_start:
|
||||
; get starting cluster of file
|
||||
%if ! _RELOCATE
|
||||
%if _ADD_SEARCH || _LOAD_DIR_SEG
|
||||
mov si,[es:di + deClusterLow]
|
||||
%elif _ATTRIB_SAVE && ! _DIR_ENTRY_500
|
||||
mov si,[es:di - deAttrib + deClusterLow]
|
||||
%else
|
||||
mov si,[es:di + deClusterLow - DIRENTRY_size \
|
||||
- (DIRENTRY_size * !!_DIR_ENTRY_520)]
|
||||
@ -1510,10 +1712,9 @@ relocated:
|
||||
mov bx, _LOAD_ADR>>4 ; => load address
|
||||
%if _FAT16 && !_LOAD_NON_FAT
|
||||
mov di, -1 ; = no FAT sector read yet
|
||||
%if _SET_FAT_SEG
|
||||
%if ! _RELOCATE
|
||||
mov word [VAR(fat_seg)], ADR_FATBUF>>4
|
||||
%endif
|
||||
%if _SET_FAT_SEG && _SET_FAT_SEG_NORMAL
|
||||
; This is not strictly needed because a FAT sector is
|
||||
; read in any case, initialising this variable later.
|
||||
mov word [VAR(fat_sector)], di
|
||||
%endif
|
||||
%endif
|
||||
@ -1637,7 +1838,10 @@ next_cluster:
|
||||
|
||||
%else ; _LOAD_NON_FAT
|
||||
mov di, _LOAD_NON_FAT
|
||||
mov ax, word [VAR(adj_sectors_per_cluster)]
|
||||
mov al, [VAR(sectors_per_cluster)]
|
||||
dec ax
|
||||
mov ah, 0
|
||||
inc ax
|
||||
mov cx, ax
|
||||
mul word [VAR(bytes_per_sector)]
|
||||
test dx, dx
|
||||
@ -1656,7 +1860,12 @@ next_cluster:
|
||||
%if _FIX_CLUSTER_SIZE
|
||||
mov cx, _FIX_CLUSTER_SIZE
|
||||
%else
|
||||
mov cx, [VAR(adj_sectors_per_cluster)]
|
||||
; adjusted sectors per cluster
|
||||
; decode EDR-DOS's special value 0 meaning 256
|
||||
mov cl, [VAR(sectors_per_cluster)]
|
||||
dec cx
|
||||
mov ch, 0
|
||||
inc cx
|
||||
%endif
|
||||
%endif
|
||||
|
||||
@ -1669,7 +1878,7 @@ next_cluster:
|
||||
; xxx - this will always load an entire cluster (e.g. 64 sectors),
|
||||
; even if the file is shorter than this
|
||||
@@:
|
||||
%if _LOAD_ADR < ADR_FREE_UNTIL && _FIX_SECTOR_SIZE
|
||||
%if ! _RELOCATE && _LOAD_ADR < ADR_FREE_UNTIL && _FIX_SECTOR_SIZE
|
||||
cmp bx, (ADR_FREE_UNTIL >> 4) - (_FIX_SECTOR_SIZE >> 4)
|
||||
%else
|
||||
cmp bx, [VAR(last_available_sector)]
|
||||
@ -1708,8 +1917,21 @@ next_cluster:
|
||||
%endif ; _LOAD_NON_FAT
|
||||
@@:
|
||||
|
||||
%if _WARN_PART_SIZE
|
||||
%assign num $ - read_fat_start
|
||||
%warning read_fat size is num bytes
|
||||
%endif
|
||||
|
||||
|
||||
finish_start:
|
||||
%if _LOAD_MIN_PARA
|
||||
%if ((_LOAD_ADR >> 4) + _LOAD_MIN_PARA) & 255 == 0
|
||||
; If the value is divisible by 256 we can compare only the
|
||||
; high byte for the same CF result: NC iff bx >= limit.
|
||||
cmp bh, ((_LOAD_ADR >> 4) + _LOAD_MIN_PARA) >> 8
|
||||
%else
|
||||
cmp bx, (_LOAD_ADR >> 4) + _LOAD_MIN_PARA
|
||||
%endif
|
||||
mov al, 'E'
|
||||
jb error
|
||||
%endif
|
||||
@ -1827,6 +2049,12 @@ CHECKLINEAR equ _LOAD_ADR + _CHECKOFFSET
|
||||
jmp (_LOAD_ADR>>4)+_EXEC_SEG_ADJ:_EXEC_OFS
|
||||
|
||||
|
||||
%if _WARN_PART_SIZE
|
||||
%assign num $ - finish_start
|
||||
%warning finish size is num bytes
|
||||
%endif
|
||||
|
||||
|
||||
%if ! _RELOCATE
|
||||
errorhandler
|
||||
|
||||
|
@ -44,7 +44,9 @@ Public domain by C. Masloch, 2012
|
||||
numdef ADD_DIR_SEG, 0 ; => where to store dir entry (0 if nowhere)
|
||||
|
||||
numdef QUERY_GEOMETRY, 1 ; query geometry via 13.08 (for CHS access)
|
||||
numdef QUERY_GEOMETRY_DISABLED, 0
|
||||
numdef USE_PART_INFO, 1 ; use ds:si-> partition info from MBR, if any
|
||||
numdef USE_PART_INFO_DISABLED, 0
|
||||
numdef USE_AUTO_UNIT, 1 ; use unit passed from ROM-BIOS in dl
|
||||
numdef RPL, 1 ; support RPL and do not overwrite it
|
||||
numdef CHS, 1 ; support CHS (if it fits)
|
||||
@ -75,11 +77,18 @@ Public domain by C. Masloch, 2012
|
||||
numdef FIX_CLUSTER_SIZE_SKIP_CHECK, 0 ; don't check cluster size
|
||||
numdef NO_LIMIT, 0 ; allow using more memory than a boot sector
|
||||
; also will not write 0AA55h signature!
|
||||
numdef WARN_PART_SIZE, 0
|
||||
|
||||
numdef LBA_SKIP_CHECK, 1 ; don't use proper LBA extensions check
|
||||
numdef LBA_SKIP_CY, 1 ; skip check: set up CY before 13.42
|
||||
numdef LBA_SKIP_ANY, 0 ; skip check: try CHS on any error
|
||||
incdef _LBA_SKIP_ANY, LBA_SKIP_CY
|
||||
numdef LBA_RETRY, 0 ; retry LBA reads one time
|
||||
numdef CHS_RETRY, 1 ; retry CHS reads one time
|
||||
numdef CHS_RETRY_REPEAT,16 ; retry CHS reads multiple times
|
||||
; (value of the def is used as count)
|
||||
numdef CHS_RETRY_NORMAL,1 ; do not use aggressive optimisation
|
||||
numdef RETRY_RESET, 1 ; call reset disk system 13.00 on retries
|
||||
|
||||
; Unlike the 1440 KiB diskette image defaults for the FAT12
|
||||
; loader we just fill the BPB with zeros by default.
|
||||
@ -615,6 +624,14 @@ fsiboot_table: ; this table is used by the FSIBOOT stage
|
||||
; => directory sector buffer (one sector)
|
||||
%endif
|
||||
.writedirentry: dw writedirentry.loaddir
|
||||
; INP: es:bx -> found dir entry in dir sector buffer
|
||||
; si:di = loaded sector-in-FAT
|
||||
; CHG: ax, cx, dx
|
||||
; STT: ss:bp -> boot sector
|
||||
; ds = ss
|
||||
; UP
|
||||
; OUT: directory entry copied if so desired
|
||||
; (is a no-op if not to copy dir entry)
|
||||
.filename: dw .load_name
|
||||
; -> name to search
|
||||
.minpara: dw _LOAD_MIN_PARA
|
||||
@ -628,6 +645,11 @@ fsiboot_table: ; this table is used by the FSIBOOT stage
|
||||
fsiboot_name:
|
||||
fill 8, 32, db _FSIBOOTNAME
|
||||
|
||||
%if _WARN_PART_SIZE
|
||||
%assign num $ - start
|
||||
%warning BPB + data size is num bytes
|
||||
%endif
|
||||
|
||||
|
||||
; Code
|
||||
|
||||
@ -654,6 +676,8 @@ skip_bpb:
|
||||
; FF FF FF FF 08 00 08 01 FF FF FF FF FF FF FF FF, which was detected
|
||||
; as a valid partition table entry by this handling. Therefore, we
|
||||
; only accept partition information when booting from a hard disk now.
|
||||
|
||||
; start of magic byte sequence for instsect
|
||||
test dl, dl ; floppy ?
|
||||
jns @F ; don't attempt detection -->
|
||||
; Check whether an MBR left us partition information.
|
||||
@ -667,15 +691,23 @@ skip_bpb:
|
||||
; Assume the movsw instructions won't run with si = FFFFh.
|
||||
mov di, hidden_sectors ; -> BPB field
|
||||
add si, 8 ; -> partition start sector in info
|
||||
%if _USE_PART_INFO_DISABLED
|
||||
nop
|
||||
nop ; size has to match enabled code
|
||||
%else
|
||||
movsw
|
||||
movsw ; overwrite BPB field with value from info
|
||||
%endif
|
||||
@@:
|
||||
; end of magic byte sequence for instsect
|
||||
%endif
|
||||
mov ds, cx
|
||||
sti
|
||||
|
||||
|
||||
%if _QUERY_GEOMETRY ; +27 bytes
|
||||
|
||||
; start of magic byte sequence for instsect
|
||||
; test dl, dl ; floppy?
|
||||
; jns @F ; don't attempt query, might fail -->
|
||||
; Note that while the original PC BIOS doesn't support this function
|
||||
@ -685,7 +717,12 @@ skip_bpb:
|
||||
; xor cx, cx ; initialise cl to 0
|
||||
; Already from prologue cx = 0.
|
||||
stc ; initialise to CY
|
||||
%if _QUERY_GEOMETRY_DISABLED
|
||||
nop
|
||||
nop ; size has to match enabled code
|
||||
%else
|
||||
int 13h ; query drive geometry
|
||||
%endif
|
||||
jc @F ; apparently failed -->
|
||||
and cx, 3Fh ; get sectors
|
||||
jz @F ; invalid (S is 1-based), don't use -->
|
||||
@ -694,6 +731,7 @@ skip_bpb:
|
||||
inc cx ; cx = number of heads (H is 0-based)
|
||||
mov [VAR(heads)], cx
|
||||
@@:
|
||||
; end of magic byte sequence for instsect
|
||||
%endif
|
||||
|
||||
|
||||
@ -854,6 +892,13 @@ load_fsiboot:
|
||||
%endif
|
||||
|
||||
|
||||
%if _WARN_PART_SIZE
|
||||
%assign num $ - skip_bpb
|
||||
%warning init size is num bytes
|
||||
%endif
|
||||
|
||||
|
||||
finish_start:
|
||||
; INP: es:bx -> found dir entry in dir sector buffer
|
||||
; si:di = loaded sector-in-FAT
|
||||
; CHG: ax, cx, dx
|
||||
@ -1030,6 +1075,13 @@ CHECKLINEAR equ _LOAD_ADR + _CHECKOFFSET
|
||||
; ss:bp-> boot sector with BPB
|
||||
jmp (_LOAD_ADR>>4)+_EXEC_SEG_ADJ:_EXEC_OFS
|
||||
|
||||
%if _WARN_PART_SIZE
|
||||
%assign num $ - finish_start
|
||||
%warning finish size is num bytes
|
||||
%endif
|
||||
|
||||
|
||||
error_start:
|
||||
|
||||
error_fsiboot:
|
||||
mov al,'I'
|
||||
@ -1057,6 +1109,11 @@ error:
|
||||
|
||||
int 19h ; re-start the boot process
|
||||
|
||||
%if _WARN_PART_SIZE
|
||||
%assign num $ - error_start
|
||||
%warning error size is num bytes
|
||||
%endif
|
||||
|
||||
|
||||
; Read a sector using Int13.02 or Int13.42
|
||||
;
|
||||
@ -1076,7 +1133,7 @@ read_sector:
|
||||
push ax
|
||||
push si
|
||||
|
||||
push bx
|
||||
mov es, bx ; => buffer
|
||||
|
||||
; DX:AX==LBA sector number
|
||||
; add partition start (= number of hidden sectors)
|
||||
@ -1118,17 +1175,22 @@ read_sector:
|
||||
jc .no_lba
|
||||
cmp bx, 0AA55h
|
||||
jne .no_lba
|
||||
test cl, 1 ; support bitmap bit 0
|
||||
jz .no_lba
|
||||
shr cl, 1 ; support bitmap bit 0
|
||||
jnc .no_lba
|
||||
%endif
|
||||
|
||||
%if _LBA_RETRY
|
||||
%if _LBA_SKIP_CHECK && _LBA_SKIP_CY
|
||||
stc
|
||||
%endif
|
||||
mov ah, 42h
|
||||
int 13h ; 13.42 extensions read
|
||||
jnc .lba_done
|
||||
|
||||
%if _RETRY_RESET
|
||||
xor ax, ax
|
||||
int 13h
|
||||
int 13h ; reset disk
|
||||
%endif
|
||||
|
||||
; have to reset the LBAPACKET's lpCount, as the handler may
|
||||
; set it to "the number of blocks successfully transferred".
|
||||
@ -1136,15 +1198,24 @@ read_sector:
|
||||
mov byte [si + 2], 1
|
||||
%endif
|
||||
|
||||
%if _LBA_SKIP_CHECK && _LBA_SKIP_CY
|
||||
stc
|
||||
%endif
|
||||
mov ah, 42h
|
||||
int 13h
|
||||
%if _LBA_SKIP_CHECK && _CHS
|
||||
%if _LBA_SKIP_ANY
|
||||
jc .no_lba
|
||||
.err_CY: equ .err
|
||||
.err_2: equ .err
|
||||
%else
|
||||
jnc .lba_done
|
||||
cmp ah, 1 ; invalid function?
|
||||
je .no_lba ; try CHS instead -->
|
||||
.err_CY:
|
||||
.err_2:
|
||||
jmp .lba_error
|
||||
%endif
|
||||
%else
|
||||
.err_CY:
|
||||
jc .lba_error
|
||||
@ -1156,10 +1227,8 @@ read_sector:
|
||||
mov byte [bp + 2], 0Ch ; LBA-enabled FAT32 FS partition type
|
||||
%endif
|
||||
add sp, 10h
|
||||
pop bx
|
||||
mov es, bx
|
||||
%if _CHS
|
||||
jmp short .chs_done
|
||||
jmp short .done
|
||||
%endif
|
||||
|
||||
.lba_error: equ .err
|
||||
@ -1225,34 +1294,56 @@ read_sector:
|
||||
; ah has bits set iff it was >= 4, indicating a cylinder >= 1024.
|
||||
or bl, ah ; collect set bits from ah
|
||||
mov dl,[VAR(boot_unit)] ; dl = drive
|
||||
.nz_err:
|
||||
jnz .err_2 ; error if cylinder >= 1024 -->
|
||||
; ! bx = 0 (for 13.02 call)
|
||||
|
||||
; we call INT 13h AH=02h once for each sector. Multi-sector reads
|
||||
; may fail if we cross a track or 64K boundary
|
||||
pop es
|
||||
%if _CHS_RETRY_REPEAT
|
||||
mov si, _CHS_RETRY_REPEAT + 1
|
||||
%if _CHS_RETRY_NORMAL && _RETRY_RESET
|
||||
db __TEST_IMM16 ; (skip int 13h)
|
||||
.loop_chs_retry_repeat:
|
||||
int 13h ; reset disk
|
||||
%elif _RETRY_RESET
|
||||
.loop_chs_retry_repeat:
|
||||
mov ax, 0201h
|
||||
int 13h ; read one sector
|
||||
jnc .done
|
||||
xor ax, ax
|
||||
int 13h ; reset disk
|
||||
%else
|
||||
.loop_chs_retry_repeat:
|
||||
%endif
|
||||
dec si ; another attempt ?
|
||||
jnz .loop_chs_retry_repeat ; yes -->
|
||||
jmp .err_2
|
||||
%else
|
||||
%if _CHS_RETRY
|
||||
js .nz_err ; no -->
|
||||
mov ax, 0201h
|
||||
int 13h ; read one sector
|
||||
%if _CHS_RETRY_NORMAL && _RETRY_RESET
|
||||
mov ax, bx ; ax = 0
|
||||
%endif
|
||||
jc .loop_chs_retry_repeat
|
||||
; fall through to .done
|
||||
%else
|
||||
mov ax, 0201h
|
||||
%if _CHS_RETRY
|
||||
%if _RETRY_RESET
|
||||
; In this case we cannot store to the stack and
|
||||
; pop the value at the right moment for both
|
||||
; cases of the "jnc .done" branch. So use the
|
||||
; original code to re-init ax to 0201h.
|
||||
int 13h ; read one sector
|
||||
jnc .done
|
||||
; reset drive
|
||||
xor ax, ax
|
||||
int 13h
|
||||
mov ax, 0201h
|
||||
%else
|
||||
push ax
|
||||
int 13h ; read one sector
|
||||
pop ax ; restore ax = 0201h
|
||||
jnc .done
|
||||
%endif
|
||||
%endif
|
||||
; try read again
|
||||
mov ax, 0201h
|
||||
int 13h
|
||||
jc .err_CY
|
||||
%endif
|
||||
@ -1260,12 +1351,11 @@ read_sector:
|
||||
.err_CY: equ .err
|
||||
%endif
|
||||
|
||||
%endif ; _CHS
|
||||
|
||||
.done:
|
||||
; increment segment
|
||||
mov bx, es
|
||||
%endif
|
||||
|
||||
.chs_done:
|
||||
%if _FIX_SECTOR_SIZE
|
||||
add bx, _FIX_SECTOR_SIZE >> 4
|
||||
%else
|
||||
@ -1285,6 +1375,11 @@ read_sector:
|
||||
.retn:
|
||||
retn
|
||||
|
||||
%if _WARN_PART_SIZE
|
||||
%assign num $ - read_sector
|
||||
%warning read_sector size is num bytes
|
||||
%endif
|
||||
|
||||
|
||||
%if _ADD_SEARCH
|
||||
add_name: ; = blank-padded 11-byte filename to search for
|
||||
@ -1381,9 +1476,9 @@ fsiboot:
|
||||
|
||||
; adjusted sectors per cluster (store in a word,
|
||||
; and decode EDR-DOS's special value 0 meaning 256)
|
||||
xor ax, ax
|
||||
mov al, [VAR(sectors_per_cluster)]
|
||||
dec al
|
||||
dec ax
|
||||
mov ah, 0
|
||||
inc ax
|
||||
push ax ; push into word [VAR(adj_sectors_per_cluster)]
|
||||
dec ax ; ! ah = 0
|
||||
@ -1483,13 +1578,11 @@ found_load_file:
|
||||
jc ..@CY_3_fsiboot_error_badchain
|
||||
|
||||
next_load_cluster:
|
||||
push dx
|
||||
push ax ; preserve cluster number for later
|
||||
call clust_to_first_sector
|
||||
; dx:ax = first sector of cluster
|
||||
; cx:bx = cluster value
|
||||
push cx
|
||||
push bx ; preserve cluster number for later
|
||||
|
||||
mov cx, [VAR(adj_sectors_per_cluster)]
|
||||
; cx = adjusted sectors per cluster
|
||||
|
||||
; xxx - this will always load an entire cluster (e.g. 64 sectors),
|
||||
; even if the file is shorter than this
|
||||
@ -1510,8 +1603,8 @@ next_load_cluster:
|
||||
jbe @F ; read enough -->
|
||||
|
||||
loop @BB
|
||||
pop bx
|
||||
pop cx
|
||||
pop ax
|
||||
pop dx
|
||||
|
||||
call clust_next
|
||||
jnc next_load_cluster
|
||||
@ -1536,10 +1629,11 @@ dirsearch:
|
||||
jc fsiboot_error_badchain
|
||||
|
||||
next_root_clust:
|
||||
push dx
|
||||
push ax
|
||||
call clust_to_first_sector
|
||||
push cx
|
||||
push bx
|
||||
mov cx, [VAR(adj_sectors_per_cluster)]
|
||||
; dx:ax = first sector of cluster
|
||||
; cx = adjusted sectors per cluster
|
||||
next_root_sect:
|
||||
push cx
|
||||
mov cx, [VAR(entries_per_sector)]
|
||||
@ -1572,8 +1666,8 @@ next_ent:
|
||||
pop di
|
||||
pop cx
|
||||
loop next_root_sect
|
||||
pop bx
|
||||
pop cx
|
||||
pop ax
|
||||
pop dx
|
||||
call clust_next
|
||||
jnc next_root_clust
|
||||
file_not_found:
|
||||
@ -1587,22 +1681,22 @@ fsiboot_error:
|
||||
|
||||
|
||||
; INP: dx:ax = cluster - 2 (0-based cluster)
|
||||
; OUT: cx:bx = input dx:ax
|
||||
; dx:ax = first sector of that cluster
|
||||
; CHG: -
|
||||
; OUT: dx:ax = first sector of that cluster
|
||||
; cx = adjusted sectors per cluster
|
||||
; CHG: bx
|
||||
clust_to_first_sector:
|
||||
push dx
|
||||
push ax
|
||||
mov cx, word [VAR(adj_sectors_per_cluster)]
|
||||
push dx
|
||||
mul word [VAR(adj_sectors_per_cluster)]
|
||||
mul cx
|
||||
xchg bx, ax
|
||||
xchg cx, dx
|
||||
pop ax
|
||||
mul word [VAR(adj_sectors_per_cluster)]
|
||||
push dx
|
||||
mul cx
|
||||
test dx, dx
|
||||
jnz fsiboot_error_badchain
|
||||
xchg dx, ax
|
||||
add dx, cx
|
||||
pop ax
|
||||
add dx, ax
|
||||
jc ..@CY_fsiboot_error_badchain
|
||||
xchg ax, bx
|
||||
|
||||
@ -1611,8 +1705,6 @@ clust_to_first_sector:
|
||||
..@CY_fsiboot_error_badchain:
|
||||
jc fsiboot_error_badchain
|
||||
; dx:ax = first sector in cluster
|
||||
pop bx
|
||||
pop cx ; cx:bx = cluster
|
||||
retn
|
||||
|
||||
|
||||
@ -1638,16 +1730,14 @@ found_it:
|
||||
retn
|
||||
|
||||
|
||||
; INP: cx:bx = cluster (0-based)
|
||||
; INP: dx:ax = cluster (0-based)
|
||||
; si:di = loaded FAT sector, -1 if none
|
||||
; OUT: CY if no next cluster
|
||||
; NC if next cluster found,
|
||||
; dx:ax = next cluster value (0-based)
|
||||
; NC if next cluster found
|
||||
; dx:ax = next cluster value (0-based)
|
||||
; si:di = loaded FAT sector
|
||||
; CHG: cx, bx, es
|
||||
clust_next:
|
||||
xchg ax, bx ; ax = low word cluster, clobbers bx
|
||||
mov dx, cx
|
||||
add ax, 2
|
||||
adc dx, 0
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
\cfg{html-leaf-level}{0}
|
||||
\cfg{html-template-fragment}{%k}{%b}
|
||||
\cfg{html-head-end}{<meta name="viewport" content="width=device-width, initial-scale=1.0">}
|
||||
\cfg{html-heading-hashtag-links}{true}
|
||||
|
||||
\cfg{pdf-filename}{ldosboot.pdf}
|
||||
|
||||
@ -53,6 +54,27 @@ The entrypoint is found by applying no segment adjustment (0)
|
||||
and choosing the offset 400h (1024).
|
||||
|
||||
|
||||
\S{protocol-sector-iniload-file} File properties
|
||||
|
||||
The file must be at least 4096 bytes long.
|
||||
This is now required, beyond the former lower bound of 1536 bytes,
|
||||
to support an optimisation of the FAT12 and FAT16 boot sector loaders.
|
||||
The lDebug loader and the FAT32+FSIBOOT loader currently retain the 1536 bytes limit.
|
||||
|
||||
The file may allow multi-use as a flat .COM format executable,
|
||||
flat .SYS format device driver, or MZ .EXE format executable
|
||||
and/or device driver.
|
||||
It is also valid to append arbitrary sized data such as a .ZIP archive.
|
||||
|
||||
The file needs to be placed in the root directory for the boot sector loaders.
|
||||
The lDebug loader allows to load a file
|
||||
from any subdirectory and this is also allowed.
|
||||
The file may be fragmented in any part.
|
||||
The file data may be located anywhere in the file system.
|
||||
The supported cluster sizes should be between 32 Bytes and 2 MiB, inclusive.
|
||||
The sector size should be between 32 Bytes and 8 KiB, inclusive.
|
||||
|
||||
|
||||
\S{protocol-sector-iniload-signatures} Signatures
|
||||
|
||||
At offset 1020 (3FCh) there is the signature \cq{lD}.
|
||||
@ -79,6 +101,10 @@ Currently the following signatures are defined:
|
||||
|
||||
\dd lDDebug (debuggable lDebug)
|
||||
|
||||
\dt \cq{lDbC}
|
||||
|
||||
\dd lCDebug (conditionally debuggable lDebug)
|
||||
|
||||
\dt \cq{lDTP}
|
||||
|
||||
\dd lDOS test payload kernel (testpl.asm)
|
||||
@ -92,6 +118,7 @@ Currently the following signatures are defined:
|
||||
|
||||
Under this protocol, the pointer \cq{ss:bp} is passed.
|
||||
It points to a boot sector with (E)BPB.
|
||||
\cq{bp} must be even for compatibility with older iniload (before 2023-March).
|
||||
The stack pointer must be at most \cq{bp - 10h}.
|
||||
Below the pointed to location there live the Load Stack Variables.
|
||||
These follow this structure:
|
||||
@ -144,6 +171,7 @@ Allows iniload to determine how much of it is already loaded.
|
||||
|
||||
|
||||
An LSV extension allows to pass a command line to the kernel.
|
||||
The base pointer must be at least \cq{114h} then.
|
||||
The stack pointer must be at most \cq{bp - 114h} then.
|
||||
This follows the structure like this:
|
||||
|
||||
@ -179,8 +207,8 @@ must not equal the string \cq{CL}.
|
||||
\b dosemu2's RxDOS.3 support sets \cq{sp = bp - 10h}
|
||||
|
||||
\b ldosboot boot.asm (FAT12/FAT16) loader
|
||||
uses the variable for a \q{paragraphs per sector} value
|
||||
which is always a power of two and always below-or-equal 200h.
|
||||
makes sure not to pass the variable with the content "CL".
|
||||
Refer to placeholder and DIRSEARCHSTACK_CL_FIRST uses in the source.
|
||||
|
||||
\b ldosboot boot32.asm (FAT32) loader
|
||||
uses the variable for an \q{entries per sector} value
|
||||
@ -190,6 +218,101 @@ which is always a power of two and always below-or-equal 100h.
|
||||
sets \cq{sp = bp - 10h}
|
||||
|
||||
|
||||
\S{protocol-sector-iniload-memory} Memory map
|
||||
|
||||
The initial loader part that is loaded must be loaded
|
||||
at above or equal to linear 00600h.
|
||||
The FAT buffer segment (if used) must also be stored
|
||||
at above or equal to linear 00600h.
|
||||
The stack (which should extend at least 512 bytes below \cq{ss:bp})
|
||||
and boot sector (pointed to by \cq{ss:bp}, at least 512 bytes length)
|
||||
should also be stored at above or equal to linear 00600h.
|
||||
|
||||
There is an additional memory area,
|
||||
the Low Memory Area top reservation,
|
||||
which should be unused by the load protocol at handoff time
|
||||
but be at least 20 KiB in size.
|
||||
It is located below the usable Low Memory Area top.
|
||||
That is, directly below the EBDA, RPL-reserved memory, video memory,
|
||||
or otherwise UMA.
|
||||
This area is reserved in order to facilitate initial loader operation.
|
||||
|
||||
None of the memory areas may overlap.
|
||||
This does not include the FAT buffer in case it is uninitialised.
|
||||
|
||||
|
||||
\S{protocol-sector-iniload-loadname} Load filename in the boot sector
|
||||
|
||||
The boot sector may be expected to contain a valid
|
||||
8.3 format (blank-padded FCB) filename
|
||||
in the area of the boot sector starting behind the (E)BPB,
|
||||
extending up to below the boot sector signature word with value AA55h
|
||||
(at offset 510 in the boot sector).
|
||||
This name should not contain blanks other than trailing in the
|
||||
file name portion or trailing in the file extension portion.
|
||||
It should consist of printable ASCII codepoints.
|
||||
That is, byte values between 20h and 7Eh inclusive.
|
||||
It should not consist of eleven times the same byte value.
|
||||
Additional FAT Short File Name restrictions may be assumed.
|
||||
|
||||
Although a loader should not depend on this for crucial operation,
|
||||
it may want to detect the kernel name it was presumably loaded from
|
||||
for informational or optional purposes.
|
||||
The canonical implementation of this is currently the function
|
||||
\cq{findname} in the \cw{testpl.asm} test payload kernel.
|
||||
It is found within
|
||||
\W{https://hg.pushbx.org/ecm/ldosboot/file/e0c17723f953/testpl.asm#l668}{the ldosboot repo}.
|
||||
This handling is based on the function of the same name
|
||||
\W{https://hg.pushbx.org/ecm/instsect/file/53e4327aacd6/instsect.asm#l2442}{in the instsect application}.
|
||||
|
||||
|
||||
\S{protocol-sector-iniload-patch} Query patch support
|
||||
|
||||
The ldosboot repo includes a patch Script for lDebug (.sld) file
|
||||
which allows to patch the initial loader stage.
|
||||
The patches concern handling of the CHS geometry detection,
|
||||
and whether LBA or CHS access is used.
|
||||
There are several legacy patch sites in which patch.sld
|
||||
can directly patch the initial loader's code.
|
||||
|
||||
However, the preferred way is to find the query patch sequence.
|
||||
It should appear within the first 1536 bytes,
|
||||
that is within the part of the initial loader that must be loaded.
|
||||
This is the sequence:
|
||||
|
||||
\c 8A5640 mov dl, byte [bp + 40h]
|
||||
\c B8xxyy mov ax, yyxxh
|
||||
\c 84D2 test dl, dl
|
||||
\c 7902 jns @F
|
||||
\c 86C4 xchg al, ah
|
||||
\c @@:
|
||||
|
||||
The immediate word of the \cw{mov ax} instruction is to be patched.
|
||||
The sequence should be scanned for without regard as to what
|
||||
the current contents of this word are.
|
||||
|
||||
The following flag values are used:
|
||||
|
||||
\b 01h Force CHS access, do not detect LBA support with 13.41
|
||||
|
||||
\b 02h Force LBA access, do not detect LBA support with 13.41
|
||||
|
||||
\b 04h Force use of BPB's CHS geometry, do not detect with 13.08
|
||||
|
||||
\b 80h Used by lDebug. If this value is set for the load unit,
|
||||
then lDebug will make use of the other flags set up for that unit.
|
||||
The corresponding flags will be saved in lDebug's load_unit_flags.
|
||||
This affects only the load unit (LD in lDebug terminology),
|
||||
which suffices to pass commands in the startup Script for lDebug.
|
||||
|
||||
The flag 01h takes precedence over 02h if both are set.
|
||||
|
||||
The low byte (xxh) is used in case the loader loads
|
||||
from a diskette unit, that is a unit number below 80h.
|
||||
The high byte (yyh) is used otherwise, in case the loader loads
|
||||
from a hard disk unit, that is a unit number above-or-equal 80h.
|
||||
|
||||
|
||||
\H{protocol-iniload-payload} Iniload to payload protocol
|
||||
|
||||
The payload is loaded to an arbitrary segment.
|
||||
@ -236,7 +359,9 @@ Below the LSV, iniload passes the LOADDATA (1) structure.
|
||||
\c ldHasLBA: resb 1
|
||||
\c ldClusterSize: resw 1
|
||||
\c ldParaPerSector:resw 1
|
||||
\c ldLoadingSeg: resw 1
|
||||
\c ldLoadingSeg:
|
||||
\c ldQueryPatchValue:
|
||||
\c resw 1
|
||||
\c ldLoadUntilSeg: resw 1
|
||||
\c endstruc
|
||||
|
||||
@ -293,6 +418,15 @@ May be given as zero for non-FAT filesystems.
|
||||
|
||||
\dd Word. Internally used by iniload.
|
||||
Available for re-use by payload.
|
||||
However, ldQueryPatchValue re-uses the same field.
|
||||
|
||||
\dt ldQueryPatchValue
|
||||
|
||||
\dd Word. Passes the query patch value from the initial loader.
|
||||
This provides an opportunity to patch a well-known site
|
||||
in the initial loader to change its behaviour in some ways.
|
||||
Near the end of its operation, the initial loader
|
||||
passes along this value in this variable for the next stage to use.
|
||||
|
||||
\dt ldLoadUntilSeg
|
||||
|
||||
@ -320,6 +454,6 @@ that is there is an empty command line
|
||||
the terminator of which is followed by a byte with the value 0FFh,
|
||||
then no command line was passed to iniload.
|
||||
Currently lDebug can pass a command line to iniload when
|
||||
loading with its lDOS, RxDOS.2, or RxDOS.3 protocols.
|
||||
loading with its lDOS, RxDOS.2, RxDOS.3, or FreeDOS protocols.
|
||||
When iniload is loaded as a Multiboot1 or Multiboot2 specification kernel,
|
||||
it is also assumed that a command line can be passed.
|
||||
|
@ -78,6 +78,7 @@ ldHasLBA: resb 1
|
||||
ldClusterSize: resw 1
|
||||
ldParaPerSector:resw 1
|
||||
ldLoadingSeg: ; word
|
||||
ldQueryPatchValue: ; word
|
||||
lsvCommandLine: ; word
|
||||
.start: equ $ - lsvclBufferLength
|
||||
.signature: resw 1
|
||||
@ -124,6 +125,14 @@ ptLinux: equ 83h
|
||||
ptExtendedLinux: equ 85h
|
||||
|
||||
|
||||
query_no_geometry equ 4
|
||||
query_no_chs equ 2
|
||||
query_no_lba equ 1
|
||||
query_fd_multiplier equ 1
|
||||
query_hd_multiplier equ 256
|
||||
query_all_multiplier equ query_fd_multiplier + query_hd_multiplier
|
||||
|
||||
|
||||
%ifndef _MAP
|
||||
%elifempty _MAP
|
||||
%else ; defined non-empty, str or non-str
|
||||
@ -132,6 +141,8 @@ ptExtendedLinux: equ 85h
|
||||
|
||||
defaulting
|
||||
|
||||
numdef QUERY_PATCH, 1 ; use new style patch of CHS/LBA/geometry
|
||||
numdef QUERY_DEFAULT, 0
|
||||
numdef QUERY_GEOMETRY, 1 ; query geometry via 13.08 (for CHS access)
|
||||
numdef RPL, 1 ; support RPL and do not overwrite it
|
||||
numdef CHS, 1 ; support CHS (if it fits)
|
||||
@ -163,6 +174,7 @@ ptExtendedLinux: equ 85h
|
||||
%include "inicheck.mac"
|
||||
%endif
|
||||
|
||||
numdef PADDING, 0
|
||||
strdef PAYLOAD_FILE, "lDOSLOAD.BIN"
|
||||
numdef EXEC_OFFSET, 0
|
||||
numdef EXEC_SEGMENT, 0
|
||||
@ -328,8 +340,16 @@ ms6_entry:
|
||||
d3 call d3_display_two_characters
|
||||
d3 test ax, "00"
|
||||
|
||||
; test dx, dx
|
||||
; jnz @FF
|
||||
mov cx, cs
|
||||
cmp cx, 60h
|
||||
jne @F
|
||||
.freedos_or_msdos1_com_entry:
|
||||
jmp freedos_or_msdos1_com_entry
|
||||
@@:
|
||||
|
||||
; xor cx, cx
|
||||
;; test dx, dx
|
||||
;; jnz @FF
|
||||
; Actual DOS will always put a zero word on top of
|
||||
; the stack. But when the debugger loads us as
|
||||
; a flat format binary it may set up another
|
||||
@ -339,15 +359,10 @@ d3 test ax, "00"
|
||||
call @F
|
||||
@@:
|
||||
pop cx
|
||||
cmp cx, @B + 100h
|
||||
je msdos1_com_entry
|
||||
sub cx, @B ; cx == 0 iff entered at offset 0
|
||||
jne .freedos_or_msdos1_com_entry
|
||||
@@:
|
||||
|
||||
mov cx, cs
|
||||
cmp cx, 60h
|
||||
je freedos_entry
|
||||
|
||||
xor cx, cx
|
||||
; cx = 0
|
||||
|
||||
; Note: It has been observed that some IBMBIO.COM / IO.SYS
|
||||
; boot sector loaders pass the int 1Eh address on the
|
||||
@ -380,29 +395,50 @@ error:
|
||||
int 16h
|
||||
int 19h
|
||||
|
||||
disp_error:
|
||||
.:
|
||||
lodsb
|
||||
test al, al
|
||||
jz .ret
|
||||
|
||||
disp_error.loop:
|
||||
mov ah, 0Eh
|
||||
mov bx, 7
|
||||
; push bp
|
||||
; (call may change bp, but it is not used here any longer.)
|
||||
int 10h
|
||||
; pop bp
|
||||
jmp short .
|
||||
|
||||
msg:
|
||||
.error: db "Load error: ", 0
|
||||
disp_error:
|
||||
lodsb
|
||||
test al, al
|
||||
jnz .loop
|
||||
retn
|
||||
|
||||
|
||||
query_geometry:
|
||||
%if _QUERY_GEOMETRY ; +30 bytes
|
||||
%if _QUERY_GEOMETRY || !_LBA_SKIP_CHECK
|
||||
; magic bytes start
|
||||
mov dl, [bp + bsBPB + ebpbNew + bpbnBootUnit]
|
||||
; magic bytes
|
||||
%if _QUERY_PATCH
|
||||
mov ax, _QUERY_DEFAULT ; magic bytes, checked by patch script
|
||||
..@query_patch_site equ $ - 2
|
||||
test dl, dl ; hard disk unit ?
|
||||
jns @F ; no -->
|
||||
xchg al, ah ; get high byte into al
|
||||
; magic bytes end
|
||||
@@:
|
||||
%endif
|
||||
%endif
|
||||
|
||||
%if _QUERY_GEOMETRY ; +30 bytes
|
||||
%if !_LBA_SKIP_CHECK
|
||||
push dx
|
||||
%if _QUERY_PATCH
|
||||
push ax
|
||||
%endif
|
||||
%endif
|
||||
|
||||
%if _QUERY_PATCH
|
||||
test al, 4 ; don't query geometry ?
|
||||
jnz @F ; yes -->
|
||||
%endif
|
||||
|
||||
; test dl, dl ; floppy?
|
||||
; jns @F ; don't attempt query, might fail -->
|
||||
; Note that while the original PC BIOS doesn't support this function
|
||||
@ -423,30 +459,38 @@ query_geometry:
|
||||
%endif
|
||||
|
||||
%if !_LBA_SKIP_CHECK
|
||||
mov ah, 41h
|
||||
%if _QUERY_GEOMETRY
|
||||
pop dx
|
||||
%else
|
||||
mov dl, [bp + bsBPB + ebpbNew + bpbnBootUnit]
|
||||
%if _QUERY_PATCH
|
||||
pop ax ; restore query patch flags in al
|
||||
%endif
|
||||
pop dx ; restore unit number in dl
|
||||
%endif
|
||||
%if _QUERY_PATCH
|
||||
shr al, 1 ; CY if force CHS
|
||||
jc @F ; if so -->
|
||||
and al, 1 ; force LBA ?
|
||||
jnz .done_lba ; yes -->
|
||||
%endif
|
||||
mov ah, 41h
|
||||
mov bx, 55AAh
|
||||
stc
|
||||
int 13h ; 13.41.bx=55AA extensions installation check
|
||||
@@:
|
||||
mov al, 0 ; zero in case of no LBA support
|
||||
jc .no_lba
|
||||
cmp bx, 0AA55h
|
||||
jne .no_lba
|
||||
test cl, 1 ; support bitmap bit 0
|
||||
jz .no_lba
|
||||
shr cl, 1 ; support bitmap bit 0
|
||||
jnc .no_lba
|
||||
inc ax ; al = 1 to indicate LBA support
|
||||
.no_lba:
|
||||
.done_lba:
|
||||
mov byte [bp + ldHasLBA], al
|
||||
%else
|
||||
mov byte [bp + ldHasLBA], 0
|
||||
%endif
|
||||
|
||||
%if 1 || _QUERY_GEOMETRY || !_LBA_SKIP_CHECK
|
||||
disp_error.ret:
|
||||
retn
|
||||
%endif
|
||||
|
||||
@ -474,7 +518,7 @@ read_sector:
|
||||
push ax
|
||||
push si
|
||||
|
||||
push bx
|
||||
mov es, bx
|
||||
|
||||
; DX:AX==LBA sector number
|
||||
; add partition start (= number of hidden sectors)
|
||||
@ -530,9 +574,9 @@ read_sector:
|
||||
jne .lba_error
|
||||
|
||||
; push word [si + 4 + 0]
|
||||
push word [si + 4 + 2] ; user buffer
|
||||
push word [bp + ldSectorSeg]
|
||||
pop word [si + 4 + 2]
|
||||
push es ; => user buffer
|
||||
mov es, word [bp + ldSectorSeg]
|
||||
mov word [si + 4 + 2], es
|
||||
; and word [si + 4 + 0], byte 0
|
||||
|
||||
mov ah, 42h
|
||||
@ -550,12 +594,12 @@ read_sector:
|
||||
|
||||
pop es
|
||||
; pop cx
|
||||
call .sectorseg_helper
|
||||
add sp, 10h
|
||||
jmp .sectorseg_helper_then_done
|
||||
|
||||
.lba_done:
|
||||
add sp, 10h
|
||||
pop bx
|
||||
jmp short .chs_done
|
||||
jmp short .done
|
||||
|
||||
.lba_error: equ .err
|
||||
|
||||
@ -640,7 +684,6 @@ read_sector:
|
||||
|
||||
; we call INT 13h AH=02h once for each sector. Multi-sector reads
|
||||
; may fail if we cross a track or 64K boundary
|
||||
pop es
|
||||
|
||||
mov ax, 0201h ; read one sector
|
||||
%if _CHS_RETRY
|
||||
@ -664,24 +707,42 @@ read_sector:
|
||||
int 13h
|
||||
%endif
|
||||
.err_CY_1:
|
||||
jc .err
|
||||
jnc .sectorseg_helper_es
|
||||
%endif ; _CHS
|
||||
.err:
|
||||
error_diskaccess: equ $
|
||||
call error
|
||||
db "Disk read error.", 0
|
||||
|
||||
|
||||
%if _CHS
|
||||
.sectorseg_helper_es:
|
||||
pop es
|
||||
call .sectorseg_helper
|
||||
%endif
|
||||
|
||||
.sectorseg_helper_then_done:
|
||||
xor si, si
|
||||
mov ds, word [bp + ldSectorSeg]
|
||||
push di
|
||||
; mov di, cx
|
||||
xor di, di
|
||||
mov cx, word [bp + bsBPB + bpbBytesPerSector]
|
||||
rep movsb
|
||||
pop di
|
||||
|
||||
push ss
|
||||
pop ds
|
||||
|
||||
.done:
|
||||
; increment segment
|
||||
mov bx, es
|
||||
%endif
|
||||
|
||||
.chs_done:
|
||||
mov es, bx
|
||||
add bx, word [bp + ldParaPerSector]
|
||||
|
||||
pop si
|
||||
pop ax
|
||||
pop cx
|
||||
pop dx
|
||||
.increment_sector_number:
|
||||
; increment LBA sector number
|
||||
inc ax
|
||||
jne @F
|
||||
@ -703,21 +764,21 @@ read_sector:
|
||||
; reset drive
|
||||
xor ax, ax
|
||||
int 13h
|
||||
jc @F ; CY, reset failed, error in ah -->
|
||||
|
||||
; try read again
|
||||
pop ax ; restore function number
|
||||
%if _LBA
|
||||
call .int13_preserve_lpcount
|
||||
%else
|
||||
int 13h ; retry, CF error status, ah error number
|
||||
%endif
|
||||
retn
|
||||
jnc @FF ; NC, reset succeeded -->
|
||||
; CY, reset failed, error in ah
|
||||
|
||||
@@: ; NC or CY, stack has function number
|
||||
inc sp
|
||||
inc sp ; discard word on stack, preserve CF
|
||||
retn
|
||||
|
||||
@@:
|
||||
; try read again
|
||||
pop ax ; restore function number
|
||||
%if ! _LBA
|
||||
int 13h ; retry, CF error status, ah error number
|
||||
retn
|
||||
%endif ; else: fall through to .int13_preserve_lpcount
|
||||
%endif
|
||||
|
||||
%if _LBA
|
||||
@ -736,24 +797,6 @@ read_sector:
|
||||
retn
|
||||
%endif
|
||||
|
||||
.sectorseg_helper:
|
||||
xor si, si
|
||||
mov ds, word [bp + ldSectorSeg]
|
||||
push di
|
||||
; mov di, cx
|
||||
xor di, di
|
||||
mov cx, word [bp + bsBPB + bpbBytesPerSector]
|
||||
rep movsb
|
||||
pop di
|
||||
|
||||
push ss
|
||||
pop ds
|
||||
retn
|
||||
|
||||
.err:
|
||||
error_diskaccess:
|
||||
call error
|
||||
db "Disk read error.", 0
|
||||
|
||||
error_shortfile:
|
||||
call error
|
||||
@ -795,28 +838,25 @@ ms7_entry:
|
||||
; load unit field set, hidden sectors set
|
||||
inc dx
|
||||
dec dx ; "BJ" signature (apparently not about FAT32 support)
|
||||
cli
|
||||
cld
|
||||
|
||||
jmp .continue ; jump to handler above 600h (sector loads 800h bytes)
|
||||
|
||||
.ms6_common:
|
||||
mov ax, cs
|
||||
add ax, (3 * 512) >> 4
|
||||
.ms6_common: ; cx = 0
|
||||
mov ax, 70h + ((3 * 512) >> 4) ; MS6 entry has 3 sectors loaded
|
||||
; (and is always segment 70h)
|
||||
|
||||
.continue2_set_extra_and_empty_cmdline:
|
||||
.continue2_set_extra_and_empty_cmdline: ; cx = 0, ax => behind loaded
|
||||
%if _LSVEXTRA
|
||||
and word [bp + lsvExtra], 0
|
||||
mov word [bp + lsvExtra], cx
|
||||
%endif
|
||||
and word [bp + lsvCommandLine], 0
|
||||
.continue2:
|
||||
mov word [bp + lsvCommandLine], cx
|
||||
.continue2: ; cx = 0, ax => behind loaded
|
||||
mov word [bp + lsvLoadSeg], ax
|
||||
|
||||
xor ax, ax
|
||||
mov word [bp + lsvFATSeg], ax ; initialise to zero (for FAT12)
|
||||
dec ax
|
||||
mov word [bp + lsvFATSector + 0], ax
|
||||
mov word [bp + lsvFATSector + 2], ax ; initialise to -1
|
||||
mov word [bp + lsvFATSeg], cx ; initialise to zero (for FAT12)
|
||||
dec cx
|
||||
mov word [bp + lsvFATSector + 0], cx
|
||||
mov word [bp + lsvFATSector + 2], cx ; initialise to -1
|
||||
|
||||
; Actually it seems that the MS-DOS 7 loaders load 4 sectors
|
||||
; instead of only three (as the MS-DOS 6 loaders do).
|
||||
@ -824,21 +864,30 @@ ms7_entry:
|
||||
|
||||
jmp ldos_entry.ms7_common
|
||||
|
||||
msg:
|
||||
.error: db "Load error: ", 0
|
||||
|
||||
|
||||
finish_continue:
|
||||
mov bx, cs
|
||||
add ax, bx ; = cs + rounded up length
|
||||
sub ax, word [bp + ldLoadTop] ; = paras to move down
|
||||
jbe short finish_load
|
||||
|
||||
push ax
|
||||
mov cx, word [bp + lsvLoadSeg]
|
||||
; => after end of loaded data
|
||||
sub word [bp + lsvLoadSeg], ax
|
||||
; relocate this pointer already
|
||||
neg ax
|
||||
add ax, bx ; ax = cs - paras to move down
|
||||
; want to relocate cs to this
|
||||
jnc short error_outofmemory_j1
|
||||
mov di, relocate_to
|
||||
push ax
|
||||
push di ; dword on stack: relocate_to
|
||||
cmp ax, 60h + 1
|
||||
jb short error_outofmemory_j1
|
||||
push ax ; word on stack => where to relocate to
|
||||
dec ax ; one less to allow relocator
|
||||
mov es, ax
|
||||
|
||||
@ -850,17 +899,18 @@ finish_relocation:
|
||||
push di ; dword on stack: relocator destination
|
||||
|
||||
mov ds, bx ; ds => unrelocated cs
|
||||
inc ax ; ax => where to relocate to
|
||||
mov si, relocator ; ds:si -> relocator
|
||||
relocator_size equ relocator.end - relocator
|
||||
%rep (relocator_size + 1) / 2
|
||||
movsw ; place relocator
|
||||
%endrep
|
||||
mov es, ax
|
||||
xor di, di ; -> where to relocate to
|
||||
%if relocator_size > 16
|
||||
%error Relocator is too large
|
||||
%endif
|
||||
xor di, di ; word [ss:sp+4]:di -> where to relocate to
|
||||
xor si, si ; ds:si = cs:0
|
||||
|
||||
mov cx, word [bp + lsvLoadSeg]
|
||||
; cx => after end of loaded data
|
||||
sub cx, bx ; length of currently loaded fragment
|
||||
mov bx, 1000h
|
||||
mov ax, cx
|
||||
@ -907,8 +957,6 @@ relocate_to:
|
||||
test ax, ax ; another round needed?
|
||||
jnz @BB ; yes -->
|
||||
|
||||
pop ax
|
||||
sub word [bp + lsvLoadSeg], ax
|
||||
push ss
|
||||
pop ds
|
||||
|
||||
@ -926,7 +974,6 @@ finish_load:
|
||||
; ldLoadUntilSeg => after last to-be-loaded paragraph
|
||||
|
||||
mov bx, word [bp + lsvLoadSeg]
|
||||
mov word [bp + ldLoadingSeg], bx
|
||||
cmp bx, ax
|
||||
jae short loaded_all_if_ae ; (for FreeDOS entrypoint) already loaded -->
|
||||
|
||||
@ -940,32 +987,26 @@ finish_load:
|
||||
jc short error_badchain_j
|
||||
|
||||
skip_next_clust:
|
||||
push dx
|
||||
push ax
|
||||
call clust_to_first_sector
|
||||
push cx
|
||||
push bx
|
||||
mov cx, [bp + ldClusterSize]
|
||||
skip_next_sect:
|
||||
push cx
|
||||
|
||||
mov bx, [bp + ldLoadingSeg]
|
||||
cmp bx, [bp + ldLoadUntilSeg]
|
||||
jae loaded_all.3stack
|
||||
jae loaded_all.2stack
|
||||
|
||||
mov cx, bx
|
||||
add cx, [bp + ldParaPerSector]
|
||||
cmp cx, [bp + lsvLoadSeg]
|
||||
add bx, [bp + ldParaPerSector]
|
||||
; bx += paras per sector
|
||||
cmp bx, [bp + lsvLoadSeg]
|
||||
ja skipped_all
|
||||
inc ax ; emulate read_sector:
|
||||
jnz @F
|
||||
inc dx ; dx:ax += 1
|
||||
@@:
|
||||
mov bx, cx ; bx += paras per sector
|
||||
; emulate read_sector:
|
||||
call read_sector.increment_sector_number
|
||||
; dx:ax += 1
|
||||
mov [bp + ldLoadingSeg], bx
|
||||
|
||||
pop cx
|
||||
loop skip_next_sect
|
||||
pop bx
|
||||
pop cx
|
||||
pop ax
|
||||
pop dx
|
||||
call clust_next
|
||||
jnc skip_next_clust
|
||||
end_of_chain:
|
||||
@ -982,6 +1023,8 @@ loaded_all_if_ae:
|
||||
|
||||
|
||||
skipped_all:
|
||||
sub bx, [bp + ldParaPerSector]
|
||||
; restore bx => next sector to read
|
||||
call read_sector
|
||||
; we can depend on the fact that at least
|
||||
; up to end was already loaded, so this
|
||||
@ -997,31 +1040,32 @@ error_badchain_j:
|
||||
|
||||
|
||||
; ds => first chunk of to be relocated data
|
||||
; es => first chunk of relocation destination
|
||||
; word [ss:sp] => first chunk of relocation destination
|
||||
; cx = number of words in first chunk
|
||||
relocator:
|
||||
pop es ; => where to relocate to
|
||||
rep movsw
|
||||
retf ; jump to relocated relocate_to
|
||||
.end:
|
||||
|
||||
|
||||
; INP: dx:ax = cluster - 2 (0-based cluster)
|
||||
; OUT: cx:bx = input dx:ax
|
||||
; dx:ax = first sector of that cluster
|
||||
; CHG: -
|
||||
; OUT: dx:ax = first sector of that cluster
|
||||
; cx = adjusted sectors per cluster
|
||||
; CHG: bx
|
||||
clust_to_first_sector:
|
||||
push dx
|
||||
push ax
|
||||
mov cx, word [bp + ldClusterSize]
|
||||
push dx
|
||||
mul word [bp + ldClusterSize]
|
||||
mul cx
|
||||
xchg bx, ax
|
||||
xchg cx, dx
|
||||
pop ax
|
||||
mul word [bp + ldClusterSize]
|
||||
push dx
|
||||
mul cx
|
||||
test dx, dx
|
||||
jnz short error_badchain_j
|
||||
xchg dx, ax
|
||||
add dx, cx
|
||||
pop ax
|
||||
add dx, ax
|
||||
.cy_error_badchain:
|
||||
jc short error_badchain_j
|
||||
xchg ax, bx
|
||||
@ -1030,21 +1074,17 @@ clust_to_first_sector:
|
||||
adc dx, [bp + lsvDataStart + 2]
|
||||
jc short .cy_error_badchain
|
||||
; dx:ax = first sector in cluster
|
||||
pop bx
|
||||
pop cx ; cx:bx = cluster
|
||||
retn
|
||||
|
||||
|
||||
; INP: cx:bx = cluster (0-based)
|
||||
; INP: dx:ax = cluster (0-based)
|
||||
; si:di = loaded FAT sector, -1 if none
|
||||
; OUT: CY if no next cluster
|
||||
; NC if next cluster found,
|
||||
; dx:ax = next cluster value (0-based)
|
||||
; NC if next cluster found
|
||||
; dx:ax = next cluster value (0-based)
|
||||
; si:di = loaded FAT sector
|
||||
; CHG: cx, bx
|
||||
clust_next:
|
||||
mov ax, bx
|
||||
mov dx, cx
|
||||
add ax, 2
|
||||
adc dx, 0
|
||||
|
||||
@ -1153,25 +1193,25 @@ check_clust:
|
||||
|
||||
|
||||
ms6_continue1:
|
||||
mov es, cx
|
||||
mov bp, 7C00h
|
||||
mov es, cx ; cx = 0
|
||||
mov bp, 7C00h ; 0:bp -> boot sector with BPB
|
||||
|
||||
mov word [es:di], si
|
||||
mov word [es:di + 2], ds ; restore old int 1Eh address
|
||||
|
||||
mov ss, cx
|
||||
mov ss, cx ; = 0
|
||||
mov sp, 7C00h + lsvCommandLine
|
||||
|
||||
mov dx, word [es:500h + 26]
|
||||
mov cx, word [es:500h + 20]
|
||||
mov word [bp + lsvFirstCluster + 0], dx
|
||||
mov word [bp + lsvFirstCluster + 2], cx
|
||||
push word [es:500h + 20]
|
||||
push word [es:500h + 26]
|
||||
pop word [bp + lsvFirstCluster + 0]
|
||||
pop word [bp + lsvFirstCluster + 2]
|
||||
|
||||
sub bx, word [bp + bsBPB + bpbHiddenSectors + 0]
|
||||
sbb ax, word [bp + bsBPB + bpbHiddenSectors + 2]
|
||||
mov word [bp + lsvDataStart + 0], bx
|
||||
mov word [bp + lsvDataStart + 2], ax
|
||||
jmp ms7_entry.ms6_common
|
||||
jmp ms7_entry.ms6_common ; passing cx = 0
|
||||
|
||||
|
||||
%assign num 1020-($-$$)
|
||||
@ -1193,7 +1233,8 @@ ldos_entry:
|
||||
cli
|
||||
cld
|
||||
|
||||
; cs:ip = 70h:400h
|
||||
; ip = 400h
|
||||
; cs = arbitrary; typically 60h, 70h, or 200h
|
||||
; dwo [ss:bp - 4] = first data sector (without hidden sectors)
|
||||
; wo [ss:bp - 6] = load_seg, => after last loaded data
|
||||
; wo [ss:bp - 8] = fat_seg, 0 if invalid
|
||||
@ -1214,6 +1255,7 @@ ldos_entry:
|
||||
;
|
||||
; Extension 2:
|
||||
; word [ss:bp - 20] = signature "CL" if valid
|
||||
; bp >= 20 + 256 if valid
|
||||
; 256bytes [ss:bp - 20 - 256] = ASCIZ command line string
|
||||
|
||||
xor ax, ax
|
||||
@ -1277,9 +1319,9 @@ init_memory:
|
||||
dec cx ; => last paragraph of higher buffer (16-byte trailer)
|
||||
mov dx, ax ; => first paragraph of higher buffer
|
||||
mov bx, cx
|
||||
and dx, 0F000h ; 64 KiB chunk of first paragraph of higher buffer
|
||||
and bx, 0F000h ; 64 KiB chunk of last paragraph of higher buffer
|
||||
cmp bx, dx ; in same chunk?
|
||||
and dh, 0F0h ; 64 KiB chunk of first paragraph of higher buffer
|
||||
and bh, 0F0h ; 64 KiB chunk of last paragraph of higher buffer
|
||||
cmp bh, dh ; in same chunk?
|
||||
mov bx, ax
|
||||
je .gotsectorseg ; yes, use higher buffer as sector buffer ->
|
||||
; bx = use higher buffer as FAT buffer
|
||||
@ -1341,33 +1383,42 @@ init_memory:
|
||||
inc cx ; => stack + BPB buffer
|
||||
push ss
|
||||
pop ds
|
||||
lea si, [bp + lsvCommandLine.start]
|
||||
mov es, cx
|
||||
push cx ; top of memory below buffers
|
||||
push ax ; => sector seg
|
||||
|
||||
xor cx, cx
|
||||
lea si, [bp + lsvCommandLine.start]
|
||||
cmp bp, si ; can have command line ?
|
||||
; (also makes sure movsw and lodsw never run
|
||||
; with si = 0FFFFh which'd cause a fault.)
|
||||
jb .no_cmdline
|
||||
|
||||
mov di, _STACKSIZE - LOADCMDLINE + ldCommandLine.start
|
||||
; -> cmd line target
|
||||
push cx ; top of memory below buffers
|
||||
mov cx, (LOADCMDLINE_size + 1) >> 1
|
||||
mov cl, (LOADCMDLINE_size + 1) >> 1
|
||||
rep movsw ; copy cmd line
|
||||
%if lsvCommandLine.start + fromwords(words(LOADCMDLINE_size)) != lsvCommandLine.signature
|
||||
%error Unexpected structure layout
|
||||
%endif
|
||||
cmp word [si], lsvclSignature
|
||||
lodsw
|
||||
cmp ax, lsvclSignature
|
||||
je @F ; if command line given -->
|
||||
.no_cmdline:
|
||||
mov byte [es: _STACKSIZE - LOADCMDLINE + ldCommandLine.start ], cl
|
||||
; truncate as if empty line given
|
||||
dec cx ; cl = 0FFh
|
||||
@@:
|
||||
mov byte [es:di - 1], cl
|
||||
mov byte [es: _STACKSIZE - LOADCMDLINE + ldCommandLine.start \
|
||||
+ fromwords(words(LOADCMDLINE_size)) - 1 ], cl
|
||||
; remember whether command line given
|
||||
; = 0 if given (also truncates if too long)
|
||||
; = 0FFh if not given
|
||||
|
||||
push ax
|
||||
%if lsvCommandLine.signature + 2 != lsvExtra
|
||||
%error Unexpected structure layout
|
||||
%endif
|
||||
lodsw
|
||||
; lea si, [bp + lsvExtra]
|
||||
; si happens to be already correct here if we didn't
|
||||
; branch to .no_cmdline, however make sure to set
|
||||
; it here to support this case.
|
||||
lea si, [bp + lsvExtra]
|
||||
; ds:si -> lsv + BPB
|
||||
mov di, _STACKSIZE - LOADCMDLINE + lsvExtra
|
||||
; es:di -> where to place lsv
|
||||
@ -1413,7 +1464,8 @@ init_memory:
|
||||
test bx, bx
|
||||
jz .is_fat32
|
||||
|
||||
lea si, [bp + 510] ; -> last source word
|
||||
; lea si, [bp + 510] ; -> last source word
|
||||
mov si, _STACKSIZE - LOADCMDLINE + 510
|
||||
lea di, [si + (ebpbNew - bpbNew)] ; -> last dest word
|
||||
mov cx, (512 - bsBPB - bpbNew + 1) >> 1
|
||||
; move sector up, except common BPB start part
|
||||
@ -1457,9 +1509,9 @@ init_memory:
|
||||
|
||||
; adjusted sectors per cluster (store in a word,
|
||||
; and decode EDR-DOS's special value 0 meaning 256)
|
||||
xor ax, ax
|
||||
mov al, [bp + bsBPB + bpbSectorsPerCluster]
|
||||
dec al
|
||||
dec ax
|
||||
mov ah, 0
|
||||
inc ax
|
||||
mov [bp + ldClusterSize], ax
|
||||
|
||||
@ -1512,7 +1564,7 @@ init_memory:
|
||||
@@:
|
||||
cmp ax, 0FFF7h - 2
|
||||
ja .badclusters
|
||||
mov byte [bp + ldFATType], 16
|
||||
shr byte [bp + ldFATType], 1 ; = 16
|
||||
cmp ax, 0FF7h - 2
|
||||
ja .got_fat_type
|
||||
|
||||
@ -1569,42 +1621,30 @@ init_memory:
|
||||
and ax, bx ; rounded up,
|
||||
; ((payload.actual_end -$$+0 +15) >> 4 + pps - 1) & ~ (pps - 1)
|
||||
|
||||
mov bx, cs
|
||||
jmp finish_continue
|
||||
|
||||
|
||||
%assign num 1024+512-4-($-$$)
|
||||
%assign num 1024+512-($-$$)
|
||||
%warning num bytes in front of end
|
||||
_fill 1024+512-4,38,start
|
||||
; -4 is for the following two instructions.
|
||||
; they want execution to fall through to
|
||||
; load_next_clust_continue. placing them
|
||||
; at the very end of the 3 sectors allows
|
||||
; not to use a jump here.
|
||||
|
||||
load_next_clust:
|
||||
call clust_to_first_sector
|
||||
push cx
|
||||
align 16, nop
|
||||
_fill 1024+512,90h,start ; check that we are at 3 sectors end
|
||||
_fill 1024+512,38,start
|
||||
end:
|
||||
|
||||
load_next_clust_continue:
|
||||
push bx
|
||||
mov cx, [bp + ldClusterSize]
|
||||
|
||||
load_next_clust:
|
||||
push dx
|
||||
push ax
|
||||
call clust_to_first_sector
|
||||
load_next_sect:
|
||||
push cx
|
||||
mov bx, [bp + ldLoadingSeg]
|
||||
cmp bx, [bp + ldLoadUntilSeg]
|
||||
jae loaded_all.3stack_j
|
||||
jae loaded_all.2stack_j
|
||||
|
||||
call read_sector
|
||||
skipped_all_continue:
|
||||
mov [bp + ldLoadingSeg], bx
|
||||
pop cx
|
||||
loop load_next_sect
|
||||
pop bx
|
||||
pop cx
|
||||
pop ax
|
||||
pop dx
|
||||
call clust_next
|
||||
jnc load_next_clust
|
||||
jmp end_of_chain
|
||||
@ -1616,11 +1656,13 @@ skipped_all_continue:
|
||||
; if we jump to here, then the whole file has
|
||||
; been loaded, so this jump doesn't have to
|
||||
; stay in the 32 bytes after the end label.
|
||||
loaded_all.3stack_j:
|
||||
jmp loaded_all.3stack
|
||||
loaded_all.2stack_j:
|
||||
jmp loaded_all.2stack
|
||||
|
||||
|
||||
ms7_entry.continue:
|
||||
cli
|
||||
cld
|
||||
pop bx
|
||||
pop es
|
||||
pop word [es:bx]
|
||||
@ -1640,8 +1682,8 @@ ms7_entry.continue:
|
||||
sbb word [bp + lsvDataStart + 2], dx
|
||||
|
||||
mov ax, cs
|
||||
add ax, (4 * 512) >> 4
|
||||
|
||||
add ax, (4 * 512) >> 4 ; MS7 entry has 4 sectors loaded
|
||||
xor cx, cx ; cx = 0
|
||||
jmp ms7_entry.continue2_set_extra_and_empty_cmdline
|
||||
|
||||
|
||||
@ -1656,8 +1698,7 @@ end2:
|
||||
; This handling is in the second header part,
|
||||
; behind the needed part to finish loading.
|
||||
; It is only used when the file is completely loaded.
|
||||
loaded_all.3stack:
|
||||
pop ax
|
||||
loaded_all.2stack:
|
||||
pop ax
|
||||
pop ax
|
||||
loaded_all:
|
||||
@ -1723,6 +1764,13 @@ loaded_all:
|
||||
; al = 0 else
|
||||
rep stosb ; clear remainder of buffer
|
||||
|
||||
%if _QUERY_PATCH
|
||||
mov ax, word [cs:..@query_patch_site]
|
||||
%else
|
||||
mov ax, _QUERY_DEFAULT
|
||||
%endif
|
||||
mov word [bp + ldQueryPatchValue], ax
|
||||
|
||||
mov ax, cs
|
||||
add ax, ((payload -$$+0) >> 4) + _EXEC_SEGMENT
|
||||
push ax
|
||||
@ -1754,6 +1802,13 @@ error_data_checksum_failed:
|
||||
%endif
|
||||
|
||||
|
||||
freedos_or_msdos1_com_entry:
|
||||
call @F
|
||||
@@:
|
||||
pop cx
|
||||
cmp cx, @B
|
||||
jne msdos1_com_entry
|
||||
|
||||
freedos_entry:
|
||||
; This is the FreeDOS compatible entry point.
|
||||
; Supports FAT32 too.
|
||||
@ -1815,7 +1870,8 @@ d3 test ax, "F0"
|
||||
.multiboot_entry:
|
||||
mov ax, cs
|
||||
add ax, (payload.actual_end -$$+0 +15) >> 4
|
||||
|
||||
; Multiboot1/2 and FreeDOS have whole image
|
||||
xor cx, cx ; cx = 0
|
||||
jmp ms7_entry.continue2
|
||||
|
||||
|
||||
@ -2475,3 +2531,14 @@ second_payload:
|
||||
.end:
|
||||
%endif
|
||||
|
||||
%if ($ - start) < 4096
|
||||
_fill 4096, 38, start ; fill to new minimum limit
|
||||
%endif
|
||||
|
||||
%if _PADDING
|
||||
%if ($ - $$) > _PADDING
|
||||
%warning No padding needed
|
||||
%else
|
||||
times _PADDING - ($ - $$) db 0
|
||||
%endif
|
||||
%endif
|
||||
|
@ -31,15 +31,15 @@ header:
|
||||
dw (payload -$$+0) >> 4 ; exeHeaderSize
|
||||
dw 0 ; exeMinAlloc
|
||||
dw -1 ; exeMaxAlloc
|
||||
dw 0 ; exeInitSS
|
||||
dw -2 ; exeInitSP
|
||||
dw (payload.end + 15 - payload) / 16 ; exeInitSS
|
||||
dw 512 ; exeInitSP
|
||||
dw 0 ; exeChecksum
|
||||
dw 0, 0 ; exeInitCSIP
|
||||
dw 0 ; exeRelocTable
|
||||
endarea header
|
||||
|
||||
|
||||
align 16, db 38
|
||||
align 16, db 0
|
||||
payload:
|
||||
jmp strict short entry
|
||||
db "CONFIG"
|
||||
@ -50,7 +50,7 @@ payload:
|
||||
entry: equ $
|
||||
jmp entry_common
|
||||
|
||||
times 0xC0 - ($ - payload) db 0
|
||||
times 0xC0 - ($ - payload) nop
|
||||
entry_common: equ $
|
||||
|
||||
incbin _FILE
|
||||
|
@ -13,20 +13,88 @@ DISCLAIMER: THE WORKS ARE WITHOUT WARRANTY.
|
||||
@:help
|
||||
; Available patches:
|
||||
;
|
||||
; :patch_iniload_no_query_geometry
|
||||
; :patch_iniload_no_lba
|
||||
; :patch_iniload_no_query_geometry (new or old style)
|
||||
; :patch_iniload_no_lba (new or old style)
|
||||
; :patch_iniload_no_query_geometry_old (old style)
|
||||
; :patch_iniload_no_lba_old (old style)
|
||||
; :patch_iniload_no_chs (new style only)
|
||||
; :patch_iniload_detect_lba (new style only)
|
||||
; :patch_iniload_detect_geometry (new style only)
|
||||
;
|
||||
; Inputs: vef = nonzero to debug
|
||||
; cs:0 -> iniload
|
||||
; cs:ve7 -> iniload
|
||||
; Output: vee = nonzero if error
|
||||
; iniload patched
|
||||
; iniload patched if successful
|
||||
; Change: ve0 to vef, src, sro, aao, stack
|
||||
;
|
||||
; :query_patch_iniload (new style)
|
||||
;
|
||||
; Input: ve8 = what to set for new style query patch
|
||||
; 0 = default, -1 = none (do old style patch)
|
||||
; ve9 = what to clear for new style query patch
|
||||
; Requires lDebug release 3 or later
|
||||
@goto :eof
|
||||
|
||||
|
||||
:query_patch_iniload
|
||||
@if not (vef) then r ysf |= C000
|
||||
@:query_patch_common
|
||||
r ve0 word (sp - 100)
|
||||
a ss:ve0
|
||||
mov dl, byte [bp + 40]
|
||||
mov ax, 0
|
||||
.
|
||||
r ve1 := aao - 2
|
||||
r vec := ve1 - ve0
|
||||
s cs:ve7 l #1536 range ss:ve0 l vec
|
||||
if (src == 0 && vee == -1) then goto :eof
|
||||
if not (src) then goto :query_patch_error
|
||||
a ss:ve0
|
||||
test dl, dl
|
||||
jns (ve0 + 6)
|
||||
db 86,C4 ; xchg al, ah
|
||||
.
|
||||
if (word [srs:sro + vec + 2] != word [ss:ve0 + 0]) then goto :query_patch_error
|
||||
if (word [srs:sro + vec + 4] != word [ss:ve0 + 2]) then goto :query_patch_error
|
||||
if (word [srs:sro + vec + 6] != word [ss:ve0 + 4]) then goto :query_patch_error
|
||||
if not (ve8 or ve9) then goto :query_patch_found
|
||||
r word [srs:sro + vec] or:= ve8
|
||||
r word [srs:sro + vec] and:= ~ve9
|
||||
:query_patch_success
|
||||
r ve8 := 0
|
||||
r ve9 := 0
|
||||
r vee := 0
|
||||
r ysf &= ~C000
|
||||
; Patched successfully (new style)
|
||||
@goto :eof
|
||||
|
||||
:query_patch_found
|
||||
r ve8 := 0
|
||||
r ve9 := 0
|
||||
r vee := 0
|
||||
r ysf &= ~C000
|
||||
; Patch site found, no patch requested (new style)
|
||||
@goto :eof
|
||||
|
||||
:query_patch_error
|
||||
r ve8 := 0
|
||||
r ve9 := 0
|
||||
r vee := 1
|
||||
r ysf &= ~C000
|
||||
; Patch failed (new style)
|
||||
@goto :eof
|
||||
|
||||
|
||||
:patch_iniload_no_query_geometry
|
||||
@if not (vef) then r ysf |= C000
|
||||
r vee := -1
|
||||
r ve8 := 404
|
||||
r ve9 := 0
|
||||
y :query_patch_common
|
||||
@if not (vee == -1) then goto :eof
|
||||
|
||||
:patch_iniload_no_query_geometry_old
|
||||
@if not (vef) then r ysf |= C000
|
||||
r ve0 word (sp - 100)
|
||||
a ss:ve0
|
||||
mov ah, 08
|
||||
@ -37,13 +105,22 @@ a ss:ve0
|
||||
.
|
||||
r ve1 := aao - 1
|
||||
r vec := ve1 - ve0
|
||||
s cs:0 l #8192 range ss:ve0 l vec
|
||||
s cs:ve7 l #1536 range ss:ve0 l vec
|
||||
if not (src) then goto :error
|
||||
r byte [srs:sro + vec - 1] := EB
|
||||
r word [srs:sro + vec - 3] := 9090
|
||||
goto :success
|
||||
|
||||
|
||||
:patch_iniload_no_lba
|
||||
@if not (vef) then r ysf |= C000
|
||||
r vee := -1
|
||||
r ve8 := 101
|
||||
r ve9 := 0
|
||||
y :query_patch_common
|
||||
@if not (vee == -1) then goto :eof
|
||||
|
||||
:patch_iniload_no_lba_old
|
||||
@if not (vef) then r ysf |= C000
|
||||
r ve0 word (sp - 100)
|
||||
a ss:ve0
|
||||
mov ah, 41
|
||||
@ -56,7 +133,7 @@ a ss:ve0
|
||||
.
|
||||
r ve1 := aao - 1
|
||||
r vec := ve1 - ve0
|
||||
s cs:0 l #8192 range ss:ve0 l vec
|
||||
s cs:ve7 l #1536 range ss:ve0 l vec
|
||||
if (src) then goto :patch_iniload_no_lba.success
|
||||
a ss:ve0
|
||||
mov ah, 41
|
||||
@ -69,20 +146,64 @@ a ss:ve0
|
||||
.
|
||||
r ve1 := aao - 1
|
||||
r vec := ve1 - ve0
|
||||
s cs:0 l #8192 range ss:ve0 l vec
|
||||
s cs:ve7 l #1536 range ss:ve0 l vec
|
||||
if (src) then goto :patch_iniload_no_lba.success
|
||||
a ss:ve0
|
||||
mov ah, 41
|
||||
mov bx, 55AA
|
||||
stc
|
||||
int 13
|
||||
mov al, 0
|
||||
jc (ve0)
|
||||
.
|
||||
r ve1 := aao - 1
|
||||
r vec := ve1 - ve0
|
||||
s cs:ve7 l #1536 range ss:ve0 l vec
|
||||
if not (src) then goto :error
|
||||
|
||||
:patch_iniload_no_lba.success
|
||||
r byte [srs:sro + vec - 1] := EB
|
||||
r word [srs:sro + vec - 5] := 9090
|
||||
goto :success
|
||||
|
||||
:success
|
||||
r ve8 := 0
|
||||
r ve9 := 0
|
||||
r vee := 0
|
||||
r ysf &= ~C000
|
||||
; Patched successfully
|
||||
@goto :eof
|
||||
|
||||
|
||||
:patch_iniload_no_chs
|
||||
@if not (vef) then r ysf |= C000
|
||||
r vee := -1
|
||||
r ve9 := 0
|
||||
r ve8 := 202
|
||||
y :query_patch_common
|
||||
@if not (vee == -1) then goto :eof
|
||||
goto :error
|
||||
|
||||
:patch_iniload_detect_lba
|
||||
@if not (vef) then r ysf |= C000
|
||||
r vee := -1
|
||||
r ve8 := 0
|
||||
r ve9 := 303
|
||||
y :query_patch_common
|
||||
@if not (vee == -1) then goto :eof
|
||||
goto :error
|
||||
|
||||
:patch_iniload_detect_geometry
|
||||
@if not (vef) then r ysf |= C000
|
||||
r vee := -1
|
||||
r ve8 := 0
|
||||
r ve9 := 404
|
||||
y :query_patch_common
|
||||
@if not (vee == -1) then goto :eof
|
||||
goto :error
|
||||
|
||||
:error
|
||||
r ve8 := 0
|
||||
r ve9 := 0
|
||||
r vee := 1
|
||||
r ysf &= ~C000
|
||||
; Patch failed
|
||||
|
@ -32,6 +32,7 @@
|
||||
[ -z "$BOOT_COMMAND" ] && BOOT_COMMAND=~/.dosemu/drive_c/command.com
|
||||
[ -z "$BOOT_PROTOCOL" ] && BOOT_PROTOCOL=FREEDOS
|
||||
[ -z "$BOOT_OPTIONS" ] && BOOT_OPTIONS=" "
|
||||
[ -z "$MKTMPINC" ] && MKTMPINC=mktmpinc.pl
|
||||
[ -z "$NASM" ] && NASM=nasm
|
||||
[ -z "$CHECKSUM" ] && CHECKSUM="${INICHECK_DIR%/}"/iniload/checksum
|
||||
|
||||
|
@ -270,7 +270,17 @@ fi
|
||||
|
||||
echo -ne 'failure\r\n' > result.txt
|
||||
|
||||
TMPINC=""
|
||||
if command -v "$MKTMPINC" &> /dev/null
|
||||
then
|
||||
TMPINC="-D_TMPINC"
|
||||
fi
|
||||
if [[ -n "$TMPINC" ]]
|
||||
then
|
||||
"$MKTMPINC" "${LDOSBOOT_DIR%/}"/$bootname.asm > /dev/null
|
||||
fi
|
||||
"$NASM" "${LDOSBOOT_DIR%/}"/$bootname.asm -w-user \
|
||||
$TMPINC \
|
||||
-D_LOAD_NAME="'TESTWRIT'" -D_LOAD_EXT="'SYS'" -D_FAT$bpe \
|
||||
-D_UNIT=$unit \
|
||||
"$@" \
|
||||
@ -283,6 +293,7 @@ echo -ne 'failure\r\n' > result.txt
|
||||
"$options_i_ldosboot" \
|
||||
"$options_i_lmacros" \
|
||||
"$options_i_scanptab" \
|
||||
-D_PADDING='(48 * 1024)' \
|
||||
-D_PAYLOAD_FILE="'testwrit.bin'" -o testwrit.sys -l testwrin.lst \
|
||||
-D_INILOAD_SIGNATURE='"TW"' &&
|
||||
"$NASM" "${BOOTIMG_DIR%/}"/bootimg.asm \
|
||||
@ -292,8 +303,8 @@ echo -ne 'failure\r\n' > result.txt
|
||||
-D_BPE="$bpe" -D_SPC="$spc" -D_SPI="$spi" \
|
||||
-D_SPF="$(( (spi / spc * bpe / 8 + 511) / 512 ))" \
|
||||
-D_NUMROOT="$nr" \
|
||||
-o $name.img -l $name.lst \
|
||||
-D_PAYLOADFILE="testwrit.sys,result.txt" \
|
||||
-D_MAP=$name.map -o $name.img -l $name.lst \
|
||||
-D_PAYLOADFILE="testwrit.sys,result.txt,::chdir,dir" \
|
||||
-D_BOOTFILE="'$bootfile'" \
|
||||
-D_UNIT=$unit \
|
||||
"$@" \
|
||||
@ -301,6 +312,10 @@ echo -ne 'failure\r\n' > result.txt
|
||||
"$options_i_lmacros" \
|
||||
"$options_i_bootimg"
|
||||
(($?)) && exit $?
|
||||
if [[ -n "$TMPINC" ]]
|
||||
then
|
||||
rm -f *.tmp
|
||||
fi
|
||||
|
||||
pgid="$(ps -o pgid= $$)"
|
||||
function handle_timeout_process() {
|
||||
@ -366,11 +381,16 @@ then
|
||||
cp -aL "$BOOT_KERNEL" "${BOOT_KERNEL##*/}"
|
||||
cp -aL "$BOOT_COMMAND" "${BOOT_COMMAND##*/}"
|
||||
echo -ne "@echo off\r\ninst${bpe}tw.com C:\r\nquit.com\r\n" > autoexec.bat
|
||||
if [[ -n "$TMPINC" ]]
|
||||
then
|
||||
"$MKTMPINC" "${LDOSBOOT_DIR%/}"/boot.asm > /dev/null
|
||||
fi
|
||||
"$NASM" quit.asm \
|
||||
"$options_i_lmacros" \
|
||||
-o quit.com &&
|
||||
"$NASM" "${LDOSBOOT_DIR%/}"/boot.asm -w-user \
|
||||
"$options_i_lmacros" \
|
||||
$TMPINC \
|
||||
-D_COMPAT_"$BOOT_PROTOCOL"=1 \
|
||||
-D_LBA=0 -D_USE_PART_INFO=0 -D_QUERY_GEOMETRY=0 \
|
||||
$BOOT_OPTIONS \
|
||||
@ -384,6 +404,10 @@ then
|
||||
-D_PAYLOADFILE="${BOOT_KERNEL##*/},${BOOT_COMMAND##*/},autoexec.bat,inst${bpe}tw.com,quit.com" \
|
||||
-D_BOOTFILE="'bootinst.bin'"
|
||||
(($?)) && exit $?
|
||||
if [[ -n "$TMPINC" ]]
|
||||
then
|
||||
rm -f *.tmp
|
||||
fi
|
||||
timeout --foreground 10 "$QEMU" -fda diskinst.img "$qemu_switch" "$name".img -boot order=a -display none 2> /dev/null
|
||||
rc=$?
|
||||
handle_timeout_process
|
||||
@ -397,8 +421,13 @@ fi
|
||||
|
||||
if ((! direct))
|
||||
then
|
||||
if [[ -n "$TMPINC" ]]
|
||||
then
|
||||
"$MKTMPINC" "${LDOSBOOT_DIR%/}"/boot.asm > /dev/null
|
||||
fi
|
||||
"$NASM" "${LDOSBOOT_DIR%/}"/boot.asm -w-user \
|
||||
"$options_i_lmacros" \
|
||||
$TMPINC \
|
||||
-D_LOAD_NAME="'LDEBUG'" -D_LOAD_EXT="'COM'" \
|
||||
-D_MAP=boot12db.map -l boot12db.lst -o boot12db.bin &&
|
||||
"$NASM" "${BOOTIMG_DIR%/}"/bootimg.asm \
|
||||
@ -409,6 +438,10 @@ then
|
||||
-o diskldbg.img -l diskldbg.lst \
|
||||
-D_PAYLOADFILE="ldebug.com" -D_BOOTFILE="'boot12db.bin'"
|
||||
(($?)) && exit $?
|
||||
if [[ -n "$TMPINC" ]]
|
||||
then
|
||||
rm -f *.tmp
|
||||
fi
|
||||
|
||||
if ((dosemu))
|
||||
then
|
||||
|
@ -863,5 +863,9 @@ signature2:
|
||||
dw 2638h
|
||||
|
||||
%if _PADDING
|
||||
%if ($ - $$) > _PADDING
|
||||
%warning No padding needed
|
||||
%else
|
||||
times _PADDING - ($ - $$) db 0
|
||||
%endif
|
||||
%endif
|
||||
|
@ -128,6 +128,7 @@ ATTR_ARCHIVE equ 20h
|
||||
numdef LBA_RETRY, 1 ; retry LBA reads
|
||||
numdef CHS_RETRY, 1 ; retry CHS reads
|
||||
|
||||
numdef PADDING, 0
|
||||
strdef FILE_NAME, "RESULT"
|
||||
strdef FILE_EXT, "TXT" ; name of file to write
|
||||
strdef FILE_SUCCESS_MSG,"success"
|
||||
@ -501,7 +502,7 @@ write_sector:
|
||||
push ax
|
||||
push si
|
||||
|
||||
push bx
|
||||
mov es, bx
|
||||
|
||||
; DX:AX==LBA sector number
|
||||
; add partition start (= number of hidden sectors)
|
||||
@ -557,7 +558,8 @@ write_sector:
|
||||
testopt [bp + ldHasLBA], 2
|
||||
jz @F
|
||||
|
||||
mov es, word [si + 4 + 2] ; user buffer
|
||||
; es => user buffer
|
||||
push es
|
||||
call .sectorseg_helper_write
|
||||
mov word [si + 4 + 2], es ; => sector buffer
|
||||
mov ah, 43h
|
||||
@ -567,14 +569,16 @@ write_sector:
|
||||
int 13h
|
||||
; (don't need .int13_preserve_lpcount as no further call)
|
||||
%endif
|
||||
pop es ; ! restore es => user buffer
|
||||
jc .lba_error
|
||||
jmp .lba_done
|
||||
|
||||
@@:
|
||||
; push word [si + 4 + 0]
|
||||
push word [si + 4 + 2] ; user buffer
|
||||
push word [bp + ldSectorSeg]
|
||||
pop word [si + 4 + 2]
|
||||
push es ; => user buffer
|
||||
mov es, word [bp + ldSectorSeg]
|
||||
mov word [si + 4 + 2], es
|
||||
; => sector buffer
|
||||
; and word [si + 4 + 0], byte 0
|
||||
|
||||
mov ah, 42h
|
||||
@ -586,14 +590,13 @@ write_sector:
|
||||
%endif
|
||||
jc .lba_error
|
||||
|
||||
pop es
|
||||
pop es ; => user buffer
|
||||
; pop cx
|
||||
call .sectorseg_helper_read
|
||||
|
||||
.lba_done:
|
||||
add sp, 10h
|
||||
pop bx
|
||||
jmp short .chs_done
|
||||
jmp short .done
|
||||
|
||||
.lba_error: equ .err
|
||||
|
||||
@ -678,7 +681,6 @@ write_sector:
|
||||
|
||||
; we call INT 13h AH=02h once for each sector. Multi-sector reads
|
||||
; may fail if we cross a track or 64K boundary
|
||||
pop es
|
||||
|
||||
call .get_ah_3_write_2_read
|
||||
mov al, 01h ; access one sector
|
||||
@ -722,14 +724,11 @@ write_sector:
|
||||
|
||||
pop es
|
||||
call .sectorseg_helper_read
|
||||
%endif ; _CHS
|
||||
|
||||
.done:
|
||||
; increment segment
|
||||
mov bx, es
|
||||
%endif
|
||||
|
||||
.chs_done:
|
||||
mov es, bx
|
||||
add bx, word [bp + ldParaPerSector]
|
||||
|
||||
pop si
|
||||
@ -757,21 +756,21 @@ write_sector:
|
||||
; reset drive
|
||||
xor ax, ax
|
||||
int 13h
|
||||
jc @F ; CY, reset failed, error in ah -->
|
||||
|
||||
; try read again
|
||||
pop ax ; restore function number
|
||||
%if _LBA
|
||||
call .int13_preserve_lpcount
|
||||
%else
|
||||
int 13h ; retry, CF error status, ah error number
|
||||
%endif
|
||||
retn
|
||||
jnc @FF ; NC, reset succeeded -->
|
||||
; CY, reset failed, error in ah
|
||||
|
||||
@@: ; NC or CY, stack has function number
|
||||
inc sp
|
||||
inc sp ; discard word on stack, preserve CF
|
||||
retn
|
||||
|
||||
@@:
|
||||
; try read again
|
||||
pop ax ; restore function number
|
||||
%if ! _LBA
|
||||
int 13h ; retry, CF error status, ah error number
|
||||
retn
|
||||
%endif ; else: fall through to .int13_preserve_lpcount
|
||||
%endif
|
||||
|
||||
%if _LBA
|
||||
@ -1021,3 +1020,11 @@ check_clust:
|
||||
|
||||
align 16, db 38
|
||||
end:
|
||||
|
||||
%if _PADDING
|
||||
%if ($ - $$) > _PADDING
|
||||
%warning No padding needed
|
||||
%else
|
||||
times _PADDING - ($ - $$) db 0
|
||||
%endif
|
||||
%endif
|
||||
|
Loading…
Reference in New Issue
Block a user