edrdos icon indicating copy to clipboard operation
edrdos copied to clipboard

Kernel for low memory machines

Open Torinde opened this issue 9 months ago • 42 comments

On 256K - with no config.sys and autoexec.bat uses 58K: Image

On 192K doesn't reach the prompt: Image

Since usage is 58K should it be possible to run on 192K, 128K, 64K (having ~6K free)? And maybe in a restricted version down to 32K and 16K? That version will be useful for some of the bigger sizes as well - to get more free memory.

Ideally, also a true 16K version as well - made to boot from 200h (like QDOS - IBM PC with modified BIOS) instead of the current 7C00h (IBM PC).

As reference: QDOS is claimed to fit in 6 KB RAM (my tests show between 9K and 10K) and MS-DOS 1.00 is claimed to fit in 8 KB (my tests with PC DOS 0.90/1.00/1.10 and MS-DOS 1.25 show between 12K and 15K). Strangely, MS-DOS 1.25 boots at 48K, but not at 32K while PC DOS 1.10 boots at 32K (and has exactly the same memory usage as MS-DOS 1.25) - maybe the problem is similar for SvarDOS at 192K and MS-DOS 1.25 at 32K?

There is PC adaptation of QDOS sources, but without binaries. I asked there if they can compile, but if you can help that's welcome too! For the pure 16K configuration (16K DIP setting and only 16K memory present) the PC adapted QDOS has to be restored to boot from 200h. Would be good to get such MS-DOS 1.25 modification as well.

Related:

  • https://github.com/SvarDOS/bugz/issues/31

Torinde avatar Feb 23 '25 23:02 Torinde

One, but probably not the only reason it is not running with less than 256K RAM, is the initial uncompression and relocation stage of the FreeDOS style EDR kernel.sys, which gets loaded to segment 0x60, uncompresses to segment 0x2000 and then relocates to its "native" segment 0x70.

The kernel can be build uncompressed, and with a boot loader implementing the EDR load protocol can be loaded directly to segment 0x70. This renders the uncompression and relocation step unnecessary, and the code for it is disabled.

The easiest way to achive this would be:

wmake SINGLEFILE=0 COMPRESSED=0

which generates a dual-file DRBIO.SYS, DRDOS.SYS version of the kernel. When this is used with the provided SYS command, and no KERNEL.SYS is in the directory, SYS installs a volume boot record that uses the native EDR boot protocol.

BUT, I do not remember right now what it was, but I think I have found other reasons inside the kernel why it will not work with less than 256K. If you want to go lower, probably another kernel would be more appropriate. As on machines with less than 256K, I doubt that anyone will need FAT32, for example.

One candidate of such a kernel might be @ecm-pushbx derivate of the MS-DOS 4 kernel 1 (I think she now calls it lDOS). I do not know what exactly its minimum requirement is. But chances are that it is lower than that of the EDR kernel.

boeckmann avatar Feb 24 '25 08:02 boeckmann

Thank you! I see you have 1.44M image with dual-file version - it behaves a little bit different from the one above (more intro text and asks for date/time) Image

But it uses 6KB more memory - 192K XT1982: Image Works also with 176K. Doesn't work at 128K.

So, I assume it's also compressed. Can you please point me to a binary versions of the non-compressed kernel? It seems single file non-compressed is the combination requiring the least amount of RAM.

I also got the compressed version (on 360K FDD) working at 176K and 192K:

192K XT1982 - after solving for the BIOS error 131 (messed up hardware config - 16MHz 8088, etc.): Image

256K PC1982 (without Cassette) Image

192K PC1982 (without Cassette) - doesn't reach the prompt (and has BIOS errors: 3055 201) Image It seems these errors are due to bug in the BIOS (but in 86Box both BIOSes give it - maybe the ROM files are wrong) - to DOS it appears as 48K: Image

192K PC1982 with GLaBIOS - RAM is also wrong, 176K, but it works: Image

At 128K - single beep and blinking cursor (XT and PC 1982 BIOS, PC 1982 GLaBIOS)

At 196K MS-DOS 4.01 uses 55K, which is close to SvarDOS's 58K - wouldn't the effort to trim usage be similar? Of course there are also MS-DOS 2.0, 1.25 and QDOS, but I was hoping for variant of a recent one...

