diff options
| author | bunnei <bunneidev@gmail.com> | 2018-10-23 18:52:01 -0400 | 
|---|---|---|
| committer | bunnei <bunneidev@gmail.com> | 2018-10-25 18:03:54 -0400 | 
| commit | cebce2a93adb1c24c3ff14c62f9c052d93886707 (patch) | |
| tree | e9bfa2d0d7a1fa0ade7ad8c0c34bba7068e6fe9f /src/core/hle | |
| parent | c2049aa4e5e7a77b0f1988e7082921b2e5083fa6 (diff) | |
ldr: Partially implement LoadNro.
- This is an incomplete implementation. It was tested with Super Mario Party.
Diffstat (limited to 'src/core/hle')
| -rw-r--r-- | src/core/hle/service/ldr/ldr.cpp | 52 | 
1 files changed, 49 insertions, 3 deletions
| diff --git a/src/core/hle/service/ldr/ldr.cpp b/src/core/hle/service/ldr/ldr.cpp index ec32faf15..d607d985e 100644 --- a/src/core/hle/service/ldr/ldr.cpp +++ b/src/core/hle/service/ldr/ldr.cpp @@ -3,9 +3,13 @@  // Refer to the license.txt file included.  #include <memory> +#include <fmt/format.h> +#include "core/hle/ipc_helpers.h" +#include "core/hle/kernel/process.h"  #include "core/hle/service/ldr/ldr.h"  #include "core/hle/service/service.h" +#include "core/loader/nro.h"  namespace Service::LDR { @@ -59,16 +63,58 @@ public:      explicit RelocatableObject() : ServiceFramework{"ldr:ro"} {          // clang-format off          static const FunctionInfo functions[] = { -            {0, nullptr, "LoadNro"}, +            {0, &RelocatableObject::LoadNro, "LoadNro"},              {1, nullptr, "UnloadNro"}, -            {2, nullptr, "LoadNrr"}, +            {2, &RelocatableObject::LoadNrr, "LoadNrr"},              {3, nullptr, "UnloadNrr"}, -            {4, nullptr, "Initialize"}, +            {4, &RelocatableObject::Initialize, "Initialize"},          };          // clang-format on          RegisterHandlers(functions);      } + +    void LoadNrr(Kernel::HLERequestContext& ctx) { +        IPC::ResponseBuilder rb{ctx, 2}; +        rb.Push(RESULT_SUCCESS); +        LOG_WARNING(Service_LDR, "(STUBBED) called"); +    } + +    void LoadNro(Kernel::HLERequestContext& ctx) { +        IPC::RequestParser rp{ctx}; +        rp.Skip(2, false); +        const VAddr nro_addr{rp.Pop<VAddr>()}; +        const u64 nro_size{rp.Pop<u64>()}; +        const VAddr bss_addr{rp.Pop<VAddr>()}; +        const u64 bss_size{rp.Pop<u64>()}; + +        // Read NRO data from memory +        std::vector<u8> nro_data(nro_size); +        Memory::ReadBlock(nro_addr, nro_data.data(), nro_size); + +        // Load NRO as new executable module +        const VAddr addr{*Core::CurrentProcess()->VMManager().FindFreeRegion(nro_size + bss_size)}; +        Loader::AppLoader_NRO::LoadNro(nro_data, fmt::format("nro-{:08x}", addr), addr); + +        // TODO(bunnei): This is an incomplete implementation. It was tested with Super Mario Party. +        // It is currently missing: +        // - Signature checks with LoadNRR +        // - Checking if a module has already been loaded +        // - Using/validating BSS, etc. params (these are used from NRO header instead) +        // - Error checking +        // - ...Probably other things + +        IPC::ResponseBuilder rb{ctx, 4}; +        rb.Push(RESULT_SUCCESS); +        rb.Push(addr); +        LOG_WARNING(Service_LDR, "(STUBBED) called"); +    } + +    void Initialize(Kernel::HLERequestContext& ctx) { +        IPC::ResponseBuilder rb{ctx, 2}; +        rb.Push(RESULT_SUCCESS); +        LOG_WARNING(Service_LDR, "(STUBBED) called"); +    }  };  void InstallInterfaces(SM::ServiceManager& sm) { | 
