Loading bootloader_message/bootloader_message.cpp +45 −23 Original line number Diff line number Diff line Loading @@ -80,26 +80,23 @@ static bool wait_for_device(const std::string& blk_device, std::string* err) { return ret == 0; } static bool read_misc_partition(void* p, size_t size, size_t offset, std::string* err) { std::string misc_blk_device = get_misc_blk_device(err); if (misc_blk_device.empty()) { return false; } static bool read_misc_partition(void* p, size_t size, const std::string& misc_blk_device, size_t offset, std::string* err) { if (!wait_for_device(misc_blk_device, err)) { return false; } android::base::unique_fd fd(open(misc_blk_device.c_str(), O_RDONLY)); if (fd.get() == -1) { if (fd == -1) { *err = android::base::StringPrintf("failed to open %s: %s", misc_blk_device.c_str(), strerror(errno)); return false; } if (lseek(fd.get(), static_cast<off_t>(offset), SEEK_SET) != static_cast<off_t>(offset)) { if (lseek(fd, static_cast<off_t>(offset), SEEK_SET) != static_cast<off_t>(offset)) { *err = android::base::StringPrintf("failed to lseek %s: %s", misc_blk_device.c_str(), strerror(errno)); return false; } if (!android::base::ReadFully(fd.get(), p, size)) { if (!android::base::ReadFully(fd, p, size)) { *err = android::base::StringPrintf("failed to read %s: %s", misc_blk_device.c_str(), strerror(errno)); return false; Loading @@ -107,29 +104,25 @@ static bool read_misc_partition(void* p, size_t size, size_t offset, std::string return true; } static bool write_misc_partition(const void* p, size_t size, size_t offset, std::string* err) { std::string misc_blk_device = get_misc_blk_device(err); if (misc_blk_device.empty()) { return false; } android::base::unique_fd fd(open(misc_blk_device.c_str(), O_WRONLY | O_SYNC)); if (fd.get() == -1) { static bool write_misc_partition(const void* p, size_t size, const std::string& misc_blk_device, size_t offset, std::string* err) { android::base::unique_fd fd(open(misc_blk_device.c_str(), O_WRONLY)); if (fd == -1) { *err = android::base::StringPrintf("failed to open %s: %s", misc_blk_device.c_str(), strerror(errno)); return false; } if (lseek(fd.get(), static_cast<off_t>(offset), SEEK_SET) != static_cast<off_t>(offset)) { if (lseek(fd, static_cast<off_t>(offset), SEEK_SET) != static_cast<off_t>(offset)) { *err = android::base::StringPrintf("failed to lseek %s: %s", misc_blk_device.c_str(), strerror(errno)); return false; } if (!android::base::WriteFully(fd.get(), p, size)) { if (!android::base::WriteFully(fd, p, size)) { *err = android::base::StringPrintf("failed to write %s: %s", misc_blk_device.c_str(), strerror(errno)); return false; } // TODO: O_SYNC and fsync duplicates each other? if (fsync(fd.get()) == -1) { if (fsync(fd) == -1) { *err = android::base::StringPrintf("failed to fsync %s: %s", misc_blk_device.c_str(), strerror(errno)); return false; Loading @@ -137,12 +130,32 @@ static bool write_misc_partition(const void* p, size_t size, size_t offset, std: return true; } bool read_bootloader_message_from(bootloader_message* boot, const std::string& misc_blk_device, std::string* err) { return read_misc_partition(boot, sizeof(*boot), misc_blk_device, BOOTLOADER_MESSAGE_OFFSET_IN_MISC, err); } bool read_bootloader_message(bootloader_message* boot, std::string* err) { return read_misc_partition(boot, sizeof(*boot), BOOTLOADER_MESSAGE_OFFSET_IN_MISC, err); std::string misc_blk_device = get_misc_blk_device(err); if (misc_blk_device.empty()) { return false; } return read_bootloader_message_from(boot, misc_blk_device, err); } bool write_bootloader_message_to(const bootloader_message& boot, const std::string& misc_blk_device, std::string* err) { return write_misc_partition(&boot, sizeof(boot), misc_blk_device, BOOTLOADER_MESSAGE_OFFSET_IN_MISC, err); } bool write_bootloader_message(const bootloader_message& boot, std::string* err) { return write_misc_partition(&boot, sizeof(boot), BOOTLOADER_MESSAGE_OFFSET_IN_MISC, err); std::string misc_blk_device = get_misc_blk_device(err); if (misc_blk_device.empty()) { return false; } return write_bootloader_message_to(boot, misc_blk_device, err); } bool clear_bootloader_message(std::string* err) { Loading Loading @@ -177,12 +190,21 @@ bool write_reboot_bootloader(std::string* err) { } bool read_wipe_package(std::string* package_data, size_t size, std::string* err) { std::string misc_blk_device = get_misc_blk_device(err); if (misc_blk_device.empty()) { return false; } package_data->resize(size); return read_misc_partition(&(*package_data)[0], size, WIPE_PACKAGE_OFFSET_IN_MISC, err); return read_misc_partition(&(*package_data)[0], size, misc_blk_device, WIPE_PACKAGE_OFFSET_IN_MISC, err); } bool write_wipe_package(const std::string& package_data, std::string* err) { return write_misc_partition(package_data.data(), package_data.size(), std::string misc_blk_device = get_misc_blk_device(err); if (misc_blk_device.empty()) { return false; } return write_misc_partition(package_data.data(), package_data.size(), misc_blk_device, WIPE_PACKAGE_OFFSET_IN_MISC, err); } Loading bootloader_message/include/bootloader_message/bootloader_message.h +18 −0 Original line number Diff line number Diff line Loading @@ -178,15 +178,33 @@ static_assert(sizeof(struct bootloader_control) == #include <string> #include <vector> // Read bootloader message into boot. Error message will be set in err. bool read_bootloader_message(bootloader_message* boot, std::string* err); // Read bootloader message from the specified misc device into boot. bool read_bootloader_message_from(bootloader_message* boot, const std::string& misc_blk_device, std::string* err); // Write bootloader message to BCB. bool write_bootloader_message(const bootloader_message& boot, std::string* err); // Write bootloader message to the specified BCB device. 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. bool write_bootloader_message(const std::vector<std::string>& options, std::string* err); // Clear BCB. bool clear_bootloader_message(std::string* err); // Writes the reboot-bootloader reboot reason to the bootloader_message. bool write_reboot_bootloader(std::string* err); // Read the wipe package from BCB (from offset WIPE_PACKAGE_OFFSET_IN_MISC). bool read_wipe_package(std::string* package_data, size_t size, std::string* err); // Write the wipe package into BCB (to offset WIPE_PACKAGE_OFFSET_IN_MISC). bool write_wipe_package(const std::string& package_data, std::string* err); #else Loading tests/Android.mk +2 −0 Original line number Diff line number Diff line Loading @@ -80,10 +80,12 @@ LOCAL_STATIC_LIBRARIES := \ libedify \ libotafault \ libupdater \ libbootloader_message \ libverifier \ libminui \ libotautil \ libmounts \ libfs_mgr \ liblog \ libselinux \ libext4_utils_static \ Loading tests/component/updater_test.cpp +59 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ #include <android-base/file.h> #include <android-base/properties.h> #include <android-base/test_utils.h> #include <bootloader_message/bootloader_message.h> #include <gtest/gtest.h> #include <ziparchive/zip_archive.h> Loading Loading @@ -451,3 +452,61 @@ TEST_F(UpdaterTest, write_value) { script = "write_value(\"value\", \"/proc/0/file1\")"; expect("", script.c_str(), kNoCause); } TEST_F(UpdaterTest, get_stage) { // get_stage() expects one argument. expect(nullptr, "get_stage()", kArgsParsingFailure); expect(nullptr, "get_stage(\"arg1\", \"arg2\")", kArgsParsingFailure); expect(nullptr, "get_stage(\"arg1\", \"arg2\", \"arg3\")", kArgsParsingFailure); // Set up a local file as BCB. TemporaryFile tf; std::string temp_file(tf.path); bootloader_message boot; strlcpy(boot.stage, "2/3", sizeof(boot.stage)); std::string err; ASSERT_TRUE(write_bootloader_message_to(boot, temp_file, &err)); // Can read the stage value. std::string script("get_stage(\"" + temp_file + "\")"); expect("2/3", script.c_str(), kNoCause); // Bad BCB path. script = "get_stage(\"doesntexist\")"; expect("", script.c_str(), kNoCause); } TEST_F(UpdaterTest, set_stage) { // set_stage() expects two arguments. expect(nullptr, "set_stage()", kArgsParsingFailure); expect(nullptr, "set_stage(\"arg1\")", kArgsParsingFailure); expect(nullptr, "set_stage(\"arg1\", \"arg2\", \"arg3\")", kArgsParsingFailure); // Set up a local file as BCB. TemporaryFile tf; std::string temp_file(tf.path); bootloader_message boot; strlcpy(boot.command, "command", sizeof(boot.command)); strlcpy(boot.stage, "2/3", sizeof(boot.stage)); std::string err; ASSERT_TRUE(write_bootloader_message_to(boot, temp_file, &err)); // Write with set_stage(). std::string script("set_stage(\"" + temp_file + "\", \"1/3\")"); expect(tf.path, script.c_str(), kNoCause); // Verify. bootloader_message boot_verify; ASSERT_TRUE(read_bootloader_message_from(&boot_verify, temp_file, &err)); // Stage should be updated, with command part untouched. ASSERT_STREQ("1/3", boot_verify.stage); ASSERT_STREQ(boot.command, boot_verify.command); // Bad BCB path. script = "set_stage(\"doesntexist\", \"1/3\")"; expect("", script.c_str(), kNoCause); script = "set_stage(\"/dev/full\", \"1/3\")"; expect("", script.c_str(), kNoCause); } updater/Android.mk +2 −0 Original line number Diff line number Diff line Loading @@ -27,12 +27,14 @@ updater_common_static_libraries := \ libedify \ libziparchive \ libotautil \ libbootloader_message \ libutils \ libmounts \ libotafault \ libext4_utils_static \ libfec \ libfec_rs \ libfs_mgr \ liblog \ libselinux \ libsparse_static \ Loading Loading
bootloader_message/bootloader_message.cpp +45 −23 Original line number Diff line number Diff line Loading @@ -80,26 +80,23 @@ static bool wait_for_device(const std::string& blk_device, std::string* err) { return ret == 0; } static bool read_misc_partition(void* p, size_t size, size_t offset, std::string* err) { std::string misc_blk_device = get_misc_blk_device(err); if (misc_blk_device.empty()) { return false; } static bool read_misc_partition(void* p, size_t size, const std::string& misc_blk_device, size_t offset, std::string* err) { if (!wait_for_device(misc_blk_device, err)) { return false; } android::base::unique_fd fd(open(misc_blk_device.c_str(), O_RDONLY)); if (fd.get() == -1) { if (fd == -1) { *err = android::base::StringPrintf("failed to open %s: %s", misc_blk_device.c_str(), strerror(errno)); return false; } if (lseek(fd.get(), static_cast<off_t>(offset), SEEK_SET) != static_cast<off_t>(offset)) { if (lseek(fd, static_cast<off_t>(offset), SEEK_SET) != static_cast<off_t>(offset)) { *err = android::base::StringPrintf("failed to lseek %s: %s", misc_blk_device.c_str(), strerror(errno)); return false; } if (!android::base::ReadFully(fd.get(), p, size)) { if (!android::base::ReadFully(fd, p, size)) { *err = android::base::StringPrintf("failed to read %s: %s", misc_blk_device.c_str(), strerror(errno)); return false; Loading @@ -107,29 +104,25 @@ static bool read_misc_partition(void* p, size_t size, size_t offset, std::string return true; } static bool write_misc_partition(const void* p, size_t size, size_t offset, std::string* err) { std::string misc_blk_device = get_misc_blk_device(err); if (misc_blk_device.empty()) { return false; } android::base::unique_fd fd(open(misc_blk_device.c_str(), O_WRONLY | O_SYNC)); if (fd.get() == -1) { static bool write_misc_partition(const void* p, size_t size, const std::string& misc_blk_device, size_t offset, std::string* err) { android::base::unique_fd fd(open(misc_blk_device.c_str(), O_WRONLY)); if (fd == -1) { *err = android::base::StringPrintf("failed to open %s: %s", misc_blk_device.c_str(), strerror(errno)); return false; } if (lseek(fd.get(), static_cast<off_t>(offset), SEEK_SET) != static_cast<off_t>(offset)) { if (lseek(fd, static_cast<off_t>(offset), SEEK_SET) != static_cast<off_t>(offset)) { *err = android::base::StringPrintf("failed to lseek %s: %s", misc_blk_device.c_str(), strerror(errno)); return false; } if (!android::base::WriteFully(fd.get(), p, size)) { if (!android::base::WriteFully(fd, p, size)) { *err = android::base::StringPrintf("failed to write %s: %s", misc_blk_device.c_str(), strerror(errno)); return false; } // TODO: O_SYNC and fsync duplicates each other? if (fsync(fd.get()) == -1) { if (fsync(fd) == -1) { *err = android::base::StringPrintf("failed to fsync %s: %s", misc_blk_device.c_str(), strerror(errno)); return false; Loading @@ -137,12 +130,32 @@ static bool write_misc_partition(const void* p, size_t size, size_t offset, std: return true; } bool read_bootloader_message_from(bootloader_message* boot, const std::string& misc_blk_device, std::string* err) { return read_misc_partition(boot, sizeof(*boot), misc_blk_device, BOOTLOADER_MESSAGE_OFFSET_IN_MISC, err); } bool read_bootloader_message(bootloader_message* boot, std::string* err) { return read_misc_partition(boot, sizeof(*boot), BOOTLOADER_MESSAGE_OFFSET_IN_MISC, err); std::string misc_blk_device = get_misc_blk_device(err); if (misc_blk_device.empty()) { return false; } return read_bootloader_message_from(boot, misc_blk_device, err); } bool write_bootloader_message_to(const bootloader_message& boot, const std::string& misc_blk_device, std::string* err) { return write_misc_partition(&boot, sizeof(boot), misc_blk_device, BOOTLOADER_MESSAGE_OFFSET_IN_MISC, err); } bool write_bootloader_message(const bootloader_message& boot, std::string* err) { return write_misc_partition(&boot, sizeof(boot), BOOTLOADER_MESSAGE_OFFSET_IN_MISC, err); std::string misc_blk_device = get_misc_blk_device(err); if (misc_blk_device.empty()) { return false; } return write_bootloader_message_to(boot, misc_blk_device, err); } bool clear_bootloader_message(std::string* err) { Loading Loading @@ -177,12 +190,21 @@ bool write_reboot_bootloader(std::string* err) { } bool read_wipe_package(std::string* package_data, size_t size, std::string* err) { std::string misc_blk_device = get_misc_blk_device(err); if (misc_blk_device.empty()) { return false; } package_data->resize(size); return read_misc_partition(&(*package_data)[0], size, WIPE_PACKAGE_OFFSET_IN_MISC, err); return read_misc_partition(&(*package_data)[0], size, misc_blk_device, WIPE_PACKAGE_OFFSET_IN_MISC, err); } bool write_wipe_package(const std::string& package_data, std::string* err) { return write_misc_partition(package_data.data(), package_data.size(), std::string misc_blk_device = get_misc_blk_device(err); if (misc_blk_device.empty()) { return false; } return write_misc_partition(package_data.data(), package_data.size(), misc_blk_device, WIPE_PACKAGE_OFFSET_IN_MISC, err); } Loading
bootloader_message/include/bootloader_message/bootloader_message.h +18 −0 Original line number Diff line number Diff line Loading @@ -178,15 +178,33 @@ static_assert(sizeof(struct bootloader_control) == #include <string> #include <vector> // Read bootloader message into boot. Error message will be set in err. bool read_bootloader_message(bootloader_message* boot, std::string* err); // Read bootloader message from the specified misc device into boot. bool read_bootloader_message_from(bootloader_message* boot, const std::string& misc_blk_device, std::string* err); // Write bootloader message to BCB. bool write_bootloader_message(const bootloader_message& boot, std::string* err); // Write bootloader message to the specified BCB device. 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. bool write_bootloader_message(const std::vector<std::string>& options, std::string* err); // Clear BCB. bool clear_bootloader_message(std::string* err); // Writes the reboot-bootloader reboot reason to the bootloader_message. bool write_reboot_bootloader(std::string* err); // Read the wipe package from BCB (from offset WIPE_PACKAGE_OFFSET_IN_MISC). bool read_wipe_package(std::string* package_data, size_t size, std::string* err); // Write the wipe package into BCB (to offset WIPE_PACKAGE_OFFSET_IN_MISC). bool write_wipe_package(const std::string& package_data, std::string* err); #else Loading
tests/Android.mk +2 −0 Original line number Diff line number Diff line Loading @@ -80,10 +80,12 @@ LOCAL_STATIC_LIBRARIES := \ libedify \ libotafault \ libupdater \ libbootloader_message \ libverifier \ libminui \ libotautil \ libmounts \ libfs_mgr \ liblog \ libselinux \ libext4_utils_static \ Loading
tests/component/updater_test.cpp +59 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ #include <android-base/file.h> #include <android-base/properties.h> #include <android-base/test_utils.h> #include <bootloader_message/bootloader_message.h> #include <gtest/gtest.h> #include <ziparchive/zip_archive.h> Loading Loading @@ -451,3 +452,61 @@ TEST_F(UpdaterTest, write_value) { script = "write_value(\"value\", \"/proc/0/file1\")"; expect("", script.c_str(), kNoCause); } TEST_F(UpdaterTest, get_stage) { // get_stage() expects one argument. expect(nullptr, "get_stage()", kArgsParsingFailure); expect(nullptr, "get_stage(\"arg1\", \"arg2\")", kArgsParsingFailure); expect(nullptr, "get_stage(\"arg1\", \"arg2\", \"arg3\")", kArgsParsingFailure); // Set up a local file as BCB. TemporaryFile tf; std::string temp_file(tf.path); bootloader_message boot; strlcpy(boot.stage, "2/3", sizeof(boot.stage)); std::string err; ASSERT_TRUE(write_bootloader_message_to(boot, temp_file, &err)); // Can read the stage value. std::string script("get_stage(\"" + temp_file + "\")"); expect("2/3", script.c_str(), kNoCause); // Bad BCB path. script = "get_stage(\"doesntexist\")"; expect("", script.c_str(), kNoCause); } TEST_F(UpdaterTest, set_stage) { // set_stage() expects two arguments. expect(nullptr, "set_stage()", kArgsParsingFailure); expect(nullptr, "set_stage(\"arg1\")", kArgsParsingFailure); expect(nullptr, "set_stage(\"arg1\", \"arg2\", \"arg3\")", kArgsParsingFailure); // Set up a local file as BCB. TemporaryFile tf; std::string temp_file(tf.path); bootloader_message boot; strlcpy(boot.command, "command", sizeof(boot.command)); strlcpy(boot.stage, "2/3", sizeof(boot.stage)); std::string err; ASSERT_TRUE(write_bootloader_message_to(boot, temp_file, &err)); // Write with set_stage(). std::string script("set_stage(\"" + temp_file + "\", \"1/3\")"); expect(tf.path, script.c_str(), kNoCause); // Verify. bootloader_message boot_verify; ASSERT_TRUE(read_bootloader_message_from(&boot_verify, temp_file, &err)); // Stage should be updated, with command part untouched. ASSERT_STREQ("1/3", boot_verify.stage); ASSERT_STREQ(boot.command, boot_verify.command); // Bad BCB path. script = "set_stage(\"doesntexist\", \"1/3\")"; expect("", script.c_str(), kNoCause); script = "set_stage(\"/dev/full\", \"1/3\")"; expect("", script.c_str(), kNoCause); }
updater/Android.mk +2 −0 Original line number Diff line number Diff line Loading @@ -27,12 +27,14 @@ updater_common_static_libraries := \ libedify \ libziparchive \ libotautil \ libbootloader_message \ libutils \ libmounts \ libotafault \ libext4_utils_static \ libfec \ libfec_rs \ libfs_mgr \ liblog \ libselinux \ libsparse_static \ Loading