--- /dev/null
+# Project: Acess Shell\r
+\r
+CC = gcc\r
+AS = nasm\r
+LD = ld\r
+RM = @rm -f\r
+\r
+COBJ = main.o lib.o\r
+BIN = ../CLIShell\r
+ACESSDIR = /home/hodgeja/Projects/Acess2/Usermode\r
+\r
+INCS = -I$(ACESSDIR)/include -I./include\r
+CFLAGS = -Wall -fno-builtin -fno-stack-protector $(INCS)\r
+ASFLAGS = -felf\r
+LDFLAGS = -T $(ACESSDIR)/Libraries/acess.ld -I /Acess/Libs/ld-acess.so -lc\r
+\r
+.PHONY : all clean\r
+\r
+all: $(BIN)\r
+\r
+$(BIN): $(AOBJ) $(COBJ)\r
+ @echo --- $(LD) -o $@\r
+ @$(LD) $(LDFLAGS) -o $@ $(AOBJ) $(COBJ) -Map Map.txt\r
+ objdump -d $(BIN) > $(BIN).dsm\r
+ cp $(BIN) /mnt/AcessHDD/Acess2/\r
+\r
+clean:\r
+ $(RM) $(AOBJ) $(COBJ) $(BIN)\r
+\r
+$(COBJ): %.o: %.c\r
+ @echo --- GCC -o $@\r
+ @$(CC) $(CFLAGS) -c $? -o $@\r
+\r
+$(AOBJ): %.ao: %.asm\r
+ @echo --- $(AS) -o $@\r
+ @$(AS) $(ASFLAGS) -o $@ $<\r
--- /dev/null
+/*\r
+ Acess Shell Version 2\r
+- Based on IOOS CLI Shell\r
+*/\r
+#ifndef _HEADER_H\r
+#define _HEADER_H\r
+\r
+#define NULL ((void*)0)\r
+\r
+#define Print(str) do{char*s=(str);write(_stdout,strlen(s)+1,s);}while(0)\r
+\r
+extern int _stdout;\r
+extern int _stdin;\r
+\r
+extern int GeneratePath(char *file, char *base, char *tmpPath);\r
+\r
+\r
+#endif\r
--- /dev/null
+/*\r
+ * AcessOS Shell Version 2\r
+ *\r
+ * See file COPYING for \r
+ */\r
+#include "header.h"\r
+\r
+// === CODE ===\r
+/**\r
+ * \fn int GeneratePath(char *file, char *base, char *Dest)\r
+ * \brief Generates a path given a base and a filename\r
+ * \param \r
+ */\r
+int GeneratePath(char *file, char *base, char *Dest)\r
+{\r
+ char *pathComps[64];\r
+ char *tmpStr;\r
+ int iPos = 0;\r
+ int iPos2 = 0;\r
+ \r
+ // Parse Base Path\r
+ if(file[0] != '/')\r
+ {\r
+ pathComps[iPos++] = tmpStr = base+1;\r
+ while(*tmpStr)\r
+ {\r
+ if(*tmpStr++ == '/')\r
+ {\r
+ pathComps[iPos] = tmpStr;\r
+ iPos ++;\r
+ }\r
+ }\r
+ }\r
+ \r
+ //Print(" GeneratePath: Base Done\n");\r
+ \r
+ // Parse Argument Path\r
+ pathComps[iPos++] = tmpStr = file;\r
+ while(*tmpStr)\r
+ {\r
+ if(*tmpStr++ == '/')\r
+ {\r
+ pathComps[iPos] = tmpStr;\r
+ iPos ++;\r
+ }\r
+ }\r
+ pathComps[iPos] = NULL;\r
+ \r
+ //Print(" GeneratePath: Path Done\n");\r
+ \r
+ // Cleanup\r
+ iPos2 = iPos = 0;\r
+ while(pathComps[iPos])\r
+ {\r
+ tmpStr = pathComps[iPos];\r
+ // Always Increment iPos\r
+ iPos++;\r
+ // ..\r
+ if(tmpStr[0] == '.' && tmpStr[1] == '.' && (tmpStr[2] == '/' || tmpStr[2] == '\0') )\r
+ {\r
+ if(iPos2 != 0)\r
+ iPos2 --;\r
+ continue;\r
+ }\r
+ // .\r
+ if(tmpStr[0] == '.' && (tmpStr[1] == '/' || tmpStr[1] == '\0') )\r
+ {\r
+ continue;\r
+ }\r
+ // Empty\r
+ if(tmpStr[0] == '/' || tmpStr[0] == '\0')\r
+ {\r
+ continue;\r
+ }\r
+ \r
+ // Set New Position\r
+ pathComps[iPos2] = tmpStr;\r
+ iPos2++;\r
+ }\r
+ pathComps[iPos2] = NULL;\r
+ \r
+ // Build New Path\r
+ iPos2 = 1; iPos = 0;\r
+ Dest[0] = '/';\r
+ while(pathComps[iPos])\r
+ {\r
+ tmpStr = pathComps[iPos];\r
+ while(*tmpStr && *tmpStr != '/')\r
+ {\r
+ Dest[iPos2++] = *tmpStr;\r
+ tmpStr++;\r
+ }\r
+ Dest[iPos2++] = '/';\r
+ iPos++;\r
+ }\r
+ if(iPos2 > 1)\r
+ Dest[iPos2-1] = 0;\r
+ else\r
+ Dest[iPos2] = 0;\r
+ \r
+ return iPos2; //Length\r
+}\r
--- /dev/null
+/*\r
+ AcessOS Shell Version 2\r
+- Based on IOOS CLI Shell\r
+*/\r
+#include <acess/sys.h>\r
+#include <stdlib.h>\r
+#include "header.h"\r
+\r
+#define _stdin 0\r
+#define _stdout 1\r
+#define _stderr 2\r
+\r
+// ==== PROTOTYPES ====\r
+char *ReadCommandLine(int *Length);\r
+void Parse_Args(char *str, char **dest);\r
+void Command_Colour(int argc, char **argv);\r
+void Command_Clear(int argc, char **argv);\r
+//void Command_Ls(int argc, char **argv);\r
+void Command_Cd(int argc, char **argv);\r
+//void Command_Cat(int argc, char **argv);\r
+\r
+// ==== CONSTANT GLOBALS ====\r
+char *cCOLOUR_NAMES[8] = {"black", "red", "green", "yellow", "blue", "magenta", "cyan", "white"};\r
+struct {\r
+ char *name;\r
+ void (*fcn)(int argc, char **argv);\r
+} cBUILTINS[] = {\r
+ {"colour", Command_Colour}, {"clear", Command_Clear}, {"cd", Command_Cd}\r
+};\r
+#define BUILTIN_COUNT (sizeof(cBUILTINS)/sizeof(cBUILTINS[0]))\r
+\r
+// ==== LOCAL VARIABLES ====\r
+char gsCommandBuffer[1024];\r
+char *gsCurrentDirectory = "/";\r
+char gsTmpBuffer[1024];\r
+char **gasCommandHistory;\r
+ int giLastCommand = 0;\r
+ int giCommandSpace = 0;\r
+\r
+// ==== CODE ====\r
+int main(int argc, char *argv[], char *envp[])\r
+{\r
+ char *sCommandStr;\r
+ char *saArgs[32];\r
+ int length = 0;\r
+ int pid = -1;\r
+ int iArgCount = 0;\r
+ int bCached = 1;\r
+ t_sysFInfo info;\r
+ \r
+ //Command_Clear(0, NULL);\r
+ \r
+ write(_stdout, 36, "AcessOS/AcessBasic Shell Version 2\n");\r
+ write(_stdout, 30, " Based on CLI Shell for IOOS\n");\r
+ write(_stdout, 2, "\n");\r
+ for(;;)\r
+ {\r
+ // Free last command & arguments\r
+ if(saArgs[0]) free(saArgs);\r
+ if(!bCached) free(sCommandStr);\r
+ bCached = 0;\r
+ write(_stdout, strlen(gsCurrentDirectory), gsCurrentDirectory);\r
+ write(_stdout, 3, "$ ");\r
+ \r
+ // Read Command line\r
+ sCommandStr = ReadCommandLine( &length );\r
+ \r
+ // Check if the command should be cached\r
+ if(gasCommandHistory == NULL || strcmp(sCommandStr, gasCommandHistory[giLastCommand]) != 0)\r
+ {\r
+ if(giLastCommand >= giCommandSpace) {\r
+ giCommandSpace += 12;\r
+ gasCommandHistory = realloc(gasCommandHistory, giCommandSpace*sizeof(char*));\r
+ }\r
+ giLastCommand ++;\r
+ gasCommandHistory[ giLastCommand ] = sCommandStr;\r
+ bCached = 1;\r
+ }\r
+ \r
+ // Parse Command Line into arguments\r
+ Parse_Args(sCommandStr, saArgs);\r
+ \r
+ // Count Arguments\r
+ iArgCount = 0;\r
+ while(saArgs[iArgCount]) iArgCount++;\r
+ \r
+ // Silently Ignore all empty commands\r
+ if(saArgs[1][0] == '\0') continue;\r
+ \r
+ // Check Built-In Commands\r
+ // [HACK] Mem Usage - Use Length in place of `i'\r
+ for(length=0;length<BUILTIN_COUNT;length++)\r
+ {\r
+ if(strcmp(saArgs[1], cBUILTINS[length].name) == 0)\r
+ {\r
+ cBUILTINS[length].fcn(iArgCount-1, &saArgs[1]);\r
+ break;\r
+ }\r
+ }
+ // Calling a file\r
+ if(length == BUILTIN_COUNT)\r
+ {\r
+ GeneratePath(saArgs[1], gsCurrentDirectory, gsTmpBuffer);\r
+ // Use length in place of fp\r
+ length = open(gsTmpBuffer, 0);\r
+ // Check file existence\r
+ if(length == -1) {\r
+ Print("Unknown Command: `");Print(saArgs[1]);Print("'\n"); // Error Message\r
+ continue;\r
+ }\r
+ // Check if the file is a directory\r
+ finfo( length, &info );
+ close( length );\r
+ if(info.flags & FILEFLAG_DIRECTORY) {\r
+ Print("`");Print(saArgs[1]); // Error Message\r
+ Print("' is a directory.\n");\r
+ continue;\r
+ }\r
+ pid = clone(CLONE_VM, 0);\r
+ if(pid == 0) execve(gsTmpBuffer, &saArgs[1], NULL);\r
+ if(pid <= 0) {\r
+ Print("Unablt to create process: `");Print(gsTmpBuffer);Print("'\n"); // Error Message
+ //SysDebug("pid = %i\n", pid);\r
+ }\r
+ else {\r
+ //waitpid(pid, K_WAITPID_DIE);\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+/**\r
+ * \fn char *ReadCommandLine(int *Length)\r
+ * \brief Read from the command line\r
+ */\r
+char *ReadCommandLine(int *Length)\r
+{\r
+ char *ret;\r
+ int len, pos, space = 1023;\r
+ char ch;\r
+ \r
+ // Preset Variables\r
+ ret = malloc( space+1 );\r
+ len = 0;\r
+ pos = 0;\r
+ \r
+ // Read In Command Line\r
+ do {\r
+ read(_stdin, 1, &ch); // Read Character from stdin (read is a blocking call)\r
+ // Ignore control characters\r
+ if(ch < 0) continue;\r
+ // Backspace\r
+ if(ch == '\b') {\r
+ if(len <= 0) continue; // Protect against underflows\r
+ if(pos == len) { // Simple case of end of string\r
+ len --; pos--;\r
+ } else {\r
+ memmove(&ret[pos-1], &ret[pos], len-pos);\r
+ pos --;\r
+ len --;\r
+ }\r
+ write(_stdout, 1, &ch);\r
+ continue;\r
+ }\r
+ // Expand Buffer\r
+ if(len > space) {\r
+ space += 256;\r
+ ret = realloc(ret, space+1);\r
+ if(!ret) return NULL;\r
+ }\r
+ \r
+ write(_stdout, 1, &ch);\r
+ ret[pos++] = ch;\r
+ len ++;\r
+ } while(ch != '\n');\r
+ \r
+ // Remove newline\r
+ pos --;\r
+ ret[pos] = '\0';\r
+ \r
+ // Return length\r
+ if(Length) *Length = len;\r
+ \r
+ return ret;\r
+}\r
+\r
+/**\r
+ * \fn void Parse_Args(char *str, char **dest)\r
+ * \brief Parse a string into an argument array\r
+ */\r
+void Parse_Args(char *str, char **dest)\r
+{\r
+ int i = 1;\r
+ char *buf = malloc( strlen(str) + 1 );\r
+ \r
+ strcpy(buf, str);\r
+ dest[0] = buf;\r
+ \r
+ // Trim leading whitespace\r
+ while(*buf == ' ' && *buf) buf++;\r
+ \r
+ for(;;)\r
+ {\r
+ dest[i] = buf; // Save start of string\r
+ i++;\r
+ while(*buf && *buf != ' ')\r
+ {\r
+ if(*buf++ == '"')\r
+ {\r
+ while(*buf && !(*buf == '"' && buf[-1] != '\\'))\r
+ buf++;\r
+ }\r
+ }\r
+ if(*buf == '\0') break;\r
+ *buf = '\0';\r
+ while(*++buf == ' ' && *buf);\r
+ if(*buf == '\0') break;\r
+ }\r
+ dest[i] = NULL;\r
+ if(i == 1) {\r
+ free(buf);\r
+ dest[0] = NULL;\r
+ }\r
+}\r
+\r
+/**\r
+ * \fn void Command_Colour(int argc, char **argv)\r
+ * \brief \r
+ */\r
+void Command_Colour(int argc, char **argv)\r
+{\r
+ int fg, bg;\r
+ char clrStr[6] = "\x1B[37m";\r
+ \r
+ // Verify Arg Count\r
+ if(argc < 2)\r
+ {\r
+ Print("Please specify a colour\n");\r
+ goto usage;\r
+ }\r
+ \r
+ // Check Colour\r
+ for(fg=0;fg<8;fg++)\r
+ if(strcmp(cCOLOUR_NAMES[fg], argv[1]) == 0)\r
+ break;\r
+\r
+ // Foreground a valid colour\r
+ if(fg == 8) {\r
+ Print("Unknown Colour '");Print(argv[1]);Print("'\n");\r
+ goto usage;\r
+ }\r
+ // Set Foreground\r
+ clrStr[3] = '0' + fg;\r
+ write(_stdout, 6, clrStr);\r
+ \r
+ // Need to Set Background?\r
+ if(argc > 2)\r
+ {\r
+ for(bg=0;bg<8;bg++)\r
+ if(strcmp(cCOLOUR_NAMES[bg], argv[2]) == 0)\r
+ break;\r
+ \r
+ // Valid colour\r
+ if(bg == 8)\r
+ {\r
+ Print("Unknown Colour '");Print(argv[2]);Print("'\n");\r
+ goto usage;\r
+ }\r
+ \r
+ clrStr[2] = '4';\r
+ clrStr[3] = '0' + bg;\r
+ write(_stdout, 6, clrStr);\r
+ }\r
+ // Return\r
+ return;\r
+\r
+ // Function Usage (Requested via a Goto (I know it's ugly))\r
+usage:\r
+ Print("Valid Colours are ");\r
+ for(fg=0;fg<8;fg++)\r
+ {\r
+ Print(cCOLOUR_NAMES[fg]);\r
+ write(_stdout, 3, ", ");\r
+ }\r
+ write(_stdout, 4, "\b\b\n");\r
+ return;\r
+}\r
+\r
+void Command_Clear(int argc, char **argv)\r
+{\r
+ write(_stdout, 4, "\x1B[2J"); //Clear Screen\r
+}\r
+\r
+void Command_Cd(int argc, char **argv)\r
+{\r
+ char tmpPath[1024];\r
+ int fp;\r
+ t_sysFInfo stats;\r
+ \r
+ if(argc < 2)\r
+ {\r
+ Print(gsCurrentDirectory);Print("\n");\r
+ return;\r
+ }\r
+ \r
+ GeneratePath(argv[1], gsCurrentDirectory, tmpPath);\r
+ \r
+ fp = open(tmpPath, 0);\r
+ if(fp == -1) {\r
+ write(_stdout, 26, "Directory does not exist\n");\r
+ return;\r
+ }\r
+ finfo(fp, &stats);\r
+ close(fp);\r
+ \r
+ if(!(stats.flags & FILEFLAG_DIRECTORY)) {\r
+ write(_stdout, 17, "Not a Directory\n");\r
+ return;\r
+ }\r
+ \r
+ strcpy(gsCurrentDirectory, tmpPath);\r
+}\r
+\r
--- /dev/null
+#
+#
+#
+
+CC = gcc
+AS = nasm
+LD = ld
+RM = rm -f
+
+ASFLAGS = -felf
+CPPFLAGS = -nostdinc -I../../include
+CFLAGS = -Wall -Werror -O3 $(CPPFLAGS)
+LDFLAGS = -I/Acess/Libs/ld-acess.so -L../../Libraries ../../Libraries/crt0.o -lacess
+
+OBJ = main.o
+BIN = ../init
+
+.PHONY: all clean
+
+all: $(BIN)
+
+$(BIN): $(OBJ) Makefile
+ $(LD) $(LDFLAGS) $(OBJ) -o $(BIN)
+ cp $(BIN) /mnt/AcessHDD/Acess2/
+
+%.o: %.c
+ $(CC) $(CFLAGS) -c $< -o $@
--- /dev/null
+/*
+ * Acess2 System Init Task
+ */
+#include <acess/sys.h>
+
+// === CONSTANTS ===
+#define NULL ((void*)0)
+#define DEFAULT_TERMINAL "/Devices/VTerm/0"
+#define DEFAULT_SHELL "/Acess/CLIShell"
+
+// === CODE ===
+/**
+ * \fn int main(int argc, char *argv[])
+ */
+int main(int argc, char *argv[])
+{
+ open(DEFAULT_TERMINAL, OPENFLAG_READ); // Stdin
+ open(DEFAULT_TERMINAL, OPENFLAG_WRITE); // Stdout
+ open(DEFAULT_TERMINAL, OPENFLAG_WRITE); // Stderr
+
+ write(1, 13, "Hello, World!");
+
+ if(clone(CLONE_VM, 0) == 0)
+ {
+ execve(DEFAULT_SHELL, NULL, NULL);
+ }
+
+ for(;;) sleep();
+
+ return 42;
+}
--- /dev/null
+OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")\r
+OUTPUT_ARCH(i386)\r
+ENTRY(start)\r
+SEARCH_DIR(/home/hodgeja/Projects/Acess2/Usermode/Libraries)\r
+INPUT(-lacess crt0.o)\r
+SECTIONS\r
+{\r
+ /* Read-only sections, merged into text segment: */\r
+ PROVIDE (__executable_start = 0x08048000); . = 0x08048000 + SIZEOF_HEADERS;\r
+ .interp : { *(.interp) }\r
+ .note.gnu.build-id : { *(.note.gnu.build-id) }\r
+ .hash : { *(.hash) }\r
+ .gnu.hash : { *(.gnu.hash) }\r
+ .dynsym : { *(.dynsym) }\r
+ .dynstr : { *(.dynstr) }\r
+ .gnu.version : { *(.gnu.version) }\r
+ .gnu.version_d : { *(.gnu.version_d) }\r
+ .gnu.version_r : { *(.gnu.version_r) }\r
+ .rel.dyn :\r
+ {\r
+ *(.rel.init)\r
+ *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*)\r
+ *(.rel.fini)\r
+ *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*)\r
+ *(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*)\r
+ *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*)\r
+ *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*)\r
+ *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*)\r
+ *(.rel.ctors)\r
+ *(.rel.dtors)\r
+ *(.rel.got)\r
+ *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*)\r
+ }\r
+ .rela.dyn :\r
+ {\r
+ *(.rela.init)\r
+ *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)\r
+ *(.rela.fini)\r
+ *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)\r
+ *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)\r
+ *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)\r
+ *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)\r
+ *(.rela.ctors)\r
+ *(.rela.dtors)\r
+ *(.rela.got)\r
+ *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)\r
+ }\r
+ .rel.plt : { *(.rel.plt) }\r
+ .rela.plt : { *(.rela.plt) }\r
+ .init :\r
+ {\r
+ KEEP (*(.init))\r
+ } =0x90909090\r
+ .plt : { *(.plt) }\r
+ .text :\r
+ {\r
+ *(.text .stub .text.* .gnu.linkonce.t.*)\r
+ /* .gnu.warning sections are handled specially by elf32.em. */\r
+ *(.gnu.warning)\r
+ } =0x90909090\r
+ .fini :\r
+ {\r
+ KEEP (*(.fini))\r
+ } =0x90909090\r
+ PROVIDE (__etext = .);\r
+ PROVIDE (_etext = .);\r
+ PROVIDE (etext = .);\r
+ .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }\r
+ .rodata1 : { *(.rodata1) }\r
+ .eh_frame_hdr : { *(.eh_frame_hdr) }\r
+ .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) }\r
+ .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) }\r
+ /* Adjust the address for the data segment. We want to adjust up to\r
+ the same address within the page on the next page up. */\r
+ . = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (CONSTANT (MAXPAGESIZE) - 1)); . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));\r
+ /* Exception handling */\r
+ .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) }\r
+ .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }\r
+ /* Thread Local Storage sections */\r
+ .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) }\r
+ .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }\r
+ .preinit_array :\r
+ {\r
+ PROVIDE_HIDDEN (__preinit_array_start = .);\r
+ KEEP (*(.preinit_array))\r
+ PROVIDE_HIDDEN (__preinit_array_end = .);\r
+ }\r
+ .init_array :\r
+ {\r
+ PROVIDE_HIDDEN (__init_array_start = .);\r
+ KEEP (*(SORT(.init_array.*)))\r
+ KEEP (*(.init_array))\r
+ PROVIDE_HIDDEN (__init_array_end = .);\r
+ }\r
+ .fini_array :\r
+ {\r
+ PROVIDE_HIDDEN (__fini_array_start = .);\r
+ KEEP (*(.fini_array))\r
+ KEEP (*(SORT(.fini_array.*)))\r
+ PROVIDE_HIDDEN (__fini_array_end = .);\r
+ }\r
+ .ctors :\r
+ {\r
+ /* gcc uses crtbegin.o to find the start of\r
+ the constructors, so we make sure it is\r
+ first. Because this is a wildcard, it\r
+ doesn't matter if the user does not\r
+ actually link against crtbegin.o; the\r
+ linker won't look for a file to match a\r
+ wildcard. The wildcard also means that it\r
+ doesn't matter which directory crtbegin.o\r
+ is in. */\r
+ KEEP (*crtbegin.o(.ctors))\r
+ KEEP (*crtbegin?.o(.ctors))\r
+ /* We don't want to include the .ctor section from\r
+ the crtend.o file until after the sorted ctors.\r
+ The .ctor section from the crtend file contains the\r
+ end of ctors marker and it must be last */\r
+ KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))\r
+ KEEP (*(SORT(.ctors.*)))\r
+ KEEP (*(.ctors))\r
+ }\r
+ .dtors :\r
+ {\r
+ KEEP (*crtbegin.o(.dtors))\r
+ KEEP (*crtbegin?.o(.dtors))\r
+ KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))\r
+ KEEP (*(SORT(.dtors.*)))\r
+ KEEP (*(.dtors))\r
+ }\r
+ .jcr : { KEEP (*(.jcr)) }\r
+ .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) }\r
+ .dynamic : { *(.dynamic) }\r
+ .got : { *(.got) }\r
+ . = DATA_SEGMENT_RELRO_END (12, .);\r
+ .got.plt : { *(.got.plt) }\r
+ .data :\r
+ {\r
+ *(.data .data.* .gnu.linkonce.d.*)\r
+ SORT(CONSTRUCTORS)\r
+ }\r
+ .data1 : { *(.data1) }\r
+ _edata = .; PROVIDE (edata = .);\r
+ __bss_start = .;\r
+ .bss :\r
+ {\r
+ *(.dynbss)\r
+ *(.bss .bss.* .gnu.linkonce.b.*)\r
+ *(COMMON)\r
+ /* Align here to ensure that the .bss section occupies space up to\r
+ _end. Align after .bss to ensure correct alignment even if the\r
+ .bss section disappears because there are no input sections.\r
+ FIXME: Why do we need it? When there is no .bss section, we don't\r
+ pad the .data section. */\r
+ . = ALIGN(. != 0 ? 32 / 8 : 1);\r
+ }\r
+ . = ALIGN(32 / 8);\r
+ . = ALIGN(32 / 8);\r
+ _end = .; PROVIDE (end = .);\r
+ . = DATA_SEGMENT_END (.);\r
+ /* Stabs debugging sections. */\r
+ .stab 0 : { *(.stab) }\r
+ .stabstr 0 : { *(.stabstr) }\r
+ .stab.excl 0 : { *(.stab.excl) }\r
+ .stab.exclstr 0 : { *(.stab.exclstr) }\r
+ .stab.index 0 : { *(.stab.index) }\r
+ .stab.indexstr 0 : { *(.stab.indexstr) }\r
+ .comment 0 : { *(.comment) }\r
+ /* DWARF debug sections.\r
+ Symbols in the DWARF debugging sections are relative to the beginning\r
+ of the section so we begin them at 0. */\r
+ /* DWARF 1 */\r
+ .debug 0 : { *(.debug) }\r
+ .line 0 : { *(.line) }\r
+ /* GNU DWARF 1 extensions */\r
+ .debug_srcinfo 0 : { *(.debug_srcinfo) }\r
+ .debug_sfnames 0 : { *(.debug_sfnames) }\r
+ /* DWARF 1.1 and DWARF 2 */\r
+ .debug_aranges 0 : { *(.debug_aranges) }\r
+ .debug_pubnames 0 : { *(.debug_pubnames) }\r
+ /* DWARF 2 */\r
+ .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }\r
+ .debug_abbrev 0 : { *(.debug_abbrev) }\r
+ .debug_line 0 : { *(.debug_line) }\r
+ .debug_frame 0 : { *(.debug_frame) }\r
+ .debug_str 0 : { *(.debug_str) }\r
+ .debug_loc 0 : { *(.debug_loc) }\r
+ .debug_macinfo 0 : { *(.debug_macinfo) }\r
+ /* SGI/MIPS DWARF 2 extensions */\r
+ .debug_weaknames 0 : { *(.debug_weaknames) }\r
+ .debug_funcnames 0 : { *(.debug_funcnames) }\r
+ .debug_typenames 0 : { *(.debug_typenames) }\r
+ .debug_varnames 0 : { *(.debug_varnames) }\r
+ /* DWARF 3 */\r
+ .debug_pubtypes 0 : { *(.debug_pubtypes) }\r
+ .debug_ranges 0 : { *(.debug_ranges) }\r
+ .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }\r
+ /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) }\r
+}\r
--- /dev/null
+#
+#
+#
+
+AS = nasm
+RM = rm -f
+
+ASFLAGS = -felf
+
+.PHONY: all clean
+
+all: ../crt0.o
+
+../crt0.o: crt0.asm
+ $(AS) $(ASFLAGS) $< -o $@
--- /dev/null
+;
+; Acess2
+; C Runtime 0
+; - crt0.asm
+
+[BITS 32]
+[section .text]
+
+
+[global _start]
+[global start]
+[extern main]
+_start:
+start:
+ call main
+ mov eax, ebx ; Set Argument 1 to Return Value
+ xor eax, eax ; Set EAX to SYS_EXIT (0)
+ int 0xAC
+ jmp $ ; This should never be reached
--- /dev/null
+# Acess Dynamic Linker (ELF) Version 1\r
+# LD-ACESS.SO\r
+# Makefile\r
+\r
+CC = gcc\r
+AS = nasm\r
+RM = @rm -f\r
+LD = ld\r
+OBJDUMP = objdump\r
+\r
+COBJ = main.o lib.o loadlib.o elf.o pe.o\r
+AOBJ = helpers.ao\r
+BIN = ../ld-acess.so\r
+\r
+CPPFLAGS = -I../../include\r
+CFLAGS = -Wall -fno-builtin -fleading-underscore -fno-stack-protector\r
+ASFLAGS = -felf\r
+#LDFLAGS = --oformat elf32-i386 -Map map.txt -Bstatic -e _SoMain -shared\r
+#LDFLAGS = --oformat elf32-i386 -Map map.txt -Bstatic -e _SoMain -Ttext 0xBFFFE000\r
+LDFLAGS = -T link.ld -Map map.txt -Bstatic\r
+\r
+\r
+.PHONY: all clean\r
+\r
+all: $(BIN)\r
+\r
+clean:\r
+ $(RM) $(BIN) $(AOBJ) $(COBJ)\r
+\r
+$(BIN): $(AOBJ) $(COBJ)\r
+ $(LD) $(LDFLAGS) -o $(BIN) $(AOBJ) $(COBJ) > link.txt\r
+ $(OBJDUMP) -x $(BIN) > ld-acess.dmp\r
+ $(OBJDUMP) -d $(BIN) > ld-acess.dsm\r
+ cp $(BIN) /mnt/AcessHDD/Acess2/Libs\r
+\r
+$(COBJ): %.o: %.c\r
+ $(CC) $(CFLAGS) -o $@ -c $<\r
+\r
+$(AOBJ): %.ao: %.asm\r
+ $(AS) $(ASFLAGS) -o $@ $<\r
+
--- /dev/null
+/*\r
+ AcessOS v1\r
+ By thePowersGang\r
+ ld-acess.so\r
+ COMMON.H\r
+*/\r
+#ifndef _COMMON_H\r
+#define _COMMON_H\r
+\r
+#define NULL ((void*)0)\r
+\r
+#include <stdarg.h>\r
+\r
+// === Types ===\r
+typedef unsigned int Uint;\r
+typedef unsigned char Uint8;\r
+typedef unsigned short Uint16;\r
+typedef unsigned long Uint32;\r
+typedef signed char Sint8;\r
+typedef signed short Sint16;\r
+typedef signed long Sint32;\r
+
+// === Main ===
+extern int DoRelocate( Uint base, char **envp, char *Filename );
+\r
+// === Library/Symbol Manipulation ==\r
+extern Uint LoadLibrary(char *filename, char *SearchDir, char **envp);
+extern void AddLoaded(char *File, Uint base);
+extern Uint GetSymbol(char *name);\r
+extern int GetSymbolFromBase(Uint base, char *name, Uint *ret);\r
+\r
+// === Library Functions ===\r
+extern void strcpy(char *dest, char *src);
+extern int strcmp(char *s1, char *s2);\r
+extern int strlen(char *str);\r
+\r
+// === System Calls ===\r
+extern void SysExit();\r
+extern void SysDebug(char *fmt, ...); //!< Now implemented in main.c\r
+extern void SysDebugV(char *fmt, ...);\r
+extern Uint SysLoadBin(char *path, Uint *entry);\r
+extern Uint SysUnloadBin(Uint Base);\r
+
+// === ELF Loader ===
+extern int ElfGetSymbol(Uint Base, char *name, Uint *ret);\r
+\r
+// === PE Loader ===\r
+extern int PE_GetSymbol(Uint Base, char *Name, Uint *ret);\r
+\r
+#endif\r
--- /dev/null
+/*\r
+ AcessOS 1 - Dynamic Loader\r
+ By thePowersGang\r
+*/\r
+#include "common.h"\r
+#include "elf32.h"\r
+
+#define DEBUG 0
+
+#if DEBUG\r
+# define DEBUGS(v...) SysDebug(v)\r
+#else
+# define DEBUGS(...)
+#endif
+\r
+// === CONSTANTS ===
+#if DEBUG\r
+//static const char *csaDT_NAMES[] = {"DT_NULL", "DT_NEEDED", "DT_PLTRELSZ", "DT_PLTGOT", "DT_HASH", "DT_STRTAB", "DT_SYMTAB", "DT_RELA", "DT_RELASZ", "DT_RELAENT", "DT_STRSZ", "DT_SYMENT", "DT_INIT", "DT_FINI", "DT_SONAME", "DT_RPATH", "DT_SYMBOLIC", "DT_REL", "DT_RELSZ", "DT_RELENT", "DT_PLTREL", "DT_DEBUG", "DT_TEXTREL", "DT_JMPREL"};\r
+static const char *csaR_NAMES[] = {"R_386_NONE", "R_386_32", "R_386_PC32", "R_386_GOT32", "R_386_PLT32", "R_386_COPY", "R_386_GLOB_DAT", "R_386_JMP_SLOT", "R_386_RELATIVE", "R_386_GOTOFF", "R_386_GOTPC", "R_386_LAST"};
+#endif\r
+\r
+// === PROTOTYPES ===\r
+void elf_doRelocate(Uint r_info, Uint32 *ptr, Uint32 addend, Elf32_Sym *symtab, Uint base);\r
+Uint ElfHashString(char *name);\r
+\r
+// === CODE ===\r
+/**\r
+ \fn int ElfRelocate(void *Base, char **envp, char *Filename)\r
+ \brief Relocates a loaded ELF Executable\r
+*/\r
+int ElfRelocate(void *Base, char **envp, char *Filename)\r
+{\r
+ Elf32_Ehdr *hdr = Base;\r
+ Elf32_Phdr *phtab;\r
+ int i, j; // Counters\r
+ char *libPath;\r
+ Uint iRealBase = -1;\r
+ Uint iBaseDiff;\r
+ int iSegmentCount;\r
+ int iSymCount;\r
+ Elf32_Rel *rel = NULL;\r
+ Elf32_Rela *rela = NULL;\r
+ Uint32 *pltgot = NULL;\r
+ void *plt = NULL;\r
+ int relSz=0, relEntSz=8;\r
+ int relaSz=0, relaEntSz=8;\r
+ int pltSz=0, pltType=0;\r
+ Elf32_Dyn *dynamicTab = NULL; // Dynamic Table Pointer\r
+ char *dynstrtab = NULL; // .dynamic String Table\r
+ Elf32_Sym *dynsymtab;\r
+ \r
+ DEBUGS("ElfRelocate: (Base=0x%x)\n", Base);\r
+ \r
+ // Parse Program Header to get Dynamic Table\r
+ phtab = Base + hdr->phoff;\r
+ iSegmentCount = hdr->phentcount;\r
+ for(i=0;i<iSegmentCount;i++)\r
+ {\r
+ // Determine linked base address\r
+ if(phtab[i].Type == PT_LOAD && iRealBase > phtab[i].VAddr)\r
+ iRealBase = phtab[i].VAddr;\r
+ \r
+ // Find Dynamic Section\r
+ if(phtab[i].Type == PT_DYNAMIC) {\r
+ if(dynamicTab) {\r
+ DEBUGS(" WARNING - elf_relocate: Multiple PT_DYNAMIC segments\n");\r
+ continue;\r
+ }\r
+ dynamicTab = (void *) phtab[i].VAddr;\r
+ j = i; // Save Dynamic Table ID\r
+ }\r
+ }\r
+ \r
+ // Page Align real base\r
+ iRealBase &= ~0xFFF;\r
+ DEBUGS(" elf_relocate: True Base = 0x%x, Compiled Base = 0x%x\n", Base, iRealBase);\r
+ \r
+ // Adjust "Real" Base\r
+ iBaseDiff = (Uint)Base - iRealBase;\r
+ \r
+ hdr->entrypoint += iBaseDiff; // Adjust Entrypoint\r
+ \r
+ // Check if a PT_DYNAMIC segement was found\r
+ if(!dynamicTab) {\r
+ SysDebug(" elf_relocate: No PT_DYNAMIC segment in image, returning\n");\r
+ return hdr->entrypoint;\r
+ }\r
+ \r
+ // Adjust Dynamic Table\r
+ dynamicTab = (void *) ((Uint)dynamicTab + iBaseDiff);\r
+
+ // === Get Symbol table and String Table ===\r
+ for( j = 0; dynamicTab[j].d_tag != DT_NULL; j++)\r
+ {
+ switch(dynamicTab[j].d_tag)
+ {
+ // --- Symbol Table ---\r
+ case DT_SYMTAB:\r
+ DEBUGS(" elf_relocate: DYNAMIC Symbol Table 0x%x (0x%x)\n",\r
+ dynamicTab[j].d_val, dynamicTab[j].d_val + iBaseDiff);\r
+ dynamicTab[j].d_val += iBaseDiff;\r
+ dynsymtab = (void*)(dynamicTab[j].d_val);\r
+ hdr->misc.SymTable = dynamicTab[j].d_val; // Saved in unused bytes of ident\r
+ break;\r
+ // --- String Table ---\r
+ case DT_STRTAB:\r
+ DEBUGS(" elf_relocate: DYNAMIC String Table 0x%x (0x%x)\n",\r
+ dynamicTab[j].d_val, dynamicTab[j].d_val + iBaseDiff);\r
+ dynamicTab[j].d_val += iBaseDiff;\r
+ dynstrtab = (void*)(dynamicTab[j].d_val);\r
+ break;\r
+ // --- Hash Table --\r
+ case DT_HASH:\r
+ dynamicTab[j].d_val += iBaseDiff;\r
+ iSymCount = ((Uint*)(dynamicTab[j].d_val))[1];\r
+ hdr->misc.HashTable = dynamicTab[j].d_val; // Saved in unused bytes of ident\r
+ break;
+ }
+ }
+\r
+ if(dynsymtab == NULL) {\r
+ SysDebug("WARNING: No Dynamic Symbol table, returning\n");\r
+ return hdr->entrypoint;\r
+ }\r
+ \r
+ // Alter Symbols to true base\r
+ for(i=0;i<iSymCount;i++)\r
+ {\r
+ dynsymtab[i].value += iBaseDiff;
+ dynsymtab[i].nameOfs += (Uint)dynstrtab;\r
+ //DEBUGS("elf_relocate: Sym '%s' = 0x%x (relocated)\n", dynsymtab[i].name, dynsymtab[i].value);\r
+ }\r
+
+ // === Add to loaded list (can be imported now) ===
+ AddLoaded( Filename, (Uint)Base );
+
+ // === Parse Relocation Data ===\r
+ DEBUGS(" elf_relocate: dynamicTab = 0x%x\n", dynamicTab);\r
+ for( j = 0; dynamicTab[j].d_tag != DT_NULL; j++)\r
+ {\r
+ switch(dynamicTab[j].d_tag)\r
+ {\r
+ // --- Shared Library Name ---\r
+ case DT_SONAME:\r
+ DEBUGS(" elf_relocate: .so Name '%s'\n", dynstrtab+dynamicTab[j].d_val);\r
+ break;\r
+ // --- Needed Library ---\r
+ case DT_NEEDED:\r
+ libPath = dynstrtab + dynamicTab[j].d_val;\r
+ DEBUGS(" Required Library '%s'\n", libPath);\r
+ if(LoadLibrary(libPath, NULL, envp) == 0) {\r
+ #if DEBUG\r
+ DEBUGS(" elf_relocate: Unable to load '%s'\n", libPath);\r
+ #else\r
+ SysDebug("Unable to load required library '%s'\n", libPath);\r
+ #endif\r
+ return 0;\r
+ }\r
+ break;\r
+ // --- PLT/GOT ---\r
+ case DT_PLTGOT: pltgot = (void*)iBaseDiff+(dynamicTab[j].d_val); break;\r
+ case DT_JMPREL: plt = (void*)(iBaseDiff+dynamicTab[j].d_val); break;\r
+ case DT_PLTREL: pltType = dynamicTab[j].d_val; break;\r
+ case DT_PLTRELSZ: pltSz = dynamicTab[j].d_val; break;\r
+ \r
+ // --- Relocation ---\r
+ case DT_REL: rel = (void*)(iBaseDiff + dynamicTab[j].d_val); break;\r
+ case DT_RELSZ: relSz = dynamicTab[j].d_val; break;\r
+ case DT_RELENT: relEntSz = dynamicTab[j].d_val; break;\r
+ case DT_RELA: rela = (void*)(iBaseDiff + dynamicTab[j].d_val); break;\r
+ case DT_RELASZ: relaSz = dynamicTab[j].d_val; break;\r
+ case DT_RELAENT: relaEntSz = dynamicTab[j].d_val; break;\r
+ \r
+ // --- Symbol Table ---\r
+ case DT_SYMTAB:\r
+ // --- Hash Table ---\r
+ case DT_HASH:\r
+ // --- String Table ---\r
+ case DT_STRTAB:\r
+ break;\r
+ \r
+ // --- Unknown ---\r
+ default:\r
+ if(dynamicTab[j].d_tag > DT_JMPREL) continue;\r
+ //DEBUGS(" elf_relocate: %i-%i = %s,0x%x\n",\r
+ // i,j, csaDT_NAMES[dynamicTab[j].d_tag],dynamicTab[j].d_val);\r
+ break;\r
+ }\r
+ }\r
+ \r
+ DEBUGS(" elf_relocate: Beginning Relocation\n");\r
+ \r
+ // Parse Relocation Entries\r
+ if(rel && relSz)\r
+ {\r
+ Uint32 *ptr;\r
+ DEBUGS(" elf_relocate: rel=0x%x, relSz=0x%x, relEntSz=0x%x\n", rel, relSz, relEntSz);\r
+ j = relSz / relEntSz;\r
+ for( i = 0; i < j; i++ )\r
+ {
+ //DEBUGS(" Rel %i: 0x%x+0x%x\n", i, iBaseDiff, rel[i].r_offset);\r
+ ptr = (void*)(iBaseDiff + rel[i].r_offset);\r
+ elf_doRelocate(rel[i].r_info, ptr, *ptr, dynsymtab, iBaseDiff);\r
+ }\r
+ }\r
+ // Parse Relocation Entries\r
+ if(rela && relaSz)\r
+ {\r
+ Uint32 *ptr;\r
+ DEBUGS(" elf_relocate: rela=0x%x, relaSz=0x%x, relaEntSz=0x%x\n", rela, relaSz, relaEntSz);\r
+ j = relaSz / relaEntSz;\r
+ for( i = 0; i < j; i++ )\r
+ {\r
+ ptr = (void*)(iBaseDiff + rela[i].r_offset);\r
+ elf_doRelocate(rel[i].r_info, ptr, rela[i].r_addend, dynsymtab, iBaseDiff);\r
+ }\r
+ }\r
+ \r
+ // === Process PLT (Procedure Linkage Table) ===\r
+ if(plt && pltSz)\r
+ {\r
+ Uint32 *ptr;\r
+ DEBUGS(" elf_relocate: Relocate PLT, plt=0x%x\n", plt);\r
+ if(pltType == DT_REL)\r
+ {\r
+ Elf32_Rel *pltRel = plt;\r
+ j = pltSz / sizeof(Elf32_Rel);\r
+ DEBUGS(" elf_relocate: PLT Reloc Type = Rel, %i entries\n", j);\r
+ for(i=0;i<j;i++)\r
+ {\r
+ ptr = (void*)(iBaseDiff + pltRel[i].r_offset);\r
+ elf_doRelocate(pltRel[i].r_info, ptr, *ptr, dynsymtab, iRealBase);\r
+ }\r
+ }\r
+ else\r
+ {\r
+ Elf32_Rela *pltRela = plt;\r
+ j = pltSz / sizeof(Elf32_Rela);\r
+ DEBUGS(" elf_relocate: PLT Reloc Type = Rela, %i entries\n", j);\r
+ for(i=0;i<j;i++)\r
+ {\r
+ ptr = (void*)(iRealBase + pltRela[i].r_offset);\r
+ elf_doRelocate(pltRela[i].r_info, ptr, pltRela[i].r_addend, dynsymtab, iRealBase);\r
+ }\r
+ }\r
+ }\r
+ \r
+ DEBUGS("ElfRelocate: RETURN 0x%x", hdr->entrypoint);\r
+ return hdr->entrypoint;\r
+}\r
+\r
+void elf_doRelocate(Uint r_info, Uint32 *ptr, Uint32 addend, Elf32_Sym *symtab, Uint base)\r
+{\r
+ int type = ELF32_R_TYPE(r_info);\r
+ int sym = ELF32_R_SYM(r_info);\r
+ Uint32 val;\r
+ switch( type )\r
+ {\r
+ // Standard 32 Bit Relocation (S+A)\r
+ case R_386_32:\r
+ val = GetSymbol( symtab[sym].name );\r
+ DEBUGS(" elf_doRelocate: R_386_32 *0x%x += 0x%x('%s')\n",\r
+ ptr, val, symtab[sym].name);\r
+ *ptr = val + addend;\r
+ break;\r
+ \r
+ // 32 Bit Relocation wrt. Offset (S+A-P)\r
+ case R_386_PC32:\r
+ DEBUGS(" elf_doRelocate: #%i: '%s'\n", sym, symtab[sym].name);\r
+ val = GetSymbol( symtab[sym].name );\r
+ DEBUGS(" elf_doRelocate: R_386_PC32 *0x%x = 0x%x + 0x%x - 0x%x\n",\r
+ ptr, *ptr, val, (Uint)ptr );\r
+ *ptr = val + addend - (Uint)ptr;\r
+ //*ptr = val + addend - ((Uint)ptr - base);\r
+ break;
+\r
+ // Absolute Value of a symbol (S)\r
+ case R_386_GLOB_DAT:\r
+ case R_386_JMP_SLOT:
+ DEBUGS(" elf_doRelocate: #%i: '%s'\n", sym, symtab[sym].name);\r
+ val = GetSymbol( symtab[sym].name );\r
+ DEBUGS(" elf_doRelocate: %s *0x%x = 0x%x\n", csaR_NAMES[type], ptr, val);\r
+ *ptr = val;\r
+ break;\r
+\r
+ // Base Address (B+A)\r
+ case R_386_RELATIVE:\r
+ DEBUGS(" elf_doRelocate: R_386_RELATIVE *0x%x = 0x%x + 0x%x\n", ptr, base, addend);\r
+ *ptr = base + addend;\r
+ break;\r
+ \r
+ default:\r
+ DEBUGS(" elf_doRelocate: Rel 0x%x: 0x%x,%s\n", ptr, sym, csaR_NAMES[type]);\r
+ break;\r
+ }\r
+ \r
+}
+\r
+/**\r
+ * \fn int ElfGetSymbol(Uint Base, char *name, Uint *ret)\r
+ */
+int ElfGetSymbol(Uint Base, char *Name, Uint *ret)
+{
+ Elf32_Ehdr *hdr = (void*)Base;\r
+ Elf32_Sym *symtab;
+ int nbuckets = 0;\r
+ int iSymCount = 0;
+ int i;\r
+ Uint *pBuckets;\r
+ Uint *pChains;\r
+ Uint iNameHash;
+\r
+ //DEBUGS("ElfGetSymbol: (Base=0x%x, Name='%s')\n", Base, Name);\r
+\r
+ pBuckets = (void *) hdr->misc.HashTable;\r
+ symtab = (void *) hdr->misc.SymTable;\r
+
+ nbuckets = pBuckets[0];\r
+ iSymCount = pBuckets[1];\r
+ pBuckets = &pBuckets[2];\r
+ pChains = &pBuckets[ nbuckets ];\r
+ \r
+ // Get hash
+ iNameHash = ElfHashString(Name);\r
+ iNameHash %= nbuckets;\r
+ //DEBUGS(" ElfGetSymbol: iNameHash = 0x%x\n", iNameHash);\r
+
+ // Walk Chain\r
+ i = pBuckets[ iNameHash ];\r
+ //DEBUGS(" ElfGetSymbol: strcmp(Name, \"%s\")\n", symtab[i].name);\r
+ if(symtab[i].shndx != SHN_UNDEF && strcmp(symtab[i].name, Name) == 0) {\r
+ *ret = symtab[ i ].value;\r
+ return 1;\r
+ }\r
+ \r
+ //DEBUGS(" ElfGetSymbol: Hash of first = 0x%x\n", ElfHashString( symtab[i].name ) % nbuckets);\r
+ while(pChains[i] != STN_UNDEF)\r
+ {\r
+ //DEBUGS(" pChains[%i] = %i\n", i, pChains[i]);\r
+ i = pChains[i];\r
+ //DEBUGS(" ElfGetSymbol: strcmp(Name, \"%s\")\n", symtab[ i ].name);\r
+ if(symtab[i].shndx != SHN_UNDEF && strcmp(symtab[ i ].name, Name) == 0) {\r
+ //DEBUGS("ElfGetSymbol: RETURN 1, '%s' = 0x%x\n", symtab[ i ].name, symtab[ i ].value);\r
+ *ret = symtab[ i ].value;\r
+ return 1;\r
+ }\r
+ }\r
+ \r
+ //DEBUGS("ElfGetSymbol: RETURN 0, Symbol '%s' not found\n", Name);
+ return 0;
+}\r
+\r
+Uint ElfHashString(char *name)\r
+{\r
+ Uint h = 0, g;\r
+ while(*name)\r
+ {\r
+ h = (h << 4) + *name++;\r
+ if( (g = h & 0xf0000000) )\r
+ h ^= g >> 24;\r
+ h &= ~g;\r
+ }\r
+ return h;\r
+}\r
+\r
+#if 0\r
+unsigned long elf_hash(const unsigned char *name)\r
+{\r
+ unsigned long h = 0, g;\r
+ while (*name)\r
+ {\r
+ h = (h << 4) + *name++;\r
+ if (g = h & 0xf0000000)\r
+ h ^= g >> 24;\r
+ h &= ~g;\r
+ }\r
+ return h;\r
+}\r
+#endif\r
--- /dev/null
+/**\r
+ Acess v1\r
+ \file elf32.h\r
+ \brief ELF Exeutable Loader\r
+*/\r
+#ifndef _ELF32_H\r
+#define _ELF32_H\r
+\r
+/**\r
+ \struct elf_header_s\r
+ \brief ELF File Header\r
+*/\r
+struct sElf32_Ehdr {\r
+ union {\r
+ char ident[16]; //!< Identifier Bytes\r
+ struct {\r
+ Uint Ident1;\r
+ Uint Ident2;\r
+ Uint HashTable;\r
+ Uint SymTable;\r
+ } misc;\r
+ };\r
+ Uint16 filetype; //!< File Type\r
+ Uint16 machine; //!< Machine / Arch\r
+ Uint32 version; //!< Version (File?)\r
+ Uint32 entrypoint; //!< Entry Point\r
+ Uint32 phoff; //!< Program Header Offset\r
+ Uint32 shoff; //!< Section Header Offset\r
+ Uint32 flags; //!< Flags\r
+ Uint16 headersize; //!< Header Size\r
+ Uint16 phentsize; //!< Program Header Entry Size\r
+ Uint16 phentcount; //!< Program Header Entry Count\r
+ Uint16 shentsize; //!< Section Header Entry Size\r
+ Uint16 shentcount; //!< Section Header Entry Count\r
+ Uint16 shstrindex; //!< Section Header String Table Index\r
+};\r
+\r
+/**\r
+ \name Executable Types\r
+ \{\r
+*/\r
+#define ET_NONE 0 //!< NULL Type\r
+#define ET_REL 1 //!< Relocatable (Object)\r
+#define ET_EXEC 2 //!< Executable\r
+#define ET_DYN 3 //!< Dynamic Library\r
+#define ET_CORE 4 //!< Core?\r
+#define ET_LOPROC 0xFF00 //!< Low Impl Defined\r
+#define ET_HIPROC 0xFFFF //!< High Impl Defined\r
+//! \}\r
+\r
+/**\r
+ \name Section IDs\r
+ \{\r
+*/\r
+#define SHN_UNDEF 0 //!< Undefined Section\r
+#define SHN_LORESERVE 0xFF00 //!< Low Reserved\r
+#define SHN_LOPROC 0xFF00 //!< Low Impl Defined\r
+#define SHN_HIPROC 0xFF1F //!< High Impl Defined\r
+#define SHN_ABS 0xFFF1 //!< Absolute Address (Base: 0, Size: -1)\r
+#define SHN_COMMON 0xFFF2 //!< Common\r
+#define SHN_HIRESERVE 0xFFFF //!< High Reserved\r
+//! \}\r
+\r
+/**\r
+ \enum eElfSectionTypes\r
+ \brief ELF Section Types\r
+*/\r
+enum eElfSectionTypes {\r
+ SHT_NULL, //0\r
+ SHT_PROGBITS, //1\r
+ SHT_SYMTAB, //2\r
+ SHT_STRTAB, //3\r
+ SHT_RELA, //4\r
+ SHT_HASH, //5\r
+ SHT_DYNAMIC, //6\r
+ SHT_NOTE, //7\r
+ SHT_NOBITS, //8\r
+ SHT_REL, //9\r
+ SHT_SHLIB, //A\r
+ SHT_DYNSYM, //B\r
+ SHT_LAST, //C\r
+ SHT_LOPROC = 0x70000000,\r
+ SHT_HIPROC = 0x7fffffff,\r
+ SHT_LOUSER = 0x80000000,\r
+ SHT_HIUSER = 0xffffffff\r
+};\r
+\r
+#define SHF_WRITE 0x1\r
+#define SHF_ALLOC 0x2\r
+#define SHF_EXECINSTR 0x4\r
+#define SHF_MASKPROC 0xf0000000\r
+\r
+struct sElf32_Shent {\r
+ Uint32 name;\r
+ Uint32 type;\r
+ Uint32 flags;\r
+ Uint32 address;\r
+ Uint32 offset;\r
+ Uint32 size;\r
+ Uint32 link;\r
+ Uint32 info;\r
+ Uint32 addralign;\r
+ Uint32 entsize;\r
+}; //sizeof = 40\r
+\r
+struct elf_sym_s {
+ union {\r
+ Uint32 nameOfs;
+ char *name;
+ };\r
+ Uint32 value; //Address\r
+ Uint32 size;\r
+ Uint8 info;\r
+ Uint8 other;\r
+ Uint16 shndx;\r
+};\r
+#define STN_UNDEF 0 // Undefined Symbol\r
+\r
+enum {\r
+ PT_NULL, //0\r
+ PT_LOAD, //1\r
+ PT_DYNAMIC, //2\r
+ PT_INTERP, //3\r
+ PT_NOTE, //4\r
+ PT_SHLIB, //5\r
+ PT_PHDR, //6\r
+ PT_LOPROC = 0x70000000,\r
+ PT_HIPROC = 0x7fffffff\r
+};\r
+\r
+struct sElf32_Phdr {\r
+ Uint32 Type;\r
+ Uint Offset;\r
+ Uint VAddr;\r
+ Uint PAddr;\r
+ Uint32 FileSize;\r
+ Uint32 MemSize;\r
+ Uint32 Flags;\r
+ Uint32 Align;\r
+};\r
+\r
+struct elf32_rel_s {\r
+ Uint32 r_offset;\r
+ Uint32 r_info;\r
+};\r
+\r
+struct elf32_rela_s {\r
+ Uint32 r_offset;\r
+ Uint32 r_info;\r
+ Sint32 r_addend;\r
+};\r
+\r
+enum {\r
+ R_386_NONE=0, // none\r
+ R_386_32, // S+A\r
+ R_386_PC32, // S+A-P\r
+ R_386_GOT32, // G+A-P\r
+ R_386_PLT32, // L+A-P\r
+ R_386_COPY, // none\r
+ R_386_GLOB_DAT, // S\r
+ R_386_JMP_SLOT, // S\r
+ R_386_RELATIVE, // B+A\r
+ R_386_GOTOFF, // S+A-GOT\r
+ R_386_GOTPC, // GOT+A-P\r
+ R_386_LAST // none\r
+};\r
+\r
+#define ELF32_R_SYM(i) ((i)>>8) // Takes an info value and returns a symbol index\r
+#define ELF32_R_TYPE(i) ((i)&0xFF) // Takes an info value and returns a type\r
+#define ELF32_R_INFO(s,t) (((s)<<8)+((t)&0xFF)) // Takes a type and symbol index and returns an info value\r
+\r
+struct elf32_dyn_s {\r
+ Uint16 d_tag;\r
+ Uint32 d_val; //Also d_ptr\r
+};\r
+\r
+enum {\r
+ DT_NULL, //!< Marks End of list\r
+ DT_NEEDED, //!< Offset in strtab to needed library\r
+ DT_PLTRELSZ, //!< Size in bytes of PLT\r
+ DT_PLTGOT, //!< Address of PLT/GOT\r
+ DT_HASH, //!< Address of symbol hash table\r
+ DT_STRTAB, //!< String Table address\r
+ DT_SYMTAB, //!< Symbol Table address\r
+ DT_RELA, //!< Relocation table address\r
+ DT_RELASZ, //!< Size of relocation table\r
+ DT_RELAENT, //!< Size of entry in relocation table\r
+ DT_STRSZ, //!< Size of string table\r
+ DT_SYMENT, //!< Size of symbol table entry\r
+ DT_INIT, //!< Address of initialisation function\r
+ DT_FINI, //!< Address of termination function\r
+ DT_SONAME, //!< String table offset of so name\r
+ DT_RPATH, //!< String table offset of library path\r
+ DT_SYMBOLIC,//!< Reverse order of symbol searching for library, search libs first then executable\r
+ DT_REL, //!< Relocation Entries (Elf32_Rel instead of Elf32_Rela)\r
+ DT_RELSZ, //!< Size of above table (bytes)\r
+ DT_RELENT, //!< Size of entry in above table\r
+ DT_PLTREL, //!< Relocation entry of PLT\r
+ DT_DEBUG, //!< Debugging Entry - Unknown contents\r
+ DT_TEXTREL, //!< Indicates that modifcations to a non-writeable segment may occur\r
+ DT_JMPREL, //!< Address of PLT only relocation entries\r
+ DT_LOPROC = 0x70000000, //!< Low Definable\r
+ DT_HIPROC = 0x7FFFFFFF //!< High Definable\r
+};\r
+\r
+typedef struct sElf32_Ehdr Elf32_Ehdr;\r
+typedef struct sElf32_Phdr Elf32_Phdr;\r
+typedef struct sElf32_Shent Elf32_Shent;\r
+typedef struct elf_sym_s elf_symtab;\r
+typedef struct elf_sym_s Elf32_Sym;\r
+typedef struct elf32_rel_s Elf32_Rel;\r
+typedef struct elf32_rela_s Elf32_Rela;\r
+typedef struct elf32_dyn_s Elf32_Dyn;\r
+\r
+#endif // defined(_EXE_ELF_H)\r
--- /dev/null
+/*\r
+ AcessOS 1\r
+ Dynamic Loader\r
+ By thePowersGang\r
+*/\r
+#include "common.h"\r
+\r
+// === CODE ===\r
+void strcpy(char *dest, char *src)\r
+{\r
+ while(*src) {\r
+ *dest = *src;\r
+ src ++; dest ++;\r
+ }\r
+ *dest = '\0';\r
+}
+
+int strcmp(char *s1, char *s2)
+{
+ while(*s1 == *s2 && *s1 != 0) s1++,s2++;
+ return *s1-*s2;
+}\r
+\r
+int strlen(char *str)\r
+{\r
+ int len = 0;\r
+ while(*str) len++,str++;\r
+ return len;\r
+}
+
--- /dev/null
+/*\r
+ AcessOS 1 - Dynamic Loader\r
+ By thePowersGang\r
+*/\r
+#include "common.h"\r
+\r
+#define DEBUG 0\r
+\r
+#if DEBUG\r
+# define DEBUGS(v...) SysDebug(v)\r
+#else\r
+# define DEBUGS(v...) \r
+#endif\r
+\r
+// === PROTOTYPES ===\r
+Uint IsFileLoaded(char *file);
+ int GetSymbolFromBase(Uint base, char *name, Uint *ret);\r
+\r
+// === GLOABLS ===\r
+#define MAX_LOADED_LIBRARIES 64\r
+#define MAX_STRINGS_BYTES 4096\r
+struct {\r
+ Uint Base;\r
+ char *Name;\r
+} gLoadedLibraries[MAX_LOADED_LIBRARIES];\r
+char gsLoadedStrings[MAX_STRINGS_BYTES];\r
+char *gsNextAvailString = gsLoadedStrings;\r
+//tLoadLib *gpLoadedLibraries = NULL;\r
+\r
+// === CODE ===\r
+Uint LoadLibrary(char *filename, char *SearchDir, char **envp)\r
+{\r
+ char sTmpName[1024] = "/Acess/Libs/";\r
+ Uint iArg;\r
+ void (*fEntry)(int, int, char *[], char**);\r
+ \r
+ DEBUGS("LoadLibrary: (filename='%s', envp=0x%x)\n", filename, envp);\r
+ \r
+ // Create Temp Name\r
+ strcpy(&sTmpName[12], filename);\r
+ DEBUGS(" LoadLibrary: sTmpName='%s'\n", sTmpName);\r
+ \r
+ if( (iArg = IsFileLoaded(sTmpName)) )\r
+ return iArg;\r
+ \r
+ // Load Library\r
+ iArg = SysLoadBin(sTmpName, (Uint*)&fEntry);\r
+ if(iArg == 0) {\r
+ DEBUGS("LoadLibrary: RETURN 0\n");\r
+ return 0;\r
+ }\r
+ \r
+ DEBUGS(" LoadLibrary: iArg=0x%x, iEntry=0x%x\n", iArg, fEntry);\r
+ \r
+ // Load Symbols\r
+ fEntry = (void*)DoRelocate( iArg, envp, sTmpName );\r
+ \r
+ // Call Entrypoint\r
+ DEBUGS(" LoadLibrary: '%s' Entry 0x%x\n", filename, fEntry);\r
+ fEntry(iArg, 0, NULL, envp);\r
+ \r
+ DEBUGS("LoadLibrary: RETURN 1\n");\r
+ return iArg;\r
+}
+\r
+/**\r
+ * \fn Uint IsFileLoaded(char *file)\r
+ * \brief Determine if a file is already loaded\r
+ */\r
+Uint IsFileLoaded(char *file)\r
+{\r
+ int i;\r
+ DEBUGS("IsFileLoaded: (file='%s')\n", file);\r
+ for( i = 0; i < MAX_LOADED_LIBRARIES; i++ )\r
+ {\r
+ if(gLoadedLibraries[i].Base == 0) break; // Last entry has Base set to NULL\r
+ if(strcmp(gLoadedLibraries[i].Name, file) == 0) {\r
+ DEBUGS("IsFileLoaded: Found %i (0x%x)\n", i, gLoadedLibraries[i].Base);\r
+ return gLoadedLibraries[i].Base;\r
+ }\r
+ }\r
+ DEBUGS("IsFileLoaded: Not Found\n");\r
+ return 0;\r
+}\r
+\r
+/**\r
+ * \fn void AddLoaded(char *File, Uint base)\r
+ * \brief Add a file to the loaded list\r
+ */
+void AddLoaded(char *File, Uint base)
+{\r
+ int i, length;\r
+ char *name = gsNextAvailString;\r
+ \r
+ DEBUGS("AddLoaded: (File='%s', base=0x%x)", File, base);\r
+ \r
+ // Find a free slot\r
+ for( i = 0; i < MAX_LOADED_LIBRARIES; i ++ )\r
+ {\r
+ if(gLoadedLibraries[i].Base == 0) break;\r
+ }\r
+ if(i == MAX_LOADED_LIBRARIES) {\r
+ SysDebug("ERROR - ld-acess.so has run out of load slots!");\r
+ return;\r
+ }\r
+ \r
+ // Check space in string buffer\r
+ length = strlen(File);\r
+ if(&name[length+1] >= &gsLoadedStrings[MAX_STRINGS_BYTES]) {\r
+ SysDebug("ERROR - ld-acess.so has run out of string buffer memory!");\r
+ return;\r
+ }\r
+ \r
+ // Set information\r
+ gLoadedLibraries[i].Base = base;\r
+ strcpy(name, File);\r
+ gLoadedLibraries[i].Name = name;\r
+ gsNextAvailString = &name[length+1];\r
+ DEBUGS("'%s' (0x%x) loaded as %i\n", name, base, i);\r
+ return;
+}\r
+\r
+/**\r
+ * \fn void Unload(Uint Base)\r
+ */\r
+void Unload(Uint Base)\r
+{ \r
+ int i, j;\r
+ int id;\r
+ char *str;\r
+ for( id = 0; id < MAX_LOADED_LIBRARIES; id++ )\r
+ {\r
+ if(gLoadedLibraries[id].Base == Base) break;\r
+ }\r
+ if(id == MAX_LOADED_LIBRARIES) return;\r
+ \r
+ // Unload Binary\r
+ SysUnloadBin( Base );\r
+ // Save String Pointer\r
+ str = gLoadedLibraries[id].Name;\r
+ \r
+ // Compact Loaded List\r
+ j = id;\r
+ for( i = j + 1; i < MAX_LOADED_LIBRARIES; i++, j++ )\r
+ {\r
+ if(gLoadedLibraries[i].Base == 0) break;\r
+ // Compact String\r
+ strcpy(str, gLoadedLibraries[i].Name);\r
+ str += strlen(str)+1;\r
+ // Compact Entry\r
+ gLoadedLibraries[j].Base = gLoadedLibraries[i].Base;\r
+ gLoadedLibraries[j].Name = str;\r
+ }\r
+ \r
+ // NULL Last Entry\r
+ gLoadedLibraries[j].Base = 0;\r
+ gLoadedLibraries[j].Name = NULL;\r
+ // Save next string\r
+ gsNextAvailString = str;\r
+}\r
+\r
+/**
+ \fn Uint GetSymbol(char *name)
+ \brief Gets a symbol value from a loaded library
+*/
+Uint GetSymbol(char *name)
+{\r
+ int i;
+ Uint ret;\r
+ for(i=0;i<sizeof(gLoadedLibraries)/sizeof(gLoadedLibraries[0]);i++)\r
+ {\r
+ if(gLoadedLibraries[i].Base == 0) break;
+// SysDebug(" GetSymbol: Trying 0x%x\n", gLoadedLibraries[i]);
+ if(GetSymbolFromBase(gLoadedLibraries[i].Base, name, &ret)) return ret;\r
+ }\r
+ SysDebug("GetSymbol: === Symbol '%s' not found ===\n", name);\r
+ return 0;
+}
+
+/**
+ \fn int GetSymbolFromBase(Uint base, char *name, Uint *ret)
+ \breif Gets a symbol from a specified library
+*/
+int GetSymbolFromBase(Uint base, char *name, Uint *ret)
+{
+ if(*(Uint32*)base == (0x7F|('E'<<8)|('L'<<16)|('F'<<24)))
+ return ElfGetSymbol(base, name, ret);
+ if(*(Uint16*)base == ('M'|('Z'<<8)))
+ return PE_GetSymbol(base, name, ret);
+ return 0;
+}
+
--- /dev/null
+/*\r
+ AcessOS 1 - Dynamic Loader\r
+ By thePowersGang\r
+*/\r
+#include "common.h"\r
+\r
+// === PROTOTYPES ===\r
+ int DoRelocate( Uint base, char **envp, char *Filename );\r
+ int CallUser(Uint entry, Uint SP);\r
+ int ElfRelocate(void *Base, char *envp[], char *Filename);\r
+ int PE_Relocate(void *Base, char *envp[], char *Filename);\r
+\r
+// === Imports ===\r
+extern void gLinkedBase;\r
+ \r
+// === CODE ===\r
+/**\r
+ \fn int SoMain(Uint base, int argc, char *argv[], char **envp)\r
+ \brief Library entry point\r
+ \note This is the entrypoint for the library\r
+*/\r
+int SoMain(Uint base, int arg1)\r
+{\r
+ int ret;\r
+ \r
+ SysDebug("SoMain: base = 0x%x", base);\r
+ SysDebug("SoMain: arg1 = 0x%x", arg1);\r
+ \r
+ // - Assume that the file pointer will be less than 4096\r
+ if(base < 0x1000) {\r
+ SysDebug("ld-acess - SoMain: Passed file pointer %i\n", base);\r
+ SysExit();\r
+ for(;;);\r
+ }\r
+ // Check if we are being called directly\r
+ if(base == (Uint)&gLinkedBase) {\r
+ SysDebug("ld-acess should not be directly called\n");\r
+ SysExit();\r
+ for(;;);\r
+ }\r
+ \r
+ // Otherwise do relocations\r
+ //ret = DoRelocate( base, envp, "Executable" );\r
+ ret = DoRelocate( base, NULL, "Executable" );\r
+ if( ret == 0 ) {\r
+ SysDebug("ld-acess - SoMain: Relocate failed, base=0x%x\n", base);\r
+ SysExit();\r
+ for(;;);\r
+ }\r
+ \r
+ // And call user\r
+ //SysDebug("Calling User at 0x%x\n", ret);\r
+ CallUser( ret, (Uint)&arg1 );\r
+ \r
+ return 0;\r
+}\r
+\r
+/**\r
+ \fn int DoRelocate(Uint base, char **envp)\r
+ \brief Relocates an in-memory image\r
+*/\r
+int DoRelocate( Uint base, char **envp, char *Filename )\r
+{\r
+ // Load Executable\r
+ if(*(Uint*)base == (0x7F|('E'<<8)|('L'<<16)|('F'<<24)))\r
+ return ElfRelocate((void*)base, envp, Filename);\r
+ if(*(Uint16*)base == ('M'|('Z'<<8)))\r
+ return PE_Relocate((void*)base, envp, Filename);\r
+ \r
+ SysDebug("ld-acess - DoRelocate: Unkown file format '0x%x 0x%x 0x%x 0x%x'\n",\r
+ *(Uint8*)(base), *(Uint8*)(base+1), *(Uint8*)(base+2), *(Uint8*)(base+3) );\r
+ SysDebug("ld-acess - DoRelocate: File '%s'\n", Filename);\r
+ SysExit();\r
+ for(;;);\r
+}\r
+\r
+/**\r
+ \fn int CallUser(Uint entry, Uint sp)\r
+*/\r
+int CallUser(Uint entry, Uint sp)\r
+{\r
+ SysDebug("CallUser: (entry=0x%x, sp=0x%x)", entry, sp);\r
+ *(Uint*)(sp-4) = 0; // Clear return address\r
+ __asm__ __volatile__ (\r
+ "mov %%eax, %%esp;\n\t"\r
+ "jmp *%%ecx"\r
+ : : "a"(sp-4), "c"(entry));\r
+ for(;;);\r
+}\r
--- /dev/null
+/*\r
+ * Acess v1\r
+ * Portable Executable Loader\r
+ */\r
+#include "common.h"\r
+#include "pe.h"\r
+\r
+#define PE_DEBUG 0\r
+#define DEBUG (ACESS_DEBUG|PE_DEBUG)\r
+\r
+//#define DLL_BASE_PATH "/Acess/Windows/"\r
+#define DLL_BASE_PATH NULL\r
+\r
+#if DEBUG\r
+# define DEBUGS(v...) SysDebug(v)\r
+#else\r
+# define DEBUGS(v...)\r
+#endif\r
+\r
+// === PROTOTYPES ===\r
+ int PE_Relocate(void *Base, char **envp, char *Filename);\r
+char *PE_int_GetTrueFile(char *file);\r
+ int PE_int_GetForwardSymbol(char *Fwd, Uint *Value);\r
+\r
+// === CODE ===\r
+int PE_Relocate(void *Base, char *envp[], char *Filename)\r
+{\r
+ tPE_DOS_HEADER *dosHdr = Base;\r
+ tPE_IMAGE_HEADERS *peHeaders;\r
+ tPE_DATA_DIR *directory;\r
+ tPE_IMPORT_DIR *impDir;\r
+ tPE_HINT_NAME *name;\r
+ Uint32 *importTab, *aIAT;\r
+ int i, j;\r
+ Uint iBase = (Uint)Base;\r
+ Uint iLibBase;\r
+ \r
+ DEBUGS("PE_Relocate: (Base=0x%x)\n", Base);\r
+ \r
+ peHeaders = Base + dosHdr->PeHdrOffs;\r
+ \r
+ directory = peHeaders->OptHeader.Directory;\r
+ \r
+ // === Load Import Tables\r
+ impDir = Base + directory[PE_DIR_IMPORT].RVA;\r
+ for( i = 0; impDir[i].DLLName != NULL; i++ )\r
+ {\r
+ impDir[i].DLLName += iBase;\r
+ impDir[i].ImportLookupTable += iBase/4;\r
+ impDir[i].ImportAddressTable += iBase/4;\r
+ DEBUGS(" PE_Relocate: DLL Required '%s'(0x%x)\n", impDir[i].DLLName, impDir[i].DLLName);\r
+ iLibBase = LoadLibrary(PE_int_GetTrueFile(impDir[i].DLLName), DLL_BASE_PATH, envp);\r
+ if(iLibBase == 0) {\r
+ SysDebug("Unable to load required library '%s'\n", impDir[i].DLLName);\r
+ return 0;\r
+ }\r
+ DEBUGS(" PE_Relocate: Loaded as 0x%x\n", iLibBase);\r
+ importTab = impDir[i].ImportLookupTable;\r
+ aIAT = impDir[i].ImportAddressTable;\r
+ for( j = 0; importTab[j] != 0; j++ )\r
+ {\r
+ if( importTab[j] & 0x80000000 )\r
+ DEBUGS(" PE_Relocate: Import Ordinal %i\n", importTab[j] & 0x7FFFFFFF);\r
+ else\r
+ {\r
+ name = (void*)( iBase + importTab[j] );\r
+ DEBUGS(" PE_Relocate: Import Name '%s', Hint 0x%x\n", name->Name, name->Hint);\r
+ if( GetSymbolFromBase(iLibBase, name->Name, (Uint*)&aIAT[j]) == 0 ) {\r
+ SysDebug("Unable to find symbol '%s' in library '%s'\n", name->Name, impDir[i].DLLName);\r
+ return 0;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ \r
+ #if DEBUG\r
+ for(i=0;i<PE_DIR_LAST;i++) {\r
+ if(directory[i].RVA == 0) continue;\r
+ SysDebug("directory[%i] = {RVA=0x%x,Size=0x%x}\n", i, directory[i].RVA, directory[i].Size);\r
+ }\r
+ #endif\r
+ \r
+ DEBUGS("PE_Relocate: RETURN 0x%x\n", iBase + peHeaders->OptHeader.EntryPoint);\r
+ \r
+ return iBase + peHeaders->OptHeader.EntryPoint;\r
+}\r
+\r
+/**\r
+ * \fn int PE_GetSymbol(Uint Base, char *Name, Uint *Ret)\r
+ */\r
+int PE_GetSymbol(Uint Base, char *Name, Uint *Ret)\r
+{\r
+ tPE_DOS_HEADER *dosHdr = (void*)Base;\r
+ tPE_IMAGE_HEADERS *peHeaders;\r
+ tPE_DATA_DIR *directory;\r
+ tPE_EXPORT_DIR *expDir;\r
+ Uint32 *nameTable, *addrTable;\r
+ Uint16 *ordTable;\r
+ int i;\r
+ int symbolCount;\r
+ char *name;\r
+ Uint retVal;\r
+ Uint expLen;\r
+ \r
+ peHeaders = (void*)( Base + dosHdr->PeHdrOffs );\r
+ directory = peHeaders->OptHeader.Directory;\r
+ \r
+ expDir = (void*)( Base + directory[PE_DIR_EXPORT].RVA );\r
+ expLen = directory[PE_DIR_EXPORT].Size;\r
+ symbolCount = expDir->NumNamePointers;\r
+ nameTable = (void*)( Base + expDir->NamePointerRVA );\r
+ ordTable = (void*)( Base + expDir->OrdinalTableRVA );\r
+ addrTable = (void*)( Base + expDir->AddressRVA );\r
+ //DEBUGS(" PE_GetSymbol: %i Symbols\n", symbolCount);\r
+ for(i=0;i<symbolCount;i++)\r
+ {\r
+ name = (char*)( Base + nameTable[i] );\r
+ //DEBUGS(" PE_GetSymbol: '%s' = 0x%x\n", name, Base + addrTable[ ordTable[i] ]);\r
+ if(strcmp(name, Name) == 0)\r
+ {\r
+ retVal = Base + addrTable[ ordTable[i] ];\r
+ // Check for forwarding\r
+ if((Uint)expDir < retVal && retVal < (Uint)expDir + expLen) {\r
+ char *fwd = (char*)retVal;\r
+ DEBUGS(" PE_GetSymbol: '%s' forwards to '%s'\n", name, fwd);\r
+ return PE_int_GetForwardSymbol(fwd, Ret);\r
+ }\r
+ *Ret = retVal;\r
+ return 1;\r
+ }\r
+ }\r
+ return 0;\r
+}\r
+\r
+/**\r
+ * \fn char *PE_int_GetTrueFile(char *file)\r
+ * \brief Get the true file name\r
+ */\r
+char *PE_int_GetTrueFile(char *file)\r
+{\r
+ int i;\r
+ if(file[0] != ':') return file;\r
+\r
+ // Translate name\r
+ for(i=1;file[i];i++)\r
+ if(file[i] == '_')\r
+ file[i] = '.';\r
+ \r
+ return &file[1];\r
+}\r
+\r
+int PE_int_GetForwardSymbol(char *Fwd, Uint *Value)\r
+{\r
+ char *libname;\r
+ char *sym;\r
+ int i;\r
+ Uint libbase;\r
+ int ret;\r
+ \r
+ // -- Find seperator\r
+ // PE spec says that there sould only be one, but the string may\r
+ // be mutilated in the loader\r
+ for(i=0;Fwd[i]!='\0';i++);\r
+ for(;i&&Fwd[i]!='.';i--);\r
+ \r
+ Fwd[i] = '\0';\r
+ sym = &Fwd[i+1];\r
+ \r
+ libname = PE_int_GetTrueFile(Fwd);\r
+ \r
+ DEBUGS(" PE_int_GetForwardSymbol: Get '%s' from '%s'\n", sym, libname);\r
+ \r
+ libbase = LoadLibrary(libname, DLL_BASE_PATH, NULL);\r
+ ret = GetSymbolFromBase(libbase, sym, Value);\r
+ if(!ret) {\r
+ SysDebug(" PE_int_GetForwardSymbol: Unable to find '%s' in '%s'\n", sym, libname);\r
+ }\r
+ Fwd[i] = '.';\r
+ return ret;\r
+}\r
--- /dev/null
+/*\r
+AcessOS/AcessBasic v1\r
+PE Loader\r
+HEADER\r
+*/\r
+#ifndef _EXE_PE_H\r
+#define _EXE_PE_H\r
+\r
+enum ePE_MACHINES {\r
+ PE_MACHINE_I386 = 0x14c, // Intel 386+\r
+ PE_MACHINE_IA64 = 0x200 // Intel-64\r
+};\r
+\r
+enum ePE_DIR_INDX {\r
+ PE_DIR_EXPORT, // 0\r
+ PE_DIR_IMPORT, // 1\r
+ PE_DIR_RESOURCE, // 2\r
+ PE_DIR_EXCEPTION, // 3\r
+ PE_DIR_SECRURITY, // 4\r
+ PE_DIR_RELOC, // 5\r
+ PE_DIR_DEBUG, // 6\r
+ PE_DIR_COPYRIGHT, // 7\r
+ PE_DIR_ARCHITECTURE,// 8\r
+ PE_DIR_GLOBALPTR, // 9\r
+ PE_DIR_TLS, // 10\r
+ PE_DIR_LOAD_CFG, // 11\r
+ PE_DIR_BOUND_IMPORT,// 12\r
+ PE_DIR_IAT, // 13\r
+ PE_DIR_DELAY_IMPORT,// 14\r
+ PE_DIR_COM_DESCRIPTOR, //15\r
+ PE_DIR_LAST\r
+};\r
+\r
+typedef struct {\r
+ Uint32 RVA;\r
+ Uint32 Size;\r
+} tPE_DATA_DIR;\r
+\r
+typedef struct {\r
+ Uint32 *ImportLookupTable; //0x80000000 is Ordninal Flag\r
+ Uint32 TimeStamp;\r
+ Uint32 FowarderChain;\r
+ char *DLLName;\r
+ Uint32 *ImportAddressTable; // Array of Addresses - To be edited by loader\r
+} tPE_IMPORT_DIR;\r
+\r
+typedef struct {\r
+ Uint32 Flags;\r
+ Uint32 Timestamp;\r
+ Uint16 MajorVer;\r
+ Uint16 MinorVer;\r
+ Uint32 NameRVA; // DLL Name\r
+ Uint32 OrdinalBase;\r
+ Uint32 NumAddresses;\r
+ Uint32 NumNamePointers;\r
+ Uint32 AddressRVA;\r
+ Uint32 NamePointerRVA;\r
+ Uint32 OrdinalTableRVA;\r
+} tPE_EXPORT_DIR;\r
+\r
+typedef struct {\r
+ Uint16 Hint;\r
+ char Name[]; // Zero Terminated String\r
+} tPE_HINT_NAME;\r
+\r
+typedef struct {\r
+ char Name[8];\r
+ Uint32 VirtualSize;\r
+ Uint32 RVA;\r
+ Uint32 RawSize;\r
+ Uint32 RawOffs;\r
+ Uint32 RelocationsPtr; //Set to 0 in executables\r
+ Uint32 LineNumberPtr; //Pointer to Line Numbers\r
+ Uint16 RelocationCount; // Set to 0 in executables\r
+ Uint16 LineNumberCount;\r
+ Uint32 Flags;\r
+} tPE_SECTION_HEADER;\r
+\r
+#define PE_SECTION_FLAG_CODE 0x00000020 // Section contains executable code.\r
+#define PE_SECTION_FLAG_IDATA 0x00000040 // Section contains initialized data.\r
+#define PE_SECTION_FLAG_UDATA 0x00000080 // Section contains uninitialized data.\r
+#define PE_SECTION_FLAG_DISCARDABLE 0x02000000 // Section can be discarded as needed.\r
+#define PE_SECTION_FLAG_MEM_NOT_CACHED 0x04000000 // Section cannot be cached.\r
+#define PE_SECTION_FLAG_MEM_NOT_PAGED 0x08000000 // Section is not pageable.\r
+#define PE_SECTION_FLAG_MEM_SHARED 0x10000000 // Section can be shared in memory.\r
+#define PE_SECTION_FLAG_MEM_EXECUTE 0x20000000 // Section can be executed as code.\r
+#define PE_SECTION_FLAG_MEM_READ 0x40000000 // Section can be read.\r
+#define PE_SECTION_FLAG_MEM_WRITE 0x80000000 // Section can be written to.\r
+\r
+typedef struct {\r
+ Uint32 page;\r
+ Uint32 size;\r
+ Uint16 ents[];\r
+} tPE_FIXUP_BLOCK;\r
+\r
+//File Header\r
+typedef struct {\r
+ Uint16 Machine;\r
+ Uint16 SectionCount;\r
+ Uint32 CreationTimestamp;\r
+ Uint32 SymbolTableOffs;\r
+ Uint32 SymbolCount;\r
+ Uint16 OptHeaderSize;\r
+ Uint16 Flags;\r
+} tPE_FILE_HEADER;\r
+\r
+typedef struct {\r
+ Uint16 Magic; //0x10b: 32Bit, 0x20b: 64Bit\r
+ Uint16 LinkerVersion;\r
+ Uint32 CodeSize; //Sum of all Code Segment Sizes\r
+ Uint32 DataSize; //Sum of all Intialised Data Segments\r
+ Uint32 BssSize; //Sum of all Unintialised Data Segments\r
+ Uint32 EntryPoint;\r
+ Uint32 CodeRVA;\r
+ Uint32 DataRVA;\r
+ Uint32 ImageBase; //Prefered Base Address\r
+ Uint32 SectionAlignment;\r
+ Uint32 FileAlignment;\r
+ Uint32 WindowsVersion; //Unused/Irrelevent\r
+ Uint32 ImageVersion; //Unused/Irrelevent\r
+ Uint32 SubsystemVersion; //Unused, Set to 4\r
+ Uint32 Win32Version; //Unused\r
+ Uint32 ImageSize;\r
+ Uint32 HeaderSize;\r
+ Uint32 Checksum; //Unknown Method, Can be set to 0\r
+ Uint16 Subsystem; //Required Windows Subsystem (None, GUI, Console)\r
+ Uint16 DllFlags;\r
+ Uint32 MaxStackSize; //Reserved Stack Size\r
+ Uint32 InitialStackSize; //Commited Stack Size\r
+ Uint32 InitialReservedHeap; // Reserved Heap Size\r
+ Uint32 InitialCommitedHeap; // Commited Heap Size\r
+ Uint32 LoaderFlags; // Obselete\r
+ Uint32 NumberOfDirEntries;\r
+ tPE_DATA_DIR Directory[16];\r
+} tPE_OPT_HEADER;\r
+\r
+// Root Header\r
+typedef struct {\r
+ Uint32 Signature;\r
+ tPE_FILE_HEADER FileHeader;\r
+ tPE_OPT_HEADER OptHeader;\r
+} tPE_IMAGE_HEADERS;\r
+\r
+typedef struct {\r
+ Uint16 Ident;\r
+ Uint16 Resvd[29];\r
+ Uint32 PeHdrOffs; // File address of new exe header\r
+} tPE_DOS_HEADER;\r
+\r
+#endif\r
--- /dev/null
+#
+#
+#
+
+AS = nasm
+LD = ld
+STRIP = strip
+RM = rm -f
+
+ASFLAGS = -felf
+LDFLAGS = -nostdlib -shared -I/Acess/Libs/ld-acess.so -e SoMain
+
+OBJ = core.ao vfs.ao mm.ao
+BIN = ../libacess.so
+
+.PHONY: all clean
+
+all: $(BIN)
+
+clean:
+ $(RM) $(BIN) $(OBJ)
+
+$(BIN): $(OBJ)
+ $(LD) $(LDFLAGS) -o $(BIN) $(OBJ)
+ $(STRIP) $(BIN)
+ cp $(BIN) /mnt/AcessHDD/Acess2/Libs
+
+%.ao: %.asm syscalls.inc.asm
+ $(AS) $(ASFLAGS) -o $@ $<
--- /dev/null
+;
+; Acess2 System Interface
+;
+%include "syscalls.inc.asm"
+
+[BITS 32]
+[section .data]
+[global _errno]
+_errno:
+ dd 0
+
+[section .text]
+[global SoMain:func]
+SoMain:
+ ret
+
+; --- Process Controll ---
+SYSCALL1 _exit, SYS_EXIT
+SYSCALL2 clone, SYS_CLONE
+SYSCALL2 kill, SYS_KILL
+SYSCALL2 signal, SYS_SIGNAL
+SYSCALL0 yield, SYS_YIELD
+SYSCALL0 sleep, SYS_SLEEP
+SYSCALL1 wait, SYS_WAIT
+
+SYSCALL0 gettid, SYS_GETTID
+SYSCALL0 getpid, SYS_GETPID
+SYSCALL0 getuid, SYS_GETUID
+SYSCALL0 getgid, SYS_GETGID
+
+SYSCALL0 setuid, SYS_SETUID
+SYSCALL0 setgid, SYS_SETGID
+
+SYSCALL1 SysSetName, SYS_SETNAME
+SYSCALL2 SysGetName, SYS_GETNAME
+
+SYSCALL1 SysSetPri, SYS_SETPRI
+
+SYSCALL3 SysSendMessage, SYS_SENDMSG
+SYSCALL3 SysGetMessage, SYS_GETMSG
+
+SYSCALL3 SysSpawn, SYS_SPAWN
+SYSCALL3 execve, SYS_EXECVE
+SYSCALL2 SysLoadBin, SYS_LOADBIN
+
--- /dev/null
+;
+; Acess2 System Interface
+;
+%include "syscalls.inc.asm"
+
+[BITS 32]
+[extern _errno]
+
+[section .text]
+SYSCALL0 _SysGetPhys, SYS_GETPHYS ; uint64_t _SysGetPhys(uint addr)
+SYSCALL1 _SysAllocate, SYS_ALLOCATE ; uint64_t _SysAllocate(uint addr)
--- /dev/null
+; ========================
+; AcssMicro - System Calls
+; ========================
+
+%include "../../../Kernel/include/syscalls.inc.asm"
+
+; System Call - No Arguments
+%macro SYSCALL0 2
+[global %1:func]
+%1:
+ push ebx
+ mov eax, %2
+ int 0xAC
+ mov [_errno], ebx
+ pop ebx
+ ret
+%endmacro
+
+; System Call - 1 Argument
+%macro SYSCALL1 2
+[global %1:func]
+%1:
+ push ebp
+ mov ebp, esp
+ push ebx
+ mov eax, %2
+ mov ebx, [ebp+8]
+ int 0xAC
+ mov [_errno], ebx
+ pop ebx
+ pop ebp
+ ret
+%endmacro
+
+; System Call - 2 Arguments
+%macro SYSCALL2 2
+[global %1:func]
+%1:
+ push ebp
+ mov ebp, esp
+ push ebx
+ mov eax, %2
+ mov ebx, [ebp+8]
+ mov ecx, [ebp+12]
+ int 0xAC
+ mov [_errno], ebx
+ pop ebx
+ pop ebp
+ ret
+%endmacro
+
+; System Call - 3 Arguments
+%macro SYSCALL3 2
+[global %1:func]
+%1:
+ push ebp
+ mov ebp, esp
+ push ebx
+ mov eax, %2
+ mov ebx, [ebp+8]
+ mov ecx, [ebp+12]
+ mov edx, [ebp+16]
+ int 0xAC
+ mov [_errno], ebx
+ pop ebx
+ pop ebp
+ ret
+%endmacro
+
+; System Call - 4 Arguments
+%macro SYSCALL4 2
+[global %1:func]
+%1:
+ push ebp
+ mov ebp, esp
+ push ebx
+ push edi
+ mov eax, %2
+ mov ebx, [ebp+8]
+ mov ecx, [ebp+12]
+ mov edx, [ebp+16]
+ mov edi, [ebp+20]
+ int 0xAC
+ mov [_errno], ebx
+ pop edi
+ pop ebx
+ pop ebp
+ ret
+%endmacro
--- /dev/null
+;
+; Acess2 System Interface
+;
+%include "syscalls.inc.asm"
+
+[BITS 32]
+[extern _errno]
+
+[section .text]
+SYSCALL2 open, SYS_OPEN
+SYSCALL3 reopen, SYS_REOPEN
+SYSCALL1 close, SYS_CLOSE
+SYSCALL3 read, SYS_READ
+SYSCALL4 write, SYS_WRITE ; int, int64_t, void*
+SYSCALL4 seek, SYS_SEEK ; int, int64_t, int
+SYSCALL2 finfo, SYS_FINFO
--- /dev/null
+# AcessOS Basic C Library\r
+# Makefile\r
+\r
+CC = gcc\r
+AS = nasm\r
+RM = @rm -f\r
+LD = ld\r
+OBJDUMP = objdump\r
+ACESSDIR = /home/hodgeja/Projects/Acess2\r
+\r
+CPPFLAGS = -I$(ACESSDIR)/Usermode/include\r
+CFLAGS = -Wall -fPIC -fno-builtin -fno-stack-protector $(CPPFLAGS)\r
+ASFLAGS = -felf\r
+LDFLAGS = -x -shared -soname libc.so.1 -Map map.txt -e SoMain -L$(ACESSDIR)/Usermode/Libraries -lacess\r
+\r
+OBJ_LIBC = heap.o stdlib.o stub.o env.o fileIO.o signals.o\r
+BIN = ../libc.so.1\r
+\r
+.PHONY: all clean\r
+\r
+all: $(BIN) $(OBJ_LIBC)\r
+\r
+clean:\r
+ $(RM) $(BIN) $(OBJ_LIBC)\r
+\r
+# Core C Library\r
+$(BIN): $(OBJ_LIBC)\r
+ @echo --- ld -shared -o $@\r
+ @$(LD) $(LDFLAGS) $(OBJ_LIBC) -o $@\r
+ $(OBJDUMP) -d $@ > libc.so.1.dsm\r
+ $(OBJDUMP) -x -r -R $@ > libc.so.1.dmp\r
+ cp ../libc.so.1 ../libc.so\r
+ cp ../libc.so.1 /mnt/AcessHDD/Acess2/Libs/\r
+\r
+# C Runtime 0\r
+../crt0.o: crt0.asm\r
+ @echo --- $(AS) -o $@\r
+ @$(AS) $(ASFLAGS) -o $@ $<\r
+\r
+$(filter %.o, $(OBJ_LIBC)): %.o: %.c config.h\r
+ @echo --- $(CC) -o $@\r
+ @$(CC) $(CFLAGS) -DBUILD_SO -o $@ -c $<\r
+\r
+$(filter %.ao, $(OBJ_LIBC)): %.ao: %.asm\r
+ @echo --- $(AS) -o $@\r
+ @$(AS) $(ASFLAGS) -o $@ $<\r
--- /dev/null
+/*
+AcessOS C Library
+- Environment Handler
+*/
+#include <stdlib.h>
+
+// === GLOBALS ===
+char **_envp = NULL;
+
+// === CODE ===
+char *getenv(const char *name)
+{
+ char **env;
+ char *str;
+ int len;
+
+ if(!_envp) return NULL;
+ if(!name) return NULL;
+
+
+ len = strlen((char*)name);
+
+ env = _envp;
+ while(*env) {
+ str = *env;
+ if(str[len] == '=' && strncmp((char*)name, str, len) == 0) {
+ return str+len+1;
+ }
+ env ++;
+ }
+
+ return NULL;
+}
--- /dev/null
+/*\r
+AcessOS Basic C Library\r
+*/\r
+#include "config.h"\r
+#include <acess/sys.h>\r
+#include <stdlib.h>\r
+#include <stdio.h>\r
+#include "stdio_int.h"\r
+\r
+#define DEBUG_BUILD 0\r
+\r
+// === CONSTANTS ===\r
+\r
+// === PROTOTYPES ===\r
+struct sFILE *get_file_struct();\r
+\r
+// === GLOBALS ===\r
+struct sFILE _iob[STDIO_MAX_STREAMS]; // IO Buffer\r
+\r
+// === CODE ===\r
+/**\r
+ * \fn FILE *freopen(FILE *fp, char *file, char *mode)\r
+ */\r
+FILE *freopen(FILE *fp, char *file, char *mode)\r
+{\r
+ int openFlags = 0;\r
+ int i;\r
+ \r
+ // Sanity Check Arguments\r
+ if(!fp || !file || !mode) return NULL;\r
+ \r
+ if(fp->Flags) {\r
+ fflush(fp);\r
+ close(fp->FD);\r
+ }\r
+ \r
+ // Get main mode\r
+ switch(mode[0])\r
+ {\r
+ case 'r': fp->Flags = FILE_FLAG_MODE_READ; break;\r
+ case 'w': fp->Flags = FILE_FLAG_MODE_WRITE; break;\r
+ case 'a': fp->Flags = FILE_FLAG_MODE_APPEND; break;\r
+ case 'x': fp->Flags = FILE_FLAG_MODE_EXEC; break;\r
+ default:\r
+ return NULL;\r
+ }\r
+ // Get Modifiers\r
+ for(i=1;mode[i];i++)\r
+ {\r
+ switch(mode[i])\r
+ {\r
+ case '+': fp->Flags |= FILE_FLAG_M_EXT;\r
+ }\r
+ }\r
+ \r
+ // Get Open Flags\r
+ switch(mode[0])\r
+ {\r
+ // Read\r
+ case 'r': openFlags = OPENFLAG_READ;\r
+ if(fp->Flags & FILE_FLAG_M_EXT)\r
+ openFlags |= OPENFLAG_WRITE;\r
+ break;\r
+ // Write\r
+ case 'w': openFlags = OPENFLAG_WRITE;\r
+ if(fp->Flags & FILE_FLAG_M_EXT)\r
+ openFlags |= OPENFLAG_READ;\r
+ break;\r
+ // Execute\r
+ case 'x': openFlags = OPENFLAG_EXEC;\r
+ break;\r
+ }\r
+ \r
+ //Open File\r
+ fp->FD = reopen(fp->FD, file, openFlags);\r
+ if(fp->FD == -1) {\r
+ fp->Flags = 0;\r
+ return NULL;\r
+ }\r
+ \r
+ if(mode[0] == 'a') {\r
+ seek(fp->FD, 0, SEEK_END); //SEEK_END\r
+ }\r
+ \r
+ return fp;\r
+}\r
+/**\r
+ \fn FILE *fopen(char *file, char *mode)\r
+ \brief Opens a file and returns the pointer\r
+ \param file String - Filename to open\r
+ \param mode Mode to open in\r
+*/\r
+FILE *fopen(char *file, char *mode)\r
+{\r
+ FILE *retFile;\r
+ \r
+ // Sanity Check Arguments\r
+ if(!file || !mode) return NULL;\r
+ \r
+ // Create Return Structure\r
+ retFile = get_file_struct();\r
+ \r
+ return freopen(retFile, file, mode);\r
+}\r
+\r
+void fclose(FILE *fp)\r
+{\r
+ close(fp->FD);\r
+ free(fp);\r
+}\r
+\r
+void fflush(FILE *fp)\r
+{\r
+ ///\todo Implement\r
+}\r
+\r
+/**\r
+ * \fn int fprintf(FILE *fp, const char *format, ...)\r
+ * \brief Print a formatted string to a stream\r
+ */\r
+int fprintf(FILE *fp, const char *format, ...)\r
+{\r
+ int size;\r
+ char *buf;\r
+ va_list args;\r
+ \r
+ if(!fp || !format) return -1;\r
+ \r
+ // Get Size\r
+ va_start(args, format);\r
+ size = ssprintfv((char*)format, args);\r
+ va_end(args);\r
+ \r
+ // Allocate buffer\r
+ buf = (char*)malloc(size+1);\r
+ buf[size] = '\0';\r
+ \r
+ // Print\r
+ va_start(args, format);\r
+ sprintfv(buf, (char*)format, args);\r
+ va_end(args);\r
+ \r
+ // Write to stream\r
+ write(fp->FD, size+1, buf);\r
+ \r
+ // Free buffer\r
+ free(buf);\r
+ \r
+ // Return written byte count\r
+ return size;\r
+}\r
+\r
+// --- INTERNAL ---\r
+/**\r
+ * \fn FILE *get_file_struct()\r
+ * \brief Returns a file descriptor structure\r
+ */\r
+FILE *get_file_struct()\r
+{\r
+ int i;\r
+ for(i=0;i<STDIO_MAX_STREAMS;i++)\r
+ {\r
+ if(_iob[i].Flags == 0) return &_iob[i];\r
+ }\r
+ return NULL;\r
+}\r
--- /dev/null
+/*\r
+AcessOS Basic LibC\r
+heap.c - Heap Manager\r
+*/\r
+#include <acess/sys.h>\r
+#include <stdlib.h>\r
+#include "lib.h"\r
+\r
+// === Constants ===\r
+#define MAGIC 0xACE55051 //AcessOS1\r
+#define MAGIC_FREE (~MAGIC)\r
+#define BLOCK_SIZE 16 //Minimum\r
+#define HEAP_INIT_SIZE 0x10000\r
+\r
+typedef unsigned int Uint;\r
+\r
+//Typedefs\r
+typedef struct {\r
+ Uint magic;\r
+ Uint size;\r
+} heap_head;\r
+typedef struct {\r
+ heap_head *header;\r
+ Uint magic;\r
+} heap_foot;\r
+\r
+//Globals\r
+void *_heap_start = NULL;\r
+void *_heap_end = NULL;\r
+\r
+//Prototypes\r
+EXPORT void *malloc(Uint bytes);\r
+EXPORT void free(void *mem);\r
+EXPORT void *realloc(void *mem, Uint bytes);\r
+EXPORT void *sbrk(int increment);\r
+LOCAL void *extendHeap(int bytes);\r
+LOCAL uint brk(int delta);\r
+\r
+//Code\r
+\r
+/**\r
+ \fn EXPORT void *malloc(size_t bytes)\r
+ \brief Allocates memory from the heap space\r
+ \param bytes Integer - Size of buffer to return\r
+ \return Pointer to buffer\r
+*/\r
+EXPORT void *malloc(size_t bytes)\r
+{\r
+ Uint bestSize;\r
+ Uint closestMatch = 0;\r
+ Uint bestMatchAddr = 0;\r
+ heap_head *curBlock;\r
+ \r
+ // Initialise Heap\r
+ if(_heap_start == NULL)\r
+ {LOCAL void *sbrk(int delta);\r
+ _heap_start = sbrk(0);\r
+ _heap_end = _heap_start;\r
+ extendHeap(HEAP_INIT_SIZE);\r
+ }\r
+ \r
+ curBlock = _heap_start;\r
+ \r
+ bestSize = bytes + sizeof(heap_head) + sizeof(heap_foot) + BLOCK_SIZE - 1;\r
+ bestSize = (bestSize/BLOCK_SIZE)*BLOCK_SIZE; //Round up to block size\r
+ \r
+ while((Uint)curBlock < (Uint)_heap_end)\r
+ {\r
+ //SysDebug(" malloc: curBlock = 0x%x, curBlock->magic = 0x%x\n", curBlock, curBlock->magic);\r
+ if(curBlock->magic == MAGIC_FREE)\r
+ {\r
+ if(curBlock->size == bestSize)\r
+ break;\r
+ if(bestSize < curBlock->size && (curBlock->size < closestMatch || closestMatch == 0)) {\r
+ closestMatch = curBlock->size;\r
+ bestMatchAddr = (Uint)curBlock;\r
+ }\r
+ }\r
+ else if(curBlock->magic != MAGIC)\r
+ {\r
+ //Corrupt Heap\r
+ //SysDebug("malloc: Corrupt Heap\n");\r
+ return NULL;\r
+ }\r
+ curBlock = (heap_head*)((Uint)curBlock + curBlock->size);\r
+ }\r
+ \r
+ if((Uint)curBlock < (Uint)_heap_start) {\r
+ //SysDebug("malloc: Heap underrun for some reason\n");\r
+ return NULL;\r
+ }\r
+ \r
+ //Found a perfect match\r
+ if((Uint)curBlock < (Uint)_heap_end) {\r
+ curBlock->magic = MAGIC;\r
+ return (void*)((Uint)curBlock + sizeof(heap_head));\r
+ }\r
+ \r
+ //Out of Heap Space\r
+ if(!closestMatch) {\r
+ curBlock = extendHeap(bestSize); //Allocate more\r
+ if(curBlock == NULL) {\r
+ //SysDebug("malloc: Out of Heap Space\n");\r
+ return NULL;\r
+ }\r
+ curBlock->magic = MAGIC;\r
+ return (void*)((Uint)curBlock + sizeof(heap_head));\r
+ }\r
+ \r
+ //Split Block?\r
+ if(closestMatch - bestSize > BLOCK_SIZE) {\r
+ heap_foot *foot;\r
+ curBlock = (heap_head*)bestMatchAddr;\r
+ curBlock->magic = MAGIC;\r
+ curBlock->size = bestSize;\r
+ foot = (heap_foot*)(bestMatchAddr + bestSize - sizeof(heap_foot));\r
+ foot->header = curBlock;\r
+ foot->magic = MAGIC;\r
+\r
+ curBlock = (heap_head*)(bestMatchAddr + bestSize);\r
+ curBlock->magic = MAGIC_FREE;\r
+ curBlock->size = closestMatch - bestSize;\r
+ \r
+ foot = (heap_foot*)(bestMatchAddr + closestMatch - sizeof(heap_foot));\r
+ foot->header = curBlock;\r
+ \r
+ ((heap_head*)bestMatchAddr)->magic = MAGIC; //mark as used\r
+ return (void*)(bestMatchAddr + sizeof(heap_head));\r
+ }\r
+ \r
+ //Don't Split the block\r
+ ((heap_head*)bestMatchAddr)->magic = MAGIC;\r
+ return (void*)(bestMatchAddr+sizeof(heap_head));\r
+}\r
+\r
+/**\r
+ \fn EXPORT void free(void *mem)\r
+ \brief Free previously allocated memory\r
+ \param mem Pointer - Memory to free\r
+*/\r
+EXPORT void free(void *mem)\r
+{\r
+ heap_head *head = mem;\r
+ \r
+ if(head->magic != MAGIC) //Valid Heap Address\r
+ return;\r
+ \r
+ head->magic = MAGIC_FREE;\r
+ \r
+ //Unify Right\r
+ if((Uint)head + head->size < (Uint)_heap_end)\r
+ {\r
+ heap_head *nextHead = (heap_head*)((Uint)head + head->size);\r
+ if(nextHead->magic == MAGIC_FREE) { //Is the next block free\r
+ head->size += nextHead->size; //Amalgamate\r
+ nextHead->magic = 0; //For Security\r
+ }\r
+ }\r
+ //Unify Left\r
+ if((Uint)head - sizeof(heap_foot) > (Uint)_heap_start)\r
+ {\r
+ heap_head *prevHead;\r
+ heap_foot *prevFoot = (heap_foot *)((Uint)head - sizeof(heap_foot));\r
+ if(prevFoot->magic == MAGIC) {\r
+ prevHead = prevFoot->header;\r
+ if(prevHead->magic == MAGIC_FREE) {\r
+ prevHead->size += head->size; //Amalgamate\r
+ head->magic = 0; //For Security\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+/**\r
+ \fn EXPORT void *realloc(void *oldPos, size_t bytes)\r
+ \brief Reallocate a block of memory\r
+ \param bytes Integer - Size of new buffer\r
+ \param oldPos Pointer - Old Buffer\r
+ \return Pointer to new buffer\r
+*/\r
+EXPORT void *realloc(void *oldPos, size_t bytes)\r
+{\r
+ void *ret;\r
+ heap_head *head;\r
+ \r
+ if(oldPos == NULL) {\r
+ return malloc(bytes);\r
+ }\r
+ \r
+ //Check for free space after block\r
+ head = (heap_head*)((Uint)oldPos-sizeof(heap_head));\r
+ \r
+ //Hack to used free's amagamating algorithym and malloc's splitting\r
+ free(oldPos);\r
+ \r
+ //Allocate new memory\r
+ ret = malloc(bytes);\r
+ if(ret == NULL)\r
+ return NULL;\r
+ \r
+ //Copy Old Data\r
+ if((Uint)ret != (Uint)oldPos) {\r
+ memcpy(ret, oldPos, head->size-sizeof(heap_head)-sizeof(heap_foot));\r
+ }\r
+ \r
+ //Return\r
+ return ret;\r
+}\r
+\r
+/**\r
+ \fn LOCAL void *extendHeap(int bytes)\r
+ \brief Create a new block at the end of the heap area\r
+ \param bytes Integer - Size reqired\r
+ \return Pointer to last free block\r
+ */\r
+\r
+LOCAL void *extendHeap(int bytes)\r
+{\r
+ heap_head *head = _heap_end;\r
+ heap_foot *foot;\r
+ \r
+ //Expand Memory Space (Use foot as a temp pointer)\r
+ foot = sbrk(bytes);\r
+ if(foot == (void*)-1)\r
+ return NULL;\r
+ \r
+ \r
+ //Create New Block\r
+ // Header\r
+ head->magic = MAGIC_FREE; //Unallocated\r
+ head->size = bytes;\r
+ // Footer\r
+ foot = _heap_end + bytes - sizeof(heap_foot);\r
+ foot->header = head;\r
+ foot->magic = MAGIC;\r
+ \r
+ //Combine with previous block if nessasary\r
+ if(_heap_end != _heap_start && ((heap_foot*)((Uint)_heap_end-sizeof(heap_foot)))->magic == MAGIC) {\r
+ heap_head *tmpHead = ((heap_foot*)((Uint)_heap_end-sizeof(heap_foot)))->header;\r
+ if(tmpHead->magic == MAGIC_FREE) {\r
+ tmpHead->size += bytes;\r
+ foot->header = tmpHead;\r
+ head = tmpHead;\r
+ }\r
+ }\r
+ \r
+ _heap_end = (void*) ((Uint)foot+sizeof(heap_foot));\r
+ return head;\r
+}\r
+\r
+/**\r
+ \fn EXPORT void *sbrk(int increment)\r
+ \brief Increases the program's memory space\r
+ \param count Integer - Size of heap increase\r
+ \return Pointer to start of new region\r
+*/\r
+EXPORT void *sbrk(int increment)\r
+{\r
+ size_t newEnd;\r
+ static size_t oldEnd = 0;\r
+ static size_t curEnd = 0;\r
+\r
+ //SysDebug("sbrk: (increment=%i)\n", increment);\r
+\r
+ if (oldEnd == 0) curEnd = oldEnd = brk(0);\r
+\r
+ //SysDebug(" sbrk: oldEnd = 0x%x\n", oldEnd);\r
+ if (increment == 0) return (void *) curEnd;\r
+\r
+ newEnd = curEnd + increment;\r
+\r
+ if (brk(newEnd) == curEnd) return (void *) -1;\r
+ oldEnd = curEnd;\r
+ curEnd = newEnd;\r
+ //SysDebug(" sbrk: newEnd = 0x%x\n", newEnd);\r
+\r
+ return (void *) oldEnd;\r
+}\r
+\r
+/**\r
+ * \fn EXPORT int IsHeap(void *ptr)\r
+ */\r
+EXPORT int IsHeap(void *ptr)\r
+{\r
+ #if 0\r
+ heap_head *head;\r
+ heap_foot *foot;\r
+ #endif\r
+ if( (Uint)ptr < (Uint)_heap_start ) return 0;\r
+ if( (Uint)ptr > (Uint)_heap_end ) return 0;\r
+ \r
+ #if 0\r
+ head = (void*)((Uint)ptr - 4);\r
+ if( head->magic != MAGIC ) return 0;\r
+ foot = (void*)( (Uint)ptr + head->size - sizeof(heap_foot) );\r
+ if( foot->magic != MAGIC ) return 0;\r
+ #endif\r
+ return 1;\r
+}\r
+\r
+// === STATIC FUNCTIONS ===\r
+/**\r
+ * Does the job of brk(0)\r
+ */\r
+static void *FindHeapBase()\r
+{\r
+ #define MAX 0xC0000000 // Address\r
+ #define THRESHOLD 512 // Pages\r
+ uint addr;\r
+ uint stretch = 0;\r
+ \r
+ // Scan address space\r
+ for(addr = 0;\r
+ addr < MAX;\r
+ addr += 0x1000\r
+ )\r
+ {\r
+ if( _SysGetPhys(addr) == 0 ) {\r
+ stretch = 0;\r
+ } else {\r
+ stretch ++;\r
+ if(stretch > THRESHOLD)\r
+ {\r
+ return (void*)( addr + stretch*0x1000 );\r
+ }\r
+ }\r
+ }\r
+ return NULL;\r
+}\r
+\r
+LOCAL uint brk(int delta)\r
+{\r
+ static uint curpos;\r
+ uint pages;\r
+ uint ret = curpos;\r
+ \r
+ // Find initial position\r
+ if(curpos == 0) curpos = (uint)FindHeapBase();\r
+ \r
+ // Get Current Position\r
+ if(delta == 0)\r
+ {\r
+ return curpos;\r
+ }\r
+ \r
+ // Do we need to add pages\r
+ if(curpos & 0xFFF && (curpos & 0xFFF) + delta < 0x1000)\r
+ return curpos += delta;\r
+ \r
+ // Page align current position\r
+ if(curpos & 0xFFF) delta -= 0x1000 - (curpos & 0xFFF);\r
+ curpos = (curpos + 0xFFF) & ~0xFFF;\r
+ \r
+ // Allocate Pages\r
+ pages = (delta + 0xFFF) >> 12;\r
+ while(pages--)\r
+ {\r
+ _SysAllocate(curpos);\r
+ curpos += 0x1000;\r
+ delta -= 0x1000;\r
+ }\r
+ \r
+ // Bring the current position to exactly what we want\r
+ curpos -= ((delta + 0xFFF) & ~0xFFF) - delta;\r
+ \r
+ return ret; // Return old curpos\r
+}\r
--- /dev/null
+/*
+ * AcessOS Basic C Library
+ * signals.c
+*/
+#include <syscalls.h>
+#include <stdlib.h>
+#include <signal.h>
+#include "lib.h"
+
+// === CONSTANTS ===
+#define NUM_SIGNALS 32
+
+// === GLOBALS ===
+sighandler_t sighandlers[NUM_SIGNALS];
+
+// === CODE ===
+sighandler_t signal(int num, sighandler_t handler)
+{
+ sighandler_t prev;
+ if(num < 0 || num >= NUM_SIGNALS) return NULL;
+ prev = sighandlers[num];
+ sighandlers[num] = handler;
+ return prev;
+}
--- /dev/null
+/*\r
+AcessOS Basic C Library\r
+\r
+stdlib.c\r
+*/\r
+#include <acess/sys.h>\r
+#include <stdlib.h>\r
+#include "lib.h"\r
+\r
+int _stdout = 1;\r
+int _stdin = 2;\r
+\r
+EXPORT int puts(const char *str);\r
+EXPORT void itoa(char *buf, unsigned long num, int base, int minLength, char pad);\r
+EXPORT int atoi(const char *str);\r
+EXPORT int puts(const char *str);\r
+EXPORT int ssprintfv(char *format, va_list args);\r
+EXPORT void sprintfv(char *buf, char *format, va_list args);\r
+EXPORT int printf(const char *format, ...);\r
+EXPORT int strlen(const char *str);\r
+EXPORT int strcmp(char *str1, char *str2);\r
+EXPORT int strncmp(char *str1, char *str2, size_t len);\r
+EXPORT char *strcpy(char *dst, const char *src);\r
+\r
+// === CODE ===\r
+EXPORT int putchar(int ch)\r
+{\r
+ return write(_stdout, 1, (char*)&ch);\r
+}\r
+\r
+EXPORT int puts(const char *str)\r
+{\r
+ int len;\r
+ \r
+ if(!str) return 0;\r
+ len = strlen(str);\r
+ \r
+ len = write(_stdout, len, (char*)str);\r
+ write(_stdout, 1, "\n");\r
+ return len;\r
+}\r
+\r
+//sprintfv\r
+/**\r
+ \fn EXPORT void sprintfv(char *buf, char *format, va_list args)\r
+ \brief Prints a formatted string to a buffer\r
+ \param buf Pointer - Destination Buffer\r
+ \param format String - Format String\r
+ \param args VarArgs List - Arguments\r
+*/\r
+EXPORT void sprintfv(char *buf, char *format, va_list args)\r
+{\r
+ char tmp[33];\r
+ int c, arg, minSize;\r
+ int pos = 0;\r
+ char *p;\r
+ char pad;\r
+\r
+ tmp[32] = '\0';\r
+ \r
+ while((c = *format++) != 0)\r
+ {\r
+ //SysDebug("c = '%c'\n", c);\r
+ if (c != '%') {\r
+ buf[pos++] = c;\r
+ continue;\r
+ }\r
+ \r
+ c = *format++;\r
+ if(c == '%') {\r
+ buf[pos++] = '%';\r
+ continue;\r
+ }\r
+ \r
+ // Padding\r
+ if(c == '0') {\r
+ pad = '0';\r
+ c = *format++;\r
+ } else\r
+ pad = ' ';\r
+ minSize = 0;\r
+ if('1' <= c && c <= '9')\r
+ {\r
+ while('0' <= c && c <= '9')\r
+ {\r
+ minSize *= 10;\r
+ minSize += c - '0';\r
+ c = *format++;\r
+ }\r
+ }\r
+ \r
+ p = tmp;\r
+ \r
+ // Get Argument\r
+ arg = va_arg(args, int);\r
+ // Get Type\r
+ switch (c) {\r
+ case 'd':\r
+ case 'i':\r
+ if(arg < 0) {\r
+ buf[pos++] = '-';\r
+ arg = -arg;\r
+ }\r
+ itoa(tmp, arg, 10, minSize, pad);\r
+ goto sprintf_puts;\r
+ // break;\r
+ case 'u':\r
+ itoa(tmp, arg, 10, minSize, pad);\r
+ goto sprintf_puts;\r
+ // break;\r
+ case 'x':\r
+ itoa(tmp, arg, 16, minSize, pad);\r
+ goto sprintf_puts;\r
+ // break;\r
+ case 'o':\r
+ itoa(tmp, arg, 8, minSize, pad);\r
+ goto sprintf_puts;\r
+ // break;\r
+ case 'b':\r
+ itoa(tmp, arg, 2, minSize, pad);\r
+ goto sprintf_puts;\r
+ // break;\r
+\r
+ case 's':\r
+ p = (void*)arg;\r
+ sprintf_puts:\r
+ if(!p) p = "(null)";\r
+ while(*p) buf[pos++] = *p++;\r
+ break;\r
+\r
+ default:\r
+ buf[pos++] = arg;\r
+ break;\r
+ }\r
+ }\r
+ buf[pos++] = '\0';\r
+}\r
+/*\r
+ssprintfv\r
+- Size, Stream, Print Formated, Variable Argument List\r
+*/\r
+/**\r
+ \fn EXPORT int ssprintfv(char *format, va_list args)\r
+ \brief Gets the total character count from a formatted string\r
+ \param format String - Format String\r
+ \param args VarArgs - Argument List\r
+*/\r
+EXPORT int ssprintfv(char *format, va_list args)\r
+{\r
+ char tmp[33];\r
+ int c, arg, minSize;\r
+ int len = 0;\r
+ char *p;\r
+ char pad;\r
+\r
+ tmp[32] = '\0';\r
+ \r
+ while((c = *format++) != 0)\r
+ {\r
+ if (c != '%') {\r
+ len++;\r
+ continue;\r
+ }\r
+ \r
+ c = *format++;\r
+ \r
+ // Literal '%'\r
+ if(c == '%') {\r
+ len++;\r
+ continue;\r
+ }\r
+ \r
+ // Padding\r
+ if(c == '0') {\r
+ pad = '0';\r
+ c = *format++;\r
+ } else\r
+ pad = ' ';\r
+ minSize = 0;\r
+ if('1' <= c && c <= '9')\r
+ {\r
+ while('0' <= c && c <= '9')\r
+ {\r
+ minSize *= 10;\r
+ minSize += c - '0';\r
+ c = *format++;\r
+ }\r
+ }\r
+ \r
+ p = tmp;\r
+ arg = va_arg(args, int);\r
+ switch (c) { \r
+ case 'd':\r
+ case 'i':\r
+ if(arg < 0) {\r
+ len ++;\r
+ arg = -arg;\r
+ }\r
+ itoa(tmp, arg, 10, minSize, pad);\r
+ goto sprintf_puts;\r
+ case 'u':\r
+ itoa(tmp, arg, 10, minSize, pad);\r
+ goto sprintf_puts;\r
+ case 'x':\r
+ itoa(tmp, arg, 16, minSize, pad);\r
+ goto sprintf_puts;\r
+ case 'o':\r
+ itoa(tmp, arg, 8, minSize, pad);\r
+ p = tmp;\r
+ goto sprintf_puts;\r
+ case 'b':\r
+ itoa(tmp, arg, 2, minSize, pad);\r
+ goto sprintf_puts;\r
+\r
+ case 's':\r
+ p = (char*)arg;\r
+ sprintf_puts:\r
+ if(!p) p = "(null)";\r
+ while(*p) len++, p++;\r
+ break;\r
+\r
+ default:\r
+ len ++;\r
+ break;\r
+ }\r
+ }\r
+ return len;\r
+}\r
+\r
+const char cUCDIGITS[] = "0123456789ABCDEF";\r
+/**\r
+ * \fn static void itoa(char *buf, unsigned long num, int base, int minLength, char pad)\r
+ * \brief Convert an integer into a character string\r
+ */\r
+EXPORT void itoa(char *buf, unsigned long num, int base, int minLength, char pad)\r
+{\r
+ char tmpBuf[32];\r
+ int pos=0, i;\r
+\r
+ if(!buf) return;\r
+ if(base > 16) {\r
+ buf[0] = 0;\r
+ return;\r
+ }\r
+ \r
+ while(num > base-1) {\r
+ tmpBuf[pos] = cUCDIGITS[ num % base ];\r
+ num = (long) num / base; //Shift {number} right 1 digit\r
+ pos++;\r
+ }\r
+\r
+ tmpBuf[pos++] = cUCDIGITS[ num % base ]; //Last digit of {number}\r
+ i = 0;\r
+ minLength -= pos;\r
+ while(minLength-- > 0) buf[i++] = pad;\r
+ while(pos-- > 0) buf[i++] = tmpBuf[pos]; //Reverse the order of characters\r
+ buf[i] = 0;\r
+}\r
+\r
+/**\r
+ */\r
+EXPORT int atoi(const char *str)\r
+{\r
+ int neg = 0;\r
+ int ret = 0;\r
+ \r
+ // NULL Check\r
+ if(!str) return 0;\r
+ \r
+ while(*str == ' ' || *str == '\t') str++;\r
+ \r
+ // Check for negative\r
+ if(*str == '-') {\r
+ neg = 1;\r
+ str++;\r
+ }\r
+ \r
+ if(*str == '0') {\r
+ str ++;\r
+ if(*str == 'x') {\r
+ str++;\r
+ // Hex\r
+ while( ('0' <= *str && *str <= '9')\r
+ || ('A' <= *str && *str <= 'F' )\r
+ || ('a' <= *str && *str <= 'f' )\r
+ )\r
+ {\r
+ ret *= 16;\r
+ if(*str <= '9') {\r
+ ret += *str - '0';\r
+ } else if (*str <= 'F') {\r
+ ret += *str - 'A' + 10;\r
+ } else {\r
+ ret += *str - 'a' + 10;\r
+ }\r
+ str++;\r
+ }\r
+ } else {\r
+ // Octal\r
+ while( '0' <= *str && *str <= '7' )\r
+ {\r
+ ret *= 8;\r
+ ret += *str - '0';\r
+ str++;\r
+ }\r
+ }\r
+ } else {\r
+ // Decimal\r
+ while( '0' <= *str && *str <= '9' )\r
+ {\r
+ ret *= 10;\r
+ ret += *str - '0';\r
+ str++;\r
+ }\r
+ }\r
+ \r
+ // Negate if needed\r
+ if(neg) ret = -ret;\r
+ return ret;\r
+}\r
+\r
+//printf\r
+EXPORT int printf(const char *format, ...)\r
+{\r
+ int size;\r
+ char *buf;\r
+ va_list args;\r
+ \r
+ va_start(args, format);\r
+ size = ssprintfv((char*)format, args);\r
+ va_end(args);\r
+ \r
+ buf = (char*)malloc(size+1);\r
+ buf[size] = '\0';\r
+ \r
+ va_start(args, format);\r
+ sprintfv(buf, (char*)format, args);\r
+ va_end(args);\r
+ \r
+ \r
+ write(_stdout, size+1, buf);\r
+ \r
+ free(buf);\r
+ return size;\r
+}\r
+\r
+EXPORT int sprintf(const char *buf, char *format, ...)\r
+{\r
+ va_list args;\r
+ va_start(args, format);\r
+ sprintfv((char*)buf, (char*)format, args);\r
+ va_end(args);\r
+ return 1;\r
+}\r
+\r
+\r
+//MEMORY\r
+EXPORT int strcmp(char *s1, char *s2)\r
+{\r
+ while(*s1 == *s2 && *s1 != '\0' && *s2 != '\0') {\r
+ s1++; s2++;\r
+ }\r
+ return (int)*s1 - (int)*s2;\r
+}\r
+EXPORT char *strcpy(char *dst, const char *src)\r
+{\r
+ char *_dst = dst;\r
+ while(*src) {\r
+ *dst = *src;\r
+ src++; dst++;\r
+ }\r
+ *dst = '\0';\r
+ return _dst;\r
+}\r
+EXPORT int strlen(const char *str)\r
+{\r
+ int retval;\r
+ for(retval = 0; *str != '\0'; str++)\r
+ retval++;\r
+ return retval;\r
+}\r
+\r
+EXPORT int strncmp(char *s1, char *s2, size_t len)\r
+{\r
+ while(--len && *s1 == *s2 && *s1 != '\0' && *s2 != '\0') {\r
+ s1++; s2++;\r
+ }\r
+ return (int)*s1 - (int)*s2;\r
+}\r
+\r
+EXPORT void *memcpy(void *dest, void *src, unsigned int count)\r
+{\r
+ char *sp = (char *)src;\r
+ char *dp = (char *)dest;\r
+ for(;count--;) *dp++ = *sp++;\r
+ return dest;\r
+}\r
+\r
+EXPORT void *memmove(void *dest, void *src, unsigned int count)\r
+{\r
+ char *sp = (char *)src;\r
+ char *dp = (char *)dest;\r
+ // Check if corruption will happen\r
+ if( (unsigned int)dest > (unsigned int)src && (unsigned int)dest < (unsigned int)src+count )\r
+ for(;count--;) dp[count] = sp[count];\r
+ else\r
+ for(;count--;) *dp++ = *sp++;\r
+ return dest;\r
+}\r
--- /dev/null
+/*\r
+AcessOS Basic C Library\r
+*/\r
+\r
+extern char **_envp;\r
+\r
+/**\r
+ * \fn int SoMain()\r
+ * \brief Stub Entrypoint\r
+ * \param BaseAddress Unused - Load Address of libc\r
+ * \param argc Unused - Argument Count (0 for current version of ld-acess)\r
+ * \param argv Unused - Arguments (NULL for current version of ld-acess)\r
+ * \param envp Environment Pointer\r
+ */\r
+int SoMain(unsigned int BaseAddress, int argc, char **argv, char **envp)\r
+{\r
+ // Init for env.c\r
+ _envp = envp;\r
+ \r
+ return 1;\r
+}\r
--- /dev/null
+/*
+ * Acess2 System Interface Header
+ */
+#ifndef _SYS_SYS_H_
+#define _SYS_SYS_H_
+
+#include <stdint.h>
+
+// === CONSTANTS ===
+#define OPENFLAG_EXEC 0x01
+#define OPENFLAG_READ 0x02
+#define OPENFLAG_WRITE 0x04
+#define OPENFLAG_NOLINK 0x40
+#define SEEK_SET 1
+#define SEEK_CUR 0
+#define SEEK_END -1
+#define CLONE_VM 0x10
+#define FILEFLAG_DIRECTORY 0x10
+
+// === TYPES ===
+struct s_sysFInfo {
+ uint uid, gid;
+ uint flags;
+ int numacls;
+ uint64_t size;
+ uint64_t atime;
+ uint64_t mtime;
+ uint64_t ctime;
+};
+typedef struct s_sysFInfo t_sysFInfo;
+
+// === FUNCTIONS ===
+// --- Proc ---
+void sleep();
+ int clone(int flags, void *stack);
+ int execve(char *path, char **argv, char **envp);
+// --- VFS ---
+ int open(char *path, int flags);
+ int reopen(int fd, char *path, int flags);
+void close(int fd);
+uint64_t read(int fd, uint64_t length, void *buffer);
+uint64_t write(int fd, uint64_t length, void *buffer);
+ int seek(int fd, uint64_t offset, int whence);
+ int ioctl(int fd, int id, void *data);
+ int finfo(int fd, t_sysFInfo *info);
+
+// --- MEMORY ---
+uint64_t _SysGetPhys(uint vaddr);
+uint64_t _SysAllocate(uint vaddr);
+
+#endif
--- /dev/null
+/*
+ */
+#ifndef _STDTYPES_H_
+#define _STDTYPES_H_
+
+typedef unsigned int uint;
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned long uint32_t;
+typedef unsigned long long uint64_t;
+
+typedef signed char int8_t;
+typedef signed short int16_t;
+typedef signed long int32_t;
+typedef signed long long int64_t;
+
+#endif
--- /dev/null
+/*\r
+ * AcessOS LibC\r
+ * stdlib.h\r
+ */\r
+#ifndef __STDIO_H\r
+#define __STDIO_H
+
+typedef struct sFILE FILE;
+\r
+extern int printf(const char *format, ...);\r
+extern void sprintfv(char *buf, char *format, va_list args);\r
+extern int ssprintfv(char *format, va_list args);\r
+extern int sprintf(char *buf, char *format, ...);
+\r
+extern FILE *fopen(char *file, char *mode);\r
+extern FILE *freopen(FILE *fp, char *file, char *mode);
+extern void fclose(FILE *fp);\r
+extern void fflush(FILE *fp);\r
+\r
+extern int fprintf(FILE *fp, const char *format, ...);
+
+#endif\r
+
--- /dev/null
+/*\r
+AcessOS LibC\r
+\r
+stdlib.h\r
+*/\r
+#ifndef __STDLIB_H\r
+#define __STDLIB_H\r
+\r
+#include <stdarg.h>\r
+#include <sys/types.h>\r
+\r
+#ifndef NULL\r
+# define NULL ((void*)0)\r
+#endif\r
+\r
+typedef unsigned int size_t;\r
+\r
+// --- Spinlock Macros ---\r
+#define DEFLOCK(_name) static int _spinlock_##_name=0;\r
+//#define LOCK(_name) __asm__ __volatile__("jmp ._tst;\n\t._lp:call yield;\n\t._tst:lock btsl $1,(%0);\n\tjc ._lp"::"D"(&_spinlock_##_name))\r
+#define LOCK(_name) do{int v=1;while(v){__asm__ __volatile__("lock cmpxchgl %%eax, (%1)":"=a"(v):"D"((&_spinlock_##_name)),"a"(1));yield();}}while(0)\r
+#define UNLOCK(_name) __asm__ __volatile__("lock andl $0, (%0)"::"D"(&_spinlock_##_name))\r
+\r
+// --- StdLib ---\r
+extern int atoi(const char *ptr);\r
+\r
+extern void *memcpy(void *dest, void *src, size_t count);\r
+extern void *memmove(void *dest, void *src, size_t count);\r
+\r
+// --- Environment ---\r
+extern char *getenv(const char *name);\r
+\r
+// --- Heap ---\r
+extern void free(void *mem);\r
+extern void *malloc(unsigned int bytes);\r
+extern void *realloc(void *oldPos, unsigned int bytes);\r
+extern int IsHeap(void *ptr);\r
+\r
+// --- Strings ---\r
+extern int strlen(const char *string);\r
+extern int strcmp(char *str1, char *str2);\r
+extern int strncmp(char *str1, char *str2, size_t len);\r
+extern char *strcpy(char *dst, const char *src);\r
+\r
+#ifndef SEEK_CUR\r
+# define SEEK_CUR 0\r
+# define SEEK_SET 1\r
+# define SEEK_END (-1)\r
+#endif\r
+\r
+#endif\r
--- /dev/null
+/**
+ * \file basic_drivers.h
+ */
+#ifndef _SYS_BASIC_DRIVERS_H
+#define _SYS_BASIC_DRIVERS_H
+
+// === COMMON ===
+enum eDrv_Common {
+ DRV_IOCTL_NULL,
+ DRV_IOCTL_TYPE,
+ DRV_IOCTL_IDENT,
+ DRV_IOCTL_VER
+};
+
+enum eDrv_Types {
+ DRV_TYPE_NULL, //!< NULL Type - Custom Interface
+ DRV_TYPE_TERMINAL, //!< Terminal
+ DRV_TYPE_VIDEO, //!< Video - LFB
+ DRV_TYPE_SOUND, //!< Audio
+ DRV_TYPE_MOUSE, //!< Mouse
+ DRV_TYPE_JOYSTICK //!< Joystick / Gamepad
+};
+
+// === VIDEO ===
+enum eDrv_Video {
+ VID_IOCTL_SETMODE = 4,
+ VID_IOCTL_GETMODE,
+ VID_IOCTL_FINDMODE,
+ VID_IOCTL_MODEINFO,
+ VID_IOCTL_REQLFB // Request LFB
+};\r
+struct sVideo_IOCtl_Mode {\r
+ short id;\r
+ Uint16 width;\r
+ Uint16 height;\r
+ Uint16 bpp;\r
+};\r
+typedef struct sVideo_IOCtl_Mode tVideo_IOCtl_Mode; //!< Mode Type
+
+// === MOUSE ===
+enum eDrv_Mouse {\r
+ MSE_IOCTL_SENS = 4,\r
+ MSE_IOCTL_MAX_X,\r
+ MSE_IOCTL_MAX_Y\r
+};
+
+#endif
--- /dev/null
+/*\r
+ Syscall Definitions\r
+*/\r
+\r
+#include <sys/types.h>\r
+\r
+#define OPEN_FLAG_READ 1\r
+#define OPEN_FLAG_WRITE 2\r
+#define OPEN_FLAG_EXEC 4\r
+\r
+enum {\r
+ K_WAITPID_DIE = 0\r
+};\r
+\r
+// === System Calls ===\r
+extern void _exit(int ret);\r
+extern int brk(int bssend);\r
+extern int execve(char *file, char *args[], char *envp[]);\r
+extern int fork();\r
+extern int yield();\r
+extern int sleep();\r
+\r
+extern int open(char *file, int flags);\r
+extern int close(int fp);\r
+extern int read(int fp, int len, void *buf);\r
+extern int write(int fp, int len, void *buf);\r
+extern int tell(int fp);\r
+extern void seek(int fp, int dist, int flag);\r
+extern int fstat(int fp, t_fstat *st);\r
+extern int ioctl(int fp, int call, void *arg);\r
+extern int readdir(int fp, char *file);\r
+extern int kdebug(char *fmt, ...);\r
+extern int waitpid(int pid, int action);\r
+extern int gettid(); // Get Thread ID\r
+extern int getpid(); // Get Process ID\r
+extern int sendmsg(int dest, unsigned int *Data);\r
+extern int pollmsg(int *src, unsigned int *Data);\r
+extern int getmsg(int *src, unsigned int *Data);\r
--- /dev/null
+
+#ifndef _SYS_TYPES_H
+#define _SYS_TYPES_H
+
+typedef struct {
+ int st_dev; //dev_t
+ int st_ino; //ino_t
+ int st_mode; //mode_t
+ unsigned int st_nlink;
+ unsigned int st_uid;
+ unsigned int st_gid;
+ int st_rdev; //dev_t
+ unsigned int st_size;
+ long st_atime; //time_t
+ long st_mtime;
+ long st_ctime;
+} t_fstat;
+
+#define S_IFMT 0170000 /* type of file */
+#define S_IFDIR 0040000 /* directory */
+#define S_IFCHR 0020000 /* character special */
+#define S_IFBLK 0060000 /* block special */
+#define S_IFREG 0100000 /* regular */
+#define S_IFLNK 0120000 /* symbolic link */
+#define S_IFSOCK 0140000 /* socket */
+#define S_IFIFO 0010000 /* fifo */
+
+#endif