A user found that lDOS iniload was used in a certain boot image. After my answer identifying and describing iniload, the following question occurred in a comment:
If I already have some kernel files (e.g. IO.SYS, MSDOS.SYS, KERNEL.SYS), how do I create an iniload file which contains the kernel file(s) as payload? Is this process documented somewhere?
The gold standard for building a complete, triple-mode kernel so that it is wrapped by lDOS iniload and optionally with an inicomp stage is the lDebug mak.sh script. Basically it assembles iniload.asm
with the include pathnames for lmacros, ldosboot, scanptab, passing a number of options including an "_INILOAD_CFG" file and some defines that set up the kernel mode entry as 0:32
and the MZ executable image as being the same as the kernel image. The payload file is chosen as either the debugger's .BIG image or the complete inicomp stage with the packed payload and depacker.
RxDOS 7.2x also used to use lDOS iniload. However, RxDOS is obsolete and unmaintained.
The FreeDOS kernel payload is fairly easy to implement, and was thus the first intermediate, non-native stage added to the lDOS ecosystem. (I'm counting the lRxDOS kernel and lDebug as native stages. Likewise inicomp and checkpl.) This goes back to the fact that the FreeDOS load protocol only demands the entire file be loaded, and that the load unit is transferred in BL. Even with my additional assumptions of passing SS:BP -> a boot sector with the unit and hidden sectors it is simple enough to carry the kernel as a payload, relocate it, and transfer control to it at the expected address.
Therefore, the following two NASM commands suffice to create an iniload kernel that carries a FreeDOS kernel as a payload, if the lmacros, ldosboot, and scanptab repositories are already checked out into their respective directories:
nasm -I lmacros/ ldosboot/fdkernpl.asm -o payload.bin \ -D_PAYLOAD_FILE="'kernel.sys'" && nasm -I lmacros/ -I ldosboot/ -I scanptab/ ldosboot/iniload.asm -o ldos.com \ -D_PAYLOAD_FILE="'payload.bin'" -l ldos.lst -D_INILOAD_SIGNATURE="'FD'"
Note that there is a problem with FreeDOS's SYS CONFIG command: It expects its kernel CONFIG block at the very beginning of the kernel file. This space is used by iniload's zero entrypoint and MZ header, so it cannot hold the CONFIG block then. I intend to eventually patch SYS CONFIG so it will recognise a CONFIG block within the first 8 KiB or so.
The original (non-lDOS-flavour, 2011 era) EDR-DOS load differs little from FreeDOS. The load unit register (BL vs DL) is irrelevant to fdkernpl as it provides both of them. The load address at 00700h would be easy enough to add to fdkernpl, albeit at the current time this is not implemented (hardcoding 00600h instead).
However, EDR-DOS load used to imply a second file. EDR-DOS used to use only the DS:BP -> BPB with hidden sectors and the load unit in DL to find the file system of the second file, opting to include its own directory scanner to find the desired file, with the name DRDOS.SYS
. Read on for my thoughts on that.
MS-DOS v4.00 had two modules that were combined (appended) to create the io.sys
file: msload and msbio. The msload part (or the "Non-Contiguous IBMBIO Loader (MSLOAD)") essentially has most of the same duties as iniload: Walk the FAT and load its payload, which is found after the initial loader within the file. The msbio stage is the kernel proper. Unlike msload, iniload can (when using its native lDOS / RxDOS.3 load) re-use both a FAT sector buffer and parts of its payload that the prior loader already may have loaded.
The iniload to payload protocol doesn't promise a particular load address for the payload. This is one part of what a stage like fdkernpl does. It does depend on the payload being loaded to a paragraph boundary, and to an address that is at least 00600h.
msload always expects to find its payload at a certain address within the file. (In MS-DOS v4 it also depended on the kernel file's first data cluster being cluster 2 in the file system. This is no longer true of MS-DOS v5 and MS-DOS v6, nor the more different MS-DOS v7.) Therefore, we want to replace msload using iniload, not just chain to a complete image (like fdkernpl does) that includes msload.
To replace msload only, we could exactly replicate the handoff from msload to msbio:
For bypassing msload it probably helps to study the msload passing control to msbio. This revision in my repo is the last of the msload/msbio/msdos dual-file setup, but it does already have build fixes and creates .tls (trace listing) files useful for debugging. According to this the registers are ax:bx = data start including hidden sectors, ch = media ID, dl = int 13h unit, and of course the msdos file's directory entry must still be at 00520h.
The problem with an (E)DR-DOS or MS-DOS wrapper for iniload is that these kernels were designed to load a second file, known respectively as ibmdos, drdos, or msdos. If you want to use the second module from the same file as iniload, you cannot just provide the file in memory. You also have to patch the ibmbio/drbio/msbio stage to actually use that module in preference to loading the file from disk.
I did not create a binary patch like that for any dual-file kernel yet.
Enhanced DR-DOS is the first dual-file kernel that I recently patched at the source level to be loaded from iniload, that is using a single-file load.
The second non-native stage, drkernpl, was first created for EDR-DOS in late 2023. Because it doesn't patch the bio stage, it only solves half of the problem: Carrying both drbio and drdos as payloads, and passing the position and size of drdos to the drbio module's entry. I decided to pass AX => the drdos module, and SI = its length in bytes. These two registers weren't yet used in the FreeDOS-based EDR-DOS load.
I documented the process of changing EDR-DOS to a single-file load exactly one year ago. As listed there, the drkernpl stage was based on fdkernpl, except it would load drbio to 00700h and pass the drdos as well. I patched the source texts of drbio to use the passed drdos rather than load it from disk. In a subsequent changeset I deleted most of the "BDOS loader" (albeit I restored a part of it which deals with changing the default drive).
After this, the single-file kernel was completed by building the combined file as an iniload kernel. The following commands were first used to do this:
nasm ../ldosboot/drkernpl.asm -I ../lmacros/ -I drbio/bin/ -I drdos/bin/ -o edrdos.bin lzip -9vvfkc edrdos.bin > edrdos.lz nasm ../inicomp/inicomp.asm -I ../inicomp/ -I ../lmacros/ -D_PAYLOAD_FILE='"edrdos.lz"' -o edrdos.pak -D_LZD # nasm ../ldosboot/iniload.asm -I ../lmacros/ -I ../scanptab/ -D_PAYLOAD_FILE='"edrdos.pak"' -D_INILOAD_SIGNATURE='"DR"' -o edrpack.com "$@" # nasm ../ldosboot/iniload.asm -I ../lmacros/ -I ../scanptab/ -D_PAYLOAD_FILE='"edrdos.bin"' -D_INILOAD_SIGNATURE='"DR"' -o edrdos.com "$@" nasm ../ldosboot/drload.asm -I ../lmacros/ -D_PAYLOAD_FILE='"edrdos.pak"' -o edrpack.sys "$@" nasm ../ldosboot/drload.asm -I ../lmacros/ -D_PAYLOAD_FILE='"edrdos.bin"' -o edrdos.sys "$@"
As commented in the changeset message:
The lmacros, ldosboot, inicomp, and scanptab repositories have to be accessible as sister directories of the repo. lzip must be found in the path.
A subsequent changeset enabled the commented-out lines to create .COM files, adding a "second payload .EXE" image. After assembling the utility to be used for the MZ executable image as in nasm version.asm -I ../lmacros/ -o version.com
I used the following command to create edrdos.com
:
nasm ../ldosboot/iniload.asm -I ../ldosboot/ -I ../lmacros/ -I ../scanptab/ \ -D_PAYLOAD_FILE='"edrdos.bin"' -D_INILOAD_SIGNATURE='"DR"' -o edrdos.com \ -D_SECOND_PAYLOAD_EXE -D_SECOND_PAYLOAD_FILE='"version.com"' \ -D_SECOND_PAYLOAD_EXE_IP=256 \ "$@"
In 2024 August I also described the EDR-DOS single-file load some on the freedos-devel mailing list. One point from this mail I elided so far is the drload stage. This is a replacement for lDOS iniload that only supports being loaded using FreeDOS or old EDR-DOS load, and only as a kernel. The advantage as compared to iniload is that no file system or disk read code needs to be included, making drload's footprint smaller than iniload's (drload: 1B0h = 432 Bytes, iniload: FD0h = 4048 Bytes). Current builds include four kernel files: Two dual-mode iniload files and two drload kernel-only files, as well as two each of edrpack (compressed) and edrdos (uncompressed).
The 2024 early May blog post casually lists the single-file load, pointing to a 2024-05-04 changeset. This re-used drkernpl, the optional inicomp, the drload alternative to iniload, as well as the scripting to bind everything together from the EDR-DOS changes. The output filenames however were changed to lmsdos.* and lmspack.*, indicating that I consider the fork a mix between lDOS and MS-DOS.
Only a single file, msbio/msinit.asm, had to be changed to patch the msbio to use the resident msdos rather than loading it. In a subsequent changeset the DOS loader was dropped, similar to how EDR-DOS's BDOS loader was cut down. An additional changeset dropped a few more variables.
A while later, I wrote about lMS-DOS's single-file load again, describing a novel problem with the dual-file load. At this point I had replicated the kernel preparation from lDebug's mak.sh
script into the kernwrap repo. This allows choosing any of the now 13 compression methods supported by inicomp. Other than this it creates the same edrdos/lmsdos and edrpack/lmspack files as before.
MS-DOS v7 (as bundled with MSWindows 95/4.00 and 98/4.10) uses slightly different msload stages, and its initial loader must have an MZ executable header. It is documented that the MZ header actually encodes a valid MZ executable image, containing a program called MSDCM (Device Configuration Manager). Unlike MS-DOS v6 and (E)DR-DOS, the v7 load already acts as a single-file load, with msdos.sys
repurposed as another configuration text file.
That means it may be possible to strip msload and replace it by iniload (plus another intermediate stage), and have the MZ header still reference the MSDCM executable image. I have little incentive to do this work however. It is uncertain whether this would work well. I seem to recall that the MS-DOS v7 io.sys
kernel file also contains a compressed boot splash logo, and I do not know if this would be accessed correctly if msload was replaced.
MS-DOS v8 (as bundled with MSWindows Me/4.90) is similar to v7, except it compresses the kernel (as in the payload of msload, presumably?) and carries some anti-features to dissuade booting into MS-DOS (sans MSWindows) from a hard disk.