/*
* 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