mirror of
https://github.com/fincs/FeOS.git
synced 2025-06-19 03:25:33 -04:00
698 lines
14 KiB
C
698 lines
14 KiB
C
#include "feos.h"
|
|
#include "loader.h"
|
|
#include "feosfifo.h"
|
|
#include "thread.h"
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
#include <time.h>
|
|
#include <errno.h>
|
|
|
|
#include <malloc.h>
|
|
#include <sys/statvfs.h>
|
|
#include <sys/stat.h>
|
|
#include <unistd.h>
|
|
#include <dirent.h>
|
|
#include <fcntl.h>
|
|
|
|
static inline int _fileno_helper(FILE* f) { return fileno(f); }
|
|
|
|
void* LdrFindSymbol(module_t hMod, const char* sym)
|
|
{
|
|
CHK_HMOD(hMod);
|
|
return LdrFindInTbl(&GetRuntimeData(hMod)->exp, sym);
|
|
}
|
|
|
|
int __aeabi_idiv(int, int);
|
|
int __aeabi_idivmod(int, int);
|
|
unsigned int __aeabi_uidiv(unsigned int, unsigned int);
|
|
unsigned int __aeabi_uidivmod(unsigned int, unsigned int);
|
|
|
|
long long __aeabi_ldivmod(long long, long long);
|
|
unsigned long long __aeabi_uldivmod(unsigned long long, unsigned long long);
|
|
|
|
void DC_DrainWriteBuffer();
|
|
void KeWaitForMemAddr(volatile byte_t*, byte_t);
|
|
|
|
void KeSetExcptHandler(void*);
|
|
|
|
// Execution status functions
|
|
|
|
typedef int (* systemfunc_t)(const char* command);
|
|
|
|
systemfunc_t __system;
|
|
|
|
int system(const char* command)
|
|
{
|
|
if (command == NULL) return !!__system;
|
|
return __system(command);
|
|
}
|
|
|
|
const char* LdrGetModuleName(module_t hMod)
|
|
{
|
|
CHK_HMOD(hMod);
|
|
return GetRuntimeData(hMod)->name;
|
|
}
|
|
|
|
module_t LdrGetModule(const char* name)
|
|
{
|
|
sassert(name, ERRSTR_INVALIDPARAM);
|
|
fxe_runtime_header* rh = LdrModuleListFind(name);
|
|
return rh ? rh->hThis : NULL;
|
|
}
|
|
|
|
// Memory/disk usage functions
|
|
|
|
typedef struct
|
|
{
|
|
word_t total, free, used;
|
|
} usagestats_t;
|
|
|
|
typedef struct
|
|
{
|
|
u64 total, free, used;
|
|
} usagestats64_t;
|
|
|
|
bool KeGetDiskStats(usagestats64_t* pStats)
|
|
{
|
|
struct statvfs fiData;
|
|
if (pStats && statvfs("/", &fiData) >= 0)
|
|
{
|
|
pStats->total = (u64)fiData.f_frsize * fiData.f_blocks;
|
|
pStats->free = (u64)fiData.f_bsize * fiData.f_bfree;
|
|
pStats->used = pStats->total - pStats->free;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void KeGetMemStats(usagestats_t* pStats)
|
|
{
|
|
if (!pStats) return;
|
|
|
|
u8 *heapLimit = getHeapLimit(), *heapStart = getHeapStart(), *heapEnd = getHeapEnd();
|
|
struct mallinfo mi = mallinfo();
|
|
pStats->total = ((u32)(heapLimit - heapStart) + (BIT(20)-1)) &~ (BIT(20)-1); // MB-align the size
|
|
pStats->free = mi.fordblks + (heapLimit - heapEnd);
|
|
pStats->used = pStats->total - pStats->free;
|
|
}
|
|
|
|
int KeGetTickCount()
|
|
{
|
|
extern volatile int vblankCounter;
|
|
return vblankCounter;
|
|
}
|
|
|
|
int KeGetOSVersion()
|
|
{
|
|
return FEOS_VERSION_PACK;
|
|
}
|
|
|
|
static systeminfo_t sysInfo =
|
|
{
|
|
FEOS_VERSION_PACK,
|
|
FEOS_VERSION_TEXT,
|
|
#ifndef DEBUG
|
|
0,
|
|
#else
|
|
SYSTEM_FLAGS_DEBUG,
|
|
#endif
|
|
SYSTEM_TYPE_DS,
|
|
NULL,
|
|
SYSTEM_MODE_DS,
|
|
NULL,
|
|
};
|
|
|
|
void KeInitSystemInfo()
|
|
{
|
|
extern bool __dsimode;
|
|
|
|
#define SYSTYPE sysInfo.systemType
|
|
#define SYSFLAGS sysInfo.systemFlags
|
|
|
|
// DSi mode detection
|
|
if (__dsimode)
|
|
{
|
|
sysInfo.systemMode = SYSTEM_MODE_DSi;
|
|
sysInfo.systemType = SYSTEM_TYPE_DSi;
|
|
}
|
|
|
|
byte_t fw1D, fw2F, pm4;
|
|
// Retrieve some bits from ARM7
|
|
{
|
|
FeOSFifoMsg msg;
|
|
msg.type = FEOS_ARM7_GET_SYSTEM_INFO;
|
|
|
|
fifoSendDatamsg(FIFO_FEOS, sizeof(msg), (void*) &msg);
|
|
while (!fifoCheckValue32(FIFO_FEOS));
|
|
|
|
word_t ret = fifoGetValue32(FIFO_FEOS);
|
|
fw1D = ret;
|
|
fw2F = ret >> 8;
|
|
pm4 = ret >> 16;
|
|
}
|
|
|
|
// Detect system type
|
|
// Based on http://adshomebrewersdiary.blogspot.com.es/2012/01/telling-ds-models-apart.html
|
|
|
|
if (SYSTYPE == SYSTEM_TYPE_DS) do
|
|
{
|
|
if (swiIsDebugger())
|
|
{
|
|
SYSTYPE = SYSTEM_TYPE_DSDebug;
|
|
break;
|
|
}
|
|
|
|
if (pm4 & 0x80)
|
|
{
|
|
SYSTYPE = SYSTEM_TYPE_DSLite;
|
|
break;
|
|
}
|
|
|
|
if (fw1D != 0xFF && fw1D & 3)
|
|
SYSFLAGS |= SYSTEM_FLAGS_CHINESE;
|
|
} while(0);
|
|
|
|
if (SYSTYPE == SYSTEM_TYPE_DSLite) do
|
|
{
|
|
if (fw1D & 4)
|
|
{
|
|
SYSTYPE = SYSTEM_TYPE_DSi;
|
|
break;
|
|
}
|
|
|
|
if (fw1D & 3)
|
|
SYSFLAGS |= SYSTEM_FLAGS_CHINESE;
|
|
} while(0);
|
|
|
|
if (SYSTYPE == SYSTEM_TYPE_DSi) do
|
|
{
|
|
if (fw2F >= 0x18)
|
|
{
|
|
SYSTYPE = SYSTEM_TYPE_DSi_XL;
|
|
break;
|
|
}
|
|
|
|
// TODO: chinese DSi detection
|
|
} while(0);
|
|
|
|
if (SYSTYPE == SYSTEM_TYPE_DSi_XL) do
|
|
{
|
|
if (fw2F >= 0x1C)
|
|
{
|
|
SYSTYPE = SYSTEM_TYPE_3DS;
|
|
break;
|
|
}
|
|
|
|
// TODO: chinese DSi XL detection
|
|
} while(0);
|
|
|
|
// TODO: 3DS XL detection
|
|
// TODO: chinese 3DS XL detection (does that even exist??)
|
|
|
|
// Emulator detection
|
|
bool __isEmulator();
|
|
if (__isEmulator())
|
|
SYSFLAGS |= SYSTEM_FLAGS_EMULATOR;
|
|
|
|
#undef SYSTYPE
|
|
#undef SYSFLAGS
|
|
|
|
switch (sysInfo.systemType)
|
|
{
|
|
#define _TEXT(_x,_y) case _x: sysInfo.systemTypeText = _y; break
|
|
_TEXT(SYSTEM_TYPE_DS, "Nintendo DS (Original)");
|
|
_TEXT(SYSTEM_TYPE_DSDebug, "Nintendo DS (Debug)");
|
|
_TEXT(SYSTEM_TYPE_DSLite, "Nintendo DS Lite");
|
|
_TEXT(SYSTEM_TYPE_DSi, "Nintendo DSi");
|
|
_TEXT(SYSTEM_TYPE_DSi_XL, "Nintendo DSi XL");
|
|
_TEXT(SYSTEM_TYPE_3DS, "Nintendo 3DS");
|
|
_TEXT(SYSTEM_TYPE_3DS_XL, "Nintendo 3DS XL");
|
|
#undef _TEXT
|
|
}
|
|
|
|
switch (sysInfo.systemMode)
|
|
{
|
|
#define _TEXT(_x,_y) case _x: sysInfo.systemModeText = _y; break
|
|
_TEXT(SYSTEM_MODE_DS, "Standard DS Mode (67.03 MHz)");
|
|
_TEXT(SYSTEM_MODE_DSi, "Enhanced DSi Mode (134.06 MHz)");
|
|
#undef _TEXT
|
|
}
|
|
}
|
|
|
|
const systeminfo_t* KeGetSysInfo()
|
|
{
|
|
return &sysInfo;
|
|
}
|
|
|
|
static inline void divmod3232(int a, int b)
|
|
{
|
|
REG_DIVCNT = DIV_32_32;
|
|
while(REG_DIVCNT & DIV_BUSY);
|
|
|
|
REG_DIV_NUMER_L = a;
|
|
REG_DIV_DENOM_L = b;
|
|
while(REG_DIVCNT & DIV_BUSY);
|
|
}
|
|
|
|
static inline void divmod6432(long long a, int b)
|
|
{
|
|
REG_DIVCNT = DIV_64_32;
|
|
while(REG_DIVCNT & DIV_BUSY);
|
|
|
|
REG_DIV_NUMER = a;
|
|
REG_DIV_DENOM_L = b;
|
|
while(REG_DIVCNT & DIV_BUSY);
|
|
}
|
|
|
|
static inline void divmod6464(long long a, long long b)
|
|
{
|
|
REG_DIVCNT = DIV_64_64;
|
|
while(REG_DIVCNT & DIV_BUSY);
|
|
|
|
REG_DIV_NUMER = a;
|
|
REG_DIV_DENOM = b;
|
|
while(REG_DIVCNT & DIV_BUSY);
|
|
}
|
|
|
|
int KeDiv3232(int a, int b)
|
|
{
|
|
divmod3232(a, b);
|
|
return REG_DIV_RESULT_L;
|
|
}
|
|
|
|
int KeMod3232(int a, int b)
|
|
{
|
|
divmod3232(a, b);
|
|
return REG_DIVREM_RESULT_L;
|
|
}
|
|
|
|
int KeDiv6432(long long a, int b)
|
|
{
|
|
divmod6432(a, b);
|
|
return REG_DIV_RESULT_L;
|
|
}
|
|
|
|
int KeMod6432(long long a, int b)
|
|
{
|
|
divmod6432(a, b);
|
|
return REG_DIVREM_RESULT_L;
|
|
}
|
|
|
|
long long KeDiv6464(long long a, long long b)
|
|
{
|
|
divmod6464(a, b);
|
|
return REG_DIV_RESULT;
|
|
}
|
|
|
|
long long KeMod6464(long long a, long long b)
|
|
{
|
|
divmod6464(a, b);
|
|
return REG_DIVREM_RESULT;
|
|
}
|
|
|
|
unsigned int KeSqrt32(unsigned int a)
|
|
{
|
|
REG_SQRTCNT = SQRT_32;
|
|
while(REG_SQRTCNT & SQRT_BUSY);
|
|
|
|
REG_SQRT_PARAM_L = a;
|
|
while(REG_SQRTCNT & SQRT_BUSY);
|
|
|
|
return REG_SQRT_RESULT;
|
|
}
|
|
|
|
unsigned int KeSqrt64(long long a)
|
|
{
|
|
REG_SQRTCNT = SQRT_64;
|
|
while(REG_SQRTCNT & SQRT_BUSY);
|
|
|
|
REG_SQRT_PARAM = a;
|
|
while(REG_SQRTCNT & SQRT_BUSY);
|
|
|
|
return REG_SQRT_RESULT;
|
|
}
|
|
|
|
#define IoStdinHook curExecStatus->stdin_hook
|
|
#define IoStdoutHook curExecStatus->stdout_hook
|
|
#define IoStderrHook curExecStatus->stderr_hook
|
|
|
|
FILE* IoGetStdin()
|
|
{
|
|
return !IoStdinHook ? stdin : (FILE*)IoStdinHook;
|
|
}
|
|
|
|
FILE* IoGetStdout()
|
|
{
|
|
return !IoStdoutHook ? stdout : (FILE*)IoStdoutHook;
|
|
}
|
|
|
|
FILE* IoGetStderr()
|
|
{
|
|
return !IoStderrHook ? stderr : (FILE*)IoStderrHook;
|
|
}
|
|
|
|
FILE* IoSetStdin(FILE* newstdin)
|
|
{
|
|
FILE* oldstdin = (FILE*)IoStdinHook;
|
|
IoStdinHook = newstdin;
|
|
return oldstdin;
|
|
}
|
|
|
|
FILE* IoSetStdout(FILE* newstdout)
|
|
{
|
|
FILE* oldstdout = (FILE*)IoStdoutHook;
|
|
IoStdoutHook = newstdout;
|
|
return oldstdout;
|
|
}
|
|
|
|
FILE* IoSetStderr(FILE* newstderr)
|
|
{
|
|
FILE* oldstderr = (FILE*)IoStderrHook;
|
|
IoStderrHook = newstderr;
|
|
return oldstderr;
|
|
}
|
|
|
|
FILE* IoOpenStream(const void*);
|
|
|
|
#undef stricmp
|
|
#undef strnicmp
|
|
|
|
BEGIN_TABLE(FEOSKRNL)
|
|
ADD_FUNC_(DC_DrainWriteBuffer),
|
|
ADD_FUNC_(DC_FlushAll),
|
|
ADD_FUNC_(DC_FlushRange),
|
|
ADD_FUNC_(IC_InvalidateAll),
|
|
ADD_FUNC_(IC_InvalidateRange),
|
|
ADD_FUNC_(IoGetStderr),
|
|
ADD_FUNC_(IoGetStdin),
|
|
ADD_FUNC_(IoGetStdout),
|
|
ADD_FUNC_(IoOpenStream),
|
|
ADD_FUNC_(IoSetStderr),
|
|
ADD_FUNC_(IoSetStdin),
|
|
ADD_FUNC_(IoSetStdout),
|
|
ADD_FUNC_(KeDiv3232),
|
|
ADD_FUNC_(KeDiv6432),
|
|
ADD_FUNC_(KeDiv6464),
|
|
ADD_FUNC_(KeGetDiskStats),
|
|
ADD_ALIAS(KeGetErrnoPtr, __errno),
|
|
ADD_FUNC_(KeGetMemStats),
|
|
ADD_FUNC_(KeGetOSVersion),
|
|
ADD_FUNC_(KeGetSysInfo),
|
|
ADD_FUNC_(KeGetTickCount),
|
|
ADD_FUNC_(KeMod3232),
|
|
ADD_FUNC_(KeMod6432),
|
|
ADD_FUNC_(KeMod6464),
|
|
ADD_FUNC_(KeSetExcptHandler),
|
|
ADD_FUNC_(KeSqrt32),
|
|
ADD_FUNC_(KeSqrt64),
|
|
ADD_FUNC_(KeWaitForMemAddr),
|
|
ADD_FUNC_(LdrEnumModules),
|
|
ADD_FUNC_(LdrExecuteArgv),
|
|
ADD_FUNC_(LdrFindSymbol),
|
|
ADD_FUNC_(LdrFreeModule),
|
|
ADD_FUNC_(LdrGetExidxTbl),
|
|
ADD_FUNC_(LdrGetModule),
|
|
ADD_FUNC_(LdrGetModuleName),
|
|
ADD_FUNC_(LdrLoadModule),
|
|
ADD_FUNC_(LdrLockModule),
|
|
ADD_FUNC_(LdrResGetSize),
|
|
ADD_FUNC_(LdrResRead),
|
|
ADD_FUNC_(LdrResSeek),
|
|
ADD_FUNC_(LdrResTell),
|
|
ADD_FUNC_(LdrResolveAddr),
|
|
ADD_FUNC_(LdrUnlockModule),
|
|
ADD_FUNC_(PsCreateFromArgv),
|
|
ADD_FUNC_(PsCreateFromCmdLine),
|
|
ADD_FUNC_(ThrCreate),
|
|
ADD_FUNC_(ThrDetach),
|
|
ADD_FUNC_(ThrExit),
|
|
ADD_FUNC_(ThrFree),
|
|
ADD_FUNC_(ThrGetExitCode),
|
|
ADD_FUNC_(ThrGetSelf),
|
|
ADD_FUNC_(ThrIsActive),
|
|
ADD_FUNC_(ThrJoin),
|
|
ADD_FUNC_(ThrRunInContext),
|
|
ADD_FUNC_(ThrSetPriority),
|
|
ADD_FUNC_(ThrTlsAlloc),
|
|
ADD_FUNC_(ThrTlsFree),
|
|
ADD_FUNC_(ThrTlsGetValue),
|
|
ADD_FUNC_(ThrTlsSetValue),
|
|
ADD_FUNC_(ThrYield),
|
|
ADD_FUNC_(__aeabi_idiv),
|
|
ADD_FUNC_(__aeabi_idivmod),
|
|
ADD_FUNC_(__aeabi_ldivmod),
|
|
ADD_FUNC_(__aeabi_uidiv),
|
|
ADD_FUNC_(__aeabi_uidivmod),
|
|
ADD_FUNC_(__aeabi_uldivmod),
|
|
ADD_FUNC_(abs),
|
|
ADD_FUNC_(acosLerp),
|
|
ADD_FUNC_(asctime),
|
|
ADD_FUNC_(asinLerp),
|
|
ADD_FUNC_(atoi),
|
|
ADD_FUNC_(bsearch),
|
|
ADD_FUNC_(calloc),
|
|
ADD_FUNC_(chdir),
|
|
ADD_FUNC_(clearerr),
|
|
ADD_FUNC_(close),
|
|
ADD_FUNC_(closedir),
|
|
ADD_FUNC_(cosLerp),
|
|
ADD_FUNC_(ctime),
|
|
ADD_FUNC_(div),
|
|
ADD_ALIAS(exit, LdrModuleExit),
|
|
ADD_FUNC_(fclose),
|
|
ADD_FUNC_(fdopen),
|
|
ADD_FUNC_(feof),
|
|
ADD_FUNC_(ferror),
|
|
ADD_FUNC_(fflush),
|
|
ADD_FUNC_(fgetc),
|
|
ADD_FUNC_(fgets),
|
|
ADD_ALIAS(fileno, _fileno_helper),
|
|
ADD_FUNC_(fopen),
|
|
ADD_FUNC_(fputc),
|
|
ADD_FUNC_(fputs),
|
|
ADD_FUNC_(fread),
|
|
ADD_FUNC_(free),
|
|
ADD_FUNC_(freopen),
|
|
ADD_FUNC_(fseek),
|
|
ADD_FUNC_(fstat),
|
|
ADD_FUNC_(ftell),
|
|
ADD_FUNC_(ftruncate),
|
|
ADD_FUNC_(fwrite),
|
|
ADD_FUNC_(getcwd),
|
|
ADD_ALIAS(getdelim, __getdelim),
|
|
ADD_FUNC_(gmtime),
|
|
ADD_FUNC_(isalnum),
|
|
ADD_FUNC_(isalpha),
|
|
ADD_FUNC_(iscntrl),
|
|
ADD_FUNC_(isdigit),
|
|
ADD_FUNC_(isgraph),
|
|
ADD_FUNC_(islower),
|
|
ADD_FUNC_(isprint),
|
|
ADD_FUNC_(ispunct),
|
|
ADD_FUNC_(isspace),
|
|
ADD_FUNC_(isupper),
|
|
ADD_FUNC_(isxdigit),
|
|
ADD_FUNC_(localtime),
|
|
ADD_FUNC_(longjmp),
|
|
ADD_FUNC_(lseek),
|
|
ADD_FUNC_(malloc),
|
|
ADD_FUNC_(memalign),
|
|
ADD_FUNC_(memchr),
|
|
ADD_FUNC_(memcmp),
|
|
ADD_FUNC_(memcpy),
|
|
ADD_FUNC_(memmove),
|
|
ADD_FUNC_(memset),
|
|
ADD_FUNC_(mkdir),
|
|
ADD_FUNC_(mktime),
|
|
ADD_FUNC_(open),
|
|
ADD_FUNC_(opendir),
|
|
ADD_FUNC_(qsort),
|
|
ADD_FUNC_(rand),
|
|
ADD_FUNC_(read),
|
|
ADD_FUNC_(readdir),
|
|
ADD_FUNC_(realloc),
|
|
ADD_FUNC_(remove),
|
|
ADD_FUNC_(rename),
|
|
ADD_FUNC_(rewinddir),
|
|
ADD_FUNC_(seekdir),
|
|
ADD_FUNC_(setjmp),
|
|
ADD_FUNC_(setvbuf),
|
|
ADD_FUNC_(sinLerp),
|
|
ADD_FUNC_(srand),
|
|
ADD_FUNC_(stat),
|
|
ADD_FUNC_(strcat),
|
|
ADD_FUNC_(strchr),
|
|
ADD_FUNC_(strcmp),
|
|
ADD_FUNC_(strcpy),
|
|
ADD_FUNC_(strcspn),
|
|
ADD_FUNC_(strerror),
|
|
ADD_FUNC_(strftime),
|
|
ADD_ALIAS(stricmp, strcasecmp),
|
|
ADD_FUNC_(strlen),
|
|
ADD_FUNC_(strncat),
|
|
ADD_FUNC_(strncmp),
|
|
ADD_FUNC_(strncpy),
|
|
ADD_ALIAS(strnicmp, strncasecmp),
|
|
ADD_FUNC_(strpbrk),
|
|
ADD_FUNC_(strrchr),
|
|
ADD_FUNC_(strspn),
|
|
ADD_FUNC_(strstr),
|
|
ADD_FUNC_(strtok),
|
|
ADD_FUNC_(strtok_r),
|
|
ADD_FUNC_(strtol),
|
|
ADD_FUNC_(strtoul),
|
|
ADD_FUNC_(system),
|
|
ADD_FUNC_(tanLerp),
|
|
ADD_FUNC_(telldir),
|
|
ADD_FUNC_(time),
|
|
ADD_FUNC_(tolower),
|
|
ADD_FUNC_(toupper),
|
|
ADD_FUNC_(ungetc),
|
|
ADD_ALIAS(vfprintf, vfiprintf),
|
|
ADD_ALIAS(vfscanf, vfiscanf),
|
|
ADD_ALIAS(vsnprintf, vsniprintf),
|
|
ADD_ALIAS(vsprintf, vsiprintf),
|
|
ADD_ALIAS(vsscanf, vsiscanf),
|
|
ADD_FUNC_(write),
|
|
END_TABLE(FEOSKRNL)
|
|
|
|
MAKE_FAKEMODULE(FEOSKRNL)
|
|
|
|
#define stricmp strcasecmp
|
|
#define strnicmp strncasecmp
|
|
|
|
static word_t dummy_entrypoint(word_t a, word_t b, word_t c, word_t d)
|
|
{
|
|
return FEOS_RC_OK;
|
|
}
|
|
|
|
static executeStatus_t defaultExecStatus;
|
|
executeStatus_t* curExecStatus = &defaultExecStatus;
|
|
|
|
void KeInitDefaultExecStatus()
|
|
{
|
|
defaultExecStatus.cwdBuffer = _getCwdBuf();
|
|
}
|
|
|
|
#define EXECSTAT_ADDENDUM 256
|
|
|
|
#define GET_ADDENDUM(x) ((char*)(x) + sizeof(executeStatus_t));
|
|
|
|
execstat_t KeExecStatusCreate()
|
|
{
|
|
executeStatus_t* pSt = (executeStatus_t*) malloc(sizeof(executeStatus_t) + EXECSTAT_ADDENDUM);
|
|
if (!pSt) return NULL;
|
|
|
|
memset(pSt, 0, sizeof(executeStatus_t));
|
|
pSt->refcount = 1;
|
|
|
|
// Inherit standard stream hooks
|
|
pSt->stdin_hook = curExecStatus->stdin_hook;
|
|
pSt->stdout_hook = curExecStatus->stdout_hook;
|
|
pSt->stderr_hook = curExecStatus->stderr_hook;
|
|
|
|
// Inherit current working directory
|
|
pSt->cwdCluster = g_fatCwdCluster;
|
|
pSt->cwdBuffer = GET_ADDENDUM(pSt);
|
|
memcpy(pSt->cwdBuffer, curExecStatus->cwdBuffer, EXECSTAT_ADDENDUM);
|
|
|
|
return pSt;
|
|
}
|
|
|
|
void KeExecStatusAddRef(execstat_t hSt)
|
|
{
|
|
if (hSt == &defaultExecStatus) return;
|
|
hSt->refcount ++;
|
|
}
|
|
|
|
void KeExecStatusRelease(execstat_t hSt)
|
|
{
|
|
if (hSt == &defaultExecStatus) return;
|
|
word_t r = --hSt->refcount;
|
|
if (r == 0)
|
|
free(hSt);
|
|
}
|
|
|
|
void KeSetCurExecStatus(execstat_t hSt)
|
|
{
|
|
curExecStatus->cwdCluster = g_fatCwdCluster;
|
|
curExecStatus = hSt;
|
|
g_fatCwdCluster = curExecStatus->cwdCluster;
|
|
_setCwdBuf(curExecStatus->cwdBuffer);
|
|
}
|
|
|
|
execstat_t KeGetCurExecStatus()
|
|
{
|
|
return curExecStatus;
|
|
}
|
|
|
|
#define LdrCurModule curExecStatus->curModule
|
|
#define LdrExitBuf curExecStatus->exitBuf
|
|
#define LdrExitDone curExecStatus->exitDone
|
|
|
|
int LdrExecuteArgv(int argc, const char* argv[])
|
|
{
|
|
if (argc == 0) return E_INVALIDARG;
|
|
module_t hMod = LdrLoadModule(argv[0]);
|
|
if (!hMod) return E_FILENOTFOUND;
|
|
|
|
if (!__system)
|
|
__system = (systemfunc_t) LdrFindSymbol(hMod, "__system");
|
|
|
|
fxe_runtime_header* rh = GetRuntimeData(hMod);
|
|
|
|
int rc = E_INVALIDARG;
|
|
if (rh->entrypoint)
|
|
{
|
|
module_t hPrevMod = LdrCurModule;
|
|
LdrCurModule = hMod;
|
|
|
|
jmp_buf exitbuf;
|
|
word_t* pPrevBuf = LdrExitBuf;
|
|
LdrExitBuf = exitbuf;
|
|
rc = setjmp(exitbuf);
|
|
if (!LdrExitDone)
|
|
rc = rh->entrypoint(FEOS_EP_MAIN, (word_t)argc, (word_t)argv, 0);
|
|
else
|
|
LdrExitDone = false;
|
|
|
|
LdrExitBuf = pPrevBuf;
|
|
LdrCurModule = hPrevMod;
|
|
}
|
|
|
|
// If the app was forcefully killed we don't want FreeModule() to run the destructors
|
|
if ((int)rc == E_APPKILLED) rh->entrypoint = dummy_entrypoint;
|
|
|
|
LdrFreeModule(hMod);
|
|
return rc;
|
|
}
|
|
|
|
void LdrModuleExit(int rc)
|
|
{
|
|
LdrExitDone = true;
|
|
longjmp0(LdrExitBuf, rc);
|
|
}
|
|
|
|
void* LdrGetExidxTbl(module_t hMod, int* count)
|
|
{
|
|
if (hMod == (module_t)(~0))
|
|
{
|
|
// get exidx for kernel itself
|
|
typedef struct { word_t offset, size; } exidx_entry_t;
|
|
extern exidx_entry_t __exidx_start;
|
|
extern exidx_entry_t __exidx_end;
|
|
*count = &__exidx_end - &__exidx_start;
|
|
return &__exidx_start;
|
|
}
|
|
|
|
CHK_HMOD(hMod);
|
|
fxe_runtime_header* rh = GetRuntimeData(hMod);
|
|
|
|
if (!rh->exidx.nentries) return NULL;
|
|
if (count) *count = rh->exidx.nentries;
|
|
|
|
return rh->exidx.table;
|
|
}
|