From 0aca202ae936d3fccbab34f36d9246e0598849a5 Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 16 Jun 2014 18:03:13 -0400 Subject: Loader: Moved elf and loader modules to a "loader" subdirectory. --- src/core/loader/loader.cpp | 205 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 205 insertions(+) create mode 100644 src/core/loader/loader.cpp (limited to 'src/core/loader/loader.cpp') diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp new file mode 100644 index 000000000..7e6922e0c --- /dev/null +++ b/src/core/loader/loader.cpp @@ -0,0 +1,205 @@ +// Copyright 2014 Citra Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#include "common/common_types.h" +#include "common/file_util.h" + +#include "core/loader/loader.h" +#include "core/loader/elf_reader.h" +#include "core/system.h" +#include "core/core.h" +#include "core/hle/kernel/kernel.h" +#include "core/mem_map.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/// Loads a CTR ELF file +bool Load_ELF(std::string &filename) { + std::string full_path = filename; + std::string path, file, extension; + SplitPath(ReplaceAll(full_path, "\\", "/"), &path, &file, &extension); +#if EMU_PLATFORM == PLATFORM_WINDOWS + path = ReplaceAll(path, "/", "\\"); +#endif + File::IOFile f(filename, "rb"); + + if (f.IsOpen()) { + u64 size = f.GetSize(); + u8* buffer = new u8[size]; + ElfReader* elf_reader = NULL; + + f.ReadBytes(buffer, size); + + elf_reader = new ElfReader(buffer); + elf_reader->LoadInto(0x00100000); + + Kernel::LoadExec(elf_reader->GetEntryPoint()); + + delete[] buffer; + delete elf_reader; + } else { + return false; + } + f.Close(); + + return true; +} + +/// Loads a CTR BIN file extracted from an ExeFS +bool Load_BIN(std::string &filename) { + std::string full_path = filename; + std::string path, file, extension; + SplitPath(ReplaceAll(full_path, "\\", "/"), &path, &file, &extension); +#if EMU_PLATFORM == PLATFORM_WINDOWS + path = ReplaceAll(path, "/", "\\"); +#endif + File::IOFile f(filename, "rb"); + + if (f.IsOpen()) { + u64 size = f.GetSize(); + u8* buffer = new u8[size]; + + f.ReadBytes(buffer, size); + + u32 entry_point = 0x00100000; // Hardcoded, read from exheader + + const u8 *src = buffer; + u8 *dst = Memory::GetPointer(entry_point); + u32 srcSize = size; + u32 *s = (u32*)src; + u32 *d = (u32*)dst; + for (int j = 0; j < (int)(srcSize + 3) / 4; j++) + { + *d++ = (*s++); + } + + Kernel::LoadExec(entry_point); + + delete[] buffer; + } + else { + return false; + } + f.Close(); + + return true; +} + +namespace Loader { + +bool IsBootableDirectory() { + ERROR_LOG(TIME, "Unimplemented function!"); + return true; +} + +/** + * Identifies the type of a bootable file + * @param filename String filename of bootable file + * @todo (ShizZy) this function sucks... make it actually check file contents etc. + * @return FileType of file + */ +FileType IdentifyFile(std::string &filename) { + if (filename.size() == 0) { + ERROR_LOG(LOADER, "invalid filename %s", filename.c_str()); + return FILETYPE_ERROR; + } + std::string extension = filename.size() >= 5 ? filename.substr(filename.size() - 4) : ""; + + if (File::IsDirectory(filename)) { + if (IsBootableDirectory()) { + return FILETYPE_DIRECTORY_CXI; + } + else { + return FILETYPE_NORMAL_DIRECTORY; + } + } + else if (!strcasecmp(extension.c_str(), ".elf")) { + return FILETYPE_CTR_ELF; // TODO(bunnei): Do some filetype checking :p + } + else if (!strcasecmp(extension.c_str(), ".axf")) { + return FILETYPE_CTR_ELF; // TODO(bunnei): Do some filetype checking :p + } + else if (!strcasecmp(extension.c_str(), ".cxi")) { + return FILETYPE_CTR_CXI; // TODO(bunnei): Do some filetype checking :p + } + else if (!strcasecmp(extension.c_str(), ".cci")) { + return FILETYPE_CTR_CCI; // TODO(bunnei): Do some filetype checking :p + } + else if (!strcasecmp(extension.c_str(), ".bin")) { + return FILETYPE_CTR_BIN; + } + else if (!strcasecmp(extension.c_str(), ".dat")) { + return FILETYPE_LAUNCHER_DAT; + } + else if (!strcasecmp(extension.c_str(), ".zip")) { + return FILETYPE_ARCHIVE_ZIP; + } + else if (!strcasecmp(extension.c_str(), ".rar")) { + return FILETYPE_ARCHIVE_RAR; + } + else if (!strcasecmp(extension.c_str(), ".r00")) { + return FILETYPE_ARCHIVE_RAR; + } + else if (!strcasecmp(extension.c_str(), ".r01")) { + return FILETYPE_ARCHIVE_RAR; + } + return FILETYPE_UNKNOWN; +} + +/** + * Identifies and loads a bootable file + * @param filename String filename of bootable file + * @param error_string Point to string to put error message if an error has occurred + * @return True on success, otherwise false + */ +bool LoadFile(std::string &filename, std::string *error_string) { + INFO_LOG(LOADER, "Identifying file..."); + + // Note that this can modify filename! + switch (IdentifyFile(filename)) { + + case FILETYPE_CTR_ELF: + return Load_ELF(filename); + + case FILETYPE_CTR_BIN: + return Load_BIN(filename); + + case FILETYPE_ERROR: + ERROR_LOG(LOADER, "Could not read file"); + *error_string = "Error reading file"; + break; + + case FILETYPE_ARCHIVE_RAR: +#ifdef WIN32 + *error_string = "RAR file detected (Require WINRAR)"; +#else + *error_string = "RAR file detected (Require UnRAR)"; +#endif + break; + + case FILETYPE_ARCHIVE_ZIP: +#ifdef WIN32 + *error_string = "ZIP file detected (Require WINRAR)"; +#else + *error_string = "ZIP file detected (Require UnRAR)"; +#endif + break; + + case FILETYPE_NORMAL_DIRECTORY: + ERROR_LOG(LOADER, "Just a directory."); + *error_string = "Just a directory."; + break; + + case FILETYPE_UNKNOWN_BIN: + case FILETYPE_UNKNOWN_ELF: + case FILETYPE_UNKNOWN: + default: + ERROR_LOG(LOADER, "Failed to identify file"); + *error_string = " Failed to identify file"; + break; + } + return false; +} + +} // namespace \ No newline at end of file -- cgit v1.2.3 From 3577dd027ddbaa2517eacad700ed0768a1f4b518 Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 16 Jun 2014 22:57:09 -0400 Subject: Loader: Added support for booting NCCH executables. NCCH: Fixed typo in printing NCCH filename. --- src/core/loader/loader.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/core/loader/loader.cpp') diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp index 7e6922e0c..41fa9c32e 100644 --- a/src/core/loader/loader.cpp +++ b/src/core/loader/loader.cpp @@ -7,6 +7,7 @@ #include "core/loader/loader.h" #include "core/loader/elf_reader.h" +#include "core/loader/ncch.h" #include "core/system.h" #include "core/core.h" #include "core/hle/kernel/kernel.h" @@ -165,6 +166,10 @@ bool LoadFile(std::string &filename, std::string *error_string) { case FILETYPE_CTR_BIN: return Load_BIN(filename); + case FILETYPE_CTR_CXI: + case FILETYPE_CTR_CCI: + return Loader::Load_NCCH(filename, error_string); + case FILETYPE_ERROR: ERROR_LOG(LOADER, "Could not read file"); *error_string = "Error reading file"; -- cgit v1.2.3 From 1da361c7ab55e1dbe6709a738e228bfab5a5bb78 Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 16 Jun 2014 23:05:10 -0400 Subject: Elf: Renamed modules to be consistent with new loader naming, fixed tabs -> spaces. --- src/core/loader/loader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/core/loader/loader.cpp') diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp index 41fa9c32e..d8060c0e6 100644 --- a/src/core/loader/loader.cpp +++ b/src/core/loader/loader.cpp @@ -6,7 +6,7 @@ #include "common/file_util.h" #include "core/loader/loader.h" -#include "core/loader/elf_reader.h" +#include "core/loader/elf.h" #include "core/loader/ncch.h" #include "core/system.h" #include "core/core.h" -- cgit v1.2.3 From 13bdaa6c609a8718d4ce6ca3ce5f1e16f4d7c600 Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 16 Jun 2014 23:18:10 -0400 Subject: Loader: Cleaned up and removed unused code, refactored ELF namespace. --- src/core/loader/loader.cpp | 142 +-------------------------------------------- 1 file changed, 3 insertions(+), 139 deletions(-) (limited to 'src/core/loader/loader.cpp') diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp index d8060c0e6..1a647d8a5 100644 --- a/src/core/loader/loader.cpp +++ b/src/core/loader/loader.cpp @@ -2,98 +2,14 @@ // Licensed under GPLv2 // Refer to the license.txt file included. -#include "common/common_types.h" -#include "common/file_util.h" - #include "core/loader/loader.h" #include "core/loader/elf.h" #include "core/loader/ncch.h" -#include "core/system.h" -#include "core/core.h" -#include "core/hle/kernel/kernel.h" -#include "core/mem_map.h" //////////////////////////////////////////////////////////////////////////////////////////////////// -/// Loads a CTR ELF file -bool Load_ELF(std::string &filename) { - std::string full_path = filename; - std::string path, file, extension; - SplitPath(ReplaceAll(full_path, "\\", "/"), &path, &file, &extension); -#if EMU_PLATFORM == PLATFORM_WINDOWS - path = ReplaceAll(path, "/", "\\"); -#endif - File::IOFile f(filename, "rb"); - - if (f.IsOpen()) { - u64 size = f.GetSize(); - u8* buffer = new u8[size]; - ElfReader* elf_reader = NULL; - - f.ReadBytes(buffer, size); - - elf_reader = new ElfReader(buffer); - elf_reader->LoadInto(0x00100000); - - Kernel::LoadExec(elf_reader->GetEntryPoint()); - - delete[] buffer; - delete elf_reader; - } else { - return false; - } - f.Close(); - - return true; -} - -/// Loads a CTR BIN file extracted from an ExeFS -bool Load_BIN(std::string &filename) { - std::string full_path = filename; - std::string path, file, extension; - SplitPath(ReplaceAll(full_path, "\\", "/"), &path, &file, &extension); -#if EMU_PLATFORM == PLATFORM_WINDOWS - path = ReplaceAll(path, "/", "\\"); -#endif - File::IOFile f(filename, "rb"); - - if (f.IsOpen()) { - u64 size = f.GetSize(); - u8* buffer = new u8[size]; - - f.ReadBytes(buffer, size); - - u32 entry_point = 0x00100000; // Hardcoded, read from exheader - - const u8 *src = buffer; - u8 *dst = Memory::GetPointer(entry_point); - u32 srcSize = size; - u32 *s = (u32*)src; - u32 *d = (u32*)dst; - for (int j = 0; j < (int)(srcSize + 3) / 4; j++) - { - *d++ = (*s++); - } - - Kernel::LoadExec(entry_point); - - delete[] buffer; - } - else { - return false; - } - f.Close(); - - return true; -} - namespace Loader { -bool IsBootableDirectory() { - ERROR_LOG(TIME, "Unimplemented function!"); - return true; -} - /** * Identifies the type of a bootable file * @param filename String filename of bootable file @@ -107,15 +23,7 @@ FileType IdentifyFile(std::string &filename) { } std::string extension = filename.size() >= 5 ? filename.substr(filename.size() - 4) : ""; - if (File::IsDirectory(filename)) { - if (IsBootableDirectory()) { - return FILETYPE_DIRECTORY_CXI; - } - else { - return FILETYPE_NORMAL_DIRECTORY; - } - } - else if (!strcasecmp(extension.c_str(), ".elf")) { + if (!strcasecmp(extension.c_str(), ".elf")) { return FILETYPE_CTR_ELF; // TODO(bunnei): Do some filetype checking :p } else if (!strcasecmp(extension.c_str(), ".axf")) { @@ -127,24 +35,6 @@ FileType IdentifyFile(std::string &filename) { else if (!strcasecmp(extension.c_str(), ".cci")) { return FILETYPE_CTR_CCI; // TODO(bunnei): Do some filetype checking :p } - else if (!strcasecmp(extension.c_str(), ".bin")) { - return FILETYPE_CTR_BIN; - } - else if (!strcasecmp(extension.c_str(), ".dat")) { - return FILETYPE_LAUNCHER_DAT; - } - else if (!strcasecmp(extension.c_str(), ".zip")) { - return FILETYPE_ARCHIVE_ZIP; - } - else if (!strcasecmp(extension.c_str(), ".rar")) { - return FILETYPE_ARCHIVE_RAR; - } - else if (!strcasecmp(extension.c_str(), ".r00")) { - return FILETYPE_ARCHIVE_RAR; - } - else if (!strcasecmp(extension.c_str(), ".r01")) { - return FILETYPE_ARCHIVE_RAR; - } return FILETYPE_UNKNOWN; } @@ -161,10 +51,7 @@ bool LoadFile(std::string &filename, std::string *error_string) { switch (IdentifyFile(filename)) { case FILETYPE_CTR_ELF: - return Load_ELF(filename); - - case FILETYPE_CTR_BIN: - return Load_BIN(filename); + return Loader::Load_ELF(filename, error_string); case FILETYPE_CTR_CXI: case FILETYPE_CTR_CCI: @@ -175,29 +62,6 @@ bool LoadFile(std::string &filename, std::string *error_string) { *error_string = "Error reading file"; break; - case FILETYPE_ARCHIVE_RAR: -#ifdef WIN32 - *error_string = "RAR file detected (Require WINRAR)"; -#else - *error_string = "RAR file detected (Require UnRAR)"; -#endif - break; - - case FILETYPE_ARCHIVE_ZIP: -#ifdef WIN32 - *error_string = "ZIP file detected (Require WINRAR)"; -#else - *error_string = "ZIP file detected (Require UnRAR)"; -#endif - break; - - case FILETYPE_NORMAL_DIRECTORY: - ERROR_LOG(LOADER, "Just a directory."); - *error_string = "Just a directory."; - break; - - case FILETYPE_UNKNOWN_BIN: - case FILETYPE_UNKNOWN_ELF: case FILETYPE_UNKNOWN: default: ERROR_LOG(LOADER, "Failed to identify file"); @@ -207,4 +71,4 @@ bool LoadFile(std::string &filename, std::string *error_string) { return false; } -} // namespace \ No newline at end of file +} // namespace Loader -- cgit v1.2.3 From 7889cafc76ac99b8509fa3cd1558a09f8a7e5f91 Mon Sep 17 00:00:00 2001 From: bunnei Date: Wed, 18 Jun 2014 18:58:09 -0400 Subject: Loader: Implemented AppLoader interface for abstracting application loading. - Various cleanups/refactorings to Loader, ELF, and NCCH modules. - Added AppLoader interface to ELF and NCCH. - Updated Qt/GLFW frontends to check AppLoader ResultStatus. NCCH: Removed extra qualification typos. Loader: Removed unnecessary #include's. NCCH: Improved readability of memcmp statements. NCCH: Added missing space. Elf: Removed unnecessary usage of unique_ptr. Loader: Removed unnecessary usage of unique_ptr. --- src/core/loader/loader.cpp | 55 ++++++++++++++++++++++++---------------------- 1 file changed, 29 insertions(+), 26 deletions(-) (limited to 'src/core/loader/loader.cpp') diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp index 1a647d8a5..dd0863ff3 100644 --- a/src/core/loader/loader.cpp +++ b/src/core/loader/loader.cpp @@ -2,6 +2,8 @@ // Licensed under GPLv2 // Refer to the license.txt file included. +#include + #include "core/loader/loader.h" #include "core/loader/elf.h" #include "core/loader/ncch.h" @@ -16,59 +18,60 @@ namespace Loader { * @todo (ShizZy) this function sucks... make it actually check file contents etc. * @return FileType of file */ -FileType IdentifyFile(std::string &filename) { +const FileType IdentifyFile(const std::string &filename) { if (filename.size() == 0) { ERROR_LOG(LOADER, "invalid filename %s", filename.c_str()); - return FILETYPE_ERROR; + return FileType::Error; } std::string extension = filename.size() >= 5 ? filename.substr(filename.size() - 4) : ""; if (!strcasecmp(extension.c_str(), ".elf")) { - return FILETYPE_CTR_ELF; // TODO(bunnei): Do some filetype checking :p + return FileType::ELF; // TODO(bunnei): Do some filetype checking :p } else if (!strcasecmp(extension.c_str(), ".axf")) { - return FILETYPE_CTR_ELF; // TODO(bunnei): Do some filetype checking :p + return FileType::ELF; // TODO(bunnei): Do some filetype checking :p } else if (!strcasecmp(extension.c_str(), ".cxi")) { - return FILETYPE_CTR_CXI; // TODO(bunnei): Do some filetype checking :p + return FileType::CXI; // TODO(bunnei): Do some filetype checking :p } else if (!strcasecmp(extension.c_str(), ".cci")) { - return FILETYPE_CTR_CCI; // TODO(bunnei): Do some filetype checking :p + return FileType::CCI; // TODO(bunnei): Do some filetype checking :p } - return FILETYPE_UNKNOWN; + return FileType::Unknown; } /** * Identifies and loads a bootable file * @param filename String filename of bootable file - * @param error_string Point to string to put error message if an error has occurred - * @return True on success, otherwise false + * @return ResultStatus result of function */ -bool LoadFile(std::string &filename, std::string *error_string) { - INFO_LOG(LOADER, "Identifying file..."); +const ResultStatus LoadFile(std::string& filename) { + INFO_LOG(LOADER, "Loading file %s...", filename.c_str()); - // Note that this can modify filename! switch (IdentifyFile(filename)) { - case FILETYPE_CTR_ELF: - return Loader::Load_ELF(filename, error_string); + // Standard ELF file format... + case FileType::ELF: { + return AppLoader_ELF(filename).Load(); + } - case FILETYPE_CTR_CXI: - case FILETYPE_CTR_CCI: - return Loader::Load_NCCH(filename, error_string); + // NCCH/NCSD container formats... + case FileType::CXI: + case FileType::CCI: { + return AppLoader_NCCH(filename).Load(); + } - case FILETYPE_ERROR: - ERROR_LOG(LOADER, "Could not read file"); - *error_string = "Error reading file"; - break; + // Error occurred durring IdentifyFile... + case FileType::Error: + + // IdentifyFile could know identify file type... + case FileType::Unknown: - case FILETYPE_UNKNOWN: default: - ERROR_LOG(LOADER, "Failed to identify file"); - *error_string = " Failed to identify file"; - break; + return ResultStatus::ErrorInvalidFormat; } - return false; + + return ResultStatus::Error; } } // namespace Loader -- cgit v1.2.3 From 62b444cd17c17e6f8009d87609b620bcb51b43bd Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 19 Jun 2014 17:46:05 -0400 Subject: Loader: Refactored use of const. --- src/core/loader/loader.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/core/loader/loader.cpp') diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp index dd0863ff3..96cb81de0 100644 --- a/src/core/loader/loader.cpp +++ b/src/core/loader/loader.cpp @@ -18,7 +18,7 @@ namespace Loader { * @todo (ShizZy) this function sucks... make it actually check file contents etc. * @return FileType of file */ -const FileType IdentifyFile(const std::string &filename) { +FileType IdentifyFile(const std::string &filename) { if (filename.size() == 0) { ERROR_LOG(LOADER, "invalid filename %s", filename.c_str()); return FileType::Error; @@ -45,7 +45,7 @@ const FileType IdentifyFile(const std::string &filename) { * @param filename String filename of bootable file * @return ResultStatus result of function */ -const ResultStatus LoadFile(std::string& filename) { +ResultStatus LoadFile(const std::string& filename) { INFO_LOG(LOADER, "Loading file %s...", filename.c_str()); switch (IdentifyFile(filename)) { -- cgit v1.2.3