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

Side by Side Diff: reboot_mode.cc

Issue 2656004: add c++ version of the firmware utilities (Closed) Base URL: ssh://gitrw.chromium.org/firmware-utils.git
Patch Set: removed python scripts and add comments for range names in gpio Created 10 years, 6 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
« no previous file with comments | « gpio_setup.py ('k') | reboot_mode.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // NOTE: this file is translated from reboot_mode.py
6 //
7 // A script to manipulate ChromeOS CMOS reboot Field.
8 //
9 // A few bits in a byte in CMOS (called RDB, short for 'Reboot Data Byte'
10 // hereafter) are dedicated to information exchange between Linux and BIOS.
11 //
12 // The CMOS contents are available through /dev/nvrom. The location of RDB is
13 // reported by BIOS through ACPI. The few bits in RDB operated on by this script
14 // are defined in the all_mode_fields dictionary below along with their
15 // functions.
16 //
17 // When invoked without parameters this script prints values of the fields. When
18 // invoked with any of the bit field names as parameter(s), the script sets the
19 // bit(s) as required.
20 //
21 // Additional parameters allow to specify alternative ACPI and NVRAM files for
22 // testing.
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <assert.h>
27 #include <unistd.h>
28 #include <sys/param.h>
29 #include <stdint.h>
30 #include <errno.h>
31 #include <stdarg.h>
32 #include <getopt.h>
33
34 #include <string>
35 #include <algorithm>
36 #include <vector>
37 #include <map>
38
39 #define DEFAULT_ACPI_FILE "/sys/devices/platform/chromeos_acpi/CHNV"
40 #define DEFAULT_NVRAM_FILE "/dev/nvram"
41
42 ///////////////////////////////////////////////////////////////////////
43 // Utilities for quick python-C translation
44
45 using std::string;
46
47 // Works like throwing an exception - directly exit here.
48 static void RebootModeError(const char *message, ...) {
49 va_list args;
50 va_start(args, message);
51 vfprintf(stderr, message, args);
52 fprintf(stderr, "\n");
53 va_end(args);
54 exit(1);
55 }
56
57 // return a string which is upper case of input parameter.
58 static string str_to_upper(const string str) {
59 string newstr = str;
60 std::transform(str.begin(), str.end(), newstr.begin(), toupper);
61 return newstr;
62 }
63
64 ///////////////////////////////////////////////////////////////////////
65
66 typedef std::map<string, uint8_t> RDB_BitField;
67
68 struct RebootModeConfig {
69 // file path
70 string acpi_file;
71 string nvram_file;
72
73 // Offset of RDB in NVRAM
74 int rdb_offset;
75
76 // NVRAM contents read on startup
77 uint8_t rdb_value;
78
79 // A dictionary of fields to be updated as requested by the command line
80 // parameters
81 RDB_BitField fields_to_set;
82
83 // All bitfields in RDB this script provides access to. Field names prepended
84 // by `--' become this script's command line options
85 RDB_BitField all_mode_fields;
86
87 // write constructure here to ease python translation
88 RebootModeConfig() {
89 acpi_file = DEFAULT_ACPI_FILE;
90 nvram_file = DEFAULT_NVRAM_FILE;
91 rdb_offset = 0;
92 all_mode_fields["recovery"] = 0x80;
93 all_mode_fields["debug_reset"] = 0x40;
94 all_mode_fields["try_firmware_b"] = 0x20;
95 }
96 } cfg; // this is a special global object to ease python translation.
97
98 // Process bit field name command line parameter.
99 //
100 // Verifies that the value is in range (0 or 1) and adds the appropriate
101 // element to fields_to_set dictionary. Should the same field specified in the
102 // command line more than once, only the last value will be used.
103 //
104 // Raises:
105 // RebootModeError in case the parameter value is out of range.
106 void OptionHandler(const char *opt_str, const char *value_str) {
107 const char *key = opt_str;
108 int value = atoi(value_str);
109
110 if (!value && *value_str != '0')
111 RebootModeError("--%s needs numeric argument value", key);
112
113 if (value < 0 || value > 1)
114 RebootModeError("--%s should be either 0 or 1", key);
115
116 if (cfg.all_mode_fields.find(key) == cfg.all_mode_fields.end())
117 RebootModeError("INTERNAL ERROR: UNKNOWN FIELD: %s", key);
118
119 cfg.fields_to_set[key] = value;
120 }
121
122 void GetRDBOffset() {
123 const char *acpi_file = cfg.acpi_file.c_str();
124
125 FILE *f = fopen(acpi_file, "rb");
126 if (!f) {
127 perror(acpi_file);
128 RebootModeError("Cannot read acpi_file: %s", acpi_file);
129 }
130
131 char buffer[PATH_MAX]; // this should be large enough
132 if (fgets(buffer, sizeof(buffer), f) == NULL) {
133 perror(acpi_file);
134 RebootModeError("Trying to read %s but failed.", acpi_file);
135 }
136
137 cfg.rdb_offset = atoi(buffer);
138 if (!cfg.rdb_offset && *buffer != '0') { // consider this as error
139 RebootModeError("%s contents are corrupted", acpi_file);
140 }
141 }
142
143 void ReadNvram() {
144 FILE *f = fopen(cfg.nvram_file.c_str(), "rb");
145 if (!f) {
146 if (errno == 2)
147 RebootModeError("%s does not exist. Is nvram module installed?",
148 cfg.nvram_file.c_str());
149 if (errno == 13)
150 RebootModeError("Access to %s denied. Are you root?",
151 cfg.nvram_file.c_str());
152 // all other error
153 perror(cfg.nvram_file.c_str());
154 }
155
156 if (fseek(f, cfg.rdb_offset, SEEK_SET) == -1 ||
157 fread(&cfg.rdb_value, 1, 1, f) != 1) {
158 perror(cfg.nvram_file.c_str());
159 RebootModeError("Failed reading mode byte from %s", cfg.nvram_file.c_str());
160 }
161 fclose(f);
162 }
163
164 void PrintCurrentMode() {
165 printf("Current reboot mode settings:\n");
166 for (RDB_BitField::iterator i = cfg.all_mode_fields.begin();
167 i != cfg.all_mode_fields.end();
168 ++i) {
169 printf("%-15s: %d\n", i->first.c_str(),
170 (cfg.rdb_value & i->second) ? 1 : 0);
171 }
172 }
173
174 void SetNewMode() {
175 uint8_t new_mode = 0;
176 uint8_t updated_bits_mask = 0;
177
178 for (RDB_BitField::iterator i = cfg.fields_to_set.begin();
179 i != cfg.fields_to_set.end();
180 ++i) {
181 string opt = i->first;
182 uint8_t value = i->second;
183 assert(cfg.all_mode_fields.find(opt) != cfg.all_mode_fields.end());
184
185 uint8_t mask = cfg.all_mode_fields[opt];
186 if (value)
187 new_mode |= mask;
188
189 updated_bits_mask |= mask;
190 }
191
192 if ((cfg.rdb_value & updated_bits_mask) == new_mode) {
193 printf("No update required\n");
194 return;
195 }
196
197 FILE *f = fopen(cfg.nvram_file.c_str(), "rb+");
198 fseek(f, cfg.rdb_offset, SEEK_SET);
199 new_mode |= (cfg.rdb_value & ~updated_bits_mask);
200 if (fwrite(&new_mode, 1, 1, f) != 1) {
201 RebootModeError("Failed writing mode byte to %s", cfg.nvram_file.c_str());
202 }
203 fclose(f);
204 }
205
206 const char *__name__;
207
208 void usage_help_exit(int err) {
209 printf("Usage: %s [options]\n"
210 "\n"
211 "Options:\n"
212 " -h, --help\t\tshow this help message and exit\n"
213 " --acpi_file=ACPI_FILE\n"
214 " --nvram_file=NVRAM_FILE\n"
215 , __name__);
216
217 // list all possible fields
218 for (RDB_BitField::iterator i = cfg.all_mode_fields.begin();
219 i != cfg.all_mode_fields.end();
220 ++i) {
221 printf(" --%s=%s\n",
222 i->first.c_str(),
223 str_to_upper(i->first).c_str());
224 }
225 exit(err);
226 }
227
228 int main(int argc, char *argv[]) {
229 __name__ = argv[0];
230
231 struct option optv = {0};
232 std::vector<struct option> longopts;
233 int max_field_index = 0;
234
235 optv.has_arg = 0;
236 optv.val = 0;
237 optv.name = "help"; // value = 0
238 longopts.push_back(optv);
239 optv.has_arg = 1;
240
241 optv.val++;
242 optv.name = "acpi_file"; // value = 1
243 longopts.push_back(optv);
244 optv.val++;
245 optv.name = "nvram_file"; // value = 2
246 longopts.push_back(optv);
247
248 // add all known RDB fields
249 for (RDB_BitField::iterator i = cfg.all_mode_fields.begin();
250 i != cfg.all_mode_fields.end();
251 ++i) {
252 optv.name = i->first.c_str();
253 optv.val++;
254 longopts.push_back(optv);
255 }
256 max_field_index = optv.val;
257
258 // add a zero for closing options
259 optv.name = NULL;
260 optv.val = optv.has_arg = 0;
261 longopts.push_back(optv);
262
263 int optc;
264 while ((optc = getopt_long(argc, argv, "h", &longopts.front(), NULL)) != -1) {
265 switch (optc) {
266 case 1:
267 cfg.acpi_file = optarg;
268 break;
269
270 case 2:
271 cfg.nvram_file = optarg;
272 break;
273
274 default:
275 // RDB fields?
276 // printf("optc: %d %s %s\n", optc, longopts[optc].name, optarg);
277 if (optc > 0 && optc <= max_field_index)
278 OptionHandler(longopts[optc].name, optarg);
279 else
280 usage_help_exit(1);
281 break;
282 }
283 }
284
285 // currently no other non-dashed arguments allowed.
286 if (optind != argc)
287 usage_help_exit(1);
288
289 GetRDBOffset();
290 ReadNvram();
291
292 if (!cfg.fields_to_set.empty()) {
293 SetNewMode();
294 } else {
295 PrintCurrentMode();
296 }
297 return 0;
298 }
OLDNEW
« no previous file with comments | « gpio_setup.py ('k') | reboot_mode.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698