mirror of
https://github.com/FDOS/kernel.git
synced 2025-08-22 10:18:15 +02:00
460 lines
14 KiB
Plaintext
460 lines
14 KiB
Plaintext
\cfg{chapter}{Section}
|
|
|
|
\cfg{text-filename}{ldosboot.txt}
|
|
\cfg{text-chapter-numeric}{true}
|
|
\cfg{text-indent-preamble}{false}
|
|
\cfg{text-quotes}{"}{"}
|
|
\cfg{text-indent}{4}
|
|
\cfg{text-width}{72}
|
|
|
|
\cfg{html-chapter-numeric}{true}
|
|
\cfg{html-suppress-address}{true}
|
|
\cfg{html-single-filename}{ldosboot.htm}
|
|
\cfg{html-leaf-level}{0}
|
|
\cfg{html-template-fragment}{%k}{%b}
|
|
\cfg{html-head-end}{<meta name="viewport" content="width=device-width, initial-scale=1.0">}
|
|
\cfg{html-heading-hashtag-links}{true}
|
|
|
|
\cfg{pdf-filename}{ldosboot.pdf}
|
|
|
|
\cfg{ps-filename}{ldosboot.ps}
|
|
|
|
\cfg{info-filename}{ldosboot.info}
|
|
|
|
\cfg{chm-filename}{ldosboot.chm}
|
|
|
|
\cfg{winhelp-filename}{ldosboot.hlp}
|
|
|
|
\cfg{man-filename}{ldosboot.7}
|
|
\cfg{man-identity}{ldosboot}{7}{2020}{}{C. Masloch}
|
|
|
|
\title lDOS boot documentation
|
|
|
|
\copyright 2020 by C. Masloch.
|
|
Usage of the works is permitted provided that this
|
|
instrument is retained with the works, so that any entity
|
|
that uses the works is notified of this instrument.
|
|
DISCLAIMER: THE WORKS ARE WITHOUT WARRANTY.
|
|
|
|
This document has been compiled on \date{%Y-%m-%d}.
|
|
|
|
|
|
\C{protocols} lDOS boot protocols
|
|
|
|
|
|
\H{protocol-sector-iniload} Sector to iniload protocol
|
|
|
|
The iniload kernel is loaded to an arbitrary segment.
|
|
The segment must be at least 60h.
|
|
Common choices are 60h, 70h, and 200h.
|
|
At least 1536 bytes of the file must be loaded.
|
|
Current loaders will load at least 8192 bytes
|
|
if the file is as large or larger than that.
|
|
The entrypoint is found by applying no segment adjustment (0)
|
|
and choosing the offset 400h (1024).
|
|
|
|
|
|
\S{protocol-sector-iniload-file} File properties
|
|
|
|
The file must be at least 4096 bytes long.
|
|
This is now required, beyond the former lower bound of 1536 bytes,
|
|
to support an optimisation of the FAT12 and FAT16 boot sector loaders.
|
|
The lDebug loader and the FAT32+FSIBOOT loader currently retain the 1536 bytes limit.
|
|
|
|
The file may allow multi-use as a flat .COM format executable,
|
|
flat .SYS format device driver, or MZ .EXE format executable
|
|
and/or device driver.
|
|
It is also valid to append arbitrary sized data such as a .ZIP archive.
|
|
|
|
The file needs to be placed in the root directory for the boot sector loaders.
|
|
The lDebug loader allows to load a file
|
|
from any subdirectory and this is also allowed.
|
|
The file may be fragmented in any part.
|
|
The file data may be located anywhere in the file system.
|
|
The supported cluster sizes should be between 32 Bytes and 2 MiB, inclusive.
|
|
The sector size should be between 32 Bytes and 8 KiB, inclusive.
|
|
|
|
|
|
\S{protocol-sector-iniload-signatures} Signatures
|
|
|
|
At offset 1020 (3FCh) there is the signature \cq{lD}.
|
|
Behind that there are two bytes with printable non-blank ASCII codepoints.
|
|
Currently the following signatures are defined:
|
|
|
|
\dt \cq{lDOS}
|
|
|
|
\dd lDOS kernel (not yet in use)
|
|
|
|
\dt \cq{lDRx}
|
|
|
|
\dd RxDOS kernel
|
|
|
|
\dt \cq{lDFD}
|
|
|
|
\dd FreeDOS kernel wrapped in iniload (fdkernpl.asm)
|
|
|
|
\dt \cq{lDeb}
|
|
|
|
\dd lDebug
|
|
|
|
\dt \cq{lDDb}
|
|
|
|
\dd lDDebug (debuggable lDebug)
|
|
|
|
\dt \cq{lDbC}
|
|
|
|
\dd lCDebug (conditionally debuggable lDebug)
|
|
|
|
\dt \cq{lDTP}
|
|
|
|
\dd lDOS test payload kernel (testpl.asm)
|
|
|
|
\dt \cq{lDTW}
|
|
|
|
\dd lDOS test result writer kernel (testwrit.asm)
|
|
|
|
|
|
\S{protocol-sector-iniload-lsv} Load Stack Variables (LSV)
|
|
|
|
Under this protocol, the pointer \cq{ss:bp} is passed.
|
|
It points to a boot sector with (E)BPB.
|
|
\cq{bp} must be even for compatibility with older iniload (before 2023-March).
|
|
The stack pointer must be at most \cq{bp - 10h}.
|
|
Below the pointed to location there live the Load Stack Variables.
|
|
These follow this structure:
|
|
|
|
\c struc LOADSTACKVARS, -10h
|
|
\c lsvFirstCluster: resd 1
|
|
\c lsvFATSector: resd 1
|
|
\c lsvFATSeg: resw 1
|
|
\c lsvLoadSeg: resw 1
|
|
\c lsvDataStart: resd 1
|
|
\c endstruc
|
|
|
|
\dt lsvFirstCluster
|
|
|
|
\dd (FAT12, FAT16) Low word gives starting cluster of file.
|
|
High word uninitialised.
|
|
|
|
\dd (FAT32) Dword gives starting cluster of file.
|
|
|
|
\dd (else) Should be zero.
|
|
|
|
\dt lsvFATSector
|
|
|
|
\dd (FAT16) Low word gives loaded sector-in-FAT.
|
|
-1 if none loaded yet.
|
|
High word uninitialised.
|
|
|
|
\dd (FAT32) Dword gives loaded sector-in-FAT.
|
|
-1 if none loaded yet.
|
|
|
|
\dd (FAT12, else) Unused.
|
|
|
|
\dt lsvFATSeg
|
|
|
|
\dd (FAT16, FAT32) Word gives segment of FAT buffer
|
|
if word/dword [lsvFATSector] != -1.
|
|
|
|
\dd (FAT12) Word gives segment of FAT buffer.
|
|
Zero if none.
|
|
Otherwise, buffer holds entire FAT data, up to 6 KiB.
|
|
|
|
\dt lsvLoadSeg
|
|
|
|
\dd Word points to segment beyond last loaded paragraph.
|
|
Allows iniload to determine how much of it is already loaded.
|
|
|
|
\dt lsvDataStart
|
|
|
|
\dd Dword gives sector-in-partition of first cluster's data.
|
|
|
|
|
|
An LSV extension allows to pass a command line to the kernel.
|
|
The base pointer must be at least \cq{114h} then.
|
|
The stack pointer must be at most \cq{bp - 114h} then.
|
|
This follows the structure like this:
|
|
|
|
\c lsvclSignature equ "CL"
|
|
\c lsvclBufferLength equ 256
|
|
\c
|
|
\c struc LSVCMDLINE, LOADSTACKVARS - lsvclBufferLength - 4
|
|
\c lsvCommandLine:
|
|
\c .start: resb lsvclBufferLength
|
|
\c .signature: resw 1
|
|
\c lsvExtra: resw 1
|
|
\c endstruc
|
|
|
|
\dt lsvCommandLine.start
|
|
|
|
\dd Command line buffer. Contains zero-terminated command line string.
|
|
|
|
\dt lsvCommandLine.signature
|
|
|
|
\dd Contains the signature value \cq{CL} if command line is given.
|
|
|
|
\dt lsvExtra
|
|
|
|
\dd Used internally by iniload.
|
|
Space for this must be reserved when passing a command line.
|
|
|
|
If no command line is passed then either the stack pointer
|
|
must be \cq{bp - 10h}, or \cq{bp - 12h}, or
|
|
the word in the lsvCommandLine.signature variable
|
|
(\cw{word [ss:bp - 14h]})
|
|
must not equal the string \cq{CL}.
|
|
|
|
\b dosemu2's RxDOS.3 support sets \cq{sp = bp - 10h}
|
|
|
|
\b ldosboot boot.asm (FAT12/FAT16) loader
|
|
makes sure not to pass the variable with the content "CL".
|
|
Refer to placeholder and DIRSEARCHSTACK_CL_FIRST uses in the source.
|
|
|
|
\b ldosboot boot32.asm (FAT32) loader
|
|
uses the variable for an \q{entries per sector} value
|
|
which is always a power of two and always below-or-equal 100h.
|
|
|
|
\b lDebug with protocol options \cw{cmdline=0 push_dpt=0}
|
|
sets \cq{sp = bp - 10h}
|
|
|
|
|
|
\S{protocol-sector-iniload-memory} Memory map
|
|
|
|
The initial loader part that is loaded must be loaded
|
|
at above or equal to linear 00600h.
|
|
The FAT buffer segment (if used) must also be stored
|
|
at above or equal to linear 00600h.
|
|
The stack (which should extend at least 512 bytes below \cq{ss:bp})
|
|
and boot sector (pointed to by \cq{ss:bp}, at least 512 bytes length)
|
|
should also be stored at above or equal to linear 00600h.
|
|
|
|
There is an additional memory area,
|
|
the Low Memory Area top reservation,
|
|
which should be unused by the load protocol at handoff time
|
|
but be at least 20 KiB in size.
|
|
It is located below the usable Low Memory Area top.
|
|
That is, directly below the EBDA, RPL-reserved memory, video memory,
|
|
or otherwise UMA.
|
|
This area is reserved in order to facilitate initial loader operation.
|
|
|
|
None of the memory areas may overlap.
|
|
This does not include the FAT buffer in case it is uninitialised.
|
|
|
|
|
|
\S{protocol-sector-iniload-loadname} Load filename in the boot sector
|
|
|
|
The boot sector may be expected to contain a valid
|
|
8.3 format (blank-padded FCB) filename
|
|
in the area of the boot sector starting behind the (E)BPB,
|
|
extending up to below the boot sector signature word with value AA55h
|
|
(at offset 510 in the boot sector).
|
|
This name should not contain blanks other than trailing in the
|
|
file name portion or trailing in the file extension portion.
|
|
It should consist of printable ASCII codepoints.
|
|
That is, byte values between 20h and 7Eh inclusive.
|
|
It should not consist of eleven times the same byte value.
|
|
Additional FAT Short File Name restrictions may be assumed.
|
|
|
|
Although a loader should not depend on this for crucial operation,
|
|
it may want to detect the kernel name it was presumably loaded from
|
|
for informational or optional purposes.
|
|
The canonical implementation of this is currently the function
|
|
\cq{findname} in the \cw{testpl.asm} test payload kernel.
|
|
It is found within
|
|
\W{https://hg.pushbx.org/ecm/ldosboot/file/e0c17723f953/testpl.asm#l668}{the ldosboot repo}.
|
|
This handling is based on the function of the same name
|
|
\W{https://hg.pushbx.org/ecm/instsect/file/53e4327aacd6/instsect.asm#l2442}{in the instsect application}.
|
|
|
|
|
|
\S{protocol-sector-iniload-patch} Query patch support
|
|
|
|
The ldosboot repo includes a patch Script for lDebug (.sld) file
|
|
which allows to patch the initial loader stage.
|
|
The patches concern handling of the CHS geometry detection,
|
|
and whether LBA or CHS access is used.
|
|
There are several legacy patch sites in which patch.sld
|
|
can directly patch the initial loader's code.
|
|
|
|
However, the preferred way is to find the query patch sequence.
|
|
It should appear within the first 1536 bytes,
|
|
that is within the part of the initial loader that must be loaded.
|
|
This is the sequence:
|
|
|
|
\c 8A5640 mov dl, byte [bp + 40h]
|
|
\c B8xxyy mov ax, yyxxh
|
|
\c 84D2 test dl, dl
|
|
\c 7902 jns @F
|
|
\c 86C4 xchg al, ah
|
|
\c @@:
|
|
|
|
The immediate word of the \cw{mov ax} instruction is to be patched.
|
|
The sequence should be scanned for without regard as to what
|
|
the current contents of this word are.
|
|
|
|
The following flag values are used:
|
|
|
|
\b 01h Force CHS access, do not detect LBA support with 13.41
|
|
|
|
\b 02h Force LBA access, do not detect LBA support with 13.41
|
|
|
|
\b 04h Force use of BPB's CHS geometry, do not detect with 13.08
|
|
|
|
\b 80h Used by lDebug. If this value is set for the load unit,
|
|
then lDebug will make use of the other flags set up for that unit.
|
|
The corresponding flags will be saved in lDebug's load_unit_flags.
|
|
This affects only the load unit (LD in lDebug terminology),
|
|
which suffices to pass commands in the startup Script for lDebug.
|
|
|
|
The flag 01h takes precedence over 02h if both are set.
|
|
|
|
The low byte (xxh) is used in case the loader loads
|
|
from a diskette unit, that is a unit number below 80h.
|
|
The high byte (yyh) is used otherwise, in case the loader loads
|
|
from a hard disk unit, that is a unit number above-or-equal 80h.
|
|
|
|
|
|
\H{protocol-iniload-payload} Iniload to payload protocol
|
|
|
|
The payload is loaded to an arbitrary segment.
|
|
The segment must be at least 60h.
|
|
The entire payload must be loaded.
|
|
The size of the payload is determined at iniload build time.
|
|
The entrypoint is found by applying a segment adjustment
|
|
and choosing an offset.
|
|
The segment adjustment is specified at iniload build time
|
|
by the numeric define \cw{_EXEC_SEGMENT} (default 0),
|
|
and the offset by the define \cw{_EXEC_OFFSET} (default 0).
|
|
|
|
|
|
\S{protocol-iniload-payload-ebpb} Extended BIO Parameter Block (EBPB)
|
|
|
|
Above the LSV, \cw{ss:bp} points to an EBPB and surrrounding boot sector.
|
|
Note that this is always a FAT32-style EBPB.
|
|
If the filesystem that is loaded from is not FAT32,
|
|
and is therefore FAT16 or FAT12,
|
|
then the FAT16/FAT12 BPBN structure is moved up.
|
|
It is placed where the FAT32 BPBN is usually expected.
|
|
In this case, the entire boot sector contents behind the BPBN
|
|
are also moved up by the size of the FAT32-specific fields.
|
|
The FAT32-specific fields are filled with zeros,
|
|
except for the FAT32 \q{sectors per FAT} field.
|
|
It is filled with the contents of the FAT16/FAT12
|
|
\q{sectors per FAT} field.
|
|
|
|
|
|
\S{protocol-iniload-payload-lsv} Load Stack Variables (LSV)
|
|
|
|
Refer to \k{protocol-sector-iniload-lsv}.
|
|
|
|
|
|
\S{protocol-iniload-payload-ld} Load Data 1 (LD)
|
|
|
|
Below the LSV, iniload passes the LOADDATA (1) structure.
|
|
|
|
\c struc LOADDATA, LOADSTACKVARS - 10h
|
|
\c ldMemoryTop: resw 1
|
|
\c ldLoadTop: resw 1
|
|
\c ldSectorSeg: resw 1
|
|
\c ldFATType: resb 1
|
|
\c ldHasLBA: resb 1
|
|
\c ldClusterSize: resw 1
|
|
\c ldParaPerSector:resw 1
|
|
\c ldLoadingSeg:
|
|
\c ldQueryPatchValue:
|
|
\c resw 1
|
|
\c ldLoadUntilSeg: resw 1
|
|
\c endstruc
|
|
|
|
\dt ldMemoryTop
|
|
|
|
\dd Word. Segment pointer to behind usable memory.
|
|
Points at the first of the EBDA, RPL-reserved memory, or
|
|
video memory or otherwise UMA.
|
|
Indicates how much memory may be used by a typical kernel.
|
|
(lDebug detects the EBDA to move that below where it installs.)
|
|
|
|
\dt ldLoadTop
|
|
|
|
\dd Word. Segment pointer to lowest lDOS boot memory in use.
|
|
All memory between linear 600h and the segment indicated here
|
|
is usable by the payload.
|
|
Only the payload itself is stored in this area.
|
|
The other buffers, stack, and structures passed by iniload
|
|
must live above this segment.
|
|
|
|
\dt ldSectorSeg
|
|
|
|
\dd Word. Segment pointer to an 8 KiB transfer buffer.
|
|
It is insured that this buffer does not cross a 64 KiB boundary.
|
|
This may be needed by some disk units.
|
|
The buffer is not initialised to anything generally.
|
|
|
|
\dt ldFATType
|
|
|
|
\dd Byte. Indicates length of FAT entry in bits.
|
|
12 indicates FAT12, 16 FAT16, 32 FAT32.
|
|
It is planned to allow zero for non-FAT filesystems.
|
|
|
|
\dt ldHasLBA
|
|
|
|
\dd Byte. Only least significant bit used.
|
|
Bit on indicates LBA extensions available for the load disk unit.
|
|
Bit off indicates LBA extensions not available.
|
|
|
|
\dt ldClusterSize
|
|
|
|
\dd Word. Contains amount of sectors per cluster.
|
|
Unlike the byte field for the same purpose in the BPB,
|
|
this field can encode 256 (EDR-DOS compatible) without any masking.
|
|
May be given as zero for non-FAT filesystems.
|
|
|
|
\dt ldParaPerSector
|
|
|
|
\dd Word. Contains amount of paragraphs per sector.
|
|
Must be a power of two between 2 (32 B/s) and 200h (8192 B/s).
|
|
May be given as zero for non-FAT filesystems.
|
|
|
|
\dt ldLoadingSeg
|
|
|
|
\dd Word. Internally used by iniload.
|
|
Available for re-use by payload.
|
|
However, ldQueryPatchValue re-uses the same field.
|
|
|
|
\dt ldQueryPatchValue
|
|
|
|
\dd Word. Passes the query patch value from the initial loader.
|
|
This provides an opportunity to patch a well-known site
|
|
in the initial loader to change its behaviour in some ways.
|
|
Near the end of its operation, the initial loader
|
|
passes along this value in this variable for the next stage to use.
|
|
|
|
\dt ldLoadUntilSeg
|
|
|
|
\dd Word. Internally used by iniload.
|
|
Available for re-use by payload.
|
|
|
|
|
|
\S{protocol-iniload-payload-lcl} Load Command Line (LCL)
|
|
|
|
Below the LOADDATA structure, iniload passes the LOADCMDLINE structure.
|
|
|
|
\c lsvclBufferLength equ 256
|
|
\c
|
|
\c struc LOADCMDLINE, LOADDATA - lsvclBufferLength
|
|
\c ldCommandLine:
|
|
\c .start: resb lsvclBufferLength
|
|
\c endstruc
|
|
|
|
This buffer is always initialised to an ASCIZ string.
|
|
At most 255 bytes may be initialised to string data.
|
|
At most the 256th byte is a zero.
|
|
|
|
If the first word of the buffer is equal to 0FF00h,
|
|
that is there is an empty command line
|
|
the terminator of which is followed by a byte with the value 0FFh,
|
|
then no command line was passed to iniload.
|
|
Currently lDebug can pass a command line to iniload when
|
|
loading with its lDOS, RxDOS.2, RxDOS.3, or FreeDOS protocols.
|
|
When iniload is loaded as a Multiboot1 or Multiboot2 specification kernel,
|
|
it is also assumed that a command line can be passed.
|