diff options
author | Liam <byteslice@airmail.cc> | 2023-08-18 04:03:47 +0200 |
---|---|---|
committer | Liam <byteslice@airmail.cc> | 2023-08-18 04:03:47 +0200 |
commit | 8be3a041e099487b7fc3a55993e97657a981b634 (patch) | |
tree | 26492e55d911eafea368684dc931b361ce0830ff /src/core/file_sys/card_image.cpp | |
parent | Merge pull request #10989 from comex/epipe (diff) | |
download | yuzu-8be3a041e099487b7fc3a55993e97657a981b634.tar yuzu-8be3a041e099487b7fc3a55993e97657a981b634.tar.gz yuzu-8be3a041e099487b7fc3a55993e97657a981b634.tar.bz2 yuzu-8be3a041e099487b7fc3a55993e97657a981b634.tar.lz yuzu-8be3a041e099487b7fc3a55993e97657a981b634.tar.xz yuzu-8be3a041e099487b7fc3a55993e97657a981b634.tar.zst yuzu-8be3a041e099487b7fc3a55993e97657a981b634.zip |
Diffstat (limited to 'src/core/file_sys/card_image.cpp')
-rw-r--r-- | src/core/file_sys/card_image.cpp | 48 |
1 files changed, 41 insertions, 7 deletions
diff --git a/src/core/file_sys/card_image.cpp b/src/core/file_sys/card_image.cpp index 5d02865f4..3e667e74a 100644 --- a/src/core/file_sys/card_image.cpp +++ b/src/core/file_sys/card_image.cpp @@ -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}, partitions(partition_names.size()), partitions_raw(partition_names.size()), keys{Core::Crypto::KeyManager::Instance()} { - if (file->ReadObject(&header) != sizeof(GamecardHeader)) { - status = Loader::ResultStatus::ErrorBadXCIHeader; - return; - } - - if (header.magic != Common::MakeMagic('H', 'E', 'A', 'D')) { - status = Loader::ResultStatus::ErrorBadXCIHeader; + const auto header_status = TryReadHeader(); + if (header_status != Loader::ResultStatus::Success) { + status = header_status; return; } @@ -316,6 +312,44 @@ Loader::ResultStatus XCI::AddNCAFromPartition(XCIPartition part) { 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() { return GetLogoPartition() == nullptr ? 0x1 : 0x2; } |