OBJ = $(addprefix arch/$(ARCHDIR)/,$(A_OBJ))
OBJ += heap.o messages.o debug.o modules.o lib.o syscalls.o system.o threads.o drvutil.o
-OBJ += binary.o bin/elf.o
+OBJ += binary.o bin/elf.o bin/pe.o
OBJ += vfs/main.o vfs/open.o vfs/acls.o vfs/dir.o vfs/io.o vfs/mount.o vfs/memfile.o vfs/nodecache.o
OBJ += vfs/fs/root.o vfs/fs/devfs.o
OBJ += $(addprefix vfs/fs/, $(addsuffix .o,$(FILESYSTEMS)))
-BUILD_NUM = 1359
+BUILD_NUM = 1368
--- /dev/null
+/*\r
+ * Acess v1\r
+ * Portable Executable Loader\r
+ */\r
+#define DEBUG 1\r
+#include <acess.h>\r
+#include <binary.h>\r
+#include <modules.h>\r
+#include "pe.h"\r
+\r
+// === PROTOTYPES ===\r
+ int PE_Install(char **Arguments);\r
+tBinary *PE_Load(int fp);\r
+tBinary *MZ_Open(int fp);\r
+ int PE_Relocate(void *Base);\r
+ int PE_GetSymbol(void *Base, char *Name, Uint *Ret);\r
+\r
+// === GLOBALS ===\r
+MODULE_DEFINE(0, 0x0032, BinPE, PE_Install, NULL, NULL);\r
+char *gsPE_DefaultInterpreter = "/Acess/Libs/ld-acess.so";\r
+tBinaryType gPE_Loader = {\r
+ NULL,\r
+ ('M'|('Z'<<8)), 0xFFFF, // 'MZ'\r
+ "PE/DOS",\r
+ PE_Load, PE_Relocate, PE_GetSymbol\r
+ };\r
+\r
+// === CODE ===\r
+int PE_Install(char **Arguments)\r
+{\r
+ Binary_RegisterType(&gPE_Loader);\r
+ return 1;\r
+}\r
+\r
+/**\r
+ * \brief Loads a PE Binary\r
+ */\r
+tBinary *PE_Load(int FP)\r
+{\r
+ int count, i, j, k;\r
+ int iPageCount;\r
+ tBinary *ret;\r
+ tPE_DOS_HEADER dosHdr;\r
+ tPE_IMAGE_HEADERS peHeaders;\r
+ tPE_SECTION_HEADER *peSections;\r
+ char namebuf[9] = {0};\r
+ Uint iFlags, iVA;\r
+ \r
+ ENTER("xFP", FP);\r
+ \r
+ // Read DOS header and check\r
+ VFS_Read(FP, sizeof(tPE_DOS_HEADER), &dosHdr);\r
+ if( dosHdr.Ident != ('M'|('Z'<<8)) ) {\r
+ LEAVE('n');\r
+ return NULL;\r
+ }\r
+ \r
+ // - Read PE Header\r
+ VFS_Seek(FP, dosHdr.PeHdrOffs, SEEK_SET);\r
+ if( VFS_Tell(FP) != dosHdr.PeHdrOffs ) {\r
+ ret = MZ_Open(FP);\r
+ LEAVE('p', ret);\r
+ return ret;\r
+ }\r
+ VFS_Read(FP, sizeof(tPE_IMAGE_HEADERS), &peHeaders);\r
+ \r
+ // - Check PE Signature and pass on to the MZ Loader if invalid\r
+ if( peHeaders.Signature != (('P')|('E'<<8)) ) {\r
+ ret = MZ_Open(FP);\r
+ LEAVE('p', ret);\r
+ return ret;\r
+ }\r
+ \r
+ // Read Sections (Uses `count` as a temp variable)\r
+ count = sizeof(tPE_SECTION_HEADER) * peHeaders.FileHeader.SectionCount;\r
+ peSections = malloc( count );\r
+ if(!peSections)\r
+ {\r
+ Warning("PE_Load - Unable to allocate `peSections`, 0x%x bytes", count);\r
+ LEAVE('n');\r
+ return NULL;\r
+ }\r
+ VFS_Read(FP, count, peSections);\r
+ \r
+ // Count Pages\r
+ iPageCount = 1; // 1st page is headers\r
+ for( i = 0; i < peHeaders.FileHeader.SectionCount; i++ )\r
+ {\r
+ // Check if the section is loadable\r
+ // (VA is zero in non-loadable sections)\r
+ if(peSections[i].RVA + peHeaders.OptHeader.ImageBase == 0) continue;\r
+ \r
+ // Moar pages\r
+ iPageCount += (peSections[i].VirtualSize + 0xFFF) >> 12;\r
+ }\r
+ \r
+ LOG("%i Pages", iPageCount);\r
+ \r
+ // Initialise Executable Information\r
+ ret = malloc(sizeof(tBinary) + sizeof(tBinaryPage)*iPageCount);\r
+ \r
+ ret->Entry = peHeaders.OptHeader.EntryPoint + peHeaders.OptHeader.ImageBase;\r
+ ret->Base = peHeaders.OptHeader.ImageBase;\r
+ ret->Interpreter = gsPE_DefaultInterpreter;\r
+ ret->NumPages = iPageCount;\r
+ \r
+ LOG("Entry=%p, BaseAddress=0x%x\n", ret->Entry, ret->Base);\r
+ \r
+ ret->Pages[0].Virtual = peHeaders.OptHeader.ImageBase;\r
+ ret->Pages[0].Physical = 0;\r
+ ret->Pages[0].Size = 4096;\r
+ ret->Pages[0].Flags = 0;\r
+ \r
+ // Parse Sections\r
+ j = 1; // Page Index\r
+ for( i = 0; i < peHeaders.FileHeader.SectionCount; i++ )\r
+ {\r
+ iVA = peSections[i].RVA + peHeaders.OptHeader.ImageBase;\r
+ \r
+ // Skip non-loadable sections\r
+ if(iVA == 0) continue;\r
+ \r
+ // Create Name Buffer\r
+ memcpy(namebuf, peSections[i].Name, 8);\r
+ LOG("Section %i '%s', iVA = %p", i, namebuf, iVA);\r
+ \r
+ // Create Flags\r
+ iFlags = 0;\r
+ if(peSections[i].Flags & PE_SECTION_FLAG_MEM_EXECUTE)\r
+ iFlags |= BIN_PAGEFLAG_EXEC;\r
+ if( !(peSections[i].Flags & PE_SECTION_FLAG_MEM_WRITE) )\r
+ iFlags |= BIN_PAGEFLAG_RO;\r
+ \r
+ // Create Page Listing\r
+ count = (peSections[i].RawSize + 0xFFF) >> 12;\r
+ for(k=0;k<count;k++)\r
+ {\r
+ ret->Pages[j+k].Virtual = iVA + (k<<12);\r
+ ret->Pages[j+k].Physical = peSections[i].RawOffs + (k<<12); // Store the offset in the physical address\r
+ if(k == count-1 && (peSections[i].RawSize & 0xFFF))\r
+ ret->Pages[j+k].Size = peSections[i].RawSize & 0xFFF; // Byte count in page\r
+ else\r
+ ret->Pages[j+k].Size = 4096;\r
+ ret->Pages[j+k].Flags = iFlags;\r
+ }\r
+ count = (peSections[i].VirtualSize + 0xFFF) >> 12;\r
+ for(;k<count;k++)\r
+ {\r
+ ret->Pages[j+k].Virtual = iVA + (k<<12);\r
+ ret->Pages[j+k].Physical = -1; // -1 = Fill with zeros\r
+ if(k == count-1 && (peSections[i].VirtualSize & 0xFFF))\r
+ ret->Pages[j+k].Size = peSections[i].VirtualSize & 0xFFF; // Byte count in page\r
+ else\r
+ ret->Pages[j+k].Size = 4096;\r
+ ret->Pages[j+k].Flags = iFlags;\r
+ }\r
+ j += count;\r
+ \r
+ LOG("%i Name:'%s', RVA: 0x%x, Size: 0x%x (0x%x), Ofs: 0x%x, Flags: 0x%x",\r
+ i, namebuf, \r
+ iVA,\r
+ peSections[i].VirtualSize, peSections[i].RawSize, peSections[i].RawOffs,\r
+ peSections[i].Flags\r
+ );\r
+ \r
+ }\r
+ // Free Executable Memory\r
+ free(peSections);\r
+ \r
+ LEAVE('p', ret);\r
+ return ret;\r
+}\r
+\r
+/**\r
+ */\r
+tBinary *MZ_Open(int FP)\r
+{\r
+ ENTER("xFP", FP);\r
+ UNIMPLEMENTED();\r
+ LEAVE('n');\r
+ return NULL;\r
+}\r
+\r
+int PE_Relocate(void *Base)\r
+{\r
+ tPE_DOS_HEADER *dosHdr;\r
+ tPE_IMAGE_HEADERS *peHeaders;\r
+ tPE_SECTION_HEADER *peSections;\r
+ tPE_DATA_DIR *directory;\r
+ tPE_IMPORT_DIR *impDir;\r
+ int i;\r
+ Uint iBase = (Uint)Base;\r
+ #if 0\r
+ void *hLibrary;\r
+ char *libPath;\r
+ #endif\r
+ \r
+ ENTER("pBase", Base);\r
+ dosHdr = Base;\r
+ peHeaders = (void*)( iBase + dosHdr->PeHdrOffs );\r
+ peSections = (void*)( iBase + sizeof(tPE_IMAGE_HEADERS) );\r
+ \r
+ directory = (void*)(peSections[0].RVA + iBase);\r
+ \r
+ // === Load Import Tables\r
+ impDir = (void*)( directory[PE_DIR_IMPORT].RVA + iBase );\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
+ LOG("DLL Required '%s'(0x%x)", impDir[i].DLLName, impDir[i].DLLName);\r
+ #if 0\r
+ libPath = FindLibrary(impDir[i].DLLName);\r
+ if(libPath == NULL)\r
+ {\r
+ Warning("PE_Relocate - Unable to find library '%s'");\r
+ LEAVE('i', -1);\r
+ return -1;\r
+ }\r
+ LOG("DLL Path = '%s'", libPath);\r
+ hLibrary = DynLib_Load(libPath, 0);\r
+ #endif\r
+ }\r
+ \r
+ for(i=0;i<PE_DIR_LAST;i++)\r
+ LOG("directory[%i] = {RVA=0x%x,Size=0x%x}", i, directory[i].RVA, directory[i].Size);\r
+ \r
+ LEAVE('i', 0);\r
+ return 0;\r
+}\r
+\r
+int PE_GetSymbol(void *Base, char *Name, Uint *Ret)\r
+{\r
+ return 0;\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
+ Uint16 Hint;\r
+ char Name[]; // Zero Term 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
tBinaryType *gRegBinTypes = &gELF_Info;\r
\r
// === FUNCTIONS ===\r
+/**\r
+ * \brief Registers a binary type\r
+ */\r
+int Binary_RegisterType(tBinaryType *Type)\r
+{\r
+ Type->Next = gRegBinTypes;\r
+ gRegBinTypes = Type;\r
+ return 1;\r
+}\r
+\r
/**\r
* \fn int Proc_Spawn(char *Path)\r
*/\r
addr += base;\r
LOG("%i - 0x%x to 0x%x", i, addr, binary->Pages[i].Physical);\r
MM_Map( addr, (Uint) (binary->Pages[i].Physical) );\r
- if( binary->Pages[i].Physical & 1) // Read-Only\r
+ \r
+ // Read-Only?\r
+ if( binary->Pages[i].Flags & BIN_PAGEFLAG_RO)\r
MM_SetFlags( addr, MM_PFLAG_RO, -1 );\r
else\r
MM_SetFlags( addr, MM_PFLAG_COW, -1 );\r
+ \r
+ // Execute?\r
+ if( binary->Pages[i].Flags & BIN_PAGEFLAG_EXEC )\r
+ MM_SetFlags( addr, MM_PFLAG_EXEC, -1 );\r
+ else\r
+ MM_SetFlags( addr, MM_PFLAG_EXEC, 0 );\r
+ \r
}\r
\r
//Log("Mapped '%s' to 0x%x", binary->TruePath, base);\r
Uint dest;\r
tPAddr paddr;\r
paddr = (Uint)MM_AllocPhys();\r
+ if(paddr == 0) {\r
+ Warning("Binary_DoLoad - Physical memory allocation failed");\r
+ for( ; i--; ) {\r
+ MM_DerefPhys( pBinary->Pages[i].Physical );\r
+ }\r
+ return NULL;\r
+ }\r
MM_RefPhys( paddr ); // Make sure it is _NOT_ freed until we want it to be\r
dest = MM_MapTemp( paddr );\r
dest += pBinary->Pages[i].Virtual & 0xFFF;\r
LOG("dest = 0x%x, paddr = 0x%x", dest, paddr);\r
- LOG("Pages[%i]={Physical:0x%x,Virtual:0x%x,Size:0x%x}",\r
+ LOG("Pages[%i]={Physical:0x%llx,Virtual:%p,Size:0x%x}",\r
i, pBinary->Pages[i].Physical, pBinary->Pages[i].Virtual, pBinary->Pages[i].Size);\r
\r
// Pure Empty Page\r
if(pBinary->Pages[i].Physical == -1) {\r
LOG("%i - ZERO", i);\r
- memsetd( (void*)dest, 0, 1024 );\r
+ memsetd( (void*)dest, 0, 1024 - (pBinary->Pages[i].Virtual & 0xFFF)/4 );\r
}\r
else\r
{\r
VFS_Seek( fp, pBinary->Pages[i].Physical, 1 );\r
if(pBinary->Pages[i].Size != 0x1000) {\r
- LOG("%i - 0x%x - 0x%x bytes",\r
+ LOG("%i - 0x%llx - 0x%x bytes",\r
i, pBinary->Pages[i].Physical, pBinary->Pages[i].Size);\r
memset( (void*)dest, 0, 0x1000 -(dest&0xFFF) );\r
VFS_Read( fp, pBinary->Pages[i].Size, (void*)dest );\r
LOG("%i - 0x%x to 0x%x", i, addr, pBinary->Pages[i].Physical);\r
MM_Map( addr, (Uint) (pBinary->Pages[i].Physical) );\r
MM_SetFlags( addr, MM_PFLAG_KERNEL, MM_PFLAG_KERNEL );\r
- #if 0 // Why was this here? It's the kernel\r
- if( pBinary->Pages[i].Physical & 1) // Read-Only\r
+ \r
+ if( pBinary->Pages[i].Flags & BIN_PAGEFLAG_RO) // Read-Only?\r
MM_SetFlags( addr, MM_PFLAG_RO, MM_PFLAG_KERNEL );\r
- else\r
- MM_SetFlags( addr, MM_PFLAG_COW, MM_PFLAG_KERNEL );\r
- //MM_SetCOW( addr );\r
- #endif\r
}
\r
// Relocate Library\r
Uint16 Flags; //!< Load Flags
} __attribute__ ((packed)) tBinaryPage;
+/**
+ * \brief Flags for ::tBinaryPage.Flags
+ * \name Binary Page Flags
+ * \{
+ */
+//! \brief Read-only
+#define BIN_PAGEFLAG_RO 0x0001
+//! \brief Executable
+#define BIN_PAGEFLAG_EXEC 0x0002
+/**
+ * \}
+ */
+
/**
* \brief Defines a binary file
*
*/
extern char *Binary_RegInterp(char *Path);
+extern int Binary_RegisterType(tBinaryType *Type);
+
#endif