mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2025-04-22 12:34:47 +00:00
updater: use fs bindings
This commit is contained in:
parent
1fbaaa3c18
commit
60636cdc57
7 changed files with 152 additions and 170 deletions
|
@ -65,7 +65,12 @@ namespace ams::sm {
|
|||
AMS_ABORT_UNLESS(!this->has_initialized);
|
||||
|
||||
sm::DoWithSession([&]() {
|
||||
this->result = Initializer();
|
||||
if constexpr (std::is_same<decltype(Initializer()), void>::value) {
|
||||
Initializer();
|
||||
this->result = ResultSuccess();
|
||||
} else {
|
||||
this->result = Initializer();
|
||||
}
|
||||
});
|
||||
|
||||
this->has_initialized = R_SUCCEEDED(this->result);
|
||||
|
|
|
@ -32,25 +32,26 @@ namespace ams::updater {
|
|||
/* Configuration Prototypes. */
|
||||
bool HasEks(BootImageUpdateType boot_image_update_type);
|
||||
bool HasAutoRcmPreserve(BootImageUpdateType boot_image_update_type);
|
||||
NcmContentMetaType GetNcmContentMetaType(BootModeType mode);
|
||||
Result GetBootImagePackageDataId(u64 *out_data_id, BootModeType mode, void *work_buffer, size_t work_buffer_size);
|
||||
ncm::ContentMetaType GetContentMetaType(BootModeType mode);
|
||||
Result GetBootImagePackageId(ncm::SystemDataId *out_data_id, BootModeType mode, void *work_buffer, size_t work_buffer_size);
|
||||
|
||||
/* Verification Prototypes. */
|
||||
Result GetVerificationState(VerificationState *out, void *work_buffer, size_t work_buffer_size);
|
||||
Result VerifyBootImages(u64 data_id, BootModeType mode, void *work_buffer, size_t work_buffer_size, BootImageUpdateType boot_image_update_type);
|
||||
Result VerifyBootImagesNormal(u64 data_id, void *work_buffer, size_t work_buffer_size, BootImageUpdateType boot_image_update_type);
|
||||
Result VerifyBootImagesSafe(u64 data_id, void *work_buffer, size_t work_buffer_size, BootImageUpdateType boot_image_update_type);
|
||||
Result VerifyBootImages(ncm::SystemDataId data_id, BootModeType mode, void *work_buffer, size_t work_buffer_size, BootImageUpdateType boot_image_update_type);
|
||||
Result VerifyBootImagesNormal(ncm::SystemDataId data_id, void *work_buffer, size_t work_buffer_size, BootImageUpdateType boot_image_update_type);
|
||||
Result VerifyBootImagesSafe(ncm::SystemDataId data_id, void *work_buffer, size_t work_buffer_size, BootImageUpdateType boot_image_update_type);
|
||||
|
||||
/* Update Prototypes. */
|
||||
Result SetVerificationNeeded(BootModeType mode, bool needed, void *work_buffer, size_t work_buffer_size);
|
||||
Result UpdateBootImages(u64 data_id, BootModeType mode, void *work_buffer, size_t work_buffer_size, BootImageUpdateType boot_image_update_type);
|
||||
Result UpdateBootImagesNormal(u64 data_id, void *work_buffer, size_t work_buffer_size, BootImageUpdateType boot_image_update_type);
|
||||
Result UpdateBootImagesSafe(u64 data_id, void *work_buffer, size_t work_buffer_size, BootImageUpdateType boot_image_update_type);
|
||||
Result UpdateBootImages(ncm::SystemDataId data_id, BootModeType mode, void *work_buffer, size_t work_buffer_size, BootImageUpdateType boot_image_update_type);
|
||||
Result UpdateBootImagesNormal(ncm::SystemDataId data_id, void *work_buffer, size_t work_buffer_size, BootImageUpdateType boot_image_update_type);
|
||||
Result UpdateBootImagesSafe(ncm::SystemDataId data_id, void *work_buffer, size_t work_buffer_size, BootImageUpdateType boot_image_update_type);
|
||||
|
||||
/* Package helpers. */
|
||||
Result ValidateBctFileHash(Boot0Accessor &accessor, Boot0Partition which, const void *stored_hash, void *work_buffer, size_t work_buffer_size, BootImageUpdateType boot_image_update_type);
|
||||
Result GetPackage2Hash(void *dst_hash, size_t package2_size, void *work_buffer, size_t work_buffer_size, Package2Type which);
|
||||
Result WritePackage2(void *work_buffer, size_t work_buffer_size, Package2Type which, BootImageUpdateType boot_image_update_type);
|
||||
Result CompareHash(const void *lhs, const void *rhs, size_t size);
|
||||
|
||||
/* Implementations. */
|
||||
Result ValidateWorkBuffer(const void *work_buffer, size_t work_buffer_size) {
|
||||
|
@ -80,12 +81,12 @@ namespace ams::updater {
|
|||
}
|
||||
}
|
||||
|
||||
NcmContentMetaType GetNcmContentMetaType(BootModeType mode) {
|
||||
ncm::ContentMetaType GetContentMetaType(BootModeType mode) {
|
||||
switch (mode) {
|
||||
case BootModeType::Normal:
|
||||
return NcmContentMetaType_BootImagePackage;
|
||||
return ncm::ContentMetaType::BootImagePackage;
|
||||
case BootModeType::Safe:
|
||||
return NcmContentMetaType_BootImagePackageSafe;
|
||||
return ncm::ContentMetaType::BootImagePackageSafe;
|
||||
AMS_UNREACHABLE_DEFAULT_CASE();
|
||||
}
|
||||
}
|
||||
|
@ -114,8 +115,8 @@ namespace ams::updater {
|
|||
|
||||
Result VerifyBootImagesAndRepairIfNeeded(bool *out_repaired, BootModeType mode, void *work_buffer, size_t work_buffer_size, BootImageUpdateType boot_image_update_type) {
|
||||
/* Get system data id for boot images (819/81A/81B/81C). */
|
||||
u64 bip_data_id = 0;
|
||||
R_TRY(GetBootImagePackageDataId(&bip_data_id, mode, work_buffer, work_buffer_size));
|
||||
ncm::SystemDataId bip_data_id;
|
||||
R_TRY(GetBootImagePackageId(&bip_data_id, mode, work_buffer, work_buffer_size));
|
||||
|
||||
/* Verify the boot images in NAND. */
|
||||
R_TRY_CATCH(VerifyBootImages(bip_data_id, mode, work_buffer, work_buffer_size, boot_image_update_type)) {
|
||||
|
@ -130,47 +131,40 @@ namespace ams::updater {
|
|||
return SetVerificationNeeded(mode, false, work_buffer, work_buffer_size);
|
||||
}
|
||||
|
||||
Result GetBootImagePackageDataId(u64 *out_data_id, BootModeType mode, void *work_buffer, size_t work_buffer_size) {
|
||||
Result GetBootImagePackageId(ncm::SystemDataId *out_data_id, BootModeType mode, void *work_buffer, size_t work_buffer_size) {
|
||||
/* Ensure we can read content metas. */
|
||||
constexpr size_t MaxContentMetas = 0x40;
|
||||
AMS_ABORT_UNLESS(work_buffer_size >= sizeof(NcmContentMetaKey) * MaxContentMetas);
|
||||
AMS_ABORT_UNLESS(work_buffer_size >= sizeof(ncm::ContentMetaKey) * MaxContentMetas);
|
||||
|
||||
/* Open NAND System meta database, list contents. */
|
||||
NcmContentMetaDatabase meta_db;
|
||||
R_TRY(ncmOpenContentMetaDatabase(&meta_db, NcmStorageId_BuiltInSystem));
|
||||
ON_SCOPE_EXIT { serviceClose(&meta_db.s); };
|
||||
ncm::ContentMetaDatabase db;
|
||||
R_TRY(ncm::OpenContentMetaDatabase(std::addressof(db), ncm::StorageId::BuiltInSystem));
|
||||
|
||||
NcmContentMetaKey *records = reinterpret_cast<NcmContentMetaKey *>(work_buffer);
|
||||
ncm::ContentMetaKey *keys = reinterpret_cast<ncm::ContentMetaKey *>(work_buffer);
|
||||
const auto content_meta_type = GetContentMetaType(mode);
|
||||
|
||||
const auto content_meta_type = GetNcmContentMetaType(mode);
|
||||
s32 written_entries;
|
||||
s32 total_entries;
|
||||
R_TRY(ncmContentMetaDatabaseList(&meta_db, &total_entries, &written_entries, records, MaxContentMetas * sizeof(*records), content_meta_type, 0, 0, UINT64_MAX, NcmContentInstallType_Full));
|
||||
if (total_entries <= 0) {
|
||||
return ResultBootImagePackageNotFound();
|
||||
}
|
||||
|
||||
AMS_ABORT_UNLESS(total_entries == written_entries);
|
||||
auto count = db.ListContentMeta(keys, MaxContentMetas, content_meta_type);
|
||||
R_UNLESS(count.total > 0, ResultBootImagePackageNotFound());
|
||||
|
||||
/* Output is sorted, return the lowest valid exfat entry. */
|
||||
if (total_entries > 1) {
|
||||
for (size_t i = 0; i < size_t(total_entries); i++) {
|
||||
if (count.total > 1) {
|
||||
for (auto i = 0; i < count.total; i++) {
|
||||
u8 attr;
|
||||
R_TRY(ncmContentMetaDatabaseGetAttributes(&meta_db, &records[i], &attr));
|
||||
R_TRY(db.GetAttributes(std::addressof(attr), keys[i]));
|
||||
|
||||
if (attr & NcmContentMetaAttribute_IncludesExFatDriver) {
|
||||
*out_data_id = records[i].id;
|
||||
if (attr & ncm::ContentMetaAttribute_IncludesExFatDriver) {
|
||||
out_data_id->value = keys[i].id;
|
||||
return ResultSuccess();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If there's only one entry or no exfat entries, return that entry. */
|
||||
*out_data_id = records[0].id;
|
||||
out_data_id->value = keys[0].id;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result VerifyBootImages(u64 data_id, BootModeType mode, void *work_buffer, size_t work_buffer_size, BootImageUpdateType boot_image_update_type) {
|
||||
Result VerifyBootImages(ncm::SystemDataId data_id, BootModeType mode, void *work_buffer, size_t work_buffer_size, BootImageUpdateType boot_image_update_type) {
|
||||
switch (mode) {
|
||||
case BootModeType::Normal:
|
||||
return VerifyBootImagesNormal(data_id, work_buffer, work_buffer_size, boot_image_update_type);
|
||||
|
@ -180,20 +174,22 @@ namespace ams::updater {
|
|||
}
|
||||
}
|
||||
|
||||
Result VerifyBootImagesNormal(u64 data_id, void *work_buffer, size_t work_buffer_size, BootImageUpdateType boot_image_update_type) {
|
||||
Result VerifyBootImagesNormal(ncm::SystemDataId data_id, void *work_buffer, size_t work_buffer_size, BootImageUpdateType boot_image_update_type) {
|
||||
/* Ensure work buffer is big enough for us to do what we want to do. */
|
||||
R_TRY(ValidateWorkBuffer(work_buffer, work_buffer_size));
|
||||
|
||||
R_TRY_CATCH(romfsMountFromDataArchive(data_id, NcmStorageId_BuiltInSystem, GetBootImagePackageMountPath())) {
|
||||
/* Mount the boot image package. */
|
||||
const char *mount_name = GetMountName();
|
||||
R_TRY_CATCH(fs::MountSystemData(mount_name, data_id)) {
|
||||
R_CONVERT(fs::ResultTargetNotFound, ResultBootImagePackageNotFound())
|
||||
} R_END_TRY_CATCH;
|
||||
ON_SCOPE_EXIT { R_ABORT_UNLESS(romfsUnmount(GetBootImagePackageMountPath())); };
|
||||
ON_SCOPE_EXIT { fs::Unmount(mount_name); };
|
||||
|
||||
/* Read and validate hashes of boot images. */
|
||||
{
|
||||
size_t size;
|
||||
u8 nand_hash[SHA256_HASH_SIZE];
|
||||
u8 file_hash[SHA256_HASH_SIZE];
|
||||
u8 nand_hash[crypto::Sha256Generator::HashSize];
|
||||
u8 file_hash[crypto::Sha256Generator::HashSize];
|
||||
|
||||
Boot0Accessor boot0_accessor;
|
||||
R_TRY(boot0_accessor.Initialize());
|
||||
|
@ -209,44 +205,42 @@ namespace ams::updater {
|
|||
|
||||
/* Compare Package1 Normal/Sub hashes. */
|
||||
R_TRY(GetFileHash(&size, file_hash, GetPackage1Path(boot_image_update_type), work_buffer, work_buffer_size));
|
||||
|
||||
R_TRY(boot0_accessor.GetHash(nand_hash, size, work_buffer, work_buffer_size, Boot0Partition::Package1NormalMain));
|
||||
if (std::memcmp(file_hash, nand_hash, SHA256_HASH_SIZE) != 0) {
|
||||
return ResultNeedsRepairBootImages();
|
||||
}
|
||||
R_TRY(CompareHash(file_hash, nand_hash, sizeof(file_hash)));
|
||||
|
||||
R_TRY(boot0_accessor.GetHash(nand_hash, size, work_buffer, work_buffer_size, Boot0Partition::Package1NormalSub));
|
||||
if (std::memcmp(file_hash, nand_hash, SHA256_HASH_SIZE) != 0) {
|
||||
return ResultNeedsRepairBootImages();
|
||||
}
|
||||
R_TRY(CompareHash(file_hash, nand_hash, sizeof(file_hash)));
|
||||
|
||||
/* Compare Package2 Normal/Sub hashes. */
|
||||
R_TRY(GetFileHash(&size, file_hash, GetPackage2Path(boot_image_update_type), work_buffer, work_buffer_size));
|
||||
|
||||
R_TRY(GetPackage2Hash(nand_hash, size, work_buffer, work_buffer_size, Package2Type::NormalMain));
|
||||
if (std::memcmp(file_hash, nand_hash, SHA256_HASH_SIZE) != 0) {
|
||||
return ResultNeedsRepairBootImages();
|
||||
}
|
||||
R_TRY(CompareHash(file_hash, nand_hash, sizeof(file_hash)));
|
||||
|
||||
R_TRY(GetPackage2Hash(nand_hash, size, work_buffer, work_buffer_size, Package2Type::NormalSub));
|
||||
if (std::memcmp(file_hash, nand_hash, SHA256_HASH_SIZE) != 0) {
|
||||
return ResultNeedsRepairBootImages();
|
||||
}
|
||||
R_TRY(CompareHash(file_hash, nand_hash, sizeof(file_hash)));
|
||||
}
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result VerifyBootImagesSafe(u64 data_id, void *work_buffer, size_t work_buffer_size, BootImageUpdateType boot_image_update_type) {
|
||||
Result VerifyBootImagesSafe(ncm::SystemDataId data_id, void *work_buffer, size_t work_buffer_size, BootImageUpdateType boot_image_update_type) {
|
||||
/* Ensure work buffer is big enough for us to do what we want to do. */
|
||||
R_TRY(ValidateWorkBuffer(work_buffer, work_buffer_size));
|
||||
|
||||
R_TRY_CATCH(romfsMountFromDataArchive(data_id, NcmStorageId_BuiltInSystem, GetBootImagePackageMountPath())) {
|
||||
/* Mount the boot image package. */
|
||||
const char *mount_name = GetMountName();
|
||||
R_TRY_CATCH(fs::MountSystemData(mount_name, data_id)) {
|
||||
R_CONVERT(fs::ResultTargetNotFound, ResultBootImagePackageNotFound())
|
||||
} R_END_TRY_CATCH;
|
||||
ON_SCOPE_EXIT { R_ABORT_UNLESS(romfsUnmount(GetBootImagePackageMountPath())); };
|
||||
ON_SCOPE_EXIT { fs::Unmount(mount_name); };
|
||||
|
||||
/* Read and validate hashes of boot images. */
|
||||
{
|
||||
size_t size;
|
||||
u8 nand_hash[SHA256_HASH_SIZE];
|
||||
u8 file_hash[SHA256_HASH_SIZE];
|
||||
u8 nand_hash[crypto::Sha256Generator::HashSize];
|
||||
u8 file_hash[crypto::Sha256Generator::HashSize];
|
||||
|
||||
Boot0Accessor boot0_accessor;
|
||||
R_TRY(boot0_accessor.Initialize());
|
||||
|
@ -267,31 +261,27 @@ namespace ams::updater {
|
|||
|
||||
/* Compare Package1 Normal/Sub hashes. */
|
||||
R_TRY(GetFileHash(&size, file_hash, GetPackage1Path(boot_image_update_type), work_buffer, work_buffer_size));
|
||||
|
||||
R_TRY(boot1_accessor.GetHash(nand_hash, size, work_buffer, work_buffer_size, Boot1Partition::Package1SafeMain));
|
||||
if (std::memcmp(file_hash, nand_hash, SHA256_HASH_SIZE) != 0) {
|
||||
return ResultNeedsRepairBootImages();
|
||||
}
|
||||
R_TRY(CompareHash(file_hash, nand_hash, sizeof(file_hash)));
|
||||
|
||||
R_TRY(boot1_accessor.GetHash(nand_hash, size, work_buffer, work_buffer_size, Boot1Partition::Package1SafeSub));
|
||||
if (std::memcmp(file_hash, nand_hash, SHA256_HASH_SIZE) != 0) {
|
||||
return ResultNeedsRepairBootImages();
|
||||
}
|
||||
R_TRY(CompareHash(file_hash, nand_hash, sizeof(file_hash)));
|
||||
|
||||
/* Compare Package2 Normal/Sub hashes. */
|
||||
R_TRY(GetFileHash(&size, file_hash, GetPackage2Path(boot_image_update_type), work_buffer, work_buffer_size));
|
||||
|
||||
R_TRY(GetPackage2Hash(nand_hash, size, work_buffer, work_buffer_size, Package2Type::SafeMain));
|
||||
if (std::memcmp(file_hash, nand_hash, SHA256_HASH_SIZE) != 0) {
|
||||
return ResultNeedsRepairBootImages();
|
||||
}
|
||||
R_TRY(CompareHash(file_hash, nand_hash, sizeof(file_hash)));
|
||||
|
||||
R_TRY(GetPackage2Hash(nand_hash, size, work_buffer, work_buffer_size, Package2Type::SafeSub));
|
||||
if (std::memcmp(file_hash, nand_hash, SHA256_HASH_SIZE) != 0) {
|
||||
return ResultNeedsRepairBootImages();
|
||||
}
|
||||
R_TRY(CompareHash(file_hash, nand_hash, sizeof(file_hash)));
|
||||
}
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result UpdateBootImages(u64 data_id, BootModeType mode, void *work_buffer, size_t work_buffer_size, BootImageUpdateType boot_image_update_type) {
|
||||
Result UpdateBootImages(ncm::SystemDataId data_id, BootModeType mode, void *work_buffer, size_t work_buffer_size, BootImageUpdateType boot_image_update_type) {
|
||||
switch (mode) {
|
||||
case BootModeType::Normal:
|
||||
return UpdateBootImagesNormal(data_id, work_buffer, work_buffer_size, boot_image_update_type);
|
||||
|
@ -301,14 +291,16 @@ namespace ams::updater {
|
|||
}
|
||||
}
|
||||
|
||||
Result UpdateBootImagesNormal(u64 data_id, void *work_buffer, size_t work_buffer_size, BootImageUpdateType boot_image_update_type) {
|
||||
Result UpdateBootImagesNormal(ncm::SystemDataId data_id, void *work_buffer, size_t work_buffer_size, BootImageUpdateType boot_image_update_type) {
|
||||
/* Ensure work buffer is big enough for us to do what we want to do. */
|
||||
R_TRY(ValidateWorkBuffer(work_buffer, work_buffer_size));
|
||||
|
||||
R_TRY_CATCH(romfsMountFromDataArchive(data_id, NcmStorageId_BuiltInSystem, GetBootImagePackageMountPath())) {
|
||||
/* Mount the boot image package. */
|
||||
const char *mount_name = GetMountName();
|
||||
R_TRY_CATCH(fs::MountSystemData(mount_name, data_id)) {
|
||||
R_CONVERT(fs::ResultTargetNotFound, ResultBootImagePackageNotFound())
|
||||
} R_END_TRY_CATCH;
|
||||
ON_SCOPE_EXIT { R_ABORT_UNLESS(romfsUnmount(GetBootImagePackageMountPath())); };
|
||||
ON_SCOPE_EXIT { fs::Unmount(mount_name); };
|
||||
|
||||
{
|
||||
Boot0Accessor boot0_accessor;
|
||||
|
@ -356,14 +348,16 @@ namespace ams::updater {
|
|||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result UpdateBootImagesSafe(u64 data_id, void *work_buffer, size_t work_buffer_size, BootImageUpdateType boot_image_update_type) {
|
||||
Result UpdateBootImagesSafe(ncm::SystemDataId data_id, void *work_buffer, size_t work_buffer_size, BootImageUpdateType boot_image_update_type) {
|
||||
/* Ensure work buffer is big enough for us to do what we want to do. */
|
||||
R_TRY(ValidateWorkBuffer(work_buffer, work_buffer_size));
|
||||
|
||||
R_TRY_CATCH(romfsMountFromDataArchive(data_id, NcmStorageId_BuiltInSystem, GetBootImagePackageMountPath())) {
|
||||
/* Mount the boot image package. */
|
||||
const char *mount_name = GetMountName();
|
||||
R_TRY_CATCH(fs::MountSystemData(mount_name, data_id)) {
|
||||
R_CONVERT(fs::ResultTargetNotFound, ResultBootImagePackageNotFound())
|
||||
} R_END_TRY_CATCH;
|
||||
ON_SCOPE_EXIT { R_ABORT_UNLESS(romfsUnmount(GetBootImagePackageMountPath())); };
|
||||
ON_SCOPE_EXIT { fs::Unmount(mount_name); };
|
||||
|
||||
{
|
||||
Boot0Accessor boot0_accessor;
|
||||
|
@ -450,14 +444,10 @@ namespace ams::updater {
|
|||
R_TRY(accessor.PreserveAutoRcm(bct, work, which));
|
||||
}
|
||||
|
||||
u8 file_hash[SHA256_HASH_SIZE];
|
||||
sha256CalculateHash(file_hash, bct, BctSize);
|
||||
u8 file_hash[crypto::Sha256Generator::HashSize];
|
||||
crypto::GenerateSha256Hash(file_hash, sizeof(file_hash), bct, BctSize);
|
||||
|
||||
if (std::memcmp(file_hash, stored_hash, SHA256_HASH_SIZE) != 0) {
|
||||
return ResultNeedsRepairBootImages();
|
||||
}
|
||||
|
||||
return ResultSuccess();
|
||||
return CompareHash(file_hash, stored_hash, sizeof(file_hash));
|
||||
}
|
||||
|
||||
Result GetPackage2Hash(void *dst_hash, size_t package2_size, void *work_buffer, size_t work_buffer_size, Package2Type which) {
|
||||
|
@ -476,6 +466,11 @@ namespace ams::updater {
|
|||
return accessor.Write(GetPackage2Path(boot_image_update_type), work_buffer, work_buffer_size, Package2Partition::Package2);
|
||||
}
|
||||
|
||||
Result CompareHash(const void *lhs, const void *rhs, size_t size) {
|
||||
R_UNLESS(crypto::IsSameBytes(lhs, rhs, size), ResultNeedsRepairBootImages());
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
BootImageUpdateType GetBootImageUpdateType(spl::HardwareType hw_type) {
|
||||
|
@ -508,7 +503,7 @@ namespace ams::updater {
|
|||
}
|
||||
|
||||
/* Get a session to ncm. */
|
||||
sm::ScopedServiceHolder<ncmInitialize, ncmExit> ncm_holder;
|
||||
sm::ScopedServiceHolder<ncm::Initialize, ncm::Finalize> ncm_holder;
|
||||
R_ABORT_UNLESS(ncm_holder.GetResult());
|
||||
|
||||
/* Verify normal, verify safe as needed. */
|
||||
|
|
|
@ -18,47 +18,38 @@
|
|||
namespace ams::updater {
|
||||
|
||||
Result BisAccessor::Initialize() {
|
||||
R_TRY(fsOpenBisStorage(&this->storage, this->partition_id));
|
||||
this->active = true;
|
||||
return ResultSuccess();
|
||||
return fs::OpenBisPartition(std::addressof(this->storage), this->partition_id);
|
||||
}
|
||||
|
||||
void BisAccessor::Finalize() {
|
||||
if (this->active) {
|
||||
fsStorageClose(&this->storage);
|
||||
this->active = false;
|
||||
}
|
||||
/* ... */
|
||||
}
|
||||
|
||||
Result BisAccessor::Read(void *dst, size_t size, u64 offset) {
|
||||
AMS_ABORT_UNLESS((offset % SectorAlignment) == 0);
|
||||
return fsStorageRead(&this->storage, offset, dst, size);
|
||||
return this->storage->Read(static_cast<u32>(offset), dst, size);
|
||||
}
|
||||
|
||||
Result BisAccessor::Write(u64 offset, const void *src, size_t size) {
|
||||
AMS_ABORT_UNLESS((offset % SectorAlignment) == 0);
|
||||
return fsStorageWrite(&this->storage, offset, src, size);
|
||||
return this->storage->Write(static_cast<u32>(offset), src, size);
|
||||
}
|
||||
|
||||
Result BisAccessor::Write(u64 offset, size_t size, const char *bip_path, void *work_buffer, size_t work_buffer_size) {
|
||||
AMS_ABORT_UNLESS((offset % SectorAlignment) == 0);
|
||||
AMS_ABORT_UNLESS((work_buffer_size % SectorAlignment) == 0);
|
||||
|
||||
FILE *bip_fp = fopen(bip_path, "rb");
|
||||
if (bip_fp == NULL) {
|
||||
return ResultInvalidBootImagePackage();
|
||||
}
|
||||
ON_SCOPE_EXIT { fclose(bip_fp); };
|
||||
fs::FileHandle file;
|
||||
R_TRY_CATCH(fs::OpenFile(std::addressof(file), bip_path, fs::OpenMode_Read)) {
|
||||
R_CONVERT(fs::ResultPathNotFound, ResultInvalidBootImagePackage())
|
||||
} R_END_TRY_CATCH;
|
||||
ON_SCOPE_EXIT { fs::CloseFile(file); };
|
||||
|
||||
size_t written = 0;
|
||||
while (true) {
|
||||
std::memset(work_buffer, 0, work_buffer_size);
|
||||
size_t read_size = fread(work_buffer, 1, work_buffer_size, bip_fp);
|
||||
if (read_size != work_buffer_size) {
|
||||
if (ferror(bip_fp)) {
|
||||
return fsdevGetLastResult();
|
||||
}
|
||||
}
|
||||
size_t read_size;
|
||||
R_TRY(fs::ReadFile(std::addressof(read_size), file, written, work_buffer, work_buffer_size, fs::ReadOption()));
|
||||
AMS_ABORT_UNLESS(written + read_size <= size);
|
||||
|
||||
size_t aligned_size = ((read_size + SectorAlignment - 1) / SectorAlignment) * SectorAlignment;
|
||||
|
@ -91,18 +82,19 @@ namespace ams::updater {
|
|||
AMS_ABORT_UNLESS((offset % SectorAlignment) == 0);
|
||||
AMS_ABORT_UNLESS((work_buffer_size % SectorAlignment) == 0);
|
||||
|
||||
Sha256Context sha_ctx;
|
||||
sha256ContextCreate(&sha_ctx);
|
||||
crypto::Sha256Generator generator;
|
||||
generator.Initialize();
|
||||
|
||||
size_t total_read = 0;
|
||||
while (total_read < hash_size) {
|
||||
size_t cur_read_size = std::min(work_buffer_size, size - total_read);
|
||||
size_t cur_update_size = std::min(cur_read_size, hash_size - total_read);
|
||||
R_TRY(this->Read(work_buffer, cur_read_size, offset + total_read));
|
||||
sha256ContextUpdate(&sha_ctx, work_buffer, cur_update_size);
|
||||
generator.Update(work_buffer, cur_update_size);
|
||||
|
||||
total_read += cur_read_size;
|
||||
}
|
||||
sha256ContextGetHash(&sha_ctx, dst);
|
||||
generator.GetHash(dst, hash_size);
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
@ -140,9 +132,10 @@ namespace ams::updater {
|
|||
size_t read_size;
|
||||
R_TRY(this->Read(&read_size, work_buffer, BctSize, which));
|
||||
|
||||
void *dst_pubk = reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(dst_bct) + BctPubkOffset);
|
||||
void *dst_pubk = reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(dst_bct) + BctPubkOffset);
|
||||
void *src_pubk = reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(work_buffer) + BctPubkOffset);
|
||||
std::memcpy(dst_pubk, src_pubk, BctPubkSize);
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
|
|
|
@ -20,19 +20,14 @@
|
|||
namespace ams::updater {
|
||||
|
||||
class BisAccessor {
|
||||
NON_COPYABLE(BisAccessor);
|
||||
public:
|
||||
static constexpr size_t SectorAlignment = 0x200;
|
||||
private:
|
||||
FsStorage storage = {};
|
||||
FsBisPartitionId partition_id;
|
||||
bool active;
|
||||
std::unique_ptr<fs::IStorage> storage;
|
||||
const fs::BisPartitionId partition_id;
|
||||
public:
|
||||
BisAccessor(FsBisPartitionId id) : partition_id(id), active(false) { }
|
||||
~BisAccessor() {
|
||||
if (this->active) {
|
||||
fsStorageClose(&storage);
|
||||
}
|
||||
}
|
||||
explicit BisAccessor(fs::BisPartitionId id) : partition_id(id) { /* ... */ }
|
||||
|
||||
public:
|
||||
Result Initialize();
|
||||
|
@ -79,7 +74,7 @@ namespace ams::updater {
|
|||
};
|
||||
|
||||
struct Boot0Meta {
|
||||
using EnumType = Boot0Partition;
|
||||
using EnumType = Boot0Partition;
|
||||
using OffsetSizeType = OffsetSizeEntry<EnumType>;
|
||||
|
||||
static constexpr size_t NumEntries = static_cast<size_t>(EnumType::Count);
|
||||
|
@ -96,7 +91,7 @@ namespace ams::updater {
|
|||
};
|
||||
|
||||
struct Boot1Meta {
|
||||
using EnumType = Boot1Partition;
|
||||
using EnumType = Boot1Partition;
|
||||
using OffsetSizeType = OffsetSizeEntry<EnumType>;
|
||||
|
||||
static constexpr size_t NumEntries = static_cast<size_t>(EnumType::Count);
|
||||
|
@ -109,7 +104,7 @@ namespace ams::updater {
|
|||
};
|
||||
|
||||
struct Package2Meta {
|
||||
using EnumType = Package2Partition;
|
||||
using EnumType = Package2Partition;
|
||||
using OffsetSizeType = OffsetSizeEntry<EnumType>;
|
||||
|
||||
static constexpr size_t NumEntries = static_cast<size_t>(EnumType::Count);
|
||||
|
@ -121,11 +116,12 @@ namespace ams::updater {
|
|||
|
||||
template<typename Meta>
|
||||
class PartitionAccessor : public BisAccessor {
|
||||
NON_COPYABLE(PartitionAccessor);
|
||||
public:
|
||||
using EnumType = typename Meta::EnumType;
|
||||
using EnumType = typename Meta::EnumType;
|
||||
using OffsetSizeType = typename Meta::OffsetSizeType;
|
||||
public:
|
||||
PartitionAccessor(FsBisPartitionId id) : BisAccessor(id) { }
|
||||
explicit PartitionAccessor(fs::BisPartitionId id) : BisAccessor(id) { /* ... */ }
|
||||
private:
|
||||
constexpr const OffsetSizeType *FindEntry(EnumType which) {
|
||||
const OffsetSizeType *entry = nullptr;
|
||||
|
@ -182,27 +178,27 @@ namespace ams::updater {
|
|||
RepairSub,
|
||||
};
|
||||
|
||||
static constexpr FsBisPartitionId GetPackage2StorageId(Package2Type which) {
|
||||
static constexpr fs::BisPartitionId GetPackage2StorageId(Package2Type which) {
|
||||
switch (which) {
|
||||
case Package2Type::NormalMain:
|
||||
return FsBisPartitionId_BootConfigAndPackage2Part1;
|
||||
return fs::BisPartitionId::BootConfigAndPackage2Part1;
|
||||
case Package2Type::NormalSub:
|
||||
return FsBisPartitionId_BootConfigAndPackage2Part2;
|
||||
return fs::BisPartitionId::BootConfigAndPackage2Part2;
|
||||
case Package2Type::SafeMain:
|
||||
return FsBisPartitionId_BootConfigAndPackage2Part3;
|
||||
return fs::BisPartitionId::BootConfigAndPackage2Part3;
|
||||
case Package2Type::SafeSub:
|
||||
return FsBisPartitionId_BootConfigAndPackage2Part4;
|
||||
return fs::BisPartitionId::BootConfigAndPackage2Part4;
|
||||
case Package2Type::RepairMain:
|
||||
return FsBisPartitionId_BootConfigAndPackage2Part5;
|
||||
return fs::BisPartitionId::BootConfigAndPackage2Part5;
|
||||
case Package2Type::RepairSub:
|
||||
return FsBisPartitionId_BootConfigAndPackage2Part6;
|
||||
return fs::BisPartitionId::BootConfigAndPackage2Part6;
|
||||
AMS_UNREACHABLE_DEFAULT_CASE();
|
||||
}
|
||||
}
|
||||
|
||||
class Boot0Accessor : public PartitionAccessor<Boot0Meta> {
|
||||
public:
|
||||
static constexpr FsBisPartitionId PartitionId = FsBisPartitionId_BootPartition1Root;
|
||||
static constexpr fs::BisPartitionId PartitionId = fs::BisPartitionId::BootPartition1Root;
|
||||
static constexpr size_t BctPubkOffset = 0x210;
|
||||
static constexpr size_t BctPubkSize = 0x100;
|
||||
static constexpr size_t BctEksOffset = 0x450;
|
||||
|
@ -222,7 +218,7 @@ namespace ams::updater {
|
|||
|
||||
class Boot1Accessor : public PartitionAccessor<Boot1Meta> {
|
||||
public:
|
||||
static constexpr FsBisPartitionId PartitionId = FsBisPartitionId_BootPartition2Root;
|
||||
static constexpr fs::BisPartitionId PartitionId = fs::BisPartitionId::BootPartition2Root;
|
||||
public:
|
||||
Boot1Accessor() : PartitionAccessor<Boot1Meta>(PartitionId) { }
|
||||
};
|
||||
|
|
|
@ -18,49 +18,43 @@
|
|||
namespace ams::updater {
|
||||
|
||||
Result ReadFile(size_t *out_size, void *dst, size_t dst_size, const char *path) {
|
||||
FILE *fp = fopen(path, "rb");
|
||||
if (fp == NULL) {
|
||||
return ResultInvalidBootImagePackage();
|
||||
}
|
||||
ON_SCOPE_EXIT { fclose(fp); };
|
||||
/* Open the file. */
|
||||
fs::FileHandle file;
|
||||
R_TRY_CATCH(fs::OpenFile(std::addressof(file), path, fs::OpenMode_Read)) {
|
||||
R_CONVERT(fs::ResultPathNotFound, ResultInvalidBootImagePackage())
|
||||
} R_END_TRY_CATCH;
|
||||
ON_SCOPE_EXIT { fs::CloseFile(file); };
|
||||
|
||||
std::memset(dst, 0, dst_size);
|
||||
size_t read_size = fread(dst, 1, dst_size, fp);
|
||||
if (ferror(fp)) {
|
||||
return fsdevGetLastResult();
|
||||
}
|
||||
*out_size = read_size;
|
||||
return ResultSuccess();
|
||||
return fs::ReadFile(out_size, file, 0, dst, dst_size, fs::ReadOption());
|
||||
}
|
||||
|
||||
Result GetFileHash(size_t *out_size, void *dst_hash, const char *path, void *work_buffer, size_t work_buffer_size) {
|
||||
FILE *fp = fopen(path, "rb");
|
||||
if (fp == NULL) {
|
||||
return ResultInvalidBootImagePackage();
|
||||
}
|
||||
ON_SCOPE_EXIT { fclose(fp); };
|
||||
/* Open the file. */
|
||||
fs::FileHandle file;
|
||||
R_TRY_CATCH(fs::OpenFile(std::addressof(file), path, fs::OpenMode_Read)) {
|
||||
R_CONVERT(fs::ResultPathNotFound, ResultInvalidBootImagePackage())
|
||||
} R_END_TRY_CATCH;
|
||||
ON_SCOPE_EXIT { fs::CloseFile(file); };
|
||||
|
||||
Sha256Context sha_ctx;
|
||||
sha256ContextCreate(&sha_ctx);
|
||||
/* Read in chunks, hashing as we go. */
|
||||
crypto::Sha256Generator generator;
|
||||
generator.Initialize();
|
||||
|
||||
size_t total_size = 0;
|
||||
while (true) {
|
||||
size_t read_size = fread(work_buffer, 1, work_buffer_size, fp);
|
||||
if (ferror(fp)) {
|
||||
return fsdevGetLastResult();
|
||||
}
|
||||
if (read_size == 0) {
|
||||
break;
|
||||
}
|
||||
size_t size;
|
||||
R_TRY(fs::ReadFile(std::addressof(size), file, total_size, work_buffer, work_buffer_size, fs::ReadOption()));
|
||||
|
||||
sha256ContextUpdate(&sha_ctx, work_buffer, read_size);
|
||||
total_size += read_size;
|
||||
if (read_size != work_buffer_size) {
|
||||
generator.Update(work_buffer, size);
|
||||
total_size += size;
|
||||
|
||||
if (size != work_buffer_size) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
sha256ContextGetHash(&sha_ctx, dst_hash);
|
||||
generator.GetHash(dst_hash, crypto::Sha256Generator::HashSize);
|
||||
*out_size = total_size;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <sys/stat.h>
|
||||
#include "updater_paths.hpp"
|
||||
|
||||
namespace ams::updater {
|
||||
|
@ -21,7 +20,7 @@ namespace ams::updater {
|
|||
namespace {
|
||||
|
||||
/* Actual paths. */
|
||||
constexpr const char *BootImagePackageMountPath = "bip";
|
||||
constexpr const char *BootImagePackageMountName = "bip";
|
||||
constexpr const char *BctPathNx = "bip:/nx/bct";
|
||||
constexpr const char *Package1PathNx = "bip:/nx/package1";
|
||||
constexpr const char *Package2PathNx = "bip:/nx/package2";
|
||||
|
@ -33,12 +32,12 @@ namespace ams::updater {
|
|||
AMS_ABORT_UNLESS(num_candidates > 0);
|
||||
|
||||
for (size_t i = 0; i < num_candidates; i++) {
|
||||
struct stat buf;
|
||||
if (stat(candidates[i], &buf) != 0) {
|
||||
fs::DirectoryEntryType type;
|
||||
if (R_FAILED(fs::GetEntryType(std::addressof(type), candidates[i]))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!S_ISREG(buf.st_mode)) {
|
||||
if (type != fs::DirectoryEntryType_File) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -51,8 +50,8 @@ namespace ams::updater {
|
|||
|
||||
}
|
||||
|
||||
const char *GetBootImagePackageMountPath() {
|
||||
return BootImagePackageMountPath;
|
||||
const char *GetMountName() {
|
||||
return BootImagePackageMountName;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
namespace ams::updater {
|
||||
|
||||
/* Path functionality. */
|
||||
const char *GetBootImagePackageMountPath();
|
||||
const char *GetMountName();
|
||||
const char *GetBctPath(BootImageUpdateType boot_image_update_type);
|
||||
const char *GetPackage1Path(BootImageUpdateType boot_image_update_type);
|
||||
const char *GetPackage2Path(BootImageUpdateType boot_image_update_type);
|
||||
|
|
Loading…
Add table
Reference in a new issue