bootctl.cpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. /*
  2. * Copyright (C) 2016 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include <sysexits.h>
  17. #include <android/hardware/boot/1.0/IBootControl.h>
  18. using android::sp;
  19. using android::hardware::hidl_string;
  20. using android::hardware::Return;
  21. using android::hardware::boot::V1_0::BoolResult;
  22. using android::hardware::boot::V1_0::IBootControl;
  23. using android::hardware::boot::V1_0::CommandResult;
  24. using android::hardware::boot::V1_0::Slot;
  25. static void usage(FILE* where, int /* argc */, char* argv[])
  26. {
  27. fprintf(where,
  28. "%s - command-line wrapper for the boot HAL.\n"
  29. "\n"
  30. "Usage:\n"
  31. " %s COMMAND\n"
  32. "\n"
  33. "Commands:\n"
  34. " %s hal-info - Show info about boot_control HAL used.\n"
  35. " %s get-number-slots - Prints number of slots.\n"
  36. " %s get-current-slot - Prints currently running SLOT.\n"
  37. " %s mark-boot-successful - Mark current slot as GOOD.\n"
  38. " %s set-active-boot-slot SLOT - On next boot, load and execute SLOT.\n"
  39. " %s set-slot-as-unbootable SLOT - Mark SLOT as invalid.\n"
  40. " %s is-slot-bootable SLOT - Returns 0 only if SLOT is bootable.\n"
  41. " %s is-slot-marked-successful SLOT - Returns 0 only if SLOT is marked GOOD.\n"
  42. " %s get-suffix SLOT - Prints suffix for SLOT.\n"
  43. "\n"
  44. "SLOT parameter is the zero-based slot-number.\n",
  45. argv[0], argv[0], argv[0], argv[0], argv[0], argv[0],
  46. argv[0], argv[0], argv[0], argv[0], argv[0]);
  47. }
  48. static int do_hal_info(const sp<IBootControl> module) {
  49. module->interfaceDescriptor([&](const auto& descriptor) {
  50. fprintf(stdout,
  51. "HAL Version: %s\n",
  52. descriptor.c_str());
  53. });
  54. return EX_OK;
  55. }
  56. static int do_get_number_slots(sp<IBootControl> module)
  57. {
  58. uint32_t numSlots = module->getNumberSlots();
  59. fprintf(stdout, "%u\n", numSlots);
  60. return EX_OK;
  61. }
  62. static int do_get_current_slot(sp<IBootControl> module)
  63. {
  64. Slot curSlot = module->getCurrentSlot();
  65. fprintf(stdout, "%u\n", curSlot);
  66. return EX_OK;
  67. }
  68. static std::function<void(CommandResult)> generate_callback(CommandResult *crp) {
  69. return [=](CommandResult cr){
  70. *crp = cr;
  71. };
  72. }
  73. static int handle_return(const Return<void> &ret, CommandResult cr, const char* errStr) {
  74. if (!ret.isOk()) {
  75. fprintf(stderr, errStr, ret.description().c_str());
  76. return EX_SOFTWARE;
  77. } else if (!cr.success) {
  78. fprintf(stderr, errStr, cr.errMsg.c_str());
  79. return EX_SOFTWARE;
  80. }
  81. return EX_OK;
  82. }
  83. static int do_mark_boot_successful(sp<IBootControl> module)
  84. {
  85. CommandResult cr;
  86. Return<void> ret = module->markBootSuccessful(generate_callback(&cr));
  87. return handle_return(ret, cr, "Error marking as having booted successfully: %s\n");
  88. }
  89. static int do_set_active_boot_slot(sp<IBootControl> module,
  90. Slot slot_number)
  91. {
  92. CommandResult cr;
  93. Return<void> ret = module->setActiveBootSlot(slot_number, generate_callback(&cr));
  94. return handle_return(ret, cr, "Error setting active boot slot: %s\n");
  95. }
  96. static int do_set_slot_as_unbootable(sp<IBootControl> module,
  97. Slot slot_number)
  98. {
  99. CommandResult cr;
  100. Return<void> ret = module->setSlotAsUnbootable(slot_number, generate_callback(&cr));
  101. return handle_return(ret, cr, "Error setting slot as unbootable: %s\n");
  102. }
  103. static int handle_return(const Return<BoolResult> &ret, const char* errStr) {
  104. if (!ret.isOk()) {
  105. fprintf(stderr, errStr, ret.description().c_str());
  106. return EX_SOFTWARE;
  107. } else if (ret == BoolResult::INVALID_SLOT) {
  108. fprintf(stderr, errStr, "Invalid slot");
  109. return EX_SOFTWARE;
  110. } else if (ret == BoolResult::TRUE) {
  111. return EX_OK;
  112. }
  113. return EX_SOFTWARE;
  114. }
  115. static int do_is_slot_bootable(sp<IBootControl> module, Slot slot_number)
  116. {
  117. Return<BoolResult> ret = module->isSlotBootable(slot_number);
  118. return handle_return(ret, "Error calling isSlotBootable(): %s\n");
  119. }
  120. static int do_is_slot_marked_successful(sp<IBootControl> module,
  121. Slot slot_number)
  122. {
  123. Return<BoolResult> ret = module->isSlotMarkedSuccessful(slot_number);
  124. return handle_return(ret, "Error calling isSlotMarkedSuccessful(): %s\n");
  125. }
  126. static int do_get_suffix(sp<IBootControl> module, Slot slot_number) {
  127. std::function<void(hidl_string)> cb = [](hidl_string suffix){
  128. fprintf(stdout, "%s\n", suffix.c_str());
  129. };
  130. Return<void> ret = module->getSuffix(slot_number, cb);
  131. if (!ret.isOk()) {
  132. fprintf(stderr, "Error calling getSuffix(): %s\n",
  133. ret.description().c_str());
  134. return EX_SOFTWARE;
  135. }
  136. return EX_OK;
  137. }
  138. static uint32_t parse_slot(int pos, int argc, char *argv[])
  139. {
  140. if (pos > argc - 1) {
  141. usage(stderr, argc, argv);
  142. exit(EX_USAGE);
  143. return -1;
  144. }
  145. errno = 0;
  146. uint64_t ret = strtoul(argv[pos], NULL, 10);
  147. if (errno != 0 || ret > UINT_MAX) {
  148. usage(stderr, argc, argv);
  149. exit(EX_USAGE);
  150. return -1;
  151. }
  152. return (uint32_t)ret;
  153. }
  154. int main(int argc, char *argv[])
  155. {
  156. sp<IBootControl> module;
  157. if (argc < 2) {
  158. usage(stderr, argc, argv);
  159. return EX_USAGE;
  160. }
  161. module = IBootControl::getService();
  162. if (module == NULL) {
  163. fprintf(stderr, "Error getting bootctrl module.\n");
  164. return EX_SOFTWARE;
  165. }
  166. if (strcmp(argv[1], "hal-info") == 0) {
  167. return do_hal_info(module);
  168. } else if (strcmp(argv[1], "get-number-slots") == 0) {
  169. return do_get_number_slots(module);
  170. } else if (strcmp(argv[1], "get-current-slot") == 0) {
  171. return do_get_current_slot(module);
  172. } else if (strcmp(argv[1], "mark-boot-successful") == 0) {
  173. return do_mark_boot_successful(module);
  174. } else if (strcmp(argv[1], "set-active-boot-slot") == 0) {
  175. return do_set_active_boot_slot(module, parse_slot(2, argc, argv));
  176. } else if (strcmp(argv[1], "set-slot-as-unbootable") == 0) {
  177. return do_set_slot_as_unbootable(module, parse_slot(2, argc, argv));
  178. } else if (strcmp(argv[1], "is-slot-bootable") == 0) {
  179. return do_is_slot_bootable(module, parse_slot(2, argc, argv));
  180. } else if (strcmp(argv[1], "get-suffix") == 0) {
  181. return do_get_suffix(module, parse_slot(2, argc, argv));
  182. } else if (strcmp(argv[1], "is-slot-marked-successful") == 0) {
  183. return do_is_slot_marked_successful(module, parse_slot(2, argc, argv));
  184. } else {
  185. usage(stderr, argc, argv);
  186. return EX_USAGE;
  187. }
  188. return 0;
  189. }