diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/file_sys/program_metadata.cpp | 52 | ||||
| -rw-r--r-- | src/core/file_sys/program_metadata.h | 14 |
2 files changed, 51 insertions, 15 deletions
diff --git a/src/core/file_sys/program_metadata.cpp b/src/core/file_sys/program_metadata.cpp index 4e46c24cf..484d4baea 100644 --- a/src/core/file_sys/program_metadata.cpp +++ b/src/core/file_sys/program_metadata.cpp | |||
| @@ -34,11 +34,55 @@ Loader::ResultStatus ProgramMetadata::Load(VirtualFile file) { | |||
| 34 | return Loader::ResultStatus::ErrorBadACIHeader; | 34 | return Loader::ResultStatus::ErrorBadACIHeader; |
| 35 | } | 35 | } |
| 36 | 36 | ||
| 37 | if (sizeof(FileAccessControl) != file->ReadObject(&acid_file_access, acid_header.fac_offset)) { | 37 | // Load acid_file_access per-component instead of the entire struct, since this struct does not |
| 38 | // reflect the layout of the real data. | ||
| 39 | std::size_t current_offset = acid_header.fac_offset; | ||
| 40 | if (sizeof(FileAccessControl::version) != file->ReadBytes(&acid_file_access.version, | ||
| 41 | sizeof(FileAccessControl::version), | ||
| 42 | current_offset)) { | ||
| 43 | return Loader::ResultStatus::ErrorBadFileAccessControl; | ||
| 44 | } | ||
| 45 | if (sizeof(FileAccessControl::permissions) != | ||
| 46 | file->ReadBytes(&acid_file_access.permissions, sizeof(FileAccessControl::permissions), | ||
| 47 | current_offset += sizeof(FileAccessControl::version) + 3)) { | ||
| 48 | return Loader::ResultStatus::ErrorBadFileAccessControl; | ||
| 49 | } | ||
| 50 | if (sizeof(FileAccessControl::unknown) != | ||
| 51 | file->ReadBytes(&acid_file_access.unknown, sizeof(FileAccessControl::unknown), | ||
| 52 | current_offset + sizeof(FileAccessControl::permissions))) { | ||
| 38 | return Loader::ResultStatus::ErrorBadFileAccessControl; | 53 | return Loader::ResultStatus::ErrorBadFileAccessControl; |
| 39 | } | 54 | } |
| 40 | 55 | ||
| 41 | if (sizeof(FileAccessHeader) != file->ReadObject(&aci_file_access, aci_header.fah_offset)) { | 56 | // Load aci_file_access per-component instead of the entire struct, same as acid_file_access |
| 57 | current_offset = aci_header.fah_offset; | ||
| 58 | if (sizeof(FileAccessHeader::version) != file->ReadBytes(&aci_file_access.version, | ||
| 59 | sizeof(FileAccessHeader::version), | ||
| 60 | current_offset)) { | ||
| 61 | return Loader::ResultStatus::ErrorBadFileAccessHeader; | ||
| 62 | } | ||
| 63 | if (sizeof(FileAccessHeader::permissions) != | ||
| 64 | file->ReadBytes(&aci_file_access.permissions, sizeof(FileAccessHeader::permissions), | ||
| 65 | current_offset += sizeof(FileAccessHeader::version) + 3)) { | ||
| 66 | return Loader::ResultStatus::ErrorBadFileAccessHeader; | ||
| 67 | } | ||
| 68 | if (sizeof(FileAccessHeader::unk_offset) != | ||
| 69 | file->ReadBytes(&aci_file_access.unk_offset, sizeof(FileAccessHeader::unk_offset), | ||
| 70 | current_offset += sizeof(FileAccessHeader::permissions))) { | ||
| 71 | return Loader::ResultStatus::ErrorBadFileAccessHeader; | ||
| 72 | } | ||
| 73 | if (sizeof(FileAccessHeader::unk_size) != | ||
| 74 | file->ReadBytes(&aci_file_access.unk_size, sizeof(FileAccessHeader::unk_size), | ||
| 75 | current_offset += sizeof(FileAccessHeader::unk_offset))) { | ||
| 76 | return Loader::ResultStatus::ErrorBadFileAccessHeader; | ||
| 77 | } | ||
| 78 | if (sizeof(FileAccessHeader::unk_offset_2) != | ||
| 79 | file->ReadBytes(&aci_file_access.unk_offset_2, sizeof(FileAccessHeader::unk_offset_2), | ||
| 80 | current_offset += sizeof(FileAccessHeader::unk_size))) { | ||
| 81 | return Loader::ResultStatus::ErrorBadFileAccessHeader; | ||
| 82 | } | ||
| 83 | if (sizeof(FileAccessHeader::unk_size_2) != | ||
| 84 | file->ReadBytes(&aci_file_access.unk_size_2, sizeof(FileAccessHeader::unk_size_2), | ||
| 85 | current_offset + sizeof(FileAccessHeader::unk_offset_2))) { | ||
| 42 | return Loader::ResultStatus::ErrorBadFileAccessHeader; | 86 | return Loader::ResultStatus::ErrorBadFileAccessHeader; |
| 43 | } | 87 | } |
| 44 | 88 | ||
| @@ -153,9 +197,7 @@ void ProgramMetadata::Print() const { | |||
| 153 | LOG_DEBUG(Service_FS, " > Is Retail: {}", acid_header.is_retail ? "YES" : "NO"); | 197 | LOG_DEBUG(Service_FS, " > Is Retail: {}", acid_header.is_retail ? "YES" : "NO"); |
| 154 | LOG_DEBUG(Service_FS, "Title ID Min: 0x{:016X}", acid_header.title_id_min); | 198 | LOG_DEBUG(Service_FS, "Title ID Min: 0x{:016X}", acid_header.title_id_min); |
| 155 | LOG_DEBUG(Service_FS, "Title ID Max: 0x{:016X}", acid_header.title_id_max); | 199 | LOG_DEBUG(Service_FS, "Title ID Max: 0x{:016X}", acid_header.title_id_max); |
| 156 | u64_le permissions_l; // local copy to fix alignment error | 200 | LOG_DEBUG(Service_FS, "Filesystem Access: 0x{:016X}\n", acid_file_access.permissions); |
| 157 | std::memcpy(&permissions_l, &acid_file_access.permissions, sizeof(permissions_l)); | ||
| 158 | LOG_DEBUG(Service_FS, "Filesystem Access: 0x{:016X}\n", permissions_l); | ||
| 159 | 201 | ||
| 160 | // Begin ACI0 printing (actual perms, unsigned) | 202 | // Begin ACI0 printing (actual perms, unsigned) |
| 161 | LOG_DEBUG(Service_FS, "Magic: {:.4}", aci_header.magic.data()); | 203 | LOG_DEBUG(Service_FS, "Magic: {:.4}", aci_header.magic.data()); |
diff --git a/src/core/file_sys/program_metadata.h b/src/core/file_sys/program_metadata.h index 1eee916be..c89a1c445 100644 --- a/src/core/file_sys/program_metadata.h +++ b/src/core/file_sys/program_metadata.h | |||
| @@ -143,20 +143,18 @@ private: | |||
| 143 | 143 | ||
| 144 | static_assert(sizeof(AciHeader) == 0x40, "ACI0 header structure size is wrong"); | 144 | static_assert(sizeof(AciHeader) == 0x40, "ACI0 header structure size is wrong"); |
| 145 | 145 | ||
| 146 | #pragma pack(push, 1) | 146 | // FileAccessControl and FileAccessHeader need loaded per-component: this layout does not |
| 147 | 147 | // reflect the real layout to avoid reference binding to misaligned addresses | |
| 148 | struct FileAccessControl { | 148 | struct FileAccessControl { |
| 149 | u8 version; | 149 | u8 version; |
| 150 | INSERT_PADDING_BYTES(3); | 150 | // 3 padding bytes |
| 151 | u64_le permissions; | 151 | u64_le permissions; |
| 152 | std::array<u8, 0x20> unknown; | 152 | std::array<u8, 0x20> unknown; |
| 153 | }; | 153 | }; |
| 154 | 154 | ||
| 155 | static_assert(sizeof(FileAccessControl) == 0x2C, "FS access control structure size is wrong"); | ||
| 156 | |||
| 157 | struct FileAccessHeader { | 155 | struct FileAccessHeader { |
| 158 | u8 version; | 156 | u8 version; |
| 159 | INSERT_PADDING_BYTES(3); | 157 | // 3 padding bytes |
| 160 | u64_le permissions; | 158 | u64_le permissions; |
| 161 | u32_le unk_offset; | 159 | u32_le unk_offset; |
| 162 | u32_le unk_size; | 160 | u32_le unk_size; |
| @@ -164,10 +162,6 @@ private: | |||
| 164 | u32_le unk_size_2; | 162 | u32_le unk_size_2; |
| 165 | }; | 163 | }; |
| 166 | 164 | ||
| 167 | static_assert(sizeof(FileAccessHeader) == 0x1C, "FS access header structure size is wrong"); | ||
| 168 | |||
| 169 | #pragma pack(pop) | ||
| 170 | |||
| 171 | Header npdm_header; | 165 | Header npdm_header; |
| 172 | AciHeader aci_header; | 166 | AciHeader aci_header; |
| 173 | AcidHeader acid_header; | 167 | AcidHeader acid_header; |