Loading bootloader_message/bootloader_message.cpp +21 −0 Original line number Diff line number Diff line Loading @@ -176,6 +176,27 @@ bool write_bootloader_message(const std::vector<std::string>& options, std::stri return write_bootloader_message(boot, err); } bool update_bootloader_message(const std::vector<std::string>& options, std::string* err) { bootloader_message boot; if (!read_bootloader_message(&boot, err)) { return false; } // Zero out the entire fields. memset(boot.command, 0, sizeof(boot.command)); memset(boot.recovery, 0, sizeof(boot.recovery)); strlcpy(boot.command, "boot-recovery", sizeof(boot.command)); strlcpy(boot.recovery, "recovery\n", sizeof(boot.recovery)); for (const auto& s : options) { strlcat(boot.recovery, s.c_str(), sizeof(boot.recovery)); if (s.back() != '\n') { strlcat(boot.recovery, "\n", sizeof(boot.recovery)); } } return write_bootloader_message(boot, err); } bool write_reboot_bootloader(std::string* err) { bootloader_message boot; if (!read_bootloader_message(&boot, err)) { Loading bootloader_message/include/bootloader_message/bootloader_message.h +6 −1 Original line number Diff line number Diff line Loading @@ -194,9 +194,14 @@ bool write_bootloader_message(const bootloader_message& boot, std::string* err); bool write_bootloader_message_to(const bootloader_message& boot, const std::string& misc_blk_device, std::string* err); // Write bootloader message (boots into recovery with the options) to BCB. // Write bootloader message (boots into recovery with the options) to BCB. Will // set the command and recovery fields, and reset the rest. bool write_bootloader_message(const std::vector<std::string>& options, std::string* err); // Update bootloader message (boots into recovery with the options) to BCB. Will // only update the command and recovery fields. bool update_bootloader_message(const std::vector<std::string>& options, std::string* err); // Clear BCB. bool clear_bootloader_message(std::string* err); Loading recovery.cpp +12 −11 Original line number Diff line number Diff line Loading @@ -354,19 +354,20 @@ static std::vector<std::string> get_args(const int argc, char** const argv) { // bootloader control block. So the device will always boot into recovery to // finish the pending work, until finish_recovery() is called. std::vector<std::string> options(args.cbegin() + 1, args.cend()); if (!write_bootloader_message(options, &err)) { LOG(ERROR) << err; if (!update_bootloader_message(options, &err)) { LOG(ERROR) << "Failed to set BCB message: " << err; } return args; } static void set_sdcard_update_bootloader_message() { // Set the BCB to reboot back into recovery (it won't resume the install from // sdcard though). static void set_sdcard_update_bootloader_message() { std::vector<std::string> options; std::string err; if (!write_bootloader_message(options, &err)) { LOG(ERROR) << err; if (!update_bootloader_message(options, &err)) { LOG(ERROR) << "Failed to set BCB message: " << err; } } Loading Loading @@ -485,7 +486,7 @@ static void finish_recovery() { // Reset to normal system boot so recovery won't cycle indefinitely. std::string err; if (!clear_bootloader_message(&err)) { LOG(ERROR) << err; LOG(ERROR) << "Failed to clear BCB message: " << err; } // Remove the command file, so recovery won't repeat indefinitely. Loading Loading @@ -1323,7 +1324,7 @@ static void set_retry_bootloader_message(int retry_count, int argc, char** argv) // Increment the retry counter by 1. options.push_back(android::base::StringPrintf("--retry_count=%d", retry_count+1)); std::string err; if (!write_bootloader_message(options, &err)) { if (!update_bootloader_message(options, &err)) { LOG(ERROR) << err; } } Loading tests/component/bootloader_message_test.cpp +26 −0 Original line number Diff line number Diff line Loading @@ -137,3 +137,29 @@ TEST_F(BootloaderMessageTest, write_bootloader_message_options_long) { ASSERT_EQ(std::string(sizeof(boot.reserved), '\0'), std::string(boot.reserved, sizeof(boot.reserved))); } TEST_F(BootloaderMessageTest, update_bootloader_message) { // Inject some bytes into boot, which should be not overwritten later. bootloader_message boot; strlcpy(boot.recovery, "random message", sizeof(boot.recovery)); strlcpy(boot.reserved, "reserved bytes", sizeof(boot.reserved)); std::string err; ASSERT_TRUE(write_bootloader_message(boot, &err)) << "Failed to write BCB: " << err; // Update the BCB message. std::vector<std::string> options = { "option1", "option2" }; ASSERT_TRUE(update_bootloader_message(options, &err)) << "Failed to update BCB: " << err; bootloader_message boot_verify; ASSERT_TRUE(read_bootloader_message(&boot_verify, &err)) << "Failed to read BCB: " << err; // Verify that command and recovery fields should be set. ASSERT_EQ("boot-recovery", std::string(boot_verify.command)); std::string expected = "recovery\n" + android::base::Join(options, "\n") + "\n"; ASSERT_EQ(expected, std::string(boot_verify.recovery)); // The rest should be intact. ASSERT_EQ(std::string(boot.status), std::string(boot_verify.status)); ASSERT_EQ(std::string(boot.stage), std::string(boot_verify.stage)); ASSERT_EQ(std::string(boot.reserved), std::string(boot_verify.reserved)); } Loading
bootloader_message/bootloader_message.cpp +21 −0 Original line number Diff line number Diff line Loading @@ -176,6 +176,27 @@ bool write_bootloader_message(const std::vector<std::string>& options, std::stri return write_bootloader_message(boot, err); } bool update_bootloader_message(const std::vector<std::string>& options, std::string* err) { bootloader_message boot; if (!read_bootloader_message(&boot, err)) { return false; } // Zero out the entire fields. memset(boot.command, 0, sizeof(boot.command)); memset(boot.recovery, 0, sizeof(boot.recovery)); strlcpy(boot.command, "boot-recovery", sizeof(boot.command)); strlcpy(boot.recovery, "recovery\n", sizeof(boot.recovery)); for (const auto& s : options) { strlcat(boot.recovery, s.c_str(), sizeof(boot.recovery)); if (s.back() != '\n') { strlcat(boot.recovery, "\n", sizeof(boot.recovery)); } } return write_bootloader_message(boot, err); } bool write_reboot_bootloader(std::string* err) { bootloader_message boot; if (!read_bootloader_message(&boot, err)) { Loading
bootloader_message/include/bootloader_message/bootloader_message.h +6 −1 Original line number Diff line number Diff line Loading @@ -194,9 +194,14 @@ bool write_bootloader_message(const bootloader_message& boot, std::string* err); bool write_bootloader_message_to(const bootloader_message& boot, const std::string& misc_blk_device, std::string* err); // Write bootloader message (boots into recovery with the options) to BCB. // Write bootloader message (boots into recovery with the options) to BCB. Will // set the command and recovery fields, and reset the rest. bool write_bootloader_message(const std::vector<std::string>& options, std::string* err); // Update bootloader message (boots into recovery with the options) to BCB. Will // only update the command and recovery fields. bool update_bootloader_message(const std::vector<std::string>& options, std::string* err); // Clear BCB. bool clear_bootloader_message(std::string* err); Loading
recovery.cpp +12 −11 Original line number Diff line number Diff line Loading @@ -354,19 +354,20 @@ static std::vector<std::string> get_args(const int argc, char** const argv) { // bootloader control block. So the device will always boot into recovery to // finish the pending work, until finish_recovery() is called. std::vector<std::string> options(args.cbegin() + 1, args.cend()); if (!write_bootloader_message(options, &err)) { LOG(ERROR) << err; if (!update_bootloader_message(options, &err)) { LOG(ERROR) << "Failed to set BCB message: " << err; } return args; } static void set_sdcard_update_bootloader_message() { // Set the BCB to reboot back into recovery (it won't resume the install from // sdcard though). static void set_sdcard_update_bootloader_message() { std::vector<std::string> options; std::string err; if (!write_bootloader_message(options, &err)) { LOG(ERROR) << err; if (!update_bootloader_message(options, &err)) { LOG(ERROR) << "Failed to set BCB message: " << err; } } Loading Loading @@ -485,7 +486,7 @@ static void finish_recovery() { // Reset to normal system boot so recovery won't cycle indefinitely. std::string err; if (!clear_bootloader_message(&err)) { LOG(ERROR) << err; LOG(ERROR) << "Failed to clear BCB message: " << err; } // Remove the command file, so recovery won't repeat indefinitely. Loading Loading @@ -1323,7 +1324,7 @@ static void set_retry_bootloader_message(int retry_count, int argc, char** argv) // Increment the retry counter by 1. options.push_back(android::base::StringPrintf("--retry_count=%d", retry_count+1)); std::string err; if (!write_bootloader_message(options, &err)) { if (!update_bootloader_message(options, &err)) { LOG(ERROR) << err; } } Loading
tests/component/bootloader_message_test.cpp +26 −0 Original line number Diff line number Diff line Loading @@ -137,3 +137,29 @@ TEST_F(BootloaderMessageTest, write_bootloader_message_options_long) { ASSERT_EQ(std::string(sizeof(boot.reserved), '\0'), std::string(boot.reserved, sizeof(boot.reserved))); } TEST_F(BootloaderMessageTest, update_bootloader_message) { // Inject some bytes into boot, which should be not overwritten later. bootloader_message boot; strlcpy(boot.recovery, "random message", sizeof(boot.recovery)); strlcpy(boot.reserved, "reserved bytes", sizeof(boot.reserved)); std::string err; ASSERT_TRUE(write_bootloader_message(boot, &err)) << "Failed to write BCB: " << err; // Update the BCB message. std::vector<std::string> options = { "option1", "option2" }; ASSERT_TRUE(update_bootloader_message(options, &err)) << "Failed to update BCB: " << err; bootloader_message boot_verify; ASSERT_TRUE(read_bootloader_message(&boot_verify, &err)) << "Failed to read BCB: " << err; // Verify that command and recovery fields should be set. ASSERT_EQ("boot-recovery", std::string(boot_verify.command)); std::string expected = "recovery\n" + android::base::Join(options, "\n") + "\n"; ASSERT_EQ(expected, std::string(boot_verify.recovery)); // The rest should be intact. ASSERT_EQ(std::string(boot.status), std::string(boot_verify.status)); ASSERT_EQ(std::string(boot.stage), std::string(boot_verify.stage)); ASSERT_EQ(std::string(boot.reserved), std::string(boot_verify.reserved)); }