FDOS/kernel

SYS /OEM:W9X /L 0 does not set loadaddr to 0

Opened this issue · 0 comments

An /L 0 parameter to the FreeDOS / EDR-DOS loaders is arguably invalid and should not be supported usually. (A warning should be emitted though, refer to #139 .)

However, /L 0 to the OEM loaders should be valid to patch the far jump to a jmp 70h:0. However, in the following code line an /L parameter of zero is used to indicate a "not initialised" state rather than allowing a literal zero. That means for A:\>sys a: /bootonly /verbose /oem:w9x /l 0 the jump offset will still be set to the default (which is 200h for this /OEM switch), not 0.

Here's where a zero value means uninitialised:

if (!opts->kernel.loadaddr) opts->kernel.loadaddr = bootFiles[opts->flavor].loadaddr;

Here's where the /L switch is parsed:

kernel/sys/sys.c

Lines 696 to 699 in 8552d83

else if (toupper(*argp) == 'L') /* set Load segment */
{
opts->kernel.loadaddr = (WORD)strtol(argv[argno], NULL, 16);
}

Here's where the magic patch occurs for the OEM loader:

kernel/sys/sys.c

Lines 1720 to 1728 in 8552d83

if (fs == FAT12) {
/* magic offset: jmp LOADSEG:xxxxh */
defaultload = *(int *)(&newboot[0x11A]);
*(int *)(&newboot[0x11A]) = opts->kernel.loadaddr;
} else {
/* magic offset: jmp LOADSEG:xxxxh */
defaultload = *(int *)(&newboot[0x118]);
*(int *)(&newboot[0x118]) = opts->kernel.loadaddr;
}

I suggest to add additional boolean variables indicating whether a switch has been used or not, though this only seems to be really needed for the /L switch.