From 33d6dfb6b3e95ecdc5af126a676b70652c8b4169 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Mon, 30 Mar 2020 20:39:56 -0700 Subject: [PATCH] updater: improve api --- .../stratosphere/updater/updater_api.hpp | 9 ++ .../source/updater/updater_api.cpp | 114 ++++++++++-------- 2 files changed, 74 insertions(+), 49 deletions(-) diff --git a/libraries/libstratosphere/include/stratosphere/updater/updater_api.hpp b/libraries/libstratosphere/include/stratosphere/updater/updater_api.hpp index 3f8c3cc1b..268d80213 100644 --- a/libraries/libstratosphere/include/stratosphere/updater/updater_api.hpp +++ b/libraries/libstratosphere/include/stratosphere/updater/updater_api.hpp @@ -21,7 +21,16 @@ namespace ams::updater { /* Public API. */ + BootImageUpdateType GetBootImageUpdateType(int boot_image_update_type); BootImageUpdateType GetBootImageUpdateType(spl::HardwareType hw_type); + + Result GetBootImagePackageId(ncm::SystemDataId *out_data_id, BootModeType mode, void *work_buffer, size_t work_buffer_size); + + Result MarkVerifyingRequired(BootModeType mode, void *work_buffer, size_t work_buffer_size); + Result MarkVerified(BootModeType mode, void *work_buffer, size_t work_buffer_size); + + Result UpdateBootImagesFromPackage(ncm::SystemDataId boot_image_package_id, BootModeType mode, void *work_buffer, size_t work_buffer_size, BootImageUpdateType boot_image_update_type); + Result VerifyBootImagesAndRepairIfNeeded(bool *out_repaired_normal, bool *out_repaired_safe, void *work_buffer, size_t work_buffer_size, BootImageUpdateType boot_image_update_type); } diff --git a/libraries/libstratosphere/source/updater/updater_api.cpp b/libraries/libstratosphere/source/updater/updater_api.cpp index ec978113f..00894124f 100644 --- a/libraries/libstratosphere/source/updater/updater_api.cpp +++ b/libraries/libstratosphere/source/updater/updater_api.cpp @@ -33,7 +33,6 @@ namespace ams::updater { bool HasEks(BootImageUpdateType boot_image_update_type); bool HasAutoRcmPreserve(BootImageUpdateType boot_image_update_type); 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); @@ -42,8 +41,7 @@ namespace ams::updater { 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(ncm::SystemDataId data_id, BootModeType mode, void *work_buffer, size_t work_buffer_size, BootImageUpdateType boot_image_update_type); + Result SetVerificationNeeded(BootModeType mode, void *work_buffer, size_t work_buffer_size, bool needed); 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); @@ -123,45 +121,12 @@ namespace ams::updater { R_CATCH(ResultNeedsRepairBootImages) { /* Perform repair. */ *out_repaired = true; - R_TRY(UpdateBootImages(bip_data_id, mode, work_buffer, work_buffer_size, boot_image_update_type)); + R_TRY(UpdateBootImagesFromPackage(bip_data_id, mode, work_buffer, work_buffer_size, boot_image_update_type)); } } R_END_TRY_CATCH; /* We've either just verified or just repaired. Either way, we don't need to verify any more. */ - return SetVerificationNeeded(mode, false, work_buffer, 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(ncm::ContentMetaKey) * MaxContentMetas); - - /* Open NAND System meta database, list contents. */ - ncm::ContentMetaDatabase db; - R_TRY(ncm::OpenContentMetaDatabase(std::addressof(db), ncm::StorageId::BuiltInSystem)); - - ncm::ContentMetaKey *keys = reinterpret_cast(work_buffer); - const auto content_meta_type = GetContentMetaType(mode); - - 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 (count.total > 1) { - for (auto i = 0; i < count.total; i++) { - u8 attr; - R_TRY(db.GetAttributes(std::addressof(attr), keys[i])); - - 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->value = keys[0].id; - return ResultSuccess(); + return SetVerificationNeeded(mode, work_buffer, work_buffer_size, false); } Result VerifyBootImages(ncm::SystemDataId data_id, BootModeType mode, void *work_buffer, size_t work_buffer_size, BootImageUpdateType boot_image_update_type) { @@ -281,16 +246,6 @@ namespace ams::updater { return ResultSuccess(); } - 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); - case BootModeType::Safe: - return UpdateBootImagesSafe(data_id, work_buffer, work_buffer_size, boot_image_update_type); - AMS_UNREACHABLE_DEFAULT_CASE(); - } - } - 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)); @@ -409,7 +364,7 @@ namespace ams::updater { return ResultSuccess(); } - Result SetVerificationNeeded(BootModeType mode, bool needed, void *work_buffer, size_t work_buffer_size) { + Result SetVerificationNeeded(BootModeType mode, void *work_buffer, size_t work_buffer_size, bool needed) { /* Ensure work buffer is big enough for us to do what we want to do. */ R_TRY(ValidateWorkBuffer(work_buffer, work_buffer_size)); @@ -485,6 +440,67 @@ namespace ams::updater { } } + BootImageUpdateType GetBootImageUpdateType(int boot_image_update_type) { + switch (boot_image_update_type) { + case 0: + return BootImageUpdateType::Erista; + case 1: + return BootImageUpdateType::Mariko; + AMS_UNREACHABLE_DEFAULT_CASE(); + } + } + + 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(ncm::ContentMetaKey) * MaxContentMetas); + + /* Open NAND System meta database, list contents. */ + ncm::ContentMetaDatabase db; + R_TRY(ncm::OpenContentMetaDatabase(std::addressof(db), ncm::StorageId::BuiltInSystem)); + + ncm::ContentMetaKey *keys = reinterpret_cast(work_buffer); + const auto content_meta_type = GetContentMetaType(mode); + + 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 (count.total > 1) { + for (auto i = 0; i < count.total; i++) { + u8 attr; + R_TRY(db.GetAttributes(std::addressof(attr), keys[i])); + + 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->value = keys[0].id; + return ResultSuccess(); + } + + Result MarkVerifyingRequired(BootModeType mode, void *work_buffer, size_t work_buffer_size) { + return SetVerificationNeeded(mode, work_buffer, work_buffer_size, true); + } + + Result MarkVerified(BootModeType mode, void *work_buffer, size_t work_buffer_size) { + return SetVerificationNeeded(mode, work_buffer, work_buffer_size, false); + } + + Result UpdateBootImagesFromPackage(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); + case BootModeType::Safe: + return UpdateBootImagesSafe(data_id, work_buffer, work_buffer_size, boot_image_update_type); + AMS_UNREACHABLE_DEFAULT_CASE(); + } + } + Result VerifyBootImagesAndRepairIfNeeded(bool *out_repaired_normal, bool *out_repaired_safe, void *work_buffer, size_t work_buffer_size, BootImageUpdateType boot_image_update_type) { /* Always set output to false before doing anything else. */ *out_repaired_normal = false;