Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

On lDOS (lMS-DOS) LH leads to "MCB chain corrupt, or MS-DOS incompatible system." #166

Open
ecm-pushbx opened this issue Feb 17, 2025 · 3 comments

Comments

@ecm-pushbx
Copy link
Contributor

The message "MCB chain corrupt, or MS-DOS incompatible system." is displayed on attempts to use LH on a recent lDOS kernel.

With this patch it works:

diff --git a/shell/loadhigh.c b/shell/loadhigh.c
index 81340ec..49d4c37 100644
--- a/shell/loadhigh.c
+++ b/shell/loadhigh.c
@@ -422,7 +422,7 @@ static int loadhigh_prepare(void)
 
   /* Set the UMB link and malloc strategy */
   dosSetUMBLinkState(1);
-  dosSetAllocStrategy(0);
+  dosSetAllocStrategy(0x80);
 
   if ((availBlock = malloc(256 * sizeof(*availBlock))) == 0)
     return err_out_of_memory;
@@ -462,8 +462,10 @@ static int loadhigh_prepare(void)
         /* Found a free memory block: allocate it */
         word bl = DosAlloc(mcb->mcb_size);
 
-        if (bl != FP_SEG(mcb) + 1)  /* Did we get the block we wanted? */
+        if (bl != FP_SEG(mcb) + 1)  /* Did we get the block we wanted? */ {
+          printf("bl = %04X, mcb = %04X\n", bl, FP_SEG(mcb));
           return err_mcb_chain;
+        }
 
         if (region->access)		/* /L option allows access to this region */
         {
@@ -540,6 +542,7 @@ static int loadfix_prepare(void)
 
       if (bl != FP_SEG(mcb) + 1)  /* Did we get the block we wanted? */
       	{
+          printf("bl = %04X, mcb = %04X\n", bl, FP_SEG(mcb));
         return err_mcb_chain;
         }
 

Without the line 422 hunk the debug message that I added to loadhigh_prepare (line 462 hunk) is displayed so that seems to be where the error code is generated.

I don't see how with a strategy of 0 ("LMA then UMA, as one area") the allocation should occur in the UMA first as this code expects. I will have to study the FreeDOS kernel to see whether it behaves differently.

@ecm-pushbx
Copy link
Contributor Author

With this patch:

diff --git a/shell/loadhigh.c b/shell/loadhigh.c
index 81340ec..65223e1 100644
--- a/shell/loadhigh.c
+++ b/shell/loadhigh.c
@@ -422,6 +422,7 @@ static int loadhigh_prepare(void)
 
   /* Set the UMB link and malloc strategy */
   dosSetUMBLinkState(1);
+  /* dosSetAllocStrategy(0x80); */
   dosSetAllocStrategy(0);
 
   if ((availBlock = malloc(256 * sizeof(*availBlock))) == 0)
@@ -462,8 +463,12 @@ static int loadhigh_prepare(void)
         /* Found a free memory block: allocate it */
         word bl = DosAlloc(mcb->mcb_size);
 
-        if (bl != FP_SEG(mcb) + 1)  /* Did we get the block we wanted? */
+        printf("bl = %04X, mcb = %04X, strat = %04X\n",
+          bl, FP_SEG(mcb), (int)dosGetAllocStrategy());
+        if (bl != FP_SEG(mcb) + 1)  /* Did we get the block we wanted? */ {
+          printf("Error unexpected allocation!\n", bl, FP_SEG(mcb));
           return err_mcb_chain;
+        }
 
         if (region->access)		/* /L option allows access to this region */
         {
@@ -540,6 +545,7 @@ static int loadfix_prepare(void)
 
       if (bl != FP_SEG(mcb) + 1)  /* Did we get the block we wanted? */
       	{
+          printf("bl = %04X, mcb = %04X\n", bl, FP_SEG(mcb));
         return err_mcb_chain;
         }
 

On FreeDOS we get:

C:\>lh tsr.com
bl = 02C3, mcb = 02C2, strat = 0000
bl = B11C, mcb = B11B, strat = 0000
bl = C1FB, mcb = C1FA, strat = 0000
bl = F001, mcb = F000, strat = 0000

On lDOS we get:

C:\>lh tsr.com
bl = 0283, mcb = B230, strat = 0000
Error unexpected allocation!
MCB chain corrupt, or MS-DOS incompatible system.

Also, the memory allocated (at segment 283h) seems to leak.

@ecm-pushbx
Copy link
Contributor Author

The && mcb->mcb_size > 0 condition in this line is the culprit:

freecom/shell/loadhigh.c

Lines 456 to 458 in 20e61b5

for (mcbAssign(mcb, region->start)
; FP_SEG(mcb) < region->end && mcb->mcb_type == 'M' && mcb->mcb_size > 0
; mcbNext(mcb))

In the current lDOS, with things loaded into the HMA or UMA, the only parts remaining in the LMA are:

  • IVT, BDA, DOSENTRY, DOSDATA (all before the first MCB)
  • UPBs, DPBs (both in an lDOS style S MCB rather than an SD MCB)
  • The empty SD / devmark MCB (size of memory block = 0)

This last one causes FreeCOM to skip the region in the condition I referenced. MEM also has a problem with this: https://gitlab.com/FreeDOS/base/mem/-/merge_requests/1

@ecm-pushbx
Copy link
Contributor Author

ecm-pushbx commented Feb 18, 2025

Another problem: allocatedBlocks isn't checked for an array overflow of array blocks. It seems that blocks is allocated for 256 entries:

freecom/shell/loadhigh.c

Lines 156 to 158 in 20e61b5

/* Allocate dynamic memory for some arrays */
if ((block = malloc(256 * sizeof(*block))) == 0)
return err_out_of_memory;
After that if there are more than 256 blocks to reserve, the array will overflow.

ecm-pushbx added a commit to ecm-pushbx/freecom that referenced this issue Feb 18, 2025
PerditionC pushed a commit that referenced this issue Feb 18, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant