2025-09-20
Fix getfirstumcb in MS-DOS v5 device driver load corrupting ds.
Utility that just passes execution to a different program, but uncapses the entire command line. Needed for using lredir in ldos.ini (INSTALLFIRST=, INSTALLMID=, or INSTALLLAST=) as DOS allcapses the entire configuration contents. lredir needs the exact pathname as it exists on the Linux host system.
First commit is the actual utility. Second adds the MS-DOS v4 license for completeness.
Add to patldos, the lDOS patch program, two new lCFG items:
This didn't help SRDISK find its drive letter because it expected a length of at least 23. However, MS-DOS appears to pass a length excluding the length byte itself.
With this, the length of the init request header grew to 24. SRDISK is happy with that because it is larger than 22.
SRDISK may patch its initial device header to indicate it installs as a character device, and also set the number of units in the request header to 1. It doesn't want us to actually install a drive, and lMS-DOS doesn't install one either. So make it check the flag again.
%.4Fs
format codes in printf with explicit buffers filled using _fmemcpy.times foo db 0
where the db hidden behind times doesn't call our nobits mmacro. This helps shorten both ifsfunc.exe and share.exeI used some scripting using link.txt and listvars.pl to determine which variables ifsfunc.exe links to. ErrMap24 was the only variable that had been moved to DOSCODEGROUP.
tractest$ ./listvars.pl ~/proj/msdos4.hg/hg/src/BIOS/msbio{w.map,.tls} --list-data | perl -e ' my %hash = (); while (<>) { if ($ARGV =~ /\.txt/ and /^(\S+)\s+in\s+/) { $hash{uc($1)} = 1; }; if (not $ARGV =~ /\.txt/ and /Label data \"(\S+)\"/ and defined $hash{uc($1)}) { print } } ' ~/proj/msdos4.hg/hg/src/CMD/IFSFUNC/link.txt -
I also verified that all the other variables match the actual positions in DOSDATA:
perl -e ' my %hash = (); while (<>) { if ($ARGV =~ /\.txt/ and /^(\S+)\s+in\s+/) { $hash{uc($1)} = 1; }; if (not $ARGV =~ /\.txt/ and /^[0-9A-Fa-f]{4}:([0-9A-Fa-f]{4}\s+Res\s+(\S+))/ and defined $hash{uc($2)}) { print "$1\n"; } }' ~/proj/msdos4.hg/hg/src/CMD/IFSFUNC/{link.txt,ifsfuncw.map} > linkadd1.txt perl -e ' my %hash = (); while (<>) { if ($ARGV =~ /\.txt/ and /^(\S+)\s+in\s+/) { $hash{uc($1)} = 1; }; if (not $ARGV =~ /\.txt/ and /^[0-9A-Fa-f]{4}:([0-9A-Fa-f]{4}\s+Res\s+(\S+))/ and defined $hash{uc($2)}) { print "$1\n"; } }' ~/proj/msdos4.hg/hg/src/CMD/IFSFUNC/link.txt ~/proj/msdos4.hg/hg/src/BIOS/msbiow.map > linkadd2.txt sort linkadd1.txt > linkads1.txt sort linkadd2.txt > linkads2.txt diff -u linkads1.txt linkads2.txt
The only different lines are ERRMAP24 and ERRMAP24END which, as mentioned, moved to DOSCODEGROUP. This difference is handled by using ifs_ErrMap24 instead.
rep stosw
or lds
or les
in these spots. The MS-DOS v4 codebase also was missing the latter two sometimes.The need for this feature was listed in a stackoverflow question about NASM + WarpLink usage that I wrote back in 2024 December. It didn't actually turn out relevant for the lDOS kernel, but did eventually crop up again for share.exe and ifsfunc.exe
I'm surprised that my patch for this, after carefully combining disparate parts and then minimal editing to get it to assemble, actually worked on the first attempt. The WarpLink data structures aren't documented well, and use of hardcoded structure offsets is widespread in the code base. I also used the write_bytes with a write length of zero to avoid pulling out all the write code from it, which seems to have simply worked as expected.
(The map file total image size disagrees by 1 paragraph with what ecm LZEXE infoexe says. Probably a rounding problem.)
Some things are still missing, such as checking for disk full conditions on write calls correctly. In some spots WarpLink doesn't check the returned ax from int 21h function 40h at all, in others it only checks the value is nonzero rather than equal to cx.