From 95ed8ee484ba1ca9f787059cd4e6b427cbba3844 Mon Sep 17 00:00:00 2001 From: tkchia Date: Tue, 23 Aug 2022 14:35:43 +0000 Subject: [PATCH 1/3] 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) From 249e4b90692882e30af2ee105ad8fb4119d443d2 Mon Sep 17 00:00:00 2001 From: tkchia Date: Wed, 24 Aug 2022 10:17:15 +0000 Subject: [PATCH 2/3] plat/msdos386: fix a few more issues with startup and stub code - correctly calculate size of BSS area to clear - make realloc routine set both ds & es to point to new data segment - correctly initialize real mode flags when simulating real mode interrupt via DPMI - other minor fixes --- plat/msdos386/boot.s | 11 +++++------ plat/msdos386/stub.s | 8 +++++++- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/plat/msdos386/boot.s b/plat/msdos386/boot.s index 80a13662b..9e940c253 100644 --- a/plat/msdos386/boot.s +++ b/plat/msdos386/boot.s @@ -43,12 +43,12 @@ begtext: ! Clear BSS. mov edi, begbss - mov ecx, endbss+1 + mov ecx, endbss+3 sub ecx, edi - shr ecx, 1 + shr ecx, 2 xor eax, eax cld - rep stosw + rep stos ! It's now safe to switch stacks. @@ -63,10 +63,9 @@ begtext: o16 mov ax, 0x0000 o16 mov cx, 1 int 0x31 ! allocate LDT + o16 mov (.doshandle), ax mov es, ax - o16 mov bx, ax - o16 mov (.doshandle), bx - mov es, bx + xchg ebx, eax xor ecx, ecx xor edx, edx diff --git a/plat/msdos386/stub.s b/plat/msdos386/stub.s index 6eca1d6a3..184c14a89 100644 --- a/plat/msdos386/stub.s +++ b/plat/msdos386/stub.s @@ -148,6 +148,8 @@ exe_start: mov bx, fs mov dx, (pmemlen+0) mov cx, (pmemlen+2) + sub dx, 1 + sbb cx, 0 mov ax, 0x0008 int 0x31 ! set segment limit @@ -227,7 +229,8 @@ exe_start: ! is running from. This can't happen from inside the 32-bit code itself ! because it might move. ! - ! On entry, ds and ss are ignored. On exit, ds is set to the 32-bit segment. + ! On entry, ds and ss are ignored. On exit, ds and es are set to the + ! 32-bit segment. ! eax: new block size realloc: cseg mov ds, (psegds) @@ -276,6 +279,7 @@ realloc: cli ! atomically switch stacks back mov ss, (dpmi_ss) o32 mov esp, (dpmi_ebp) + mov es, (psegds32) mov ds, (psegds32) sti @@ -321,6 +325,8 @@ interrupt: mov (dpmi_edx), dx mov (dpmi_esi), si mov (dpmi_edi), di + pushf + pop (dpmi_flags) mov ax, (rseg) mov (dpmi_ds), ax mov (dpmi_ss), ax From 15955282f62be2c377643b9ed54165ef684817ed Mon Sep 17 00:00:00 2001 From: tkchia Date: Wed, 24 Aug 2022 15:17:04 +0000 Subject: [PATCH 3/3] plat/msdos386: fix some issues in libsys code - ensure es = ds = ss upon exit of each C runtime function - clear upper 16 bits of ebx before setting them to 0x0021, when invoking interrupt_ptr to simulate a RM int 0x21 - make _sys_exists use the transfer buffer (which it needs) - make _sys_rawread properly handle an end-of-file read (zero bytes read) - make argument to _sys_seterrno short --- after a failed int 0x21 call, only the lower 16 bits of eax hold the MS-DOs error code - _sys_rawlseek accepts only 3 longword arguments, not 4 (the offset is only 1 longword) - other minor fixes --- plat/msdos/libsys/sys_seterrno.c | 2 +- plat/msdos386/libsys/getpid.s | 5 +++-- plat/msdos386/libsys/rename.s | 10 ++++++---- plat/msdos386/libsys/sys_exists.s | 18 +++++++++++++++--- plat/msdos386/libsys/sys_gettime.s | 1 - plat/msdos386/libsys/sys_isopen.s | 3 +-- plat/msdos386/libsys/sys_rawcreat.s | 4 +++- plat/msdos386/libsys/sys_rawlseek.s | 9 +++++---- plat/msdos386/libsys/sys_rawopen.s | 4 +++- plat/msdos386/libsys/sys_rawread.s | 10 +++++++--- plat/msdos386/libsys/sys_rawwrite.s | 4 +++- plat/msdos386/libsys/sys_xret.s | 3 ++- plat/msdos386/libsys/unlink.s | 4 +++- 13 files changed, 52 insertions(+), 25 deletions(-) diff --git a/plat/msdos/libsys/sys_seterrno.c b/plat/msdos/libsys/sys_seterrno.c index b135aea33..54b4e5af0 100644 --- a/plat/msdos/libsys/sys_seterrno.c +++ b/plat/msdos/libsys/sys_seterrno.c @@ -35,7 +35,7 @@ static const signed char err_map[] = * Map an MS-DOS 2+ system error code to an `errno' value and store that in * `errno'. Return a longword -1. */ -long _sys_seterrno(unsigned dos_err) +long _sys_seterrno(unsigned short dos_err) { if (dos_err < sizeof(err_map) / sizeof(err_map[0])) errno = err_map[dos_err]; diff --git a/plat/msdos386/libsys/getpid.s b/plat/msdos386/libsys/getpid.s index d2a250491..fd8706379 100644 --- a/plat/msdos386/libsys/getpid.s +++ b/plat/msdos386/libsys/getpid.s @@ -38,8 +38,9 @@ _getpid: int 0x21 jnc .eur_dos movb ah, 0x51 - int 0x21 + mov ebx, 0x210000 + callf (interrupt_ptr) xchg ebx, eax .eur_dos: - xor edx, edx + movzx eax, ax ret diff --git a/plat/msdos386/libsys/rename.s b/plat/msdos386/libsys/rename.s index 4b43a0d48..cfde5305e 100644 --- a/plat/msdos386/libsys/rename.s +++ b/plat/msdos386/libsys/rename.s @@ -23,9 +23,9 @@ _rename: ! Source filename. mov esi, 4(ebx) - movzx edi, (transfer_buffer_ptr) - mov es, (pmode_ds) - cld + movzx edi, (transfer_buffer_ptr) + mov es, (pmode_ds) + cld 1: lodsb stosb @@ -47,8 +47,10 @@ _rename: o16 mov dx, (transfer_buffer_ptr) o16 mov di, ax movb ah, 0x56 - or ebx, 0x210000 + mov ebx, 0x210000 callf (interrupt_ptr) pop edi pop esi + push ss + pop es jmp .sys_zret diff --git a/plat/msdos386/libsys/sys_exists.s b/plat/msdos386/libsys/sys_exists.s index f57d28b3e..8dc1dc18c 100644 --- a/plat/msdos386/libsys/sys_exists.s +++ b/plat/msdos386/libsys/sys_exists.s @@ -16,10 +16,22 @@ .define __sys_exists __sys_exists: - mov ebx, esp - mov edx, 4(ebx) + push esi + mov esi, 4+4(esp) + movzx edi, (transfer_buffer_ptr) + mov edx, edi + mov es, (pmode_ds) + cld +1: + lodsb + stosb + testb al, al + jnz 1b mov eax, 0x4300 - int 0x21 + mov ebx, 0x210000 + callf (interrupt_ptr) + push ss + pop es sbb eax, eax inc eax ret diff --git a/plat/msdos386/libsys/sys_gettime.s b/plat/msdos386/libsys/sys_gettime.s index 733ad58ac..1d43d5f46 100644 --- a/plat/msdos386/libsys/sys_gettime.s +++ b/plat/msdos386/libsys/sys_gettime.s @@ -16,7 +16,6 @@ .define __sys_gettime __sys_gettime: - int 3 movb ah, 0x2c int 0x21 mov ebx, esp diff --git a/plat/msdos386/libsys/sys_isopen.s b/plat/msdos386/libsys/sys_isopen.s index 5a5fed07c..5f990f1c1 100644 --- a/plat/msdos386/libsys/sys_isopen.s +++ b/plat/msdos386/libsys/sys_isopen.s @@ -17,8 +17,7 @@ .define __sys_isopen __sys_isopen: - mov ebx, esp - mov ebx, 4(bx) + mov ebx, 4(esp) mov eax, 0x4400 int 0x21 sbb eax, eax diff --git a/plat/msdos386/libsys/sys_rawcreat.s b/plat/msdos386/libsys/sys_rawcreat.s index b15df3f4f..ce48d9d7c 100644 --- a/plat/msdos386/libsys/sys_rawcreat.s +++ b/plat/msdos386/libsys/sys_rawcreat.s @@ -36,10 +36,12 @@ __sys_rawcreat: movb ah, 0x3c movzx edx, (transfer_buffer_ptr) movb al, 8(ebx) - or ebx, 0x210000 + mov ebx, 0x210000 callf (interrupt_ptr) pop edi pop esi + push ss + pop es jmp .sys_axret diff --git a/plat/msdos386/libsys/sys_rawlseek.s b/plat/msdos386/libsys/sys_rawlseek.s index c38a1e0b1..8ff4bc1db 100644 --- a/plat/msdos386/libsys/sys_rawlseek.s +++ b/plat/msdos386/libsys/sys_rawlseek.s @@ -18,9 +18,10 @@ __sys_rawlseek: movb ah, 0x42 mov ebx, esp - mov edx, 8(bx) - mov ecx, 12(bx) - movb al, 16(bx) - mov ebx, 4(bx) + mov edx, 8(ebx) + mov ecx, edx + shr ecx, 16 + movb al, 12(ebx) + mov ebx, 4(ebx) int 0x21 jmp .sys_dxaxret diff --git a/plat/msdos386/libsys/sys_rawopen.s b/plat/msdos386/libsys/sys_rawopen.s index bb4ff5acb..3c8f2bf17 100644 --- a/plat/msdos386/libsys/sys_rawopen.s +++ b/plat/msdos386/libsys/sys_rawopen.s @@ -37,9 +37,11 @@ __sys_rawopen: movb ah, 0x3d o16 mov dx, (transfer_buffer_ptr) movb al, 8(ebx) - or ebx, 0x210000 + mov ebx, 0x210000 callf (interrupt_ptr) pop edi pop esi + push ss + pop es jmp .sys_axret diff --git a/plat/msdos386/libsys/sys_rawread.s b/plat/msdos386/libsys/sys_rawread.s index f5b0c1a35..ef71bf915 100644 --- a/plat/msdos386/libsys/sys_rawread.s +++ b/plat/msdos386/libsys/sys_rawread.s @@ -38,8 +38,9 @@ amount_to_read = 4*4 movb ah, 0x3f o16 mov dx, (transfer_buffer_ptr) + movzx esi, dx + mov ebx, 0x210000 o16 mov bx, file_handle(ebp) - or ebx, 0x210000 callf (interrupt_ptr) jnc success @@ -53,9 +54,10 @@ success: ! Copy eax bytes out of the transfer buffer. - push eax + movzx eax, ax mov ecx, eax - movzx esi, (transfer_buffer_ptr) + jcxz exit + push eax mov edi, write_buffer(ebp) mov es, (pmode_ds) cld @@ -69,6 +71,8 @@ success: exit: pop edi pop esi + push ss + pop es leave ret diff --git a/plat/msdos386/libsys/sys_rawwrite.s b/plat/msdos386/libsys/sys_rawwrite.s index 3ac3a7e16..56976b53b 100644 --- a/plat/msdos386/libsys/sys_rawwrite.s +++ b/plat/msdos386/libsys/sys_rawwrite.s @@ -48,8 +48,8 @@ amount_to_write = 4*4 movb ah, 0x40 o16 mov dx, (transfer_buffer_ptr) + mov ebx, 0x210000 o16 mov bx, file_handle(ebp) - or ebx, 0x210000 callf (interrupt_ptr) jnc exit @@ -59,6 +59,8 @@ amount_to_write = 4*4 exit: pop edi pop esi + push ss + pop es leave ret diff --git a/plat/msdos386/libsys/sys_xret.s b/plat/msdos386/libsys/sys_xret.s index 20c2b454b..e9b9017c9 100644 --- a/plat/msdos386/libsys/sys_xret.s +++ b/plat/msdos386/libsys/sys_xret.s @@ -20,7 +20,8 @@ ! code in ax, and return a shortword -1. If the carry flag is clear, just ! return ax as a return value. ! -! .sys_dxaxret: same as .sys_axret, but return -1 or dx:ax as a return value. +! .sys_dxaxret: same as .sys_axret, but return -1 or eax := dx:ax as a +! return value. .extern .sys_zret .extern .sys_axret diff --git a/plat/msdos386/libsys/unlink.s b/plat/msdos386/libsys/unlink.s index 7d023ad48..d2289e3c4 100644 --- a/plat/msdos386/libsys/unlink.s +++ b/plat/msdos386/libsys/unlink.s @@ -34,11 +34,13 @@ _unlink: ! Make the DOS call. - movzx edi, (transfer_buffer_ptr) + mov dx, (transfer_buffer_ptr) movb ah, 0x41 or ebx, 0x210000 callf (interrupt_ptr) pop edi pop esi + push ss + pop es jmp .sys_zret