file_sys/card_image: support dumps with prepended key area
This commit is contained in:
		| @@ -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; | ||||
| } | ||||
|   | ||||
| @@ -128,6 +128,7 @@ public: | ||||
|  | ||||
| private: | ||||
|     Loader::ResultStatus AddNCAFromPartition(XCIPartition part); | ||||
|     Loader::ResultStatus TryReadHeader(); | ||||
|  | ||||
|     VirtualFile file; | ||||
|     GamecardHeader header{}; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Liam
					Liam