summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Zach Hilman2018-10-29 21:58:11 -0400
committerGravatar Zach Hilman2018-11-15 12:48:09 -0500
commit6cd504feb921b442ab079bd2be638180e3e61c04 (patch)
tree557a5efd7249ecbe54c47dd661724c5f54ac75d8 /src
parentprocess: Make MirrorMemory take state to map new memory as (diff)
downloadyuzu-6cd504feb921b442ab079bd2be638180e3e61c04.tar.gz
yuzu-6cd504feb921b442ab079bd2be638180e3e61c04.tar.xz
yuzu-6cd504feb921b442ab079bd2be638180e3e61c04.zip
ldr_ro: Fully implement LoadNrr (command 2)
Includes parameter error checking, hash enforcement, initialization check, and max NRR load check.
Diffstat (limited to 'src')
-rw-r--r--src/core/hle/service/ldr/ldr.cpp112
1 files changed, 112 insertions, 0 deletions
diff --git a/src/core/hle/service/ldr/ldr.cpp b/src/core/hle/service/ldr/ldr.cpp
index d607d985e..7804913fa 100644
--- a/src/core/hle/service/ldr/ldr.cpp
+++ b/src/core/hle/service/ldr/ldr.cpp
@@ -13,6 +13,36 @@
13 13
14namespace Service::LDR { 14namespace Service::LDR {
15 15
16namespace ErrCodes {
17enum {
18 InvalidNRO = 52,
19 InvalidNRR = 53,
20 MissingNRRHash = 54,
21 MaximumNRO = 55,
22 MaximumNRR = 56,
23 AlreadyLoaded = 57,
24 InvalidAlignment = 81,
25 InvalidSize = 82,
26 InvalidNROAddress = 84,
27 InvalidNRRAddress = 85,
28 NotInitialized = 87,
29};
30}
31
32constexpr ResultCode ERROR_INVALID_NRO(ErrorModule::Loader, ErrCodes::InvalidNRO);
33constexpr ResultCode ERROR_INVALID_NRR(ErrorModule::Loader, ErrCodes::InvalidNRR);
34constexpr ResultCode ERROR_MISSING_NRR_HASH(ErrorModule::Loader, ErrCodes::MissingNRRHash);
35constexpr ResultCode ERROR_MAXIMUM_NRO(ErrorModule::Loader, ErrCodes::MaximumNRO);
36constexpr ResultCode ERROR_MAXIMUM_NRR(ErrorModule::Loader, ErrCodes::MaximumNRR);
37constexpr ResultCode ERROR_ALREADY_LOADED(ErrorModule::Loader, ErrCodes::AlreadyLoaded);
38constexpr ResultCode ERROR_INVALID_ALIGNMENT(ErrorModule::Loader, ErrCodes::InvalidAlignment);
39constexpr ResultCode ERROR_INVALID_SIZE(ErrorModule::Loader, ErrCodes::InvalidSize);
40constexpr ResultCode ERROR_INVALID_NRO_ADDRESS(ErrorModule::Loader, ErrCodes::InvalidNROAddress);
41constexpr ResultCode ERROR_INVALID_NRR_ADDRESS(ErrorModule::Loader, ErrCodes::InvalidNRRAddress);
42constexpr ResultCode ERROR_NOT_INITIALIZED(ErrorModule::Loader, ErrCodes::NotInitialized);
43
44constexpr u64 MAXIMUM_LOADED_RO = 0x40;
45
16class DebugMonitor final : public ServiceFramework<DebugMonitor> { 46class DebugMonitor final : public ServiceFramework<DebugMonitor> {
17public: 47public:
18 explicit DebugMonitor() : ServiceFramework{"ldr:dmnt"} { 48 explicit DebugMonitor() : ServiceFramework{"ldr:dmnt"} {
@@ -75,6 +105,88 @@ public:
75 } 105 }
76 106
77 void LoadNrr(Kernel::HLERequestContext& ctx) { 107 void LoadNrr(Kernel::HLERequestContext& ctx) {
108 IPC::RequestParser rp{ctx};
109 rp.Skip(2, false);
110 const VAddr nrr_addr{rp.Pop<VAddr>()};
111 const u64 nrr_size{rp.Pop<u64>()};
112
113 if (!initialized) {
114 LOG_ERROR(Service_LDR, "LDR:RO not initialized before use!");
115 IPC::ResponseBuilder rb{ctx, 2};
116 rb.Push(ERROR_NOT_INITIALIZED);
117 return;
118 }
119
120 if (nro.size() >= MAXIMUM_LOADED_RO) {
121 LOG_ERROR(Service_LDR, "Loading new NRR would exceed the maximum number of loaded NRRs "
122 "(0x40)! Failing...");
123 IPC::ResponseBuilder rb{ctx, 2};
124 rb.Push(ERROR_MAXIMUM_NRR);
125 return;
126 }
127
128 // NRR Address does not fall on 0x1000 byte boundary
129 if ((nrr_addr & 0xFFF) != 0) {
130 LOG_ERROR(Service_LDR, "NRR Address has invalid alignment (actual {:016X})!", nrr_addr);
131 IPC::ResponseBuilder rb{ctx, 2};
132 rb.Push(ERROR_INVALID_ALIGNMENT);
133 return;
134 }
135
136 // NRR Size is zero or causes overflow
137 if (nrr_addr + nrr_size <= nrr_addr || nrr_size == 0 || (nrr_size & 0xFFF) != 0) {
138 LOG_ERROR(Service_LDR, "NRR Size is invalid! (nrr_address={:016X}, nrr_size={:016X})",
139 nrr_addr, nrr_size);
140 IPC::ResponseBuilder rb{ctx, 2};
141 rb.Push(ERROR_INVALID_SIZE);
142 return;
143 }
144 // Read NRR data from memory
145 std::vector<u8> nrr_data(nrr_size);
146 Memory::ReadBlock(nrr_addr, nrr_data.data(), nrr_size);
147 NRRHeader header;
148 std::memcpy(&header, nrr_data.data(), sizeof(NRRHeader));
149
150 if (header.magic != Common::MakeMagic('N', 'R', 'R', '0')) {
151 LOG_ERROR(Service_LDR, "NRR did not have magic 'NRR0' (actual {:08X})!", header.magic);
152 IPC::ResponseBuilder rb{ctx, 2};
153 rb.Push(ERROR_INVALID_NRR);
154 return;
155 }
156
157 if (header.size != nrr_size) {
158 LOG_ERROR(Service_LDR,
159 "NRR header reported size did not match LoadNrr parameter size! "
160 "(header_size={:016X}, loadnrr_size={:016X})",
161 header.size, nrr_size);
162 IPC::ResponseBuilder rb{ctx, 2};
163 rb.Push(ERROR_INVALID_SIZE);
164 return;
165 }
166
167 if (Core::CurrentProcess()->GetTitleID() != header.title_id) {
168 LOG_ERROR(Service_LDR,
169 "Attempting to load NRR with title ID other than current process. (actual "
170 "{:016X})!",
171 header.title_id);
172 IPC::ResponseBuilder rb{ctx, 2};
173 rb.Push(ERROR_INVALID_NRR);
174 return;
175 }
176
177 std::vector<SHA256Hash> hashes;
178 for (std::size_t i = header.hash_offset;
179 i < (header.hash_offset + (header.hash_count << 5)); i += 8) {
180 hashes.emplace_back();
181 std::memcpy(hashes.back().data(), nrr_data.data() + i, sizeof(SHA256Hash));
182 }
183
184 nrr.insert_or_assign(nrr_addr, std::move(hashes));
185
186 IPC::ResponseBuilder rb{ctx, 2};
187 rb.Push(RESULT_SUCCESS);
188 }
189
78 IPC::ResponseBuilder rb{ctx, 2}; 190 IPC::ResponseBuilder rb{ctx, 2};
79 rb.Push(RESULT_SUCCESS); 191 rb.Push(RESULT_SUCCESS);
80 LOG_WARNING(Service_LDR, "(STUBBED) called"); 192 LOG_WARNING(Service_LDR, "(STUBBED) called");