X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Kernel%2Fbinary.c;h=8c28d724f71b82c9b6c1d34d08cdbd9583f8ac0a;hb=c0a6af0e8c4840c370e819cd44925502fae8c4ba;hp=de4d813b787716133c95e235f307461cd9725cf5;hpb=e29b02ca55d580b2f7f10d1093c3d6ad1bc59458;p=tpg%2Facess2.git diff --git a/Kernel/binary.c b/Kernel/binary.c index de4d813b..8c28d724 100644 --- a/Kernel/binary.c +++ b/Kernel/binary.c @@ -6,11 +6,11 @@ #include #include #include +#include // === CONSTANTS === #define BIN_LOWEST MM_USER_MIN // 1MiB #define BIN_GRANUALITY 0x10000 // 64KiB -//! \todo Move 0xBC000000 to mm_virt.h #define BIN_HIGHEST (USER_LIB_MAX-BIN_GRANUALITY) // Just below the kernel #define KLIB_LOWEST MM_MODULE_MIN #define KLIB_GRANUALITY 0x10000 // 32KiB @@ -24,33 +24,34 @@ typedef struct sKernelBin { } tKernelBin; // === IMPORTS === -extern int Proc_Clone(Uint *Err, Uint Flags); extern char *Threads_GetName(int ID); -extern void Threads_Exit(int, int); -extern Uint MM_ClearUser(void); -extern void Proc_StartUser(Uint Entrypoint, Uint *Bases, int ArgC, char **ArgV, char **EnvP, int DataSize); extern tKernelSymbol gKernelSymbols[]; -extern void gKernelSymbolsEnd; +extern tKernelSymbol gKernelSymbolsEnd[]; extern tBinaryType gELF_Info; // === PROTOTYPES === - int Proc_Execve(char *File, char **ArgV, char **EnvP); -Uint Binary_Load(char *file, Uint *entryPoint); -tBinary *Binary_GetInfo(char *truePath); -Uint Binary_MapIn(tBinary *binary); -Uint Binary_IsMapped(tBinary *binary); -tBinary *Binary_DoLoad(char *truePath); + int Proc_Execve(const char *File, const char **ArgV, const char **EnvP); +tVAddr Binary_Load(const char *Path, tVAddr *EntryPoint); +tBinary *Binary_GetInfo(tMount MountID, tInode InodeID); +tVAddr Binary_MapIn(tBinary *Binary, const char *Path, tVAddr LoadMin, tVAddr LoadMax); +tVAddr Binary_IsMapped(tBinary *Binary); +tBinary *Binary_DoLoad(tMount MountID, tInode Inode, const char *Path); void Binary_Dereference(tBinary *Info); +#if 0 Uint Binary_Relocate(void *Base); -Uint Binary_GetSymbolEx(char *Name, Uint *Value); -Uint Binary_FindSymbol(void *Base, char *Name, Uint *Val); +#endif +Uint Binary_GetSymbolEx(const char *Name, Uint *Value); +#if 0 +Uint Binary_FindSymbol(void *Base, const char *Name, Uint *Val); +#endif + int Binary_int_CheckMemFree( tVAddr _start, size_t _len ); // === GLOBALS === - int glBinListLock = 0; +tShortSpinlock glBinListLock; tBinary *glLoadedBinaries = NULL; char **gsaRegInterps = NULL; int giRegInterps = 0; - int glKBinListLock = 0; +tShortSpinlock glKBinListLock; tKernelBin *glLoadedKernelLibs; tBinaryType *gRegBinTypes = &gELF_Info; @@ -66,44 +67,45 @@ int Binary_RegisterType(tBinaryType *Type) } /** - * \fn int Proc_Spawn(char *Path) + * \fn int Proc_Spawn(const char *Path) */ -int Proc_Spawn(char *Path) +int Proc_Spawn(const char *Path) { char stackPath[strlen(Path)+1]; + ENTER("sPath", Path); strcpy(stackPath, Path); - LOG("stackPath = '%s'\n", stackPath); + LOG("stackPath = '%s'", stackPath); - if(Proc_Clone(NULL, CLONE_VM) == 0) + if(Proc_Clone(CLONE_VM) == 0) { // CHILD - char *args[2] = {stackPath, NULL}; - LOG("stackPath = '%s'\n", stackPath); + const char *args[2] = {stackPath, NULL}; + LOG("stackPath = '%s'", stackPath); Proc_Execve(stackPath, args, &args[1]); for(;;); } + LEAVE('i', 0); return 0; } /** - * \fn int Proc_Execve(char *File, char **ArgV, char **EnvP) * \brief Replace the current user image with another * \param File File to load as the next image * \param ArgV Arguments to pass to user * \param EnvP User's environment * \note Called Proc_ for historical reasons */ -int Proc_Execve(char *File, char **ArgV, char **EnvP) +int Proc_Execve(const char *File, const char **ArgV, const char **EnvP) { int argc, envc, i; int argenvBytes; - char *argenvBuf, *strBuf; + char **argenvBuf, *strBuf; char **argvSaved, **envpSaved; char *savedFile; - Uint entry; - Uint bases[2] = {0}; + tVAddr entry; + Uint base; // Uint because Proc_StartUser wants it ENTER("sFile pArgV pEnvP", File, ArgV, EnvP); @@ -115,23 +117,26 @@ int Proc_Execve(char *File, char **ArgV, char **EnvP) argenvBytes += strlen(ArgV[argc])+1; for( envc = 0; EnvP && EnvP[envc]; envc++ ) argenvBytes += strlen(EnvP[envc])+1; + LOG("argc = %i, envc = %i", envc); argenvBytes = (argenvBytes + sizeof(void*)-1) & ~(sizeof(void*)-1); argenvBytes += (argc+1)*sizeof(void*) + (envc+1)*sizeof(void*); // Allocate argenvBuf = malloc(argenvBytes); if(argenvBuf == NULL) { - Warning("Proc_Execve - What the hell? The kernel is out of heap space"); + Log_Error("Binary", "Proc_Execve - What the hell? The kernel is out of heap space"); + LEAVE('i', 0); return 0; } - strBuf = argenvBuf + (argc+1)*sizeof(void*) + (envc+1)*sizeof(void*); + strBuf = (char*)argenvBuf + (argc+1)*sizeof(void*) + (envc+1)*sizeof(void*); // Populate - argvSaved = (char **) argenvBuf; + argvSaved = argenvBuf; for( i = 0; i < argc; i++ ) { argvSaved[i] = strBuf; strcpy(argvSaved[i], ArgV[i]); + LOG("argv[%i] = '%s'", i, strBuf); strBuf += strlen(ArgV[i])+1; } argvSaved[i] = NULL; @@ -139,6 +144,7 @@ int Proc_Execve(char *File, char **ArgV, char **EnvP) for( i = 0; i < envc; i++ ) { envpSaved[i] = strBuf; + LOG("envp[%i] = '%s'", i, strBuf); strcpy(envpSaved[i], EnvP[i]); strBuf += strlen(EnvP[i])+1; } @@ -154,56 +160,74 @@ int Proc_Execve(char *File, char **ArgV, char **EnvP) MM_ClearUser(); // --- Load new binary - bases[0] = Binary_Load(savedFile, &entry); + base = Binary_Load(savedFile, &entry); free(savedFile); - if(bases[0] == 0) + if(base == 0) { - Warning("Proc_Execve - Unable to load '%s'", Threads_GetName(-1)); - Threads_Exit(0, 0); + free(argvSaved); + Log_Warning("Binary", "Proc_Execve - Unable to load '%s'", Threads_GetName(-1)); + LEAVE('-'); + Threads_Exit(0, -10); for(;;); } - LOG("entry = 0x%x, bases[0] = 0x%x", entry, bases[0]); + LOG("entry = 0x%x, base = 0x%x", entry, base); + +// MM_DumpTables(0, KERNEL_BASE); + LEAVE('-'); // --- And... Jump to it - Proc_StartUser(entry, bases, argc, argvSaved, envpSaved, argenvBytes); + Proc_StartUser(entry, base, argc, argvSaved, argenvBytes); for(;;); // Tell GCC that we never return } /** - * \fn Uint Binary_Load(char *file, Uint *entryPoint) + * \brief Load a binary into the current address space + * \param Path Path to binary to load + * \param EntryPoint Pointer for exectuable entry point + * \return Virtual address where the binary has been loaded */ -Uint Binary_Load(char *file, Uint *entryPoint) +tVAddr Binary_Load(const char *Path, tVAddr *EntryPoint) { - char *sTruePath; + tMount mount_id; + tInode inode; tBinary *pBinary; - Uint base = -1; + tVAddr base = -1; - ENTER("sfile", file); + ENTER("sPath pEntryPoint", Path, EntryPoint); // Sanity Check Argument - if(file == NULL) { + if(Path == NULL) { LEAVE('x', 0); return 0; } - // Get True File Path - sTruePath = VFS_GetTruePath(file); - - if(sTruePath == NULL) { - Warning("[BIN ] '%s' does not exist.", file); - LEAVE('x', 0); - return 0; + // Check if this path has been loaded before. + #if 0 + // TODO: Implement a list of string/tBinary pairs for loaded bins + #endif + + // Get Inode + { + int fd; + tFInfo info; + fd = VFS_Open(Path, VFS_OPENFLAG_READ|VFS_OPENFLAG_EXEC); + if( fd == -1 ) { + LOG("%s does not exist", Path); + LEAVE_RET('x', 0); + } + VFS_FInfo(fd, &info, 0); + VFS_Close(fd); + mount_id = info.mount; + inode = info.inode; + LOG("mount_id = %i, inode = %i", mount_id, inode); } - - LOG("sTruePath = '%s'", sTruePath); + + // TODO: Also get modifcation time? // Check if the binary has already been loaded - if( !(pBinary = Binary_GetInfo(sTruePath)) ) - pBinary = Binary_DoLoad(sTruePath); // Else load it - - // Clean Up - free(sTruePath); + if( !(pBinary = Binary_GetInfo(mount_id, inode)) ) + pBinary = Binary_DoLoad(mount_id, inode, Path); // Else load it // Error Check if(pBinary == NULL) { @@ -211,15 +235,8 @@ Uint Binary_Load(char *file, Uint *entryPoint) return 0; } - #if 0 - if( (base = Binary_IsMapped(pBinary)) ) { - LEAVE('x', base); - return base; - } - #endif - // Map into process space - base = Binary_MapIn(pBinary); // If so then map it in + base = Binary_MapIn(pBinary, Path, BIN_LOWEST, BIN_HIGHEST); // Check for errors if(base == 0) { @@ -229,64 +246,70 @@ Uint Binary_Load(char *file, Uint *entryPoint) // Interpret if(pBinary->Interpreter) { - Uint start; + tVAddr start; if( Binary_Load(pBinary->Interpreter, &start) == 0 ) { LEAVE('x', 0); return 0; } - *entryPoint = start; + *EntryPoint = start; } else - *entryPoint = pBinary->Entry - pBinary->Base + base; + *EntryPoint = pBinary->Entry - pBinary->Base + base; // Return - LOG("*entryPoint = 0x%x", *entryPoint); + LOG("*EntryPoint = 0x%x", *EntryPoint); LEAVE('x', base); return base; // Pass the base as an argument to the user if there is an interpreter } /** * \brief Finds a matching binary entry - * \param TruePath File Identifier (True path name) + * \param MountID Mountpoint ID of binary file + * \param InodeID Inode ID of the file + * \return Pointer to the binary definition (if already loaded) */ -tBinary *Binary_GetInfo(char *TruePath) +tBinary *Binary_GetInfo(tMount MountID, tInode InodeID) { tBinary *pBinary; - pBinary = glLoadedBinaries; - while(pBinary) + for(pBinary = glLoadedBinaries; pBinary; pBinary = pBinary->Next) { - if(strcmp(pBinary->TruePath, TruePath) == 0) + if(pBinary->MountID == MountID && pBinary->Inode == InodeID) return pBinary; - pBinary = pBinary->Next; } return NULL; } /** - \fn Uint Binary_MapIn(tBinary *binary) - \brief Maps an already-loaded binary into an address space. - \param binary Pointer to globally stored data. -*/ -Uint Binary_MapIn(tBinary *binary) + * \brief Maps an already-loaded binary into an address space. + * \param Binary Pointer to globally stored binary definition + * \param Path Path to the binary's file (for debug) + * \param LoadMin Lowest location to map to + * \param LoadMax Highest location to map to + * \return Base load address + */ +tVAddr Binary_MapIn(tBinary *Binary, const char *Path, tVAddr LoadMin, tVAddr LoadMax) { - Uint base; - Uint addr; - int i; - + tVAddr base; + int i, fd; + + ENTER("pBinary sPath pLoadMin pLoadMax", Binary, Path, LoadMin, LoadMax); + // Reference Executable (Makes sure that it isn't unloaded) - binary->ReferenceCount ++; + Binary->ReferenceCount ++; // Get Binary Base - base = binary->Base; + base = Binary->Base; // Check if base is free if(base != 0) { - for(i=0;iNumPages;i++) + LOG("Checking base %p", base); + for( i = 0; i < Binary->NumSections; i ++ ) { - if( MM_GetPhysAddr( binary->Pages[i].Virtual & ~0xFFF ) ) { + if( Binary_int_CheckMemFree( Binary->LoadSections[i].Virtual, Binary->LoadSections[i].MemSize ) ) + { base = 0; - LOG("Address 0x%x is taken\n", binary->Pages[i].Virtual & ~0xFFF); + LOG("Address 0x%x is taken\n", Binary->LoadSections[i].Virtual); break; } } @@ -296,56 +319,68 @@ Uint Binary_MapIn(tBinary *binary) if(base == 0) { // If so, give it a base - base = BIN_HIGHEST; - while(base >= BIN_LOWEST) + base = LoadMax; + while(base >= LoadMin) { - for(i=0;iNumPages;i++) + for( i = 0; i < Binary->NumSections; i ++ ) { - addr = binary->Pages[i].Virtual & ~0xFFF; - addr -= binary->Base; - addr += base; - if( MM_GetPhysAddr( addr ) ) break; + tVAddr addr = Binary->LoadSections[i].Virtual - Binary->Base + base; + if( Binary_int_CheckMemFree( addr, Binary->LoadSections[i].MemSize ) ) + break; } // If space was found, break - if(i == binary->NumPages) break; + if(i == Binary->NumSections) break; // Else decrement pointer and try again base -= BIN_GRANUALITY; } + LOG("Allocated base %p", base); } // Error Check - if(base < BIN_LOWEST) { - Warning("[BIN ] Executable '%s' cannot be loaded, no space", binary->TruePath); + if(base < LoadMin) { + Log_Warning("Binary", "Executable '%s' cannot be loaded, no space", Path); + LEAVE('i', 0); return 0; } // Map Executable In - for(i=0;iNumPages;i++) + fd = VFS_OpenInode(Binary->MountID, Binary->Inode, VFS_OPENFLAG_READ); + for( i = 0; i < Binary->NumSections; i ++ ) { - addr = binary->Pages[i].Virtual & ~0xFFF; - addr -= binary->Base; - addr += base; - LOG("%i - 0x%x to 0x%x", i, addr, binary->Pages[i].Physical); - MM_Map( addr, (Uint) (binary->Pages[i].Physical) ); - - // Read-Only? - if( binary->Pages[i].Flags & BIN_PAGEFLAG_RO) - MM_SetFlags( addr, MM_PFLAG_RO, -1 ); - else - MM_SetFlags( addr, MM_PFLAG_COW, -1 ); - - // Execute? - if( binary->Pages[i].Flags & BIN_PAGEFLAG_EXEC ) - MM_SetFlags( addr, MM_PFLAG_EXEC, -1 ); - else - MM_SetFlags( addr, MM_PFLAG_EXEC, 0 ); + tBinarySection *sect = &Binary->LoadSections[i]; + Uint protflags, mapflags; + tVAddr addr = sect->Virtual - Binary->Base + base; + LOG("%i - %p to offset 0x%llx (%x)", i, addr, sect->Offset, sect->Flags); + + protflags = MMAP_PROT_READ; + mapflags = MMAP_MAP_FIXED; + + if( sect->Flags & BIN_SECTFLAG_EXEC ) + protflags |= MMAP_PROT_EXEC; + // Read only pages are COW + if( sect->Flags & BIN_SECTFLAG_RO ) { + VFS_MMap( (void*)addr, sect->FileSize, protflags, MMAP_MAP_SHARED|mapflags, fd, sect->Offset ); + } + else { + protflags |= MMAP_PROT_WRITE; + VFS_MMap( (void*)addr, sect->FileSize, protflags, MMAP_MAP_PRIVATE|mapflags, fd, sect->Offset ); + } + // Apply anonymous memory for BSS + if( sect->FileSize < sect->MemSize ) { + mapflags |= MMAP_MAP_ANONYMOUS; + VFS_MMap( + (void*)(addr + sect->FileSize), sect->MemSize - sect->FileSize, + protflags, MMAP_MAP_PRIVATE|mapflags, + 0, 0 + ); + } } - //Log("Mapped '%s' to 0x%x", binary->TruePath, base); - - //LOG("*0x%x = 0x%x\n", binary->Pages[0].Virtual, *(Uint*)binary->Pages[0].Virtual); + Log_Debug("Binary", "PID %i - Mapped '%s' to 0x%x", Threads_GetPID(), Path, base); + VFS_Close(fd); + LEAVE('p', base); return base; } @@ -382,37 +417,50 @@ Uint Binary_IsMapped(tBinary *binary) * \brief Loads a binary file into memory * \param truePath Absolute filename of binary */ -tBinary *Binary_DoLoad(char *truePath) +tBinary *Binary_DoLoad(tMount MountID, tInode Inode, const char *Path) { tBinary *pBinary; - int fp, i; - Uint ident; + int fp; + Uint32 ident; tBinaryType *bt = gRegBinTypes; - ENTER("struePath", truePath); + ENTER("iMountID XInode sPath", MountID, Inode, Path); // Open File - fp = VFS_Open(truePath, VFS_OPENFLAG_READ); + fp = VFS_OpenInode(MountID, Inode, VFS_OPENFLAG_READ); if(fp == -1) { LOG("Unable to load file, access denied"); LEAVE('n'); return NULL; } + + LOG("fp = 0x%x", fp); // Read File Type VFS_Read(fp, 4, &ident); VFS_Seek(fp, 0, SEEK_SET); - + + LOG("ident = 0x%x", ident); + + // Determine the type for(; bt; bt = bt->Next) { - if( (ident & bt->Mask) != (Uint)bt->Ident ) + if( (ident & bt->Mask) != (Uint32)bt->Ident ) continue; + LOG("bt = %p (%s)", bt, bt->Name); pBinary = bt->Load(fp); break; } + + LOG("pBinary = %p", pBinary); + + // Close File + VFS_Close(fp); + + // Catch errors if(!bt) { - Warning("[BIN ] '%s' is an unknown file type. (0x%x 0x%x 0x%x 0x%x)", - truePath, ident&0xFF, (ident>>8)&0xFF, (ident>>16)&0xFF, (ident>>24)&0xFF); + Log_Warning("Binary", "'%s' is an unknown file type. (%02x %02x %02x %02x)", + Path, ident&0xFF, (ident>>8)&0xFF, (ident>>16)&0xFF, (ident>>24)&0xFF); LEAVE('n'); return NULL; } @@ -425,66 +473,22 @@ tBinary *Binary_DoLoad(char *truePath) // Initialise Structure pBinary->ReferenceCount = 0; - pBinary->TruePath = malloc( strlen(truePath) + 1 ); - strcpy(pBinary->TruePath, truePath); + pBinary->MountID = MountID; + pBinary->Inode = Inode; // Debug Information LOG("Interpreter: '%s'", pBinary->Interpreter); LOG("Base: 0x%x, Entry: 0x%x", pBinary->Base, pBinary->Entry); - LOG("NumPages: %i", pBinary->NumPages); - - // Read Data - for(i=0;iNumPages;i++) - { - Uint dest; - tPAddr paddr; - paddr = (Uint)MM_AllocPhys(); - if(paddr == 0) { - Warning("Binary_DoLoad - Physical memory allocation failed"); - for( ; i--; ) { - MM_DerefPhys( pBinary->Pages[i].Physical ); - } - return NULL; - } - MM_RefPhys( paddr ); // Make sure it is _NOT_ freed until we want it to be - dest = MM_MapTemp( paddr ); - dest += pBinary->Pages[i].Virtual & 0xFFF; - LOG("dest = 0x%x, paddr = 0x%x", dest, paddr); - LOG("Pages[%i]={Physical:0x%llx,Virtual:%p,Size:0x%x}", - i, pBinary->Pages[i].Physical, pBinary->Pages[i].Virtual, pBinary->Pages[i].Size); - - // Pure Empty Page - if(pBinary->Pages[i].Physical == -1) { - LOG("%i - ZERO", i); - memset( (void*)dest, 0, 1024 - (pBinary->Pages[i].Virtual & 0xFFF) ); - } - else - { - VFS_Seek( fp, pBinary->Pages[i].Physical, 1 ); - if(pBinary->Pages[i].Size != 0x1000) { - LOG("%i - 0x%llx - 0x%x bytes", - i, pBinary->Pages[i].Physical, pBinary->Pages[i].Size); - memset( (void*)dest, 0, 0x1000 -(dest&0xFFF) ); - VFS_Read( fp, pBinary->Pages[i].Size, (void*)dest ); - } else { - LOG("%i - 0x%x", i, pBinary->Pages[i].Physical); - VFS_Read( fp, 0x1000, (void*)dest ); - } - } - pBinary->Pages[i].Physical = paddr; - MM_FreeTemp( dest ); - } - LOG("Page Count: %i", pBinary->NumPages); - - // Close File - VFS_Close(fp); + LOG("NumSections: %i", pBinary->NumSections); // Add to the list - LOCK(&glBinListLock); + SHORTLOCK(&glBinListLock); pBinary->Next = glLoadedBinaries; glLoadedBinaries = pBinary; - RELEASE(&glBinListLock); - + SHORTREL(&glBinListLock); + + // TODO: Register the path with the binary + // Return LEAVE('p', pBinary); return pBinary; @@ -505,7 +509,7 @@ void Binary_Unload(void *Base) if((Uint)Base < 0xC0000000) { // TODO: User Binaries - Warning("[BIN ] Unloading user binaries is currently unimplemented"); + Log_Warning("BIN", "Unloading user binaries is currently unimplemented"); return; } @@ -517,8 +521,9 @@ void Binary_Unload(void *Base) // Check the base if(pKBin->Base != Base) continue; // Deallocate Memory - for(i = 0; i < pKBin->Info->NumPages; i++) { - MM_Deallocate( (Uint)Base + (i << 12) ); + for(i = 0; i < pKBin->Info->NumSections; i++) + { + // TODO: VFS_MUnmap(); } // Dereference Binary Binary_Dereference( pKBin->Info ); @@ -586,21 +591,20 @@ char *Binary_RegInterp(char *Path) // Kernel Binary Handling // ============ /** - * \fn void *Binary_LoadKernel(char *File) + * \fn void *Binary_LoadKernel(const char *File) * \brief Load a binary into kernel space * \note This function shares much with #Binary_Load, but does it's own mapping * \param File File to load into the kernel */ -void *Binary_LoadKernel(char *File) +void *Binary_LoadKernel(const char *File) { - char *sTruePath; tBinary *pBinary; tKernelBin *pKBinary; - Uint base = -1; - Uint addr; - int i; + tVAddr base = -1; + tMount mount_id; + tInode inode; - ENTER("sfile", File); + ENTER("sFile", File); // Sanity Check Argument if(File == NULL) { @@ -608,15 +612,21 @@ void *Binary_LoadKernel(char *File) return 0; } - // Get True File Path - sTruePath = VFS_GetTruePath(File); - if(sTruePath == NULL) { - LEAVE('n'); - return 0; + { + int fd = VFS_Open(File, VFS_OPENFLAG_READ); + tFInfo info; + if(fd == -1) { + LEAVE('n'); + return NULL; + } + VFS_FInfo(fd, &info, 0); + mount_id = info.mount; + inode = info.inode; + VFS_Close(fd); } // Check if the binary has already been loaded - if( (pBinary = Binary_GetInfo(sTruePath)) ) + if( (pBinary = Binary_GetInfo(mount_id, inode)) ) { for(pKBinary = glLoadedKernelLibs; pKBinary; @@ -629,7 +639,7 @@ void *Binary_LoadKernel(char *File) } } else - pBinary = Binary_DoLoad(sTruePath); // Else load it + pBinary = Binary_DoLoad(mount_id, inode, File); // Else load it // Error Check if(pBinary == NULL) { @@ -644,76 +654,13 @@ void *Binary_LoadKernel(char *File) // Reference Executable (Makes sure that it isn't unloaded) pBinary->ReferenceCount ++; - - // Check compiled base - base = pBinary->Base; - // - Sanity Check - if(base < KLIB_LOWEST || base > KLIB_HIGHEST || base + (pBinary->NumPages<<12) > KLIB_HIGHEST) { - base = 0; - } - // - Check if it is a valid base address - if(base != 0) - { - for(i=0;iNumPages;i++) - { - if( MM_GetPhysAddr( pBinary->Pages[i].Virtual & ~0xFFF ) ) { - base = 0; - LOG("Address 0x%x is taken\n", pBinary->Pages[i].Virtual & ~0xFFF); - break; - } - } - } - - // Check if the executable has no base or it is not free - if(base == 0) - { - // If so, give it a base - base = KLIB_LOWEST; - while(base < KLIB_HIGHEST) - { - for(i = 0; i < pBinary->NumPages; i++) - { - addr = pBinary->Pages[i].Virtual & ~0xFFF; - addr -= pBinary->Base; - addr += base; - if( MM_GetPhysAddr( addr ) ) break; - } - // If space was found, break - if(i == pBinary->NumPages) break; - // Else decrement pointer and try again - base += KLIB_GRANUALITY; - } - } - - // - Error Check - if(base >= KLIB_HIGHEST) { - Warning("[BIN ] Executable '%s' cannot be loaded into kernel, no space", pBinary->TruePath); - Binary_Dereference( pBinary ); - LEAVE('n'); - return 0; - } - - LOG("base = 0x%x", base); - - // - Map binary in - LOG("pBinary = {NumPages:%i, Pages=%p}", pBinary->NumPages, pBinary->Pages); - for(i = 0; i < pBinary->NumPages; i++) - { - addr = pBinary->Pages[i].Virtual & ~0xFFF; - addr -= pBinary->Base; - addr += base; - LOG("%i - 0x%x to 0x%x", i, addr, pBinary->Pages[i].Physical); - MM_Map( addr, (Uint) (pBinary->Pages[i].Physical) ); - MM_SetFlags( addr, MM_PFLAG_KERNEL, MM_PFLAG_KERNEL ); - - if( pBinary->Pages[i].Flags & BIN_PAGEFLAG_RO) // Read-Only? - MM_SetFlags( addr, MM_PFLAG_RO, MM_PFLAG_KERNEL ); - } + + Binary_MapIn(pBinary, File, KLIB_LOWEST, KLIB_HIGHEST); // Relocate Library if( !Binary_Relocate( (void*)base ) ) { - Warning("[BIN ] Relocation of '%s' failed, unloading", sTruePath); + Log_Warning("Binary", "Relocation of '%s' failed, unloading", File); Binary_Unload( (void*)base ); Binary_Dereference( pBinary ); LEAVE('n'); @@ -724,10 +671,10 @@ void *Binary_LoadKernel(char *File) pKBinary = malloc(sizeof(*pKBinary)); pKBinary->Base = (void*)base; pKBinary->Info = pBinary; - LOCK( &glKBinListLock ); + SHORTLOCK( &glKBinListLock ); pKBinary->Next = glLoadedKernelLibs; glLoadedKernelLibs = pKBinary; - RELEASE( &glKBinListLock ); + SHORTREL( &glKBinListLock ); LEAVE('p', base); return (void*)base; @@ -750,7 +697,7 @@ Uint Binary_Relocate(void *Base) return bt->Relocate( (void*)Base); } - Warning("[BIN ] 0x%x is an unknown file type. (0x%x 0x%x 0x%x 0x%x)", + Log_Warning("BIN", "%p is an unknown file type. (%02x %02x %02x %02x)", Base, ident&0xFF, (ident>>8)&0xFF, (ident>>16)&0xFF, (ident>>24)&0xFF); return 0; } @@ -763,7 +710,7 @@ Uint Binary_Relocate(void *Base) * Gets the value of a symbol from either the currently loaded * libraries or the kernel's exports. */ -int Binary_GetSymbol(char *Name, Uint *Val) +int Binary_GetSymbol(const char *Name, Uint *Val) { if( Binary_GetSymbolEx(Name, Val) ) return 1; return 0; @@ -776,7 +723,7 @@ int Binary_GetSymbol(char *Name, Uint *Val) * Gets the value of a symbol from either the currently loaded * libraries or the kernel's exports. */ -Uint Binary_GetSymbolEx(char *Name, Uint *Value) +Uint Binary_GetSymbolEx(const char *Name, Uint *Value) { int i; tKernelBin *pKBin; @@ -801,7 +748,7 @@ Uint Binary_GetSymbolEx(char *Name, Uint *Value) } } - Warning("[BIN ] Unable to find symbol '%s'", Name); + Log_Warning("BIN", "Unable to find symbol '%s'", Name); return 0; } @@ -812,7 +759,7 @@ Uint Binary_GetSymbolEx(char *Name, Uint *Value) * \param Name Name of symbol to find * \param Val Pointer to place final value */ -Uint Binary_FindSymbol(void *Base, char *Name, Uint *Val) +Uint Binary_FindSymbol(void *Base, const char *Name, Uint *Val) { Uint32 ident = *(Uint32*) Base; tBinaryType *bt = gRegBinTypes; @@ -823,11 +770,30 @@ Uint Binary_FindSymbol(void *Base, char *Name, Uint *Val) return bt->GetSymbol(Base, Name, Val); } - Warning("[BIN ] 0x%x is an unknown file type. (0x%x 0x%x 0x%x 0x%x)", + Log_Warning("BIN", "Binary_FindSymbol - %p is an unknown file type. (%02x %02x %02x %02x)", Base, ident&0xFF, ident>>8, ident>>16, ident>>24); return 0; } +/** + * \brief Check if a range of memory is fully free + * \return Inverse boolean free (0 if all pages are unmapped) + */ +int Binary_int_CheckMemFree( tVAddr _start, size_t _len ) +{ + _len += _start & (PAGE_SIZE-1); + _len = (_len + PAGE_SIZE - 1) & ~(PAGE_SIZE-1); + _start &= ~(PAGE_SIZE-1); + for( ; _len > PAGE_SIZE; _len -= PAGE_SIZE, _start += PAGE_SIZE ) { + if( MM_GetPhysAddr(_start) != 0 ) + return 1; + } + if( _len == PAGE_SIZE && MM_GetPhysAddr(_start) != 0 ) + return 1; + return 0; +} + + // === EXPORTS === EXPORT(Binary_FindSymbol); EXPORT(Binary_Unload);