From 6cbcea87a648bc236c8ec97914e342f4a0c4e8a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kan=20Kvist?= Date: Thu, 2 Jul 2020 17:27:06 +0200 Subject: Make bootctl work on devices that does not have v1.1 API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Execute the commands with the API version where the command was introduced. This makes it possible to run the v1.0 HAL commands on a device where v1.1 HAL implementation is not available. Without this patch, on devices that only support bootcontrol v1.0 API, bootctl would just fail with error message. Bug: 160405575 Test: Execute command on device that only implements v1.0 API adb shell bootctl hal-info Change-Id: I56e9a81bcae49b6859b04394d571b5151a235675 Signed-off-by: HÃ¥kan Kvist Signed-off-by: Alessio Balsini --- bootctl/bootctl.cpp | 129 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 78 insertions(+), 51 deletions(-) diff --git a/bootctl/bootctl.cpp b/bootctl/bootctl.cpp index b9aae9cd..c8f8b0bc 100644 --- a/bootctl/bootctl.cpp +++ b/bootctl/bootctl.cpp @@ -31,7 +31,12 @@ using android::hardware::boot::V1_0::Slot; using android::hardware::boot::V1_1::IBootControl; using android::hardware::boot::V1_1::MergeStatus; -static void usage(FILE* where, int /* argc */, char* argv[]) +namespace V1_0 = android::hardware::boot::V1_0; +namespace V1_1 = android::hardware::boot::V1_1; + +enum BootCtlVersion { BOOTCTL_V1_0, BOOTCTL_V1_1 }; + +static void usage(FILE* where, BootCtlVersion bootVersion, int /* argc */, char* argv[]) { fprintf(where, "%s - command-line wrapper for the boot HAL.\n" @@ -48,18 +53,22 @@ static void usage(FILE* where, int /* argc */, char* argv[]) " set-slot-as-unbootable SLOT - Mark SLOT as invalid.\n" " is-slot-bootable SLOT - Returns 0 only if SLOT is bootable.\n" " is-slot-marked-successful SLOT - Returns 0 only if SLOT is marked GOOD.\n" - " get-suffix SLOT - Prints suffix for SLOT.\n" - " set-snapshot-merge-status STAT - Sets whether a snapshot-merge of any dynamic\n" - " partition is in progress. Valid STAT values\n" - " are: none, unknown, snapshotted, merging,\n" - " or cancelled.\n" - " get-snapshot-merge-status - Prints the current snapshot-merge status.\n" - "\n" - "SLOT parameter is the zero-based slot-number.\n", + " get-suffix SLOT - Prints suffix for SLOT.\n", argv[0], argv[0]); + if (bootVersion >= BOOTCTL_V1_1) { + fprintf(where, + " set-snapshot-merge-status STAT - Sets whether a snapshot-merge of any dynamic\n" + " partition is in progress. Valid STAT values\n" + " are: none, unknown, snapshotted, merging,\n" + " or cancelled.\n" + " get-snapshot-merge-status - Prints the current snapshot-merge status.\n"); + } + fprintf(where, + "\n" + "SLOT parameter is the zero-based slot-number.\n"); } -static int do_hal_info(const sp module) { +static int do_hal_info(const sp module) { module->interfaceDescriptor([&](const auto& descriptor) { fprintf(stdout, "HAL Version: %s\n", @@ -68,14 +77,14 @@ static int do_hal_info(const sp module) { return EX_OK; } -static int do_get_number_slots(sp module) +static int do_get_number_slots(sp module) { uint32_t numSlots = module->getNumberSlots(); fprintf(stdout, "%u\n", numSlots); return EX_OK; } -static int do_get_current_slot(sp module) +static int do_get_current_slot(sp module) { Slot curSlot = module->getCurrentSlot(); fprintf(stdout, "%u\n", curSlot); @@ -99,14 +108,14 @@ static int handle_return(const Return &ret, CommandResult cr, const char* return EX_OK; } -static int do_mark_boot_successful(sp module) +static int do_mark_boot_successful(sp module) { CommandResult cr; Return ret = module->markBootSuccessful(generate_callback(&cr)); return handle_return(ret, cr, "Error marking as having booted successfully: %s\n"); } -static int do_set_active_boot_slot(sp module, +static int do_set_active_boot_slot(sp module, Slot slot_number) { CommandResult cr; @@ -114,7 +123,7 @@ static int do_set_active_boot_slot(sp module, return handle_return(ret, cr, "Error setting active boot slot: %s\n"); } -static int do_set_slot_as_unbootable(sp module, +static int do_set_slot_as_unbootable(sp module, Slot slot_number) { CommandResult cr; @@ -135,13 +144,13 @@ static int handle_return(const Return &ret, const char* errStr) { return EX_SOFTWARE; } -static int do_is_slot_bootable(sp module, Slot slot_number) +static int do_is_slot_bootable(sp module, Slot slot_number) { Return ret = module->isSlotBootable(slot_number); return handle_return(ret, "Error calling isSlotBootable(): %s\n"); } -static int do_is_slot_marked_successful(sp module, +static int do_is_slot_marked_successful(sp module, Slot slot_number) { Return ret = module->isSlotMarkedSuccessful(slot_number); @@ -157,16 +166,17 @@ std::optional stringToMergeStatus(const std::string &status) { return {}; } -static int do_set_snapshot_merge_status(sp module, int argc, char *argv[]) { +static int do_set_snapshot_merge_status(sp module, BootCtlVersion bootVersion, + int argc, char *argv[]) { if (argc != 3) { - usage(stderr, argc, argv); + usage(stderr, bootVersion, argc, argv); exit(EX_USAGE); return -1; } auto status = stringToMergeStatus(argv[2]); if (!status.has_value()) { - usage(stderr, argc, argv); + usage(stderr, bootVersion, argc, argv); exit(EX_USAGE); return -1; } @@ -194,7 +204,7 @@ std::ostream& operator<<(std::ostream& os, MergeStatus state) { } } -static int do_get_snapshot_merge_status(sp module) { +static int do_get_snapshot_merge_status(sp module) { MergeStatus ret = module->getSnapshotMergeStatus(); std::stringstream ss; ss << ret; @@ -202,7 +212,7 @@ static int do_get_snapshot_merge_status(sp module) { return EX_OK; } -static int do_get_suffix(sp module, Slot slot_number) { +static int do_get_suffix(sp module, Slot slot_number) { std::function cb = [](hidl_string suffix){ fprintf(stdout, "%s\n", suffix.c_str()); }; @@ -215,17 +225,17 @@ static int do_get_suffix(sp module, Slot slot_number) { return EX_OK; } -static uint32_t parse_slot(int pos, int argc, char *argv[]) +static uint32_t parse_slot(BootCtlVersion bootVersion, int pos, int argc, char *argv[]) { if (pos > argc - 1) { - usage(stderr, argc, argv); + usage(stderr, bootVersion, argc, argv); exit(EX_USAGE); return -1; } errno = 0; uint64_t ret = strtoul(argv[pos], NULL, 10); if (errno != 0 || ret > UINT_MAX) { - usage(stderr, argc, argv); + usage(stderr, bootVersion, argc, argv); exit(EX_USAGE); return -1; } @@ -234,45 +244,62 @@ static uint32_t parse_slot(int pos, int argc, char *argv[]) int main(int argc, char *argv[]) { - sp module; + sp v1_0_module; + sp v1_1_module; + BootCtlVersion bootVersion = BOOTCTL_V1_0; - if (argc < 2) { - usage(stderr, argc, argv); - return EX_USAGE; + v1_0_module = V1_0::IBootControl::getService(); + if (v1_0_module == nullptr) { + fprintf(stderr, "Error getting bootctrl v1.0 module.\n"); + return EX_SOFTWARE; + } + v1_1_module = V1_1::IBootControl::castFrom(v1_0_module); + if (v1_1_module != nullptr) { + bootVersion = BOOTCTL_V1_1; } - module = IBootControl::getService(); - if (module == NULL) { - fprintf(stderr, "Error getting bootctrl module.\n"); - return EX_SOFTWARE; + if (argc < 2) { + usage(stderr, bootVersion, argc, argv); + return EX_USAGE; } + // Functions present from version 1.0 if (strcmp(argv[1], "hal-info") == 0) { - return do_hal_info(module); + return do_hal_info(v1_0_module); } else if (strcmp(argv[1], "get-number-slots") == 0) { - return do_get_number_slots(module); + return do_get_number_slots(v1_0_module); } else if (strcmp(argv[1], "get-current-slot") == 0) { - return do_get_current_slot(module); + return do_get_current_slot(v1_0_module); } else if (strcmp(argv[1], "mark-boot-successful") == 0) { - return do_mark_boot_successful(module); + return do_mark_boot_successful(v1_0_module); } else if (strcmp(argv[1], "set-active-boot-slot") == 0) { - return do_set_active_boot_slot(module, parse_slot(2, argc, argv)); + return do_set_active_boot_slot(v1_0_module, parse_slot(bootVersion, 2, argc, argv)); } else if (strcmp(argv[1], "set-slot-as-unbootable") == 0) { - return do_set_slot_as_unbootable(module, parse_slot(2, argc, argv)); + return do_set_slot_as_unbootable(v1_0_module, parse_slot(bootVersion, 2, argc, argv)); } else if (strcmp(argv[1], "is-slot-bootable") == 0) { - return do_is_slot_bootable(module, parse_slot(2, argc, argv)); - } else if (strcmp(argv[1], "get-suffix") == 0) { - return do_get_suffix(module, parse_slot(2, argc, argv)); + return do_is_slot_bootable(v1_0_module, parse_slot(bootVersion, 2, argc, argv)); } else if (strcmp(argv[1], "is-slot-marked-successful") == 0) { - return do_is_slot_marked_successful(module, parse_slot(2, argc, argv)); - } else if (strcmp(argv[1], "set-snapshot-merge-status") == 0) { - return do_set_snapshot_merge_status(module, argc, argv); - } else if (strcmp(argv[1], "get-snapshot-merge-status") == 0) { - return do_get_snapshot_merge_status(module); - } else { - usage(stderr, argc, argv); - return EX_USAGE; + return do_is_slot_marked_successful(v1_0_module, parse_slot(bootVersion, 2, argc, argv)); + } else if (strcmp(argv[1], "get-suffix") == 0) { + return do_get_suffix(v1_0_module, parse_slot(bootVersion, 2, argc, argv)); + } + + // Functions present from version 1.1 + if (strcmp(argv[1], "set-snapshot-merge-status") == 0 || + strcmp(argv[1], "get-snapshot-merge-status") == 0 ) { + + if (v1_1_module == nullptr) { + fprintf(stderr, "Error getting bootctrl v1.1 module.\n"); + return EX_SOFTWARE; + } + if (strcmp(argv[1], "set-snapshot-merge-status") == 0) { + return do_set_snapshot_merge_status(v1_1_module, bootVersion, argc, argv); + } else if (strcmp(argv[1], "get-snapshot-merge-status") == 0) { + return do_get_snapshot_merge_status(v1_1_module); + } } - return 0; + // Parameter not matched, print usage + usage(stderr, bootVersion, argc, argv); + return EX_USAGE; } -- cgit v1.2.3