file_sys: Handle patch applying failures
This changes ApplyCodePatch to return a ResultStatus, which makes it possible to determine whether patch applying has failed. Previously, only a boolean was returned, and false was returned when no patch was found OR when a patch was found but applying it failed. This also changes AppLoader_NCCH to return an error if patching fails because the executable is likely to be left in an inconsistent state and we should not proceed booting in that case.
This commit is contained in:
parent
1377be9902
commit
3140086c60
|
@ -507,20 +507,22 @@ Loader::ResultStatus NCCHContainer::LoadSectionExeFS(const char* name, std::vect
|
||||||
return Loader::ResultStatus::ErrorNotUsed;
|
return Loader::ResultStatus::ErrorNotUsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NCCHContainer::ApplyCodePatch(std::vector<u8>& code) const {
|
Loader::ResultStatus NCCHContainer::ApplyCodePatch(std::vector<u8>& code) const {
|
||||||
const std::string override_ips = filepath + ".exefsdir/code.ips";
|
const std::string override_ips = filepath + ".exefsdir/code.ips";
|
||||||
|
|
||||||
FileUtil::IOFile ips_file{override_ips, "rb"};
|
FileUtil::IOFile ips_file{override_ips, "rb"};
|
||||||
if (!ips_file)
|
if (!ips_file)
|
||||||
return false;
|
return Loader::ResultStatus::ErrorNotUsed;
|
||||||
|
|
||||||
std::vector<u8> ips(ips_file.GetSize());
|
std::vector<u8> ips(ips_file.GetSize());
|
||||||
if (ips_file.ReadBytes(ips.data(), ips.size()) != ips.size())
|
if (ips_file.ReadBytes(ips.data(), ips.size()) != ips.size())
|
||||||
return false;
|
return Loader::ResultStatus::Error;
|
||||||
|
|
||||||
LOG_INFO(Service_FS, "File {} patching code.bin", override_ips);
|
LOG_INFO(Service_FS, "File {} patching code.bin", override_ips);
|
||||||
Patch::ApplyIpsPatch(ips, code);
|
if (!Patch::ApplyIpsPatch(ips, code))
|
||||||
return true;
|
return Loader::ResultStatus::Error;
|
||||||
|
|
||||||
|
return Loader::ResultStatus::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
Loader::ResultStatus NCCHContainer::LoadOverrideExeFSSection(const char* name,
|
Loader::ResultStatus NCCHContainer::LoadOverrideExeFSSection(const char* name,
|
||||||
|
|
|
@ -274,9 +274,9 @@ public:
|
||||||
/**
|
/**
|
||||||
* Apply a patch for .code (if it exists).
|
* Apply a patch for .code (if it exists).
|
||||||
* This should only be called after allocating .bss.
|
* This should only be called after allocating .bss.
|
||||||
* @return bool true if a patch was applied, false otherwise
|
* @return ResultStatus success if a patch was applied, ErrorNotUsed if no patch was found
|
||||||
*/
|
*/
|
||||||
bool ApplyCodePatch(std::vector<u8>& code) const;
|
Loader::ResultStatus ApplyCodePatch(std::vector<u8>& code) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether the NCCH container contains an ExeFS
|
* Checks whether the NCCH container contains an ExeFS
|
||||||
|
|
|
@ -100,8 +100,10 @@ ResultStatus AppLoader_NCCH::LoadExec(std::shared_ptr<Kernel::Process>& process)
|
||||||
overlay_ncch->exheader_header.codeset_info.data.num_max_pages * Memory::PAGE_SIZE +
|
overlay_ncch->exheader_header.codeset_info.data.num_max_pages * Memory::PAGE_SIZE +
|
||||||
bss_page_size;
|
bss_page_size;
|
||||||
|
|
||||||
// Apply any IPS patch now that the entire codeset (including .bss) has been allocated
|
// Apply patches now that the entire codeset (including .bss) has been allocated
|
||||||
overlay_ncch->ApplyCodePatch(code);
|
const ResultStatus patch_result = overlay_ncch->ApplyCodePatch(code);
|
||||||
|
if (patch_result != ResultStatus::Success && patch_result != ResultStatus::ErrorNotUsed)
|
||||||
|
return patch_result;
|
||||||
|
|
||||||
codeset->entrypoint = codeset->CodeSegment().addr;
|
codeset->entrypoint = codeset->CodeSegment().addr;
|
||||||
codeset->memory = std::move(code);
|
codeset->memory = std::move(code);
|
||||||
|
|
Reference in New Issue