Implementing telnet server, fixes everywhere
[tpg/acess2.git] / Kernel / binary.c
index 1276f72..5213bf2 100644 (file)
@@ -7,6 +7,7 @@
 #include <binary.h>
 #include <mm_virt.h>
 #include <hal_proc.h>
+#include <vfs_threads.h>
 
 // === CONSTANTS ===
 #define BIN_LOWEST     MM_USER_MIN             // 1MiB
@@ -30,12 +31,12 @@ extern tKernelSymbol        gKernelSymbolsEnd[];
 extern tBinaryType     gELF_Info;
 
 // === PROTOTYPES ===
- int   Proc_Execve(const char *File, const char **ArgV, const char **EnvP);
-Uint   Binary_Load(const char *file, Uint *entryPoint);
-tBinary *Binary_GetInfo(const char *truePath);
-Uint   Binary_MapIn(tBinary *binary);
-Uint   Binary_IsMapped(tBinary *binary);
-tBinary *Binary_DoLoad(const 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);
@@ -44,6 +45,7 @@ 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 ===
 tShortSpinlock glBinListLock;
@@ -75,14 +77,14 @@ int Proc_Spawn(const char *Path)
        
        strcpy(stackPath, Path);
        
-       LOG("stackPath = '%s'\n", stackPath);
+       LOG("stackPath = '%s'", stackPath);
        
-       if(Proc_Clone(CLONE_VM) == 0)
+       if(Proc_Clone(CLONE_VM|CLONE_NOUSER) == 0)
        {
                // CHILD
                const char      *args[2] = {stackPath, NULL};
-               LOG("stackPath = '%s'\n", stackPath);
-               Proc_Execve(stackPath, args, &args[1]);
+               LOG("stackPath = '%s'", stackPath);
+               Proc_Execve(stackPath, args, &args[1], 0);
                for(;;);
        }
        LEAVE('i', 0);
@@ -90,130 +92,223 @@ int Proc_Spawn(const char *Path)
 }
 
 /**
- * \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(const char *File, const char **ArgV, const 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("Binary", "Proc_Execve - What the hell? The kernel is out of heap space");
-               LEAVE('i', 0);
-               return 0;
-       }
-       strBuf = (char*)argenvBuf + (argc+1)*sizeof(void*) + (envc+1)*sizeof(void*);
-       
-       // Populate
-       argvSaved = 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("Binary", "Proc_Execve - Unable to load '%s'", Threads_GetName(-1));
+               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 file Path to binary to load
- * \param entryPoint   Pointer for exectuable entry point
+ * \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(const 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 pentryPoint", file, entryPoint);
+       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);
-       LOG("sTruePath = %p", sTruePath);
-       
-       if(sTruePath == NULL) {
-               Log_Warning("Binary", "%p '%s' does not exist.", file, 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
+
+       // 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) {
@@ -221,15 +316,8 @@ Uint Binary_Load(const 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) {
@@ -239,64 +327,70 @@ Uint Binary_Load(const 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(const 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;
                        }
                }
@@ -306,56 +400,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;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;
 }
 
@@ -392,41 +498,54 @@ Uint Binary_IsMapped(tBinary *binary)
  * \brief Loads a binary file into memory
  * \param truePath     Absolute filename of binary
  */
-tBinary *Binary_DoLoad(const 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');
@@ -435,87 +554,22 @@ tBinary *Binary_DoLoad(const char *truePath)
        
        // Initialise Structure
        pBinary->ReferenceCount = 0;
-       pBinary->TruePath = strdup(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 the address is not aligned, or the page is not full
-                       // sized, copy part of it
-                       if( (dest & 0xFFF) > 0 || pBinary->Pages[i].Size < 0x1000)
-                       {
-                               // Validate the size to prevent Kernel page faults
-                               // Clips to one page and prints a warning
-                               if( pBinary->Pages[i].Size + (dest & 0xFFF) > 0x1000) {
-                                       Log_Warning("Binary", "Loader error: Page %i (%p) of '%s' is %i bytes (> 4096)",
-                                               i, pBinary->Pages[i].Virtual, truePath,
-                                               (dest&0xFFF) + pBinary->Pages[i].Size);
-                                       pBinary->Pages[i].Size = 0x1000 - (dest & 0xFFF);
-                               }               
-                               LOG("%i - 0x%llx - 0x%x bytes",
-                                       i, pBinary->Pages[i].Physical, pBinary->Pages[i].Size);
-                               // Zero from `dest` to the end of the page
-                               memset( (void*)dest, 0, 0x1000 - (dest&0xFFF) );
-                               // Read in the data
-                               VFS_Read( fp, pBinary->Pages[i].Size, (void*)dest );
-                       }
-                       // Full page
-                       else
-                       {
-                               // Check if the page is oversized
-                               if(pBinary->Pages[i].Size > 0x1000)
-                                       Log_Warning("Binary", "Loader error - Page %i (%p) of '%s' is %i bytes (> 4096)",
-                                               i, pBinary->Pages[i].Virtual, truePath,
-                                               pBinary->Pages[i].Size);
-                               // Read data
-                               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
        SHORTLOCK(&glBinListLock);
        pBinary->Next = glLoadedBinaries;
        glLoadedBinaries = pBinary;
        SHORTREL(&glBinListLock);
-       
+
+       // TODO: Register the path with the binary      
+
        // Return
        LEAVE('p', pBinary);
        return pBinary;
@@ -548,8 +602,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 );
@@ -624,12 +679,11 @@ char *Binary_RegInterp(char *Path)
  */
 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);
        
@@ -639,15 +693,21 @@ void *Binary_LoadKernel(const 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;
@@ -660,7 +720,7 @@ void *Binary_LoadKernel(const 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) {
@@ -675,76 +735,13 @@ void *Binary_LoadKernel(const 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;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 ) )
        {
-               Log_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');
@@ -859,6 +856,25 @@ Uint Binary_FindSymbol(void *Base, const char *Name, Uint *Val)
        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);

UCC git Repository :: git.ucc.asn.au