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

Side by Side Diff: cgpt/cgpt_common.c

Issue 3594010: Address some security concerns in the cgpt tool. (Closed) Base URL: http://git.chromium.org/git/vboot_reference.git
Patch Set: A little more cleanup. Take one more look, please. Created 10 years, 2 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 | Annotate | Revision Log
« no previous file with comments | « cgpt/cgpt.h ('k') | cgpt/cmd_add.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* Copyright (c) 2010 The Chromium OS Authors. All rights reserved. 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 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 * Utility for ChromeOS-specific GPT partitions, Please see corresponding .c 5 * Utility for ChromeOS-specific GPT partitions, Please see corresponding .c
6 * files for more details. 6 * files for more details.
7 */ 7 */
8 8
9 #include "cgpt.h" 9 #include "cgpt.h"
10 10
11 #include <errno.h> 11 #include <errno.h>
12 #include <fcntl.h> 12 #include <fcntl.h>
13 #include <getopt.h> 13 #include <getopt.h>
14 #include <stdarg.h>
14 #include <stdint.h> 15 #include <stdint.h>
15 #include <stdio.h> 16 #include <stdio.h>
16 #include <stdlib.h> 17 #include <stdlib.h>
17 #include <string.h> 18 #include <string.h>
18 #include <sys/ioctl.h> 19 #include <sys/ioctl.h>
19 #include <sys/mount.h> 20 #include <sys/mount.h>
20 #include <sys/stat.h> 21 #include <sys/stat.h>
21 #include <sys/types.h> 22 #include <sys/types.h>
22 #include <unistd.h> 23 #include <unistd.h>
23 #include <assert.h>
24 #include <stdarg.h>
25 24
26 #include "cgptlib_internal.h" 25 #include "cgptlib_internal.h"
27 #include "crc32.h" 26 #include "crc32.h"
28 27
29
30 void Error(const char *format, ...) { 28 void Error(const char *format, ...) {
31 va_list ap; 29 va_list ap;
32 va_start(ap, format); 30 va_start(ap, format);
33 fprintf(stderr, "ERROR: %s %s: ", progname, command); 31 fprintf(stderr, "ERROR: %s %s: ", progname, command);
34 vfprintf(stderr, format, ap); 32 vfprintf(stderr, format, ap);
35 va_end(ap); 33 va_end(ap);
36 } 34 }
37 35
38 36
39 int CheckValid(const struct drive *drive) { 37 int CheckValid(const struct drive *drive) {
(...skipping 18 matching lines...) Expand all
58 * 56 *
59 * Returns CGPT_OK for successful. Aborts if any error occurs. 57 * Returns CGPT_OK for successful. Aborts if any error occurs.
60 */ 58 */
61 static int Load(const int fd, uint8_t **buf, 59 static int Load(const int fd, uint8_t **buf,
62 const uint64_t sector, 60 const uint64_t sector,
63 const uint64_t sector_bytes, 61 const uint64_t sector_bytes,
64 const uint64_t sector_count) { 62 const uint64_t sector_count) {
65 int count; /* byte count to read */ 63 int count; /* byte count to read */
66 int nread; 64 int nread;
67 65
68 assert(buf); 66 require(buf);
67 if (!sector_count || !sector_bytes) {
68 Error("%s() failed at line %d: sector_count=%d, sector_bytes=%d\n",
69 __FUNCTION__, __LINE__, sector_count, sector_bytes);
70 return CGPT_FAILED;
71 }
72 /* Make sure that sector_bytes * sector_count doesn't roll over. */
73 if (sector_bytes > (UINT64_MAX / sector_count)) {
74 Error("%s() failed at line %d: sector_count=%d, sector_bytes=%d\n",
75 __FUNCTION__, __LINE__, sector_count, sector_bytes);
76 return CGPT_FAILED;
77 }
69 count = sector_bytes * sector_count; 78 count = sector_bytes * sector_count;
70 *buf = malloc(count); 79 *buf = malloc(count);
71 assert(*buf); 80 require(*buf);
72 81
73 if (-1 == lseek(fd, sector * sector_bytes, SEEK_SET)) 82 if (-1 == lseek(fd, sector * sector_bytes, SEEK_SET)) {
83 Error("Can't lseek: %s\n", strerror(errno));
74 goto error_free; 84 goto error_free;
85 }
75 86
76 nread = read(fd, *buf, count); 87 nread = read(fd, *buf, count);
77 if (nread < count) 88 if (nread < count) {
89 Error("Can't read enough: %d, not %d\n", nread, count);
78 goto error_free; 90 goto error_free;
91 }
79 92
80 return CGPT_OK; 93 return CGPT_OK;
81 94
82 error_free: 95 error_free:
83 free(*buf); 96 free(*buf);
84 *buf = 0; 97 *buf = 0;
85 return CGPT_FAILED; 98 return CGPT_FAILED;
86 } 99 }
87 100
88 101
(...skipping 29 matching lines...) Expand all
118 * 131 *
119 * Returns CGPT_OK for successful, CGPT_FAILED for failed. 132 * Returns CGPT_OK for successful, CGPT_FAILED for failed.
120 */ 133 */
121 static int Save(const int fd, const uint8_t *buf, 134 static int Save(const int fd, const uint8_t *buf,
122 const uint64_t sector, 135 const uint64_t sector,
123 const uint64_t sector_bytes, 136 const uint64_t sector_bytes,
124 const uint64_t sector_count) { 137 const uint64_t sector_count) {
125 int count; /* byte count to write */ 138 int count; /* byte count to write */
126 int nwrote; 139 int nwrote;
127 140
128 assert(buf); 141 require(buf);
129 count = sector_bytes * sector_count; 142 count = sector_bytes * sector_count;
130 143
131 if (-1 == lseek(fd, sector * sector_bytes, SEEK_SET)) 144 if (-1 == lseek(fd, sector * sector_bytes, SEEK_SET))
132 return CGPT_FAILED; 145 return CGPT_FAILED;
133 146
134 nwrote = write(fd, buf, count); 147 nwrote = write(fd, buf, count);
135 if (nwrote < count) 148 if (nwrote < count)
136 return CGPT_FAILED; 149 return CGPT_FAILED;
137 150
138 return CGPT_OK; 151 return CGPT_OK;
139 } 152 }
140 153
141 154
142 // Opens a block device or file, loads raw GPT data from it. 155 // Opens a block device or file, loads raw GPT data from it.
143 // 156 //
144 // Returns CGPT_FAILED if any error happens. 157 // Returns CGPT_FAILED if any error happens.
145 // Returns CGPT_OK if success and information are stored in 'drive'. */ 158 // Returns CGPT_OK if success and information are stored in 'drive'. */
146 int DriveOpen(const char *drive_path, struct drive *drive) { 159 int DriveOpen(const char *drive_path, struct drive *drive) {
147 struct stat stat; 160 struct stat stat;
148 161
149 assert(drive_path); 162 require(drive_path);
150 assert(drive); 163 require(drive);
151 164
152 // Clear struct for proper error handling. 165 // Clear struct for proper error handling.
153 memset(drive, 0, sizeof(struct drive)); 166 memset(drive, 0, sizeof(struct drive));
154 167
155 drive->fd = open(drive_path, O_RDWR | O_LARGEFILE); 168 drive->fd = open(drive_path, O_RDWR | O_LARGEFILE | O_NOFOLLOW);
156 if (drive->fd == -1) { 169 if (drive->fd == -1) {
157 Error("Can't open %s: %s\n", drive_path, strerror(errno)); 170 Error("Can't open %s: %s\n", drive_path, strerror(errno));
158 return CGPT_FAILED; 171 return CGPT_FAILED;
159 } 172 }
160 173
161 if (fstat(drive->fd, &stat) == -1) { 174 if (fstat(drive->fd, &stat) == -1) {
175 Error("Can't fstat %s: %s\n", drive_path, strerror(errno));
162 goto error_close; 176 goto error_close;
163 } 177 }
164 if ((stat.st_mode & S_IFMT) != S_IFREG) { 178 if ((stat.st_mode & S_IFMT) != S_IFREG) {
165 if (ioctl(drive->fd, BLKGETSIZE64, &drive->size) < 0) { 179 if (ioctl(drive->fd, BLKGETSIZE64, &drive->size) < 0) {
166 Error("Can't read drive size from %s: %s\n", drive_path, strerror(errno)); 180 Error("Can't read drive size from %s: %s\n", drive_path, strerror(errno));
167 goto error_close; 181 goto error_close;
168 } 182 }
169 if (ioctl(drive->fd, BLKSSZGET, &drive->gpt.sector_bytes) < 0) { 183 if (ioctl(drive->fd, BLKSSZGET, &drive->gpt.sector_bytes) < 0) {
170 Error("Can't read sector size from %s: %s\n", 184 Error("Can't read sector size from %s: %s\n",
171 drive_path, strerror(errno)); 185 drive_path, strerror(errno));
(...skipping 25 matching lines...) Expand all
197 GPT_PMBR_SECTOR + GPT_HEADER_SECTOR, 211 GPT_PMBR_SECTOR + GPT_HEADER_SECTOR,
198 drive->gpt.sector_bytes, GPT_ENTRIES_SECTORS)) { 212 drive->gpt.sector_bytes, GPT_ENTRIES_SECTORS)) {
199 goto error_close; 213 goto error_close;
200 } 214 }
201 if (CGPT_OK != Load(drive->fd, &drive->gpt.secondary_entries, 215 if (CGPT_OK != Load(drive->fd, &drive->gpt.secondary_entries,
202 drive->gpt.drive_sectors - GPT_HEADER_SECTOR 216 drive->gpt.drive_sectors - GPT_HEADER_SECTOR
203 - GPT_ENTRIES_SECTORS, 217 - GPT_ENTRIES_SECTORS,
204 drive->gpt.sector_bytes, GPT_ENTRIES_SECTORS)) { 218 drive->gpt.sector_bytes, GPT_ENTRIES_SECTORS)) {
205 goto error_close; 219 goto error_close;
206 } 220 }
207 221
208 // We just load the data. Caller must validate it. 222 // We just load the data. Caller must validate it.
209 return CGPT_OK; 223 return CGPT_OK;
210 224
211 error_close: 225 error_close:
212 (void) DriveClose(drive, 0); 226 (void) DriveClose(drive, 0);
213 return CGPT_FAILED; 227 return CGPT_FAILED;
214 } 228 }
215 229
216 230
217 int DriveClose(struct drive *drive, int update_as_needed) { 231 int DriveClose(struct drive *drive, int update_as_needed) {
218 int errors = 0; 232 int errors = 0;
219 233
220 if (update_as_needed) { 234 if (update_as_needed) {
221 if (drive->gpt.modified & GPT_MODIFIED_HEADER1) { 235 if (drive->gpt.modified & GPT_MODIFIED_HEADER1) {
222 if (CGPT_OK != Save(drive->fd, drive->gpt.primary_header, 236 if (CGPT_OK != Save(drive->fd, drive->gpt.primary_header,
223 GPT_PMBR_SECTOR, 237 GPT_PMBR_SECTOR,
224 drive->gpt.sector_bytes, GPT_HEADER_SECTOR)) { 238 drive->gpt.sector_bytes, GPT_HEADER_SECTOR)) {
225 errors++; 239 errors++;
226 Error("Cannot write primary header: %s\n", strerror(errno)); 240 Error("Cannot write primary header: %s\n", strerror(errno));
227 } 241 }
228 } 242 }
229 243
230 if (drive->gpt.modified & GPT_MODIFIED_HEADER2) { 244 if (drive->gpt.modified & GPT_MODIFIED_HEADER2) {
231 if(CGPT_OK != Save(drive->fd, drive->gpt.secondary_header, 245 if(CGPT_OK != Save(drive->fd, drive->gpt.secondary_header,
232 drive->gpt.drive_sectors - GPT_PMBR_SECTOR, 246 drive->gpt.drive_sectors - GPT_PMBR_SECTOR,
233 drive->gpt.sector_bytes, GPT_HEADER_SECTOR)) { 247 drive->gpt.sector_bytes, GPT_HEADER_SECTOR)) {
234 errors++; 248 errors++;
235 Error("Cannot write secondary header: %s\n", strerror(errno)); 249 Error("Cannot write secondary header: %s\n", strerror(errno));
236 } 250 }
237 } 251 }
238 if (drive->gpt.modified & GPT_MODIFIED_ENTRIES1) { 252 if (drive->gpt.modified & GPT_MODIFIED_ENTRIES1) {
239 if (CGPT_OK != Save(drive->fd, drive->gpt.primary_entries, 253 if (CGPT_OK != Save(drive->fd, drive->gpt.primary_entries,
(...skipping 26 matching lines...) Expand all
266 free(drive->gpt.secondary_header); 280 free(drive->gpt.secondary_header);
267 drive->gpt.secondary_header = 0; 281 drive->gpt.secondary_header = 0;
268 if (drive->gpt.secondary_entries) 282 if (drive->gpt.secondary_entries)
269 free(drive->gpt.secondary_entries); 283 free(drive->gpt.secondary_entries);
270 drive->gpt.secondary_entries = 0; 284 drive->gpt.secondary_entries = 0;
271 285
272 return errors ? CGPT_FAILED : CGPT_OK; 286 return errors ? CGPT_FAILED : CGPT_OK;
273 } 287 }
274 288
275 289
276
277 /* GUID conversion functions. Accepted format: 290 /* GUID conversion functions. Accepted format:
278 * 291 *
279 * "C12A7328-F81F-11D2-BA4B-00A0C93EC93B" 292 * "C12A7328-F81F-11D2-BA4B-00A0C93EC93B"
280 * 293 *
281 * Returns CGPT_OK if parsing is successful; otherwise CGPT_FAILED. 294 * Returns CGPT_OK if parsing is successful; otherwise CGPT_FAILED.
282 */ 295 */
283 int StrToGuid(const char *str, Guid *guid) { 296 int StrToGuid(const char *str, Guid *guid) {
284 uint32_t time_low; 297 uint32_t time_low;
285 uint16_t time_mid; 298 uint16_t time_mid;
286 uint16_t time_high_and_version; 299 uint16_t time_high_and_version;
287 unsigned int chunk[11]; 300 unsigned int chunk[11];
288 301
289 if (11 != sscanf(str, "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", 302 if (11 != sscanf(str, "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
290 chunk+0, 303 chunk+0,
291 chunk+1, 304 chunk+1,
292 chunk+2, 305 chunk+2,
293 chunk+3, 306 chunk+3,
294 chunk+4, 307 chunk+4,
295 chunk+5, 308 chunk+5,
296 chunk+6, 309 chunk+6,
297 chunk+7, 310 chunk+7,
298 chunk+8, 311 chunk+8,
299 chunk+9, 312 chunk+9,
300 chunk+10)) { 313 chunk+10)) {
301 printf("FAILED\n"); 314 printf("FAILED\n");
302 return CGPT_FAILED; 315 return CGPT_FAILED;
303 } 316 }
304 317
305 time_low = chunk[0] & 0xffffffff; 318 time_low = chunk[0] & 0xffffffff;
306 time_mid = chunk[1] & 0xffff; 319 time_mid = chunk[1] & 0xffff;
307 time_high_and_version = chunk[2] & 0xffff; 320 time_high_and_version = chunk[2] & 0xffff;
308 321
309 guid->u.Uuid.time_low = htole32(time_low); 322 guid->u.Uuid.time_low = htole32(time_low);
310 guid->u.Uuid.time_mid = htole16(time_mid); 323 guid->u.Uuid.time_mid = htole16(time_mid);
311 guid->u.Uuid.time_high_and_version = htole16(time_high_and_version); 324 guid->u.Uuid.time_high_and_version = htole16(time_high_and_version);
312 325
313 guid->u.Uuid.clock_seq_high_and_reserved = chunk[3] & 0xff; 326 guid->u.Uuid.clock_seq_high_and_reserved = chunk[3] & 0xff;
314 guid->u.Uuid.clock_seq_low = chunk[4] & 0xff; 327 guid->u.Uuid.clock_seq_low = chunk[4] & 0xff;
315 guid->u.Uuid.node[0] = chunk[5] & 0xff; 328 guid->u.Uuid.node[0] = chunk[5] & 0xff;
316 guid->u.Uuid.node[1] = chunk[6] & 0xff; 329 guid->u.Uuid.node[1] = chunk[6] & 0xff;
317 guid->u.Uuid.node[2] = chunk[7] & 0xff; 330 guid->u.Uuid.node[2] = chunk[7] & 0xff;
318 guid->u.Uuid.node[3] = chunk[8] & 0xff; 331 guid->u.Uuid.node[3] = chunk[8] & 0xff;
319 guid->u.Uuid.node[4] = chunk[9] & 0xff; 332 guid->u.Uuid.node[4] = chunk[9] & 0xff;
320 guid->u.Uuid.node[5] = chunk[10] & 0xff; 333 guid->u.Uuid.node[5] = chunk[10] & 0xff;
321 334
322 return CGPT_OK; 335 return CGPT_OK;
323 } 336 }
324 void GuidToStr(const Guid *guid, char *str) { 337 void GuidToStr(const Guid *guid, char *str, unsigned int buflen) {
325 sprintf(str, "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", 338 require(buflen >= GUID_STRLEN);
326 le32toh(guid->u.Uuid.time_low), le16toh(guid->u.Uuid.time_mid), 339 require(snprintf(str, buflen,
327 le16toh(guid->u.Uuid.time_high_and_version), 340 "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
328 guid->u.Uuid.clock_seq_high_and_reserved, guid->u.Uuid.clock_seq_low, 341 le32toh(guid->u.Uuid.time_low),
329 guid->u.Uuid.node[0], guid->u.Uuid.node[1], guid->u.Uuid.node[2], 342 le16toh(guid->u.Uuid.time_mid),
330 guid->u.Uuid.node[3], guid->u.Uuid.node[4], guid->u.Uuid.node[5]); 343 le16toh(guid->u.Uuid.time_high_and_version),
344 guid->u.Uuid.clock_seq_high_and_reserved,
345 guid->u.Uuid.clock_seq_low,
346 guid->u.Uuid.node[0], guid->u.Uuid.node[1],
347 guid->u.Uuid.node[2], guid->u.Uuid.node[3],
348 guid->u.Uuid.node[4], guid->u.Uuid.node[5]) == GUID_STRLEN-1);
331 } 349 }
332 350
333 /* Convert UTF16 string to UTF8. Rewritten from gpt utility. 351 /* Convert possibly unterminated UTF16 string to UTF8.
334 * Caller must prepare enough space for UTF8. The rough estimation is: 352 * Caller must prepare enough space for UTF8, which could be up to
335 * 353 * twice the number of UTF16 chars plus the terminating '\0'.
336 * utf8 length = bytecount(utf16) * 1.5 354 * FIXME(wfrichar): The original implementation had security issues. As a
355 * temporary fix, I'm making this ONLY support ASCII codepoints. Bug 7542
356 * (http://code.google.com/p/chromium-os/issues/detail?id=7542) is filed to fix
357 * this.
337 */ 358 */
338 #define SIZEOF_GPTENTRY_NAME 36 /* sizeof(GptEntry.name[]) */ 359 void UTF16ToUTF8(const uint16_t *utf16, unsigned int maxinput,
339 void UTF16ToUTF8(const uint16_t *utf16, uint8_t *utf8) 360 uint8_t *utf8, unsigned int maxoutput)
340 { 361 {
341 size_t s8idx, s16idx, s16len; 362 size_t s16idx, s8idx;
342 uint32_t utfchar; 363 uint32_t utfchar;
343 unsigned int next_utf16;
344 364
345 for (s16len = 0; s16len < SIZEOF_GPTENTRY_NAME && utf16[s16len]; ++s16len); 365 if (!utf16 || !maxinput || !utf8 || !maxoutput)
366 return;
346 367
347 *utf8 = s8idx = s16idx = 0; 368 maxoutput--; /* plan for termination now */
348 while (s16idx < s16len) { 369
349 utfchar = le16toh(utf16[s16idx++]); 370 for (s16idx = s8idx = 0;
350 if ((utfchar & 0xf800) == 0xd800) { 371 s16idx < maxinput && utf16[s16idx] && maxoutput;
351 next_utf16 = le16toh(utf16[s16idx]); 372 s16idx++, maxoutput--) {
352 if ((utfchar & 0x400) != 0 || (next_utf16 & 0xfc00) != 0xdc00) 373 utfchar = le16toh(utf16[s16idx]);
353 utfchar = 0xfffd; 374 utf8[s8idx++] = utfchar & 0x7F;
354 else
355 s16idx++;
356 }
357 if (utfchar < 0x80) {
358 utf8[s8idx++] = utfchar;
359 } else if (utfchar < 0x800) {
360 utf8[s8idx++] = 0xc0 | (utfchar >> 6);
361 utf8[s8idx++] = 0x80 | (utfchar & 0x3f);
362 } else if (utfchar < 0x10000) {
363 utf8[s8idx++] = 0xe0 | (utfchar >> 12);
364 utf8[s8idx++] = 0x80 | ((utfchar >> 6) & 0x3f);
365 utf8[s8idx++] = 0x80 | (utfchar & 0x3f);
366 } else if (utfchar < 0x200000) {
367 utf8[s8idx++] = 0xf0 | (utfchar >> 18);
368 utf8[s8idx++] = 0x80 | ((utfchar >> 12) & 0x3f);
369 utf8[s8idx++] = 0x80 | ((utfchar >> 6) & 0x3f);
370 utf8[s8idx++] = 0x80 | (utfchar & 0x3f);
371 }
372 } 375 }
373 utf8[s8idx++] = 0; 376 utf8[s8idx++] = 0;
374 } 377 }
375 378
376 /* Convert UTF8 string to UTF16. Rewritten from gpt utility. 379 /* Convert UTF8 string to UTF16. The UTF8 string must be null-terminated.
377 * Caller must prepare enough space for UTF16. The conservative estimation is: 380 * Caller must prepare enough space for UTF16, including a terminating 0x0000.
378 * 381 * FIXME(wfrichar): The original implementation had security issues. As a
379 * utf16 bytecount = bytecount(utf8) / 3 * 4 382 * temporary fix, I'm making this ONLY support ASCII codepoints. Bug 7542
383 * (http://code.google.com/p/chromium-os/issues/detail?id=7542) is filed to fix
384 * this.
380 */ 385 */
381 void UTF8ToUTF16(const uint8_t *utf8, uint16_t *utf16) 386 void UTF8ToUTF16(const uint8_t *utf8, uint16_t *utf16, unsigned int maxoutput)
382 { 387 {
383 size_t s16idx, s8idx, s8len; 388 size_t s16idx, s8idx;
384 uint32_t utfchar; 389 uint32_t utfchar;
385 unsigned int c, utfbytes;
386 390
387 for (s8len = 0; utf8[s8len]; ++s8len); 391 if (!utf8 || !utf16 || !maxoutput)
392 return;
388 393
389 s8idx = s16idx = 0; 394 maxoutput--; /* plan for termination */
390 utfbytes = 0; 395
391 do { 396 for (s8idx = s16idx = 0;
392 c = utf8[s8idx++]; 397 utf8[s8idx] && maxoutput;
393 if ((c & 0xc0) != 0x80) { 398 s8idx++, maxoutput--) {
394 /* Initial characters. */ 399 utfchar = utf8[s8idx];
395 if (utfbytes != 0) { 400 utf16[s16idx++] = utfchar & 0x7F;
396 /* Incomplete encoding. */ 401 }
397 utf16[s16idx++] = 0xfffd; 402 utf16[s16idx++] = 0;
398 }
399 if ((c & 0xf8) == 0xf0) {
400 utfchar = c & 0x07;
401 utfbytes = 3;
402 } else if ((c & 0xf0) == 0xe0) {
403 utfchar = c & 0x0f;
404 utfbytes = 2;
405 } else if ((c & 0xe0) == 0xc0) {
406 utfchar = c & 0x1f;
407 utfbytes = 1;
408 } else {
409 utfchar = c & 0x7f;
410 utfbytes = 0;
411 }
412 } else {
413 /* Followup characters. */
414 if (utfbytes > 0) {
415 utfchar = (utfchar << 6) + (c & 0x3f);
416 utfbytes--;
417 } else if (utfbytes == 0)
418 utfbytes = -1;
419 utfchar = 0xfffd;
420 }
421 if (utfbytes == 0) {
422 if (utfchar >= 0x10000) {
423 utf16[s16idx++] = htole16(0xd800 | ((utfchar>>10)-0x40));
424 if (s16idx >= SIZEOF_GPTENTRY_NAME) break;
425 utf16[s16idx++] = htole16(0xdc00 | (utfchar & 0x3ff));
426 } else {
427 utf16[s16idx++] = htole16(utfchar);
428 }
429 }
430 } while (c != 0 && s16idx < SIZEOF_GPTENTRY_NAME);
431 if (s16idx < SIZEOF_GPTENTRY_NAME)
432 utf16[s16idx++] = 0;
433 } 403 }
434 404
435 struct { 405 struct {
436 Guid type; 406 Guid type;
437 char *name; 407 char *name;
438 char *description; 408 char *description;
439 } supported_types[] = { 409 } supported_types[] = {
440 {GPT_ENT_TYPE_CHROMEOS_KERNEL, "kernel", "ChromeOS kernel"}, 410 {GPT_ENT_TYPE_CHROMEOS_KERNEL, "kernel", "ChromeOS kernel"},
441 {GPT_ENT_TYPE_CHROMEOS_ROOTFS, "rootfs", "ChromeOS rootfs"}, 411 {GPT_ENT_TYPE_CHROMEOS_ROOTFS, "rootfs", "ChromeOS rootfs"},
442 {GPT_ENT_TYPE_LINUX_DATA, "data", "Linux data"}, 412 {GPT_ENT_TYPE_LINUX_DATA, "data", "Linux data"},
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
492 } 462 }
493 463
494 static uint32_t GetSizeOfEntries(const GptData *gpt) { 464 static uint32_t GetSizeOfEntries(const GptData *gpt) {
495 GptHeader *header = 0; 465 GptHeader *header = 0;
496 if (gpt->valid_headers & MASK_PRIMARY) 466 if (gpt->valid_headers & MASK_PRIMARY)
497 header = (GptHeader*)gpt->primary_header; 467 header = (GptHeader*)gpt->primary_header;
498 else if (gpt->valid_headers & MASK_SECONDARY) 468 else if (gpt->valid_headers & MASK_SECONDARY)
499 header = (GptHeader*)gpt->secondary_header; 469 header = (GptHeader*)gpt->secondary_header;
500 else 470 else
501 return 0; 471 return 0;
502 return header->number_of_entries; 472 return header->size_of_entry;
503 } 473 }
504 474
505 GptEntry *GetEntry(GptData *gpt, int secondary, int entry_index) { 475 GptEntry *GetEntry(GptData *gpt, int secondary, uint32_t entry_index) {
506 uint8_t *entries; 476 uint8_t *entries;
507 int stride = GetSizeOfEntries(gpt); 477 uint32_t stride = GetSizeOfEntries(gpt);
508 if (!stride) 478 require(stride);
509 return 0; 479 require(entry_index < GetNumberOfEntries(gpt));
510 480
511 if (secondary == PRIMARY) { 481 if (secondary == PRIMARY) {
512 entries = gpt->primary_entries; 482 entries = gpt->primary_entries;
513 } else { 483 } else {
514 entries = gpt->secondary_entries; 484 entries = gpt->secondary_entries;
515 } 485 }
516 486
517 return (GptEntry*)(&entries[stride * entry_index]); 487 return (GptEntry*)(&entries[stride * entry_index]);
518 } 488 }
519 489
520 void SetPriority(GptData *gpt, int secondary, int entry_index, int priority) { 490 void SetPriority(GptData *gpt, int secondary, uint32_t entry_index,
491 int priority) {
521 GptEntry *entry; 492 GptEntry *entry;
522 entry = GetEntry(gpt, secondary, entry_index); 493 entry = GetEntry(gpt, secondary, entry_index);
523 494 require(priority >= 0 && priority <= CGPT_ATTRIBUTE_MAX_PRIORITY);
524 assert(priority >= 0 && priority <= CGPT_ATTRIBUTE_MAX_PRIORITY);
525 entry->attrs.fields.gpt_att &= ~CGPT_ATTRIBUTE_PRIORITY_MASK; 495 entry->attrs.fields.gpt_att &= ~CGPT_ATTRIBUTE_PRIORITY_MASK;
526 entry->attrs.fields.gpt_att |= priority << CGPT_ATTRIBUTE_PRIORITY_OFFSET; 496 entry->attrs.fields.gpt_att |= priority << CGPT_ATTRIBUTE_PRIORITY_OFFSET;
527 } 497 }
528 498
529 int GetPriority(GptData *gpt, int secondary, int entry_index) { 499 int GetPriority(GptData *gpt, int secondary, uint32_t entry_index) {
530 GptEntry *entry; 500 GptEntry *entry;
531 entry = GetEntry(gpt, secondary, entry_index); 501 entry = GetEntry(gpt, secondary, entry_index);
532 return (entry->attrs.fields.gpt_att & CGPT_ATTRIBUTE_PRIORITY_MASK) >> 502 return (entry->attrs.fields.gpt_att & CGPT_ATTRIBUTE_PRIORITY_MASK) >>
533 CGPT_ATTRIBUTE_PRIORITY_OFFSET; 503 CGPT_ATTRIBUTE_PRIORITY_OFFSET;
534 } 504 }
535 505
536 void SetTries(GptData *gpt, int secondary, int entry_index, int tries) { 506 void SetTries(GptData *gpt, int secondary, uint32_t entry_index, int tries) {
537 GptEntry *entry; 507 GptEntry *entry;
538 entry = GetEntry(gpt, secondary, entry_index); 508 entry = GetEntry(gpt, secondary, entry_index);
539 509 require(tries >= 0 && tries <= CGPT_ATTRIBUTE_MAX_TRIES);
540 assert(tries >= 0 && tries <= CGPT_ATTRIBUTE_MAX_TRIES);
541 entry->attrs.fields.gpt_att &= ~CGPT_ATTRIBUTE_TRIES_MASK; 510 entry->attrs.fields.gpt_att &= ~CGPT_ATTRIBUTE_TRIES_MASK;
542 entry->attrs.fields.gpt_att |= tries << CGPT_ATTRIBUTE_TRIES_OFFSET; 511 entry->attrs.fields.gpt_att |= tries << CGPT_ATTRIBUTE_TRIES_OFFSET;
543 } 512 }
544 513
545 int GetTries(GptData *gpt, int secondary, int entry_index) { 514 int GetTries(GptData *gpt, int secondary, uint32_t entry_index) {
546 GptEntry *entry; 515 GptEntry *entry;
547 entry = GetEntry(gpt, secondary, entry_index); 516 entry = GetEntry(gpt, secondary, entry_index);
548 return (entry->attrs.fields.gpt_att & CGPT_ATTRIBUTE_TRIES_MASK) >> 517 return (entry->attrs.fields.gpt_att & CGPT_ATTRIBUTE_TRIES_MASK) >>
549 CGPT_ATTRIBUTE_TRIES_OFFSET; 518 CGPT_ATTRIBUTE_TRIES_OFFSET;
550 } 519 }
551 520
552 void SetSuccessful(GptData *gpt, int secondary, int entry_index, int success) { 521 void SetSuccessful(GptData *gpt, int secondary, uint32_t entry_index,
522 int success) {
553 GptEntry *entry; 523 GptEntry *entry;
554 entry = GetEntry(gpt, secondary, entry_index); 524 entry = GetEntry(gpt, secondary, entry_index);
555 525
556 assert(success >= 0 && success <= CGPT_ATTRIBUTE_MAX_SUCCESSFUL); 526 require(success >= 0 && success <= CGPT_ATTRIBUTE_MAX_SUCCESSFUL);
557 entry->attrs.fields.gpt_att &= ~CGPT_ATTRIBUTE_SUCCESSFUL_MASK; 527 entry->attrs.fields.gpt_att &= ~CGPT_ATTRIBUTE_SUCCESSFUL_MASK;
558 entry->attrs.fields.gpt_att |= success << CGPT_ATTRIBUTE_SUCCESSFUL_OFFSET; 528 entry->attrs.fields.gpt_att |= success << CGPT_ATTRIBUTE_SUCCESSFUL_OFFSET;
559 } 529 }
560 530
561 int GetSuccessful(GptData *gpt, int secondary, int entry_index) { 531 int GetSuccessful(GptData *gpt, int secondary, uint32_t entry_index) {
562 GptEntry *entry; 532 GptEntry *entry;
563 entry = GetEntry(gpt, secondary, entry_index); 533 entry = GetEntry(gpt, secondary, entry_index);
564 return (entry->attrs.fields.gpt_att & CGPT_ATTRIBUTE_SUCCESSFUL_MASK) >> 534 return (entry->attrs.fields.gpt_att & CGPT_ATTRIBUTE_SUCCESSFUL_MASK) >>
565 CGPT_ATTRIBUTE_SUCCESSFUL_OFFSET; 535 CGPT_ATTRIBUTE_SUCCESSFUL_OFFSET;
566 } 536 }
567 537
568 538
569 #define TOSTRING(A) #A 539 #define TOSTRING(A) #A
570 const char *GptError(int errnum) { 540 const char *GptError(int errnum) {
571 const char *error_string[] = { 541 const char *error_string[] = {
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
707 } 677 }
708 678
709 return 0; 679 return 0;
710 } 680 }
711 681
712 682
713 int IsZero(const Guid *gp) { 683 int IsZero(const Guid *gp) {
714 return (0 == memcmp(gp, &guid_unused, sizeof(Guid))); 684 return (0 == memcmp(gp, &guid_unused, sizeof(Guid)));
715 } 685 }
716 686
717 void PMBRToStr(struct pmbr *pmbr, char *str) { 687 void PMBRToStr(struct pmbr *pmbr, char *str, unsigned int buflen) {
718 char buf[256]; 688 char buf[GUID_STRLEN];
719 if (IsZero(&pmbr->boot_guid)) { 689 if (IsZero(&pmbr->boot_guid)) {
720 sprintf(str, "PMBR"); 690 require(snprintf(str, buflen, "PMBR") < buflen);
721 } else { 691 } else {
722 GuidToStr(&pmbr->boot_guid, buf); 692 GuidToStr(&pmbr->boot_guid, buf, sizeof(buf));
723 sprintf(str, "PMBR (Boot GUID: %s)", buf); 693 require(snprintf(str, buflen, "PMBR (Boot GUID: %s)", buf) < buflen);
724 } 694 }
725 } 695 }
726 696
OLDNEW
« no previous file with comments | « cgpt/cgpt.h ('k') | cgpt/cmd_add.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698