/** * \brief Take a backup of a set of file descriptors */ void *VFS_SaveHandles(int NumFDs, int *FDs) { tVFS_Handle *ret; const int max_handles = *Threads_GetMaxFD(NULL); // Check if this process has any handles if( MM_GetPhysAddr( gaUserHandles ) == 0 ) return NULL; // Allocate ret = malloc( NumFDs * sizeof(tVFS_Handle) ); if( !ret ) return NULL; if( NumFDs > max_handles ) NumFDs = max_handles; // Take copies of the handles if( FDs == NULL ) { memcpy(ret, gaUserHandles, NumFDs * sizeof(tVFS_Handle)); } else { for( int i = 0; i < NumFDs; i ++ ) { if( FDs[i] < -1 ) { Log_Warning("VFS", "VFS_SaveHandles - Slot %i error FD (%i<0), ignorning", i, FDs[i]); memset(&ret[i], 0, sizeof(tVFS_Handle)); continue ; } int fd = FDs[i] & (VFS_KERNEL_FLAG - 1); tVFS_Handle *h = VFS_GetHandle(fd); if(!h) { Log_Warning("VFS", "VFS_SaveHandles - Invalid FD 0x%x (%i) in slot %i", fd, FDs[i], i ); free(ret); return NULL; } // Log("%i: Duplicate FD %i (%p)", i, fd, h->Node); memcpy( &ret[i], h, sizeof(tVFS_Handle) ); } } // Reference nodes/mounts for( int i = 0; i < NumFDs; i ++ ) { tVFS_Handle *h = &ret[i]; // Reference node if( !h->Node ) continue ; // Debug("VFS_SaveHandles: %i %p", i, h->Node); _ReferenceNode(h->Node); h->Mount->OpenHandleCount ++; } return ret; }
/** * \brief Take a backup of a set of file descriptors */ void *VFS_SaveHandles(int NumFDs, int *FDs) { tVFS_Handle *ret; int i; int max_handles = *Threads_GetMaxFD(); // Check if this process has any handles if( MM_GetPhysAddr( gaUserHandles ) == 0 ) return NULL; // Allocate ret = malloc( NumFDs * sizeof(tVFS_Handle) ); if( !ret ) return NULL; if( NumFDs > max_handles ) NumFDs = max_handles; // Take copies of the handles for( i = 0; i < NumFDs; i ++ ) { tVFS_Handle *h; if( FDs == NULL ) h = &gaUserHandles[i]; else if( FDs[i] == -1 ) { Log_Warning("VFS", "VFS_SaveHandles - Slot %i error FD (-1), ignorning", i); memset(&ret[i], 0, sizeof(tVFS_Handle)); continue ; } else { h = VFS_GetHandle(FDs[i] & (VFS_KERNEL_FLAG - 1)); if(!h) { Log_Warning("VFS", "VFS_SaveHandles - Invalid FD %i", FDs[i] & (VFS_KERNEL_FLAG - 1) ); free(ret); return NULL; } } memcpy( &ret[i], h, sizeof(tVFS_Handle) ); // Reference node if( !h->Node ) continue ; _ReferenceNode(h->Node); h->Mount->OpenHandleCount ++; } return ret; }
void VFS_ReferenceUserHandles(void) { const int max_handles = *Threads_GetMaxFD(NULL); // Check if this process has any handles if( MM_GetPhysAddr( gaUserHandles ) == 0 ) return ; for( int i = 0; i < max_handles; i ++ ) { tVFS_Handle *h; h = &gaUserHandles[i]; if( !h->Node ) continue ; _ReferenceNode(h->Node); h->Mount->OpenHandleCount ++; } }
void VFS_CloseAllUserHandles(void) { int i; int max_handles = *Threads_GetMaxFD(); // Check if this process has any handles if( MM_GetPhysAddr( gaUserHandles ) == 0 ) return ; for( i = 0; i < max_handles; i ++ ) { tVFS_Handle *h; h = &gaUserHandles[i]; if( !h->Node ) continue ; _CloseNode(h->Node); } }
void VFS_RestoreHandles(int NumFDs, void *Handles) { tVFS_Handle *handles = Handles; int i; // NULL = nothing to do if( !Handles ) return ; // Check if there is already a set of handles if( MM_GetPhysAddr( gaUserHandles ) != 0 ) return ; // Allocate user handle area { Uint addr, size; int max_handles = *Threads_GetMaxFD(); size = max_handles * sizeof(tVFS_Handle); for(addr = 0; addr < size; addr += 0x1000) { if( !MM_Allocate( (tVAddr)gaUserHandles + addr ) ) { Warning("OOM - VFS_AllocHandle"); Threads_Exit(0, 0xFF); // Terminate user } } memset( gaUserHandles, 0, size ); } // Restore handles memcpy( gaUserHandles, handles, NumFDs * sizeof(tVFS_Handle) ); // Reference when copied for( i = 0; i < NumFDs; i ++ ) { tVFS_Handle *h = &handles[i]; if( !h->Node ) continue ; _ReferenceNode(h->Node); h->Mount->OpenHandleCount ++; } }
int VFS_AllocHandle(int bIsUser, tVFS_Node *Node, int Mode) { // Check for a user open if(bIsUser) { int max_handles = *Threads_GetMaxFD(NULL); // Allocate Buffer if( MM_GetPhysAddr( gaUserHandles ) == 0 ) { tPage *pageptr = (void*)gaUserHandles; size_t size = max_handles * sizeof(tVFS_Handle); for( size_t ofs = 0; ofs < size; ofs ++) { if( !MM_Allocate( pageptr ) ) { Warning("OOM - VFS_AllocHandle"); Threads_Exit(0, 0xFF); // Terminate user } pageptr ++; } memset( gaUserHandles, 0, size ); } // Get a handle for( int i = 0; i < max_handles; i ++ ) { if(gaUserHandles[i].Node) continue; gaUserHandles[i].Node = Node; gaUserHandles[i].Position = 0; gaUserHandles[i].Mode = Mode; return i; } } else { // Allocate space if not already if( MM_GetPhysAddr( gaKernelHandles ) == 0 ) { tPage *pageptr = (void*)gaKernelHandles; size_t size = MAX_KERNEL_FILES * sizeof(tVFS_Handle); for(size_t ofs = 0; ofs < size; ofs += size) { if( !MM_Allocate( pageptr ) ) { Panic("OOM - VFS_AllocHandle"); } pageptr ++; } memset( gaKernelHandles, 0, size ); } // Get a handle for(int i=0;i<MAX_KERNEL_FILES;i++) { if(gaKernelHandles[i].Node) continue; gaKernelHandles[i].Node = Node; gaKernelHandles[i].Position = 0; gaKernelHandles[i].Mode = Mode; return i|VFS_KERNEL_FLAG; } } return -1; }
void VFS_RestoreHandles(int NumFDs, void *Handles) { tVFS_Handle *handles = Handles; const int max_handles = *Threads_GetMaxFD(NULL); // NULL = nothing to do if( !Handles ) return ; if( NumFDs > max_handles ) { Log_Notice("VFS", "RestoreHandles: Capping from %i FDs to %i", NumFDs, max_handles); NumFDs = max_handles; } // Allocate user handle area (and dereference existing handles) for( int i = 0; i < NumFDs; i ++ ) { tVFS_Handle *h = &gaUserHandles[i]; if( !MM_GetPhysAddr(h) ) { void *pg = (void*)( (tVAddr)h & ~(PAGE_SIZE-1) ); if( !MM_Allocate( pg ) ) { // OOM? return ; } memset(pg, 0, PAGE_SIZE); } // Safe to dereference, as Threads_CloneTCB references handles #if 1 else { if(h->Node) { _CloseNode(h->Node); h->Mount->OpenHandleCount --; } } #endif } // Clean up existing // Restore handles memcpy( gaUserHandles, handles, NumFDs * sizeof(tVFS_Handle) ); // Reference when copied for( int i = 0; i < NumFDs; i ++ ) { tVFS_Handle *h = &gaUserHandles[i]; if( !h->Node ) continue ; // Debug("VFS_RestoreHandles: %i %p", i, h->Node); _ReferenceNode(h->Node); h->Mount->OpenHandleCount ++; } for( int i = NumFDs; i < max_handles; i ++ ) { gaUserHandles[i].Node = NULL; } }
int VFS_AllocHandle(int bIsUser, tVFS_Node *Node, int Mode) { // Check for a user open if(bIsUser) { int max_handles = *Threads_GetMaxFD(); // Allocate Buffer if( MM_GetPhysAddr( gaUserHandles ) == 0 ) { Uint addr, size; size = max_handles * sizeof(tVFS_Handle); for(addr = 0; addr < size; addr += 0x1000) { if( !MM_Allocate( (tVAddr)gaUserHandles + addr ) ) { Warning("OOM - VFS_AllocHandle"); Threads_Exit(0, 0xFF); // Terminate user } } memset( gaUserHandles, 0, size ); } // Get a handle for( int i = 0; i < max_handles; i ++ ) { if(gaUserHandles[i].Node) continue; gaUserHandles[i].Node = Node; gaUserHandles[i].Position = 0; gaUserHandles[i].Mode = Mode; return i; } } else { // Allocate space if not already if( MM_GetPhysAddr( gaKernelHandles ) == 0 ) { Uint addr, size; size = MAX_KERNEL_FILES * sizeof(tVFS_Handle); for(addr = 0; addr < size; addr += 0x1000) { if( !MM_Allocate( (tVAddr)gaKernelHandles + addr ) ) { Panic("OOM - VFS_AllocHandle"); Threads_Exit(0, 0xFF); // Terminate application (get some space back) } } memset( gaKernelHandles, 0, size ); } // Get a handle for(int i=0;i<MAX_KERNEL_FILES;i++) { if(gaKernelHandles[i].Node) continue; gaKernelHandles[i].Node = Node; gaKernelHandles[i].Position = 0; gaKernelHandles[i].Mode = Mode; return i|VFS_KERNEL_FLAG; } } return -1; }
// === CODE === int Multiboot_LoadMemoryMap(tMBoot_Info *MBInfo, tVAddr MapOffset, tPMemMapEnt *Map, const int MapSize, tPAddr KStart, tPAddr KEnd) { int nPMemMapEnts = 0; ENTER("pMBInfo pMapOffset pMap iMapSize PKStart PKEnd", MBInfo, MapOffset, Map, MapSize, KStart, KEnd); // Check that the memory map is present if( MBInfo->Flags & (1 << 6) ) { tMBoot_MMapEnt *ent = (void*)((tVAddr)MBInfo->MMapAddr + MapOffset); tMBoot_MMapEnt *last = (void*)((tVAddr)ent + MBInfo->MMapLength); // Build up memory map nPMemMapEnts = 0; while( ent < last && nPMemMapEnts < MapSize ) { tPMemMapEnt *nent = &Map[nPMemMapEnts]; if( !MM_GetPhysAddr(ent) ) Log_KernelPanic("MBoot", "MBoot Map entry %i addres bad (%p)", nPMemMapEnts, ent); LOG("%llx+%llx", ent->Base, ent->Length); nent->Start = ent->Base; nent->Length = ent->Length; switch(ent->Type) { case 1: nent->Type = PMEMTYPE_FREE; break; default: nent->Type = PMEMTYPE_RESERVED; break; } nent->NUMADomain = 0; nPMemMapEnts ++; ent = (void*)( (tVAddr)ent + ent->Size + 4 ); } if( ent < last ) { Log_Warning("MBoot", "Memory map has >%i entries, internal version is truncated", MapSize); } } else if( MBInfo->Flags & (1 << 0) ) { Log_Warning("MBoot", "No memory map passed, using mem_lower and mem_upper"); ASSERT(MapSize >= 2); nPMemMapEnts = 2; Map[0].Start = 0; Map[0].Length = MBInfo->LowMem * 1024; Map[0].Type = PMEMTYPE_FREE; Map[0].NUMADomain = 0; Map[1].Start = 0x100000; Map[1].Length = MBInfo->HighMem * 1024; Map[1].Type = PMEMTYPE_FREE; Map[1].NUMADomain = 0; } else { Log_KernelPanic("MBoot", "Multiboot didn't pass memory information"); } // Ensure it's valid LOG("Validating"); nPMemMapEnts = PMemMap_ValidateMap(Map, nPMemMapEnts, MapSize); // TODO: Error handling // Replace kernel with PMEMTYPE_USED LOG("Marking kernel"); nPMemMapEnts = PMemMap_MarkRangeUsed( Map, nPMemMapEnts, MapSize, KStart, KEnd - KStart ); LOG("Dumping"); PMemMap_DumpBlocks(Map, nPMemMapEnts); // Check if boot modules were passed if( MBInfo->Flags & (1 << 3) ) { // Replace modules with PMEMTYPE_USED nPMemMapEnts = PMemMap_MarkRangeUsed(Map, nPMemMapEnts, MapSize, MBInfo->Modules, MBInfo->ModuleCount*sizeof(tMBoot_Module) ); LOG("MBInfo->Modules = %x", MBInfo->Modules); tMBoot_Module *mods = (void*)( (tVAddr)MBInfo->Modules + MapOffset); for( int i = 0; i < MBInfo->ModuleCount; i ++ ) { LOG("&mods[%i] = %p", i, &mods[i]); LOG("mods[i] = {0x%x -> 0x%x}", mods[i].Start, mods[i].End); nPMemMapEnts = PMemMap_MarkRangeUsed( Map, nPMemMapEnts, MapSize, mods[i].Start, mods[i].End - mods[i].Start ); } } // Debug - Output map PMemMap_DumpBlocks(Map, nPMemMapEnts); LEAVE('i', nPMemMapEnts); return nPMemMapEnts; }