diff --git a/Kernel/include/filesystem.hpp b/Kernel/include/filesystem.hpp index 7003cde3..2bbdf690 100644 --- a/Kernel/include/filesystem.hpp +++ b/Kernel/include/filesystem.hpp @@ -139,6 +139,14 @@ namespace vfs public: vfsInode *FileSystemRoots = nullptr; + + /** + * Default reserved roots: + * + * 0 - Native + * 1 - Linux + * 2 - Windows + */ std::unordered_map FileRoots; bool PathIsRelative(const char *Path); diff --git a/Kernel/include/filesystem/ustar.hpp b/Kernel/include/filesystem/ustar.hpp index 58ac8cb8..b714b5d4 100644 --- a/Kernel/include/filesystem/ustar.hpp +++ b/Kernel/include/filesystem/ustar.hpp @@ -127,11 +127,11 @@ namespace vfs bool TestArchive(uintptr_t Address); void ReadArchive(uintptr_t Address, size_t Size); - USTAR(){}; - ~USTAR(){}; + USTAR() = default; + ~USTAR() = default; }; } -bool TestAndInitializeUSTAR(uintptr_t Address, size_t Size); +bool TestAndInitializeUSTAR(uintptr_t Address, size_t Size, size_t Index); #endif // !__FENNIX_KERNEL_FILESYSTEM_USTAR_H__ diff --git a/Kernel/kernel_thread.cpp b/Kernel/kernel_thread.cpp index 54d46d36..6bbc16f9 100644 --- a/Kernel/kernel_thread.cpp +++ b/Kernel/kernel_thread.cpp @@ -31,30 +31,72 @@ #include #include -cold int SpawnInit() +int SpawnNativeInit() +{ + const char *envp[] = { + "PATH=/sys/bin:/usr/bin", + "LD_LIBRARY_PATH=/sys/lib:/usr/lib", + "TERM=tty", + "HOME=/home/root", + "USER=root", + "TZ=UTC", + nullptr}; + + const char *argv[] = {Config.InitPath, nullptr}; + + return Execute::Spawn(Config.InitPath, argv, envp, nullptr, false, Tasking::Native, true); +} + +int SpawnLinuxInit() { const char *envp[] = { "PATH=/bin:/usr/bin", - "LD_LIBRARY_PATH=/sys/lib:/usr/lib", + "LD_LIBRARY_PATH=/lib:/usr/lib", "TERM=tty", "HOME=/root", "USER=root", "TZ=UTC", nullptr}; - const char *argv[] = { - Config.InitPath, - nullptr}; + std::string init = Config.InitPath; + std::vector fallbackPaths = { + init, + "/bin/init", + "/sbin/init", + "/system/init", + "/usr/bin/init", + "/boot/init", + "/startup/init"}; - Tasking::TaskCompatibility compat = Tasking::Native; - if (Config.LinuxSubsystem) - compat = Tasking::Linux; + const char *foundPath = nullptr; + for (const std::string &path : fallbackPaths) + { + if (!fs->PathExists(path.c_str(), fs->GetRoot(1))) + continue; - return Execute::Spawn(Config.InitPath, argv, envp, - nullptr, false, compat, true); + foundPath = path.c_str(); + break; + } + + if (!foundPath) + { + error("No valid init found in fallback paths"); + return -ENOENT; + } + + const char *argv[] = {foundPath, nullptr}; + return Execute::Spawn(foundPath, argv, envp, nullptr, false, Tasking::Linux, true); } -cold void KernelMainThread() +int SpawnInit() +{ + if (Config.LinuxSubsystem) + return SpawnLinuxInit(); + else + return SpawnNativeInit(); +} + +void KernelMainThread() { thisThread->SetPriority(Tasking::Critical); @@ -129,7 +171,7 @@ Exit: } NewLock(ShutdownLock); -cold void __no_stack_protector KernelShutdownThread(bool Reboot) +void __no_stack_protector KernelShutdownThread(bool Reboot) { SmartLock(ShutdownLock); debug("KernelShutdownThread(%s)", Reboot ? "true" : "false"); diff --git a/Kernel/kernel_vfs.cpp b/Kernel/kernel_vfs.cpp index 5b50e232..37e2eada 100644 --- a/Kernel/kernel_vfs.cpp +++ b/Kernel/kernel_vfs.cpp @@ -26,26 +26,26 @@ void SearchForInitrd() { for (size_t i = 0; i < MAX_MODULES; i++) { - uintptr_t initrdAddress = (uintptr_t)bInfo.Modules[i].Address; + uintptr_t moduleAddress = (uintptr_t)bInfo.Modules[i].Address; + size_t moduleSize = bInfo.Modules[i].Size; + const char *moduleCommand = bInfo.Modules[i].CommandLine; - if (!initrdAddress) + if (moduleAddress == 0) continue; - if (strcmp(bInfo.Modules[i].CommandLine, "rootfs") != 0) - continue; - - KPrint("rootfs found at %#lx", initrdAddress); - Memory::Virtual vmm; - if (!vmm.Check((void *)initrdAddress)) + if (!vmm.CheckRegion((void *)moduleAddress, moduleSize)) { - warn("Initrd is not mapped!"); - vmm.Map((void *)initrdAddress, (void *)initrdAddress, - bInfo.Modules[i].Size, Memory::RW); + warn("module entry is not mapped!"); + vmm.Map((void *)moduleAddress, (void *)moduleAddress, moduleSize, Memory::RW); } - if (TestAndInitializeUSTAR(initrdAddress, bInfo.Modules[i].Size)) - continue; /* Maybe add another root? */ + if (strcmp(moduleCommand, "rootfs") == 0) + { + KPrint("rootfs found at %#lx", moduleAddress); + if (TestAndInitializeUSTAR(moduleAddress, moduleSize, 0)) + continue; + } } } diff --git a/Kernel/storage/fs/ustar.cpp b/Kernel/storage/fs/ustar.cpp index 890c3231..163a9f4f 100644 --- a/Kernel/storage/fs/ustar.cpp +++ b/Kernel/storage/fs/ustar.cpp @@ -16,7 +16,6 @@ */ #include - #include #include #include @@ -160,10 +159,14 @@ namespace vfs node->Name.assign(basename, length); node->Path.assign(Name, strlen(Name)); - Files.insert(std::make_pair(NextInode, node)); - *Result = &Files.at(NextInode)->Node; + auto &&file = Files.insert(std::make_pair(NextInode, node)); + assert(file.second == true); + *Result = &file.first->second->Node; if (Parent) - Parent->Children.push_back(Files.at(NextInode)); + { + Parent->Children.push_back(file.first->second); + file.first->second->Parent = Parent; + } NextInode++; return 0; } @@ -491,6 +494,10 @@ namespace vfs FileHeader *header = (FileHeader *)Address; if (strncmp(header->signature, TMAGIC, TMAGLEN) != 0) { + /* For some reason if GRUB inflates the archive, the magic is "ustar " */ + if (strncmp(header->signature, TMAGIC, TMAGLEN - 1) == 0) + return true; + error("Invalid signature!"); return false; } @@ -564,7 +571,7 @@ namespace vfs FileHeader *header = (FileHeader *)Address; - debug("USTAR signature valid! Name:%s Signature:%s Mode:%d Size:%lu", + debug("USTAR signature valid! Name:\"%s\" Signature:\"%s\" Mode:%d Size:%lu", header->name, header->signature, StringToInt(header->mode), header->size); Memory::Virtual vmm; @@ -577,7 +584,7 @@ namespace vfs return; } - if (strncmp(header->signature, TMAGIC, TMAGLEN) != 0) + if (strncmp(header->signature, TMAGIC, TMAGLEN - 1) != 0) break; // debug("\"%s\"", header->name); @@ -817,13 +824,13 @@ O2 int __ustar_Stat(struct Inode *Node, kstat *Stat) return ((vfs::USTAR *)Node->PrivateData)->Stat(Node, Stat); } -int __ustar_DestroyInode(FileSystemInfo *Info, Inode *Node) +O2 int __ustar_DestroyInode(FileSystemInfo *Info, Inode *Node) { ((vfs::USTAR::USTARInode *)Node)->Deleted = true; return 0; } -int __ustar_Destroy(FileSystemInfo *fsi) +O2 int __ustar_Destroy(FileSystemInfo *fsi) { assert(fsi->PrivateData); delete (vfs::USTAR *)fsi->PrivateData; @@ -831,7 +838,7 @@ int __ustar_Destroy(FileSystemInfo *fsi) return 0; } -bool TestAndInitializeUSTAR(uintptr_t Address, size_t Size) +bool TestAndInitializeUSTAR(uintptr_t Address, size_t Size, size_t Index) { vfs::USTAR *ustar = new vfs::USTAR(); if (!ustar->TestArchive(Address)) @@ -863,6 +870,6 @@ bool TestAndInitializeUSTAR(uintptr_t Address, size_t Size) fsi->PrivateData = ustar; fs->LateRegisterFileSystem(ustar->DeviceID, fsi, rootfs); - fs->AddRoot(rootfs); + fs->AddRootAt(rootfs, Index); return true; }