Torinde avatar Feb 24 '25 12:02 Torinde

So, I assume it's also compressed. Can you please point me to a binary versions of the non-compressed kernel?

Sure! I uploaded you an image (1.44M) with an uncompressed single-file DRBIO.SYS. The single-file is called DRBIO.SYS (DRDOS.SYS is missing) in this case to make use of the EDR load protocol:

https://nextcloud.iww.rwth-aachen.de/index.php/s/g6Z24qbPrLbmo33

I verified that it works with 256K. Not sure how low you can go with it. Should not be worse than the lowest you did achive until now...

At 196K MS-DOS 4.01 uses 55K, which is close to SvarDOS's 58K - wouldn't the effort to trim usage be similar?

Not necessarly. It depends on how the MS-DOS kernel bootstraps. The EDR kernel moves some things around in memory even after the initial uncompression stage, which makes it require more RAM than its the 80K binary size. If the MS-DOS kernel does this more efficiently, it may work with less RAM.

boeckmann avatar Feb 24 '25 13:02 boeckmann

According to the FreeDOS FAT12 volume boot code, this by itself depends on more than 128K of RAM: https://github.com/FDOS/kernel/blob/5de2eb1aa01b0129b046cf06338453a233c6597b/boot/boot.asm#L32

boeckmann avatar Feb 24 '25 14:02 boeckmann

The memory layout of lDOS upon transfer from drkernpl to msbio currently looks like:

00000h at 0 KiB IVT
00400h at 1 KiB BDA
00500h at 1.25 KiB largely unused 256 bytes
00600h at 1.5 KiB unused 256 bytes (may be overwritten by inicomp/drkernpl)
00700h at 1.75 KiB DOSENTRY (part of msbio remaining at segment 70h, also has some init code discarded later)
019B0h at 6.4 KiB DOSDATA (DOS data segment, later relocated to eg 01220h at 4.5 KiB)
02DA0h at 11.4 KiB SYSINIT (init and config code)
086F0h at 33.7 KiB DOSCODE (DOS code segment)
11ED0h at 71.7 KiB end of msbio.bin

At https://hg.pushbx.org/ecm/msdos4/file/e40c7dc391b7/src/BIOS/msinit.nas#l867 the DOSENTRY init code calls int 12h to get the available memory size. A bit further down you can see it subtracts from that segment 64 + 64 + 1 (>2 KiB) for buffers. (This could probably be shrunk to 528 or even 512 bytes.)

After a transfer to the unrelocated SYSINIT segment, SYSINIT relocates itself and DOSCODE to below the segment calculated by subtracting the 129 paragraphs: https://hg.pushbx.org/ecm/msdos4/file/e40c7dc391b7/src/BIOS/sysinit1.nas#l606 This is done using a forwards rep movsw so the source and destination must not overlap! So it needs 71.7 + some 60.3 + 2 KiB of memory available at this point. (This could be improved.)

After this, the config code allocates a buffer for the entire configuration (ldos.ini or config.sys contents) and a temporary CDS both below its CS (the relocated SYSINIT segment).

Finally the device drivers and system data structures are allocated. This in addition to all devices and data memory needs 36 KiB free in the LMA to relocate DOSCODE to its final position, if there's no UMA nor HMA.

ecm-pushbx avatar Feb 24 '25 14:02 ecm-pushbx

According to the FreeDOS FAT12 volume boot code, this by itself depends on more than 128K of RAM: https://github.com/FDOS/kernel/blob/5de2eb1aa01b0129b046cf06338453a233c6597b/boot/boot.asm#L32

Yes, the FreeDOS loaders unconditionally relocate first thing.

lDOS loaders (which you can use to load ldos.com or lDebug) stay at 07C00h, with the stack below that, and fill the memory from 02000h up to the stack with parts of the load file. (1536 bytes absolutely must be loaded, more is a bonus.) The lDOS initial loader expects 20 KiB to be free above its input stack which means it should work with 64 KiB of memory initially. However, it needs to load the entire load file payload (70+ KiB as per my prior message) and have some space to spare for the 8 KiB sector buffer, 8 KiB FAT buffer, stack, and the initial loader itself. The initial loader can relocate itself down to 00600h to try and fulfil the space needed.

