/* * dj64 - 64bit djgpp-compatible tool-chain * Copyright (C) 2021-2024 @stsp * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include "stubinfo.h" #include "plt.h" .include "plt_defs.inc" .bss __plt_open: .quad 0 PLT_OPEN_CMD = 0 PLT_CLOSE_CMD = 1 __plt_call: .quad 0 __plt_ctrl: .quad 0 .global __plt_handle __plt_handle: .long 0 sel: .word 0 SHM_REQ_LEN = 0 SHM_RET_LEN = 4 SHM_HANDLE = 8 SHM_LINEAR = 0xc SHM_NAME = 0x10 SHM_FLAGS = 0x16 SHM_HANDLE2 = 0x18 shm_block: .fill 0x1c, 1, 0 shm_block2: .fill 0x1c, 1, 0 handle: .long 0 maddr: .long 0 SHM_NOEXEC = 1 SHM_EXCL = 2 SHM_NEW_NS = 4 SHM_NS = 8 SHM_FLG_MASK = (SHM_NOEXEC | SHM_EXCL | SHM_NEW_NS | SHM_NS) /* leave bits 4 and 5 reserved */ OPEN_FLG_SHIFT = 6 .data dos_nm: .asciz "MS-DOS" ext_nm: .asciz "DJ64" err_str: .asciz "dj64: load failure\r\n$" .text .macro asmcfunc_n nm,num .global _\nm _\nm: pushl %ebp movl %esp, %ebp pushal movl %esp, %edx movl $\num, %ecx movl $AUX_CORE, %ebx call_plt popal popl %ebp ret .endm .include "plt.inc" uplt_init: pushl __plt_handle pushl __plt_call + 4 pushl __plt_call call *%fs:STUBINFO_UENTRY addl $12, %esp ret .global plt_init plt_init: pushl %es /* check for extender, used for file I/O */ movl $0x168a, %eax movl $dos_nm, %esi int $0x2f jc 2f /* check for DJ64 */ movl $0xa00, %eax movl $ext_nm, %esi int $0x31 jc 2f orb %al, %al jnz 2f movl %es, %eax movl %eax, __plt_open + 4 movl %edi, __plt_open .macro mk_shm b,offs,size,name,err,flg,h2 movl %fs:\size, %ecx orl %ecx, %ecx jz \err xorb %al, %al cmpb %fs:\name, %al je \err movl %ecx, \b + SHM_REQ_LEN movw %fs, \b + SHM_NAME + 4 movl $\name, \b + SHM_NAME movzbw %fs:\flg, %ax andb $SHM_FLG_MASK, %al movw %ax, \b + SHM_FLAGS movl \h2, %eax movl %eax, \b + SHM_HANDLE2 /* alloc mem */ pushw %ds popw %es movl $\b, %edi movl $0xd00, %eax int $0x31 jc \err /* alloc desc */ movl $0, %eax movl $1, %ecx int $0x31 movw %ax, sel /* set base */ movw %ax, %bx movw \b + SHM_LINEAR + 2, %cx movw \b + SHM_LINEAR, %dx movl $7, %eax int $0x31 /* set limit */ movw sel, %bx movw %fs:\size, %dx decw %dx movw %fs:\size + 2, %cx movl $8, %eax int $0x31 /* seek fd */ movl %fs:STUBINFO_SELF_FD, %ebx movzwl %fs:\offs, %edx movzwl %fs:\offs + 2, %ecx movl $0x4200, %eax int $0x21 /* read payload */ pushl %ds movw sel, %ds movl %fs:STUBINFO_SELF_FD, %ebx movl %fs:\size, %ecx movl $0, %edx movl $0x3f00, %eax int $0x21 popl %ds jc 2f /* unmap shm */ movw \b + SHM_LINEAR + 2, %bx movw \b + SHM_LINEAR, %cx movl $0x801, %eax int $0x31 .endm mk_shm shm_block,STUBINFO_PAYLOAD_OFFS,STUBINFO_PAYLOAD_SIZE,STUBINFO_ARGV0,2f,STUBINFO_FLAGS,$0 mk_shm shm_block2,STUBINFO_PAYLOAD2_OFFS,STUBINFO_PAYLOAD2_SIZE,STUBINFO_PAYLOAD2_NAME,5f,STUBINFO_FLAGS+1,shm_block+SHM_HANDLE 5: // now open lib movl $0, %eax movl $PLT_OPEN_CMD, %ebx movw shm_block + SHM_HANDLE, %di movw shm_block + SHM_HANDLE + 2, %si movzbl %fs:STUBINFO_FLAGS, %ecx shrl $OPEN_FLG_SHIFT, %ecx lcalll *__plt_open jc 2f movl %eax, __plt_handle movl %es, %eax movl %eax, __plt_call + 4 movl %edi, __plt_call movl %eax, __plt_ctrl + 4 movl %esi, __plt_ctrl movl %fs:STUBINFO_FLAGS, %ecx testw $0x4080, %cx jnz 111f call uplt_init 111: movl %fs:STUBINFO_SELF_SIZE, %ecx orl %ecx, %ecx jz 3f addl $(4096-1), %ecx andl $~(4096-1), %ecx movl %ecx, %ebx shrl $16, %ebx andl $0xffff, %ecx /* alloc mem */ movl $0x501, %eax int $0x31 jc 2f movw %cx, maddr movw %bx, maddr + 2 movw %di, handle movw %si, handle + 2 /* set base */ movw maddr, %dx movw maddr + 2, %cx movw sel, %bx movl $7, %eax int $0x31 /* set limit */ movw sel, %bx movw %fs:STUBINFO_SELF_SIZE, %dx decw %dx movw %fs:STUBINFO_SELF_SIZE + 2, %cx movl $8, %eax int $0x31 /* seek fd */ movl %fs:STUBINFO_SELF_FD, %ebx movzwl %fs:STUBINFO_SELF_OFFS, %edx movzwl %fs:STUBINFO_SELF_OFFS + 2, %ecx movl $0x4200, %eax int $0x21 /* read payload */ pushl %ds movw sel, %ds movl %fs:STUBINFO_SELF_FD, %ebx movl %fs:STUBINFO_SELF_SIZE, %ecx movl $0, %edx movl $0x3f00, %eax int $0x21 popl %ds jc 2f /* close file */ movl %fs:STUBINFO_SELF_FD, %ebx movl $0x3e00, %eax int $0x21 /* free desc */ movw sel, %bx movl $1, %eax int $0x31 /* call manager */ movl %fs:STUBINFO_FLAGS, %eax movl maddr, %ebx movl %fs:STUBINFO_SELF_SIZE, %ecx movl %fs:STUBINFO_MEM_BASE, %edx call ctrl jc 2f /* free mem */ movl $0x502, %eax movw handle, %di movw handle + 2, %si int $0x31 jc 2f 11: popl %es 1: ret 2: popl %es movl $err_str, %edx movl $0x900, %eax int $0x21 movl $0x4c01, %eax int $0x21 jmp 1b 3: /* close file */ movl %fs:STUBINFO_SELF_FD, %ebx movl $0x3e00, %eax int $0x21 /* call manager */ movl %fs:STUBINFO_FLAGS, %eax movl $0, %ebx movl $0, %ecx movl %fs:STUBINFO_MEM_BASE, %edx call ctrl jc 2b jmp 11b ctrl: pushal movl %esp, %edx movl __plt_handle, %eax movl $0, %ebx movb $AUX_CORE, %bl movb $DL_API_VER, %bh movl $DL_SET_SYMTAB, %ecx movl %cs, %esi lcalll *__plt_ctrl testl %eax, %eax jnz 1f popal clc ret 1: popal stc ret .global plt_done plt_done: // close lib movl __plt_handle, %eax movl $PLT_CLOSE_CMD, %ebx movw shm_block + SHM_HANDLE, %di movw shm_block + SHM_HANDLE + 2, %si lcalll *__plt_open /* free mem */ movl $0xd01, %eax movw shm_block + SHM_HANDLE, %di movw shm_block + SHM_HANDLE + 2, %si int $0x31 /* free mem */ movl $0xd01, %eax movw shm_block2 + SHM_HANDLE, %di movw shm_block2 + SHM_HANDLE + 2, %si int $0x31 ret .bss .global _dosobj_page _dosobj_page: .space 4096