updater: use fs bindings

This commit is contained in:
Michael Scire 2020-03-07 20:48:47 -08:00
parent 1fbaaa3c18
commit 60636cdc57
7 changed files with 152 additions and 170 deletions

View file

@ -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);

View file

@ -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. */

View file

@ -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();
}

View file

@ -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) { }
};

View file

@ -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();
}

View file

@ -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;
}

View file

@ -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);