diff options
Diffstat (limited to 'src/core/file_sys')
| -rw-r--r-- | src/core/file_sys/card_image.cpp | 18 | ||||
| -rw-r--r-- | src/core/file_sys/card_image.h | 3 | ||||
| -rw-r--r-- | src/core/file_sys/submission_package.cpp | 71 | ||||
| -rw-r--r-- | src/core/file_sys/submission_package.h | 11 |
4 files changed, 57 insertions, 46 deletions
diff --git a/src/core/file_sys/card_image.cpp b/src/core/file_sys/card_image.cpp index db2f6a955..755d3303e 100644 --- a/src/core/file_sys/card_image.cpp +++ b/src/core/file_sys/card_image.cpp | |||
| @@ -29,7 +29,7 @@ constexpr std::array partition_names{ | |||
| 29 | "logo", | 29 | "logo", |
| 30 | }; | 30 | }; |
| 31 | 31 | ||
| 32 | XCI::XCI(VirtualFile file_, std::size_t program_index) | 32 | XCI::XCI(VirtualFile file_, u64 program_id, size_t program_index) |
| 33 | : file(std::move(file_)), program_nca_status{Loader::ResultStatus::ErrorXCIMissingProgramNCA}, | 33 | : file(std::move(file_)), program_nca_status{Loader::ResultStatus::ErrorXCIMissingProgramNCA}, |
| 34 | partitions(partition_names.size()), | 34 | partitions(partition_names.size()), |
| 35 | partitions_raw(partition_names.size()), keys{Core::Crypto::KeyManager::Instance()} { | 35 | partitions_raw(partition_names.size()), keys{Core::Crypto::KeyManager::Instance()} { |
| @@ -63,12 +63,12 @@ XCI::XCI(VirtualFile file_, std::size_t program_index) | |||
| 63 | 63 | ||
| 64 | secure_partition = std::make_shared<NSP>( | 64 | secure_partition = std::make_shared<NSP>( |
| 65 | main_hfs.GetFile(partition_names[static_cast<std::size_t>(XCIPartition::Secure)]), | 65 | main_hfs.GetFile(partition_names[static_cast<std::size_t>(XCIPartition::Secure)]), |
| 66 | program_index); | 66 | program_id, program_index); |
| 67 | 67 | ||
| 68 | ncas = secure_partition->GetNCAsCollapsed(); | 68 | ncas = secure_partition->GetNCAsCollapsed(); |
| 69 | program = | 69 | program = |
| 70 | secure_partition->GetNCA(secure_partition->GetProgramTitleID(), ContentRecordType::Program); | 70 | secure_partition->GetNCA(secure_partition->GetProgramTitleID(), ContentRecordType::Program); |
| 71 | program_nca_status = secure_partition->GetProgramStatus(secure_partition->GetProgramTitleID()); | 71 | program_nca_status = secure_partition->GetProgramStatus(); |
| 72 | if (program_nca_status == Loader::ResultStatus::ErrorNSPMissingProgramNCA) { | 72 | if (program_nca_status == Loader::ResultStatus::ErrorNSPMissingProgramNCA) { |
| 73 | program_nca_status = Loader::ResultStatus::ErrorXCIMissingProgramNCA; | 73 | program_nca_status = Loader::ResultStatus::ErrorXCIMissingProgramNCA; |
| 74 | } | 74 | } |
| @@ -174,6 +174,10 @@ u64 XCI::GetProgramTitleID() const { | |||
| 174 | return secure_partition->GetProgramTitleID(); | 174 | return secure_partition->GetProgramTitleID(); |
| 175 | } | 175 | } |
| 176 | 176 | ||
| 177 | std::vector<u64> XCI::GetProgramTitleIDs() const { | ||
| 178 | return secure_partition->GetProgramTitleIDs(); | ||
| 179 | } | ||
| 180 | |||
| 177 | u32 XCI::GetSystemUpdateVersion() { | 181 | u32 XCI::GetSystemUpdateVersion() { |
| 178 | const auto update = GetPartition(XCIPartition::Update); | 182 | const auto update = GetPartition(XCIPartition::Update); |
| 179 | if (update == nullptr) { | 183 | if (update == nullptr) { |
| @@ -229,9 +233,11 @@ const std::vector<std::shared_ptr<NCA>>& XCI::GetNCAs() const { | |||
| 229 | } | 233 | } |
| 230 | 234 | ||
| 231 | std::shared_ptr<NCA> XCI::GetNCAByType(NCAContentType type) const { | 235 | std::shared_ptr<NCA> XCI::GetNCAByType(NCAContentType type) const { |
| 232 | const auto iter = | 236 | const auto program_id = secure_partition->GetProgramTitleID(); |
| 233 | std::find_if(ncas.begin(), ncas.end(), | 237 | const auto iter = std::find_if( |
| 234 | [type](const std::shared_ptr<NCA>& nca) { return nca->GetType() == type; }); | 238 | ncas.begin(), ncas.end(), [this, type, program_id](const std::shared_ptr<NCA>& nca) { |
| 239 | return nca->GetType() == type && nca->GetTitleId() == program_id; | ||
| 240 | }); | ||
| 235 | return iter == ncas.end() ? nullptr : *iter; | 241 | return iter == ncas.end() ? nullptr : *iter; |
| 236 | } | 242 | } |
| 237 | 243 | ||
diff --git a/src/core/file_sys/card_image.h b/src/core/file_sys/card_image.h index 4960e90fe..0fd9fa87c 100644 --- a/src/core/file_sys/card_image.h +++ b/src/core/file_sys/card_image.h | |||
| @@ -78,7 +78,7 @@ enum class XCIPartition : u8 { Update, Normal, Secure, Logo }; | |||
| 78 | 78 | ||
| 79 | class XCI : public ReadOnlyVfsDirectory { | 79 | class XCI : public ReadOnlyVfsDirectory { |
| 80 | public: | 80 | public: |
| 81 | explicit XCI(VirtualFile file, std::size_t program_index = 0); | 81 | explicit XCI(VirtualFile file, u64 program_id = 0, size_t program_index = 0); |
| 82 | ~XCI() override; | 82 | ~XCI() override; |
| 83 | 83 | ||
| 84 | Loader::ResultStatus GetStatus() const; | 84 | Loader::ResultStatus GetStatus() const; |
| @@ -104,6 +104,7 @@ public: | |||
| 104 | VirtualFile GetLogoPartitionRaw() const; | 104 | VirtualFile GetLogoPartitionRaw() const; |
| 105 | 105 | ||
| 106 | u64 GetProgramTitleID() const; | 106 | u64 GetProgramTitleID() const; |
| 107 | std::vector<u64> GetProgramTitleIDs() const; | ||
| 107 | u32 GetSystemUpdateVersion(); | 108 | u32 GetSystemUpdateVersion(); |
| 108 | u64 GetSystemUpdateTitleID() const; | 109 | u64 GetSystemUpdateTitleID() const; |
| 109 | 110 | ||
diff --git a/src/core/file_sys/submission_package.cpp b/src/core/file_sys/submission_package.cpp index d51d469e3..f192dffa5 100644 --- a/src/core/file_sys/submission_package.cpp +++ b/src/core/file_sys/submission_package.cpp | |||
| @@ -20,8 +20,9 @@ | |||
| 20 | 20 | ||
| 21 | namespace FileSys { | 21 | namespace FileSys { |
| 22 | 22 | ||
| 23 | NSP::NSP(VirtualFile file_, std::size_t program_index_) | 23 | NSP::NSP(VirtualFile file_, u64 title_id_, std::size_t program_index_) |
| 24 | : file(std::move(file_)), program_index(program_index_), status{Loader::ResultStatus::Success}, | 24 | : file(std::move(file_)), expected_program_id(title_id_), |
| 25 | program_index(program_index_), status{Loader::ResultStatus::Success}, | ||
| 25 | pfs(std::make_shared<PartitionFilesystem>(file)), keys{Core::Crypto::KeyManager::Instance()} { | 26 | pfs(std::make_shared<PartitionFilesystem>(file)), keys{Core::Crypto::KeyManager::Instance()} { |
| 26 | if (pfs->GetStatus() != Loader::ResultStatus::Success) { | 27 | if (pfs->GetStatus() != Loader::ResultStatus::Success) { |
| 27 | status = pfs->GetStatus(); | 28 | status = pfs->GetStatus(); |
| @@ -46,60 +47,59 @@ Loader::ResultStatus NSP::GetStatus() const { | |||
| 46 | return status; | 47 | return status; |
| 47 | } | 48 | } |
| 48 | 49 | ||
| 49 | Loader::ResultStatus NSP::GetProgramStatus(u64 title_id) const { | 50 | Loader::ResultStatus NSP::GetProgramStatus() const { |
| 50 | if (IsExtractedType() && GetExeFS() != nullptr && FileSys::IsDirectoryExeFS(GetExeFS())) { | 51 | if (IsExtractedType() && GetExeFS() != nullptr && FileSys::IsDirectoryExeFS(GetExeFS())) { |
| 51 | return Loader::ResultStatus::Success; | 52 | return Loader::ResultStatus::Success; |
| 52 | } | 53 | } |
| 53 | 54 | ||
| 54 | const auto iter = program_status.find(title_id); | 55 | const auto iter = program_status.find(GetProgramTitleID()); |
| 55 | if (iter == program_status.end()) | 56 | if (iter == program_status.end()) |
| 56 | return Loader::ResultStatus::ErrorNSPMissingProgramNCA; | 57 | return Loader::ResultStatus::ErrorNSPMissingProgramNCA; |
| 57 | return iter->second; | 58 | return iter->second; |
| 58 | } | 59 | } |
| 59 | 60 | ||
| 60 | u64 NSP::GetFirstTitleID() const { | ||
| 61 | if (IsExtractedType()) { | ||
| 62 | return GetProgramTitleID(); | ||
| 63 | } | ||
| 64 | |||
| 65 | if (program_status.empty()) | ||
| 66 | return 0; | ||
| 67 | return program_status.begin()->first; | ||
| 68 | } | ||
| 69 | |||
| 70 | u64 NSP::GetProgramTitleID() const { | 61 | u64 NSP::GetProgramTitleID() const { |
| 71 | if (IsExtractedType()) { | 62 | if (IsExtractedType()) { |
| 72 | if (GetExeFS() == nullptr || !IsDirectoryExeFS(GetExeFS())) { | 63 | return GetExtractedTitleID() + program_index; |
| 73 | return 0; | 64 | } |
| 74 | } | ||
| 75 | 65 | ||
| 76 | ProgramMetadata meta; | 66 | auto program_id = expected_program_id; |
| 77 | if (meta.Load(GetExeFS()->GetFile("main.npdm")) == Loader::ResultStatus::Success) { | 67 | if (program_id == 0) { |
| 78 | return meta.GetTitleID(); | 68 | if (!program_status.empty()) { |
| 79 | } else { | 69 | program_id = program_status.begin()->first; |
| 80 | return 0; | ||
| 81 | } | 70 | } |
| 82 | } | 71 | } |
| 83 | 72 | ||
| 84 | const auto out = GetFirstTitleID(); | 73 | program_id = program_id + program_index; |
| 85 | if ((out & 0x800) == 0) | 74 | if (program_status.find(program_id) != program_status.end()) { |
| 86 | return out; | 75 | return program_id; |
| 76 | } | ||
| 87 | 77 | ||
| 88 | const auto ids = GetTitleIDs(); | 78 | const auto ids = GetProgramTitleIDs(); |
| 89 | const auto iter = | 79 | const auto iter = |
| 90 | std::find_if(ids.begin(), ids.end(), [](u64 tid) { return (tid & 0x800) == 0; }); | 80 | std::find_if(ids.begin(), ids.end(), [](u64 tid) { return (tid & 0x800) == 0; }); |
| 91 | return iter == ids.end() ? out : *iter; | 81 | return iter == ids.end() ? 0 : *iter; |
| 82 | } | ||
| 83 | |||
| 84 | u64 NSP::GetExtractedTitleID() const { | ||
| 85 | if (GetExeFS() == nullptr || !IsDirectoryExeFS(GetExeFS())) { | ||
| 86 | return 0; | ||
| 87 | } | ||
| 88 | |||
| 89 | ProgramMetadata meta; | ||
| 90 | if (meta.Load(GetExeFS()->GetFile("main.npdm")) == Loader::ResultStatus::Success) { | ||
| 91 | return meta.GetTitleID(); | ||
| 92 | } else { | ||
| 93 | return 0; | ||
| 94 | } | ||
| 92 | } | 95 | } |
| 93 | 96 | ||
| 94 | std::vector<u64> NSP::GetTitleIDs() const { | 97 | std::vector<u64> NSP::GetProgramTitleIDs() const { |
| 95 | if (IsExtractedType()) { | 98 | if (IsExtractedType()) { |
| 96 | return {GetProgramTitleID()}; | 99 | return {GetExtractedTitleID()}; |
| 97 | } | 100 | } |
| 98 | 101 | ||
| 99 | std::vector<u64> out; | 102 | std::vector<u64> out{program_ids.cbegin(), program_ids.cend()}; |
| 100 | out.reserve(ncas.size()); | ||
| 101 | for (const auto& kv : ncas) | ||
| 102 | out.push_back(kv.first); | ||
| 103 | return out; | 103 | return out; |
| 104 | } | 104 | } |
| 105 | 105 | ||
| @@ -146,7 +146,7 @@ std::shared_ptr<NCA> NSP::GetNCA(u64 title_id, ContentRecordType type, TitleType | |||
| 146 | if (extracted) | 146 | if (extracted) |
| 147 | LOG_WARNING(Service_FS, "called on an NSP that is of type extracted."); | 147 | LOG_WARNING(Service_FS, "called on an NSP that is of type extracted."); |
| 148 | 148 | ||
| 149 | const auto title_id_iter = ncas.find(title_id + program_index); | 149 | const auto title_id_iter = ncas.find(title_id); |
| 150 | if (title_id_iter == ncas.end()) | 150 | if (title_id_iter == ncas.end()) |
| 151 | return nullptr; | 151 | return nullptr; |
| 152 | 152 | ||
| @@ -160,7 +160,7 @@ std::shared_ptr<NCA> NSP::GetNCA(u64 title_id, ContentRecordType type, TitleType | |||
| 160 | VirtualFile NSP::GetNCAFile(u64 title_id, ContentRecordType type, TitleType title_type) const { | 160 | VirtualFile NSP::GetNCAFile(u64 title_id, ContentRecordType type, TitleType title_type) const { |
| 161 | if (extracted) | 161 | if (extracted) |
| 162 | LOG_WARNING(Service_FS, "called on an NSP that is of type extracted."); | 162 | LOG_WARNING(Service_FS, "called on an NSP that is of type extracted."); |
| 163 | const auto nca = GetNCA(title_id, type); | 163 | const auto nca = GetNCA(title_id, type, title_type); |
| 164 | if (nca != nullptr) | 164 | if (nca != nullptr) |
| 165 | return nca->GetBaseFile(); | 165 | return nca->GetBaseFile(); |
| 166 | return nullptr; | 166 | return nullptr; |
| @@ -286,6 +286,7 @@ void NSP::ReadNCAs(const std::vector<VirtualFile>& files) { | |||
| 286 | 286 | ||
| 287 | if (next_nca->GetType() == NCAContentType::Program) { | 287 | if (next_nca->GetType() == NCAContentType::Program) { |
| 288 | program_status[next_nca->GetTitleId()] = next_nca->GetStatus(); | 288 | program_status[next_nca->GetTitleId()] = next_nca->GetStatus(); |
| 289 | program_ids.insert(next_nca->GetTitleId() & 0xFFFFFFFFFFFFF000); | ||
| 289 | } | 290 | } |
| 290 | 291 | ||
| 291 | if (next_nca->GetStatus() != Loader::ResultStatus::Success && | 292 | if (next_nca->GetStatus() != Loader::ResultStatus::Success && |
diff --git a/src/core/file_sys/submission_package.h b/src/core/file_sys/submission_package.h index ecb3b6f15..030f36c09 100644 --- a/src/core/file_sys/submission_package.h +++ b/src/core/file_sys/submission_package.h | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | 6 | ||
| 7 | #include <map> | 7 | #include <map> |
| 8 | #include <memory> | 8 | #include <memory> |
| 9 | #include <set> | ||
| 9 | #include <vector> | 10 | #include <vector> |
| 10 | #include "common/common_types.h" | 11 | #include "common/common_types.h" |
| 11 | #include "core/file_sys/vfs.h" | 12 | #include "core/file_sys/vfs.h" |
| @@ -27,15 +28,15 @@ enum class ContentRecordType : u8; | |||
| 27 | 28 | ||
| 28 | class NSP : public ReadOnlyVfsDirectory { | 29 | class NSP : public ReadOnlyVfsDirectory { |
| 29 | public: | 30 | public: |
| 30 | explicit NSP(VirtualFile file_, std::size_t program_index_ = 0); | 31 | explicit NSP(VirtualFile file_, u64 title_id = 0, std::size_t program_index_ = 0); |
| 31 | ~NSP() override; | 32 | ~NSP() override; |
| 32 | 33 | ||
| 33 | Loader::ResultStatus GetStatus() const; | 34 | Loader::ResultStatus GetStatus() const; |
| 34 | Loader::ResultStatus GetProgramStatus(u64 title_id) const; | 35 | Loader::ResultStatus GetProgramStatus() const; |
| 35 | // Should only be used when one title id can be assured. | 36 | // Should only be used when one title id can be assured. |
| 36 | u64 GetFirstTitleID() const; | ||
| 37 | u64 GetProgramTitleID() const; | 37 | u64 GetProgramTitleID() const; |
| 38 | std::vector<u64> GetTitleIDs() const; | 38 | u64 GetExtractedTitleID() const; |
| 39 | std::vector<u64> GetProgramTitleIDs() const; | ||
| 39 | 40 | ||
| 40 | bool IsExtractedType() const; | 41 | bool IsExtractedType() const; |
| 41 | 42 | ||
| @@ -69,6 +70,7 @@ private: | |||
| 69 | 70 | ||
| 70 | VirtualFile file; | 71 | VirtualFile file; |
| 71 | 72 | ||
| 73 | const u64 expected_program_id; | ||
| 72 | const std::size_t program_index; | 74 | const std::size_t program_index; |
| 73 | 75 | ||
| 74 | bool extracted = false; | 76 | bool extracted = false; |
| @@ -78,6 +80,7 @@ private: | |||
| 78 | std::shared_ptr<PartitionFilesystem> pfs; | 80 | std::shared_ptr<PartitionFilesystem> pfs; |
| 79 | // Map title id -> {map type -> NCA} | 81 | // Map title id -> {map type -> NCA} |
| 80 | std::map<u64, std::map<std::pair<TitleType, ContentRecordType>, std::shared_ptr<NCA>>> ncas; | 82 | std::map<u64, std::map<std::pair<TitleType, ContentRecordType>, std::shared_ptr<NCA>>> ncas; |
| 83 | std::set<u64> program_ids; | ||
| 81 | std::vector<VirtualFile> ticket_files; | 84 | std::vector<VirtualFile> ticket_files; |
| 82 | 85 | ||
| 83 | Core::Crypto::KeyManager& keys; | 86 | Core::Crypto::KeyManager& keys; |