core/core: Move process execution start to System's Load()
This gives us significantly more control over where in the initialization process we start execution of the main process. Previously we were running the main process before the CPU or GPU threads were initialized (not good). This amends execution to start after all of our threads are properly set up.
This commit is contained in:
parent
32a6ceb4e5
commit
612e1388df
|
@ -168,7 +168,7 @@ struct System::Impl {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto main_process = Kernel::Process::Create(system, "main");
|
auto main_process = Kernel::Process::Create(system, "main");
|
||||||
const Loader::ResultStatus load_result{app_loader->Load(*main_process)};
|
const auto [load_result, load_parameters] = app_loader->Load(*main_process);
|
||||||
if (load_result != Loader::ResultStatus::Success) {
|
if (load_result != Loader::ResultStatus::Success) {
|
||||||
LOG_CRITICAL(Core, "Failed to load ROM (Error {})!", static_cast<int>(load_result));
|
LOG_CRITICAL(Core, "Failed to load ROM (Error {})!", static_cast<int>(load_result));
|
||||||
Shutdown();
|
Shutdown();
|
||||||
|
@ -183,6 +183,10 @@ struct System::Impl {
|
||||||
gpu_core->Start();
|
gpu_core->Start();
|
||||||
cpu_core_manager.StartThreads();
|
cpu_core_manager.StartThreads();
|
||||||
|
|
||||||
|
// All threads are started, begin main process execution, now that we're in the clear.
|
||||||
|
main_process->Run(load_parameters->main_thread_priority,
|
||||||
|
load_parameters->main_thread_stack_size);
|
||||||
|
|
||||||
status = ResultStatus::Success;
|
status = ResultStatus::Success;
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,12 +28,12 @@ namespace {
|
||||||
*
|
*
|
||||||
* @param owner_process The parent process for the main thread
|
* @param owner_process The parent process for the main thread
|
||||||
* @param kernel The kernel instance to create the main thread under.
|
* @param kernel The kernel instance to create the main thread under.
|
||||||
* @param entry_point The address at which the thread should start execution
|
|
||||||
* @param priority The priority to give the main thread
|
* @param priority The priority to give the main thread
|
||||||
*/
|
*/
|
||||||
void SetupMainThread(Process& owner_process, KernelCore& kernel, VAddr entry_point, u32 priority) {
|
void SetupMainThread(Process& owner_process, KernelCore& kernel, u32 priority) {
|
||||||
// Initialize new "main" thread
|
const auto& vm_manager = owner_process.VMManager();
|
||||||
const VAddr stack_top = owner_process.VMManager().GetTLSIORegionEndAddress();
|
const VAddr entry_point = vm_manager.GetCodeRegionBaseAddress();
|
||||||
|
const VAddr stack_top = vm_manager.GetTLSIORegionEndAddress();
|
||||||
auto thread_res = Thread::Create(kernel, "main", entry_point, priority, 0,
|
auto thread_res = Thread::Create(kernel, "main", entry_point, priority, 0,
|
||||||
owner_process.GetIdealCore(), stack_top, owner_process);
|
owner_process.GetIdealCore(), stack_top, owner_process);
|
||||||
|
|
||||||
|
@ -117,7 +117,7 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata) {
|
||||||
return handle_table.SetSize(capabilities.GetHandleTableSize());
|
return handle_table.SetSize(capabilities.GetHandleTableSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Process::Run(VAddr entry_point, s32 main_thread_priority, u64 stack_size) {
|
void Process::Run(s32 main_thread_priority, u64 stack_size) {
|
||||||
// The kernel always ensures that the given stack size is page aligned.
|
// The kernel always ensures that the given stack size is page aligned.
|
||||||
main_thread_stack_size = Common::AlignUp(stack_size, Memory::PAGE_SIZE);
|
main_thread_stack_size = Common::AlignUp(stack_size, Memory::PAGE_SIZE);
|
||||||
|
|
||||||
|
@ -133,7 +133,7 @@ void Process::Run(VAddr entry_point, s32 main_thread_priority, u64 stack_size) {
|
||||||
vm_manager.LogLayout();
|
vm_manager.LogLayout();
|
||||||
ChangeStatus(ProcessStatus::Running);
|
ChangeStatus(ProcessStatus::Running);
|
||||||
|
|
||||||
SetupMainThread(*this, kernel, entry_point, main_thread_priority);
|
SetupMainThread(*this, kernel, main_thread_priority);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Process::PrepareForTermination() {
|
void Process::PrepareForTermination() {
|
||||||
|
|
|
@ -225,9 +225,12 @@ public:
|
||||||
ResultCode LoadFromMetadata(const FileSys::ProgramMetadata& metadata);
|
ResultCode LoadFromMetadata(const FileSys::ProgramMetadata& metadata);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies address space changes and launches the process main thread.
|
* Starts the main application thread for this process.
|
||||||
|
*
|
||||||
|
* @param main_thread_priority The priority for the main thread.
|
||||||
|
* @param stack_size The stack size for the main thread in bytes.
|
||||||
*/
|
*/
|
||||||
void Run(VAddr entry_point, s32 main_thread_priority, u64 stack_size);
|
void Run(s32 main_thread_priority, u64 stack_size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepares a process for termination by stopping all of its threads
|
* Prepares a process for termination by stopping all of its threads
|
||||||
|
|
|
@ -86,25 +86,29 @@ FileType AppLoader_DeconstructedRomDirectory::IdentifyType(const FileSys::Virtua
|
||||||
return FileType::Error;
|
return FileType::Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultStatus AppLoader_DeconstructedRomDirectory::Load(Kernel::Process& process) {
|
AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirectory::Load(
|
||||||
|
Kernel::Process& process) {
|
||||||
if (is_loaded) {
|
if (is_loaded) {
|
||||||
return ResultStatus::ErrorAlreadyLoaded;
|
return {ResultStatus::ErrorAlreadyLoaded, {}};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dir == nullptr) {
|
if (dir == nullptr) {
|
||||||
if (file == nullptr)
|
if (file == nullptr) {
|
||||||
return ResultStatus::ErrorNullFile;
|
return {ResultStatus::ErrorNullFile, {}};
|
||||||
|
}
|
||||||
|
|
||||||
dir = file->GetContainingDirectory();
|
dir = file->GetContainingDirectory();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read meta to determine title ID
|
// Read meta to determine title ID
|
||||||
FileSys::VirtualFile npdm = dir->GetFile("main.npdm");
|
FileSys::VirtualFile npdm = dir->GetFile("main.npdm");
|
||||||
if (npdm == nullptr)
|
if (npdm == nullptr) {
|
||||||
return ResultStatus::ErrorMissingNPDM;
|
return {ResultStatus::ErrorMissingNPDM, {}};
|
||||||
|
}
|
||||||
|
|
||||||
ResultStatus result = metadata.Load(npdm);
|
const ResultStatus result = metadata.Load(npdm);
|
||||||
if (result != ResultStatus::Success) {
|
if (result != ResultStatus::Success) {
|
||||||
return result;
|
return {result, {}};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (override_update) {
|
if (override_update) {
|
||||||
|
@ -114,23 +118,24 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load(Kernel::Process& process)
|
||||||
|
|
||||||
// Reread in case PatchExeFS affected the main.npdm
|
// Reread in case PatchExeFS affected the main.npdm
|
||||||
npdm = dir->GetFile("main.npdm");
|
npdm = dir->GetFile("main.npdm");
|
||||||
if (npdm == nullptr)
|
if (npdm == nullptr) {
|
||||||
return ResultStatus::ErrorMissingNPDM;
|
return {ResultStatus::ErrorMissingNPDM, {}};
|
||||||
|
}
|
||||||
|
|
||||||
ResultStatus result2 = metadata.Load(npdm);
|
const ResultStatus result2 = metadata.Load(npdm);
|
||||||
if (result2 != ResultStatus::Success) {
|
if (result2 != ResultStatus::Success) {
|
||||||
return result2;
|
return {result2, {}};
|
||||||
}
|
}
|
||||||
metadata.Print();
|
metadata.Print();
|
||||||
|
|
||||||
const FileSys::ProgramAddressSpaceType arch_bits{metadata.GetAddressSpaceType()};
|
const FileSys::ProgramAddressSpaceType arch_bits{metadata.GetAddressSpaceType()};
|
||||||
if (arch_bits == FileSys::ProgramAddressSpaceType::Is32Bit ||
|
if (arch_bits == FileSys::ProgramAddressSpaceType::Is32Bit ||
|
||||||
arch_bits == FileSys::ProgramAddressSpaceType::Is32BitNoMap) {
|
arch_bits == FileSys::ProgramAddressSpaceType::Is32BitNoMap) {
|
||||||
return ResultStatus::Error32BitISA;
|
return {ResultStatus::Error32BitISA, {}};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (process.LoadFromMetadata(metadata).IsError()) {
|
if (process.LoadFromMetadata(metadata).IsError()) {
|
||||||
return ResultStatus::ErrorUnableToParseKernelMetadata;
|
return {ResultStatus::ErrorUnableToParseKernelMetadata, {}};
|
||||||
}
|
}
|
||||||
|
|
||||||
const FileSys::PatchManager pm(metadata.GetTitleID());
|
const FileSys::PatchManager pm(metadata.GetTitleID());
|
||||||
|
@ -150,7 +155,7 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load(Kernel::Process& process)
|
||||||
const auto tentative_next_load_addr =
|
const auto tentative_next_load_addr =
|
||||||
AppLoader_NSO::LoadModule(process, *module_file, load_addr, should_pass_arguments, pm);
|
AppLoader_NSO::LoadModule(process, *module_file, load_addr, should_pass_arguments, pm);
|
||||||
if (!tentative_next_load_addr) {
|
if (!tentative_next_load_addr) {
|
||||||
return ResultStatus::ErrorLoadingNSO;
|
return {ResultStatus::ErrorLoadingNSO, {}};
|
||||||
}
|
}
|
||||||
|
|
||||||
next_load_addr = *tentative_next_load_addr;
|
next_load_addr = *tentative_next_load_addr;
|
||||||
|
@ -159,8 +164,6 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load(Kernel::Process& process)
|
||||||
GDBStub::RegisterModule(module, load_addr, next_load_addr - 1, false);
|
GDBStub::RegisterModule(module, load_addr, next_load_addr - 1, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
process.Run(base_address, metadata.GetMainThreadPriority(), metadata.GetMainThreadStackSize());
|
|
||||||
|
|
||||||
// Find the RomFS by searching for a ".romfs" file in this directory
|
// Find the RomFS by searching for a ".romfs" file in this directory
|
||||||
const auto& files = dir->GetFiles();
|
const auto& files = dir->GetFiles();
|
||||||
const auto romfs_iter =
|
const auto romfs_iter =
|
||||||
|
@ -175,7 +178,8 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load(Kernel::Process& process)
|
||||||
}
|
}
|
||||||
|
|
||||||
is_loaded = true;
|
is_loaded = true;
|
||||||
return ResultStatus::Success;
|
return {ResultStatus::Success,
|
||||||
|
LoadParameters{metadata.GetMainThreadPriority(), metadata.GetMainThreadStackSize()}};
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultStatus AppLoader_DeconstructedRomDirectory::ReadRomFS(FileSys::VirtualFile& dir) {
|
ResultStatus AppLoader_DeconstructedRomDirectory::ReadRomFS(FileSys::VirtualFile& dir) {
|
||||||
|
|
|
@ -37,7 +37,7 @@ public:
|
||||||
return IdentifyType(file);
|
return IdentifyType(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultStatus Load(Kernel::Process& process) override;
|
LoadResult Load(Kernel::Process& process) override;
|
||||||
|
|
||||||
ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override;
|
ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override;
|
||||||
ResultStatus ReadIcon(std::vector<u8>& buffer) override;
|
ResultStatus ReadIcon(std::vector<u8>& buffer) override;
|
||||||
|
|
|
@ -382,13 +382,15 @@ FileType AppLoader_ELF::IdentifyType(const FileSys::VirtualFile& file) {
|
||||||
return FileType::Error;
|
return FileType::Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultStatus AppLoader_ELF::Load(Kernel::Process& process) {
|
AppLoader_ELF::LoadResult AppLoader_ELF::Load(Kernel::Process& process) {
|
||||||
if (is_loaded)
|
if (is_loaded) {
|
||||||
return ResultStatus::ErrorAlreadyLoaded;
|
return {ResultStatus::ErrorAlreadyLoaded, {}};
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<u8> buffer = file->ReadAllBytes();
|
std::vector<u8> buffer = file->ReadAllBytes();
|
||||||
if (buffer.size() != file->GetSize())
|
if (buffer.size() != file->GetSize()) {
|
||||||
return ResultStatus::ErrorIncorrectELFFileSize;
|
return {ResultStatus::ErrorIncorrectELFFileSize, {}};
|
||||||
|
}
|
||||||
|
|
||||||
const VAddr base_address = process.VMManager().GetCodeRegionBaseAddress();
|
const VAddr base_address = process.VMManager().GetCodeRegionBaseAddress();
|
||||||
ElfReader elf_reader(&buffer[0]);
|
ElfReader elf_reader(&buffer[0]);
|
||||||
|
@ -396,10 +398,9 @@ ResultStatus AppLoader_ELF::Load(Kernel::Process& process) {
|
||||||
const VAddr entry_point = codeset.entrypoint;
|
const VAddr entry_point = codeset.entrypoint;
|
||||||
|
|
||||||
process.LoadModule(std::move(codeset), entry_point);
|
process.LoadModule(std::move(codeset), entry_point);
|
||||||
process.Run(entry_point, 48, Memory::DEFAULT_STACK_SIZE);
|
|
||||||
|
|
||||||
is_loaded = true;
|
is_loaded = true;
|
||||||
return ResultStatus::Success;
|
return {ResultStatus::Success, LoadParameters{48, Memory::DEFAULT_STACK_SIZE}};
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Loader
|
} // namespace Loader
|
||||||
|
|
|
@ -26,7 +26,7 @@ public:
|
||||||
return IdentifyType(file);
|
return IdentifyType(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultStatus Load(Kernel::Process& process) override;
|
LoadResult Load(Kernel::Process& process) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Loader
|
} // namespace Loader
|
||||||
|
|
|
@ -131,6 +131,12 @@ std::ostream& operator<<(std::ostream& os, ResultStatus status);
|
||||||
/// Interface for loading an application
|
/// Interface for loading an application
|
||||||
class AppLoader : NonCopyable {
|
class AppLoader : NonCopyable {
|
||||||
public:
|
public:
|
||||||
|
struct LoadParameters {
|
||||||
|
s32 main_thread_priority;
|
||||||
|
u64 main_thread_stack_size;
|
||||||
|
};
|
||||||
|
using LoadResult = std::pair<ResultStatus, std::optional<LoadParameters>>;
|
||||||
|
|
||||||
explicit AppLoader(FileSys::VirtualFile file);
|
explicit AppLoader(FileSys::VirtualFile file);
|
||||||
virtual ~AppLoader();
|
virtual ~AppLoader();
|
||||||
|
|
||||||
|
@ -145,7 +151,7 @@ public:
|
||||||
* @param process The newly created process.
|
* @param process The newly created process.
|
||||||
* @return The status result of the operation.
|
* @return The status result of the operation.
|
||||||
*/
|
*/
|
||||||
virtual ResultStatus Load(Kernel::Process& process) = 0;
|
virtual LoadResult Load(Kernel::Process& process) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads the system mode that this application needs.
|
* Loads the system mode that this application needs.
|
||||||
|
|
|
@ -41,31 +41,37 @@ FileType AppLoader_NAX::GetFileType() const {
|
||||||
return IdentifyTypeImpl(*nax);
|
return IdentifyTypeImpl(*nax);
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultStatus AppLoader_NAX::Load(Kernel::Process& process) {
|
AppLoader_NAX::LoadResult AppLoader_NAX::Load(Kernel::Process& process) {
|
||||||
if (is_loaded) {
|
if (is_loaded) {
|
||||||
return ResultStatus::ErrorAlreadyLoaded;
|
return {ResultStatus::ErrorAlreadyLoaded, {}};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nax->GetStatus() != ResultStatus::Success)
|
const auto nax_status = nax->GetStatus();
|
||||||
return nax->GetStatus();
|
if (nax_status != ResultStatus::Success) {
|
||||||
|
return {nax_status, {}};
|
||||||
|
}
|
||||||
|
|
||||||
const auto nca = nax->AsNCA();
|
const auto nca = nax->AsNCA();
|
||||||
if (nca == nullptr) {
|
if (nca == nullptr) {
|
||||||
if (!Core::Crypto::KeyManager::KeyFileExists(false))
|
if (!Core::Crypto::KeyManager::KeyFileExists(false)) {
|
||||||
return ResultStatus::ErrorMissingProductionKeyFile;
|
return {ResultStatus::ErrorMissingProductionKeyFile, {}};
|
||||||
return ResultStatus::ErrorNAXInconvertibleToNCA;
|
}
|
||||||
|
|
||||||
|
return {ResultStatus::ErrorNAXInconvertibleToNCA, {}};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nca->GetStatus() != ResultStatus::Success)
|
const auto nca_status = nca->GetStatus();
|
||||||
return nca->GetStatus();
|
if (nca_status != ResultStatus::Success) {
|
||||||
|
return {nca_status, {}};
|
||||||
|
}
|
||||||
|
|
||||||
const auto result = nca_loader->Load(process);
|
const auto result = nca_loader->Load(process);
|
||||||
if (result != ResultStatus::Success)
|
if (result.first != ResultStatus::Success) {
|
||||||
return result;
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
is_loaded = true;
|
is_loaded = true;
|
||||||
|
return result;
|
||||||
return ResultStatus::Success;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultStatus AppLoader_NAX::ReadRomFS(FileSys::VirtualFile& dir) {
|
ResultStatus AppLoader_NAX::ReadRomFS(FileSys::VirtualFile& dir) {
|
||||||
|
|
|
@ -33,7 +33,7 @@ public:
|
||||||
|
|
||||||
FileType GetFileType() const override;
|
FileType GetFileType() const override;
|
||||||
|
|
||||||
ResultStatus Load(Kernel::Process& process) override;
|
LoadResult Load(Kernel::Process& process) override;
|
||||||
|
|
||||||
ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override;
|
ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override;
|
||||||
u64 ReadRomFSIVFCOffset() const override;
|
u64 ReadRomFSIVFCOffset() const override;
|
||||||
|
|
|
@ -30,36 +30,38 @@ FileType AppLoader_NCA::IdentifyType(const FileSys::VirtualFile& file) {
|
||||||
return FileType::Error;
|
return FileType::Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultStatus AppLoader_NCA::Load(Kernel::Process& process) {
|
AppLoader_NCA::LoadResult AppLoader_NCA::Load(Kernel::Process& process) {
|
||||||
if (is_loaded) {
|
if (is_loaded) {
|
||||||
return ResultStatus::ErrorAlreadyLoaded;
|
return {ResultStatus::ErrorAlreadyLoaded, {}};
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto result = nca->GetStatus();
|
const auto result = nca->GetStatus();
|
||||||
if (result != ResultStatus::Success) {
|
if (result != ResultStatus::Success) {
|
||||||
return result;
|
return {result, {}};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nca->GetType() != FileSys::NCAContentType::Program)
|
if (nca->GetType() != FileSys::NCAContentType::Program) {
|
||||||
return ResultStatus::ErrorNCANotProgram;
|
return {ResultStatus::ErrorNCANotProgram, {}};
|
||||||
|
}
|
||||||
|
|
||||||
const auto exefs = nca->GetExeFS();
|
const auto exefs = nca->GetExeFS();
|
||||||
|
if (exefs == nullptr) {
|
||||||
if (exefs == nullptr)
|
return {ResultStatus::ErrorNoExeFS, {}};
|
||||||
return ResultStatus::ErrorNoExeFS;
|
}
|
||||||
|
|
||||||
directory_loader = std::make_unique<AppLoader_DeconstructedRomDirectory>(exefs, true);
|
directory_loader = std::make_unique<AppLoader_DeconstructedRomDirectory>(exefs, true);
|
||||||
|
|
||||||
const auto load_result = directory_loader->Load(process);
|
const auto load_result = directory_loader->Load(process);
|
||||||
if (load_result != ResultStatus::Success)
|
if (load_result.first != ResultStatus::Success) {
|
||||||
return load_result;
|
return load_result;
|
||||||
|
}
|
||||||
|
|
||||||
if (nca->GetRomFS() != nullptr && nca->GetRomFS()->GetSize() > 0)
|
if (nca->GetRomFS() != nullptr && nca->GetRomFS()->GetSize() > 0) {
|
||||||
Service::FileSystem::RegisterRomFS(std::make_unique<FileSys::RomFSFactory>(*this));
|
Service::FileSystem::RegisterRomFS(std::make_unique<FileSys::RomFSFactory>(*this));
|
||||||
|
}
|
||||||
|
|
||||||
is_loaded = true;
|
is_loaded = true;
|
||||||
|
return load_result;
|
||||||
return ResultStatus::Success;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultStatus AppLoader_NCA::ReadRomFS(FileSys::VirtualFile& dir) {
|
ResultStatus AppLoader_NCA::ReadRomFS(FileSys::VirtualFile& dir) {
|
||||||
|
|
|
@ -33,7 +33,7 @@ public:
|
||||||
return IdentifyType(file);
|
return IdentifyType(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultStatus Load(Kernel::Process& process) override;
|
LoadResult Load(Kernel::Process& process) override;
|
||||||
|
|
||||||
ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override;
|
ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override;
|
||||||
u64 ReadRomFSIVFCOffset() const override;
|
u64 ReadRomFSIVFCOffset() const override;
|
||||||
|
|
|
@ -201,25 +201,25 @@ bool AppLoader_NRO::LoadNro(Kernel::Process& process, const FileSys::VfsFile& fi
|
||||||
return LoadNroImpl(process, file.ReadAllBytes(), file.GetName(), load_base);
|
return LoadNroImpl(process, file.ReadAllBytes(), file.GetName(), load_base);
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultStatus AppLoader_NRO::Load(Kernel::Process& process) {
|
AppLoader_NRO::LoadResult AppLoader_NRO::Load(Kernel::Process& process) {
|
||||||
if (is_loaded) {
|
if (is_loaded) {
|
||||||
return ResultStatus::ErrorAlreadyLoaded;
|
return {ResultStatus::ErrorAlreadyLoaded, {}};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load NRO
|
// Load NRO
|
||||||
const VAddr base_address = process.VMManager().GetCodeRegionBaseAddress();
|
const VAddr base_address = process.VMManager().GetCodeRegionBaseAddress();
|
||||||
|
|
||||||
if (!LoadNro(process, *file, base_address)) {
|
if (!LoadNro(process, *file, base_address)) {
|
||||||
return ResultStatus::ErrorLoadingNRO;
|
return {ResultStatus::ErrorLoadingNRO, {}};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (romfs != nullptr)
|
if (romfs != nullptr) {
|
||||||
Service::FileSystem::RegisterRomFS(std::make_unique<FileSys::RomFSFactory>(*this));
|
Service::FileSystem::RegisterRomFS(std::make_unique<FileSys::RomFSFactory>(*this));
|
||||||
|
}
|
||||||
process.Run(base_address, Kernel::THREADPRIO_DEFAULT, Memory::DEFAULT_STACK_SIZE);
|
|
||||||
|
|
||||||
is_loaded = true;
|
is_loaded = true;
|
||||||
return ResultStatus::Success;
|
return {ResultStatus::Success,
|
||||||
|
LoadParameters{Kernel::THREADPRIO_DEFAULT, Memory::DEFAULT_STACK_SIZE}};
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultStatus AppLoader_NRO::ReadIcon(std::vector<u8>& buffer) {
|
ResultStatus AppLoader_NRO::ReadIcon(std::vector<u8>& buffer) {
|
||||||
|
|
|
@ -37,7 +37,7 @@ public:
|
||||||
return IdentifyType(file);
|
return IdentifyType(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultStatus Load(Kernel::Process& process) override;
|
LoadResult Load(Kernel::Process& process) override;
|
||||||
|
|
||||||
ResultStatus ReadIcon(std::vector<u8>& buffer) override;
|
ResultStatus ReadIcon(std::vector<u8>& buffer) override;
|
||||||
ResultStatus ReadProgramId(u64& out_program_id) override;
|
ResultStatus ReadProgramId(u64& out_program_id) override;
|
||||||
|
|
|
@ -169,22 +169,21 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::Process& process,
|
||||||
return load_base + image_size;
|
return load_base + image_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultStatus AppLoader_NSO::Load(Kernel::Process& process) {
|
AppLoader_NSO::LoadResult AppLoader_NSO::Load(Kernel::Process& process) {
|
||||||
if (is_loaded) {
|
if (is_loaded) {
|
||||||
return ResultStatus::ErrorAlreadyLoaded;
|
return {ResultStatus::ErrorAlreadyLoaded, {}};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load module
|
// Load module
|
||||||
const VAddr base_address = process.VMManager().GetCodeRegionBaseAddress();
|
const VAddr base_address = process.VMManager().GetCodeRegionBaseAddress();
|
||||||
if (!LoadModule(process, *file, base_address, true)) {
|
if (!LoadModule(process, *file, base_address, true)) {
|
||||||
return ResultStatus::ErrorLoadingNSO;
|
return {ResultStatus::ErrorLoadingNSO, {}};
|
||||||
}
|
}
|
||||||
LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", file->GetName(), base_address);
|
LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", file->GetName(), base_address);
|
||||||
|
|
||||||
process.Run(base_address, Kernel::THREADPRIO_DEFAULT, Memory::DEFAULT_STACK_SIZE);
|
|
||||||
|
|
||||||
is_loaded = true;
|
is_loaded = true;
|
||||||
return ResultStatus::Success;
|
return {ResultStatus::Success,
|
||||||
|
LoadParameters{Kernel::THREADPRIO_DEFAULT, Memory::DEFAULT_STACK_SIZE}};
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Loader
|
} // namespace Loader
|
||||||
|
|
|
@ -84,7 +84,7 @@ public:
|
||||||
VAddr load_base, bool should_pass_arguments,
|
VAddr load_base, bool should_pass_arguments,
|
||||||
std::optional<FileSys::PatchManager> pm = {});
|
std::optional<FileSys::PatchManager> pm = {});
|
||||||
|
|
||||||
ResultStatus Load(Kernel::Process& process) override;
|
LoadResult Load(Kernel::Process& process) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Loader
|
} // namespace Loader
|
||||||
|
|
|
@ -72,37 +72,45 @@ FileType AppLoader_NSP::IdentifyType(const FileSys::VirtualFile& file) {
|
||||||
return FileType::Error;
|
return FileType::Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultStatus AppLoader_NSP::Load(Kernel::Process& process) {
|
AppLoader_NSP::LoadResult AppLoader_NSP::Load(Kernel::Process& process) {
|
||||||
if (is_loaded) {
|
if (is_loaded) {
|
||||||
return ResultStatus::ErrorAlreadyLoaded;
|
return {ResultStatus::ErrorAlreadyLoaded, {}};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (title_id == 0)
|
if (title_id == 0) {
|
||||||
return ResultStatus::ErrorNSPMissingProgramNCA;
|
return {ResultStatus::ErrorNSPMissingProgramNCA, {}};
|
||||||
|
}
|
||||||
|
|
||||||
if (nsp->GetStatus() != ResultStatus::Success)
|
const auto nsp_status = nsp->GetStatus();
|
||||||
return nsp->GetStatus();
|
if (nsp_status != ResultStatus::Success) {
|
||||||
|
return {nsp_status, {}};
|
||||||
|
}
|
||||||
|
|
||||||
if (nsp->GetProgramStatus(title_id) != ResultStatus::Success)
|
const auto nsp_program_status = nsp->GetProgramStatus(title_id);
|
||||||
return nsp->GetProgramStatus(title_id);
|
if (nsp_program_status != ResultStatus::Success) {
|
||||||
|
return {nsp_program_status, {}};
|
||||||
|
}
|
||||||
|
|
||||||
if (nsp->GetNCA(title_id, FileSys::ContentRecordType::Program) == nullptr) {
|
if (nsp->GetNCA(title_id, FileSys::ContentRecordType::Program) == nullptr) {
|
||||||
if (!Core::Crypto::KeyManager::KeyFileExists(false))
|
if (!Core::Crypto::KeyManager::KeyFileExists(false)) {
|
||||||
return ResultStatus::ErrorMissingProductionKeyFile;
|
return {ResultStatus::ErrorMissingProductionKeyFile, {}};
|
||||||
return ResultStatus::ErrorNSPMissingProgramNCA;
|
}
|
||||||
|
|
||||||
|
return {ResultStatus::ErrorNSPMissingProgramNCA, {}};
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto result = secondary_loader->Load(process);
|
const auto result = secondary_loader->Load(process);
|
||||||
if (result != ResultStatus::Success)
|
if (result.first != ResultStatus::Success) {
|
||||||
return result;
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
FileSys::VirtualFile update_raw;
|
FileSys::VirtualFile update_raw;
|
||||||
if (ReadUpdateRaw(update_raw) == ResultStatus::Success && update_raw != nullptr)
|
if (ReadUpdateRaw(update_raw) == ResultStatus::Success && update_raw != nullptr) {
|
||||||
Service::FileSystem::SetPackedUpdate(std::move(update_raw));
|
Service::FileSystem::SetPackedUpdate(std::move(update_raw));
|
||||||
|
}
|
||||||
|
|
||||||
is_loaded = true;
|
is_loaded = true;
|
||||||
|
return result;
|
||||||
return ResultStatus::Success;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultStatus AppLoader_NSP::ReadRomFS(FileSys::VirtualFile& file) {
|
ResultStatus AppLoader_NSP::ReadRomFS(FileSys::VirtualFile& file) {
|
||||||
|
|
|
@ -35,7 +35,7 @@ public:
|
||||||
return IdentifyType(file);
|
return IdentifyType(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultStatus Load(Kernel::Process& process) override;
|
LoadResult Load(Kernel::Process& process) override;
|
||||||
|
|
||||||
ResultStatus ReadRomFS(FileSys::VirtualFile& file) override;
|
ResultStatus ReadRomFS(FileSys::VirtualFile& file) override;
|
||||||
u64 ReadRomFSIVFCOffset() const override;
|
u64 ReadRomFSIVFCOffset() const override;
|
||||||
|
|
|
@ -48,31 +48,35 @@ FileType AppLoader_XCI::IdentifyType(const FileSys::VirtualFile& file) {
|
||||||
return FileType::Error;
|
return FileType::Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultStatus AppLoader_XCI::Load(Kernel::Process& process) {
|
AppLoader_XCI::LoadResult AppLoader_XCI::Load(Kernel::Process& process) {
|
||||||
if (is_loaded) {
|
if (is_loaded) {
|
||||||
return ResultStatus::ErrorAlreadyLoaded;
|
return {ResultStatus::ErrorAlreadyLoaded, {}};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xci->GetStatus() != ResultStatus::Success)
|
if (xci->GetStatus() != ResultStatus::Success) {
|
||||||
return xci->GetStatus();
|
return {xci->GetStatus(), {}};
|
||||||
|
}
|
||||||
|
|
||||||
if (xci->GetProgramNCAStatus() != ResultStatus::Success)
|
if (xci->GetProgramNCAStatus() != ResultStatus::Success) {
|
||||||
return xci->GetProgramNCAStatus();
|
return {xci->GetProgramNCAStatus(), {}};
|
||||||
|
}
|
||||||
|
|
||||||
if (!xci->HasProgramNCA() && !Core::Crypto::KeyManager::KeyFileExists(false))
|
if (!xci->HasProgramNCA() && !Core::Crypto::KeyManager::KeyFileExists(false)) {
|
||||||
return ResultStatus::ErrorMissingProductionKeyFile;
|
return {ResultStatus::ErrorMissingProductionKeyFile, {}};
|
||||||
|
}
|
||||||
|
|
||||||
const auto result = nca_loader->Load(process);
|
const auto result = nca_loader->Load(process);
|
||||||
if (result != ResultStatus::Success)
|
if (result.first != ResultStatus::Success) {
|
||||||
return result;
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
FileSys::VirtualFile update_raw;
|
FileSys::VirtualFile update_raw;
|
||||||
if (ReadUpdateRaw(update_raw) == ResultStatus::Success && update_raw != nullptr)
|
if (ReadUpdateRaw(update_raw) == ResultStatus::Success && update_raw != nullptr) {
|
||||||
Service::FileSystem::SetPackedUpdate(std::move(update_raw));
|
Service::FileSystem::SetPackedUpdate(std::move(update_raw));
|
||||||
|
}
|
||||||
|
|
||||||
is_loaded = true;
|
is_loaded = true;
|
||||||
|
return result;
|
||||||
return ResultStatus::Success;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultStatus AppLoader_XCI::ReadRomFS(FileSys::VirtualFile& file) {
|
ResultStatus AppLoader_XCI::ReadRomFS(FileSys::VirtualFile& file) {
|
||||||
|
|
|
@ -35,7 +35,7 @@ public:
|
||||||
return IdentifyType(file);
|
return IdentifyType(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultStatus Load(Kernel::Process& process) override;
|
LoadResult Load(Kernel::Process& process) override;
|
||||||
|
|
||||||
ResultStatus ReadRomFS(FileSys::VirtualFile& file) override;
|
ResultStatus ReadRomFS(FileSys::VirtualFile& file) override;
|
||||||
u64 ReadRomFSIVFCOffset() const override;
|
u64 ReadRomFSIVFCOffset() const override;
|
||||||
|
|
Reference in New Issue