diff options
Diffstat (limited to 'src/core')
| -rw-r--r-- | src/core/CMakeLists.txt | 44 | ||||
| -rw-r--r-- | src/core/file_sys/archive_savedata.cpp | 5 | ||||
| -rw-r--r-- | src/core/hle/kernel/kernel.cpp | 18 | ||||
| -rw-r--r-- | src/core/hle/kernel/kernel.h | 16 | ||||
| -rw-r--r-- | src/core/hle/kernel/process.cpp | 96 | ||||
| -rw-r--r-- | src/core/hle/kernel/process.h | 90 | ||||
| -rw-r--r-- | src/core/hle/kernel/thread.h | 2 | ||||
| -rw-r--r-- | src/core/loader/3dsx.cpp | 12 | ||||
| -rw-r--r-- | src/core/loader/3dsx.h | 8 | ||||
| -rw-r--r-- | src/core/loader/elf.cpp | 14 | ||||
| -rw-r--r-- | src/core/loader/elf.h | 8 | ||||
| -rw-r--r-- | src/core/loader/loader.cpp | 39 | ||||
| -rw-r--r-- | src/core/loader/loader.h | 8 | ||||
| -rw-r--r-- | src/core/loader/ncch.cpp | 24 | ||||
| -rw-r--r-- | src/core/loader/ncch.h | 36 | ||||
| -rw-r--r-- | src/core/mem_map.h | 2 | 
16 files changed, 319 insertions, 103 deletions
| diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index aaa6d87f3..ebedcb710 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -12,6 +12,8 @@ set(SRCS              arm/skyeye_common/vfp/vfpdouble.cpp              arm/skyeye_common/vfp/vfpinstr.cpp              arm/skyeye_common/vfp/vfpsingle.cpp +            core.cpp +            core_timing.cpp              file_sys/archive_backend.cpp              file_sys/archive_extsavedata.cpp              file_sys/archive_romfs.cpp @@ -21,15 +23,18 @@ set(SRCS              file_sys/archive_systemsavedata.cpp              file_sys/disk_archive.cpp              file_sys/ivfc_archive.cpp +            hle/config_mem.cpp +            hle/hle.cpp              hle/kernel/address_arbiter.cpp              hle/kernel/event.cpp              hle/kernel/kernel.cpp              hle/kernel/mutex.cpp +            hle/kernel/process.cpp              hle/kernel/semaphore.cpp              hle/kernel/session.cpp              hle/kernel/shared_memory.cpp -            hle/kernel/timer.cpp              hle/kernel/thread.cpp +            hle/kernel/timer.cpp              hle/service/ac_u.cpp              hle/service/act_u.cpp              hle/service/am_app.cpp @@ -56,10 +61,10 @@ set(SRCS              hle/service/fs/archive.cpp              hle/service/fs/fs_user.cpp              hle/service/gsp_gpu.cpp +            hle/service/gsp_lcd.cpp              hle/service/hid/hid.cpp -            hle/service/hid/hid_user.cpp              hle/service/hid/hid_spvr.cpp -            hle/service/gsp_lcd.cpp +            hle/service/hid/hid_user.cpp              hle/service/http_c.cpp              hle/service/ir/ir.cpp              hle/service/ir/ir_rst.cpp @@ -77,26 +82,22 @@ set(SRCS              hle/service/pm_app.cpp              hle/service/ptm/ptm.cpp              hle/service/ptm/ptm_play.cpp -            hle/service/ptm/ptm_u.cpp              hle/service/ptm/ptm_sysm.cpp +            hle/service/ptm/ptm_u.cpp              hle/service/service.cpp              hle/service/soc_u.cpp              hle/service/srv.cpp              hle/service/ssl_c.cpp              hle/service/y2r_u.cpp -            hle/config_mem.cpp -            hle/hle.cpp              hle/shared_page.cpp              hle/svc.cpp              hw/gpu.cpp              hw/hw.cpp              hw/lcd.cpp +            loader/3dsx.cpp              loader/elf.cpp              loader/loader.cpp              loader/ncch.cpp -            loader/3dsx.cpp -            core.cpp -            core_timing.cpp              mem_map.cpp              mem_map_funcs.cpp              settings.cpp @@ -104,6 +105,7 @@ set(SRCS              )  set(HEADERS +            arm/arm_interface.h              arm/disassembler/arm_disasm.h              arm/disassembler/load_symbol_map.h              arm/dyncom/arm_dyncom.h @@ -118,7 +120,8 @@ set(HEADERS              arm/skyeye_common/vfp/asm_vfp.h              arm/skyeye_common/vfp/vfp.h              arm/skyeye_common/vfp/vfp_helper.h -            arm/arm_interface.h +            core.h +            core_timing.h              file_sys/archive_backend.h              file_sys/archive_extsavedata.h              file_sys/archive_romfs.h @@ -126,19 +129,24 @@ set(HEADERS              file_sys/archive_savedatacheck.h              file_sys/archive_sdmc.h              file_sys/archive_systemsavedata.h +            file_sys/directory_backend.h              file_sys/disk_archive.h              file_sys/file_backend.h              file_sys/ivfc_archive.h -            file_sys/directory_backend.h +            hle/config_mem.h +            hle/function_wrappers.h +            hle/hle.h              hle/kernel/address_arbiter.h              hle/kernel/event.h              hle/kernel/kernel.h              hle/kernel/mutex.h +            hle/kernel/process.h              hle/kernel/semaphore.h              hle/kernel/session.h              hle/kernel/shared_memory.h -            hle/kernel/timer.h              hle/kernel/thread.h +            hle/kernel/timer.h +            hle/result.h              hle/service/ac_u.h              hle/service/act_u.h              hle/service/am_app.h @@ -165,10 +173,10 @@ set(HEADERS              hle/service/fs/archive.h              hle/service/fs/fs_user.h              hle/service/gsp_gpu.h +            hle/service/gsp_lcd.h              hle/service/hid/hid.h              hle/service/hid/hid_spvr.h              hle/service/hid/hid_user.h -            hle/service/gsp_lcd.h              hle/service/http_c.h              hle/service/ir/ir.h              hle/service/ir/ir_rst.h @@ -186,28 +194,22 @@ set(HEADERS              hle/service/pm_app.h              hle/service/ptm/ptm.h              hle/service/ptm/ptm_play.h -            hle/service/ptm/ptm_u.h              hle/service/ptm/ptm_sysm.h +            hle/service/ptm/ptm_u.h              hle/service/service.h              hle/service/soc_u.h              hle/service/srv.h              hle/service/ssl_c.h              hle/service/y2r_u.h -            hle/config_mem.h -            hle/result.h -            hle/function_wrappers.h -            hle/hle.h              hle/shared_page.h              hle/svc.h              hw/gpu.h              hw/hw.h              hw/lcd.h +            loader/3dsx.h              loader/elf.h              loader/loader.h              loader/ncch.h -            loader/3dsx.h -            core.h -            core_timing.h              mem_map.h              settings.h              system.h diff --git a/src/core/file_sys/archive_savedata.cpp b/src/core/file_sys/archive_savedata.cpp index 12624fa31..8dff51966 100644 --- a/src/core/file_sys/archive_savedata.cpp +++ b/src/core/file_sys/archive_savedata.cpp @@ -11,6 +11,7 @@  #include "core/file_sys/archive_savedata.h"  #include "core/file_sys/disk_archive.h" +#include "core/hle/kernel/process.h"  #include "core/hle/service/fs/archive.h"  #include "core/settings.h" @@ -36,7 +37,7 @@ ArchiveFactory_SaveData::ArchiveFactory_SaveData(const std::string& sdmc_directo  }  ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SaveData::Open(const Path& path) { -    std::string concrete_mount_point = GetSaveDataPath(mount_point, Kernel::g_program_id); +    std::string concrete_mount_point = GetSaveDataPath(mount_point, Kernel::g_current_process->program_id);      if (!FileUtil::Exists(concrete_mount_point)) {          // When a SaveData archive is created for the first time, it is not yet formatted          // and the save file/directory structure expected by the game has not yet been initialized. @@ -51,7 +52,7 @@ ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SaveData::Open(const P  }  ResultCode ArchiveFactory_SaveData::Format(const Path& path) { -    std::string concrete_mount_point = GetSaveDataPath(mount_point, Kernel::g_program_id); +    std::string concrete_mount_point = GetSaveDataPath(mount_point, Kernel::g_current_process->program_id);      FileUtil::DeleteDirRecursively(concrete_mount_point);      FileUtil::CreateFullPath(concrete_mount_point);      return RESULT_SUCCESS; diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 533fe65fd..a3715e555 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -10,15 +10,14 @@  #include "core/arm/arm_interface.h"  #include "core/core.h"  #include "core/hle/kernel/kernel.h" +#include "core/hle/kernel/process.h"  #include "core/hle/kernel/thread.h"  #include "core/hle/kernel/timer.h"  namespace Kernel {  unsigned int Object::next_object_id; -SharedPtr<Thread> g_main_thread;  HandleTable g_handle_table; -u64 g_program_id;  void WaitObject::AddWaitingThread(SharedPtr<Thread> thread) {      auto itr = std::find(waiting_threads.begin(), waiting_threads.end(), thread); @@ -140,8 +139,6 @@ void Init() {      Kernel::TimersInit();      Object::next_object_id = 0; -    g_program_id = 0; -    g_main_thread = nullptr;  }  /// Shutdown the kernel @@ -149,18 +146,7 @@ void Shutdown() {      Kernel::ThreadingShutdown();      Kernel::TimersShutdown();      g_handle_table.Clear(); // Free all kernel objects -} - -/** - * Loads executable stored at specified address - * @entry_point Entry point in memory of loaded executable - * @return True on success, otherwise false - */ -bool LoadExec(u32 entry_point) { -    // 0x30 is the typical main thread priority I've seen used so far -    g_main_thread = Kernel::SetupMainThread(Kernel::DEFAULT_STACK_SIZE, entry_point, THREADPRIO_DEFAULT); - -    return true; +    g_current_process = nullptr;  }  } // namespace diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index a7bc6b71a..7c106d37c 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -7,6 +7,7 @@  #include <boost/intrusive_ptr.hpp>  #include <array> +#include <memory>  #include <string>  #include <vector> @@ -15,6 +16,8 @@  #include "core/hle/hle.h"  #include "core/hle/result.h" +struct ApplicationInfo; +  namespace Kernel {  class Thread; @@ -270,23 +273,10 @@ private:  extern HandleTable g_handle_table; -/// The ID code of the currently running game -/// TODO(Subv): This variable should not be here,  -/// we need a way to store information about the currently loaded application  -/// for later query during runtime, maybe using the LDR service? -extern u64 g_program_id; -  /// Initialize the kernel  void Init();  /// Shutdown the kernel  void Shutdown(); -/** - * Loads executable stored at specified address - * @entry_point Entry point in memory of loaded executable - * @return True on success, otherwise false - */ -bool LoadExec(u32 entry_point); -  } // namespace diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp new file mode 100644 index 000000000..a444e22e5 --- /dev/null +++ b/src/core/hle/kernel/process.cpp @@ -0,0 +1,96 @@ +// Copyright 2015 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "common/assert.h" +#include "common/common_funcs.h" +#include "common/logging/log.h" + +#include "core/hle/kernel/process.h" +#include "core/hle/kernel/thread.h" +#include "core/mem_map.h" + +namespace Kernel { + +SharedPtr<Process> Process::Create(std::string name, u64 program_id) { +    SharedPtr<Process> process(new Process); + +    process->name = std::move(name); +    process->program_id = program_id; + +    process->flags.raw = 0; +    process->flags.memory_region = MemoryRegion::APPLICATION; + +    return process; +} + +void Process::ParseKernelCaps(const u32* kernel_caps, size_t len) { +    for (int i = 0; i < len; ++i) { +        u32 descriptor = kernel_caps[i]; +        u32 type = descriptor >> 20; + +        if (descriptor == 0xFFFFFFFF) { +            // Unused descriptor entry +            continue; +        } else if ((type & 0xF00) == 0xE00) { // 0x0FFF +            // Allowed interrupts list +            LOG_WARNING(Loader, "ExHeader allowed interrupts list ignored"); +        } else if ((type & 0xF80) == 0xF00) { // 0x07FF +            // Allowed syscalls mask +            unsigned int index = ((descriptor >> 24) & 7) * 24; +            u32 bits = descriptor & 0xFFFFFF; + +            while (bits && index < svc_access_mask.size()) { +                svc_access_mask.set(index, bits & 1); +                ++index; bits >>= 1; +            } +        } else if ((type & 0xFF0) == 0xFE0) { // 0x00FF +            // Handle table size +            handle_table_size = descriptor & 0x3FF; +        } else if ((type & 0xFF8) == 0xFF0) { // 0x007F +            // Misc. flags +            flags.raw = descriptor & 0xFFFF; +        } else if ((type & 0xFFE) == 0xFF8) { // 0x001F +            // Mapped memory range +            if (i+1 >= len || ((kernel_caps[i+1] >> 20) & 0xFFE) != 0xFF8) { +                LOG_WARNING(Loader, "Incomplete exheader memory range descriptor ignored."); +                continue; +            } +            u32 end_desc = kernel_caps[i+1]; +            ++i; // Skip over the second descriptor on the next iteration + +            AddressMapping mapping; +            mapping.address = descriptor << 12; +            mapping.size = (end_desc << 12) - mapping.address; +            mapping.writable = descriptor & BIT(20); +            mapping.unk_flag = end_desc & BIT(20); + +            address_mappings.push_back(mapping); +        } else if ((type & 0xFFF) == 0xFFE) { // 0x000F +            // Mapped memory page +            AddressMapping mapping; +            mapping.address = descriptor << 12; +            mapping.size = Memory::PAGE_SIZE; +            mapping.writable = true; // TODO: Not sure if correct +            mapping.unk_flag = false; +        } else if ((type & 0xFE0) == 0xFC0) { // 0x01FF +            // Kernel version +            int minor = descriptor & 0xFF; +            int major = (descriptor >> 8) & 0xFF; +            LOG_INFO(Loader, "ExHeader kernel version ignored: %d.%d", major, minor); +        } else { +            LOG_ERROR(Loader, "Unhandled kernel caps descriptor: 0x%08X", descriptor); +        } +    } +} + +void Process::Run(VAddr entry_point, s32 main_thread_priority, u32 stack_size) { +    Kernel::SetupMainThread(stack_size, entry_point, main_thread_priority); +} + +Kernel::Process::Process() {} +Kernel::Process::~Process() {} + +SharedPtr<Process> g_current_process; + +} diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h new file mode 100644 index 000000000..88ed9a5a5 --- /dev/null +++ b/src/core/hle/kernel/process.h @@ -0,0 +1,90 @@ +// Copyright 2015 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <bitset> + +#include <boost/container/static_vector.hpp> + +#include "common/bit_field.h" +#include "common/common_types.h" + +#include "core/hle/kernel/kernel.h" +#include "core/hle/result.h" + +namespace Kernel { + +struct AddressMapping { +    // Address and size must be page-aligned +    VAddr address; +    u32 size; +    bool writable; +    bool unk_flag; +}; + +enum class MemoryRegion : u16 { +    APPLICATION = 1, +    SYSTEM = 2, +    BASE = 3, +}; + +union ProcessFlags { +    u16 raw; + +    BitField< 0, 1, u16> allow_debug; ///< Allows other processes to attach to and debug this process. +    BitField< 1, 1, u16> force_debug; ///< Allows this process to attach to processes even if they don't have allow_debug set. +    BitField< 2, 1, u16> allow_nonalphanum; +    BitField< 3, 1, u16> shared_page_writable; ///< Shared page is mapped with write permissions. +    BitField< 4, 1, u16> privileged_priority; ///< Can use priority levels higher than 24. +    BitField< 5, 1, u16> allow_main_args; +    BitField< 6, 1, u16> shared_device_mem; +    BitField< 7, 1, u16> runnable_on_sleep; +    BitField< 8, 4, MemoryRegion> memory_region; ///< Default region for memory allocations for this process +    BitField<12, 1, u16> loaded_high; ///< Application loaded high (not at 0x00100000). +}; + +class Process final : public Object { +public: +    static SharedPtr<Process> Create(std::string name, u64 program_id); + +    std::string GetTypeName() const override { return "Process"; } +    std::string GetName() const override { return name; } + +    static const HandleType HANDLE_TYPE = HandleType::Process; +    HandleType GetHandleType() const override { return HANDLE_TYPE; } + +    /// Name of the process +    std::string name; +    /// Title ID corresponding to the process +    u64 program_id; + +    /// The process may only call SVCs which have the corresponding bit set. +    std::bitset<0x80> svc_access_mask; +    /// Maximum size of the handle table for the process. +    unsigned int handle_table_size = 0x200; +    /// Special memory ranges mapped into this processes address space. This is used to give +    /// processes access to specific I/O regions and device memory. +    boost::container::static_vector<AddressMapping, 8> address_mappings; +    ProcessFlags flags; + +    /** +     * Parses a list of kernel capability descriptors (as found in the ExHeader) and applies them +     * to this process. +     */ +    void ParseKernelCaps(const u32* kernel_caps, size_t len); + +    /** +     * Applies address space changes and launches the process main thread. +     */ +    void Run(VAddr entry_point, s32 main_thread_priority, u32 stack_size); + +private: +    Process(); +    ~Process() override; +}; + +extern SharedPtr<Process> g_current_process; + +} diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index 233bcbdbd..9958b16e6 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h @@ -171,8 +171,6 @@ private:      Handle callback_handle;  }; -extern SharedPtr<Thread> g_main_thread; -  /**   * Sets up the primary application thread   * @param stack_size The size of the thread's stack diff --git a/src/core/loader/3dsx.cpp b/src/core/loader/3dsx.cpp index 5d806c5d0..15527c5a6 100644 --- a/src/core/loader/3dsx.cpp +++ b/src/core/loader/3dsx.cpp @@ -8,9 +8,10 @@  #include "common/logging/log.h"  #include "core/file_sys/archive_romfs.h" +#include "core/hle/kernel/process.h" +#include "core/hle/service/fs/archive.h"  #include "core/loader/elf.h"  #include "core/loader/ncch.h" -#include "core/hle/service/fs/archive.h"  #include "core/mem_map.h"  #include "3dsx.h" @@ -229,8 +230,13 @@ ResultStatus AppLoader_THREEDSX::Load() {      if (!file->IsOpen())          return ResultStatus::Error; -    Load3DSXFile(*file, 0x00100000); -    Kernel::LoadExec(0x00100000); +    Kernel::g_current_process = Kernel::Process::Create(filename, 0); +    Kernel::g_current_process->svc_access_mask.set(); +    Kernel::g_current_process->address_mappings = default_address_mappings; + +    Load3DSXFile(*file, Memory::EXEFS_CODE_VADDR); + +    Kernel::g_current_process->Run(Memory::EXEFS_CODE_VADDR, 48, Kernel::DEFAULT_STACK_SIZE);      is_loaded = true;      return ResultStatus::Success; diff --git a/src/core/loader/3dsx.h b/src/core/loader/3dsx.h index a11667400..096b3ec20 100644 --- a/src/core/loader/3dsx.h +++ b/src/core/loader/3dsx.h @@ -4,6 +4,8 @@  #pragma once +#include <string> +  #include "common/common_types.h"  #include "core/loader/loader.h" @@ -15,7 +17,8 @@ namespace Loader {  /// Loads an 3DSX file  class AppLoader_THREEDSX final : public AppLoader {  public: -    AppLoader_THREEDSX(std::unique_ptr<FileUtil::IOFile>&& file) : AppLoader(std::move(file)) { } +    AppLoader_THREEDSX(std::unique_ptr<FileUtil::IOFile>&& file, std::string filename) +        : AppLoader(std::move(file)), filename(std::move(filename)) {}      /**       * Returns the type of the file @@ -29,6 +32,9 @@ public:       * @return ResultStatus result of function       */      ResultStatus Load() override; + +private: +    std::string filename;  };  } // namespace Loader diff --git a/src/core/loader/elf.cpp b/src/core/loader/elf.cpp index 467e91924..f86a98b8c 100644 --- a/src/core/loader/elf.cpp +++ b/src/core/loader/elf.cpp @@ -10,9 +10,9 @@  #include "common/logging/log.h"  #include "common/symbols.h" -#include "core/mem_map.h" -#include "core/loader/elf.h"  #include "core/hle/kernel/kernel.h" +#include "core/loader/elf.h" +#include "core/mem_map.h"  ////////////////////////////////////////////////////////////////////////////////////////////////////  // ELF Header Constants @@ -350,9 +350,15 @@ ResultStatus AppLoader_ELF::Load() {      if (file->ReadBytes(&buffer[0], size) != size)          return ResultStatus::Error; +    Kernel::g_current_process = Kernel::Process::Create(filename, 0); +    Kernel::g_current_process->svc_access_mask.set(); +    Kernel::g_current_process->address_mappings = default_address_mappings; +      ElfReader elf_reader(&buffer[0]); -    elf_reader.LoadInto(0x00100000); -    Kernel::LoadExec(elf_reader.GetEntryPoint()); +    elf_reader.LoadInto(Memory::EXEFS_CODE_VADDR); +    // TODO: Fill application title + +    Kernel::g_current_process->Run(elf_reader.GetEntryPoint(), 48, Kernel::DEFAULT_STACK_SIZE);      is_loaded = true;      return ResultStatus::Success; diff --git a/src/core/loader/elf.h b/src/core/loader/elf.h index b6e6651f5..32841606a 100644 --- a/src/core/loader/elf.h +++ b/src/core/loader/elf.h @@ -4,6 +4,8 @@  #pragma once +#include <string> +  #include "common/common_types.h"  #include "core/loader/loader.h" @@ -15,7 +17,8 @@ namespace Loader {  /// Loads an ELF/AXF file  class AppLoader_ELF final : public AppLoader {  public: -    AppLoader_ELF(std::unique_ptr<FileUtil::IOFile>&& file) : AppLoader(std::move(file)) { } +    AppLoader_ELF(std::unique_ptr<FileUtil::IOFile>&& file, std::string filename) +        : AppLoader(std::move(file)), filename(std::move(filename)) { }      /**       * Returns the type of the file @@ -29,6 +32,9 @@ public:       * @return ResultStatus result of function       */      ResultStatus Load() override; + +private: +    std::string filename;  };  } // namespace Loader diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp index de0ab540a..505e2d280 100644 --- a/src/core/loader/loader.cpp +++ b/src/core/loader/loader.cpp @@ -8,16 +8,23 @@  #include "common/make_unique.h"  #include "core/file_sys/archive_romfs.h" +#include "core/hle/kernel/process.h" +#include "core/hle/service/fs/archive.h"  #include "core/loader/3dsx.h"  #include "core/loader/elf.h"  #include "core/loader/ncch.h" -#include "core/hle/service/fs/archive.h"  #include "core/mem_map.h"  ////////////////////////////////////////////////////////////////////////////////////////////////////  namespace Loader { +const std::initializer_list<Kernel::AddressMapping> default_address_mappings = { +    { 0x1FF50000,   0x8000, true  }, // part of DSP RAM +    { 0x1FF70000,   0x8000, true  }, // part of DSP RAM +    { 0x1F000000, 0x600000, false }, // entire VRAM +}; +  /**   * Identifies the type of a bootable file   * @param file open file @@ -42,19 +49,11 @@ static FileType IdentifyFile(FileUtil::IOFile& file) {  /**   * Guess the type of a bootable file from its extension - * @param filename String filename of bootable file + * @param extension String extension of bootable file   * @return FileType of file   */ -static FileType GuessFromFilename(const std::string& filename) { -    if (filename.size() == 0) { -        LOG_ERROR(Loader, "invalid filename %s", filename.c_str()); -        return FileType::Error; -    } - -    size_t extension_loc = filename.find_last_of('.'); -    if (extension_loc == std::string::npos) -        return FileType::Unknown; -    std::string extension = Common::ToLower(filename.substr(extension_loc)); +static FileType GuessFromExtension(const std::string& extension_) { +    std::string extension = Common::ToLower(extension_);      if (extension == ".elf")          return FileType::ELF; @@ -100,8 +99,11 @@ ResultStatus LoadFile(const std::string& filename) {          return ResultStatus::Error;      } +    std::string filename_filename, filename_extension; +    Common::SplitPath(filename, nullptr, &filename_filename, &filename_extension); +      FileType type = IdentifyFile(*file); -    FileType filename_type = GuessFromFilename(filename); +    FileType filename_type = GuessFromExtension(filename_extension);      if (type != filename_type) {          LOG_WARNING(Loader, "File %s has a different type than its extension.", filename.c_str()); @@ -115,11 +117,11 @@ ResultStatus LoadFile(const std::string& filename) {      //3DSX file format...      case FileType::THREEDSX: -        return AppLoader_THREEDSX(std::move(file)).Load(); +        return AppLoader_THREEDSX(std::move(file), filename_filename).Load();      // Standard ELF file format...      case FileType::ELF: -        return AppLoader_ELF(std::move(file)).Load(); +        return AppLoader_ELF(std::move(file), filename_filename).Load();      // NCCH/NCSD container formats...      case FileType::CXI: @@ -129,7 +131,6 @@ ResultStatus LoadFile(const std::string& filename) {          // Load application and RomFS          if (ResultStatus::Success == app_loader.Load()) { -            Kernel::g_program_id = app_loader.GetProgramId();              Service::FS::RegisterArchiveType(Common::make_unique<FileSys::ArchiveFactory_RomFS>(app_loader), Service::FS::ArchiveIdCode::RomFS);              return ResultStatus::Success;          } @@ -139,11 +140,15 @@ ResultStatus LoadFile(const std::string& filename) {      // Raw BIN file format...      case FileType::BIN:      { +        Kernel::g_current_process = Kernel::Process::Create(filename_filename, 0); +        Kernel::g_current_process->svc_access_mask.set(); +        Kernel::g_current_process->address_mappings = default_address_mappings; +          size_t size = (size_t)file->GetSize();          if (file->ReadBytes(Memory::GetPointer(Memory::EXEFS_CODE_VADDR), size) != size)              return ResultStatus::Error; -        Kernel::LoadExec(Memory::EXEFS_CODE_VADDR); +        Kernel::g_current_process->Run(Memory::EXEFS_CODE_VADDR, 0x30, Kernel::DEFAULT_STACK_SIZE);          return ResultStatus::Success;      } diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h index 2b87239cf..a56f67205 100644 --- a/src/core/loader/loader.h +++ b/src/core/loader/loader.h @@ -9,6 +9,8 @@  #include "common/common_types.h"  #include "common/file_util.h" +#include "core/hle/kernel/process.h" +  ////////////////////////////////////////////////////////////////////////////////////////////////////  // Loader namespace @@ -105,6 +107,12 @@ protected:  };  /** + * Common address mappings found in most games, used for binary formats that don't have this + * information. + */ +extern const std::initializer_list<Kernel::AddressMapping> default_address_mappings; + +/**   * Identifies and loads a bootable file   * @param filename String filename of bootable file   * @return ResultStatus result of function diff --git a/src/core/loader/ncch.cpp b/src/core/loader/ncch.cpp index 9bce2b79d..0e2db2fbb 100644 --- a/src/core/loader/ncch.cpp +++ b/src/core/loader/ncch.cpp @@ -5,9 +5,12 @@  #include <memory>  #include "common/logging/log.h" +#include "common/make_unique.h" +#include "common/string_util.h" +#include "common/swap.h" -#include "core/loader/ncch.h"  #include "core/hle/kernel/kernel.h" +#include "core/loader/ncch.h"  #include "core/mem_map.h"  //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -117,8 +120,21 @@ ResultStatus AppLoader_NCCH::LoadExec() const {      std::vector<u8> code;      if (ResultStatus::Success == ReadCode(code)) { +        std::string process_name = Common::StringFromFixedZeroTerminatedBuffer( +                (const char*)exheader_header.codeset_info.name, 8); +        u64 program_id = *reinterpret_cast<u64_le const*>(&ncch_header.program_id[0]); +        Kernel::g_current_process = Kernel::Process::Create(process_name, program_id); + +        // Copy data while converting endianess +        std::array<u32, ARRAY_SIZE(exheader_header.arm11_kernel_caps.descriptors)> kernel_caps; +        std::copy_n(exheader_header.arm11_kernel_caps.descriptors, kernel_caps.size(), begin(kernel_caps)); +        Kernel::g_current_process->ParseKernelCaps(kernel_caps.data(), kernel_caps.size()); +          Memory::WriteBlock(entry_point, &code[0], code.size()); -        Kernel::LoadExec(entry_point); + +        s32 priority = exheader_header.arm11_system_local_caps.priority; +        u32 stack_size = exheader_header.codeset_info.stack_size; +        Kernel::g_current_process->Run(entry_point, priority, stack_size);          return ResultStatus::Success;      }      return ResultStatus::Error; @@ -277,8 +293,4 @@ ResultStatus AppLoader_NCCH::ReadRomFS(std::vector<u8>& buffer) const {      return ResultStatus::ErrorNotUsed;  } -u64 AppLoader_NCCH::GetProgramId() const { -    return *reinterpret_cast<u64 const*>(&ncch_header.program_id[0]); -} -  } // namespace Loader diff --git a/src/core/loader/ncch.h b/src/core/loader/ncch.h index 44c72a4e2..29e39d2c0 100644 --- a/src/core/loader/ncch.h +++ b/src/core/loader/ncch.h @@ -6,7 +6,9 @@  #include <memory> +#include "common/bit_field.h"  #include "common/common_types.h" +#include "common/swap.h"  #include "core/loader/loader.h" @@ -65,13 +67,13 @@ struct ExeFs_Header {  ////////////////////////////////////////////////////////////////////////////////////////////////////  // ExHeader (executable file system header) headers -struct ExHeader_SystemInfoFlags{ +struct ExHeader_SystemInfoFlags {      u8 reserved[5];      u8 flag;      u8 remaster_version[2];  }; -struct ExHeader_CodeSegmentInfo{ +struct ExHeader_CodeSegmentInfo {      u32 address;      u32 num_max_pages;      u32 code_size; @@ -88,17 +90,17 @@ struct ExHeader_CodeSetInfo {      u32 bss_size;  }; -struct ExHeader_DependencyList{ +struct ExHeader_DependencyList {      u8 program_id[0x30][8];  }; -struct ExHeader_SystemInfo{ +struct ExHeader_SystemInfo {      u64 save_data_size;      u8 jump_id[8];      u8 reserved_2[0x30];  }; -struct ExHeader_StorageInfo{ +struct ExHeader_StorageInfo {      u8 ext_save_data_id[8];      u8 system_save_data_id[8];      u8 reserved[8]; @@ -106,10 +108,16 @@ struct ExHeader_StorageInfo{      u8 other_attributes;  }; -struct ExHeader_ARM11_SystemLocalCaps{ +struct ExHeader_ARM11_SystemLocalCaps {      u8 program_id[8];      u32 core_version; -    u8 flags[3]; +    u8 reserved_flags[2]; +    union { +        u8 flags0; +        BitField<0, 2, u8> ideal_processor; +        BitField<2, 2, u8> affinity_mask; +        BitField<4, 4, u8> system_mode; +    };      u8 priority;      u8 resource_limit_descriptor[0x10][2];      ExHeader_StorageInfo storage_info; @@ -119,17 +127,17 @@ struct ExHeader_ARM11_SystemLocalCaps{      u8 resource_limit_category;  }; -struct ExHeader_ARM11_KernelCaps{ -    u8 descriptors[28][4]; +struct ExHeader_ARM11_KernelCaps { +    u32_le descriptors[28];      u8 reserved[0x10];  }; -struct ExHeader_ARM9_AccessControl{ +struct ExHeader_ARM9_AccessControl {      u8 descriptors[15];      u8 descversion;  }; -struct ExHeader_Header{ +struct ExHeader_Header {      ExHeader_CodeSetInfo codeset_info;      ExHeader_DependencyList dependency_list;      ExHeader_SystemInfo system_info; @@ -205,12 +213,6 @@ public:       */      ResultStatus ReadRomFS(std::vector<u8>& buffer) const override; -    /* -     * Gets the program id from the NCCH header -     * @return u64 Program id -     */ -    u64 GetProgramId() const; -  private:      /** diff --git a/src/core/mem_map.h b/src/core/mem_map.h index 1fb77c94a..fb582d65a 100644 --- a/src/core/mem_map.h +++ b/src/core/mem_map.h @@ -10,6 +10,8 @@ namespace Memory {  //////////////////////////////////////////////////////////////////////////////////////////////////// +const u32 PAGE_SIZE = 0x1000; +  enum : u32 {      BOOTROM_SIZE                = 0x00010000,   ///< Bootrom (super secret code/data @ 0x8000) size      BOOTROM_PADDR               = 0x00000000,   ///< Bootrom physical address | 