ecm-pushbx avatar Feb 24 '25 14:02 ecm-pushbx

Great, thank you both!

Results so far:

Still, it seems modern kernels may be possible to squeeze into 128K, but not 64K or less. What about 4.0 (128K) or 2.0 (48K) - are those amenable to fitting into less than their current requirements? 1.25 (48K) I assume can be made to work like 1.0 and QDOS (both already supporting 16K+7C00)

Finally, it would be useful to get any DOS in a PC compatible variant except the boot vector to be at "memory-1K" or 3C00 or 200h or another address below 16K or detect it dynamically - for usage with modified BIOS or emulators (for pure 16K or less).

PS. @ecm-pushbx - what's the meaning of the "l" in lDOS, ldebug, etc.?

Torinde avatar Feb 24 '25 16:02 Torinde

Different kernel memory usage ONLY depending if compressed / non-compressed? That does not look right to me, and should be investigated.

boeckmann avatar Feb 24 '25 21:02 boeckmann

PS. @ecm-pushbx - what's the meaning of the "l" in lDOS, ldebug, etc.?

You can read it as "lyn's" as in Evelyn (the "e" in "ecm"), if you like! Or "libre". But that's both not official. I just wanted a letter that's "free". Before it was named lDebug I named the FreeDOS Debug/X fork "NDebug" with the N standing for "Netwide" as in "Netwide Assembler". But NDEBUG is a commonly used define name for C programs and NDOS is also taken already.

The lmacros collection for NASM macros that I created and use a lot originally started out as CMMACROS.MAC, with CM2011.MAC as what would later become the second file now called lmacros2.mac. "cm" being the latter part of "ecm".

As for the readability I admired the fact that "RxDOS" uses a small letter, oft misspelled as "RX-DOS" or the like. (lRxDOS was the first kernel I extensively worked on.) So I also wanted a small letter. The boot startup message for lDOS now explicitly says "Starting small lDOS" lest it be mistaken for a capital "i". And my FreeDOS list/news announcements also generally mention the "small L".

ecm-pushbx avatar Feb 24 '25 21:02 ecm-pushbx

That does not look right to me, and should be investigated.

I hope all details are in the screenshots/link above - I downloaded from various places, maybe not all of them are the same branch.

@ecm-pushbx, fascinating, thanks for sharing!

Torinde avatar Feb 24 '25 21:02 Torinde

I compared the four different flavors (single-file, dual-file, compressed and uncompressed) for their memory consumption. I could not reproduce the 6K difference in memory usage @Torinde encountered. Maybe this resulted from slightly different configurations. I used the following images for my tests: https://github.com/SvarDOS/edrdos/actions/runs/13357828232. I replaced the compressed kernels with their matching uncompressed ones, which I built from the same Git revision. All sizes reported by MEM were within a few dozen bytes, as expected.

Squeezing the EDR kernel into 128K might be possible, but as there are some other components involved that had to be adjusted for this (at least the VBR), I will not invest any time in implementing this. However, if someone provides patches for it, I will happily integrate them.

boeckmann avatar Feb 26 '25 13:02 boeckmann

Squeezing the EDR kernel into 128K might be possible, but as there are some other components involved that had to be adjusted for this (at least the VBR), I will not invest any time in implementing this. However, if someone provides patches for it, I will happily integrate them.

lDOS flavour of the EDR-DOS kernel (edrdos.com) can be loaded using lDOS loaders, which as mentioned can operate with 128 KiB.

ecm-pushbx avatar Feb 26 '25 13:02 ecm-pushbx

Also, the lDOS boot loaders can be built with -D_COMPAT_FREEDOS to imitate the FreeDOS load protocol. They'll still use int 12h to determine the memory size rather than use the hardcoded relocation like the original FreeDOS loaders. This may allow them to work on 128 KiB machines too. Unfortunately you have to disable some of the other build options to produce a FreeDOS-compatible lDOS boot loader.

ecm-pushbx avatar Feb 26 '25 14:02 ecm-pushbx

Unfortunately you have to disable some of the other build options to produce a FreeDOS-compatible lDOS boot loader.

This is because of the size of the loader not fitting into the sector if you enable both the FreeDOS compatibility and all other default-on options.

ecm-pushbx avatar Feb 26 '25 14:02 ecm-pushbx

