/* * 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 #include #include #include #include #include #include #include #include #include #include #ifndef PAGE_SIZE #define PAGE_SIZE 4096 #endif #define _PAGE_MASK (~(PAGE_SIZE-1)) /* to align the pointer to the (next) page boundary */ #define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&_PAGE_MASK) // https://github.com/vonj/snippets.org/blob/master/strrpbrk.c static char *strrpbrk(const char *szString, const char *szChars) { const char *p; char *p0, *p1; for (p = szChars, p0 = p1 = NULL; p && *p; ++p) { p1 = strrchr(szString, *p); if (p1 && p1 > p0) p0 = p1; } return p0; } int elfexec(const char *path, int argc, char **argv) { int err, fd, len, errn; const char *p; unsigned fname; __dpmi_paddr api; __dpmi_shminfo shmi; __dpmi_meminfo dm; __dpmi_regs regs; int en_dis = !(_crt0_startup_flags & _CRT0_FLAG_NEARPTR); err = __dpmi_get_vendor_specific_api_entry_point("DJ64", &api); if (err) { fprintf(stderr, "DJ64 support missing\n"); return -1; } memset(®s, 0, sizeof(regs)); regs.d.ebx = 3; // get version pltcall32(®s, api); if (regs.d.eax < 2) { fprintf(stderr, "unsupported DJ64 version %i\n", regs.d.eax); return -1; } fd = open(path, O_RDONLY | O_BINARY); if (fd == -1) { fprintf(stderr, "failed to open %s: %s\n", path, strerror(errno)); return -1; } len = filelength(fd); p = strrpbrk(path, "/\\"); if (!p) p = path; fname = malloc32(strlen(p) + 1); strcpy(DATA_PTR(fname), p); shmi.size_requested = len; shmi.name_offset = fname; shmi.name_selector = _my_ds(); err = __dpmi_allocate_shared_memory(&shmi); free32(fname); if (err) { close(fd); fprintf(stderr, "Can't allocate shmem for %s\n", p); return -1; } if (en_dis) __djgpp_nearptr_enable(); err = read(fd, djaddr2ptr(shmi.address), len); errn = errno; if (en_dis) __djgpp_nearptr_disable(); close(fd); if (err == -1) { fprintf(stderr, "error reading %s: %s\n", path, strerror(errn)); return -1; } if (err != len) { fprintf(stderr, "read returned %i, need %i\n", err, len); return -1; } dm.handle = shmi.handle; dm.address = shmi.address; dm.size = shmi.size; err = __dpmi_free_physical_address_mapping(&dm); assert(!err); memset(®s, 0, sizeof(regs)); regs.d.ebx = 2; // exec regs.x.di = shmi.handle & 0xffff; regs.x.si = shmi.handle >> 16; pltcall32(®s, api); __dpmi_free_shared_memory(shmi.handle); /* returning only 16bit AX allows to distinguish with -1 returns above */ return regs.x.ax; }