diff options
| author | 2018-10-29 22:03:59 -0400 | |
|---|---|---|
| committer | 2018-11-15 12:48:09 -0500 | |
| commit | 5e8e7b60196c5974716952de132a333b5fe81561 (patch) | |
| tree | d89fb47b566fa4ed969965354639f5962fbc0917 /src | |
| parent | ldr_ro: Fully implement LoadNrr (command 2) (diff) | |
| download | yuzu-5e8e7b60196c5974716952de132a333b5fe81561.tar.gz yuzu-5e8e7b60196c5974716952de132a333b5fe81561.tar.xz yuzu-5e8e7b60196c5974716952de132a333b5fe81561.zip | |
ldr_ro: Implement UnloadNrr (command 3)
Includes initialization check, proper address check, alignment check, and actual unloading of a loaded NRR.
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/hle/service/ldr/ldr.cpp | 86 |
1 files changed, 84 insertions, 2 deletions
diff --git a/src/core/hle/service/ldr/ldr.cpp b/src/core/hle/service/ldr/ldr.cpp index 7804913fa..252c66831 100644 --- a/src/core/hle/service/ldr/ldr.cpp +++ b/src/core/hle/service/ldr/ldr.cpp | |||
| @@ -4,7 +4,9 @@ | |||
| 4 | 4 | ||
| 5 | #include <memory> | 5 | #include <memory> |
| 6 | #include <fmt/format.h> | 6 | #include <fmt/format.h> |
| 7 | #include <mbedtls/sha256.h> | ||
| 7 | 8 | ||
| 9 | #include "common/hex_util.h" | ||
| 8 | #include "core/hle/ipc_helpers.h" | 10 | #include "core/hle/ipc_helpers.h" |
| 9 | #include "core/hle/kernel/process.h" | 11 | #include "core/hle/kernel/process.h" |
| 10 | #include "core/hle/service/ldr/ldr.h" | 12 | #include "core/hle/service/ldr/ldr.h" |
| @@ -94,7 +96,7 @@ public: | |||
| 94 | // clang-format off | 96 | // clang-format off |
| 95 | static const FunctionInfo functions[] = { | 97 | static const FunctionInfo functions[] = { |
| 96 | {0, &RelocatableObject::LoadNro, "LoadNro"}, | 98 | {0, &RelocatableObject::LoadNro, "LoadNro"}, |
| 97 | {1, nullptr, "UnloadNro"}, | 99 | {1, &RelocatableObject::UnloadNro, "UnloadNro"}, |
| 98 | {2, &RelocatableObject::LoadNrr, "LoadNrr"}, | 100 | {2, &RelocatableObject::LoadNrr, "LoadNrr"}, |
| 99 | {3, nullptr, "UnloadNrr"}, | 101 | {3, nullptr, "UnloadNrr"}, |
| 100 | {4, &RelocatableObject::Initialize, "Initialize"}, | 102 | {4, &RelocatableObject::Initialize, "Initialize"}, |
| @@ -187,9 +189,38 @@ public: | |||
| 187 | rb.Push(RESULT_SUCCESS); | 189 | rb.Push(RESULT_SUCCESS); |
| 188 | } | 190 | } |
| 189 | 191 | ||
| 192 | void UnloadNrr(Kernel::HLERequestContext& ctx) { | ||
| 193 | if (!initialized) { | ||
| 194 | LOG_ERROR(Service_LDR, "LDR:RO not initialized before use!"); | ||
| 195 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 196 | rb.Push(ERROR_NOT_INITIALIZED); | ||
| 197 | return; | ||
| 198 | } | ||
| 199 | |||
| 200 | IPC::RequestParser rp{ctx}; | ||
| 201 | rp.Skip(2, false); | ||
| 202 | const auto nrr_addr{rp.Pop<VAddr>()}; | ||
| 203 | |||
| 204 | if ((nrr_addr & 0xFFF) != 0) { | ||
| 205 | LOG_ERROR(Service_LDR, "NRR Address has invalid alignment (actual {:016X})!", nrr_addr); | ||
| 206 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 207 | rb.Push(ERROR_INVALID_ALIGNMENT); | ||
| 208 | return; | ||
| 209 | } | ||
| 210 | |||
| 211 | const auto iter = nrr.find(nrr_addr); | ||
| 212 | if (iter == nrr.end()) { | ||
| 213 | LOG_ERROR(Service_LDR, | ||
| 214 | "Attempting to unload NRR which has not been loaded! (addr={:016X})", | ||
| 215 | nrr_addr); | ||
| 216 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 217 | rb.Push(ERROR_INVALID_NRR_ADDRESS); | ||
| 218 | return; | ||
| 219 | } | ||
| 220 | |||
| 221 | nrr.erase(iter); | ||
| 190 | IPC::ResponseBuilder rb{ctx, 2}; | 222 | IPC::ResponseBuilder rb{ctx, 2}; |
| 191 | rb.Push(RESULT_SUCCESS); | 223 | rb.Push(RESULT_SUCCESS); |
| 192 | LOG_WARNING(Service_LDR, "(STUBBED) called"); | ||
| 193 | } | 224 | } |
| 194 | 225 | ||
| 195 | void LoadNro(Kernel::HLERequestContext& ctx) { | 226 | void LoadNro(Kernel::HLERequestContext& ctx) { |
| @@ -227,6 +258,57 @@ public: | |||
| 227 | rb.Push(RESULT_SUCCESS); | 258 | rb.Push(RESULT_SUCCESS); |
| 228 | LOG_WARNING(Service_LDR, "(STUBBED) called"); | 259 | LOG_WARNING(Service_LDR, "(STUBBED) called"); |
| 229 | } | 260 | } |
| 261 | |||
| 262 | private: | ||
| 263 | using SHA256Hash = std::array<u8, 0x20>; | ||
| 264 | |||
| 265 | struct NROHeader { | ||
| 266 | u32_le entrypoint_insn; | ||
| 267 | u32_le mod_offset; | ||
| 268 | INSERT_PADDING_WORDS(2); | ||
| 269 | u32_le magic; | ||
| 270 | INSERT_PADDING_WORDS(1); | ||
| 271 | u32_le nro_size; | ||
| 272 | INSERT_PADDING_WORDS(1); | ||
| 273 | u32_le text_offset; | ||
| 274 | u32_le text_size; | ||
| 275 | u32_le ro_offset; | ||
| 276 | u32_le ro_size; | ||
| 277 | u32_le rw_offset; | ||
| 278 | u32_le rw_size; | ||
| 279 | u32_le bss_size; | ||
| 280 | INSERT_PADDING_WORDS(1); | ||
| 281 | std::array<u8, 0x20> build_id; | ||
| 282 | INSERT_PADDING_BYTES(0x20); | ||
| 283 | }; | ||
| 284 | static_assert(sizeof(NROHeader) == 0x80, "NROHeader has invalid size."); | ||
| 285 | |||
| 286 | struct NRRHeader { | ||
| 287 | u32_le magic; | ||
| 288 | INSERT_PADDING_BYTES(0x1C); | ||
| 289 | u64_le title_id_mask; | ||
| 290 | u64_le title_id_pattern; | ||
| 291 | std::array<u8, 0x100> modulus; | ||
| 292 | std::array<u8, 0x100> signature_1; | ||
| 293 | std::array<u8, 0x100> signature_2; | ||
| 294 | u64_le title_id; | ||
| 295 | u32_le size; | ||
| 296 | INSERT_PADDING_BYTES(4); | ||
| 297 | u32_le hash_offset; | ||
| 298 | u32_le hash_count; | ||
| 299 | INSERT_PADDING_BYTES(8); | ||
| 300 | }; | ||
| 301 | static_assert(sizeof(NRRHeader) == 0x350, "NRRHeader has incorrect size."); | ||
| 302 | |||
| 303 | struct NROInfo { | ||
| 304 | SHA256Hash hash; | ||
| 305 | u64 size; | ||
| 306 | }; | ||
| 307 | |||
| 308 | bool initialized = false; | ||
| 309 | |||
| 310 | std::map<VAddr, NROInfo> nro; | ||
| 311 | std::map<VAddr, std::vector<SHA256Hash>> nrr; | ||
| 230 | }; | 312 | }; |
| 231 | 313 | ||
| 232 | void InstallInterfaces(SM::ServiceManager& sm) { | 314 | void InstallInterfaces(SM::ServiceManager& sm) { |