From: John Hodge Date: Mon, 21 Sep 2009 10:02:09 +0000 (+0800) Subject: Adding usermode tree X-Git-Tag: rel0.06~557 X-Git-Url: https://git.ucc.asn.au/?a=commitdiff_plain;h=17e16b3110b4c5124b0707435e0427993d696545;p=tpg%2Facess2.git Adding usermode tree --- diff --git a/Usermode/Applications/CLIShell_src/Makefile b/Usermode/Applications/CLIShell_src/Makefile new file mode 100644 index 00000000..2d0d8f3a --- /dev/null +++ b/Usermode/Applications/CLIShell_src/Makefile @@ -0,0 +1,36 @@ +# Project: Acess Shell + +CC = gcc +AS = nasm +LD = ld +RM = @rm -f + +COBJ = main.o lib.o +BIN = ../CLIShell +ACESSDIR = /home/hodgeja/Projects/Acess2/Usermode + +INCS = -I$(ACESSDIR)/include -I./include +CFLAGS = -Wall -fno-builtin -fno-stack-protector $(INCS) +ASFLAGS = -felf +LDFLAGS = -T $(ACESSDIR)/Libraries/acess.ld -I /Acess/Libs/ld-acess.so -lc + +.PHONY : all clean + +all: $(BIN) + +$(BIN): $(AOBJ) $(COBJ) + @echo --- $(LD) -o $@ + @$(LD) $(LDFLAGS) -o $@ $(AOBJ) $(COBJ) -Map Map.txt + objdump -d $(BIN) > $(BIN).dsm + cp $(BIN) /mnt/AcessHDD/Acess2/ + +clean: + $(RM) $(AOBJ) $(COBJ) $(BIN) + +$(COBJ): %.o: %.c + @echo --- GCC -o $@ + @$(CC) $(CFLAGS) -c $? -o $@ + +$(AOBJ): %.ao: %.asm + @echo --- $(AS) -o $@ + @$(AS) $(ASFLAGS) -o $@ $< diff --git a/Usermode/Applications/CLIShell_src/header.h b/Usermode/Applications/CLIShell_src/header.h new file mode 100644 index 00000000..f90e6518 --- /dev/null +++ b/Usermode/Applications/CLIShell_src/header.h @@ -0,0 +1,18 @@ +/* + Acess Shell Version 2 +- Based on IOOS CLI Shell +*/ +#ifndef _HEADER_H +#define _HEADER_H + +#define NULL ((void*)0) + +#define Print(str) do{char*s=(str);write(_stdout,strlen(s)+1,s);}while(0) + +extern int _stdout; +extern int _stdin; + +extern int GeneratePath(char *file, char *base, char *tmpPath); + + +#endif diff --git a/Usermode/Applications/CLIShell_src/lib.c b/Usermode/Applications/CLIShell_src/lib.c new file mode 100644 index 00000000..b807dd6e --- /dev/null +++ b/Usermode/Applications/CLIShell_src/lib.c @@ -0,0 +1,102 @@ +/* + * AcessOS Shell Version 2 + * + * See file COPYING for + */ +#include "header.h" + +// === CODE === +/** + * \fn int GeneratePath(char *file, char *base, char *Dest) + * \brief Generates a path given a base and a filename + * \param + */ +int GeneratePath(char *file, char *base, char *Dest) +{ + char *pathComps[64]; + char *tmpStr; + int iPos = 0; + int iPos2 = 0; + + // Parse Base Path + if(file[0] != '/') + { + pathComps[iPos++] = tmpStr = base+1; + while(*tmpStr) + { + if(*tmpStr++ == '/') + { + pathComps[iPos] = tmpStr; + iPos ++; + } + } + } + + //Print(" GeneratePath: Base Done\n"); + + // Parse Argument Path + pathComps[iPos++] = tmpStr = file; + while(*tmpStr) + { + if(*tmpStr++ == '/') + { + pathComps[iPos] = tmpStr; + iPos ++; + } + } + pathComps[iPos] = NULL; + + //Print(" GeneratePath: Path Done\n"); + + // Cleanup + iPos2 = iPos = 0; + while(pathComps[iPos]) + { + tmpStr = pathComps[iPos]; + // Always Increment iPos + iPos++; + // .. + if(tmpStr[0] == '.' && tmpStr[1] == '.' && (tmpStr[2] == '/' || tmpStr[2] == '\0') ) + { + if(iPos2 != 0) + iPos2 --; + continue; + } + // . + if(tmpStr[0] == '.' && (tmpStr[1] == '/' || tmpStr[1] == '\0') ) + { + continue; + } + // Empty + if(tmpStr[0] == '/' || tmpStr[0] == '\0') + { + continue; + } + + // Set New Position + pathComps[iPos2] = tmpStr; + iPos2++; + } + pathComps[iPos2] = NULL; + + // Build New Path + iPos2 = 1; iPos = 0; + Dest[0] = '/'; + while(pathComps[iPos]) + { + tmpStr = pathComps[iPos]; + while(*tmpStr && *tmpStr != '/') + { + Dest[iPos2++] = *tmpStr; + tmpStr++; + } + Dest[iPos2++] = '/'; + iPos++; + } + if(iPos2 > 1) + Dest[iPos2-1] = 0; + else + Dest[iPos2] = 0; + + return iPos2; //Length +} diff --git a/Usermode/Applications/CLIShell_src/main.c b/Usermode/Applications/CLIShell_src/main.c new file mode 100644 index 00000000..28d476f3 --- /dev/null +++ b/Usermode/Applications/CLIShell_src/main.c @@ -0,0 +1,323 @@ +/* + AcessOS Shell Version 2 +- Based on IOOS CLI Shell +*/ +#include +#include +#include "header.h" + +#define _stdin 0 +#define _stdout 1 +#define _stderr 2 + +// ==== PROTOTYPES ==== +char *ReadCommandLine(int *Length); +void Parse_Args(char *str, char **dest); +void Command_Colour(int argc, char **argv); +void Command_Clear(int argc, char **argv); +//void Command_Ls(int argc, char **argv); +void Command_Cd(int argc, char **argv); +//void Command_Cat(int argc, char **argv); + +// ==== CONSTANT GLOBALS ==== +char *cCOLOUR_NAMES[8] = {"black", "red", "green", "yellow", "blue", "magenta", "cyan", "white"}; +struct { + char *name; + void (*fcn)(int argc, char **argv); +} cBUILTINS[] = { + {"colour", Command_Colour}, {"clear", Command_Clear}, {"cd", Command_Cd} +}; +#define BUILTIN_COUNT (sizeof(cBUILTINS)/sizeof(cBUILTINS[0])) + +// ==== LOCAL VARIABLES ==== +char gsCommandBuffer[1024]; +char *gsCurrentDirectory = "/"; +char gsTmpBuffer[1024]; +char **gasCommandHistory; + int giLastCommand = 0; + int giCommandSpace = 0; + +// ==== CODE ==== +int main(int argc, char *argv[], char *envp[]) +{ + char *sCommandStr; + char *saArgs[32]; + int length = 0; + int pid = -1; + int iArgCount = 0; + int bCached = 1; + t_sysFInfo info; + + //Command_Clear(0, NULL); + + write(_stdout, 36, "AcessOS/AcessBasic Shell Version 2\n"); + write(_stdout, 30, " Based on CLI Shell for IOOS\n"); + write(_stdout, 2, "\n"); + for(;;) + { + // Free last command & arguments + if(saArgs[0]) free(saArgs); + if(!bCached) free(sCommandStr); + bCached = 0; + write(_stdout, strlen(gsCurrentDirectory), gsCurrentDirectory); + write(_stdout, 3, "$ "); + + // Read Command line + sCommandStr = ReadCommandLine( &length ); + + // Check if the command should be cached + if(gasCommandHistory == NULL || strcmp(sCommandStr, gasCommandHistory[giLastCommand]) != 0) + { + if(giLastCommand >= giCommandSpace) { + giCommandSpace += 12; + gasCommandHistory = realloc(gasCommandHistory, giCommandSpace*sizeof(char*)); + } + giLastCommand ++; + gasCommandHistory[ giLastCommand ] = sCommandStr; + bCached = 1; + } + + // Parse Command Line into arguments + Parse_Args(sCommandStr, saArgs); + + // Count Arguments + iArgCount = 0; + while(saArgs[iArgCount]) iArgCount++; + + // Silently Ignore all empty commands + if(saArgs[1][0] == '\0') continue; + + // Check Built-In Commands + // [HACK] Mem Usage - Use Length in place of `i' + for(length=0;length space) { + space += 256; + ret = realloc(ret, space+1); + if(!ret) return NULL; + } + + write(_stdout, 1, &ch); + ret[pos++] = ch; + len ++; + } while(ch != '\n'); + + // Remove newline + pos --; + ret[pos] = '\0'; + + // Return length + if(Length) *Length = len; + + return ret; +} + +/** + * \fn void Parse_Args(char *str, char **dest) + * \brief Parse a string into an argument array + */ +void Parse_Args(char *str, char **dest) +{ + int i = 1; + char *buf = malloc( strlen(str) + 1 ); + + strcpy(buf, str); + dest[0] = buf; + + // Trim leading whitespace + while(*buf == ' ' && *buf) buf++; + + for(;;) + { + dest[i] = buf; // Save start of string + i++; + while(*buf && *buf != ' ') + { + if(*buf++ == '"') + { + while(*buf && !(*buf == '"' && buf[-1] != '\\')) + buf++; + } + } + if(*buf == '\0') break; + *buf = '\0'; + while(*++buf == ' ' && *buf); + if(*buf == '\0') break; + } + dest[i] = NULL; + if(i == 1) { + free(buf); + dest[0] = NULL; + } +} + +/** + * \fn void Command_Colour(int argc, char **argv) + * \brief + */ +void Command_Colour(int argc, char **argv) +{ + int fg, bg; + char clrStr[6] = "\x1B[37m"; + + // Verify Arg Count + if(argc < 2) + { + Print("Please specify a colour\n"); + goto usage; + } + + // Check Colour + for(fg=0;fg<8;fg++) + if(strcmp(cCOLOUR_NAMES[fg], argv[1]) == 0) + break; + + // Foreground a valid colour + if(fg == 8) { + Print("Unknown Colour '");Print(argv[1]);Print("'\n"); + goto usage; + } + // Set Foreground + clrStr[3] = '0' + fg; + write(_stdout, 6, clrStr); + + // Need to Set Background? + if(argc > 2) + { + for(bg=0;bg<8;bg++) + if(strcmp(cCOLOUR_NAMES[bg], argv[2]) == 0) + break; + + // Valid colour + if(bg == 8) + { + Print("Unknown Colour '");Print(argv[2]);Print("'\n"); + goto usage; + } + + clrStr[2] = '4'; + clrStr[3] = '0' + bg; + write(_stdout, 6, clrStr); + } + // Return + return; + + // Function Usage (Requested via a Goto (I know it's ugly)) +usage: + Print("Valid Colours are "); + for(fg=0;fg<8;fg++) + { + Print(cCOLOUR_NAMES[fg]); + write(_stdout, 3, ", "); + } + write(_stdout, 4, "\b\b\n"); + return; +} + +void Command_Clear(int argc, char **argv) +{ + write(_stdout, 4, "\x1B[2J"); //Clear Screen +} + +void Command_Cd(int argc, char **argv) +{ + char tmpPath[1024]; + int fp; + t_sysFInfo stats; + + if(argc < 2) + { + Print(gsCurrentDirectory);Print("\n"); + return; + } + + GeneratePath(argv[1], gsCurrentDirectory, tmpPath); + + fp = open(tmpPath, 0); + if(fp == -1) { + write(_stdout, 26, "Directory does not exist\n"); + return; + } + finfo(fp, &stats); + close(fp); + + if(!(stats.flags & FILEFLAG_DIRECTORY)) { + write(_stdout, 17, "Not a Directory\n"); + return; + } + + strcpy(gsCurrentDirectory, tmpPath); +} + diff --git a/Usermode/Applications/init_src/Makefile b/Usermode/Applications/init_src/Makefile new file mode 100644 index 00000000..a51f61ba --- /dev/null +++ b/Usermode/Applications/init_src/Makefile @@ -0,0 +1,27 @@ +# +# +# + +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 $@ diff --git a/Usermode/Applications/init_src/main.c b/Usermode/Applications/init_src/main.c new file mode 100644 index 00000000..e701b44e --- /dev/null +++ b/Usermode/Applications/init_src/main.c @@ -0,0 +1,31 @@ +/* + * Acess2 System Init Task + */ +#include + +// === 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; +} diff --git a/Usermode/Libraries/acess.ld b/Usermode/Libraries/acess.ld new file mode 100644 index 00000000..adf7b2a0 --- /dev/null +++ b/Usermode/Libraries/acess.ld @@ -0,0 +1,199 @@ +OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") +OUTPUT_ARCH(i386) +ENTRY(start) +SEARCH_DIR(/home/hodgeja/Projects/Acess2/Usermode/Libraries) +INPUT(-lacess crt0.o) +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + PROVIDE (__executable_start = 0x08048000); . = 0x08048000 + SIZEOF_HEADERS; + .interp : { *(.interp) } + .note.gnu.build-id : { *(.note.gnu.build-id) } + .hash : { *(.hash) } + .gnu.hash : { *(.gnu.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } + .rel.dyn : + { + *(.rel.init) + *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) + *(.rel.fini) + *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) + *(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*) + *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) + *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) + *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) + *(.rel.ctors) + *(.rel.dtors) + *(.rel.got) + *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) + } + .rela.dyn : + { + *(.rela.init) + *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) + *(.rela.fini) + *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) + *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) + *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) + *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) + *(.rela.ctors) + *(.rela.dtors) + *(.rela.got) + *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) + } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + .init : + { + KEEP (*(.init)) + } =0x90909090 + .plt : { *(.plt) } + .text : + { + *(.text .stub .text.* .gnu.linkonce.t.*) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + } =0x90909090 + .fini : + { + KEEP (*(.fini)) + } =0x90909090 + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } + .rodata1 : { *(.rodata1) } + .eh_frame_hdr : { *(.eh_frame_hdr) } + .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) } + .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) } + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. */ + . = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (CONSTANT (MAXPAGESIZE) - 1)); . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE)); + /* Exception handling */ + .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) } + .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } + /* Thread Local Storage sections */ + .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } + .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + } + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + PROVIDE_HIDDEN (__fini_array_end = .); + } + .ctors : + { + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + /* We don't want to include the .ctor section from + the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } + .jcr : { KEEP (*(.jcr)) } + .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) } + .dynamic : { *(.dynamic) } + .got : { *(.got) } + . = DATA_SEGMENT_RELRO_END (12, .); + .got.plt : { *(.got.plt) } + .data : + { + *(.data .data.* .gnu.linkonce.d.*) + SORT(CONSTRUCTORS) + } + .data1 : { *(.data1) } + _edata = .; PROVIDE (edata = .); + __bss_start = .; + .bss : + { + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + /* Align here to ensure that the .bss section occupies space up to + _end. Align after .bss to ensure correct alignment even if the + .bss section disappears because there are no input sections. + FIXME: Why do we need it? When there is no .bss section, we don't + pad the .data section. */ + . = ALIGN(. != 0 ? 32 / 8 : 1); + } + . = ALIGN(32 / 8); + . = ALIGN(32 / 8); + _end = .; PROVIDE (end = .); + . = DATA_SEGMENT_END (.); + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /* DWARF 3 */ + .debug_pubtypes 0 : { *(.debug_pubtypes) } + .debug_ranges 0 : { *(.debug_ranges) } + .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) } + /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) } +} diff --git a/Usermode/Libraries/crt0.o_src/Makefile b/Usermode/Libraries/crt0.o_src/Makefile new file mode 100644 index 00000000..c039e72b --- /dev/null +++ b/Usermode/Libraries/crt0.o_src/Makefile @@ -0,0 +1,15 @@ +# +# +# + +AS = nasm +RM = rm -f + +ASFLAGS = -felf + +.PHONY: all clean + +all: ../crt0.o + +../crt0.o: crt0.asm + $(AS) $(ASFLAGS) $< -o $@ diff --git a/Usermode/Libraries/crt0.o_src/crt0.asm b/Usermode/Libraries/crt0.o_src/crt0.asm new file mode 100644 index 00000000..07db9de2 --- /dev/null +++ b/Usermode/Libraries/crt0.o_src/crt0.asm @@ -0,0 +1,19 @@ +; +; 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 diff --git a/Usermode/Libraries/ld-acess.so_src/Makefile b/Usermode/Libraries/ld-acess.so_src/Makefile new file mode 100644 index 00000000..2d005160 --- /dev/null +++ b/Usermode/Libraries/ld-acess.so_src/Makefile @@ -0,0 +1,41 @@ +# Acess Dynamic Linker (ELF) Version 1 +# LD-ACESS.SO +# Makefile + +CC = gcc +AS = nasm +RM = @rm -f +LD = ld +OBJDUMP = objdump + +COBJ = main.o lib.o loadlib.o elf.o pe.o +AOBJ = helpers.ao +BIN = ../ld-acess.so + +CPPFLAGS = -I../../include +CFLAGS = -Wall -fno-builtin -fleading-underscore -fno-stack-protector +ASFLAGS = -felf +#LDFLAGS = --oformat elf32-i386 -Map map.txt -Bstatic -e _SoMain -shared +#LDFLAGS = --oformat elf32-i386 -Map map.txt -Bstatic -e _SoMain -Ttext 0xBFFFE000 +LDFLAGS = -T link.ld -Map map.txt -Bstatic + + +.PHONY: all clean + +all: $(BIN) + +clean: + $(RM) $(BIN) $(AOBJ) $(COBJ) + +$(BIN): $(AOBJ) $(COBJ) + $(LD) $(LDFLAGS) -o $(BIN) $(AOBJ) $(COBJ) > link.txt + $(OBJDUMP) -x $(BIN) > ld-acess.dmp + $(OBJDUMP) -d $(BIN) > ld-acess.dsm + cp $(BIN) /mnt/AcessHDD/Acess2/Libs + +$(COBJ): %.o: %.c + $(CC) $(CFLAGS) -o $@ -c $< + +$(AOBJ): %.ao: %.asm + $(AS) $(ASFLAGS) -o $@ $< + diff --git a/Usermode/Libraries/ld-acess.so_src/common.h b/Usermode/Libraries/ld-acess.so_src/common.h new file mode 100644 index 00000000..22066f91 --- /dev/null +++ b/Usermode/Libraries/ld-acess.so_src/common.h @@ -0,0 +1,50 @@ +/* + AcessOS v1 + By thePowersGang + ld-acess.so + COMMON.H +*/ +#ifndef _COMMON_H +#define _COMMON_H + +#define NULL ((void*)0) + +#include + +// === Types === +typedef unsigned int Uint; +typedef unsigned char Uint8; +typedef unsigned short Uint16; +typedef unsigned long Uint32; +typedef signed char Sint8; +typedef signed short Sint16; +typedef signed long Sint32; + +// === Main === +extern int DoRelocate( Uint base, char **envp, char *Filename ); + +// === Library/Symbol Manipulation == +extern Uint LoadLibrary(char *filename, char *SearchDir, char **envp); +extern void AddLoaded(char *File, Uint base); +extern Uint GetSymbol(char *name); +extern int GetSymbolFromBase(Uint base, char *name, Uint *ret); + +// === Library Functions === +extern void strcpy(char *dest, char *src); +extern int strcmp(char *s1, char *s2); +extern int strlen(char *str); + +// === System Calls === +extern void SysExit(); +extern void SysDebug(char *fmt, ...); //!< Now implemented in main.c +extern void SysDebugV(char *fmt, ...); +extern Uint SysLoadBin(char *path, Uint *entry); +extern Uint SysUnloadBin(Uint Base); + +// === ELF Loader === +extern int ElfGetSymbol(Uint Base, char *name, Uint *ret); + +// === PE Loader === +extern int PE_GetSymbol(Uint Base, char *Name, Uint *ret); + +#endif diff --git a/Usermode/Libraries/ld-acess.so_src/elf.c b/Usermode/Libraries/ld-acess.so_src/elf.c new file mode 100644 index 00000000..56f75e2b --- /dev/null +++ b/Usermode/Libraries/ld-acess.so_src/elf.c @@ -0,0 +1,379 @@ +/* + AcessOS 1 - Dynamic Loader + By thePowersGang +*/ +#include "common.h" +#include "elf32.h" + +#define DEBUG 0 + +#if DEBUG +# define DEBUGS(v...) SysDebug(v) +#else +# define DEBUGS(...) +#endif + +// === CONSTANTS === +#if DEBUG +//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"}; +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 + +// === PROTOTYPES === +void elf_doRelocate(Uint r_info, Uint32 *ptr, Uint32 addend, Elf32_Sym *symtab, Uint base); +Uint ElfHashString(char *name); + +// === CODE === +/** + \fn int ElfRelocate(void *Base, char **envp, char *Filename) + \brief Relocates a loaded ELF Executable +*/ +int ElfRelocate(void *Base, char **envp, char *Filename) +{ + Elf32_Ehdr *hdr = Base; + Elf32_Phdr *phtab; + int i, j; // Counters + char *libPath; + Uint iRealBase = -1; + Uint iBaseDiff; + int iSegmentCount; + int iSymCount; + Elf32_Rel *rel = NULL; + Elf32_Rela *rela = NULL; + Uint32 *pltgot = NULL; + void *plt = NULL; + int relSz=0, relEntSz=8; + int relaSz=0, relaEntSz=8; + int pltSz=0, pltType=0; + Elf32_Dyn *dynamicTab = NULL; // Dynamic Table Pointer + char *dynstrtab = NULL; // .dynamic String Table + Elf32_Sym *dynsymtab; + + DEBUGS("ElfRelocate: (Base=0x%x)\n", Base); + + // Parse Program Header to get Dynamic Table + phtab = Base + hdr->phoff; + iSegmentCount = hdr->phentcount; + for(i=0;i phtab[i].VAddr) + iRealBase = phtab[i].VAddr; + + // Find Dynamic Section + if(phtab[i].Type == PT_DYNAMIC) { + if(dynamicTab) { + DEBUGS(" WARNING - elf_relocate: Multiple PT_DYNAMIC segments\n"); + continue; + } + dynamicTab = (void *) phtab[i].VAddr; + j = i; // Save Dynamic Table ID + } + } + + // Page Align real base + iRealBase &= ~0xFFF; + DEBUGS(" elf_relocate: True Base = 0x%x, Compiled Base = 0x%x\n", Base, iRealBase); + + // Adjust "Real" Base + iBaseDiff = (Uint)Base - iRealBase; + + hdr->entrypoint += iBaseDiff; // Adjust Entrypoint + + // Check if a PT_DYNAMIC segement was found + if(!dynamicTab) { + SysDebug(" elf_relocate: No PT_DYNAMIC segment in image, returning\n"); + return hdr->entrypoint; + } + + // Adjust Dynamic Table + dynamicTab = (void *) ((Uint)dynamicTab + iBaseDiff); + + // === Get Symbol table and String Table === + for( j = 0; dynamicTab[j].d_tag != DT_NULL; j++) + { + switch(dynamicTab[j].d_tag) + { + // --- Symbol Table --- + case DT_SYMTAB: + DEBUGS(" elf_relocate: DYNAMIC Symbol Table 0x%x (0x%x)\n", + dynamicTab[j].d_val, dynamicTab[j].d_val + iBaseDiff); + dynamicTab[j].d_val += iBaseDiff; + dynsymtab = (void*)(dynamicTab[j].d_val); + hdr->misc.SymTable = dynamicTab[j].d_val; // Saved in unused bytes of ident + break; + // --- String Table --- + case DT_STRTAB: + DEBUGS(" elf_relocate: DYNAMIC String Table 0x%x (0x%x)\n", + dynamicTab[j].d_val, dynamicTab[j].d_val + iBaseDiff); + dynamicTab[j].d_val += iBaseDiff; + dynstrtab = (void*)(dynamicTab[j].d_val); + break; + // --- Hash Table -- + case DT_HASH: + dynamicTab[j].d_val += iBaseDiff; + iSymCount = ((Uint*)(dynamicTab[j].d_val))[1]; + hdr->misc.HashTable = dynamicTab[j].d_val; // Saved in unused bytes of ident + break; + } + } + + if(dynsymtab == NULL) { + SysDebug("WARNING: No Dynamic Symbol table, returning\n"); + return hdr->entrypoint; + } + + // Alter Symbols to true base + for(i=0;i DT_JMPREL) continue; + //DEBUGS(" elf_relocate: %i-%i = %s,0x%x\n", + // i,j, csaDT_NAMES[dynamicTab[j].d_tag],dynamicTab[j].d_val); + break; + } + } + + DEBUGS(" elf_relocate: Beginning Relocation\n"); + + // Parse Relocation Entries + if(rel && relSz) + { + Uint32 *ptr; + DEBUGS(" elf_relocate: rel=0x%x, relSz=0x%x, relEntSz=0x%x\n", rel, relSz, relEntSz); + j = relSz / relEntSz; + for( i = 0; i < j; i++ ) + { + //DEBUGS(" Rel %i: 0x%x+0x%x\n", i, iBaseDiff, rel[i].r_offset); + ptr = (void*)(iBaseDiff + rel[i].r_offset); + elf_doRelocate(rel[i].r_info, ptr, *ptr, dynsymtab, iBaseDiff); + } + } + // Parse Relocation Entries + if(rela && relaSz) + { + Uint32 *ptr; + DEBUGS(" elf_relocate: rela=0x%x, relaSz=0x%x, relaEntSz=0x%x\n", rela, relaSz, relaEntSz); + j = relaSz / relaEntSz; + for( i = 0; i < j; i++ ) + { + ptr = (void*)(iBaseDiff + rela[i].r_offset); + elf_doRelocate(rel[i].r_info, ptr, rela[i].r_addend, dynsymtab, iBaseDiff); + } + } + + // === Process PLT (Procedure Linkage Table) === + if(plt && pltSz) + { + Uint32 *ptr; + DEBUGS(" elf_relocate: Relocate PLT, plt=0x%x\n", plt); + if(pltType == DT_REL) + { + Elf32_Rel *pltRel = plt; + j = pltSz / sizeof(Elf32_Rel); + DEBUGS(" elf_relocate: PLT Reloc Type = Rel, %i entries\n", j); + for(i=0;ientrypoint); + return hdr->entrypoint; +} + +void elf_doRelocate(Uint r_info, Uint32 *ptr, Uint32 addend, Elf32_Sym *symtab, Uint base) +{ + int type = ELF32_R_TYPE(r_info); + int sym = ELF32_R_SYM(r_info); + Uint32 val; + switch( type ) + { + // Standard 32 Bit Relocation (S+A) + case R_386_32: + val = GetSymbol( symtab[sym].name ); + DEBUGS(" elf_doRelocate: R_386_32 *0x%x += 0x%x('%s')\n", + ptr, val, symtab[sym].name); + *ptr = val + addend; + break; + + // 32 Bit Relocation wrt. Offset (S+A-P) + case R_386_PC32: + DEBUGS(" elf_doRelocate: #%i: '%s'\n", sym, symtab[sym].name); + val = GetSymbol( symtab[sym].name ); + DEBUGS(" elf_doRelocate: R_386_PC32 *0x%x = 0x%x + 0x%x - 0x%x\n", + ptr, *ptr, val, (Uint)ptr ); + *ptr = val + addend - (Uint)ptr; + //*ptr = val + addend - ((Uint)ptr - base); + break; + + // Absolute Value of a symbol (S) + case R_386_GLOB_DAT: + case R_386_JMP_SLOT: + DEBUGS(" elf_doRelocate: #%i: '%s'\n", sym, symtab[sym].name); + val = GetSymbol( symtab[sym].name ); + DEBUGS(" elf_doRelocate: %s *0x%x = 0x%x\n", csaR_NAMES[type], ptr, val); + *ptr = val; + break; + + // Base Address (B+A) + case R_386_RELATIVE: + DEBUGS(" elf_doRelocate: R_386_RELATIVE *0x%x = 0x%x + 0x%x\n", ptr, base, addend); + *ptr = base + addend; + break; + + default: + DEBUGS(" elf_doRelocate: Rel 0x%x: 0x%x,%s\n", ptr, sym, csaR_NAMES[type]); + break; + } + +} + +/** + * \fn int ElfGetSymbol(Uint Base, char *name, Uint *ret) + */ +int ElfGetSymbol(Uint Base, char *Name, Uint *ret) +{ + Elf32_Ehdr *hdr = (void*)Base; + Elf32_Sym *symtab; + int nbuckets = 0; + int iSymCount = 0; + int i; + Uint *pBuckets; + Uint *pChains; + Uint iNameHash; + + //DEBUGS("ElfGetSymbol: (Base=0x%x, Name='%s')\n", Base, Name); + + pBuckets = (void *) hdr->misc.HashTable; + symtab = (void *) hdr->misc.SymTable; + + nbuckets = pBuckets[0]; + iSymCount = pBuckets[1]; + pBuckets = &pBuckets[2]; + pChains = &pBuckets[ nbuckets ]; + + // Get hash + iNameHash = ElfHashString(Name); + iNameHash %= nbuckets; + //DEBUGS(" ElfGetSymbol: iNameHash = 0x%x\n", iNameHash); + + // Walk Chain + i = pBuckets[ iNameHash ]; + //DEBUGS(" ElfGetSymbol: strcmp(Name, \"%s\")\n", symtab[i].name); + if(symtab[i].shndx != SHN_UNDEF && strcmp(symtab[i].name, Name) == 0) { + *ret = symtab[ i ].value; + return 1; + } + + //DEBUGS(" ElfGetSymbol: Hash of first = 0x%x\n", ElfHashString( symtab[i].name ) % nbuckets); + while(pChains[i] != STN_UNDEF) + { + //DEBUGS(" pChains[%i] = %i\n", i, pChains[i]); + i = pChains[i]; + //DEBUGS(" ElfGetSymbol: strcmp(Name, \"%s\")\n", symtab[ i ].name); + if(symtab[i].shndx != SHN_UNDEF && strcmp(symtab[ i ].name, Name) == 0) { + //DEBUGS("ElfGetSymbol: RETURN 1, '%s' = 0x%x\n", symtab[ i ].name, symtab[ i ].value); + *ret = symtab[ i ].value; + return 1; + } + } + + //DEBUGS("ElfGetSymbol: RETURN 0, Symbol '%s' not found\n", Name); + return 0; +} + +Uint ElfHashString(char *name) +{ + Uint h = 0, g; + while(*name) + { + h = (h << 4) + *name++; + if( (g = h & 0xf0000000) ) + h ^= g >> 24; + h &= ~g; + } + return h; +} + +#if 0 +unsigned long elf_hash(const unsigned char *name) +{ + unsigned long h = 0, g; + while (*name) + { + h = (h << 4) + *name++; + if (g = h & 0xf0000000) + h ^= g >> 24; + h &= ~g; + } + return h; +} +#endif diff --git a/Usermode/Libraries/ld-acess.so_src/elf32.h b/Usermode/Libraries/ld-acess.so_src/elf32.h new file mode 100644 index 00000000..eededf4e --- /dev/null +++ b/Usermode/Libraries/ld-acess.so_src/elf32.h @@ -0,0 +1,215 @@ +/** + Acess v1 + \file elf32.h + \brief ELF Exeutable Loader +*/ +#ifndef _ELF32_H +#define _ELF32_H + +/** + \struct elf_header_s + \brief ELF File Header +*/ +struct sElf32_Ehdr { + union { + char ident[16]; //!< Identifier Bytes + struct { + Uint Ident1; + Uint Ident2; + Uint HashTable; + Uint SymTable; + } misc; + }; + Uint16 filetype; //!< File Type + Uint16 machine; //!< Machine / Arch + Uint32 version; //!< Version (File?) + Uint32 entrypoint; //!< Entry Point + Uint32 phoff; //!< Program Header Offset + Uint32 shoff; //!< Section Header Offset + Uint32 flags; //!< Flags + Uint16 headersize; //!< Header Size + Uint16 phentsize; //!< Program Header Entry Size + Uint16 phentcount; //!< Program Header Entry Count + Uint16 shentsize; //!< Section Header Entry Size + Uint16 shentcount; //!< Section Header Entry Count + Uint16 shstrindex; //!< Section Header String Table Index +}; + +/** + \name Executable Types + \{ +*/ +#define ET_NONE 0 //!< NULL Type +#define ET_REL 1 //!< Relocatable (Object) +#define ET_EXEC 2 //!< Executable +#define ET_DYN 3 //!< Dynamic Library +#define ET_CORE 4 //!< Core? +#define ET_LOPROC 0xFF00 //!< Low Impl Defined +#define ET_HIPROC 0xFFFF //!< High Impl Defined +//! \} + +/** + \name Section IDs + \{ +*/ +#define SHN_UNDEF 0 //!< Undefined Section +#define SHN_LORESERVE 0xFF00 //!< Low Reserved +#define SHN_LOPROC 0xFF00 //!< Low Impl Defined +#define SHN_HIPROC 0xFF1F //!< High Impl Defined +#define SHN_ABS 0xFFF1 //!< Absolute Address (Base: 0, Size: -1) +#define SHN_COMMON 0xFFF2 //!< Common +#define SHN_HIRESERVE 0xFFFF //!< High Reserved +//! \} + +/** + \enum eElfSectionTypes + \brief ELF Section Types +*/ +enum eElfSectionTypes { + SHT_NULL, //0 + SHT_PROGBITS, //1 + SHT_SYMTAB, //2 + SHT_STRTAB, //3 + SHT_RELA, //4 + SHT_HASH, //5 + SHT_DYNAMIC, //6 + SHT_NOTE, //7 + SHT_NOBITS, //8 + SHT_REL, //9 + SHT_SHLIB, //A + SHT_DYNSYM, //B + SHT_LAST, //C + SHT_LOPROC = 0x70000000, + SHT_HIPROC = 0x7fffffff, + SHT_LOUSER = 0x80000000, + SHT_HIUSER = 0xffffffff +}; + +#define SHF_WRITE 0x1 +#define SHF_ALLOC 0x2 +#define SHF_EXECINSTR 0x4 +#define SHF_MASKPROC 0xf0000000 + +struct sElf32_Shent { + Uint32 name; + Uint32 type; + Uint32 flags; + Uint32 address; + Uint32 offset; + Uint32 size; + Uint32 link; + Uint32 info; + Uint32 addralign; + Uint32 entsize; +}; //sizeof = 40 + +struct elf_sym_s { + union { + Uint32 nameOfs; + char *name; + }; + Uint32 value; //Address + Uint32 size; + Uint8 info; + Uint8 other; + Uint16 shndx; +}; +#define STN_UNDEF 0 // Undefined Symbol + +enum { + PT_NULL, //0 + PT_LOAD, //1 + PT_DYNAMIC, //2 + PT_INTERP, //3 + PT_NOTE, //4 + PT_SHLIB, //5 + PT_PHDR, //6 + PT_LOPROC = 0x70000000, + PT_HIPROC = 0x7fffffff +}; + +struct sElf32_Phdr { + Uint32 Type; + Uint Offset; + Uint VAddr; + Uint PAddr; + Uint32 FileSize; + Uint32 MemSize; + Uint32 Flags; + Uint32 Align; +}; + +struct elf32_rel_s { + Uint32 r_offset; + Uint32 r_info; +}; + +struct elf32_rela_s { + Uint32 r_offset; + Uint32 r_info; + Sint32 r_addend; +}; + +enum { + R_386_NONE=0, // none + R_386_32, // S+A + R_386_PC32, // S+A-P + R_386_GOT32, // G+A-P + R_386_PLT32, // L+A-P + R_386_COPY, // none + R_386_GLOB_DAT, // S + R_386_JMP_SLOT, // S + R_386_RELATIVE, // B+A + R_386_GOTOFF, // S+A-GOT + R_386_GOTPC, // GOT+A-P + R_386_LAST // none +}; + +#define ELF32_R_SYM(i) ((i)>>8) // Takes an info value and returns a symbol index +#define ELF32_R_TYPE(i) ((i)&0xFF) // Takes an info value and returns a type +#define ELF32_R_INFO(s,t) (((s)<<8)+((t)&0xFF)) // Takes a type and symbol index and returns an info value + +struct elf32_dyn_s { + Uint16 d_tag; + Uint32 d_val; //Also d_ptr +}; + +enum { + DT_NULL, //!< Marks End of list + DT_NEEDED, //!< Offset in strtab to needed library + DT_PLTRELSZ, //!< Size in bytes of PLT + DT_PLTGOT, //!< Address of PLT/GOT + DT_HASH, //!< Address of symbol hash table + DT_STRTAB, //!< String Table address + DT_SYMTAB, //!< Symbol Table address + DT_RELA, //!< Relocation table address + DT_RELASZ, //!< Size of relocation table + DT_RELAENT, //!< Size of entry in relocation table + DT_STRSZ, //!< Size of string table + DT_SYMENT, //!< Size of symbol table entry + DT_INIT, //!< Address of initialisation function + DT_FINI, //!< Address of termination function + DT_SONAME, //!< String table offset of so name + DT_RPATH, //!< String table offset of library path + DT_SYMBOLIC,//!< Reverse order of symbol searching for library, search libs first then executable + DT_REL, //!< Relocation Entries (Elf32_Rel instead of Elf32_Rela) + DT_RELSZ, //!< Size of above table (bytes) + DT_RELENT, //!< Size of entry in above table + DT_PLTREL, //!< Relocation entry of PLT + DT_DEBUG, //!< Debugging Entry - Unknown contents + DT_TEXTREL, //!< Indicates that modifcations to a non-writeable segment may occur + DT_JMPREL, //!< Address of PLT only relocation entries + DT_LOPROC = 0x70000000, //!< Low Definable + DT_HIPROC = 0x7FFFFFFF //!< High Definable +}; + +typedef struct sElf32_Ehdr Elf32_Ehdr; +typedef struct sElf32_Phdr Elf32_Phdr; +typedef struct sElf32_Shent Elf32_Shent; +typedef struct elf_sym_s elf_symtab; +typedef struct elf_sym_s Elf32_Sym; +typedef struct elf32_rel_s Elf32_Rel; +typedef struct elf32_rela_s Elf32_Rela; +typedef struct elf32_dyn_s Elf32_Dyn; + +#endif // defined(_EXE_ELF_H) diff --git a/Usermode/Libraries/ld-acess.so_src/lib.c b/Usermode/Libraries/ld-acess.so_src/lib.c new file mode 100644 index 00000000..d327213f --- /dev/null +++ b/Usermode/Libraries/ld-acess.so_src/lib.c @@ -0,0 +1,30 @@ +/* + AcessOS 1 + Dynamic Loader + By thePowersGang +*/ +#include "common.h" + +// === CODE === +void strcpy(char *dest, char *src) +{ + while(*src) { + *dest = *src; + src ++; dest ++; + } + *dest = '\0'; +} + +int strcmp(char *s1, char *s2) +{ + while(*s1 == *s2 && *s1 != 0) s1++,s2++; + return *s1-*s2; +} + +int strlen(char *str) +{ + int len = 0; + while(*str) len++,str++; + return len; +} + diff --git a/Usermode/Libraries/ld-acess.so_src/loadlib.c b/Usermode/Libraries/ld-acess.so_src/loadlib.c new file mode 100644 index 00000000..267555d1 --- /dev/null +++ b/Usermode/Libraries/ld-acess.so_src/loadlib.c @@ -0,0 +1,192 @@ +/* + AcessOS 1 - Dynamic Loader + By thePowersGang +*/ +#include "common.h" + +#define DEBUG 0 + +#if DEBUG +# define DEBUGS(v...) SysDebug(v) +#else +# define DEBUGS(v...) +#endif + +// === PROTOTYPES === +Uint IsFileLoaded(char *file); + int GetSymbolFromBase(Uint base, char *name, Uint *ret); + +// === GLOABLS === +#define MAX_LOADED_LIBRARIES 64 +#define MAX_STRINGS_BYTES 4096 +struct { + Uint Base; + char *Name; +} gLoadedLibraries[MAX_LOADED_LIBRARIES]; +char gsLoadedStrings[MAX_STRINGS_BYTES]; +char *gsNextAvailString = gsLoadedStrings; +//tLoadLib *gpLoadedLibraries = NULL; + +// === CODE === +Uint LoadLibrary(char *filename, char *SearchDir, char **envp) +{ + char sTmpName[1024] = "/Acess/Libs/"; + Uint iArg; + void (*fEntry)(int, int, char *[], char**); + + DEBUGS("LoadLibrary: (filename='%s', envp=0x%x)\n", filename, envp); + + // Create Temp Name + strcpy(&sTmpName[12], filename); + DEBUGS(" LoadLibrary: sTmpName='%s'\n", sTmpName); + + if( (iArg = IsFileLoaded(sTmpName)) ) + return iArg; + + // Load Library + iArg = SysLoadBin(sTmpName, (Uint*)&fEntry); + if(iArg == 0) { + DEBUGS("LoadLibrary: RETURN 0\n"); + return 0; + } + + DEBUGS(" LoadLibrary: iArg=0x%x, iEntry=0x%x\n", iArg, fEntry); + + // Load Symbols + fEntry = (void*)DoRelocate( iArg, envp, sTmpName ); + + // Call Entrypoint + DEBUGS(" LoadLibrary: '%s' Entry 0x%x\n", filename, fEntry); + fEntry(iArg, 0, NULL, envp); + + DEBUGS("LoadLibrary: RETURN 1\n"); + return iArg; +} + +/** + * \fn Uint IsFileLoaded(char *file) + * \brief Determine if a file is already loaded + */ +Uint IsFileLoaded(char *file) +{ + int i; + DEBUGS("IsFileLoaded: (file='%s')\n", file); + for( i = 0; i < MAX_LOADED_LIBRARIES; i++ ) + { + if(gLoadedLibraries[i].Base == 0) break; // Last entry has Base set to NULL + if(strcmp(gLoadedLibraries[i].Name, file) == 0) { + DEBUGS("IsFileLoaded: Found %i (0x%x)\n", i, gLoadedLibraries[i].Base); + return gLoadedLibraries[i].Base; + } + } + DEBUGS("IsFileLoaded: Not Found\n"); + return 0; +} + +/** + * \fn void AddLoaded(char *File, Uint base) + * \brief Add a file to the loaded list + */ +void AddLoaded(char *File, Uint base) +{ + int i, length; + char *name = gsNextAvailString; + + DEBUGS("AddLoaded: (File='%s', base=0x%x)", File, base); + + // Find a free slot + for( i = 0; i < MAX_LOADED_LIBRARIES; i ++ ) + { + if(gLoadedLibraries[i].Base == 0) break; + } + if(i == MAX_LOADED_LIBRARIES) { + SysDebug("ERROR - ld-acess.so has run out of load slots!"); + return; + } + + // Check space in string buffer + length = strlen(File); + if(&name[length+1] >= &gsLoadedStrings[MAX_STRINGS_BYTES]) { + SysDebug("ERROR - ld-acess.so has run out of string buffer memory!"); + return; + } + + // Set information + gLoadedLibraries[i].Base = base; + strcpy(name, File); + gLoadedLibraries[i].Name = name; + gsNextAvailString = &name[length+1]; + DEBUGS("'%s' (0x%x) loaded as %i\n", name, base, i); + return; +} + +/** + * \fn void Unload(Uint Base) + */ +void Unload(Uint Base) +{ + int i, j; + int id; + char *str; + for( id = 0; id < MAX_LOADED_LIBRARIES; id++ ) + { + if(gLoadedLibraries[id].Base == Base) break; + } + if(id == MAX_LOADED_LIBRARIES) return; + + // Unload Binary + SysUnloadBin( Base ); + // Save String Pointer + str = gLoadedLibraries[id].Name; + + // Compact Loaded List + j = id; + for( i = j + 1; i < MAX_LOADED_LIBRARIES; i++, j++ ) + { + if(gLoadedLibraries[i].Base == 0) break; + // Compact String + strcpy(str, gLoadedLibraries[i].Name); + str += strlen(str)+1; + // Compact Entry + gLoadedLibraries[j].Base = gLoadedLibraries[i].Base; + gLoadedLibraries[j].Name = str; + } + + // NULL Last Entry + gLoadedLibraries[j].Base = 0; + gLoadedLibraries[j].Name = NULL; + // Save next string + gsNextAvailString = str; +} + +/** + \fn Uint GetSymbol(char *name) + \brief Gets a symbol value from a loaded library +*/ +Uint GetSymbol(char *name) +{ + int i; + Uint ret; + for(i=0;iPeHdrOffs; + + directory = peHeaders->OptHeader.Directory; + + // === Load Import Tables + impDir = Base + directory[PE_DIR_IMPORT].RVA; + for( i = 0; impDir[i].DLLName != NULL; i++ ) + { + impDir[i].DLLName += iBase; + impDir[i].ImportLookupTable += iBase/4; + impDir[i].ImportAddressTable += iBase/4; + DEBUGS(" PE_Relocate: DLL Required '%s'(0x%x)\n", impDir[i].DLLName, impDir[i].DLLName); + iLibBase = LoadLibrary(PE_int_GetTrueFile(impDir[i].DLLName), DLL_BASE_PATH, envp); + if(iLibBase == 0) { + SysDebug("Unable to load required library '%s'\n", impDir[i].DLLName); + return 0; + } + DEBUGS(" PE_Relocate: Loaded as 0x%x\n", iLibBase); + importTab = impDir[i].ImportLookupTable; + aIAT = impDir[i].ImportAddressTable; + for( j = 0; importTab[j] != 0; j++ ) + { + if( importTab[j] & 0x80000000 ) + DEBUGS(" PE_Relocate: Import Ordinal %i\n", importTab[j] & 0x7FFFFFFF); + else + { + name = (void*)( iBase + importTab[j] ); + DEBUGS(" PE_Relocate: Import Name '%s', Hint 0x%x\n", name->Name, name->Hint); + if( GetSymbolFromBase(iLibBase, name->Name, (Uint*)&aIAT[j]) == 0 ) { + SysDebug("Unable to find symbol '%s' in library '%s'\n", name->Name, impDir[i].DLLName); + return 0; + } + } + } + } + + #if DEBUG + for(i=0;iOptHeader.EntryPoint); + + return iBase + peHeaders->OptHeader.EntryPoint; +} + +/** + * \fn int PE_GetSymbol(Uint Base, char *Name, Uint *Ret) + */ +int PE_GetSymbol(Uint Base, char *Name, Uint *Ret) +{ + tPE_DOS_HEADER *dosHdr = (void*)Base; + tPE_IMAGE_HEADERS *peHeaders; + tPE_DATA_DIR *directory; + tPE_EXPORT_DIR *expDir; + Uint32 *nameTable, *addrTable; + Uint16 *ordTable; + int i; + int symbolCount; + char *name; + Uint retVal; + Uint expLen; + + peHeaders = (void*)( Base + dosHdr->PeHdrOffs ); + directory = peHeaders->OptHeader.Directory; + + expDir = (void*)( Base + directory[PE_DIR_EXPORT].RVA ); + expLen = directory[PE_DIR_EXPORT].Size; + symbolCount = expDir->NumNamePointers; + nameTable = (void*)( Base + expDir->NamePointerRVA ); + ordTable = (void*)( Base + expDir->OrdinalTableRVA ); + addrTable = (void*)( Base + expDir->AddressRVA ); + //DEBUGS(" PE_GetSymbol: %i Symbols\n", symbolCount); + for(i=0;i libc.so.1.dsm + $(OBJDUMP) -x -r -R $@ > libc.so.1.dmp + cp ../libc.so.1 ../libc.so + cp ../libc.so.1 /mnt/AcessHDD/Acess2/Libs/ + +# C Runtime 0 +../crt0.o: crt0.asm + @echo --- $(AS) -o $@ + @$(AS) $(ASFLAGS) -o $@ $< + +$(filter %.o, $(OBJ_LIBC)): %.o: %.c config.h + @echo --- $(CC) -o $@ + @$(CC) $(CFLAGS) -DBUILD_SO -o $@ -c $< + +$(filter %.ao, $(OBJ_LIBC)): %.ao: %.asm + @echo --- $(AS) -o $@ + @$(AS) $(ASFLAGS) -o $@ $< diff --git a/Usermode/Libraries/libc.so_src/env.c b/Usermode/Libraries/libc.so_src/env.c new file mode 100644 index 00000000..c0f8ea3f --- /dev/null +++ b/Usermode/Libraries/libc.so_src/env.c @@ -0,0 +1,33 @@ +/* +AcessOS C Library +- Environment Handler +*/ +#include + +// === 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; +} diff --git a/Usermode/Libraries/libc.so_src/fileIO.c b/Usermode/Libraries/libc.so_src/fileIO.c new file mode 100644 index 00000000..be6f80b2 --- /dev/null +++ b/Usermode/Libraries/libc.so_src/fileIO.c @@ -0,0 +1,166 @@ +/* +AcessOS Basic C Library +*/ +#include "config.h" +#include +#include +#include +#include "stdio_int.h" + +#define DEBUG_BUILD 0 + +// === CONSTANTS === + +// === PROTOTYPES === +struct sFILE *get_file_struct(); + +// === GLOBALS === +struct sFILE _iob[STDIO_MAX_STREAMS]; // IO Buffer + +// === CODE === +/** + * \fn FILE *freopen(FILE *fp, char *file, char *mode) + */ +FILE *freopen(FILE *fp, char *file, char *mode) +{ + int openFlags = 0; + int i; + + // Sanity Check Arguments + if(!fp || !file || !mode) return NULL; + + if(fp->Flags) { + fflush(fp); + close(fp->FD); + } + + // Get main mode + switch(mode[0]) + { + case 'r': fp->Flags = FILE_FLAG_MODE_READ; break; + case 'w': fp->Flags = FILE_FLAG_MODE_WRITE; break; + case 'a': fp->Flags = FILE_FLAG_MODE_APPEND; break; + case 'x': fp->Flags = FILE_FLAG_MODE_EXEC; break; + default: + return NULL; + } + // Get Modifiers + for(i=1;mode[i];i++) + { + switch(mode[i]) + { + case '+': fp->Flags |= FILE_FLAG_M_EXT; + } + } + + // Get Open Flags + switch(mode[0]) + { + // Read + case 'r': openFlags = OPENFLAG_READ; + if(fp->Flags & FILE_FLAG_M_EXT) + openFlags |= OPENFLAG_WRITE; + break; + // Write + case 'w': openFlags = OPENFLAG_WRITE; + if(fp->Flags & FILE_FLAG_M_EXT) + openFlags |= OPENFLAG_READ; + break; + // Execute + case 'x': openFlags = OPENFLAG_EXEC; + break; + } + + //Open File + fp->FD = reopen(fp->FD, file, openFlags); + if(fp->FD == -1) { + fp->Flags = 0; + return NULL; + } + + if(mode[0] == 'a') { + seek(fp->FD, 0, SEEK_END); //SEEK_END + } + + return fp; +} +/** + \fn FILE *fopen(char *file, char *mode) + \brief Opens a file and returns the pointer + \param file String - Filename to open + \param mode Mode to open in +*/ +FILE *fopen(char *file, char *mode) +{ + FILE *retFile; + + // Sanity Check Arguments + if(!file || !mode) return NULL; + + // Create Return Structure + retFile = get_file_struct(); + + return freopen(retFile, file, mode); +} + +void fclose(FILE *fp) +{ + close(fp->FD); + free(fp); +} + +void fflush(FILE *fp) +{ + ///\todo Implement +} + +/** + * \fn int fprintf(FILE *fp, const char *format, ...) + * \brief Print a formatted string to a stream + */ +int fprintf(FILE *fp, const char *format, ...) +{ + int size; + char *buf; + va_list args; + + if(!fp || !format) return -1; + + // Get Size + va_start(args, format); + size = ssprintfv((char*)format, args); + va_end(args); + + // Allocate buffer + buf = (char*)malloc(size+1); + buf[size] = '\0'; + + // Print + va_start(args, format); + sprintfv(buf, (char*)format, args); + va_end(args); + + // Write to stream + write(fp->FD, size+1, buf); + + // Free buffer + free(buf); + + // Return written byte count + return size; +} + +// --- INTERNAL --- +/** + * \fn FILE *get_file_struct() + * \brief Returns a file descriptor structure + */ +FILE *get_file_struct() +{ + int i; + for(i=0;i +#include +#include "lib.h" + +// === Constants === +#define MAGIC 0xACE55051 //AcessOS1 +#define MAGIC_FREE (~MAGIC) +#define BLOCK_SIZE 16 //Minimum +#define HEAP_INIT_SIZE 0x10000 + +typedef unsigned int Uint; + +//Typedefs +typedef struct { + Uint magic; + Uint size; +} heap_head; +typedef struct { + heap_head *header; + Uint magic; +} heap_foot; + +//Globals +void *_heap_start = NULL; +void *_heap_end = NULL; + +//Prototypes +EXPORT void *malloc(Uint bytes); +EXPORT void free(void *mem); +EXPORT void *realloc(void *mem, Uint bytes); +EXPORT void *sbrk(int increment); +LOCAL void *extendHeap(int bytes); +LOCAL uint brk(int delta); + +//Code + +/** + \fn EXPORT void *malloc(size_t bytes) + \brief Allocates memory from the heap space + \param bytes Integer - Size of buffer to return + \return Pointer to buffer +*/ +EXPORT void *malloc(size_t bytes) +{ + Uint bestSize; + Uint closestMatch = 0; + Uint bestMatchAddr = 0; + heap_head *curBlock; + + // Initialise Heap + if(_heap_start == NULL) + {LOCAL void *sbrk(int delta); + _heap_start = sbrk(0); + _heap_end = _heap_start; + extendHeap(HEAP_INIT_SIZE); + } + + curBlock = _heap_start; + + bestSize = bytes + sizeof(heap_head) + sizeof(heap_foot) + BLOCK_SIZE - 1; + bestSize = (bestSize/BLOCK_SIZE)*BLOCK_SIZE; //Round up to block size + + while((Uint)curBlock < (Uint)_heap_end) + { + //SysDebug(" malloc: curBlock = 0x%x, curBlock->magic = 0x%x\n", curBlock, curBlock->magic); + if(curBlock->magic == MAGIC_FREE) + { + if(curBlock->size == bestSize) + break; + if(bestSize < curBlock->size && (curBlock->size < closestMatch || closestMatch == 0)) { + closestMatch = curBlock->size; + bestMatchAddr = (Uint)curBlock; + } + } + else if(curBlock->magic != MAGIC) + { + //Corrupt Heap + //SysDebug("malloc: Corrupt Heap\n"); + return NULL; + } + curBlock = (heap_head*)((Uint)curBlock + curBlock->size); + } + + if((Uint)curBlock < (Uint)_heap_start) { + //SysDebug("malloc: Heap underrun for some reason\n"); + return NULL; + } + + //Found a perfect match + if((Uint)curBlock < (Uint)_heap_end) { + curBlock->magic = MAGIC; + return (void*)((Uint)curBlock + sizeof(heap_head)); + } + + //Out of Heap Space + if(!closestMatch) { + curBlock = extendHeap(bestSize); //Allocate more + if(curBlock == NULL) { + //SysDebug("malloc: Out of Heap Space\n"); + return NULL; + } + curBlock->magic = MAGIC; + return (void*)((Uint)curBlock + sizeof(heap_head)); + } + + //Split Block? + if(closestMatch - bestSize > BLOCK_SIZE) { + heap_foot *foot; + curBlock = (heap_head*)bestMatchAddr; + curBlock->magic = MAGIC; + curBlock->size = bestSize; + foot = (heap_foot*)(bestMatchAddr + bestSize - sizeof(heap_foot)); + foot->header = curBlock; + foot->magic = MAGIC; + + curBlock = (heap_head*)(bestMatchAddr + bestSize); + curBlock->magic = MAGIC_FREE; + curBlock->size = closestMatch - bestSize; + + foot = (heap_foot*)(bestMatchAddr + closestMatch - sizeof(heap_foot)); + foot->header = curBlock; + + ((heap_head*)bestMatchAddr)->magic = MAGIC; //mark as used + return (void*)(bestMatchAddr + sizeof(heap_head)); + } + + //Don't Split the block + ((heap_head*)bestMatchAddr)->magic = MAGIC; + return (void*)(bestMatchAddr+sizeof(heap_head)); +} + +/** + \fn EXPORT void free(void *mem) + \brief Free previously allocated memory + \param mem Pointer - Memory to free +*/ +EXPORT void free(void *mem) +{ + heap_head *head = mem; + + if(head->magic != MAGIC) //Valid Heap Address + return; + + head->magic = MAGIC_FREE; + + //Unify Right + if((Uint)head + head->size < (Uint)_heap_end) + { + heap_head *nextHead = (heap_head*)((Uint)head + head->size); + if(nextHead->magic == MAGIC_FREE) { //Is the next block free + head->size += nextHead->size; //Amalgamate + nextHead->magic = 0; //For Security + } + } + //Unify Left + if((Uint)head - sizeof(heap_foot) > (Uint)_heap_start) + { + heap_head *prevHead; + heap_foot *prevFoot = (heap_foot *)((Uint)head - sizeof(heap_foot)); + if(prevFoot->magic == MAGIC) { + prevHead = prevFoot->header; + if(prevHead->magic == MAGIC_FREE) { + prevHead->size += head->size; //Amalgamate + head->magic = 0; //For Security + } + } + } +} + +/** + \fn EXPORT void *realloc(void *oldPos, size_t bytes) + \brief Reallocate a block of memory + \param bytes Integer - Size of new buffer + \param oldPos Pointer - Old Buffer + \return Pointer to new buffer +*/ +EXPORT void *realloc(void *oldPos, size_t bytes) +{ + void *ret; + heap_head *head; + + if(oldPos == NULL) { + return malloc(bytes); + } + + //Check for free space after block + head = (heap_head*)((Uint)oldPos-sizeof(heap_head)); + + //Hack to used free's amagamating algorithym and malloc's splitting + free(oldPos); + + //Allocate new memory + ret = malloc(bytes); + if(ret == NULL) + return NULL; + + //Copy Old Data + if((Uint)ret != (Uint)oldPos) { + memcpy(ret, oldPos, head->size-sizeof(heap_head)-sizeof(heap_foot)); + } + + //Return + return ret; +} + +/** + \fn LOCAL void *extendHeap(int bytes) + \brief Create a new block at the end of the heap area + \param bytes Integer - Size reqired + \return Pointer to last free block + */ + +LOCAL void *extendHeap(int bytes) +{ + heap_head *head = _heap_end; + heap_foot *foot; + + //Expand Memory Space (Use foot as a temp pointer) + foot = sbrk(bytes); + if(foot == (void*)-1) + return NULL; + + + //Create New Block + // Header + head->magic = MAGIC_FREE; //Unallocated + head->size = bytes; + // Footer + foot = _heap_end + bytes - sizeof(heap_foot); + foot->header = head; + foot->magic = MAGIC; + + //Combine with previous block if nessasary + if(_heap_end != _heap_start && ((heap_foot*)((Uint)_heap_end-sizeof(heap_foot)))->magic == MAGIC) { + heap_head *tmpHead = ((heap_foot*)((Uint)_heap_end-sizeof(heap_foot)))->header; + if(tmpHead->magic == MAGIC_FREE) { + tmpHead->size += bytes; + foot->header = tmpHead; + head = tmpHead; + } + } + + _heap_end = (void*) ((Uint)foot+sizeof(heap_foot)); + return head; +} + +/** + \fn EXPORT void *sbrk(int increment) + \brief Increases the program's memory space + \param count Integer - Size of heap increase + \return Pointer to start of new region +*/ +EXPORT void *sbrk(int increment) +{ + size_t newEnd; + static size_t oldEnd = 0; + static size_t curEnd = 0; + + //SysDebug("sbrk: (increment=%i)\n", increment); + + if (oldEnd == 0) curEnd = oldEnd = brk(0); + + //SysDebug(" sbrk: oldEnd = 0x%x\n", oldEnd); + if (increment == 0) return (void *) curEnd; + + newEnd = curEnd + increment; + + if (brk(newEnd) == curEnd) return (void *) -1; + oldEnd = curEnd; + curEnd = newEnd; + //SysDebug(" sbrk: newEnd = 0x%x\n", newEnd); + + return (void *) oldEnd; +} + +/** + * \fn EXPORT int IsHeap(void *ptr) + */ +EXPORT int IsHeap(void *ptr) +{ + #if 0 + heap_head *head; + heap_foot *foot; + #endif + if( (Uint)ptr < (Uint)_heap_start ) return 0; + if( (Uint)ptr > (Uint)_heap_end ) return 0; + + #if 0 + head = (void*)((Uint)ptr - 4); + if( head->magic != MAGIC ) return 0; + foot = (void*)( (Uint)ptr + head->size - sizeof(heap_foot) ); + if( foot->magic != MAGIC ) return 0; + #endif + return 1; +} + +// === STATIC FUNCTIONS === +/** + * Does the job of brk(0) + */ +static void *FindHeapBase() +{ + #define MAX 0xC0000000 // Address + #define THRESHOLD 512 // Pages + uint addr; + uint stretch = 0; + + // Scan address space + for(addr = 0; + addr < MAX; + addr += 0x1000 + ) + { + if( _SysGetPhys(addr) == 0 ) { + stretch = 0; + } else { + stretch ++; + if(stretch > THRESHOLD) + { + return (void*)( addr + stretch*0x1000 ); + } + } + } + return NULL; +} + +LOCAL uint brk(int delta) +{ + static uint curpos; + uint pages; + uint ret = curpos; + + // Find initial position + if(curpos == 0) curpos = (uint)FindHeapBase(); + + // Get Current Position + if(delta == 0) + { + return curpos; + } + + // Do we need to add pages + if(curpos & 0xFFF && (curpos & 0xFFF) + delta < 0x1000) + return curpos += delta; + + // Page align current position + if(curpos & 0xFFF) delta -= 0x1000 - (curpos & 0xFFF); + curpos = (curpos + 0xFFF) & ~0xFFF; + + // Allocate Pages + pages = (delta + 0xFFF) >> 12; + while(pages--) + { + _SysAllocate(curpos); + curpos += 0x1000; + delta -= 0x1000; + } + + // Bring the current position to exactly what we want + curpos -= ((delta + 0xFFF) & ~0xFFF) - delta; + + return ret; // Return old curpos +} diff --git a/Usermode/Libraries/libc.so_src/signals.c b/Usermode/Libraries/libc.so_src/signals.c new file mode 100644 index 00000000..ddaf5448 --- /dev/null +++ b/Usermode/Libraries/libc.so_src/signals.c @@ -0,0 +1,24 @@ +/* + * AcessOS Basic C Library + * signals.c +*/ +#include +#include +#include +#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; +} diff --git a/Usermode/Libraries/libc.so_src/stdlib.c b/Usermode/Libraries/libc.so_src/stdlib.c new file mode 100644 index 00000000..44dc55fa --- /dev/null +++ b/Usermode/Libraries/libc.so_src/stdlib.c @@ -0,0 +1,409 @@ +/* +AcessOS Basic C Library + +stdlib.c +*/ +#include +#include +#include "lib.h" + +int _stdout = 1; +int _stdin = 2; + +EXPORT int puts(const char *str); +EXPORT void itoa(char *buf, unsigned long num, int base, int minLength, char pad); +EXPORT int atoi(const char *str); +EXPORT int puts(const char *str); +EXPORT int ssprintfv(char *format, va_list args); +EXPORT void sprintfv(char *buf, char *format, va_list args); +EXPORT int printf(const char *format, ...); +EXPORT int strlen(const char *str); +EXPORT int strcmp(char *str1, char *str2); +EXPORT int strncmp(char *str1, char *str2, size_t len); +EXPORT char *strcpy(char *dst, const char *src); + +// === CODE === +EXPORT int putchar(int ch) +{ + return write(_stdout, 1, (char*)&ch); +} + +EXPORT int puts(const char *str) +{ + int len; + + if(!str) return 0; + len = strlen(str); + + len = write(_stdout, len, (char*)str); + write(_stdout, 1, "\n"); + return len; +} + +//sprintfv +/** + \fn EXPORT void sprintfv(char *buf, char *format, va_list args) + \brief Prints a formatted string to a buffer + \param buf Pointer - Destination Buffer + \param format String - Format String + \param args VarArgs List - Arguments +*/ +EXPORT void sprintfv(char *buf, char *format, va_list args) +{ + char tmp[33]; + int c, arg, minSize; + int pos = 0; + char *p; + char pad; + + tmp[32] = '\0'; + + while((c = *format++) != 0) + { + //SysDebug("c = '%c'\n", c); + if (c != '%') { + buf[pos++] = c; + continue; + } + + c = *format++; + if(c == '%') { + buf[pos++] = '%'; + continue; + } + + // Padding + if(c == '0') { + pad = '0'; + c = *format++; + } else + pad = ' '; + minSize = 0; + if('1' <= c && c <= '9') + { + while('0' <= c && c <= '9') + { + minSize *= 10; + minSize += c - '0'; + c = *format++; + } + } + + p = tmp; + + // Get Argument + arg = va_arg(args, int); + // Get Type + switch (c) { + case 'd': + case 'i': + if(arg < 0) { + buf[pos++] = '-'; + arg = -arg; + } + itoa(tmp, arg, 10, minSize, pad); + goto sprintf_puts; + // break; + case 'u': + itoa(tmp, arg, 10, minSize, pad); + goto sprintf_puts; + // break; + case 'x': + itoa(tmp, arg, 16, minSize, pad); + goto sprintf_puts; + // break; + case 'o': + itoa(tmp, arg, 8, minSize, pad); + goto sprintf_puts; + // break; + case 'b': + itoa(tmp, arg, 2, minSize, pad); + goto sprintf_puts; + // break; + + case 's': + p = (void*)arg; + sprintf_puts: + if(!p) p = "(null)"; + while(*p) buf[pos++] = *p++; + break; + + default: + buf[pos++] = arg; + break; + } + } + buf[pos++] = '\0'; +} +/* +ssprintfv +- Size, Stream, Print Formated, Variable Argument List +*/ +/** + \fn EXPORT int ssprintfv(char *format, va_list args) + \brief Gets the total character count from a formatted string + \param format String - Format String + \param args VarArgs - Argument List +*/ +EXPORT int ssprintfv(char *format, va_list args) +{ + char tmp[33]; + int c, arg, minSize; + int len = 0; + char *p; + char pad; + + tmp[32] = '\0'; + + while((c = *format++) != 0) + { + if (c != '%') { + len++; + continue; + } + + c = *format++; + + // Literal '%' + if(c == '%') { + len++; + continue; + } + + // Padding + if(c == '0') { + pad = '0'; + c = *format++; + } else + pad = ' '; + minSize = 0; + if('1' <= c && c <= '9') + { + while('0' <= c && c <= '9') + { + minSize *= 10; + minSize += c - '0'; + c = *format++; + } + } + + p = tmp; + arg = va_arg(args, int); + switch (c) { + case 'd': + case 'i': + if(arg < 0) { + len ++; + arg = -arg; + } + itoa(tmp, arg, 10, minSize, pad); + goto sprintf_puts; + case 'u': + itoa(tmp, arg, 10, minSize, pad); + goto sprintf_puts; + case 'x': + itoa(tmp, arg, 16, minSize, pad); + goto sprintf_puts; + case 'o': + itoa(tmp, arg, 8, minSize, pad); + p = tmp; + goto sprintf_puts; + case 'b': + itoa(tmp, arg, 2, minSize, pad); + goto sprintf_puts; + + case 's': + p = (char*)arg; + sprintf_puts: + if(!p) p = "(null)"; + while(*p) len++, p++; + break; + + default: + len ++; + break; + } + } + return len; +} + +const char cUCDIGITS[] = "0123456789ABCDEF"; +/** + * \fn static void itoa(char *buf, unsigned long num, int base, int minLength, char pad) + * \brief Convert an integer into a character string + */ +EXPORT void itoa(char *buf, unsigned long num, int base, int minLength, char pad) +{ + char tmpBuf[32]; + int pos=0, i; + + if(!buf) return; + if(base > 16) { + buf[0] = 0; + return; + } + + while(num > base-1) { + tmpBuf[pos] = cUCDIGITS[ num % base ]; + num = (long) num / base; //Shift {number} right 1 digit + pos++; + } + + tmpBuf[pos++] = cUCDIGITS[ num % base ]; //Last digit of {number} + i = 0; + minLength -= pos; + while(minLength-- > 0) buf[i++] = pad; + while(pos-- > 0) buf[i++] = tmpBuf[pos]; //Reverse the order of characters + buf[i] = 0; +} + +/** + */ +EXPORT int atoi(const char *str) +{ + int neg = 0; + int ret = 0; + + // NULL Check + if(!str) return 0; + + while(*str == ' ' || *str == '\t') str++; + + // Check for negative + if(*str == '-') { + neg = 1; + str++; + } + + if(*str == '0') { + str ++; + if(*str == 'x') { + str++; + // Hex + while( ('0' <= *str && *str <= '9') + || ('A' <= *str && *str <= 'F' ) + || ('a' <= *str && *str <= 'f' ) + ) + { + ret *= 16; + if(*str <= '9') { + ret += *str - '0'; + } else if (*str <= 'F') { + ret += *str - 'A' + 10; + } else { + ret += *str - 'a' + 10; + } + str++; + } + } else { + // Octal + while( '0' <= *str && *str <= '7' ) + { + ret *= 8; + ret += *str - '0'; + str++; + } + } + } else { + // Decimal + while( '0' <= *str && *str <= '9' ) + { + ret *= 10; + ret += *str - '0'; + str++; + } + } + + // Negate if needed + if(neg) ret = -ret; + return ret; +} + +//printf +EXPORT int printf(const char *format, ...) +{ + int size; + char *buf; + va_list args; + + va_start(args, format); + size = ssprintfv((char*)format, args); + va_end(args); + + buf = (char*)malloc(size+1); + buf[size] = '\0'; + + va_start(args, format); + sprintfv(buf, (char*)format, args); + va_end(args); + + + write(_stdout, size+1, buf); + + free(buf); + return size; +} + +EXPORT int sprintf(const char *buf, char *format, ...) +{ + va_list args; + va_start(args, format); + sprintfv((char*)buf, (char*)format, args); + va_end(args); + return 1; +} + + +//MEMORY +EXPORT int strcmp(char *s1, char *s2) +{ + while(*s1 == *s2 && *s1 != '\0' && *s2 != '\0') { + s1++; s2++; + } + return (int)*s1 - (int)*s2; +} +EXPORT char *strcpy(char *dst, const char *src) +{ + char *_dst = dst; + while(*src) { + *dst = *src; + src++; dst++; + } + *dst = '\0'; + return _dst; +} +EXPORT int strlen(const char *str) +{ + int retval; + for(retval = 0; *str != '\0'; str++) + retval++; + return retval; +} + +EXPORT int strncmp(char *s1, char *s2, size_t len) +{ + while(--len && *s1 == *s2 && *s1 != '\0' && *s2 != '\0') { + s1++; s2++; + } + return (int)*s1 - (int)*s2; +} + +EXPORT void *memcpy(void *dest, void *src, unsigned int count) +{ + char *sp = (char *)src; + char *dp = (char *)dest; + for(;count--;) *dp++ = *sp++; + return dest; +} + +EXPORT void *memmove(void *dest, void *src, unsigned int count) +{ + char *sp = (char *)src; + char *dp = (char *)dest; + // Check if corruption will happen + if( (unsigned int)dest > (unsigned int)src && (unsigned int)dest < (unsigned int)src+count ) + for(;count--;) dp[count] = sp[count]; + else + for(;count--;) *dp++ = *sp++; + return dest; +} diff --git a/Usermode/Libraries/libc.so_src/stub.c b/Usermode/Libraries/libc.so_src/stub.c new file mode 100644 index 00000000..05adb8eb --- /dev/null +++ b/Usermode/Libraries/libc.so_src/stub.c @@ -0,0 +1,21 @@ +/* +AcessOS Basic C Library +*/ + +extern char **_envp; + +/** + * \fn int SoMain() + * \brief Stub Entrypoint + * \param BaseAddress Unused - Load Address of libc + * \param argc Unused - Argument Count (0 for current version of ld-acess) + * \param argv Unused - Arguments (NULL for current version of ld-acess) + * \param envp Environment Pointer + */ +int SoMain(unsigned int BaseAddress, int argc, char **argv, char **envp) +{ + // Init for env.c + _envp = envp; + + return 1; +} diff --git a/Usermode/include/acess/sys.h b/Usermode/include/acess/sys.h new file mode 100644 index 00000000..d0b45307 --- /dev/null +++ b/Usermode/include/acess/sys.h @@ -0,0 +1,51 @@ +/* + * Acess2 System Interface Header + */ +#ifndef _SYS_SYS_H_ +#define _SYS_SYS_H_ + +#include + +// === 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 diff --git a/Usermode/include/stdint.h b/Usermode/include/stdint.h new file mode 100644 index 00000000..3ad94bda --- /dev/null +++ b/Usermode/include/stdint.h @@ -0,0 +1,17 @@ +/* + */ +#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 diff --git a/Usermode/include/stdio.h b/Usermode/include/stdio.h new file mode 100644 index 00000000..b8e70f95 --- /dev/null +++ b/Usermode/include/stdio.h @@ -0,0 +1,23 @@ +/* + * AcessOS LibC + * stdlib.h + */ +#ifndef __STDIO_H +#define __STDIO_H + +typedef struct sFILE FILE; + +extern int printf(const char *format, ...); +extern void sprintfv(char *buf, char *format, va_list args); +extern int ssprintfv(char *format, va_list args); +extern int sprintf(char *buf, char *format, ...); + +extern FILE *fopen(char *file, char *mode); +extern FILE *freopen(FILE *fp, char *file, char *mode); +extern void fclose(FILE *fp); +extern void fflush(FILE *fp); + +extern int fprintf(FILE *fp, const char *format, ...); + +#endif + diff --git a/Usermode/include/stdlib.h b/Usermode/include/stdlib.h new file mode 100644 index 00000000..87744271 --- /dev/null +++ b/Usermode/include/stdlib.h @@ -0,0 +1,51 @@ +/* +AcessOS LibC + +stdlib.h +*/ +#ifndef __STDLIB_H +#define __STDLIB_H + +#include +#include + +#ifndef NULL +# define NULL ((void*)0) +#endif + +typedef unsigned int size_t; + +// --- Spinlock Macros --- +#define DEFLOCK(_name) static int _spinlock_##_name=0; +//#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)) +#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) +#define UNLOCK(_name) __asm__ __volatile__("lock andl $0, (%0)"::"D"(&_spinlock_##_name)) + +// --- StdLib --- +extern int atoi(const char *ptr); + +extern void *memcpy(void *dest, void *src, size_t count); +extern void *memmove(void *dest, void *src, size_t count); + +// --- Environment --- +extern char *getenv(const char *name); + +// --- Heap --- +extern void free(void *mem); +extern void *malloc(unsigned int bytes); +extern void *realloc(void *oldPos, unsigned int bytes); +extern int IsHeap(void *ptr); + +// --- Strings --- +extern int strlen(const char *string); +extern int strcmp(char *str1, char *str2); +extern int strncmp(char *str1, char *str2, size_t len); +extern char *strcpy(char *dst, const char *src); + +#ifndef SEEK_CUR +# define SEEK_CUR 0 +# define SEEK_SET 1 +# define SEEK_END (-1) +#endif + +#endif diff --git a/Usermode/include/sys/basic_drivers.h b/Usermode/include/sys/basic_drivers.h new file mode 100644 index 00000000..ee5334e5 --- /dev/null +++ b/Usermode/include/sys/basic_drivers.h @@ -0,0 +1,47 @@ +/** + * \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 +}; +struct sVideo_IOCtl_Mode { + short id; + Uint16 width; + Uint16 height; + Uint16 bpp; +}; +typedef struct sVideo_IOCtl_Mode tVideo_IOCtl_Mode; //!< Mode Type + +// === MOUSE === +enum eDrv_Mouse { + MSE_IOCTL_SENS = 4, + MSE_IOCTL_MAX_X, + MSE_IOCTL_MAX_Y +}; + +#endif diff --git a/Usermode/include/sys/sys.h b/Usermode/include/sys/sys.h new file mode 100644 index 00000000..7ddf5832 --- /dev/null +++ b/Usermode/include/sys/sys.h @@ -0,0 +1,38 @@ +/* + Syscall Definitions +*/ + +#include + +#define OPEN_FLAG_READ 1 +#define OPEN_FLAG_WRITE 2 +#define OPEN_FLAG_EXEC 4 + +enum { + K_WAITPID_DIE = 0 +}; + +// === System Calls === +extern void _exit(int ret); +extern int brk(int bssend); +extern int execve(char *file, char *args[], char *envp[]); +extern int fork(); +extern int yield(); +extern int sleep(); + +extern int open(char *file, int flags); +extern int close(int fp); +extern int read(int fp, int len, void *buf); +extern int write(int fp, int len, void *buf); +extern int tell(int fp); +extern void seek(int fp, int dist, int flag); +extern int fstat(int fp, t_fstat *st); +extern int ioctl(int fp, int call, void *arg); +extern int readdir(int fp, char *file); +extern int kdebug(char *fmt, ...); +extern int waitpid(int pid, int action); +extern int gettid(); // Get Thread ID +extern int getpid(); // Get Process ID +extern int sendmsg(int dest, unsigned int *Data); +extern int pollmsg(int *src, unsigned int *Data); +extern int getmsg(int *src, unsigned int *Data); diff --git a/Usermode/include/sys/types.h b/Usermode/include/sys/types.h new file mode 100644 index 00000000..03ee846b --- /dev/null +++ b/Usermode/include/sys/types.h @@ -0,0 +1,28 @@ + +#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