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

Side by Side 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, 7 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "update_engine/set_bootable_flag_action.h" 5 #include "update_engine/set_bootable_flag_action.h"
6 #include <sys/stat.h> 6 #include <sys/stat.h>
7 #include <sys/types.h> 7 #include <sys/types.h>
8 #include <errno.h> 8 #include <errno.h>
9 #include <fcntl.h> 9 #include <fcntl.h>
10 #include <string> 10 #include <string>
11 #include <vector>
12 #include "update_engine/subprocess.h"
11 #include "update_engine/utils.h" 13 #include "update_engine/utils.h"
12 14
13 using std::string; 15 using std::string;
16 using std::vector;
14 17
15 namespace chromeos_update_engine { 18 namespace chromeos_update_engine {
16 19
20 namespace {
21 const char* const kGpt = "/usr/bin/gpt";
22 const ssize_t kPmbrLength = 512;
23 }
24
17 void SetBootableFlagAction::PerformAction() { 25 void SetBootableFlagAction::PerformAction() {
18 ScopedActionCompleter completer(processor_, this); 26 ScopedActionCompleter completer(processor_, this);
19 27
20 if (!HasInputObject() || GetInputObject().empty()) { 28 TEST_AND_RETURN(HasInputObject());
21 LOG(ERROR) << "SetBootableFlagAction: No input object."; 29 const InstallPlan install_plan = GetInputObject();
22 return; 30 TEST_AND_RETURN(!install_plan.install_path.empty());
31 const string partition = install_plan.install_path;
32 string root_device = utils::RootDevice(partition);
33 string partition_number = utils::PartitionNumber(partition);
34
35 utils::BootLoader boot_loader;
36 TEST_AND_RETURN(utils::GetBootloader(&boot_loader));
37
38 // For now, only support Syslinux bootloader
39 TEST_AND_RETURN(boot_loader == utils::BootLoader_SYSLINUX);
40
41 string temp_file;
42 TEST_AND_RETURN(utils::MakeTempFile("/tmp/pmbr_copy.XXXXXX",
43 &temp_file,
44 NULL));
45 ScopedPathUnlinker temp_file_unlinker(temp_file);
46
47 // Copy existing PMBR to temp file
48 vector<char> buf(kPmbrLength);
49 {
50 int fd = open(root_device.c_str(), O_RDONLY);
51 TEST_AND_RETURN(fd >= 0);
52 ScopedFdCloser fd_closer(&fd);
53 ssize_t bytes_read;
54 TEST_AND_RETURN(utils::PReadAll(fd, &buf[0], buf.size(), 0, &bytes_read));
23 } 55 }
24 string device = GetInputObject(); 56 TEST_AND_RETURN(utils::WriteFile(temp_file.c_str(), &buf[0], buf.size()));
25 57
26 if (device.size() < 2) { 58 // Call gpt tool to do the work
27 LOG(ERROR) << "Device name too short: " << device; 59 vector<string> command;
28 return; 60 command.push_back(kGpt);
29 } 61 command.push_back("-S");
62 command.push_back("boot");
63 command.push_back("-i");
64 command.push_back(partition_number);
65 command.push_back("-b");
66 command.push_back(temp_file);
67 command.push_back(root_device);
68 int rc = 0;
69 Subprocess::SynchronousExec(command, &rc);
70 TEST_AND_RETURN(rc == 0);
30 71
31 // Make sure device is valid. 72 completer.set_success(true);
32 const char last_char = device[device.size() - 1]; 73 if (HasOutputPipe())
33 if ((last_char < '1') || (last_char > '4')) { 74 SetOutputObject(GetInputObject());
34 LOG(ERROR) << "Bad device:" << device;
35 return;
36 }
37
38 // We were passed the partition_number'th partition; indexed from 1, not 0
39 int partition_number = last_char - '0';
40
41 const char second_to_last_char = device[device.size() - 2];
42 if ((second_to_last_char >= '0') && (second_to_last_char <= '9')) {
43 LOG(ERROR) << "Bad device:" << device;
44 return;
45 }
46
47 // Strip trailing 1-4 off end of device
48 device.resize(device.size() - 1);
49
50 char mbr[512]; // MBR is the first 512 bytes of the device
51 if (!ReadMbr(mbr, sizeof(mbr), device.c_str()))
52 return;
53
54 // Check MBR. Verify that last two byes are 0x55aa. This is the MBR signature.
55 if ((mbr[510] != static_cast<char>(0x55)) ||
56 (mbr[511] != static_cast<char>(0xaa))) {
57 LOG(ERROR) << "Bad MBR signature";
58 return;
59 }
60
61 // Mark partition passed in bootable and all other partitions non bootable.
62 // There are 4 partition table entries, each 16 bytes, stored consecutively
63 // beginning at byte 446. Within each entry, the first byte is the
64 // bootable flag. It's set to 0x80 (bootable) or 0x00 (not bootable).
65 for (int i = 0; i < 4; i++) {
66 int offset = 446 + 16 * i;
67
68 // partition_number is indexed from 1, not 0
69 if ((i + 1) == partition_number)
70 mbr[offset] = 0x80;
71 else
72 mbr[offset] = '\0';
73 }
74
75 // Write MBR back to disk
76 bool success = WriteMbr(mbr, sizeof(mbr), device.c_str());
77 if (success) {
78 completer.set_success(true);
79 if (HasOutputPipe()) {
80 SetOutputObject(GetInputObject());
81 }
82 }
83 } 75 }
84 76
85 bool SetBootableFlagAction::ReadMbr(char* buffer,
86 int buffer_len,
87 const char* device) {
88 int fd = open(device, O_RDONLY, 0);
89 TEST_AND_RETURN_FALSE(fd >= 0);
90
91 ssize_t r = read(fd, buffer, buffer_len);
92 close(fd);
93 TEST_AND_RETURN_FALSE(r == buffer_len);
94
95 return true;
96 }
97
98 bool SetBootableFlagAction::WriteMbr(const char* buffer,
99 int buffer_len,
100 const char* device) {
101 int fd = open(device, O_WRONLY, 0666);
102 TEST_AND_RETURN_FALSE(fd >= 0);
103 ScopedFdCloser fd_closer(&fd);
104
105 ssize_t bytes_written = 0;
106 while (bytes_written < buffer_len) {
107 ssize_t r = write(fd, buffer + bytes_written, buffer_len - bytes_written);
108 TEST_AND_RETURN_FALSE_ERRNO(r >= 0);
109 bytes_written += r;
110 }
111 TEST_AND_RETURN_FALSE(bytes_written == buffer_len);
112
113 return true;
114 }
115
116
117 } // namespace chromeos_update_engine 77 } // namespace chromeos_update_engine
OLDNEW
« 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