Merge pull request #11309 from liamwhite/full-xci

file_sys/card_image: support dumps with prepended key area
This commit is contained in:
liamwhite 2023-08-21 16:09:22 -04:00 committed by GitHub
commit 9d6ac28999
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 42 additions and 7 deletions

View file

@ -31,13 +31,9 @@ XCI::XCI(VirtualFile file_, u64 program_id, size_t program_index)
: file(std::move(file_)), program_nca_status{Loader::ResultStatus::ErrorXCIMissingProgramNCA}, : file(std::move(file_)), program_nca_status{Loader::ResultStatus::ErrorXCIMissingProgramNCA},
partitions(partition_names.size()), partitions(partition_names.size()),
partitions_raw(partition_names.size()), keys{Core::Crypto::KeyManager::Instance()} { partitions_raw(partition_names.size()), keys{Core::Crypto::KeyManager::Instance()} {
if (file->ReadObject(&header) != sizeof(GamecardHeader)) { const auto header_status = TryReadHeader();
status = Loader::ResultStatus::ErrorBadXCIHeader; if (header_status != Loader::ResultStatus::Success) {
return; status = header_status;
}
if (header.magic != Common::MakeMagic('H', 'E', 'A', 'D')) {
status = Loader::ResultStatus::ErrorBadXCIHeader;
return; return;
} }
@ -316,6 +312,44 @@ Loader::ResultStatus XCI::AddNCAFromPartition(XCIPartition part) {
return Loader::ResultStatus::Success; return Loader::ResultStatus::Success;
} }
Loader::ResultStatus XCI::TryReadHeader() {
constexpr size_t CardInitialDataRegionSize = 0x1000;
// Define the function we'll use to determine if we read a valid header.
const auto ReadCardHeader = [&]() {
// Ensure we can read the entire header. If we can't, we can't read the card image.
if (file->ReadObject(&header) != sizeof(GamecardHeader)) {
return Loader::ResultStatus::ErrorBadXCIHeader;
}
// Ensure the header magic matches. If it doesn't, this isn't a card image header.
if (header.magic != Common::MakeMagic('H', 'E', 'A', 'D')) {
return Loader::ResultStatus::ErrorBadXCIHeader;
}
// We read a card image header.
return Loader::ResultStatus::Success;
};
// Try to read the header directly.
if (ReadCardHeader() == Loader::ResultStatus::Success) {
return Loader::ResultStatus::Success;
}
// Get the size of the file.
const size_t card_image_size = file->GetSize();
// If we are large enough to have a key area, offset past the key area and retry.
if (card_image_size >= CardInitialDataRegionSize) {
file = std::make_shared<OffsetVfsFile>(file, card_image_size - CardInitialDataRegionSize,
CardInitialDataRegionSize);
return ReadCardHeader();
}
// We had no header and aren't large enough to have a key area, so this can't be parsed.
return Loader::ResultStatus::ErrorBadXCIHeader;
}
u8 XCI::GetFormatVersion() { u8 XCI::GetFormatVersion() {
return GetLogoPartition() == nullptr ? 0x1 : 0x2; return GetLogoPartition() == nullptr ? 0x1 : 0x2;
} }

View file

@ -128,6 +128,7 @@ public:
private: private:
Loader::ResultStatus AddNCAFromPartition(XCIPartition part); Loader::ResultStatus AddNCAFromPartition(XCIPartition part);
Loader::ResultStatus TryReadHeader();
VirtualFile file; VirtualFile file;
GamecardHeader header{}; GamecardHeader header{};