From 95ed8ee484ba1ca9f787059cd4e6b427cbba3844 Mon Sep 17 00:00:00 2001 From: tkchia Date: Tue, 23 Aug 2022 14:35:43 +0000 Subject: [PATCH] plat/msdos386: fix startup code so that it works under dosemu2 - do not try to store data through code segment selectors - set each segment limit to segment size - 1, not segment size - get PSP segment while still in real/V86 mode (DPMI host might choose to return PM selector for int 0x21, ah = 0x62) - other minor fixes --- plat/msdos386/boot.s | 28 ++++++++++++++-------------- plat/msdos386/stub.s | 39 ++++++++++++++++++++++----------------- 2 files changed, 36 insertions(+), 31 deletions(-) diff --git a/plat/msdos386/boot.s b/plat/msdos386/boot.s index 6e1b02add..80a13662b 100644 --- a/plat/msdos386/boot.s +++ b/plat/msdos386/boot.s @@ -21,23 +21,24 @@ begtext: ! ax: pmode code segment of stub ! bx: pmode data segment of stub ! cx: rmode segment of stub - ! dx: pointer to realloc routine (in stub)e + ! dx: pointer to realloc routine (in stub) ! si: pointer to interrupt routine (in stub) ! di: pointer to transfer buffer (in stub) + ! bp: rmode PSP segment ! Resize the segment to include the BSS. - o16 cseg mov (realloc_ptr+4), ax - cseg mov (realloc_ptr+0), edx - cseg o16 mov (pmode_cs), ax - cseg o16 mov (pmode_ds), bx - cseg o16 mov (rmode), cx - cseg o16 mov (interrupt_ptr+4), ax - cseg mov (interrupt_ptr+0), esi - cseg o16 mov (transfer_buffer_ptr), di + o16 mov (realloc_ptr+4), ax + mov (realloc_ptr+0), edx + o16 mov (pmode_cs), ax + o16 mov (pmode_ds), bx + o16 mov (rmode), cx + o16 mov (interrupt_ptr+4), ax + mov (interrupt_ptr+0), esi + o16 mov (transfer_buffer_ptr), di mov eax, __end - cseg callf (realloc_ptr) + callf (realloc_ptr) ! Clear BSS. @@ -71,7 +72,8 @@ begtext: xor edx, edx o16 mov ax, 0x0007 int 0x31 ! set base address to 0 - o16 mov cx, 0x0010 + o16 dec dx + o16 mov cx, 0x000f o16 mov ax, 0x0008 int 0x31 ! set limit to 1MB @@ -84,9 +86,7 @@ begtext: ! Locate the PSP. - movb ah, 0x62 - int 0x21 - movzx esi, bx + movzx esi, bp shl esi, 4 ! convert to linear address ! Copy the whole thing into 32-bit memory. diff --git a/plat/msdos386/stub.s b/plat/msdos386/stub.s index 219d66470..6eca1d6a3 100644 --- a/plat/msdos386/stub.s +++ b/plat/msdos386/stub.s @@ -127,7 +127,7 @@ exe_start: mov cx, 1 int 0x31 ! allocate LDT jc bad_dpmi - mov es, ax + mov fs, ax mov (psegcs32), ax mov cx, (pmemlen+0) @@ -140,12 +140,12 @@ exe_start: mov dx, cx mov cx, bx - mov bx, es + mov bx, fs mov ax, 0x0007 int 0x31 ! set segment base address jc bad_dpmi - mov bx, es + mov bx, fs mov dx, (pmemlen+0) mov cx, (pmemlen+2) mov ax, 0x0008 @@ -155,23 +155,23 @@ exe_start: and cx, 3 shl cx, 5 or cx, 0xc09b ! 32-bit, big, code, non-conforming, readable - mov bx, es + mov bx, fs mov ax, 0x0009 int 0x31 ! set descriptor access rights ! Allocate the data segment (as a simple clone of the code segment). (10e) mov ax, 0x000a - mov bx, es + mov bx, fs int 0x31 - mov fs, ax + mov es, ax mov (psegds32), ax mov cx, ax and cx, 3 shl cx, 5 or cx, 0xc093 ! 32-bit, big, data, r/w, expand-up - mov bx, fs + mov bx, es mov ax, 0x0009 int 0x31 ! set descriptor access rights @@ -198,7 +198,7 @@ exe_start: o32 movzx ecx, ax ! number of bytes read o32 mov esi, transfer_buffer cld - o32 rep movsb + rep a32 movsb jmp 1b 2: @@ -216,9 +216,10 @@ exe_start: o32 mov edx, realloc o32 mov esi, interruptf o32 mov edi, transfer_buffer + o32 movzx ebp, (pspseg) push es pop ds - push es + push fs push 0 retf ! 19b @@ -253,19 +254,21 @@ realloc: mov (pmemaddr+0), cx mov (pmemaddr+2), bx - mov bx, (psegds32) - mov dx, (pmemlen+0) - mov cx, (pmemlen+2) - mov ax, 0x0008 - int 0x31 ! set ds segment limit - jc bad_dpmi + mov bx, (psegcs32) mov dx, (pmemaddr+0) mov cx, (pmemaddr+2) mov ax, 0x0007 + int 0x31 ! set cs linear address + jc bad_dpmi + mov bx, (psegds32) int 0x31 ! set ds linear address jc bad_dpmi - mov bx, (psegcs32) - int 0x31 ! set cs linear address + mov dx, (pmemlen+0) + mov cx, (pmemlen+2) + sub dx, 1 + sbb cx, 0 + mov ax, 0x0008 + int 0x31 ! set ds segment limit jc bad_dpmi popa @@ -308,6 +311,7 @@ exit_with_error: ! Simulate DOS interrupt. int21: + o32 movzx ebx, bx o32 or ebx, 0x210000 ! Simulate interrupt in the high half of ebx. interrupt: @@ -327,6 +331,7 @@ interrupt: o32 mov edi, dpmi_edi mov ax, 0x300 o32 shr ebx, 16 + xor cx, cx int 0x31 ! simulate DOS interrupt pop es o32 movzx eax, (dpmi_eax)