summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Zach Hilman2018-10-29 22:03:59 -0400
committerGravatar Zach Hilman2018-11-15 12:48:09 -0500
commit5e8e7b60196c5974716952de132a333b5fe81561 (patch)
treed89fb47b566fa4ed969965354639f5962fbc0917 /src
parentldr_ro: Fully implement LoadNrr (command 2) (diff)
downloadyuzu-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.cpp86
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
262private:
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
232void InstallInterfaces(SM::ServiceManager& sm) { 314void InstallInterfaces(SM::ServiceManager& sm) {