I replaced the compressed kernels with their matching uncompressed ones

@boeckmann, can you please post the resulting binaries?

@ecm-pushbx, can I download latest lDOS flavour of EDR-DOS somewhere? But I assume you don't have -D_COMPAT_FREEDOS release anyway.

Of course, it's better to get versed into compiling those myself, but that can take a while...

128K would cover all configurations from PC/XT onwards and matches MS-DOS 4.0. 64K I understand is not possible, but would've been relevant as then basically all PC compatible models are covered (e.g. including the earliest IBM PC with maximum memory). Unfortunate, as I see usage after booting is 6K below 64K... gave me hopes.

Torinde avatar Feb 27 '25 09:02 Torinde

@Torinde the uncompressed kernels reside in the files edrdos 8.img (dual-file) and edrdos 9.img (single-file) from following link: https://nextcloud.iww.rwth-aachen.de/index.php/s/eWYWWRzd2q4YeS2

The compressed are the ones are from: https://github.com/SvarDOS/edrdos/actions/runs/13357828232

boeckmann avatar Feb 27 '25 09:02 boeckmann

@ecm-pushbx, can I download latest lDOS flavour of EDR-DOS somewhere?

https://pushbx.org/ecm/download/edrdos.zip - the kernel files are in the bin subdirectory. All of them are single-file kernels, that is you only need any one single file of all of them. The edrpack files are compressed (which is at best neutral and could be worse for low-memory machines), edrdos are not. The .com files are lDOS iniload files and can thus boot as MS-DOS io.sys, IBM-DOS ibmbio.com, lDOS ldos.com, or FreeDOS kernel.sys (among more). The .sys files must be loaded as FreeDOS kernel.sys or EDR-DOS drbio.sys, trying to load them with an lDOS loader results in a "check 'V'alue error".

But I assume you don't have -D_COMPAT_FREEDOS release anyway.

There's no releases of the boot loaders other than in the instsect.com file shipped with lDebug (lDOS loader defaulting to loading ldebug.com), but it isn't difficult to build them with the debugger's makinst.sh script.

I didn't test these builds but https://pushbx.org/ecm/test/20250227/ has two different builds of instsect.com which are built with either FreeDOS compatibility (default name kernel.sys albeit you can override it with eg /F=edrdos.com) or with lDOS compatibility but the default name edrdos.com to load the uncompressed lDOS flavour, lDOS iniload wrapped kernel.

As mentioned the FreeDOS files need to disable some options, I went for -D_RPL=0 -D_RPL_GRACE_AREA=0 -D_LBA=0 in this case. RPL is usually not needed, the grace area otherwise used with -D_RPL=0 would defeat the purpose of loading in a memory constricted machine, and LBA isn't needed for loading off diskette drives.

Reviewing this I found that even with the RPL grace area set to zero, the subtraction in https://hg.pushbx.org/ecm/ldosboot/file/fb07dd3288a4/boot.asm#l1615 is for more than 64 KiB (20 KiB lDOS reserved, 8 KiB FAT sector buffer, 8 KiB to align the FAT sector buffer, nearly 32 KiB for addressing the stack with 7C00h) so it may fail on a 128 KiB machine. If so it may cause an "Out of 'M'emory" error (the letter 'M' displayed) if you try to boot it.

Of course, it's better to get versed into compiling those myself, but that can take a while...

lDOS flavour EDR-DOS builds with just NASM, WarpLink, x2b2, convlist.pl (from repo tractest), and some tools that can be built using gcc ia16 (or another C compiler). The scripts in the lDOS EDR-DOS repo do have to run in a DOS environment, eg in dosemu2 on Linux. The lDOS boot loaders only need NASM and bash to build IIRC.

ecm-pushbx avatar Feb 27 '25 10:02 ecm-pushbx

Oh, I forgot that you want to load the SvarDOS flavour kernel at 00700h to avoid the relocation needed otherwise (when loading at 00600h). Unfortunately, just building instsect's loaders with a different name and load address will be likely to cause an error 9 (data boundary error) when crossing a 64 KiB boundary, which the diskette ISA DMA cannot deal with. The lDOS iniload has code to handle this, lDOS boot.asm does not.

