deconstructed_rom_directory.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. // Copyright 2018 yuzu emulator team
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include "common/common_funcs.h"
  5. #include "common/common_paths.h"
  6. #include "common/file_util.h"
  7. #include "common/logging/log.h"
  8. #include "common/string_util.h"
  9. #include "core/hle/kernel/process.h"
  10. #include "core/hle/kernel/resource_limit.h"
  11. #include "core/loader/deconstructed_rom_directory.h"
  12. #include "core/loader/nso.h"
  13. #include "core/memory.h"
  14. namespace Loader {
  15. AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory(FileUtil::IOFile&& file,
  16. std::string filepath)
  17. : AppLoader(std::move(file)), filepath(std::move(filepath)) {}
  18. FileType AppLoader_DeconstructedRomDirectory::IdentifyType(FileUtil::IOFile& file,
  19. const std::string& filepath) {
  20. bool is_main_found{};
  21. bool is_rtld_found{};
  22. bool is_sdk_found{};
  23. const auto callback = [&](unsigned* num_entries_out, const std::string& directory,
  24. const std::string& virtual_name) -> bool {
  25. // Skip directories
  26. std::string physical_name = directory + virtual_name;
  27. if (FileUtil::IsDirectory(physical_name)) {
  28. return true;
  29. }
  30. // Verify filename
  31. if (Common::ToLower(virtual_name) == "main") {
  32. is_main_found = true;
  33. } else if (Common::ToLower(virtual_name) == "rtld") {
  34. is_rtld_found = true;
  35. } else if (Common::ToLower(virtual_name) == "sdk") {
  36. is_sdk_found = true;
  37. } else {
  38. // Contrinue searching
  39. return true;
  40. }
  41. // Verify file is an NSO
  42. FileUtil::IOFile file(physical_name, "rb");
  43. if (AppLoader_NSO::IdentifyType(file, physical_name) != FileType::NSO) {
  44. return false;
  45. }
  46. // We are done if we've found and verified all required NSOs
  47. return !(is_main_found && is_rtld_found && is_sdk_found);
  48. };
  49. // Search the directory recursively, looking for the required modules
  50. const std::string directory = filepath.substr(0, filepath.find_last_of("/\\")) + DIR_SEP;
  51. FileUtil::ForeachDirectoryEntry(nullptr, directory, callback);
  52. if (is_main_found && is_rtld_found && is_sdk_found) {
  53. return FileType::DeconstructedRomDirectory;
  54. }
  55. return FileType::Error;
  56. }
  57. ResultStatus AppLoader_DeconstructedRomDirectory::Load(
  58. Kernel::SharedPtr<Kernel::Process>& process) {
  59. if (is_loaded) {
  60. return ResultStatus::ErrorAlreadyLoaded;
  61. }
  62. if (!file.IsOpen()) {
  63. return ResultStatus::Error;
  64. }
  65. process = Kernel::Process::Create("main");
  66. // Load NSO modules
  67. VAddr next_load_addr{Memory::PROCESS_IMAGE_VADDR};
  68. for (const auto& module : {"rtld", "main", "subsdk0", "subsdk1", "subsdk2", "subsdk3",
  69. "subsdk4", "subsdk5", "subsdk6", "subsdk7", "sdk"}) {
  70. const std::string path =
  71. filepath.substr(0, filepath.find_last_of("/\\")) + DIR_SEP + module;
  72. const VAddr load_addr = next_load_addr;
  73. next_load_addr = AppLoader_NSO::LoadModule(path, load_addr);
  74. if (next_load_addr) {
  75. LOG_DEBUG(Loader, "loaded module %s @ 0x%llx", module, load_addr);
  76. } else {
  77. next_load_addr = load_addr;
  78. }
  79. }
  80. process->svc_access_mask.set();
  81. process->address_mappings = default_address_mappings;
  82. process->resource_limit =
  83. Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION);
  84. process->Run(Memory::PROCESS_IMAGE_VADDR, 48, Kernel::DEFAULT_STACK_SIZE);
  85. is_loaded = true;
  86. return ResultStatus::Success;
  87. }
  88. } // namespace Loader