mirror of
https://github.com/FDOS/kernel.git
synced 2025-07-27 07:44:09 +02:00
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_NAME, "LDOS"
|
||||||
strdef LOAD_EXT, "COM" ; name of file to load
|
strdef LOAD_EXT, "COM" ; name of file to load
|
||||||
numdef LOAD_ADR, 02000h ; where 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 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_SEG_ADJ, 0 ; how far cs will be from _LOAD_ADR
|
||||||
numdef EXEC_OFS, 400h ; what value ip will be
|
numdef EXEC_OFS, 400h ; what value ip will be
|
||||||
@ -41,12 +41,16 @@ Public domain by C. Masloch, 2012
|
|||||||
strdef ADD_NAME, ""
|
strdef ADD_NAME, ""
|
||||||
strdef ADD_EXT, "" ; name of second file to search
|
strdef ADD_EXT, "" ; name of second file to search
|
||||||
numdef ADD_DIR_SEG, 0 ; => where to store dir entry (0 if nowhere)
|
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_DIRBUF, end -start+7C00h ; 07E00h
|
||||||
gendef _ADR_FATBUF, 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, 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, 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 USE_AUTO_UNIT, 1 ; use unit passed from ROM-BIOS in dl
|
||||||
numdef RPL, 1 ; support RPL and do not overwrite it
|
numdef RPL, 1 ; support RPL and do not overwrite it
|
||||||
numdef RPL_GRACE_AREA, 130 * 1024
|
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 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_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, 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 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_ES, 0 ; if to set es = 0 before jump
|
||||||
numdef ZERO_DS, 0 ; if to set ds = 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 FIX_CLUSTER_SIZE_SKIP_CHECK, 0 ; don't check cluster size
|
||||||
numdef NO_LIMIT, 0 ; allow using more memory than a boot sector
|
numdef NO_LIMIT, 0 ; allow using more memory than a boot sector
|
||||||
; also will not write 0AA55h signature!
|
; 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_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 LBA_RETRY, 0 ; retry LBA reads one time
|
||||||
numdef CHS_RETRY, 1 ; retry CHS reads one time
|
numdef CHS_RETRY, 1 ; retry CHS reads one time
|
||||||
numdef CHS_RETRY_REPEAT,16 ; retry CHS reads multiple times
|
numdef CHS_RETRY_REPEAT,16 ; retry CHS reads multiple times
|
||||||
; (value of the def is used as count)
|
; (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 MEDIAID, 0F0h ; media ID
|
||||||
numdef UNIT, 0 ; load unit in BPB
|
numdef UNIT, 0 ; load unit in BPB
|
||||||
@ -133,7 +145,7 @@ Public domain by C. Masloch, 2012
|
|||||||
|
|
||||||
%if (!!_COMPAT_FREEDOS + !!_COMPAT_IBM + \
|
%if (!!_COMPAT_FREEDOS + !!_COMPAT_IBM + \
|
||||||
!!_COMPAT_MS7 + !!_COMPAT_MS6 + \
|
!!_COMPAT_MS7 + !!_COMPAT_MS6 + \
|
||||||
!!_COMPAT_LDOS || _COMPAT_KERNEL7E) > 1
|
!!_COMPAT_LDOS + !!_COMPAT_KERNEL7E) > 1
|
||||||
%error At most one set must be selected.
|
%error At most one set must be selected.
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
@ -244,7 +256,7 @@ Public domain by C. Masloch, 2012
|
|||||||
strdef LOAD_NAME, "LDOS"
|
strdef LOAD_NAME, "LDOS"
|
||||||
strdef LOAD_EXT, "COM"
|
strdef LOAD_EXT, "COM"
|
||||||
numdef LOAD_ADR, 02000h
|
numdef LOAD_ADR, 02000h
|
||||||
numdef LOAD_MIN_PARA, paras(1536)
|
numdef LOAD_MIN_PARA, paras(4096)
|
||||||
numdef EXEC_SEG_ADJ, 0
|
numdef EXEC_SEG_ADJ, 0
|
||||||
numdef EXEC_OFS, 400h
|
numdef EXEC_OFS, 400h
|
||||||
numdef CHECKOFFSET, 1020
|
numdef CHECKOFFSET, 1020
|
||||||
@ -613,19 +625,73 @@ start:
|
|||||||
|
|
||||||
ADR_STACK_START equ _LASTVARIABLE -start+POSITION
|
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
|
%ifn _FIX_SECTOR_SIZE
|
||||||
; (word) number of 16-byte paragraphs per sector
|
; (word) number of 16-byte paragraphs per sector
|
||||||
nextvariable para_per_sector, 2, relocatestart
|
nextvariable para_per_sector, 2, relocatestart
|
||||||
%endif
|
%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
|
%ifn ! _RELOCATE && _LOAD_ADR < ADR_FREE_UNTIL && _FIX_SECTOR_SIZE
|
||||||
; (word) segment of last available memory for sector
|
; (word) segment of last available memory for sector
|
||||||
nextvariable last_available_sector, 2
|
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
|
%endif
|
||||||
|
|
||||||
lowest_variable equ _LASTVARIABLE
|
lowest_variable equ _LASTVARIABLE
|
||||||
@ -706,8 +772,6 @@ add_name:
|
|||||||
; This happens to be aligned anyway. But even if
|
; This happens to be aligned anyway. But even if
|
||||||
; it didn't, we'd rather save that byte than use
|
; it didn't, we'd rather save that byte than use
|
||||||
; it to align these fields. So comment this out.
|
; it to align these fields. So comment this out.
|
||||||
filename:
|
|
||||||
dw add_name
|
|
||||||
dirseg:
|
dirseg:
|
||||||
dw _ADD_DIR_SEG
|
dw _ADD_DIR_SEG
|
||||||
%endif
|
%endif
|
||||||
@ -724,6 +788,8 @@ dirseg:
|
|||||||
[list -]
|
[list -]
|
||||||
%else
|
%else
|
||||||
; === error.tmp ===
|
; === error.tmp ===
|
||||||
|
error_start:
|
||||||
|
|
||||||
read_sector.err:
|
read_sector.err:
|
||||||
mov al, 'R' ; Disk 'R'ead error
|
mov al, 'R' ; Disk 'R'ead error
|
||||||
%if ! _MEMORY_CONTINUE || _RELOCATE || _LOAD_ADR >= ADR_FREE_FROM
|
%if ! _MEMORY_CONTINUE || _RELOCATE || _LOAD_ADR >= ADR_FREE_FROM
|
||||||
@ -751,6 +817,11 @@ error:
|
|||||||
int 16h
|
int 16h
|
||||||
|
|
||||||
int 19h ; re-start the boot process
|
int 19h ; re-start the boot process
|
||||||
|
|
||||||
|
%if _WARN_PART_SIZE
|
||||||
|
%assign num $ - error_start
|
||||||
|
%warning error size is num bytes
|
||||||
|
%endif
|
||||||
; === eof ===
|
; === eof ===
|
||||||
%endif
|
%endif
|
||||||
%if _TMPINC
|
%if _TMPINC
|
||||||
@ -765,6 +836,7 @@ error:
|
|||||||
[list -]
|
[list -]
|
||||||
%else
|
%else
|
||||||
; === read.tmp ===
|
; === read.tmp ===
|
||||||
|
read_sector_start:
|
||||||
; INP: dx:ax = sector
|
; INP: dx:ax = sector
|
||||||
; OUT: only if successful
|
; OUT: only if successful
|
||||||
; dx:ax = incremented
|
; dx:ax = incremented
|
||||||
@ -775,8 +847,24 @@ error:
|
|||||||
%if ADR_DIRBUF == ADR_FATBUF
|
%if ADR_DIRBUF == ADR_FATBUF
|
||||||
read_sector_dirbuf:
|
read_sector_dirbuf:
|
||||||
%endif
|
%endif
|
||||||
|
%if _FAT16 && ! _LOAD_NON_FAT
|
||||||
read_sector_fatbuf:
|
read_sector_fatbuf:
|
||||||
|
%endif
|
||||||
|
%if (ADR_DIRBUF == ADR_FATBUF) || (_FAT16 && ! _LOAD_NON_FAT)
|
||||||
mov bx, ADR_FATBUF>>4
|
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
|
%endif
|
||||||
|
|
||||||
; Read a sector using Int13.02 or Int13.42
|
; Read a sector using Int13.02 or Int13.42
|
||||||
@ -797,7 +885,7 @@ read_sector:
|
|||||||
push ax
|
push ax
|
||||||
push si
|
push si
|
||||||
|
|
||||||
push bx
|
mov es, bx ; => buffer
|
||||||
|
|
||||||
; DX:AX==LBA sector number
|
; DX:AX==LBA sector number
|
||||||
; add partition start (= number of hidden sectors)
|
; add partition start (= number of hidden sectors)
|
||||||
@ -839,17 +927,22 @@ read_sector:
|
|||||||
jc .no_lba
|
jc .no_lba
|
||||||
cmp bx, 0AA55h
|
cmp bx, 0AA55h
|
||||||
jne .no_lba
|
jne .no_lba
|
||||||
test cl, 1 ; support bitmap bit 0
|
shr cl, 1 ; support bitmap bit 0
|
||||||
jz .no_lba
|
jnc .no_lba
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
%if _LBA_RETRY
|
%if _LBA_RETRY
|
||||||
|
%if _LBA_SKIP_CHECK && _LBA_SKIP_CY
|
||||||
|
stc
|
||||||
|
%endif
|
||||||
mov ah, 42h
|
mov ah, 42h
|
||||||
int 13h ; 13.42 extensions read
|
int 13h ; 13.42 extensions read
|
||||||
jnc .lba_done
|
jnc .lba_done
|
||||||
|
|
||||||
|
%if _RETRY_RESET
|
||||||
xor ax, ax
|
xor ax, ax
|
||||||
int 13h
|
int 13h ; reset disk
|
||||||
|
%endif
|
||||||
|
|
||||||
; have to reset the LBAPACKET's lpCount, as the handler may
|
; have to reset the LBAPACKET's lpCount, as the handler may
|
||||||
; set it to "the number of blocks successfully transferred".
|
; set it to "the number of blocks successfully transferred".
|
||||||
@ -857,10 +950,17 @@ read_sector:
|
|||||||
mov byte [si + 2], 1
|
mov byte [si + 2], 1
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
|
%if _LBA_SKIP_CHECK && _LBA_SKIP_CY
|
||||||
|
stc
|
||||||
|
%endif
|
||||||
mov ah, 42h
|
mov ah, 42h
|
||||||
int 13h
|
int 13h
|
||||||
%if _LBA_SKIP_CHECK && _CHS
|
%if _LBA_SKIP_CHECK && _CHS
|
||||||
|
%if _LBA_SKIP_ANY
|
||||||
|
jc .no_lba
|
||||||
|
%else
|
||||||
jc .lba_check_error_1
|
jc .lba_check_error_1
|
||||||
|
%endif
|
||||||
%else
|
%else
|
||||||
.cy_err:
|
.cy_err:
|
||||||
jc .lba_error
|
jc .lba_error
|
||||||
@ -871,10 +971,8 @@ read_sector:
|
|||||||
mov byte [bp + 2], 0Eh ; LBA-enabled FAT16 FS partition type
|
mov byte [bp + 2], 0Eh ; LBA-enabled FAT16 FS partition type
|
||||||
%endif
|
%endif
|
||||||
add sp, 10h
|
add sp, 10h
|
||||||
pop bx
|
|
||||||
mov es, bx
|
|
||||||
%if _CHS
|
%if _CHS
|
||||||
jmp short .chs_done
|
jmp short .done
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
.lba_error: equ .err
|
.lba_error: equ .err
|
||||||
@ -883,10 +981,12 @@ read_sector:
|
|||||||
.no_lba: equ .err
|
.no_lba: equ .err
|
||||||
%else
|
%else
|
||||||
%if _LBA_SKIP_CHECK
|
%if _LBA_SKIP_CHECK
|
||||||
|
%if ! _LBA_SKIP_ANY
|
||||||
.lba_check_error_1:
|
.lba_check_error_1:
|
||||||
cmp ah, 1 ; invalid function?
|
cmp ah, 1 ; invalid function?
|
||||||
jne .lba_error ; no, other error -->
|
jne .lba_error ; no, other error -->
|
||||||
; try CHS instead
|
; try CHS instead
|
||||||
|
%endif
|
||||||
.cy_err: equ .err
|
.cy_err: equ .err
|
||||||
%endif
|
%endif
|
||||||
.no_lba:
|
.no_lba:
|
||||||
@ -955,29 +1055,50 @@ read_sector:
|
|||||||
|
|
||||||
; we call INT 13h AH=02h once for each sector. Multi-sector reads
|
; we call INT 13h AH=02h once for each sector. Multi-sector reads
|
||||||
; may fail if we cross a track or 64K boundary
|
; may fail if we cross a track or 64K boundary
|
||||||
pop es
|
|
||||||
%if _CHS_RETRY_REPEAT
|
%if _CHS_RETRY_REPEAT
|
||||||
mov si, _CHS_RETRY_REPEAT + 1
|
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:
|
.loop_chs_retry_repeat:
|
||||||
mov ax, 0201h
|
|
||||||
int 13h ; read one sector
|
|
||||||
jnc .done
|
|
||||||
xor ax, ax
|
xor ax, ax
|
||||||
int 13h ; reset disk
|
int 13h ; reset disk
|
||||||
|
%else
|
||||||
|
.loop_chs_retry_repeat:
|
||||||
|
%endif
|
||||||
dec si ; another attempt ?
|
dec si ; another attempt ?
|
||||||
jnz .loop_chs_retry_repeat ; yes -->
|
js .nz_err ; no -->
|
||||||
jmp .err
|
|
||||||
%else
|
|
||||||
%if _CHS_RETRY
|
|
||||||
mov ax, 0201h
|
mov ax, 0201h
|
||||||
int 13h ; read one sector
|
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
|
jnc .done
|
||||||
; reset drive
|
; reset drive
|
||||||
xor ax, ax
|
xor ax, ax
|
||||||
int 13h
|
int 13h
|
||||||
|
mov ax, 0201h
|
||||||
|
%else
|
||||||
|
push ax
|
||||||
|
int 13h ; read one sector
|
||||||
|
pop ax ; restore ax = 0201h
|
||||||
|
jnc .done
|
||||||
|
%endif
|
||||||
%endif
|
%endif
|
||||||
; try read again
|
; try read again
|
||||||
mov ax, 0201h
|
|
||||||
int 13h
|
int 13h
|
||||||
%if _LBA_SKIP_CHECK
|
%if _LBA_SKIP_CHECK
|
||||||
inc bx
|
inc bx
|
||||||
@ -987,12 +1108,11 @@ read_sector:
|
|||||||
%endif
|
%endif
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
|
%endif ; _CHS
|
||||||
|
|
||||||
.done:
|
.done:
|
||||||
; increment segment
|
; increment segment
|
||||||
mov bx, es
|
mov bx, es
|
||||||
%endif
|
|
||||||
|
|
||||||
.chs_done:
|
|
||||||
%if _FIX_SECTOR_SIZE
|
%if _FIX_SECTOR_SIZE
|
||||||
add bx, _FIX_SECTOR_SIZE >> 4
|
add bx, _FIX_SECTOR_SIZE >> 4
|
||||||
%else
|
%else
|
||||||
@ -1010,6 +1130,11 @@ read_sector:
|
|||||||
@@:
|
@@:
|
||||||
|
|
||||||
retn
|
retn
|
||||||
|
|
||||||
|
%if _WARN_PART_SIZE
|
||||||
|
%assign num $ - read_sector_start
|
||||||
|
%warning read_sector size is num bytes
|
||||||
|
%endif
|
||||||
; === eof ===
|
; === eof ===
|
||||||
%endif
|
%endif
|
||||||
%if _TMPINC
|
%if _TMPINC
|
||||||
@ -1020,6 +1145,11 @@ read_sector:
|
|||||||
[list +]
|
[list +]
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
|
%if _WARN_PART_SIZE
|
||||||
|
%assign num $ - start
|
||||||
|
%warning BPB + data size is num bytes
|
||||||
|
%endif
|
||||||
|
|
||||||
|
|
||||||
; Code
|
; 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
|
; 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
|
; as a valid partition table entry by this handling. Therefore, we
|
||||||
; only accept partition information when booting from a hard disk now.
|
; only accept partition information when booting from a hard disk now.
|
||||||
|
|
||||||
|
; start of magic byte sequence for instsect
|
||||||
test dl, dl ; floppy ?
|
test dl, dl ; floppy ?
|
||||||
jns @F ; don't attempt detection -->
|
jns @F ; don't attempt detection -->
|
||||||
; Check whether an MBR left us partition information.
|
; Check whether an MBR left us partition information.
|
||||||
@ -1058,15 +1190,23 @@ skip_bpb:
|
|||||||
; Assume the movsw instructions won't run with si = FFFFh.
|
; Assume the movsw instructions won't run with si = FFFFh.
|
||||||
mov di, hidden_sectors ; -> BPB field
|
mov di, hidden_sectors ; -> BPB field
|
||||||
add si, 8 ; -> partition start sector in info
|
add si, 8 ; -> partition start sector in info
|
||||||
|
%if _USE_PART_INFO_DISABLED
|
||||||
|
nop
|
||||||
|
nop ; size has to match enabled code
|
||||||
|
%else
|
||||||
movsw
|
movsw
|
||||||
movsw ; overwrite BPB field with value from info
|
movsw ; overwrite BPB field with value from info
|
||||||
|
%endif
|
||||||
@@:
|
@@:
|
||||||
|
; end of magic byte sequence for instsect
|
||||||
%endif
|
%endif
|
||||||
mov ds, cx
|
mov ds, cx
|
||||||
sti
|
sti
|
||||||
|
|
||||||
|
|
||||||
%if _QUERY_GEOMETRY ; +27 bytes
|
%if _QUERY_GEOMETRY ; +27 bytes
|
||||||
|
|
||||||
|
; start of magic byte sequence for instsect
|
||||||
; test dl, dl ; floppy?
|
; test dl, dl ; floppy?
|
||||||
; jns @F ; don't attempt query, might fail -->
|
; jns @F ; don't attempt query, might fail -->
|
||||||
; Note that while the original PC BIOS doesn't support this function
|
; 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
|
; xor cx, cx ; initialise cl to 0
|
||||||
; Already from prologue cx = 0.
|
; Already from prologue cx = 0.
|
||||||
stc ; initialise to CY
|
stc ; initialise to CY
|
||||||
|
%if _QUERY_GEOMETRY_DISABLED
|
||||||
|
nop
|
||||||
|
nop ; size has to match enabled code
|
||||||
|
%else
|
||||||
int 13h ; query drive geometry
|
int 13h ; query drive geometry
|
||||||
|
%endif
|
||||||
jc @F ; apparently failed -->
|
jc @F ; apparently failed -->
|
||||||
and cx, 3Fh ; get sectors
|
and cx, 3Fh ; get sectors
|
||||||
jz @F ; invalid (S is 1-based), don't use -->
|
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)
|
inc cx ; cx = number of heads (H is 0-based)
|
||||||
mov [VAR(heads)], cx
|
mov [VAR(heads)], cx
|
||||||
@@:
|
@@:
|
||||||
|
; end of magic byte sequence for instsect
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
%if _FIX_SECTOR_SIZE
|
%if _FIX_SECTOR_SIZE
|
||||||
@ -1100,15 +1246,6 @@ skip_bpb:
|
|||||||
mov al, 'C'
|
mov al, 'C'
|
||||||
jne error
|
jne error
|
||||||
%endif
|
%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
|
%endif
|
||||||
mov ch, 0 ; ! ch = 0
|
mov ch, 0 ; ! ch = 0
|
||||||
%else
|
%else
|
||||||
@ -1123,16 +1260,7 @@ skip_bpb:
|
|||||||
jne error
|
jne error
|
||||||
%endif
|
%endif
|
||||||
%else
|
%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
|
; ! 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
|
%endif
|
||||||
push bx ; push into word [VAR(para_per_sector)]
|
push bx ; push into word [VAR(para_per_sector)]
|
||||||
|
|
||||||
@ -1140,6 +1268,14 @@ skip_bpb:
|
|||||||
shr bx, 1 ; /2 = 32-byte entries per sector
|
shr bx, 1 ; /2 = 32-byte entries per sector
|
||||||
%endif
|
%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)
|
; number of sectors used for root directory (store in CX)
|
||||||
mov si, [VAR(num_root_dir_ents)]
|
mov si, [VAR(num_root_dir_ents)]
|
||||||
mov ax, bx
|
mov ax, bx
|
||||||
@ -1194,21 +1330,48 @@ next_sect:
|
|||||||
|
|
||||||
xor di, di ; es:di-> first entry in this sector
|
xor di, di ; es:di-> first entry in this sector
|
||||||
next_ent:
|
next_ent:
|
||||||
|
%if DIRSEARCHSTACK_CL_FIRST
|
||||||
|
push cx ; first dirsearchstack word = entries-in-sector
|
||||||
|
push si ; other: entries total
|
||||||
|
%else
|
||||||
push si
|
push si
|
||||||
push di
|
push cx ; second dirsearchstack word = entries-in-sector
|
||||||
push cx
|
%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
|
%if _ADD_SEARCH
|
||||||
mov si, [VAR(filename)]
|
mov si, add_name
|
||||||
|
filename equ $ - 2 ; SMC to update to load_name later
|
||||||
%else
|
%else
|
||||||
mov si, load_name ; ds:si-> name to match
|
mov si, load_name ; ds:si-> name to match
|
||||||
%endif
|
%endif
|
||||||
mov cx, 11 ; length of padded 8.3 FAT filename
|
mov cx, 11 ; length of padded 8.3 FAT filename
|
||||||
repe cmpsb ; check entry
|
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
|
pop di
|
||||||
|
%if DIRSEARCHSTACK_CL_FIRST
|
||||||
pop si
|
pop si
|
||||||
|
pop cx ; pop from dirsearchstack
|
||||||
|
%else
|
||||||
|
pop cx
|
||||||
|
pop si ; pop from dirsearchstack
|
||||||
|
%endif
|
||||||
lea di, [di + DIRENTRY_size]
|
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
|
dec si ; count down entire root's entries
|
||||||
loopnz next_ent ; count down sector's entries (jumps iff si >0 && cx >0)
|
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:
|
found_it:
|
||||||
%if _ADD_SEARCH || _LOAD_DIR_SEG
|
%if _ADD_SEARCH || _LOAD_DIR_SEG
|
||||||
|
%if _ATTRIB_SAVE
|
||||||
|
pop di ; es:di -> dir entry (pop from dirsearchstack)
|
||||||
|
%endif
|
||||||
mov cx, 32
|
mov cx, 32
|
||||||
mov ax, _LOAD_DIR_SEG
|
mov ax, _LOAD_DIR_SEG
|
||||||
|
%if ! _ATTRIB_SAVE
|
||||||
sub di, cx ; es:di -> dir entry
|
sub di, cx ; es:di -> dir entry
|
||||||
|
%endif
|
||||||
%if _ADD_SEARCH
|
%if _ADD_SEARCH
|
||||||
xchg ax, word [VAR(dirseg)]
|
xchg ax, word [VAR(dirseg)]
|
||||||
%endif
|
%endif
|
||||||
@ -1281,12 +1449,18 @@ found_it:
|
|||||||
%else
|
%else
|
||||||
%error Must not store directory entries to same segment
|
%error Must not store directory entries to same segment
|
||||||
%endif
|
%endif
|
||||||
|
%if _ATTRIB_SAVE
|
||||||
|
pop si ; discard cx/si
|
||||||
|
pop si ; discard si/cx (dirsearchstack)
|
||||||
|
%endif
|
||||||
pop si
|
pop si
|
||||||
pop ax
|
pop ax
|
||||||
pop dx ; restore root start and count
|
pop dx ; restore root start and count
|
||||||
; (bx still holds entries per sector)
|
; (bx still holds entries per sector)
|
||||||
je next_dir_search ; jump to search load file next -->
|
je next_dir_search ; jump to search load file next -->
|
||||||
%endif
|
%endif
|
||||||
|
times PLACEHOLDER push bx
|
||||||
|
; push into cmdline_signature_placeholder
|
||||||
%if _RELOCATE
|
%if _RELOCATE
|
||||||
push word [es:di + deClusterLow]
|
push word [es:di + deClusterLow]
|
||||||
; (word on stack) = first cluster number
|
; (word on stack) = first cluster number
|
||||||
@ -1294,10 +1468,14 @@ found_it:
|
|||||||
%else
|
%else
|
||||||
%if _DIR_ENTRY_500 ; +24 bytes, probably
|
%if _DIR_ENTRY_500 ; +24 bytes, probably
|
||||||
mov cx, 32
|
mov cx, 32
|
||||||
push ds
|
%if _ATTRIB_SAVE
|
||||||
push es
|
pop si ; es:si -> dir entry (pop from dirsearchstack)
|
||||||
|
%else
|
||||||
xchg si, di
|
xchg si, di
|
||||||
sub si, cx
|
sub si, cx
|
||||||
|
%endif
|
||||||
|
push ds
|
||||||
|
push es
|
||||||
push es
|
push es
|
||||||
pop ds ; ds:si -> directory entry
|
pop ds ; ds:si -> directory entry
|
||||||
xor ax, ax
|
xor ax, ax
|
||||||
@ -1312,14 +1490,30 @@ found_it:
|
|||||||
pop ds
|
pop ds
|
||||||
xchg si, di ; es:di -> behind (second) directory entry
|
xchg si, di ; es:di -> behind (second) directory entry
|
||||||
%endif
|
%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 _RELOCATE
|
||||||
|
%if _DIR_ENTRY_500 || !_ATTRIB_SAVE
|
||||||
push word [es:di + deClusterLow - DIRENTRY_size \
|
push word [es:di + deClusterLow - DIRENTRY_size \
|
||||||
- (DIRENTRY_size * !!_DIR_ENTRY_520)]
|
- (DIRENTRY_size * !!_DIR_ENTRY_520)]
|
||||||
; (word on stack) = first cluster number
|
; (word on stack) = first cluster number
|
||||||
|
%else
|
||||||
|
push word [es:di + deClusterLow - (deName + 11)]
|
||||||
|
; (word on stack) = first cluster number
|
||||||
|
%endif
|
||||||
%endif
|
%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
|
%if _RELOCATE || _LOAD_ADR >= ADR_FREE_FROM
|
||||||
|
memory_start:
|
||||||
; Get conventional memory size and store it
|
; Get conventional memory size and store it
|
||||||
int 12h
|
int 12h
|
||||||
mov cl, 6
|
mov cl, 6
|
||||||
@ -1406,6 +1600,11 @@ found_it:
|
|||||||
rep movsw ; relocate stack, sector
|
rep movsw ; relocate stack, sector
|
||||||
retf ; jump to relocated code
|
retf ; jump to relocated code
|
||||||
|
|
||||||
|
%if _WARN_PART_SIZE
|
||||||
|
%assign num $ - memory_start
|
||||||
|
%warning memory size is num bytes
|
||||||
|
%endif
|
||||||
|
|
||||||
|
|
||||||
readhandler
|
readhandler
|
||||||
|
|
||||||
@ -1442,10 +1641,13 @@ relocated:
|
|||||||
push ax ; push into word [VAR(last_available_sector)]
|
push ax ; push into word [VAR(last_available_sector)]
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
|
read_fat_start:
|
||||||
; get starting cluster of file
|
; get starting cluster of file
|
||||||
%if ! _RELOCATE
|
%if ! _RELOCATE
|
||||||
%if _ADD_SEARCH || _LOAD_DIR_SEG
|
%if _ADD_SEARCH || _LOAD_DIR_SEG
|
||||||
mov si,[es:di + deClusterLow]
|
mov si,[es:di + deClusterLow]
|
||||||
|
%elif _ATTRIB_SAVE && ! _DIR_ENTRY_500
|
||||||
|
mov si,[es:di - deAttrib + deClusterLow]
|
||||||
%else
|
%else
|
||||||
mov si,[es:di + deClusterLow - DIRENTRY_size \
|
mov si,[es:di + deClusterLow - DIRENTRY_size \
|
||||||
- (DIRENTRY_size * !!_DIR_ENTRY_520)]
|
- (DIRENTRY_size * !!_DIR_ENTRY_520)]
|
||||||
@ -1510,10 +1712,9 @@ relocated:
|
|||||||
mov bx, _LOAD_ADR>>4 ; => load address
|
mov bx, _LOAD_ADR>>4 ; => load address
|
||||||
%if _FAT16 && !_LOAD_NON_FAT
|
%if _FAT16 && !_LOAD_NON_FAT
|
||||||
mov di, -1 ; = no FAT sector read yet
|
mov di, -1 ; = no FAT sector read yet
|
||||||
%if _SET_FAT_SEG
|
%if _SET_FAT_SEG && _SET_FAT_SEG_NORMAL
|
||||||
%if ! _RELOCATE
|
; This is not strictly needed because a FAT sector is
|
||||||
mov word [VAR(fat_seg)], ADR_FATBUF>>4
|
; read in any case, initialising this variable later.
|
||||||
%endif
|
|
||||||
mov word [VAR(fat_sector)], di
|
mov word [VAR(fat_sector)], di
|
||||||
%endif
|
%endif
|
||||||
%endif
|
%endif
|
||||||
@ -1637,7 +1838,10 @@ next_cluster:
|
|||||||
|
|
||||||
%else ; _LOAD_NON_FAT
|
%else ; _LOAD_NON_FAT
|
||||||
mov di, _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
|
mov cx, ax
|
||||||
mul word [VAR(bytes_per_sector)]
|
mul word [VAR(bytes_per_sector)]
|
||||||
test dx, dx
|
test dx, dx
|
||||||
@ -1656,7 +1860,12 @@ next_cluster:
|
|||||||
%if _FIX_CLUSTER_SIZE
|
%if _FIX_CLUSTER_SIZE
|
||||||
mov cx, _FIX_CLUSTER_SIZE
|
mov cx, _FIX_CLUSTER_SIZE
|
||||||
%else
|
%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
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
@ -1669,7 +1878,7 @@ next_cluster:
|
|||||||
; xxx - this will always load an entire cluster (e.g. 64 sectors),
|
; xxx - this will always load an entire cluster (e.g. 64 sectors),
|
||||||
; even if the file is shorter than this
|
; 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)
|
cmp bx, (ADR_FREE_UNTIL >> 4) - (_FIX_SECTOR_SIZE >> 4)
|
||||||
%else
|
%else
|
||||||
cmp bx, [VAR(last_available_sector)]
|
cmp bx, [VAR(last_available_sector)]
|
||||||
@ -1708,8 +1917,21 @@ next_cluster:
|
|||||||
%endif ; _LOAD_NON_FAT
|
%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_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
|
cmp bx, (_LOAD_ADR >> 4) + _LOAD_MIN_PARA
|
||||||
|
%endif
|
||||||
mov al, 'E'
|
mov al, 'E'
|
||||||
jb error
|
jb error
|
||||||
%endif
|
%endif
|
||||||
@ -1827,6 +2049,12 @@ CHECKLINEAR equ _LOAD_ADR + _CHECKOFFSET
|
|||||||
jmp (_LOAD_ADR>>4)+_EXEC_SEG_ADJ:_EXEC_OFS
|
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
|
%if ! _RELOCATE
|
||||||
errorhandler
|
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 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, 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, 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 USE_AUTO_UNIT, 1 ; use unit passed from ROM-BIOS in dl
|
||||||
numdef RPL, 1 ; support RPL and do not overwrite it
|
numdef RPL, 1 ; support RPL and do not overwrite it
|
||||||
numdef CHS, 1 ; support CHS (if it fits)
|
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 FIX_CLUSTER_SIZE_SKIP_CHECK, 0 ; don't check cluster size
|
||||||
numdef NO_LIMIT, 0 ; allow using more memory than a boot sector
|
numdef NO_LIMIT, 0 ; allow using more memory than a boot sector
|
||||||
; also will not write 0AA55h signature!
|
; 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_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 LBA_RETRY, 0 ; retry LBA reads one time
|
||||||
numdef CHS_RETRY, 1 ; retry CHS reads one time
|
numdef CHS_RETRY, 1 ; retry CHS reads one time
|
||||||
numdef CHS_RETRY_REPEAT,16 ; retry CHS reads multiple times
|
numdef CHS_RETRY_REPEAT,16 ; retry CHS reads multiple times
|
||||||
; (value of the def is used as count)
|
; (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
|
; Unlike the 1440 KiB diskette image defaults for the FAT12
|
||||||
; loader we just fill the BPB with zeros by default.
|
; 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)
|
; => directory sector buffer (one sector)
|
||||||
%endif
|
%endif
|
||||||
.writedirentry: dw writedirentry.loaddir
|
.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
|
.filename: dw .load_name
|
||||||
; -> name to search
|
; -> name to search
|
||||||
.minpara: dw _LOAD_MIN_PARA
|
.minpara: dw _LOAD_MIN_PARA
|
||||||
@ -628,6 +645,11 @@ fsiboot_table: ; this table is used by the FSIBOOT stage
|
|||||||
fsiboot_name:
|
fsiboot_name:
|
||||||
fill 8, 32, db _FSIBOOTNAME
|
fill 8, 32, db _FSIBOOTNAME
|
||||||
|
|
||||||
|
%if _WARN_PART_SIZE
|
||||||
|
%assign num $ - start
|
||||||
|
%warning BPB + data size is num bytes
|
||||||
|
%endif
|
||||||
|
|
||||||
|
|
||||||
; Code
|
; 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
|
; 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
|
; as a valid partition table entry by this handling. Therefore, we
|
||||||
; only accept partition information when booting from a hard disk now.
|
; only accept partition information when booting from a hard disk now.
|
||||||
|
|
||||||
|
; start of magic byte sequence for instsect
|
||||||
test dl, dl ; floppy ?
|
test dl, dl ; floppy ?
|
||||||
jns @F ; don't attempt detection -->
|
jns @F ; don't attempt detection -->
|
||||||
; Check whether an MBR left us partition information.
|
; Check whether an MBR left us partition information.
|
||||||
@ -667,15 +691,23 @@ skip_bpb:
|
|||||||
; Assume the movsw instructions won't run with si = FFFFh.
|
; Assume the movsw instructions won't run with si = FFFFh.
|
||||||
mov di, hidden_sectors ; -> BPB field
|
mov di, hidden_sectors ; -> BPB field
|
||||||
add si, 8 ; -> partition start sector in info
|
add si, 8 ; -> partition start sector in info
|
||||||
|
%if _USE_PART_INFO_DISABLED
|
||||||
|
nop
|
||||||
|
nop ; size has to match enabled code
|
||||||
|
%else
|
||||||
movsw
|
movsw
|
||||||
movsw ; overwrite BPB field with value from info
|
movsw ; overwrite BPB field with value from info
|
||||||
|
%endif
|
||||||
@@:
|
@@:
|
||||||
|
; end of magic byte sequence for instsect
|
||||||
%endif
|
%endif
|
||||||
mov ds, cx
|
mov ds, cx
|
||||||
sti
|
sti
|
||||||
|
|
||||||
|
|
||||||
%if _QUERY_GEOMETRY ; +27 bytes
|
%if _QUERY_GEOMETRY ; +27 bytes
|
||||||
|
|
||||||
|
; start of magic byte sequence for instsect
|
||||||
; test dl, dl ; floppy?
|
; test dl, dl ; floppy?
|
||||||
; jns @F ; don't attempt query, might fail -->
|
; jns @F ; don't attempt query, might fail -->
|
||||||
; Note that while the original PC BIOS doesn't support this function
|
; 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
|
; xor cx, cx ; initialise cl to 0
|
||||||
; Already from prologue cx = 0.
|
; Already from prologue cx = 0.
|
||||||
stc ; initialise to CY
|
stc ; initialise to CY
|
||||||
|
%if _QUERY_GEOMETRY_DISABLED
|
||||||
|
nop
|
||||||
|
nop ; size has to match enabled code
|
||||||
|
%else
|
||||||
int 13h ; query drive geometry
|
int 13h ; query drive geometry
|
||||||
|
%endif
|
||||||
jc @F ; apparently failed -->
|
jc @F ; apparently failed -->
|
||||||
and cx, 3Fh ; get sectors
|
and cx, 3Fh ; get sectors
|
||||||
jz @F ; invalid (S is 1-based), don't use -->
|
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)
|
inc cx ; cx = number of heads (H is 0-based)
|
||||||
mov [VAR(heads)], cx
|
mov [VAR(heads)], cx
|
||||||
@@:
|
@@:
|
||||||
|
; end of magic byte sequence for instsect
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
|
|
||||||
@ -854,6 +892,13 @@ load_fsiboot:
|
|||||||
%endif
|
%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
|
; INP: es:bx -> found dir entry in dir sector buffer
|
||||||
; si:di = loaded sector-in-FAT
|
; si:di = loaded sector-in-FAT
|
||||||
; CHG: ax, cx, dx
|
; CHG: ax, cx, dx
|
||||||
@ -1030,6 +1075,13 @@ CHECKLINEAR equ _LOAD_ADR + _CHECKOFFSET
|
|||||||
; ss:bp-> boot sector with BPB
|
; ss:bp-> boot sector with BPB
|
||||||
jmp (_LOAD_ADR>>4)+_EXEC_SEG_ADJ:_EXEC_OFS
|
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:
|
error_fsiboot:
|
||||||
mov al,'I'
|
mov al,'I'
|
||||||
@ -1057,6 +1109,11 @@ error:
|
|||||||
|
|
||||||
int 19h ; re-start the boot process
|
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
|
; Read a sector using Int13.02 or Int13.42
|
||||||
;
|
;
|
||||||
@ -1076,7 +1133,7 @@ read_sector:
|
|||||||
push ax
|
push ax
|
||||||
push si
|
push si
|
||||||
|
|
||||||
push bx
|
mov es, bx ; => buffer
|
||||||
|
|
||||||
; DX:AX==LBA sector number
|
; DX:AX==LBA sector number
|
||||||
; add partition start (= number of hidden sectors)
|
; add partition start (= number of hidden sectors)
|
||||||
@ -1118,17 +1175,22 @@ read_sector:
|
|||||||
jc .no_lba
|
jc .no_lba
|
||||||
cmp bx, 0AA55h
|
cmp bx, 0AA55h
|
||||||
jne .no_lba
|
jne .no_lba
|
||||||
test cl, 1 ; support bitmap bit 0
|
shr cl, 1 ; support bitmap bit 0
|
||||||
jz .no_lba
|
jnc .no_lba
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
%if _LBA_RETRY
|
%if _LBA_RETRY
|
||||||
|
%if _LBA_SKIP_CHECK && _LBA_SKIP_CY
|
||||||
|
stc
|
||||||
|
%endif
|
||||||
mov ah, 42h
|
mov ah, 42h
|
||||||
int 13h ; 13.42 extensions read
|
int 13h ; 13.42 extensions read
|
||||||
jnc .lba_done
|
jnc .lba_done
|
||||||
|
|
||||||
|
%if _RETRY_RESET
|
||||||
xor ax, ax
|
xor ax, ax
|
||||||
int 13h
|
int 13h ; reset disk
|
||||||
|
%endif
|
||||||
|
|
||||||
; have to reset the LBAPACKET's lpCount, as the handler may
|
; have to reset the LBAPACKET's lpCount, as the handler may
|
||||||
; set it to "the number of blocks successfully transferred".
|
; set it to "the number of blocks successfully transferred".
|
||||||
@ -1136,15 +1198,24 @@ read_sector:
|
|||||||
mov byte [si + 2], 1
|
mov byte [si + 2], 1
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
|
%if _LBA_SKIP_CHECK && _LBA_SKIP_CY
|
||||||
|
stc
|
||||||
|
%endif
|
||||||
mov ah, 42h
|
mov ah, 42h
|
||||||
int 13h
|
int 13h
|
||||||
%if _LBA_SKIP_CHECK && _CHS
|
%if _LBA_SKIP_CHECK && _CHS
|
||||||
|
%if _LBA_SKIP_ANY
|
||||||
|
jc .no_lba
|
||||||
|
.err_CY: equ .err
|
||||||
|
.err_2: equ .err
|
||||||
|
%else
|
||||||
jnc .lba_done
|
jnc .lba_done
|
||||||
cmp ah, 1 ; invalid function?
|
cmp ah, 1 ; invalid function?
|
||||||
je .no_lba ; try CHS instead -->
|
je .no_lba ; try CHS instead -->
|
||||||
.err_CY:
|
.err_CY:
|
||||||
.err_2:
|
.err_2:
|
||||||
jmp .lba_error
|
jmp .lba_error
|
||||||
|
%endif
|
||||||
%else
|
%else
|
||||||
.err_CY:
|
.err_CY:
|
||||||
jc .lba_error
|
jc .lba_error
|
||||||
@ -1156,10 +1227,8 @@ read_sector:
|
|||||||
mov byte [bp + 2], 0Ch ; LBA-enabled FAT32 FS partition type
|
mov byte [bp + 2], 0Ch ; LBA-enabled FAT32 FS partition type
|
||||||
%endif
|
%endif
|
||||||
add sp, 10h
|
add sp, 10h
|
||||||
pop bx
|
|
||||||
mov es, bx
|
|
||||||
%if _CHS
|
%if _CHS
|
||||||
jmp short .chs_done
|
jmp short .done
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
.lba_error: equ .err
|
.lba_error: equ .err
|
||||||
@ -1225,34 +1294,56 @@ read_sector:
|
|||||||
; ah has bits set iff it was >= 4, indicating a cylinder >= 1024.
|
; ah has bits set iff it was >= 4, indicating a cylinder >= 1024.
|
||||||
or bl, ah ; collect set bits from ah
|
or bl, ah ; collect set bits from ah
|
||||||
mov dl,[VAR(boot_unit)] ; dl = drive
|
mov dl,[VAR(boot_unit)] ; dl = drive
|
||||||
|
.nz_err:
|
||||||
jnz .err_2 ; error if cylinder >= 1024 -->
|
jnz .err_2 ; error if cylinder >= 1024 -->
|
||||||
; ! bx = 0 (for 13.02 call)
|
; ! bx = 0 (for 13.02 call)
|
||||||
|
|
||||||
; we call INT 13h AH=02h once for each sector. Multi-sector reads
|
; we call INT 13h AH=02h once for each sector. Multi-sector reads
|
||||||
; may fail if we cross a track or 64K boundary
|
; may fail if we cross a track or 64K boundary
|
||||||
pop es
|
|
||||||
%if _CHS_RETRY_REPEAT
|
%if _CHS_RETRY_REPEAT
|
||||||
mov si, _CHS_RETRY_REPEAT + 1
|
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:
|
.loop_chs_retry_repeat:
|
||||||
mov ax, 0201h
|
|
||||||
int 13h ; read one sector
|
|
||||||
jnc .done
|
|
||||||
xor ax, ax
|
xor ax, ax
|
||||||
int 13h ; reset disk
|
int 13h ; reset disk
|
||||||
|
%else
|
||||||
|
.loop_chs_retry_repeat:
|
||||||
|
%endif
|
||||||
dec si ; another attempt ?
|
dec si ; another attempt ?
|
||||||
jnz .loop_chs_retry_repeat ; yes -->
|
js .nz_err ; no -->
|
||||||
jmp .err_2
|
|
||||||
%else
|
|
||||||
%if _CHS_RETRY
|
|
||||||
mov ax, 0201h
|
mov ax, 0201h
|
||||||
int 13h ; read one sector
|
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
|
jnc .done
|
||||||
; reset drive
|
; reset drive
|
||||||
xor ax, ax
|
xor ax, ax
|
||||||
int 13h
|
int 13h
|
||||||
|
mov ax, 0201h
|
||||||
|
%else
|
||||||
|
push ax
|
||||||
|
int 13h ; read one sector
|
||||||
|
pop ax ; restore ax = 0201h
|
||||||
|
jnc .done
|
||||||
|
%endif
|
||||||
%endif
|
%endif
|
||||||
; try read again
|
; try read again
|
||||||
mov ax, 0201h
|
|
||||||
int 13h
|
int 13h
|
||||||
jc .err_CY
|
jc .err_CY
|
||||||
%endif
|
%endif
|
||||||
@ -1260,12 +1351,11 @@ read_sector:
|
|||||||
.err_CY: equ .err
|
.err_CY: equ .err
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
|
%endif ; _CHS
|
||||||
|
|
||||||
.done:
|
.done:
|
||||||
; increment segment
|
; increment segment
|
||||||
mov bx, es
|
mov bx, es
|
||||||
%endif
|
|
||||||
|
|
||||||
.chs_done:
|
|
||||||
%if _FIX_SECTOR_SIZE
|
%if _FIX_SECTOR_SIZE
|
||||||
add bx, _FIX_SECTOR_SIZE >> 4
|
add bx, _FIX_SECTOR_SIZE >> 4
|
||||||
%else
|
%else
|
||||||
@ -1285,6 +1375,11 @@ read_sector:
|
|||||||
.retn:
|
.retn:
|
||||||
retn
|
retn
|
||||||
|
|
||||||
|
%if _WARN_PART_SIZE
|
||||||
|
%assign num $ - read_sector
|
||||||
|
%warning read_sector size is num bytes
|
||||||
|
%endif
|
||||||
|
|
||||||
|
|
||||||
%if _ADD_SEARCH
|
%if _ADD_SEARCH
|
||||||
add_name: ; = blank-padded 11-byte filename to search for
|
add_name: ; = blank-padded 11-byte filename to search for
|
||||||
@ -1381,9 +1476,9 @@ fsiboot:
|
|||||||
|
|
||||||
; adjusted sectors per cluster (store in a word,
|
; adjusted sectors per cluster (store in a word,
|
||||||
; and decode EDR-DOS's special value 0 meaning 256)
|
; and decode EDR-DOS's special value 0 meaning 256)
|
||||||
xor ax, ax
|
|
||||||
mov al, [VAR(sectors_per_cluster)]
|
mov al, [VAR(sectors_per_cluster)]
|
||||||
dec al
|
dec ax
|
||||||
|
mov ah, 0
|
||||||
inc ax
|
inc ax
|
||||||
push ax ; push into word [VAR(adj_sectors_per_cluster)]
|
push ax ; push into word [VAR(adj_sectors_per_cluster)]
|
||||||
dec ax ; ! ah = 0
|
dec ax ; ! ah = 0
|
||||||
@ -1483,13 +1578,11 @@ found_load_file:
|
|||||||
jc ..@CY_3_fsiboot_error_badchain
|
jc ..@CY_3_fsiboot_error_badchain
|
||||||
|
|
||||||
next_load_cluster:
|
next_load_cluster:
|
||||||
|
push dx
|
||||||
|
push ax ; preserve cluster number for later
|
||||||
call clust_to_first_sector
|
call clust_to_first_sector
|
||||||
; dx:ax = first sector of cluster
|
; dx:ax = first sector of cluster
|
||||||
; cx:bx = cluster value
|
; cx = adjusted sectors per cluster
|
||||||
push cx
|
|
||||||
push bx ; preserve cluster number for later
|
|
||||||
|
|
||||||
mov cx, [VAR(adj_sectors_per_cluster)]
|
|
||||||
|
|
||||||
; xxx - this will always load an entire cluster (e.g. 64 sectors),
|
; xxx - this will always load an entire cluster (e.g. 64 sectors),
|
||||||
; even if the file is shorter than this
|
; even if the file is shorter than this
|
||||||
@ -1510,8 +1603,8 @@ next_load_cluster:
|
|||||||
jbe @F ; read enough -->
|
jbe @F ; read enough -->
|
||||||
|
|
||||||
loop @BB
|
loop @BB
|
||||||
pop bx
|
pop ax
|
||||||
pop cx
|
pop dx
|
||||||
|
|
||||||
call clust_next
|
call clust_next
|
||||||
jnc next_load_cluster
|
jnc next_load_cluster
|
||||||
@ -1536,10 +1629,11 @@ dirsearch:
|
|||||||
jc fsiboot_error_badchain
|
jc fsiboot_error_badchain
|
||||||
|
|
||||||
next_root_clust:
|
next_root_clust:
|
||||||
|
push dx
|
||||||
|
push ax
|
||||||
call clust_to_first_sector
|
call clust_to_first_sector
|
||||||
push cx
|
; dx:ax = first sector of cluster
|
||||||
push bx
|
; cx = adjusted sectors per cluster
|
||||||
mov cx, [VAR(adj_sectors_per_cluster)]
|
|
||||||
next_root_sect:
|
next_root_sect:
|
||||||
push cx
|
push cx
|
||||||
mov cx, [VAR(entries_per_sector)]
|
mov cx, [VAR(entries_per_sector)]
|
||||||
@ -1572,8 +1666,8 @@ next_ent:
|
|||||||
pop di
|
pop di
|
||||||
pop cx
|
pop cx
|
||||||
loop next_root_sect
|
loop next_root_sect
|
||||||
pop bx
|
pop ax
|
||||||
pop cx
|
pop dx
|
||||||
call clust_next
|
call clust_next
|
||||||
jnc next_root_clust
|
jnc next_root_clust
|
||||||
file_not_found:
|
file_not_found:
|
||||||
@ -1587,22 +1681,22 @@ fsiboot_error:
|
|||||||
|
|
||||||
|
|
||||||
; INP: dx:ax = cluster - 2 (0-based cluster)
|
; INP: dx:ax = cluster - 2 (0-based cluster)
|
||||||
; OUT: cx:bx = input dx:ax
|
; OUT: dx:ax = first sector of that cluster
|
||||||
; dx:ax = first sector of that cluster
|
; cx = adjusted sectors per cluster
|
||||||
; CHG: -
|
; CHG: bx
|
||||||
clust_to_first_sector:
|
clust_to_first_sector:
|
||||||
push dx
|
mov cx, word [VAR(adj_sectors_per_cluster)]
|
||||||
push ax
|
|
||||||
push dx
|
push dx
|
||||||
mul word [VAR(adj_sectors_per_cluster)]
|
mul cx
|
||||||
xchg bx, ax
|
xchg bx, ax
|
||||||
xchg cx, dx
|
|
||||||
pop ax
|
pop ax
|
||||||
mul word [VAR(adj_sectors_per_cluster)]
|
push dx
|
||||||
|
mul cx
|
||||||
test dx, dx
|
test dx, dx
|
||||||
jnz fsiboot_error_badchain
|
jnz fsiboot_error_badchain
|
||||||
xchg dx, ax
|
xchg dx, ax
|
||||||
add dx, cx
|
pop ax
|
||||||
|
add dx, ax
|
||||||
jc ..@CY_fsiboot_error_badchain
|
jc ..@CY_fsiboot_error_badchain
|
||||||
xchg ax, bx
|
xchg ax, bx
|
||||||
|
|
||||||
@ -1611,8 +1705,6 @@ clust_to_first_sector:
|
|||||||
..@CY_fsiboot_error_badchain:
|
..@CY_fsiboot_error_badchain:
|
||||||
jc fsiboot_error_badchain
|
jc fsiboot_error_badchain
|
||||||
; dx:ax = first sector in cluster
|
; dx:ax = first sector in cluster
|
||||||
pop bx
|
|
||||||
pop cx ; cx:bx = cluster
|
|
||||||
retn
|
retn
|
||||||
|
|
||||||
|
|
||||||
@ -1638,16 +1730,14 @@ found_it:
|
|||||||
retn
|
retn
|
||||||
|
|
||||||
|
|
||||||
; INP: cx:bx = cluster (0-based)
|
; INP: dx:ax = cluster (0-based)
|
||||||
; si:di = loaded FAT sector, -1 if none
|
; si:di = loaded FAT sector, -1 if none
|
||||||
; OUT: CY if no next cluster
|
; OUT: CY if no next cluster
|
||||||
; NC if next cluster found,
|
; NC if next cluster found
|
||||||
; dx:ax = next cluster value (0-based)
|
; dx:ax = next cluster value (0-based)
|
||||||
; si:di = loaded FAT sector
|
; si:di = loaded FAT sector
|
||||||
; CHG: cx, bx, es
|
; CHG: cx, bx, es
|
||||||
clust_next:
|
clust_next:
|
||||||
xchg ax, bx ; ax = low word cluster, clobbers bx
|
|
||||||
mov dx, cx
|
|
||||||
add ax, 2
|
add ax, 2
|
||||||
adc dx, 0
|
adc dx, 0
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
\cfg{html-leaf-level}{0}
|
\cfg{html-leaf-level}{0}
|
||||||
\cfg{html-template-fragment}{%k}{%b}
|
\cfg{html-template-fragment}{%k}{%b}
|
||||||
\cfg{html-head-end}{<meta name="viewport" content="width=device-width, initial-scale=1.0">}
|
\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}
|
\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).
|
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
|
\S{protocol-sector-iniload-signatures} Signatures
|
||||||
|
|
||||||
At offset 1020 (3FCh) there is the signature \cq{lD}.
|
At offset 1020 (3FCh) there is the signature \cq{lD}.
|
||||||
@ -79,6 +101,10 @@ Currently the following signatures are defined:
|
|||||||
|
|
||||||
\dd lDDebug (debuggable lDebug)
|
\dd lDDebug (debuggable lDebug)
|
||||||
|
|
||||||
|
\dt \cq{lDbC}
|
||||||
|
|
||||||
|
\dd lCDebug (conditionally debuggable lDebug)
|
||||||
|
|
||||||
\dt \cq{lDTP}
|
\dt \cq{lDTP}
|
||||||
|
|
||||||
\dd lDOS test payload kernel (testpl.asm)
|
\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.
|
Under this protocol, the pointer \cq{ss:bp} is passed.
|
||||||
It points to a boot sector with (E)BPB.
|
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}.
|
The stack pointer must be at most \cq{bp - 10h}.
|
||||||
Below the pointed to location there live the Load Stack Variables.
|
Below the pointed to location there live the Load Stack Variables.
|
||||||
These follow this structure:
|
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.
|
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.
|
The stack pointer must be at most \cq{bp - 114h} then.
|
||||||
This follows the structure like this:
|
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 dosemu2's RxDOS.3 support sets \cq{sp = bp - 10h}
|
||||||
|
|
||||||
\b ldosboot boot.asm (FAT12/FAT16) loader
|
\b ldosboot boot.asm (FAT12/FAT16) loader
|
||||||
uses the variable for a \q{paragraphs per sector} value
|
makes sure not to pass the variable with the content "CL".
|
||||||
which is always a power of two and always below-or-equal 200h.
|
Refer to placeholder and DIRSEARCHSTACK_CL_FIRST uses in the source.
|
||||||
|
|
||||||
\b ldosboot boot32.asm (FAT32) loader
|
\b ldosboot boot32.asm (FAT32) loader
|
||||||
uses the variable for an \q{entries per sector} value
|
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}
|
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
|
\H{protocol-iniload-payload} Iniload to payload protocol
|
||||||
|
|
||||||
The payload is loaded to an arbitrary segment.
|
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 ldHasLBA: resb 1
|
||||||
\c ldClusterSize: resw 1
|
\c ldClusterSize: resw 1
|
||||||
\c ldParaPerSector:resw 1
|
\c ldParaPerSector:resw 1
|
||||||
\c ldLoadingSeg: resw 1
|
\c ldLoadingSeg:
|
||||||
|
\c ldQueryPatchValue:
|
||||||
|
\c resw 1
|
||||||
\c ldLoadUntilSeg: resw 1
|
\c ldLoadUntilSeg: resw 1
|
||||||
\c endstruc
|
\c endstruc
|
||||||
|
|
||||||
@ -293,6 +418,15 @@ May be given as zero for non-FAT filesystems.
|
|||||||
|
|
||||||
\dd Word. Internally used by iniload.
|
\dd Word. Internally used by iniload.
|
||||||
Available for re-use by payload.
|
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
|
\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,
|
the terminator of which is followed by a byte with the value 0FFh,
|
||||||
then no command line was passed to iniload.
|
then no command line was passed to iniload.
|
||||||
Currently lDebug can pass a command line to iniload when
|
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,
|
When iniload is loaded as a Multiboot1 or Multiboot2 specification kernel,
|
||||||
it is also assumed that a command line can be passed.
|
it is also assumed that a command line can be passed.
|
||||||
|
@ -78,6 +78,7 @@ ldHasLBA: resb 1
|
|||||||
ldClusterSize: resw 1
|
ldClusterSize: resw 1
|
||||||
ldParaPerSector:resw 1
|
ldParaPerSector:resw 1
|
||||||
ldLoadingSeg: ; word
|
ldLoadingSeg: ; word
|
||||||
|
ldQueryPatchValue: ; word
|
||||||
lsvCommandLine: ; word
|
lsvCommandLine: ; word
|
||||||
.start: equ $ - lsvclBufferLength
|
.start: equ $ - lsvclBufferLength
|
||||||
.signature: resw 1
|
.signature: resw 1
|
||||||
@ -124,6 +125,14 @@ ptLinux: equ 83h
|
|||||||
ptExtendedLinux: equ 85h
|
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
|
%ifndef _MAP
|
||||||
%elifempty _MAP
|
%elifempty _MAP
|
||||||
%else ; defined non-empty, str or non-str
|
%else ; defined non-empty, str or non-str
|
||||||
@ -132,6 +141,8 @@ ptExtendedLinux: equ 85h
|
|||||||
|
|
||||||
defaulting
|
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 QUERY_GEOMETRY, 1 ; query geometry via 13.08 (for CHS access)
|
||||||
numdef RPL, 1 ; support RPL and do not overwrite it
|
numdef RPL, 1 ; support RPL and do not overwrite it
|
||||||
numdef CHS, 1 ; support CHS (if it fits)
|
numdef CHS, 1 ; support CHS (if it fits)
|
||||||
@ -163,6 +174,7 @@ ptExtendedLinux: equ 85h
|
|||||||
%include "inicheck.mac"
|
%include "inicheck.mac"
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
|
numdef PADDING, 0
|
||||||
strdef PAYLOAD_FILE, "lDOSLOAD.BIN"
|
strdef PAYLOAD_FILE, "lDOSLOAD.BIN"
|
||||||
numdef EXEC_OFFSET, 0
|
numdef EXEC_OFFSET, 0
|
||||||
numdef EXEC_SEGMENT, 0
|
numdef EXEC_SEGMENT, 0
|
||||||
@ -328,8 +340,16 @@ ms6_entry:
|
|||||||
d3 call d3_display_two_characters
|
d3 call d3_display_two_characters
|
||||||
d3 test ax, "00"
|
d3 test ax, "00"
|
||||||
|
|
||||||
; test dx, dx
|
mov cx, cs
|
||||||
; jnz @FF
|
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
|
; Actual DOS will always put a zero word on top of
|
||||||
; the stack. But when the debugger loads us as
|
; the stack. But when the debugger loads us as
|
||||||
; a flat format binary it may set up another
|
; a flat format binary it may set up another
|
||||||
@ -339,15 +359,10 @@ d3 test ax, "00"
|
|||||||
call @F
|
call @F
|
||||||
@@:
|
@@:
|
||||||
pop cx
|
pop cx
|
||||||
cmp cx, @B + 100h
|
sub cx, @B ; cx == 0 iff entered at offset 0
|
||||||
je msdos1_com_entry
|
jne .freedos_or_msdos1_com_entry
|
||||||
@@:
|
@@:
|
||||||
|
; cx = 0
|
||||||
mov cx, cs
|
|
||||||
cmp cx, 60h
|
|
||||||
je freedos_entry
|
|
||||||
|
|
||||||
xor cx, cx
|
|
||||||
|
|
||||||
; Note: It has been observed that some IBMBIO.COM / IO.SYS
|
; Note: It has been observed that some IBMBIO.COM / IO.SYS
|
||||||
; boot sector loaders pass the int 1Eh address on the
|
; boot sector loaders pass the int 1Eh address on the
|
||||||
@ -380,29 +395,50 @@ error:
|
|||||||
int 16h
|
int 16h
|
||||||
int 19h
|
int 19h
|
||||||
|
|
||||||
disp_error:
|
|
||||||
.:
|
disp_error.loop:
|
||||||
lodsb
|
|
||||||
test al, al
|
|
||||||
jz .ret
|
|
||||||
mov ah, 0Eh
|
mov ah, 0Eh
|
||||||
mov bx, 7
|
mov bx, 7
|
||||||
; push bp
|
; push bp
|
||||||
; (call may change bp, but it is not used here any longer.)
|
; (call may change bp, but it is not used here any longer.)
|
||||||
int 10h
|
int 10h
|
||||||
; pop bp
|
; pop bp
|
||||||
jmp short .
|
disp_error:
|
||||||
|
lodsb
|
||||||
msg:
|
test al, al
|
||||||
.error: db "Load error: ", 0
|
jnz .loop
|
||||||
|
retn
|
||||||
|
|
||||||
|
|
||||||
query_geometry:
|
query_geometry:
|
||||||
%if _QUERY_GEOMETRY ; +30 bytes
|
%if _QUERY_GEOMETRY || !_LBA_SKIP_CHECK
|
||||||
|
; magic bytes start
|
||||||
mov dl, [bp + bsBPB + ebpbNew + bpbnBootUnit]
|
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
|
%if !_LBA_SKIP_CHECK
|
||||||
push dx
|
push dx
|
||||||
|
%if _QUERY_PATCH
|
||||||
|
push ax
|
||||||
|
%endif
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
|
%if _QUERY_PATCH
|
||||||
|
test al, 4 ; don't query geometry ?
|
||||||
|
jnz @F ; yes -->
|
||||||
|
%endif
|
||||||
|
|
||||||
; test dl, dl ; floppy?
|
; test dl, dl ; floppy?
|
||||||
; jns @F ; don't attempt query, might fail -->
|
; jns @F ; don't attempt query, might fail -->
|
||||||
; Note that while the original PC BIOS doesn't support this function
|
; Note that while the original PC BIOS doesn't support this function
|
||||||
@ -423,30 +459,38 @@ query_geometry:
|
|||||||
%endif
|
%endif
|
||||||
|
|
||||||
%if !_LBA_SKIP_CHECK
|
%if !_LBA_SKIP_CHECK
|
||||||
mov ah, 41h
|
|
||||||
%if _QUERY_GEOMETRY
|
%if _QUERY_GEOMETRY
|
||||||
pop dx
|
%if _QUERY_PATCH
|
||||||
%else
|
pop ax ; restore query patch flags in al
|
||||||
mov dl, [bp + bsBPB + ebpbNew + bpbnBootUnit]
|
%endif
|
||||||
|
pop dx ; restore unit number in dl
|
||||||
%endif
|
%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
|
mov bx, 55AAh
|
||||||
stc
|
stc
|
||||||
int 13h ; 13.41.bx=55AA extensions installation check
|
int 13h ; 13.41.bx=55AA extensions installation check
|
||||||
|
@@:
|
||||||
mov al, 0 ; zero in case of no LBA support
|
mov al, 0 ; zero in case of no LBA support
|
||||||
jc .no_lba
|
jc .no_lba
|
||||||
cmp bx, 0AA55h
|
cmp bx, 0AA55h
|
||||||
jne .no_lba
|
jne .no_lba
|
||||||
test cl, 1 ; support bitmap bit 0
|
shr cl, 1 ; support bitmap bit 0
|
||||||
jz .no_lba
|
jnc .no_lba
|
||||||
inc ax ; al = 1 to indicate LBA support
|
inc ax ; al = 1 to indicate LBA support
|
||||||
.no_lba:
|
.no_lba:
|
||||||
|
.done_lba:
|
||||||
mov byte [bp + ldHasLBA], al
|
mov byte [bp + ldHasLBA], al
|
||||||
%else
|
%else
|
||||||
mov byte [bp + ldHasLBA], 0
|
mov byte [bp + ldHasLBA], 0
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
%if 1 || _QUERY_GEOMETRY || !_LBA_SKIP_CHECK
|
%if 1 || _QUERY_GEOMETRY || !_LBA_SKIP_CHECK
|
||||||
disp_error.ret:
|
|
||||||
retn
|
retn
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
@ -474,7 +518,7 @@ read_sector:
|
|||||||
push ax
|
push ax
|
||||||
push si
|
push si
|
||||||
|
|
||||||
push bx
|
mov es, bx
|
||||||
|
|
||||||
; DX:AX==LBA sector number
|
; DX:AX==LBA sector number
|
||||||
; add partition start (= number of hidden sectors)
|
; add partition start (= number of hidden sectors)
|
||||||
@ -530,9 +574,9 @@ read_sector:
|
|||||||
jne .lba_error
|
jne .lba_error
|
||||||
|
|
||||||
; push word [si + 4 + 0]
|
; push word [si + 4 + 0]
|
||||||
push word [si + 4 + 2] ; user buffer
|
push es ; => user buffer
|
||||||
push word [bp + ldSectorSeg]
|
mov es, word [bp + ldSectorSeg]
|
||||||
pop word [si + 4 + 2]
|
mov word [si + 4 + 2], es
|
||||||
; and word [si + 4 + 0], byte 0
|
; and word [si + 4 + 0], byte 0
|
||||||
|
|
||||||
mov ah, 42h
|
mov ah, 42h
|
||||||
@ -550,12 +594,12 @@ read_sector:
|
|||||||
|
|
||||||
pop es
|
pop es
|
||||||
; pop cx
|
; pop cx
|
||||||
call .sectorseg_helper
|
add sp, 10h
|
||||||
|
jmp .sectorseg_helper_then_done
|
||||||
|
|
||||||
.lba_done:
|
.lba_done:
|
||||||
add sp, 10h
|
add sp, 10h
|
||||||
pop bx
|
jmp short .done
|
||||||
jmp short .chs_done
|
|
||||||
|
|
||||||
.lba_error: equ .err
|
.lba_error: equ .err
|
||||||
|
|
||||||
@ -640,7 +684,6 @@ read_sector:
|
|||||||
|
|
||||||
; we call INT 13h AH=02h once for each sector. Multi-sector reads
|
; we call INT 13h AH=02h once for each sector. Multi-sector reads
|
||||||
; may fail if we cross a track or 64K boundary
|
; may fail if we cross a track or 64K boundary
|
||||||
pop es
|
|
||||||
|
|
||||||
mov ax, 0201h ; read one sector
|
mov ax, 0201h ; read one sector
|
||||||
%if _CHS_RETRY
|
%if _CHS_RETRY
|
||||||
@ -664,24 +707,42 @@ read_sector:
|
|||||||
int 13h
|
int 13h
|
||||||
%endif
|
%endif
|
||||||
.err_CY_1:
|
.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
|
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:
|
.done:
|
||||||
; increment segment
|
; increment segment
|
||||||
mov bx, es
|
mov bx, es
|
||||||
%endif
|
|
||||||
|
|
||||||
.chs_done:
|
|
||||||
mov es, bx
|
|
||||||
add bx, word [bp + ldParaPerSector]
|
add bx, word [bp + ldParaPerSector]
|
||||||
|
|
||||||
pop si
|
pop si
|
||||||
pop ax
|
pop ax
|
||||||
pop cx
|
pop cx
|
||||||
pop dx
|
pop dx
|
||||||
|
.increment_sector_number:
|
||||||
; increment LBA sector number
|
; increment LBA sector number
|
||||||
inc ax
|
inc ax
|
||||||
jne @F
|
jne @F
|
||||||
@ -703,21 +764,21 @@ read_sector:
|
|||||||
; reset drive
|
; reset drive
|
||||||
xor ax, ax
|
xor ax, ax
|
||||||
int 13h
|
int 13h
|
||||||
jc @F ; CY, reset failed, error in ah -->
|
jnc @FF ; NC, reset succeeded -->
|
||||||
|
; 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
|
|
||||||
|
|
||||||
@@: ; NC or CY, stack has function number
|
@@: ; NC or CY, stack has function number
|
||||||
inc sp
|
inc sp
|
||||||
inc sp ; discard word on stack, preserve CF
|
inc sp ; discard word on stack, preserve CF
|
||||||
retn
|
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
|
%endif
|
||||||
|
|
||||||
%if _LBA
|
%if _LBA
|
||||||
@ -736,24 +797,6 @@ read_sector:
|
|||||||
retn
|
retn
|
||||||
%endif
|
%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:
|
error_shortfile:
|
||||||
call error
|
call error
|
||||||
@ -795,28 +838,25 @@ ms7_entry:
|
|||||||
; load unit field set, hidden sectors set
|
; load unit field set, hidden sectors set
|
||||||
inc dx
|
inc dx
|
||||||
dec dx ; "BJ" signature (apparently not about FAT32 support)
|
dec dx ; "BJ" signature (apparently not about FAT32 support)
|
||||||
cli
|
|
||||||
cld
|
|
||||||
|
|
||||||
jmp .continue ; jump to handler above 600h (sector loads 800h bytes)
|
jmp .continue ; jump to handler above 600h (sector loads 800h bytes)
|
||||||
|
|
||||||
.ms6_common:
|
.ms6_common: ; cx = 0
|
||||||
mov ax, cs
|
mov ax, 70h + ((3 * 512) >> 4) ; MS6 entry has 3 sectors loaded
|
||||||
add ax, (3 * 512) >> 4
|
; (and is always segment 70h)
|
||||||
|
|
||||||
.continue2_set_extra_and_empty_cmdline:
|
.continue2_set_extra_and_empty_cmdline: ; cx = 0, ax => behind loaded
|
||||||
%if _LSVEXTRA
|
%if _LSVEXTRA
|
||||||
and word [bp + lsvExtra], 0
|
mov word [bp + lsvExtra], cx
|
||||||
%endif
|
%endif
|
||||||
and word [bp + lsvCommandLine], 0
|
mov word [bp + lsvCommandLine], cx
|
||||||
.continue2:
|
.continue2: ; cx = 0, ax => behind loaded
|
||||||
mov word [bp + lsvLoadSeg], ax
|
mov word [bp + lsvLoadSeg], ax
|
||||||
|
|
||||||
xor ax, ax
|
mov word [bp + lsvFATSeg], cx ; initialise to zero (for FAT12)
|
||||||
mov word [bp + lsvFATSeg], ax ; initialise to zero (for FAT12)
|
dec cx
|
||||||
dec ax
|
mov word [bp + lsvFATSector + 0], cx
|
||||||
mov word [bp + lsvFATSector + 0], ax
|
mov word [bp + lsvFATSector + 2], cx ; initialise to -1
|
||||||
mov word [bp + lsvFATSector + 2], ax ; initialise to -1
|
|
||||||
|
|
||||||
; Actually it seems that the MS-DOS 7 loaders load 4 sectors
|
; Actually it seems that the MS-DOS 7 loaders load 4 sectors
|
||||||
; instead of only three (as the MS-DOS 6 loaders do).
|
; instead of only three (as the MS-DOS 6 loaders do).
|
||||||
@ -824,21 +864,30 @@ ms7_entry:
|
|||||||
|
|
||||||
jmp ldos_entry.ms7_common
|
jmp ldos_entry.ms7_common
|
||||||
|
|
||||||
|
msg:
|
||||||
|
.error: db "Load error: ", 0
|
||||||
|
|
||||||
|
|
||||||
finish_continue:
|
finish_continue:
|
||||||
|
mov bx, cs
|
||||||
add ax, bx ; = cs + rounded up length
|
add ax, bx ; = cs + rounded up length
|
||||||
sub ax, word [bp + ldLoadTop] ; = paras to move down
|
sub ax, word [bp + ldLoadTop] ; = paras to move down
|
||||||
jbe short finish_load
|
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
|
neg ax
|
||||||
add ax, bx ; ax = cs - paras to move down
|
add ax, bx ; ax = cs - paras to move down
|
||||||
|
; want to relocate cs to this
|
||||||
jnc short error_outofmemory_j1
|
jnc short error_outofmemory_j1
|
||||||
mov di, relocate_to
|
mov di, relocate_to
|
||||||
push ax
|
push ax
|
||||||
push di ; dword on stack: relocate_to
|
push di ; dword on stack: relocate_to
|
||||||
cmp ax, 60h + 1
|
cmp ax, 60h + 1
|
||||||
jb short error_outofmemory_j1
|
jb short error_outofmemory_j1
|
||||||
|
push ax ; word on stack => where to relocate to
|
||||||
dec ax ; one less to allow relocator
|
dec ax ; one less to allow relocator
|
||||||
mov es, ax
|
mov es, ax
|
||||||
|
|
||||||
@ -850,17 +899,18 @@ finish_relocation:
|
|||||||
push di ; dword on stack: relocator destination
|
push di ; dword on stack: relocator destination
|
||||||
|
|
||||||
mov ds, bx ; ds => unrelocated cs
|
mov ds, bx ; ds => unrelocated cs
|
||||||
inc ax ; ax => where to relocate to
|
|
||||||
mov si, relocator ; ds:si -> relocator
|
mov si, relocator ; ds:si -> relocator
|
||||||
relocator_size equ relocator.end - relocator
|
relocator_size equ relocator.end - relocator
|
||||||
%rep (relocator_size + 1) / 2
|
%rep (relocator_size + 1) / 2
|
||||||
movsw ; place relocator
|
movsw ; place relocator
|
||||||
%endrep
|
%endrep
|
||||||
mov es, ax
|
%if relocator_size > 16
|
||||||
xor di, di ; -> where to relocate to
|
%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
|
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
|
sub cx, bx ; length of currently loaded fragment
|
||||||
mov bx, 1000h
|
mov bx, 1000h
|
||||||
mov ax, cx
|
mov ax, cx
|
||||||
@ -907,8 +957,6 @@ relocate_to:
|
|||||||
test ax, ax ; another round needed?
|
test ax, ax ; another round needed?
|
||||||
jnz @BB ; yes -->
|
jnz @BB ; yes -->
|
||||||
|
|
||||||
pop ax
|
|
||||||
sub word [bp + lsvLoadSeg], ax
|
|
||||||
push ss
|
push ss
|
||||||
pop ds
|
pop ds
|
||||||
|
|
||||||
@ -926,7 +974,6 @@ finish_load:
|
|||||||
; ldLoadUntilSeg => after last to-be-loaded paragraph
|
; ldLoadUntilSeg => after last to-be-loaded paragraph
|
||||||
|
|
||||||
mov bx, word [bp + lsvLoadSeg]
|
mov bx, word [bp + lsvLoadSeg]
|
||||||
mov word [bp + ldLoadingSeg], bx
|
|
||||||
cmp bx, ax
|
cmp bx, ax
|
||||||
jae short loaded_all_if_ae ; (for FreeDOS entrypoint) already loaded -->
|
jae short loaded_all_if_ae ; (for FreeDOS entrypoint) already loaded -->
|
||||||
|
|
||||||
@ -940,32 +987,26 @@ finish_load:
|
|||||||
jc short error_badchain_j
|
jc short error_badchain_j
|
||||||
|
|
||||||
skip_next_clust:
|
skip_next_clust:
|
||||||
|
push dx
|
||||||
|
push ax
|
||||||
call clust_to_first_sector
|
call clust_to_first_sector
|
||||||
push cx
|
|
||||||
push bx
|
|
||||||
mov cx, [bp + ldClusterSize]
|
|
||||||
skip_next_sect:
|
skip_next_sect:
|
||||||
push cx
|
|
||||||
|
|
||||||
mov bx, [bp + ldLoadingSeg]
|
mov bx, [bp + ldLoadingSeg]
|
||||||
cmp bx, [bp + ldLoadUntilSeg]
|
cmp bx, [bp + ldLoadUntilSeg]
|
||||||
jae loaded_all.3stack
|
jae loaded_all.2stack
|
||||||
|
|
||||||
mov cx, bx
|
add bx, [bp + ldParaPerSector]
|
||||||
add cx, [bp + ldParaPerSector]
|
; bx += paras per sector
|
||||||
cmp cx, [bp + lsvLoadSeg]
|
cmp bx, [bp + lsvLoadSeg]
|
||||||
ja skipped_all
|
ja skipped_all
|
||||||
inc ax ; emulate read_sector:
|
; emulate read_sector:
|
||||||
jnz @F
|
call read_sector.increment_sector_number
|
||||||
inc dx ; dx:ax += 1
|
; dx:ax += 1
|
||||||
@@:
|
|
||||||
mov bx, cx ; bx += paras per sector
|
|
||||||
mov [bp + ldLoadingSeg], bx
|
mov [bp + ldLoadingSeg], bx
|
||||||
|
|
||||||
pop cx
|
|
||||||
loop skip_next_sect
|
loop skip_next_sect
|
||||||
pop bx
|
pop ax
|
||||||
pop cx
|
pop dx
|
||||||
call clust_next
|
call clust_next
|
||||||
jnc skip_next_clust
|
jnc skip_next_clust
|
||||||
end_of_chain:
|
end_of_chain:
|
||||||
@ -982,6 +1023,8 @@ loaded_all_if_ae:
|
|||||||
|
|
||||||
|
|
||||||
skipped_all:
|
skipped_all:
|
||||||
|
sub bx, [bp + ldParaPerSector]
|
||||||
|
; restore bx => next sector to read
|
||||||
call read_sector
|
call read_sector
|
||||||
; we can depend on the fact that at least
|
; we can depend on the fact that at least
|
||||||
; up to end was already loaded, so this
|
; up to end was already loaded, so this
|
||||||
@ -997,31 +1040,32 @@ error_badchain_j:
|
|||||||
|
|
||||||
|
|
||||||
; ds => first chunk of to be relocated data
|
; 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
|
; cx = number of words in first chunk
|
||||||
relocator:
|
relocator:
|
||||||
|
pop es ; => where to relocate to
|
||||||
rep movsw
|
rep movsw
|
||||||
retf ; jump to relocated relocate_to
|
retf ; jump to relocated relocate_to
|
||||||
.end:
|
.end:
|
||||||
|
|
||||||
|
|
||||||
; INP: dx:ax = cluster - 2 (0-based cluster)
|
; INP: dx:ax = cluster - 2 (0-based cluster)
|
||||||
; OUT: cx:bx = input dx:ax
|
; OUT: dx:ax = first sector of that cluster
|
||||||
; dx:ax = first sector of that cluster
|
; cx = adjusted sectors per cluster
|
||||||
; CHG: -
|
; CHG: bx
|
||||||
clust_to_first_sector:
|
clust_to_first_sector:
|
||||||
push dx
|
mov cx, word [bp + ldClusterSize]
|
||||||
push ax
|
|
||||||
push dx
|
push dx
|
||||||
mul word [bp + ldClusterSize]
|
mul cx
|
||||||
xchg bx, ax
|
xchg bx, ax
|
||||||
xchg cx, dx
|
|
||||||
pop ax
|
pop ax
|
||||||
mul word [bp + ldClusterSize]
|
push dx
|
||||||
|
mul cx
|
||||||
test dx, dx
|
test dx, dx
|
||||||
jnz short error_badchain_j
|
jnz short error_badchain_j
|
||||||
xchg dx, ax
|
xchg dx, ax
|
||||||
add dx, cx
|
pop ax
|
||||||
|
add dx, ax
|
||||||
.cy_error_badchain:
|
.cy_error_badchain:
|
||||||
jc short error_badchain_j
|
jc short error_badchain_j
|
||||||
xchg ax, bx
|
xchg ax, bx
|
||||||
@ -1030,21 +1074,17 @@ clust_to_first_sector:
|
|||||||
adc dx, [bp + lsvDataStart + 2]
|
adc dx, [bp + lsvDataStart + 2]
|
||||||
jc short .cy_error_badchain
|
jc short .cy_error_badchain
|
||||||
; dx:ax = first sector in cluster
|
; dx:ax = first sector in cluster
|
||||||
pop bx
|
|
||||||
pop cx ; cx:bx = cluster
|
|
||||||
retn
|
retn
|
||||||
|
|
||||||
|
|
||||||
; INP: cx:bx = cluster (0-based)
|
; INP: dx:ax = cluster (0-based)
|
||||||
; si:di = loaded FAT sector, -1 if none
|
; si:di = loaded FAT sector, -1 if none
|
||||||
; OUT: CY if no next cluster
|
; OUT: CY if no next cluster
|
||||||
; NC if next cluster found,
|
; NC if next cluster found
|
||||||
; dx:ax = next cluster value (0-based)
|
; dx:ax = next cluster value (0-based)
|
||||||
; si:di = loaded FAT sector
|
; si:di = loaded FAT sector
|
||||||
; CHG: cx, bx
|
; CHG: cx, bx
|
||||||
clust_next:
|
clust_next:
|
||||||
mov ax, bx
|
|
||||||
mov dx, cx
|
|
||||||
add ax, 2
|
add ax, 2
|
||||||
adc dx, 0
|
adc dx, 0
|
||||||
|
|
||||||
@ -1153,25 +1193,25 @@ check_clust:
|
|||||||
|
|
||||||
|
|
||||||
ms6_continue1:
|
ms6_continue1:
|
||||||
mov es, cx
|
mov es, cx ; cx = 0
|
||||||
mov bp, 7C00h
|
mov bp, 7C00h ; 0:bp -> boot sector with BPB
|
||||||
|
|
||||||
mov word [es:di], si
|
mov word [es:di], si
|
||||||
mov word [es:di + 2], ds ; restore old int 1Eh address
|
mov word [es:di + 2], ds ; restore old int 1Eh address
|
||||||
|
|
||||||
mov ss, cx
|
mov ss, cx ; = 0
|
||||||
mov sp, 7C00h + lsvCommandLine
|
mov sp, 7C00h + lsvCommandLine
|
||||||
|
|
||||||
mov dx, word [es:500h + 26]
|
push word [es:500h + 20]
|
||||||
mov cx, word [es:500h + 20]
|
push word [es:500h + 26]
|
||||||
mov word [bp + lsvFirstCluster + 0], dx
|
pop word [bp + lsvFirstCluster + 0]
|
||||||
mov word [bp + lsvFirstCluster + 2], cx
|
pop word [bp + lsvFirstCluster + 2]
|
||||||
|
|
||||||
sub bx, word [bp + bsBPB + bpbHiddenSectors + 0]
|
sub bx, word [bp + bsBPB + bpbHiddenSectors + 0]
|
||||||
sbb ax, word [bp + bsBPB + bpbHiddenSectors + 2]
|
sbb ax, word [bp + bsBPB + bpbHiddenSectors + 2]
|
||||||
mov word [bp + lsvDataStart + 0], bx
|
mov word [bp + lsvDataStart + 0], bx
|
||||||
mov word [bp + lsvDataStart + 2], ax
|
mov word [bp + lsvDataStart + 2], ax
|
||||||
jmp ms7_entry.ms6_common
|
jmp ms7_entry.ms6_common ; passing cx = 0
|
||||||
|
|
||||||
|
|
||||||
%assign num 1020-($-$$)
|
%assign num 1020-($-$$)
|
||||||
@ -1193,7 +1233,8 @@ ldos_entry:
|
|||||||
cli
|
cli
|
||||||
cld
|
cld
|
||||||
|
|
||||||
; cs:ip = 70h:400h
|
; ip = 400h
|
||||||
|
; cs = arbitrary; typically 60h, 70h, or 200h
|
||||||
; dwo [ss:bp - 4] = first data sector (without hidden sectors)
|
; dwo [ss:bp - 4] = first data sector (without hidden sectors)
|
||||||
; wo [ss:bp - 6] = load_seg, => after last loaded data
|
; wo [ss:bp - 6] = load_seg, => after last loaded data
|
||||||
; wo [ss:bp - 8] = fat_seg, 0 if invalid
|
; wo [ss:bp - 8] = fat_seg, 0 if invalid
|
||||||
@ -1214,6 +1255,7 @@ ldos_entry:
|
|||||||
;
|
;
|
||||||
; Extension 2:
|
; Extension 2:
|
||||||
; word [ss:bp - 20] = signature "CL" if valid
|
; word [ss:bp - 20] = signature "CL" if valid
|
||||||
|
; bp >= 20 + 256 if valid
|
||||||
; 256bytes [ss:bp - 20 - 256] = ASCIZ command line string
|
; 256bytes [ss:bp - 20 - 256] = ASCIZ command line string
|
||||||
|
|
||||||
xor ax, ax
|
xor ax, ax
|
||||||
@ -1277,9 +1319,9 @@ init_memory:
|
|||||||
dec cx ; => last paragraph of higher buffer (16-byte trailer)
|
dec cx ; => last paragraph of higher buffer (16-byte trailer)
|
||||||
mov dx, ax ; => first paragraph of higher buffer
|
mov dx, ax ; => first paragraph of higher buffer
|
||||||
mov bx, cx
|
mov bx, cx
|
||||||
and dx, 0F000h ; 64 KiB chunk of first paragraph of higher buffer
|
and dh, 0F0h ; 64 KiB chunk of first paragraph of higher buffer
|
||||||
and bx, 0F000h ; 64 KiB chunk of last paragraph of higher buffer
|
and bh, 0F0h ; 64 KiB chunk of last paragraph of higher buffer
|
||||||
cmp bx, dx ; in same chunk?
|
cmp bh, dh ; in same chunk?
|
||||||
mov bx, ax
|
mov bx, ax
|
||||||
je .gotsectorseg ; yes, use higher buffer as sector buffer ->
|
je .gotsectorseg ; yes, use higher buffer as sector buffer ->
|
||||||
; bx = use higher buffer as FAT buffer
|
; bx = use higher buffer as FAT buffer
|
||||||
@ -1341,33 +1383,42 @@ init_memory:
|
|||||||
inc cx ; => stack + BPB buffer
|
inc cx ; => stack + BPB buffer
|
||||||
push ss
|
push ss
|
||||||
pop ds
|
pop ds
|
||||||
lea si, [bp + lsvCommandLine.start]
|
|
||||||
mov es, cx
|
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
|
mov di, _STACKSIZE - LOADCMDLINE + ldCommandLine.start
|
||||||
; -> cmd line target
|
; -> cmd line target
|
||||||
push cx ; top of memory below buffers
|
mov cl, (LOADCMDLINE_size + 1) >> 1
|
||||||
mov cx, (LOADCMDLINE_size + 1) >> 1
|
|
||||||
rep movsw ; copy cmd line
|
rep movsw ; copy cmd line
|
||||||
%if lsvCommandLine.start + fromwords(words(LOADCMDLINE_size)) != lsvCommandLine.signature
|
%if lsvCommandLine.start + fromwords(words(LOADCMDLINE_size)) != lsvCommandLine.signature
|
||||||
%error Unexpected structure layout
|
%error Unexpected structure layout
|
||||||
%endif
|
%endif
|
||||||
cmp word [si], lsvclSignature
|
lodsw
|
||||||
|
cmp ax, lsvclSignature
|
||||||
je @F ; if command line given -->
|
je @F ; if command line given -->
|
||||||
|
.no_cmdline:
|
||||||
mov byte [es: _STACKSIZE - LOADCMDLINE + ldCommandLine.start ], cl
|
mov byte [es: _STACKSIZE - LOADCMDLINE + ldCommandLine.start ], cl
|
||||||
; truncate as if empty line given
|
; truncate as if empty line given
|
||||||
dec cx ; cl = 0FFh
|
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
|
; remember whether command line given
|
||||||
; = 0 if given (also truncates if too long)
|
; = 0 if given (also truncates if too long)
|
||||||
; = 0FFh if not given
|
; = 0FFh if not given
|
||||||
|
|
||||||
push ax
|
; si happens to be already correct here if we didn't
|
||||||
%if lsvCommandLine.signature + 2 != lsvExtra
|
; branch to .no_cmdline, however make sure to set
|
||||||
%error Unexpected structure layout
|
; it here to support this case.
|
||||||
%endif
|
lea si, [bp + lsvExtra]
|
||||||
lodsw
|
|
||||||
; lea si, [bp + lsvExtra]
|
|
||||||
; ds:si -> lsv + BPB
|
; ds:si -> lsv + BPB
|
||||||
mov di, _STACKSIZE - LOADCMDLINE + lsvExtra
|
mov di, _STACKSIZE - LOADCMDLINE + lsvExtra
|
||||||
; es:di -> where to place lsv
|
; es:di -> where to place lsv
|
||||||
@ -1413,7 +1464,8 @@ init_memory:
|
|||||||
test bx, bx
|
test bx, bx
|
||||||
jz .is_fat32
|
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
|
lea di, [si + (ebpbNew - bpbNew)] ; -> last dest word
|
||||||
mov cx, (512 - bsBPB - bpbNew + 1) >> 1
|
mov cx, (512 - bsBPB - bpbNew + 1) >> 1
|
||||||
; move sector up, except common BPB start part
|
; move sector up, except common BPB start part
|
||||||
@ -1457,9 +1509,9 @@ init_memory:
|
|||||||
|
|
||||||
; adjusted sectors per cluster (store in a word,
|
; adjusted sectors per cluster (store in a word,
|
||||||
; and decode EDR-DOS's special value 0 meaning 256)
|
; and decode EDR-DOS's special value 0 meaning 256)
|
||||||
xor ax, ax
|
|
||||||
mov al, [bp + bsBPB + bpbSectorsPerCluster]
|
mov al, [bp + bsBPB + bpbSectorsPerCluster]
|
||||||
dec al
|
dec ax
|
||||||
|
mov ah, 0
|
||||||
inc ax
|
inc ax
|
||||||
mov [bp + ldClusterSize], ax
|
mov [bp + ldClusterSize], ax
|
||||||
|
|
||||||
@ -1512,7 +1564,7 @@ init_memory:
|
|||||||
@@:
|
@@:
|
||||||
cmp ax, 0FFF7h - 2
|
cmp ax, 0FFF7h - 2
|
||||||
ja .badclusters
|
ja .badclusters
|
||||||
mov byte [bp + ldFATType], 16
|
shr byte [bp + ldFATType], 1 ; = 16
|
||||||
cmp ax, 0FF7h - 2
|
cmp ax, 0FF7h - 2
|
||||||
ja .got_fat_type
|
ja .got_fat_type
|
||||||
|
|
||||||
@ -1569,42 +1621,30 @@ init_memory:
|
|||||||
and ax, bx ; rounded up,
|
and ax, bx ; rounded up,
|
||||||
; ((payload.actual_end -$$+0 +15) >> 4 + pps - 1) & ~ (pps - 1)
|
; ((payload.actual_end -$$+0 +15) >> 4 + pps - 1) & ~ (pps - 1)
|
||||||
|
|
||||||
mov bx, cs
|
|
||||||
jmp finish_continue
|
jmp finish_continue
|
||||||
|
|
||||||
|
|
||||||
%assign num 1024+512-4-($-$$)
|
%assign num 1024+512-($-$$)
|
||||||
%warning num bytes in front of end
|
%warning num bytes in front of end
|
||||||
_fill 1024+512-4,38,start
|
_fill 1024+512,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
|
|
||||||
end:
|
end:
|
||||||
|
|
||||||
load_next_clust_continue:
|
|
||||||
push bx
|
load_next_clust:
|
||||||
mov cx, [bp + ldClusterSize]
|
push dx
|
||||||
|
push ax
|
||||||
|
call clust_to_first_sector
|
||||||
load_next_sect:
|
load_next_sect:
|
||||||
push cx
|
|
||||||
mov bx, [bp + ldLoadingSeg]
|
mov bx, [bp + ldLoadingSeg]
|
||||||
cmp bx, [bp + ldLoadUntilSeg]
|
cmp bx, [bp + ldLoadUntilSeg]
|
||||||
jae loaded_all.3stack_j
|
jae loaded_all.2stack_j
|
||||||
|
|
||||||
call read_sector
|
call read_sector
|
||||||
skipped_all_continue:
|
skipped_all_continue:
|
||||||
mov [bp + ldLoadingSeg], bx
|
mov [bp + ldLoadingSeg], bx
|
||||||
pop cx
|
|
||||||
loop load_next_sect
|
loop load_next_sect
|
||||||
pop bx
|
pop ax
|
||||||
pop cx
|
pop dx
|
||||||
call clust_next
|
call clust_next
|
||||||
jnc load_next_clust
|
jnc load_next_clust
|
||||||
jmp end_of_chain
|
jmp end_of_chain
|
||||||
@ -1616,11 +1656,13 @@ skipped_all_continue:
|
|||||||
; if we jump to here, then the whole file has
|
; if we jump to here, then the whole file has
|
||||||
; been loaded, so this jump doesn't have to
|
; been loaded, so this jump doesn't have to
|
||||||
; stay in the 32 bytes after the end label.
|
; stay in the 32 bytes after the end label.
|
||||||
loaded_all.3stack_j:
|
loaded_all.2stack_j:
|
||||||
jmp loaded_all.3stack
|
jmp loaded_all.2stack
|
||||||
|
|
||||||
|
|
||||||
ms7_entry.continue:
|
ms7_entry.continue:
|
||||||
|
cli
|
||||||
|
cld
|
||||||
pop bx
|
pop bx
|
||||||
pop es
|
pop es
|
||||||
pop word [es:bx]
|
pop word [es:bx]
|
||||||
@ -1640,8 +1682,8 @@ ms7_entry.continue:
|
|||||||
sbb word [bp + lsvDataStart + 2], dx
|
sbb word [bp + lsvDataStart + 2], dx
|
||||||
|
|
||||||
mov ax, cs
|
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
|
jmp ms7_entry.continue2_set_extra_and_empty_cmdline
|
||||||
|
|
||||||
|
|
||||||
@ -1656,8 +1698,7 @@ end2:
|
|||||||
; This handling is in the second header part,
|
; This handling is in the second header part,
|
||||||
; behind the needed part to finish loading.
|
; behind the needed part to finish loading.
|
||||||
; It is only used when the file is completely loaded.
|
; It is only used when the file is completely loaded.
|
||||||
loaded_all.3stack:
|
loaded_all.2stack:
|
||||||
pop ax
|
|
||||||
pop ax
|
pop ax
|
||||||
pop ax
|
pop ax
|
||||||
loaded_all:
|
loaded_all:
|
||||||
@ -1723,6 +1764,13 @@ loaded_all:
|
|||||||
; al = 0 else
|
; al = 0 else
|
||||||
rep stosb ; clear remainder of buffer
|
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
|
mov ax, cs
|
||||||
add ax, ((payload -$$+0) >> 4) + _EXEC_SEGMENT
|
add ax, ((payload -$$+0) >> 4) + _EXEC_SEGMENT
|
||||||
push ax
|
push ax
|
||||||
@ -1754,6 +1802,13 @@ error_data_checksum_failed:
|
|||||||
%endif
|
%endif
|
||||||
|
|
||||||
|
|
||||||
|
freedos_or_msdos1_com_entry:
|
||||||
|
call @F
|
||||||
|
@@:
|
||||||
|
pop cx
|
||||||
|
cmp cx, @B
|
||||||
|
jne msdos1_com_entry
|
||||||
|
|
||||||
freedos_entry:
|
freedos_entry:
|
||||||
; This is the FreeDOS compatible entry point.
|
; This is the FreeDOS compatible entry point.
|
||||||
; Supports FAT32 too.
|
; Supports FAT32 too.
|
||||||
@ -1815,7 +1870,8 @@ d3 test ax, "F0"
|
|||||||
.multiboot_entry:
|
.multiboot_entry:
|
||||||
mov ax, cs
|
mov ax, cs
|
||||||
add ax, (payload.actual_end -$$+0 +15) >> 4
|
add ax, (payload.actual_end -$$+0 +15) >> 4
|
||||||
|
; Multiboot1/2 and FreeDOS have whole image
|
||||||
|
xor cx, cx ; cx = 0
|
||||||
jmp ms7_entry.continue2
|
jmp ms7_entry.continue2
|
||||||
|
|
||||||
|
|
||||||
@ -2475,3 +2531,14 @@ second_payload:
|
|||||||
.end:
|
.end:
|
||||||
%endif
|
%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 (payload -$$+0) >> 4 ; exeHeaderSize
|
||||||
dw 0 ; exeMinAlloc
|
dw 0 ; exeMinAlloc
|
||||||
dw -1 ; exeMaxAlloc
|
dw -1 ; exeMaxAlloc
|
||||||
dw 0 ; exeInitSS
|
dw (payload.end + 15 - payload) / 16 ; exeInitSS
|
||||||
dw -2 ; exeInitSP
|
dw 512 ; exeInitSP
|
||||||
dw 0 ; exeChecksum
|
dw 0 ; exeChecksum
|
||||||
dw 0, 0 ; exeInitCSIP
|
dw 0, 0 ; exeInitCSIP
|
||||||
dw 0 ; exeRelocTable
|
dw 0 ; exeRelocTable
|
||||||
endarea header
|
endarea header
|
||||||
|
|
||||||
|
|
||||||
align 16, db 38
|
align 16, db 0
|
||||||
payload:
|
payload:
|
||||||
jmp strict short entry
|
jmp strict short entry
|
||||||
db "CONFIG"
|
db "CONFIG"
|
||||||
@ -50,7 +50,7 @@ payload:
|
|||||||
entry: equ $
|
entry: equ $
|
||||||
jmp entry_common
|
jmp entry_common
|
||||||
|
|
||||||
times 0xC0 - ($ - payload) db 0
|
times 0xC0 - ($ - payload) nop
|
||||||
entry_common: equ $
|
entry_common: equ $
|
||||||
|
|
||||||
incbin _FILE
|
incbin _FILE
|
||||||
|
@ -13,20 +13,88 @@ DISCLAIMER: THE WORKS ARE WITHOUT WARRANTY.
|
|||||||
@:help
|
@:help
|
||||||
; Available patches:
|
; Available patches:
|
||||||
;
|
;
|
||||||
; :patch_iniload_no_query_geometry
|
; :patch_iniload_no_query_geometry (new or old style)
|
||||||
; :patch_iniload_no_lba
|
; :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
|
; Inputs: vef = nonzero to debug
|
||||||
; cs:0 -> iniload
|
; cs:ve7 -> iniload
|
||||||
; Output: vee = nonzero if error
|
; Output: vee = nonzero if error
|
||||||
; iniload patched
|
; iniload patched if successful
|
||||||
; Change: ve0 to vef, src, sro, aao, stack
|
; 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
|
; Requires lDebug release 3 or later
|
||||||
@goto :eof
|
@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
|
:patch_iniload_no_query_geometry
|
||||||
@if not (vef) then r ysf |= C000
|
@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)
|
r ve0 word (sp - 100)
|
||||||
a ss:ve0
|
a ss:ve0
|
||||||
mov ah, 08
|
mov ah, 08
|
||||||
@ -37,13 +105,22 @@ a ss:ve0
|
|||||||
.
|
.
|
||||||
r ve1 := aao - 1
|
r ve1 := aao - 1
|
||||||
r vec := ve1 - ve0
|
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
|
if not (src) then goto :error
|
||||||
r byte [srs:sro + vec - 1] := EB
|
r word [srs:sro + vec - 3] := 9090
|
||||||
goto :success
|
goto :success
|
||||||
|
|
||||||
|
|
||||||
:patch_iniload_no_lba
|
:patch_iniload_no_lba
|
||||||
@if not (vef) then r ysf |= C000
|
@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)
|
r ve0 word (sp - 100)
|
||||||
a ss:ve0
|
a ss:ve0
|
||||||
mov ah, 41
|
mov ah, 41
|
||||||
@ -56,7 +133,7 @@ a ss:ve0
|
|||||||
.
|
.
|
||||||
r ve1 := aao - 1
|
r ve1 := aao - 1
|
||||||
r vec := ve1 - ve0
|
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
|
if (src) then goto :patch_iniload_no_lba.success
|
||||||
a ss:ve0
|
a ss:ve0
|
||||||
mov ah, 41
|
mov ah, 41
|
||||||
@ -69,20 +146,64 @@ a ss:ve0
|
|||||||
.
|
.
|
||||||
r ve1 := aao - 1
|
r ve1 := aao - 1
|
||||||
r vec := ve1 - ve0
|
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
|
if not (src) then goto :error
|
||||||
|
|
||||||
:patch_iniload_no_lba.success
|
:patch_iniload_no_lba.success
|
||||||
r byte [srs:sro + vec - 1] := EB
|
r word [srs:sro + vec - 5] := 9090
|
||||||
goto :success
|
goto :success
|
||||||
|
|
||||||
:success
|
:success
|
||||||
|
r ve8 := 0
|
||||||
|
r ve9 := 0
|
||||||
r vee := 0
|
r vee := 0
|
||||||
r ysf &= ~C000
|
r ysf &= ~C000
|
||||||
; Patched successfully
|
; Patched successfully
|
||||||
@goto :eof
|
@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
|
:error
|
||||||
|
r ve8 := 0
|
||||||
|
r ve9 := 0
|
||||||
r vee := 1
|
r vee := 1
|
||||||
r ysf &= ~C000
|
r ysf &= ~C000
|
||||||
; Patch failed
|
; Patch failed
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
[ -z "$BOOT_COMMAND" ] && BOOT_COMMAND=~/.dosemu/drive_c/command.com
|
[ -z "$BOOT_COMMAND" ] && BOOT_COMMAND=~/.dosemu/drive_c/command.com
|
||||||
[ -z "$BOOT_PROTOCOL" ] && BOOT_PROTOCOL=FREEDOS
|
[ -z "$BOOT_PROTOCOL" ] && BOOT_PROTOCOL=FREEDOS
|
||||||
[ -z "$BOOT_OPTIONS" ] && BOOT_OPTIONS=" "
|
[ -z "$BOOT_OPTIONS" ] && BOOT_OPTIONS=" "
|
||||||
|
[ -z "$MKTMPINC" ] && MKTMPINC=mktmpinc.pl
|
||||||
[ -z "$NASM" ] && NASM=nasm
|
[ -z "$NASM" ] && NASM=nasm
|
||||||
[ -z "$CHECKSUM" ] && CHECKSUM="${INICHECK_DIR%/}"/iniload/checksum
|
[ -z "$CHECKSUM" ] && CHECKSUM="${INICHECK_DIR%/}"/iniload/checksum
|
||||||
|
|
||||||
|
@ -270,7 +270,17 @@ fi
|
|||||||
|
|
||||||
echo -ne 'failure\r\n' > result.txt
|
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 \
|
"$NASM" "${LDOSBOOT_DIR%/}"/$bootname.asm -w-user \
|
||||||
|
$TMPINC \
|
||||||
-D_LOAD_NAME="'TESTWRIT'" -D_LOAD_EXT="'SYS'" -D_FAT$bpe \
|
-D_LOAD_NAME="'TESTWRIT'" -D_LOAD_EXT="'SYS'" -D_FAT$bpe \
|
||||||
-D_UNIT=$unit \
|
-D_UNIT=$unit \
|
||||||
"$@" \
|
"$@" \
|
||||||
@ -283,6 +293,7 @@ echo -ne 'failure\r\n' > result.txt
|
|||||||
"$options_i_ldosboot" \
|
"$options_i_ldosboot" \
|
||||||
"$options_i_lmacros" \
|
"$options_i_lmacros" \
|
||||||
"$options_i_scanptab" \
|
"$options_i_scanptab" \
|
||||||
|
-D_PADDING='(48 * 1024)' \
|
||||||
-D_PAYLOAD_FILE="'testwrit.bin'" -o testwrit.sys -l testwrin.lst \
|
-D_PAYLOAD_FILE="'testwrit.bin'" -o testwrit.sys -l testwrin.lst \
|
||||||
-D_INILOAD_SIGNATURE='"TW"' &&
|
-D_INILOAD_SIGNATURE='"TW"' &&
|
||||||
"$NASM" "${BOOTIMG_DIR%/}"/bootimg.asm \
|
"$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_BPE="$bpe" -D_SPC="$spc" -D_SPI="$spi" \
|
||||||
-D_SPF="$(( (spi / spc * bpe / 8 + 511) / 512 ))" \
|
-D_SPF="$(( (spi / spc * bpe / 8 + 511) / 512 ))" \
|
||||||
-D_NUMROOT="$nr" \
|
-D_NUMROOT="$nr" \
|
||||||
-o $name.img -l $name.lst \
|
-D_MAP=$name.map -o $name.img -l $name.lst \
|
||||||
-D_PAYLOADFILE="testwrit.sys,result.txt" \
|
-D_PAYLOADFILE="testwrit.sys,result.txt,::chdir,dir" \
|
||||||
-D_BOOTFILE="'$bootfile'" \
|
-D_BOOTFILE="'$bootfile'" \
|
||||||
-D_UNIT=$unit \
|
-D_UNIT=$unit \
|
||||||
"$@" \
|
"$@" \
|
||||||
@ -301,6 +312,10 @@ echo -ne 'failure\r\n' > result.txt
|
|||||||
"$options_i_lmacros" \
|
"$options_i_lmacros" \
|
||||||
"$options_i_bootimg"
|
"$options_i_bootimg"
|
||||||
(($?)) && exit $?
|
(($?)) && exit $?
|
||||||
|
if [[ -n "$TMPINC" ]]
|
||||||
|
then
|
||||||
|
rm -f *.tmp
|
||||||
|
fi
|
||||||
|
|
||||||
pgid="$(ps -o pgid= $$)"
|
pgid="$(ps -o pgid= $$)"
|
||||||
function handle_timeout_process() {
|
function handle_timeout_process() {
|
||||||
@ -366,11 +381,16 @@ then
|
|||||||
cp -aL "$BOOT_KERNEL" "${BOOT_KERNEL##*/}"
|
cp -aL "$BOOT_KERNEL" "${BOOT_KERNEL##*/}"
|
||||||
cp -aL "$BOOT_COMMAND" "${BOOT_COMMAND##*/}"
|
cp -aL "$BOOT_COMMAND" "${BOOT_COMMAND##*/}"
|
||||||
echo -ne "@echo off\r\ninst${bpe}tw.com C:\r\nquit.com\r\n" > autoexec.bat
|
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 \
|
"$NASM" quit.asm \
|
||||||
"$options_i_lmacros" \
|
"$options_i_lmacros" \
|
||||||
-o quit.com &&
|
-o quit.com &&
|
||||||
"$NASM" "${LDOSBOOT_DIR%/}"/boot.asm -w-user \
|
"$NASM" "${LDOSBOOT_DIR%/}"/boot.asm -w-user \
|
||||||
"$options_i_lmacros" \
|
"$options_i_lmacros" \
|
||||||
|
$TMPINC \
|
||||||
-D_COMPAT_"$BOOT_PROTOCOL"=1 \
|
-D_COMPAT_"$BOOT_PROTOCOL"=1 \
|
||||||
-D_LBA=0 -D_USE_PART_INFO=0 -D_QUERY_GEOMETRY=0 \
|
-D_LBA=0 -D_USE_PART_INFO=0 -D_QUERY_GEOMETRY=0 \
|
||||||
$BOOT_OPTIONS \
|
$BOOT_OPTIONS \
|
||||||
@ -384,6 +404,10 @@ then
|
|||||||
-D_PAYLOADFILE="${BOOT_KERNEL##*/},${BOOT_COMMAND##*/},autoexec.bat,inst${bpe}tw.com,quit.com" \
|
-D_PAYLOADFILE="${BOOT_KERNEL##*/},${BOOT_COMMAND##*/},autoexec.bat,inst${bpe}tw.com,quit.com" \
|
||||||
-D_BOOTFILE="'bootinst.bin'"
|
-D_BOOTFILE="'bootinst.bin'"
|
||||||
(($?)) && exit $?
|
(($?)) && 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
|
timeout --foreground 10 "$QEMU" -fda diskinst.img "$qemu_switch" "$name".img -boot order=a -display none 2> /dev/null
|
||||||
rc=$?
|
rc=$?
|
||||||
handle_timeout_process
|
handle_timeout_process
|
||||||
@ -397,8 +421,13 @@ fi
|
|||||||
|
|
||||||
if ((! direct))
|
if ((! direct))
|
||||||
then
|
then
|
||||||
|
if [[ -n "$TMPINC" ]]
|
||||||
|
then
|
||||||
|
"$MKTMPINC" "${LDOSBOOT_DIR%/}"/boot.asm > /dev/null
|
||||||
|
fi
|
||||||
"$NASM" "${LDOSBOOT_DIR%/}"/boot.asm -w-user \
|
"$NASM" "${LDOSBOOT_DIR%/}"/boot.asm -w-user \
|
||||||
"$options_i_lmacros" \
|
"$options_i_lmacros" \
|
||||||
|
$TMPINC \
|
||||||
-D_LOAD_NAME="'LDEBUG'" -D_LOAD_EXT="'COM'" \
|
-D_LOAD_NAME="'LDEBUG'" -D_LOAD_EXT="'COM'" \
|
||||||
-D_MAP=boot12db.map -l boot12db.lst -o boot12db.bin &&
|
-D_MAP=boot12db.map -l boot12db.lst -o boot12db.bin &&
|
||||||
"$NASM" "${BOOTIMG_DIR%/}"/bootimg.asm \
|
"$NASM" "${BOOTIMG_DIR%/}"/bootimg.asm \
|
||||||
@ -409,6 +438,10 @@ then
|
|||||||
-o diskldbg.img -l diskldbg.lst \
|
-o diskldbg.img -l diskldbg.lst \
|
||||||
-D_PAYLOADFILE="ldebug.com" -D_BOOTFILE="'boot12db.bin'"
|
-D_PAYLOADFILE="ldebug.com" -D_BOOTFILE="'boot12db.bin'"
|
||||||
(($?)) && exit $?
|
(($?)) && exit $?
|
||||||
|
if [[ -n "$TMPINC" ]]
|
||||||
|
then
|
||||||
|
rm -f *.tmp
|
||||||
|
fi
|
||||||
|
|
||||||
if ((dosemu))
|
if ((dosemu))
|
||||||
then
|
then
|
||||||
|
@ -863,5 +863,9 @@ signature2:
|
|||||||
dw 2638h
|
dw 2638h
|
||||||
|
|
||||||
%if _PADDING
|
%if _PADDING
|
||||||
|
%if ($ - $$) > _PADDING
|
||||||
|
%warning No padding needed
|
||||||
|
%else
|
||||||
times _PADDING - ($ - $$) db 0
|
times _PADDING - ($ - $$) db 0
|
||||||
|
%endif
|
||||||
%endif
|
%endif
|
||||||
|
@ -128,6 +128,7 @@ ATTR_ARCHIVE equ 20h
|
|||||||
numdef LBA_RETRY, 1 ; retry LBA reads
|
numdef LBA_RETRY, 1 ; retry LBA reads
|
||||||
numdef CHS_RETRY, 1 ; retry CHS reads
|
numdef CHS_RETRY, 1 ; retry CHS reads
|
||||||
|
|
||||||
|
numdef PADDING, 0
|
||||||
strdef FILE_NAME, "RESULT"
|
strdef FILE_NAME, "RESULT"
|
||||||
strdef FILE_EXT, "TXT" ; name of file to write
|
strdef FILE_EXT, "TXT" ; name of file to write
|
||||||
strdef FILE_SUCCESS_MSG,"success"
|
strdef FILE_SUCCESS_MSG,"success"
|
||||||
@ -501,7 +502,7 @@ write_sector:
|
|||||||
push ax
|
push ax
|
||||||
push si
|
push si
|
||||||
|
|
||||||
push bx
|
mov es, bx
|
||||||
|
|
||||||
; DX:AX==LBA sector number
|
; DX:AX==LBA sector number
|
||||||
; add partition start (= number of hidden sectors)
|
; add partition start (= number of hidden sectors)
|
||||||
@ -557,7 +558,8 @@ write_sector:
|
|||||||
testopt [bp + ldHasLBA], 2
|
testopt [bp + ldHasLBA], 2
|
||||||
jz @F
|
jz @F
|
||||||
|
|
||||||
mov es, word [si + 4 + 2] ; user buffer
|
; es => user buffer
|
||||||
|
push es
|
||||||
call .sectorseg_helper_write
|
call .sectorseg_helper_write
|
||||||
mov word [si + 4 + 2], es ; => sector buffer
|
mov word [si + 4 + 2], es ; => sector buffer
|
||||||
mov ah, 43h
|
mov ah, 43h
|
||||||
@ -567,14 +569,16 @@ write_sector:
|
|||||||
int 13h
|
int 13h
|
||||||
; (don't need .int13_preserve_lpcount as no further call)
|
; (don't need .int13_preserve_lpcount as no further call)
|
||||||
%endif
|
%endif
|
||||||
|
pop es ; ! restore es => user buffer
|
||||||
jc .lba_error
|
jc .lba_error
|
||||||
jmp .lba_done
|
jmp .lba_done
|
||||||
|
|
||||||
@@:
|
@@:
|
||||||
; push word [si + 4 + 0]
|
; push word [si + 4 + 0]
|
||||||
push word [si + 4 + 2] ; user buffer
|
push es ; => user buffer
|
||||||
push word [bp + ldSectorSeg]
|
mov es, word [bp + ldSectorSeg]
|
||||||
pop word [si + 4 + 2]
|
mov word [si + 4 + 2], es
|
||||||
|
; => sector buffer
|
||||||
; and word [si + 4 + 0], byte 0
|
; and word [si + 4 + 0], byte 0
|
||||||
|
|
||||||
mov ah, 42h
|
mov ah, 42h
|
||||||
@ -586,14 +590,13 @@ write_sector:
|
|||||||
%endif
|
%endif
|
||||||
jc .lba_error
|
jc .lba_error
|
||||||
|
|
||||||
pop es
|
pop es ; => user buffer
|
||||||
; pop cx
|
; pop cx
|
||||||
call .sectorseg_helper_read
|
call .sectorseg_helper_read
|
||||||
|
|
||||||
.lba_done:
|
.lba_done:
|
||||||
add sp, 10h
|
add sp, 10h
|
||||||
pop bx
|
jmp short .done
|
||||||
jmp short .chs_done
|
|
||||||
|
|
||||||
.lba_error: equ .err
|
.lba_error: equ .err
|
||||||
|
|
||||||
@ -678,7 +681,6 @@ write_sector:
|
|||||||
|
|
||||||
; we call INT 13h AH=02h once for each sector. Multi-sector reads
|
; we call INT 13h AH=02h once for each sector. Multi-sector reads
|
||||||
; may fail if we cross a track or 64K boundary
|
; may fail if we cross a track or 64K boundary
|
||||||
pop es
|
|
||||||
|
|
||||||
call .get_ah_3_write_2_read
|
call .get_ah_3_write_2_read
|
||||||
mov al, 01h ; access one sector
|
mov al, 01h ; access one sector
|
||||||
@ -722,14 +724,11 @@ write_sector:
|
|||||||
|
|
||||||
pop es
|
pop es
|
||||||
call .sectorseg_helper_read
|
call .sectorseg_helper_read
|
||||||
|
%endif ; _CHS
|
||||||
|
|
||||||
.done:
|
.done:
|
||||||
; increment segment
|
; increment segment
|
||||||
mov bx, es
|
mov bx, es
|
||||||
%endif
|
|
||||||
|
|
||||||
.chs_done:
|
|
||||||
mov es, bx
|
|
||||||
add bx, word [bp + ldParaPerSector]
|
add bx, word [bp + ldParaPerSector]
|
||||||
|
|
||||||
pop si
|
pop si
|
||||||
@ -757,21 +756,21 @@ write_sector:
|
|||||||
; reset drive
|
; reset drive
|
||||||
xor ax, ax
|
xor ax, ax
|
||||||
int 13h
|
int 13h
|
||||||
jc @F ; CY, reset failed, error in ah -->
|
jnc @FF ; NC, reset succeeded -->
|
||||||
|
; 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
|
|
||||||
|
|
||||||
@@: ; NC or CY, stack has function number
|
@@: ; NC or CY, stack has function number
|
||||||
inc sp
|
inc sp
|
||||||
inc sp ; discard word on stack, preserve CF
|
inc sp ; discard word on stack, preserve CF
|
||||||
retn
|
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
|
%endif
|
||||||
|
|
||||||
%if _LBA
|
%if _LBA
|
||||||
@ -1021,3 +1020,11 @@ check_clust:
|
|||||||
|
|
||||||
align 16, db 38
|
align 16, db 38
|
||||||
end:
|
end:
|
||||||
|
|
||||||
|
%if _PADDING
|
||||||
|
%if ($ - $$) > _PADDING
|
||||||
|
%warning No padding needed
|
||||||
|
%else
|
||||||
|
times _PADDING - ($ - $$) db 0
|
||||||
|
%endif
|
||||||
|
%endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user