Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(62)

Unified Diff: src/platform/update_engine/set_bootable_flag_action.cc

Issue 1881001: AU: Many minor cleanup changes (Closed) Base URL: ssh://git@chromiumos-git/chromeos
Patch Set: fixes for review Created 10 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/platform/update_engine/set_bootable_flag_action.cc
diff --git a/src/platform/update_engine/set_bootable_flag_action.cc b/src/platform/update_engine/set_bootable_flag_action.cc
index 8075b2cb992ee346def8654171865c4ad85bbdeb..ad574ccf31e08bf358587af4dc4b1cba70e83f04 100644
--- a/src/platform/update_engine/set_bootable_flag_action.cc
+++ b/src/platform/update_engine/set_bootable_flag_action.cc
@@ -8,110 +8,70 @@
#include <errno.h>
#include <fcntl.h>
#include <string>
+#include <vector>
+#include "update_engine/subprocess.h"
#include "update_engine/utils.h"
using std::string;
+using std::vector;
namespace chromeos_update_engine {
-void SetBootableFlagAction::PerformAction() {
- ScopedActionCompleter completer(processor_, this);
-
- if (!HasInputObject() || GetInputObject().empty()) {
- LOG(ERROR) << "SetBootableFlagAction: No input object.";
- return;
- }
- string device = GetInputObject();
-
- if (device.size() < 2) {
- LOG(ERROR) << "Device name too short: " << device;
- return;
- }
-
- // Make sure device is valid.
- const char last_char = device[device.size() - 1];
- if ((last_char < '1') || (last_char > '4')) {
- LOG(ERROR) << "Bad device:" << device;
- return;
- }
-
- // We were passed the partition_number'th partition; indexed from 1, not 0
- int partition_number = last_char - '0';
-
- const char second_to_last_char = device[device.size() - 2];
- if ((second_to_last_char >= '0') && (second_to_last_char <= '9')) {
- LOG(ERROR) << "Bad device:" << device;
- return;
- }
-
- // Strip trailing 1-4 off end of device
- device.resize(device.size() - 1);
-
- char mbr[512]; // MBR is the first 512 bytes of the device
- if (!ReadMbr(mbr, sizeof(mbr), device.c_str()))
- return;
-
- // Check MBR. Verify that last two byes are 0x55aa. This is the MBR signature.
- if ((mbr[510] != static_cast<char>(0x55)) ||
- (mbr[511] != static_cast<char>(0xaa))) {
- LOG(ERROR) << "Bad MBR signature";
- return;
- }
-
- // Mark partition passed in bootable and all other partitions non bootable.
- // There are 4 partition table entries, each 16 bytes, stored consecutively
- // beginning at byte 446. Within each entry, the first byte is the
- // bootable flag. It's set to 0x80 (bootable) or 0x00 (not bootable).
- for (int i = 0; i < 4; i++) {
- int offset = 446 + 16 * i;
-
- // partition_number is indexed from 1, not 0
- if ((i + 1) == partition_number)
- mbr[offset] = 0x80;
- else
- mbr[offset] = '\0';
- }
-
- // Write MBR back to disk
- bool success = WriteMbr(mbr, sizeof(mbr), device.c_str());
- if (success) {
- completer.set_success(true);
- if (HasOutputPipe()) {
- SetOutputObject(GetInputObject());
- }
- }
-}
-
-bool SetBootableFlagAction::ReadMbr(char* buffer,
- int buffer_len,
- const char* device) {
- int fd = open(device, O_RDONLY, 0);
- TEST_AND_RETURN_FALSE(fd >= 0);
-
- ssize_t r = read(fd, buffer, buffer_len);
- close(fd);
- TEST_AND_RETURN_FALSE(r == buffer_len);
-
- return true;
+namespace {
+const char* const kGpt = "/usr/bin/gpt";
+const ssize_t kPmbrLength = 512;
}
-bool SetBootableFlagAction::WriteMbr(const char* buffer,
- int buffer_len,
- const char* device) {
- int fd = open(device, O_WRONLY, 0666);
- TEST_AND_RETURN_FALSE(fd >= 0);
- ScopedFdCloser fd_closer(&fd);
+void SetBootableFlagAction::PerformAction() {
+ ScopedActionCompleter completer(processor_, this);
- ssize_t bytes_written = 0;
- while (bytes_written < buffer_len) {
- ssize_t r = write(fd, buffer + bytes_written, buffer_len - bytes_written);
- TEST_AND_RETURN_FALSE_ERRNO(r >= 0);
- bytes_written += r;
+ TEST_AND_RETURN(HasInputObject());
+ const InstallPlan install_plan = GetInputObject();
+ TEST_AND_RETURN(!install_plan.install_path.empty());
+ const string partition = install_plan.install_path;
+ string root_device = utils::RootDevice(partition);
+ string partition_number = utils::PartitionNumber(partition);
+
+ utils::BootLoader boot_loader;
+ TEST_AND_RETURN(utils::GetBootloader(&boot_loader));
+
+ // For now, only support Syslinux bootloader
+ TEST_AND_RETURN(boot_loader == utils::BootLoader_SYSLINUX);
+
+ string temp_file;
+ TEST_AND_RETURN(utils::MakeTempFile("/tmp/pmbr_copy.XXXXXX",
+ &temp_file,
+ NULL));
+ ScopedPathUnlinker temp_file_unlinker(temp_file);
+
+ // Copy existing PMBR to temp file
+ vector<char> buf(kPmbrLength);
+ {
+ int fd = open(root_device.c_str(), O_RDONLY);
+ TEST_AND_RETURN(fd >= 0);
+ ScopedFdCloser fd_closer(&fd);
+ ssize_t bytes_read;
+ TEST_AND_RETURN(utils::PReadAll(fd, &buf[0], buf.size(), 0, &bytes_read));
}
- TEST_AND_RETURN_FALSE(bytes_written == buffer_len);
-
- return true;
+ TEST_AND_RETURN(utils::WriteFile(temp_file.c_str(), &buf[0], buf.size()));
+
+ // Call gpt tool to do the work
+ vector<string> command;
+ command.push_back(kGpt);
+ command.push_back("-S");
+ command.push_back("boot");
+ command.push_back("-i");
+ command.push_back(partition_number);
+ command.push_back("-b");
+ command.push_back(temp_file);
+ command.push_back(root_device);
+ int rc = 0;
+ Subprocess::SynchronousExec(command, &rc);
+ TEST_AND_RETURN(rc == 0);
+
+ completer.set_success(true);
+ if (HasOutputPipe())
+ SetOutputObject(GetInputObject());
}
-
} // namespace chromeos_update_engine
« no previous file with comments | « src/platform/update_engine/set_bootable_flag_action.h ('k') | src/platform/update_engine/set_bootable_flag_action_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698