You may want to work around this a different way. Place the kernel file to load at 00700h (ie old EDR-DOS compatible load protocol) in drbio.sys and assemble this file with NASM:

; Public Domain

	cpu 8086
	org 0
start:
	mov ax, cs
	add ax, 10h
	push ax
	xor ax, ax
	push ax
	retf

	times 256 - ($ - $$) int3

payload:
	incbin "drbio.sys"

The result of this must be loaded as kernel.sys at address 00600h and will transfer control to the payload at cs + 10h:0. That means the FreeDOS loader works without the risk of causing the DMA boundary error (as 00600h is aligned on a 512-byte boundary) but the SvarDOS flavour kernel is loaded to 00700h and entered at 70h:0, so that it needn't be relocated.

ecm-pushbx avatar Feb 27 '25 12:02 ecm-pushbx

After start: you should also insert mov dl, bl in the wrapper I posted in my last comment. EDR-DOS load expects the load unit in DL, but FreeDOS load may or may not put it there.

ecm-pushbx avatar Feb 27 '25 13:02 ecm-pushbx

@boeckmann, thanks! With all 4 of your latest files I get 64K usage. With the SvarDOS from Jan 2025 I get 58K usage, so it seems some of the last changes increased the memory usage.

@ecm-pushbx, following your instructions I got a bootable image with uncompressed kernel and FreeDOS loader - result is 58K: Image

Boots at 176K. At 128K almost gets to the prompt, but stops at blinking cursor: Image

I don't know yet how to compile myself, so I can't follow your second instructions about 700h. If you make a binary that you think it's worth to try at 128K or 64K - please let me know.

Torinde avatar Feb 27 '25 14:02 Torinde

@ecm-pushbx, following your instructions I got a bootable image with uncompressed kernel and FreeDOS loader - result is 58K: Image

Boots at 176K. At 128K almost gets to the prompt, but stops at blinking cursor: Image

Is this the lDOS flavour or a SvarDOS flavour?

I don't know yet how to compile myself, so I can't follow your second instructions about 700h. If you make a binary that you think it's worth to try at 128K or 64K - please let me know.

If it boots that far then likely the 00700h load isn't needed. But if you do want to try it, assembling (not compiling) https://pushbx.org/ecm/test/20250227/drbio2fd.asm is as easy as putting this file and drbio.sys in a directory and running nasm drbio2fd.asm -o kernel.sys

ecm-pushbx avatar Feb 27 '25 14:02 ecm-pushbx

Oh I can see in your screenshots that it's the lDOS flavour. You don't need a FreeDOS loader for that, just use the lDOS loader.

ecm-pushbx avatar Feb 27 '25 14:02 ecm-pushbx

@boeckmann, thanks! With all 4 of your latest files I get 64K usage. With the SvarDOS from Jan 2025 I get 58K usage, so it seems some of the last changes increased the memory usage.

@Torinde this should be completely different system configurations. The SvarDOS image you compare with uses SvarCOM as command interpreter, for example. My images from the actions page and the ones I uploaded to my nextcloud only use EDR components: kernel and command.com.

boeckmann avatar Feb 27 '25 15:02 boeckmann

this should be completely different system configurations.

Clear, SvarCOM is using less memory.

@ecm-pushbx, with lDOS loader I don't seem to be able to boot at 128K either (but maybe I did mess up something).

Torinde avatar Mar 10 '25 16:03 Torinde

Current lDOS seems to work fine after I r word [0:413] = #128 (loaded using lDebug's lDOS loader).

ecm-pushbx avatar Mar 30 '25 17:03 ecm-pushbx

I recently changed it so the initial relocation of SYSINIT + DOSCODE + DOSDATA is done using movp so it can overlap source and destination, and it's done by the DOSENTRY section's init code and the relocation code overwriting itself would be detected and cause an error.

ecm-pushbx avatar Mar 30 '25 18:03 ecm-pushbx

This code seems to be the first problem: https://hg.pushbx.org/ecm/edrdos/file/6c174e5361fb/drbio/biosinit.nas#l245

	mov	ax,[mem_size]		; get top of memory
	sub	ax,MOVE_DOWN
	mov	[mem_max],ax		; last available paragraph

The equate is defined here: https://hg.pushbx.org/ecm/edrdos/file/6c174e5361fb/drbio/config.mac#l55

