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 00000000..7e6922e0 --- /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