diff options
| author | 2015-01-20 12:55:28 -0500 | |
|---|---|---|
| committer | 2015-01-20 12:55:28 -0500 | |
| commit | 205170fa623efdd5eafb0c957d728babe4836f45 (patch) | |
| tree | 26dd9e4c7ae9cc7a3bb09f42c942c4e47c9cc06f /src/core/loader/loader.cpp | |
| parent | Merge pull request #496 from lioncash/warn (diff) | |
| parent | Loader: Clean up the ELF AppLoader. (diff) | |
| download | yuzu-205170fa623efdd5eafb0c957d728babe4836f45.tar.gz yuzu-205170fa623efdd5eafb0c957d728babe4836f45.tar.xz yuzu-205170fa623efdd5eafb0c957d728babe4836f45.zip | |
Merge pull request #241 from linkmauve/better-loader
Improve the loader a bit
Diffstat (limited to 'src/core/loader/loader.cpp')
| -rw-r--r-- | src/core/loader/loader.cpp | 110 |
1 files changed, 77 insertions, 33 deletions
diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp index 45cf425df..60460292d 100644 --- a/src/core/loader/loader.cpp +++ b/src/core/loader/loader.cpp | |||
| @@ -19,11 +19,32 @@ namespace Loader { | |||
| 19 | 19 | ||
| 20 | /** | 20 | /** |
| 21 | * Identifies the type of a bootable file | 21 | * Identifies the type of a bootable file |
| 22 | * @param file open file | ||
| 23 | * @return FileType of file | ||
| 24 | */ | ||
| 25 | static FileType IdentifyFile(FileUtil::IOFile& file) { | ||
| 26 | FileType type; | ||
| 27 | |||
| 28 | #define CHECK_TYPE(loader) \ | ||
| 29 | type = AppLoader_##loader::IdentifyType(file); \ | ||
| 30 | if (FileType::Error != type) \ | ||
| 31 | return type; | ||
| 32 | |||
| 33 | CHECK_TYPE(THREEDSX) | ||
| 34 | CHECK_TYPE(ELF) | ||
| 35 | CHECK_TYPE(NCCH) | ||
| 36 | |||
| 37 | #undef CHECK_TYPE | ||
| 38 | |||
| 39 | return FileType::Unknown; | ||
| 40 | } | ||
| 41 | |||
| 42 | /** | ||
| 43 | * Guess the type of a bootable file from its extension | ||
| 22 | * @param filename String filename of bootable file | 44 | * @param filename String filename of bootable file |
| 23 | * @todo (ShizZy) this function sucks... make it actually check file contents etc. | ||
| 24 | * @return FileType of file | 45 | * @return FileType of file |
| 25 | */ | 46 | */ |
| 26 | FileType IdentifyFile(const std::string &filename) { | 47 | static FileType GuessFromFilename(const std::string& filename) { |
| 27 | if (filename.size() == 0) { | 48 | if (filename.size() == 0) { |
| 28 | LOG_ERROR(Loader, "invalid filename %s", filename.c_str()); | 49 | LOG_ERROR(Loader, "invalid filename %s", filename.c_str()); |
| 29 | return FileType::Error; | 50 | return FileType::Error; |
| @@ -34,47 +55,74 @@ FileType IdentifyFile(const std::string &filename) { | |||
| 34 | return FileType::Unknown; | 55 | return FileType::Unknown; |
| 35 | std::string extension = Common::ToLower(filename.substr(extension_loc)); | 56 | std::string extension = Common::ToLower(filename.substr(extension_loc)); |
| 36 | 57 | ||
| 37 | // TODO(bunnei): Do actual filetype checking instead of naively checking the extension | 58 | if (extension == ".elf") |
| 38 | if (extension == ".elf") { | ||
| 39 | return FileType::ELF; | 59 | return FileType::ELF; |
| 40 | } else if (extension == ".axf") { | 60 | else if (extension == ".axf") |
| 41 | return FileType::ELF; | 61 | return FileType::ELF; |
| 42 | } else if (extension == ".cxi") { | 62 | else if (extension == ".cxi") |
| 43 | return FileType::CXI; | 63 | return FileType::CXI; |
| 44 | } else if (extension == ".cci") { | 64 | else if (extension == ".cci") |
| 45 | return FileType::CCI; | 65 | return FileType::CCI; |
| 46 | } else if (extension == ".bin") { | 66 | else if (extension == ".bin") |
| 47 | return FileType::BIN; | 67 | return FileType::BIN; |
| 48 | } else if (extension == ".3ds") { | 68 | else if (extension == ".3ds") |
| 49 | return FileType::CCI; | 69 | return FileType::CCI; |
| 50 | } else if (extension == ".3dsx") { | 70 | else if (extension == ".3dsx") |
| 51 | return FileType::THREEDSX; | 71 | return FileType::THREEDSX; |
| 52 | } | ||
| 53 | return FileType::Unknown; | 72 | return FileType::Unknown; |
| 54 | } | 73 | } |
| 55 | 74 | ||
| 56 | /** | 75 | static const char* GetFileTypeString(FileType type) { |
| 57 | * Identifies and loads a bootable file | 76 | switch (type) { |
| 58 | * @param filename String filename of bootable file | 77 | case FileType::CCI: |
| 59 | * @return ResultStatus result of function | 78 | return "NCSD"; |
| 60 | */ | 79 | case FileType::CXI: |
| 80 | return "NCCH"; | ||
| 81 | case FileType::ELF: | ||
| 82 | return "ELF"; | ||
| 83 | case FileType::THREEDSX: | ||
| 84 | return "3DSX"; | ||
| 85 | case FileType::BIN: | ||
| 86 | return "raw"; | ||
| 87 | case FileType::Error: | ||
| 88 | case FileType::Unknown: | ||
| 89 | return "unknown"; | ||
| 90 | } | ||
| 91 | } | ||
| 92 | |||
| 61 | ResultStatus LoadFile(const std::string& filename) { | 93 | ResultStatus LoadFile(const std::string& filename) { |
| 62 | LOG_INFO(Loader, "Loading file %s...", filename.c_str()); | 94 | std::unique_ptr<FileUtil::IOFile> file(new FileUtil::IOFile(filename, "rb")); |
| 95 | if (!file->IsOpen()) { | ||
| 96 | LOG_ERROR(Loader, "Failed to load file %s", filename.c_str()); | ||
| 97 | return ResultStatus::Error; | ||
| 98 | } | ||
| 99 | |||
| 100 | FileType type = IdentifyFile(*file); | ||
| 101 | FileType filename_type = GuessFromFilename(filename); | ||
| 102 | |||
| 103 | if (type != filename_type) { | ||
| 104 | LOG_WARNING(Loader, "File %s has a different type than its extension.", filename.c_str()); | ||
| 105 | if (FileType::Unknown == type) | ||
| 106 | type = filename_type; | ||
| 107 | } | ||
| 63 | 108 | ||
| 64 | switch (IdentifyFile(filename)) { | 109 | LOG_INFO(Loader, "Loading file %s as %s...", filename.c_str(), GetFileTypeString(type)); |
| 110 | |||
| 111 | switch (type) { | ||
| 65 | 112 | ||
| 66 | //3DSX file format... | 113 | //3DSX file format... |
| 67 | case FileType::THREEDSX: | 114 | case FileType::THREEDSX: |
| 68 | return AppLoader_THREEDSX(filename).Load(); | 115 | return AppLoader_THREEDSX(std::move(file)).Load(); |
| 69 | 116 | ||
| 70 | // Standard ELF file format... | 117 | // Standard ELF file format... |
| 71 | case FileType::ELF: | 118 | case FileType::ELF: |
| 72 | return AppLoader_ELF(filename).Load(); | 119 | return AppLoader_ELF(std::move(file)).Load(); |
| 73 | 120 | ||
| 74 | // NCCH/NCSD container formats... | 121 | // NCCH/NCSD container formats... |
| 75 | case FileType::CXI: | 122 | case FileType::CXI: |
| 76 | case FileType::CCI: { | 123 | case FileType::CCI: |
| 77 | AppLoader_NCCH app_loader(filename); | 124 | { |
| 125 | AppLoader_NCCH app_loader(std::move(file)); | ||
| 78 | 126 | ||
| 79 | // Load application and RomFS | 127 | // Load application and RomFS |
| 80 | if (ResultStatus::Success == app_loader.Load()) { | 128 | if (ResultStatus::Success == app_loader.Load()) { |
| @@ -88,16 +136,11 @@ ResultStatus LoadFile(const std::string& filename) { | |||
| 88 | // Raw BIN file format... | 136 | // Raw BIN file format... |
| 89 | case FileType::BIN: | 137 | case FileType::BIN: |
| 90 | { | 138 | { |
| 91 | LOG_INFO(Loader, "Loading BIN file %s...", filename.c_str()); | 139 | size_t size = (size_t)file->GetSize(); |
| 92 | 140 | if (file->ReadBytes(Memory::GetPointer(Memory::EXEFS_CODE_VADDR), size) != size) | |
| 93 | FileUtil::IOFile file(filename, "rb"); | ||
| 94 | |||
| 95 | if (file.IsOpen()) { | ||
| 96 | file.ReadBytes(Memory::GetPointer(Memory::EXEFS_CODE_VADDR), (size_t)file.GetSize()); | ||
| 97 | Kernel::LoadExec(Memory::EXEFS_CODE_VADDR); | ||
| 98 | } else { | ||
| 99 | return ResultStatus::Error; | 141 | return ResultStatus::Error; |
| 100 | } | 142 | |
| 143 | Kernel::LoadExec(Memory::EXEFS_CODE_VADDR); | ||
| 101 | return ResultStatus::Success; | 144 | return ResultStatus::Success; |
| 102 | } | 145 | } |
| 103 | 146 | ||
| @@ -106,10 +149,11 @@ ResultStatus LoadFile(const std::string& filename) { | |||
| 106 | 149 | ||
| 107 | // IdentifyFile could know identify file type... | 150 | // IdentifyFile could know identify file type... |
| 108 | case FileType::Unknown: | 151 | case FileType::Unknown: |
| 109 | 152 | { | |
| 110 | default: | 153 | LOG_CRITICAL(Loader, "File %s is of unknown type."); |
| 111 | return ResultStatus::ErrorInvalidFormat; | 154 | return ResultStatus::ErrorInvalidFormat; |
| 112 | } | 155 | } |
| 156 | } | ||
| 113 | return ResultStatus::Error; | 157 | return ResultStatus::Error; |
| 114 | } | 158 | } |
| 115 | 159 | ||