MOVE_DOWN	equ	1800h		; start relocated code 96K down

This results in word [mem_max] = 800h (32 KiB) which is below the segment A05h at which the drdos module is loaded by drkernpl. I believe this may cause the crash at https://hg.pushbx.org/ecm/edrdos/file/6c174e5361fb/drbio/biosinit.nas#l491 where it jumps to code that's all-zeroes.

ecm-pushbx avatar Mar 30 '25 18:03 ecm-pushbx

https://hg.pushbx.org/ecm/edrdos/file/6c174e5361fb/drbio/biosinit.nas#l270 this seems to corrupt the drdos image already, with that image at A05h:0 length 8FE0h, the rep movsb copying from 70h:2080h length 2E40h to 991h:2080h length 2E40h.

-h linear es:2080
B990  decimal: 47504
-h linear es:2080+2E40
E7D0  decimal: 59344
-h linear A05:0
A050  decimal: 41040
-h linear A05:0+8FE0
00013030  decimal: 77872
-

ecm-pushbx avatar Mar 30 '25 18:03 ecm-pushbx

Now with a patch: https://pushbx.org/ecm/test/20250330-edrdos-early-low-memory.diff

diff --git a/drbio/biosinit.nas b/drbio/biosinit.nas
--- a/drbio/biosinit.nas
+++ b/drbio/biosinit.nas
@@ -260,6 +260,28 @@
 	 jz	biosinit30		; if ROMed we have nothing to relocate
 	mov	[rcode_seg],ax		; relocated BIOS lives here
 	add	ax,dx			; remember how much we allocated
+
+%ifn SVARDOS
+	push ds
+	mov cx, [drdoslen]
+	mov bx, [drdosseg]
+	mov ds, bx
+	xor si, si
+	mov es, ax
+	xor di, di
+	cmp ax, bx	; cmp es, ds
+	jb .forward
+	mov si, cx
+	mov di, cx
+	std
+	cmpsb
+.forward:
+	rep movsb
+	cld
+	pop ds
+	mov cl, 4
+%endif	; SVARDOS
+
 	mov	dx,[rcode_offset]
 	mov	si,dx
 	mov	di,dx
@@ -293,16 +315,7 @@
 	rep	movsw			; move it
 	pop	ds
  %endif	; SINGLEFILE
-%else	; SVARDOS
-	push ds
-	mov cx, [drdoslen]
-	mov ds, [drdosseg]
-	xor si, si
-	mov es, ax
-	xor di, di
-	rep movsb
-	pop ds
-%endif	; SVARDOS
+%endif ; SVARDOS
 
 	mov	ax,offset biosinit_end+32
 	mov	cl,4			; Leave the Last Paragraph Free for

I get up to https://hg.pushbx.org/ecm/edrdos/file/6c174e5361fb/drbio/biosinit.nas#l1079 which calls with AX = 1AAh (6.6 KiB) the function alloc_seg https://hg.pushbx.org/ecm/edrdos/file/6c174e5361fb/drbio/biosinit.nas#l1698 which has word [mem_max] = 639h (24.8 KiB) and word [mem_current] = 499h (18.3 KiB). This fails as there is not enough memory on this heap. Unfortunately it doesn't even display an error message, halting in a loop at https://hg.pushbx.org/ecm/edrdos/file/6c174e5361fb/drbio/biosinit.nas#l1731 which is even entered with Disabled Interrupts, preventing the debugger from breaking out of this loop using a timer.

In any case there is an early memory corruption that seems to be fixed by the patch that relocates drdos first, then part of biosinit, and the patched kernel appears to run fine with more memory too. However, the heap of memory allocatable for DOS DS relocation is too small. mem_max starts out as 32 KiB but obviously it ends up smaller than that by the time we want to relocate DOS DS as I listed.

ecm-pushbx avatar Mar 30 '25 19:03 ecm-pushbx

mem_max is decreased in https://hg.pushbx.org/ecm/edrdos/file/6c174e5361fb/drbio/biosinit.nas#l456 for DPBs and in https://hg.pushbx.org/ecm/edrdos/file/6c174e5361fb/drbio/biosinit.nas#l402 for the initial DOS DS (pre-relocation).

ecm-pushbx avatar Mar 30 '25 19:03 ecm-pushbx