#include <acess.h>
#include <binary.h>
#include <mm_virt.h>
+#include <hal_proc.h>
+#include <vfs_threads.h>
// === 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
} 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 Binary_int_CacheArgs(const char **Path, const char ***ArgV, const char ***EnvP, void *DestBuffer);
+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;
}
/**
- * \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|CLONE_NOUSER) == 0)
{
// CHILD
- char *args[2] = {stackPath, NULL};
- LOG("stackPath = '%s'\n", stackPath);
- Proc_Execve(stackPath, args, &args[1]);
+ const char *args[2] = {stackPath, NULL};
+ LOG("stackPath = '%s'", stackPath);
+ Proc_Execve(stackPath, args, &args[1], 0);
for(;;);
}
+ LEAVE('i', 0);
return 0;
}
/**
- * \fn int Proc_Execve(char *File, char **ArgV, char **EnvP)
+ * \todo Document
+ */
+int Binary_int_CacheArgs(const char **Path, const char ***ArgV, const char ***EnvP, void *DestBuffer)
+{
+ int size, argc=0, envc=0;
+ int i;
+ char *strbuf;
+ const char **arrays;
+
+ // Calculate size
+ size = 0;
+ if( ArgV && *ArgV )
+ {
+ const char **argv = *ArgV;
+ for( argc = 0; argv[argc]; argc ++ )
+ size += strlen( argv[argc] ) + 1;
+ }
+ if( EnvP && *EnvP )
+ {
+ const char **envp = *EnvP;
+ for( envc = 0; envp[envc]; envc ++ )
+ size += strlen( envp[envc] ) + 1;
+ }
+ size = (size + sizeof(void*)-1) & ~(sizeof(void*)-1); // Word align
+ size += (argc+1+envc+1)*sizeof(void*); // Arrays
+ if( Path )
+ {
+ size += strlen( *Path ) + 1;
+ }
+
+ if( DestBuffer )
+ {
+ arrays = DestBuffer;
+ strbuf = (void*)&arrays[argc+1+envc+1];
+
+ // Fill ArgV
+ if( ArgV && *ArgV )
+ {
+ const char **argv = *ArgV;
+ for( i = 0; argv[i]; i ++ )
+ {
+ arrays[i] = strbuf;
+ strcpy(strbuf, argv[i]);
+ strbuf += strlen( argv[i] ) + 1;
+ }
+ *ArgV = arrays;
+ arrays += i;
+ }
+ *arrays++ = NULL;
+ // Fill EnvP
+ if( EnvP && *EnvP )
+ {
+ const char **envp = *EnvP;
+ for( i = 0; envp[i]; i ++ )
+ {
+ arrays[i] = strbuf;
+ strcpy(strbuf, envp[i]);
+ strbuf += strlen( envp[i] ) + 1;
+ }
+ *EnvP = arrays;
+ arrays += i;
+ }
+ *arrays++ = NULL;
+ // Fill path
+ if( Path )
+ {
+ strcpy(strbuf, *Path);
+ *Path = strbuf;
+ }
+ }
+
+ return size;
+}
+
+/**
+ * \brief Create a new process with the specified set of file descriptors
+ */
+int Proc_SysSpawn(const char *Binary, const char **ArgV, const char **EnvP, int nFD, int *FDs)
+{
+ void *handles;
+ void *cachebuf;
+ int size;
+ tPID ret;
+
+ // --- Save File, ArgV and EnvP
+ size = Binary_int_CacheArgs( &Binary, &ArgV, &EnvP, NULL );
+ cachebuf = malloc( size );
+ Binary_int_CacheArgs( &Binary, &ArgV, &EnvP, cachebuf );
+
+ // Cache the VFS handles
+ handles = VFS_SaveHandles(nFD, FDs);
+
+ // Create new process
+ ret = Proc_Clone(CLONE_VM|CLONE_NOUSER);
+ if( ret == 0 )
+ {
+ VFS_RestoreHandles(nFD, handles);
+ VFS_FreeSavedHandles(nFD, handles);
+ // Frees cachebuf
+ Proc_Execve(Binary, ArgV, EnvP, size);
+ for(;;);
+ }
+ if( ret < 0 )
+ {
+ VFS_FreeSavedHandles(nFD, handles);
+ }
+
+ return ret;
+}
+
+/**
* \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 DataSize)
{
- int argc, envc, i;
- int argenvBytes;
- char *argenvBuf, *strBuf;
- char **argvSaved, **envpSaved;
- char *savedFile;
- Uint entry;
- Uint bases[2] = {0};
+ void *cachebuf;
+ tVAddr entry;
+ Uint base; // Uint because Proc_StartUser wants it
+ int argc;
ENTER("sFile pArgV pEnvP", File, ArgV, EnvP);
- // --- Save File, ArgV and EnvP (also get argc)
-
- // Count Arguments, Environment Variables and total string sizes
- argenvBytes = 0;
- for( argc = 0; ArgV && ArgV[argc]; argc++ )
- argenvBytes += strlen(ArgV[argc])+1;
- for( envc = 0; EnvP && EnvP[envc]; envc++ )
- argenvBytes += strlen(EnvP[envc])+1;
- argenvBytes = (argenvBytes + sizeof(void*)-1) & ~(sizeof(void*)-1);
- argenvBytes += (argc+1)*sizeof(void*) + (envc+1)*sizeof(void*);
-
- // Allocate
- argenvBuf = malloc(argenvBytes);
- if(argenvBuf == NULL) {
- Log_Error("BIN", "Proc_Execve - What the hell? The kernel is out of heap space");
- return 0;
- }
- strBuf = argenvBuf + (argc+1)*sizeof(void*) + (envc+1)*sizeof(void*);
-
- // Populate
- argvSaved = (char **) argenvBuf;
- for( i = 0; i < argc; i++ )
- {
- argvSaved[i] = strBuf;
- strcpy(argvSaved[i], ArgV[i]);
- strBuf += strlen(ArgV[i])+1;
- }
- argvSaved[i] = NULL;
- envpSaved = &argvSaved[i+1];
- for( i = 0; i < envc; i++ )
+ // --- Save File, ArgV and EnvP
+ if( DataSize == 0 )
{
- envpSaved[i] = strBuf;
- strcpy(envpSaved[i], EnvP[i]);
- strBuf += strlen(EnvP[i])+1;
+ DataSize = Binary_int_CacheArgs( &File, &ArgV, &EnvP, NULL );
+ cachebuf = malloc( DataSize );
+ Binary_int_CacheArgs( &File, &ArgV, &EnvP, cachebuf );
}
- envpSaved[i] = NULL;
-
- savedFile = malloc(strlen(File)+1);
- strcpy(savedFile, File);
+
+ // --- Get argc
+ for( argc = 0; ArgV && ArgV[argc]; argc ++ );
// --- Set Process Name
Threads_SetName(File);
// --- Clear User Address space
- MM_ClearUser();
+ // NOTE: This is a little roundabout, maybe telling ClearUser to not touch the
+ // PPD area would be a better idea.
+ {
+ int nfd = *Threads_GetMaxFD();
+ void *handles;
+ handles = VFS_SaveHandles(nfd, NULL);
+ VFS_CloseAllUserHandles();
+ MM_ClearUser();
+ VFS_RestoreHandles(nfd, handles);
+ VFS_FreeSavedHandles(nfd, handles);
+ }
// --- Load new binary
- bases[0] = Binary_Load(savedFile, &entry);
- free(savedFile);
- if(bases[0] == 0)
+ base = Binary_Load(File, &entry);
+ if(base == 0)
{
- Log_Warning("BIN", "Proc_Execve - Unable to load '%s'", Threads_GetName(-1));
- Threads_Exit(0, 0);
+ Log_Warning("Binary", "Proc_Execve - Unable to load '%s'", File);
+ 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);
LEAVE('-');
// --- And... Jump to it
- Proc_StartUser(entry, bases, argc, argvSaved, envpSaved, argenvBytes);
+ Proc_StartUser(entry, base, argc, ArgV, DataSize);
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) {
- Log_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) {
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) {
// 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;i<binary->NumPages;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;
}
}
if(base == 0)
{
// If so, give it a base
- base = BIN_HIGHEST;
- while(base >= BIN_LOWEST)
+ base = LoadMax;
+ while(base >= LoadMin)
{
- for(i=0;i<binary->NumPages;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) {
- Log_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;i<binary->NumPages;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_Debug("Binary", "PID %i - Mapped '%s' to 0x%x", Threads_GetPID(), 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 %p", Threads_GetPID(), Path, base);
+ VFS_Close(fd);
+ LEAVE('p', base);
return base;
}
* \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;
}
+
+ // Close File
+ VFS_Close(fp);
+
+ // Catch errors
if(!bt) {
- Log_Warning("BIN", "'%s' is an unknown file type. (%02x %02x %02x %02x)",
- 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;
}
+ LOG("pBinary = %p", pBinary);
+
// Error Check
if(pBinary == NULL) {
LEAVE('n');
// 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;i<pBinary->NumPages;i++)
- {
- Uint dest;
- tPAddr paddr;
- paddr = (Uint)MM_AllocPhys();
- if(paddr == 0) {
- Log_Warning("BIN", "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;
// 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 );
// 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) {
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;
}
}
else
- pBinary = Binary_DoLoad(sTruePath); // Else load it
+ pBinary = Binary_DoLoad(mount_id, inode, File); // Else load it
// Error Check
if(pBinary == NULL) {
// 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;i<pBinary->NumPages;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) {
- Log_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');
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;
* 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;
* 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;
* \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;
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);