cgpt_common.c 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078
  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. * Utility for ChromeOS-specific GPT partitions, Please see corresponding .c
  6. * files for more details.
  7. */
  8. #include <errno.h>
  9. #include <fcntl.h>
  10. #include <getopt.h>
  11. #ifndef HAVE_MACOS
  12. #include <linux/major.h>
  13. #include <mtd/mtd-user.h>
  14. #endif
  15. #include <stdarg.h>
  16. #include <stdint.h>
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include <sys/ioctl.h>
  21. #include <sys/mount.h>
  22. #include <sys/stat.h>
  23. #include <sys/types.h>
  24. #include <unistd.h>
  25. #include "cgpt.h"
  26. #include "cgptlib_internal.h"
  27. #include "crc32.h"
  28. #include "vboot_host.h"
  29. static const char kErrorTag[] = "ERROR";
  30. static const char kWarningTag[] = "WARNING";
  31. static void LogToStderr(const char *tag, const char *format, va_list ap) {
  32. fprintf(stderr, "%s: ", tag);
  33. vfprintf(stderr, format, ap);
  34. }
  35. void Error(const char *format, ...) {
  36. va_list ap;
  37. va_start(ap, format);
  38. LogToStderr(kErrorTag, format, ap);
  39. va_end(ap);
  40. }
  41. void Warning(const char *format, ...) {
  42. va_list ap;
  43. va_start(ap, format);
  44. LogToStderr(kWarningTag, format, ap);
  45. va_end(ap);
  46. }
  47. int check_int_parse(char option, const char *buf) {
  48. if (!*optarg || (buf && *buf)) {
  49. Error("invalid argument to -%c: \"%s\"\n", option, optarg);
  50. return 1;
  51. }
  52. return 0;
  53. }
  54. int check_int_limit(char option, int val, int low, int high) {
  55. if (val < low || val > high) {
  56. Error("value for -%c must be between %d and %d", option, low, high);
  57. return 1;
  58. }
  59. return 0;
  60. }
  61. int CheckValid(const struct drive *drive) {
  62. if ((drive->gpt.valid_headers != MASK_BOTH) ||
  63. (drive->gpt.valid_entries != MASK_BOTH)) {
  64. Warning("One of the GPT headers/entries is invalid\n\n");
  65. return CGPT_FAILED;
  66. }
  67. return CGPT_OK;
  68. }
  69. int Load(struct drive *drive, uint8_t **buf,
  70. const uint64_t sector,
  71. const uint64_t sector_bytes,
  72. const uint64_t sector_count) {
  73. int count; /* byte count to read */
  74. int nread;
  75. require(buf);
  76. if (!sector_count || !sector_bytes) {
  77. Error("%s() failed at line %d: sector_count=%d, sector_bytes=%d\n",
  78. __FUNCTION__, __LINE__, sector_count, sector_bytes);
  79. return CGPT_FAILED;
  80. }
  81. /* Make sure that sector_bytes * sector_count doesn't roll over. */
  82. if (sector_bytes > (UINT64_MAX / sector_count)) {
  83. Error("%s() failed at line %d: sector_count=%d, sector_bytes=%d\n",
  84. __FUNCTION__, __LINE__, sector_count, sector_bytes);
  85. return CGPT_FAILED;
  86. }
  87. count = sector_bytes * sector_count;
  88. *buf = malloc(count);
  89. require(*buf);
  90. if (-1 == lseek(drive->fd, sector * sector_bytes, SEEK_SET)) {
  91. Error("Can't seek: %s\n", strerror(errno));
  92. goto error_free;
  93. }
  94. nread = read(drive->fd, *buf, count);
  95. if (nread < count) {
  96. Error("Can't read enough: %d, not %d\n", nread, count);
  97. goto error_free;
  98. }
  99. return CGPT_OK;
  100. error_free:
  101. free(*buf);
  102. *buf = 0;
  103. return CGPT_FAILED;
  104. }
  105. int ReadPMBR(struct drive *drive) {
  106. if (-1 == lseek(drive->fd, 0, SEEK_SET))
  107. return CGPT_FAILED;
  108. int nread = read(drive->fd, &drive->pmbr, sizeof(struct pmbr));
  109. if (nread != sizeof(struct pmbr))
  110. return CGPT_FAILED;
  111. return CGPT_OK;
  112. }
  113. int WritePMBR(struct drive *drive) {
  114. if (-1 == lseek(drive->fd, 0, SEEK_SET))
  115. return CGPT_FAILED;
  116. int nwrote = write(drive->fd, &drive->pmbr, sizeof(struct pmbr));
  117. if (nwrote != sizeof(struct pmbr))
  118. return CGPT_FAILED;
  119. return CGPT_OK;
  120. }
  121. int Save(struct drive *drive, const uint8_t *buf,
  122. const uint64_t sector,
  123. const uint64_t sector_bytes,
  124. const uint64_t sector_count) {
  125. int count; /* byte count to write */
  126. int nwrote;
  127. require(buf);
  128. count = sector_bytes * sector_count;
  129. if (-1 == lseek(drive->fd, sector * sector_bytes, SEEK_SET))
  130. return CGPT_FAILED;
  131. nwrote = write(drive->fd, buf, count);
  132. if (nwrote < count)
  133. return CGPT_FAILED;
  134. return CGPT_OK;
  135. }
  136. static int GptLoad(struct drive *drive, uint32_t sector_bytes) {
  137. drive->gpt.sector_bytes = sector_bytes;
  138. if (drive->size % drive->gpt.sector_bytes) {
  139. Error("Media size (%llu) is not a multiple of sector size(%d)\n",
  140. (long long unsigned int)drive->size, drive->gpt.sector_bytes);
  141. return -1;
  142. }
  143. drive->gpt.streaming_drive_sectors = drive->size / drive->gpt.sector_bytes;
  144. /* TODO(namnguyen): Remove this and totally trust gpt_drive_sectors. */
  145. if (!(drive->gpt.flags & GPT_FLAG_EXTERNAL)) {
  146. drive->gpt.gpt_drive_sectors = drive->gpt.streaming_drive_sectors;
  147. } /* Else, we trust gpt.gpt_drive_sectors. */
  148. // Read the data.
  149. if (CGPT_OK != Load(drive, &drive->gpt.primary_header,
  150. GPT_PMBR_SECTORS,
  151. drive->gpt.sector_bytes, GPT_HEADER_SECTORS)) {
  152. Error("Cannot read primary GPT header\n");
  153. return -1;
  154. }
  155. if (CGPT_OK != Load(drive, &drive->gpt.secondary_header,
  156. drive->gpt.gpt_drive_sectors - GPT_PMBR_SECTORS,
  157. drive->gpt.sector_bytes, GPT_HEADER_SECTORS)) {
  158. Error("Cannot read secondary GPT header\n");
  159. return -1;
  160. }
  161. GptHeader* primary_header = (GptHeader*)drive->gpt.primary_header;
  162. if (CheckHeader(primary_header, 0, drive->gpt.streaming_drive_sectors,
  163. drive->gpt.gpt_drive_sectors,
  164. drive->gpt.flags) == 0) {
  165. if (CGPT_OK != Load(drive, &drive->gpt.primary_entries,
  166. primary_header->entries_lba,
  167. drive->gpt.sector_bytes,
  168. CalculateEntriesSectors(primary_header))) {
  169. Error("Cannot read primary partition entry array\n");
  170. return -1;
  171. }
  172. } else {
  173. Warning("Primary GPT header is %s\n",
  174. memcmp(primary_header->signature, GPT_HEADER_SIGNATURE_IGNORED,
  175. GPT_HEADER_SIGNATURE_SIZE) ? "invalid" : "being ignored");
  176. drive->gpt.primary_entries = calloc(MAX_NUMBER_OF_ENTRIES,
  177. sizeof(GptEntry));
  178. }
  179. GptHeader* secondary_header = (GptHeader*)drive->gpt.secondary_header;
  180. if (CheckHeader(secondary_header, 1, drive->gpt.streaming_drive_sectors,
  181. drive->gpt.gpt_drive_sectors,
  182. drive->gpt.flags) == 0) {
  183. if (CGPT_OK != Load(drive, &drive->gpt.secondary_entries,
  184. secondary_header->entries_lba,
  185. drive->gpt.sector_bytes,
  186. CalculateEntriesSectors(secondary_header))) {
  187. Error("Cannot read secondary partition entry array\n");
  188. return -1;
  189. }
  190. } else {
  191. Warning("Secondary GPT header is %s\n",
  192. memcmp(primary_header->signature, GPT_HEADER_SIGNATURE_IGNORED,
  193. GPT_HEADER_SIGNATURE_SIZE) ? "invalid" : "being ignored");
  194. drive->gpt.secondary_entries = calloc(MAX_NUMBER_OF_ENTRIES,
  195. sizeof(GptEntry));
  196. }
  197. return 0;
  198. }
  199. static int GptSave(struct drive *drive) {
  200. int errors = 0;
  201. if (!(drive->gpt.ignored & MASK_PRIMARY)) {
  202. if (drive->gpt.modified & GPT_MODIFIED_HEADER1) {
  203. if (CGPT_OK != Save(drive, drive->gpt.primary_header,
  204. GPT_PMBR_SECTORS,
  205. drive->gpt.sector_bytes, GPT_HEADER_SECTORS)) {
  206. errors++;
  207. Error("Cannot write primary header: %s\n", strerror(errno));
  208. }
  209. }
  210. GptHeader* primary_header = (GptHeader*)drive->gpt.primary_header;
  211. if (drive->gpt.modified & GPT_MODIFIED_ENTRIES1) {
  212. if (CGPT_OK != Save(drive, drive->gpt.primary_entries,
  213. primary_header->entries_lba,
  214. drive->gpt.sector_bytes,
  215. CalculateEntriesSectors(primary_header))) {
  216. errors++;
  217. Error("Cannot write primary entries: %s\n", strerror(errno));
  218. }
  219. }
  220. // Sync primary GPT before touching secondary so one is always valid.
  221. if (drive->gpt.modified & (GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1))
  222. if (fsync(drive->fd) < 0 && errno == EIO) {
  223. errors++;
  224. Error("I/O error when trying to write primary GPT\n");
  225. }
  226. }
  227. // Only start writing secondary GPT if primary was written correctly.
  228. if (!errors && !(drive->gpt.ignored & MASK_SECONDARY)) {
  229. if (drive->gpt.modified & GPT_MODIFIED_HEADER2) {
  230. if(CGPT_OK != Save(drive, drive->gpt.secondary_header,
  231. drive->gpt.gpt_drive_sectors - GPT_PMBR_SECTORS,
  232. drive->gpt.sector_bytes, GPT_HEADER_SECTORS)) {
  233. errors++;
  234. Error("Cannot write secondary header: %s\n", strerror(errno));
  235. }
  236. }
  237. GptHeader* secondary_header = (GptHeader*)drive->gpt.secondary_header;
  238. if (drive->gpt.modified & GPT_MODIFIED_ENTRIES2) {
  239. if (CGPT_OK != Save(drive, drive->gpt.secondary_entries,
  240. secondary_header->entries_lba,
  241. drive->gpt.sector_bytes,
  242. CalculateEntriesSectors(secondary_header))) {
  243. errors++;
  244. Error("Cannot write secondary entries: %s\n", strerror(errno));
  245. }
  246. }
  247. }
  248. if (drive->gpt.primary_header)
  249. free(drive->gpt.primary_header);
  250. drive->gpt.primary_header = 0;
  251. if (drive->gpt.primary_entries)
  252. free(drive->gpt.primary_entries);
  253. drive->gpt.primary_entries = 0;
  254. if (drive->gpt.secondary_header)
  255. free(drive->gpt.secondary_header);
  256. drive->gpt.secondary_header = 0;
  257. if (drive->gpt.secondary_entries)
  258. free(drive->gpt.secondary_entries);
  259. drive->gpt.secondary_entries = 0;
  260. return errors ? -1 : 0;
  261. }
  262. /*
  263. * Query drive size and bytes per sector. Return zero on success. On error,
  264. * -1 is returned and errno is set appropriately.
  265. */
  266. static int ObtainDriveSize(int fd, uint64_t* size, uint32_t* sector_bytes) {
  267. struct stat stat;
  268. if (fstat(fd, &stat) == -1) {
  269. return -1;
  270. }
  271. #ifndef HAVE_MACOS
  272. if ((stat.st_mode & S_IFMT) != S_IFREG) {
  273. if (ioctl(fd, BLKGETSIZE64, size) < 0) {
  274. return -1;
  275. }
  276. if (ioctl(fd, BLKSSZGET, sector_bytes) < 0) {
  277. return -1;
  278. }
  279. } else {
  280. *sector_bytes = 512; /* bytes */
  281. *size = stat.st_size;
  282. }
  283. #else
  284. *sector_bytes = 512; /* bytes */
  285. *size = stat.st_size;
  286. #endif
  287. return 0;
  288. }
  289. int DriveOpen(const char *drive_path, struct drive *drive, int mode,
  290. uint64_t drive_size) {
  291. uint32_t sector_bytes;
  292. require(drive_path);
  293. require(drive);
  294. // Clear struct for proper error handling.
  295. memset(drive, 0, sizeof(struct drive));
  296. drive->fd = open(drive_path, mode |
  297. #ifndef HAVE_MACOS
  298. O_LARGEFILE |
  299. #endif
  300. O_NOFOLLOW);
  301. if (drive->fd == -1) {
  302. Error("Can't open %s: %s\n", drive_path, strerror(errno));
  303. return CGPT_FAILED;
  304. }
  305. sector_bytes = 512;
  306. uint64_t gpt_drive_size;
  307. if (ObtainDriveSize(drive->fd, &gpt_drive_size, &sector_bytes) != 0) {
  308. Error("Can't get drive size and bytes per sector for %s: %s\n",
  309. drive_path, strerror(errno));
  310. goto error_close;
  311. }
  312. drive->gpt.gpt_drive_sectors = gpt_drive_size / sector_bytes;
  313. if (drive_size == 0) {
  314. drive->size = gpt_drive_size;
  315. drive->gpt.flags = 0;
  316. } else {
  317. drive->size = drive_size;
  318. drive->gpt.flags = GPT_FLAG_EXTERNAL;
  319. }
  320. if (GptLoad(drive, sector_bytes)) {
  321. goto error_close;
  322. }
  323. // We just load the data. Caller must validate it.
  324. return CGPT_OK;
  325. error_close:
  326. (void) DriveClose(drive, 0);
  327. return CGPT_FAILED;
  328. }
  329. int DriveClose(struct drive *drive, int update_as_needed) {
  330. int errors = 0;
  331. if (update_as_needed) {
  332. if (GptSave(drive)) {
  333. errors++;
  334. }
  335. }
  336. // Sync early! Only sync file descriptor here, and leave the whole system sync
  337. // outside cgpt because whole system sync would trigger tons of disk accesses
  338. // and timeout tests.
  339. fsync(drive->fd);
  340. close(drive->fd);
  341. return errors ? CGPT_FAILED : CGPT_OK;
  342. }
  343. /* GUID conversion functions. Accepted format:
  344. *
  345. * "C12A7328-F81F-11D2-BA4B-00A0C93EC93B"
  346. *
  347. * Returns CGPT_OK if parsing is successful; otherwise CGPT_FAILED.
  348. */
  349. int StrToGuid(const char *str, Guid *guid) {
  350. uint32_t time_low;
  351. uint16_t time_mid;
  352. uint16_t time_high_and_version;
  353. unsigned int chunk[11];
  354. if (11 != sscanf(str, "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
  355. chunk+0,
  356. chunk+1,
  357. chunk+2,
  358. chunk+3,
  359. chunk+4,
  360. chunk+5,
  361. chunk+6,
  362. chunk+7,
  363. chunk+8,
  364. chunk+9,
  365. chunk+10)) {
  366. printf("FAILED\n");
  367. return CGPT_FAILED;
  368. }
  369. time_low = chunk[0] & 0xffffffff;
  370. time_mid = chunk[1] & 0xffff;
  371. time_high_and_version = chunk[2] & 0xffff;
  372. guid->u.Uuid.time_low = htole32(time_low);
  373. guid->u.Uuid.time_mid = htole16(time_mid);
  374. guid->u.Uuid.time_high_and_version = htole16(time_high_and_version);
  375. guid->u.Uuid.clock_seq_high_and_reserved = chunk[3] & 0xff;
  376. guid->u.Uuid.clock_seq_low = chunk[4] & 0xff;
  377. guid->u.Uuid.node[0] = chunk[5] & 0xff;
  378. guid->u.Uuid.node[1] = chunk[6] & 0xff;
  379. guid->u.Uuid.node[2] = chunk[7] & 0xff;
  380. guid->u.Uuid.node[3] = chunk[8] & 0xff;
  381. guid->u.Uuid.node[4] = chunk[9] & 0xff;
  382. guid->u.Uuid.node[5] = chunk[10] & 0xff;
  383. return CGPT_OK;
  384. }
  385. void GuidToStr(const Guid *guid, char *str, unsigned int buflen) {
  386. require(buflen >= GUID_STRLEN);
  387. require(snprintf(str, buflen,
  388. "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
  389. le32toh(guid->u.Uuid.time_low),
  390. le16toh(guid->u.Uuid.time_mid),
  391. le16toh(guid->u.Uuid.time_high_and_version),
  392. guid->u.Uuid.clock_seq_high_and_reserved,
  393. guid->u.Uuid.clock_seq_low,
  394. guid->u.Uuid.node[0], guid->u.Uuid.node[1],
  395. guid->u.Uuid.node[2], guid->u.Uuid.node[3],
  396. guid->u.Uuid.node[4], guid->u.Uuid.node[5]) == GUID_STRLEN-1);
  397. }
  398. /* Convert possibly unterminated UTF16 string to UTF8.
  399. * Caller must prepare enough space for UTF8, which could be up to
  400. * twice the byte length of UTF16 string plus the terminating '\0'.
  401. * See the following table for encoding lengths.
  402. *
  403. * Code point UTF16 UTF8
  404. * 0x0000-0x007F 2 bytes 1 byte
  405. * 0x0080-0x07FF 2 bytes 2 bytes
  406. * 0x0800-0xFFFF 2 bytes 3 bytes
  407. * 0x10000-0x10FFFF 4 bytes 4 bytes
  408. *
  409. * This function uses a simple state meachine to convert UTF-16 char(s) to
  410. * a code point. Once a code point is parsed out, the state machine throws
  411. * out sequencial UTF-8 chars in one time.
  412. *
  413. * Return: CGPT_OK --- all character are converted successfully.
  414. * CGPT_FAILED --- convert error, i.e. output buffer is too short.
  415. */
  416. int UTF16ToUTF8(const uint16_t *utf16, unsigned int maxinput,
  417. uint8_t *utf8, unsigned int maxoutput)
  418. {
  419. size_t s16idx, s8idx;
  420. uint32_t code_point = 0;
  421. int code_point_ready = 1; // code point is ready to output.
  422. int retval = CGPT_OK;
  423. if (!utf16 || !maxinput || !utf8 || !maxoutput)
  424. return CGPT_FAILED;
  425. maxoutput--; /* plan for termination now */
  426. for (s16idx = s8idx = 0;
  427. s16idx < maxinput && utf16[s16idx] && maxoutput;
  428. s16idx++) {
  429. uint16_t codeunit = le16toh(utf16[s16idx]);
  430. if (code_point_ready) {
  431. if (codeunit >= 0xD800 && codeunit <= 0xDBFF) {
  432. /* high surrogate, need the low surrogate. */
  433. code_point_ready = 0;
  434. code_point = (codeunit & 0x03FF) + 0x0040;
  435. } else {
  436. /* BMP char, output it. */
  437. code_point = codeunit;
  438. }
  439. } else {
  440. /* expect the low surrogate */
  441. if (codeunit >= 0xDC00 && codeunit <= 0xDFFF) {
  442. code_point = (code_point << 10) | (codeunit & 0x03FF);
  443. code_point_ready = 1;
  444. } else {
  445. /* the second code unit is NOT the low surrogate. Unexpected. */
  446. code_point_ready = 0;
  447. retval = CGPT_FAILED;
  448. break;
  449. }
  450. }
  451. /* If UTF code point is ready, output it. */
  452. if (code_point_ready) {
  453. require(code_point <= 0x10FFFF);
  454. if (code_point <= 0x7F && maxoutput >= 1) {
  455. maxoutput -= 1;
  456. utf8[s8idx++] = code_point & 0x7F;
  457. } else if (code_point <= 0x7FF && maxoutput >= 2) {
  458. maxoutput -= 2;
  459. utf8[s8idx++] = 0xC0 | (code_point >> 6);
  460. utf8[s8idx++] = 0x80 | (code_point & 0x3F);
  461. } else if (code_point <= 0xFFFF && maxoutput >= 3) {
  462. maxoutput -= 3;
  463. utf8[s8idx++] = 0xE0 | (code_point >> 12);
  464. utf8[s8idx++] = 0x80 | ((code_point >> 6) & 0x3F);
  465. utf8[s8idx++] = 0x80 | (code_point & 0x3F);
  466. } else if (code_point <= 0x10FFFF && maxoutput >= 4) {
  467. maxoutput -= 4;
  468. utf8[s8idx++] = 0xF0 | (code_point >> 18);
  469. utf8[s8idx++] = 0x80 | ((code_point >> 12) & 0x3F);
  470. utf8[s8idx++] = 0x80 | ((code_point >> 6) & 0x3F);
  471. utf8[s8idx++] = 0x80 | (code_point & 0x3F);
  472. } else {
  473. /* buffer underrun */
  474. retval = CGPT_FAILED;
  475. break;
  476. }
  477. }
  478. }
  479. utf8[s8idx++] = 0;
  480. return retval;
  481. }
  482. /* Convert UTF8 string to UTF16. The UTF8 string must be null-terminated.
  483. * Caller must prepare enough space for UTF16, including a terminating 0x0000.
  484. * See the following table for encoding lengths. In any case, the caller
  485. * just needs to prepare the byte length of UTF8 plus the terminating 0x0000.
  486. *
  487. * Code point UTF16 UTF8
  488. * 0x0000-0x007F 2 bytes 1 byte
  489. * 0x0080-0x07FF 2 bytes 2 bytes
  490. * 0x0800-0xFFFF 2 bytes 3 bytes
  491. * 0x10000-0x10FFFF 4 bytes 4 bytes
  492. *
  493. * This function converts UTF8 chars to a code point first. Then, convrts it
  494. * to UTF16 code unit(s).
  495. *
  496. * Return: CGPT_OK --- all character are converted successfully.
  497. * CGPT_FAILED --- convert error, i.e. output buffer is too short.
  498. */
  499. int UTF8ToUTF16(const uint8_t *utf8, uint16_t *utf16, unsigned int maxoutput)
  500. {
  501. size_t s16idx, s8idx;
  502. uint32_t code_point = 0;
  503. unsigned int expected_units = 1;
  504. unsigned int decoded_units = 1;
  505. int retval = CGPT_OK;
  506. if (!utf8 || !utf16 || !maxoutput)
  507. return CGPT_FAILED;
  508. maxoutput--; /* plan for termination */
  509. for (s8idx = s16idx = 0;
  510. utf8[s8idx] && maxoutput;
  511. s8idx++) {
  512. uint8_t code_unit;
  513. code_unit = utf8[s8idx];
  514. if (expected_units != decoded_units) {
  515. /* Trailing bytes of multi-byte character */
  516. if ((code_unit & 0xC0) == 0x80) {
  517. code_point = (code_point << 6) | (code_unit & 0x3F);
  518. ++decoded_units;
  519. } else {
  520. /* Unexpected code unit. */
  521. retval = CGPT_FAILED;
  522. break;
  523. }
  524. } else {
  525. /* parsing a new code point. */
  526. decoded_units = 1;
  527. if (code_unit <= 0x7F) {
  528. code_point = code_unit;
  529. expected_units = 1;
  530. } else if (code_unit <= 0xBF) {
  531. /* 0x80-0xBF must NOT be the heading byte unit of a new code point. */
  532. retval = CGPT_FAILED;
  533. break;
  534. } else if (code_unit >= 0xC2 && code_unit <= 0xDF) {
  535. code_point = code_unit & 0x1F;
  536. expected_units = 2;
  537. } else if (code_unit >= 0xE0 && code_unit <= 0xEF) {
  538. code_point = code_unit & 0x0F;
  539. expected_units = 3;
  540. } else if (code_unit >= 0xF0 && code_unit <= 0xF4) {
  541. code_point = code_unit & 0x07;
  542. expected_units = 4;
  543. } else {
  544. /* illegal code unit: 0xC0-0xC1, 0xF5-0xFF */
  545. retval = CGPT_FAILED;
  546. break;
  547. }
  548. }
  549. /* If no more unit is needed, output the UTF16 unit(s). */
  550. if ((retval == CGPT_OK) &&
  551. (expected_units == decoded_units)) {
  552. /* Check if the encoding is the shortest possible UTF-8 sequence. */
  553. switch (expected_units) {
  554. case 2:
  555. if (code_point <= 0x7F) retval = CGPT_FAILED;
  556. break;
  557. case 3:
  558. if (code_point <= 0x7FF) retval = CGPT_FAILED;
  559. break;
  560. case 4:
  561. if (code_point <= 0xFFFF) retval = CGPT_FAILED;
  562. break;
  563. }
  564. if (retval == CGPT_FAILED) break; /* leave immediately */
  565. if ((code_point <= 0xD7FF) ||
  566. (code_point >= 0xE000 && code_point <= 0xFFFF)) {
  567. utf16[s16idx++] = code_point;
  568. maxoutput -= 1;
  569. } else if (code_point >= 0x10000 && code_point <= 0x10FFFF &&
  570. maxoutput >= 2) {
  571. utf16[s16idx++] = 0xD800 | ((code_point >> 10) - 0x0040);
  572. utf16[s16idx++] = 0xDC00 | (code_point & 0x03FF);
  573. maxoutput -= 2;
  574. } else {
  575. /* Three possibilities fall into here. Both are failure cases.
  576. * a. surrogate pair (non-BMP characters; 0xD800~0xDFFF)
  577. * b. invalid code point > 0x10FFFF
  578. * c. buffer underrun
  579. */
  580. retval = CGPT_FAILED;
  581. break;
  582. }
  583. }
  584. }
  585. /* A null-terminator shows up before the UTF8 sequence ends. */
  586. if (expected_units != decoded_units) {
  587. retval = CGPT_FAILED;
  588. }
  589. utf16[s16idx++] = 0;
  590. return retval;
  591. }
  592. /* global types to compare against */
  593. const Guid guid_chromeos_firmware = GPT_ENT_TYPE_CHROMEOS_FIRMWARE;
  594. const Guid guid_chromeos_kernel = GPT_ENT_TYPE_CHROMEOS_KERNEL;
  595. const Guid guid_chromeos_rootfs = GPT_ENT_TYPE_CHROMEOS_ROOTFS;
  596. const Guid guid_linux_data = GPT_ENT_TYPE_LINUX_DATA;
  597. const Guid guid_chromeos_reserved = GPT_ENT_TYPE_CHROMEOS_RESERVED;
  598. const Guid guid_efi = GPT_ENT_TYPE_EFI;
  599. const Guid guid_unused = GPT_ENT_TYPE_UNUSED;
  600. const static struct {
  601. const Guid *type;
  602. char *name;
  603. char *description;
  604. } supported_types[] = {
  605. {&guid_chromeos_firmware, "firmware", "ChromeOS firmware"},
  606. {&guid_chromeos_kernel, "kernel", "ChromeOS kernel"},
  607. {&guid_chromeos_rootfs, "rootfs", "ChromeOS rootfs"},
  608. {&guid_linux_data, "data", "Linux data"},
  609. {&guid_chromeos_reserved, "reserved", "ChromeOS reserved"},
  610. {&guid_efi, "efi", "EFI System Partition"},
  611. {&guid_unused, "unused", "Unused (nonexistent) partition"},
  612. };
  613. /* Resolves human-readable GPT type.
  614. * Returns CGPT_OK if found.
  615. * Returns CGPT_FAILED if no known type found. */
  616. int ResolveType(const Guid *type, char *buf) {
  617. int i;
  618. for (i = 0; i < ARRAY_COUNT(supported_types); ++i) {
  619. if (!memcmp(type, supported_types[i].type, sizeof(Guid))) {
  620. strcpy(buf, supported_types[i].description);
  621. return CGPT_OK;
  622. }
  623. }
  624. return CGPT_FAILED;
  625. }
  626. int SupportedType(const char *name, Guid *type) {
  627. int i;
  628. for (i = 0; i < ARRAY_COUNT(supported_types); ++i) {
  629. if (!strcmp(name, supported_types[i].name)) {
  630. memcpy(type, supported_types[i].type, sizeof(Guid));
  631. return CGPT_OK;
  632. }
  633. }
  634. return CGPT_FAILED;
  635. }
  636. void PrintTypes(void) {
  637. int i;
  638. printf("The partition type may also be given as one of these aliases:\n\n");
  639. for (i = 0; i < ARRAY_COUNT(supported_types); ++i) {
  640. printf(" %-10s %s\n", supported_types[i].name,
  641. supported_types[i].description);
  642. }
  643. printf("\n");
  644. }
  645. static GptHeader* GetGptHeader(const GptData *gpt) {
  646. if (gpt->valid_headers & MASK_PRIMARY)
  647. return (GptHeader*)gpt->primary_header;
  648. else if (gpt->valid_headers & MASK_SECONDARY)
  649. return (GptHeader*)gpt->secondary_header;
  650. else
  651. return 0;
  652. }
  653. uint32_t GetNumberOfEntries(const struct drive *drive) {
  654. GptHeader *header = GetGptHeader(&drive->gpt);
  655. if (!header)
  656. return 0;
  657. return header->number_of_entries;
  658. }
  659. GptEntry *GetEntry(GptData *gpt, int secondary, uint32_t entry_index) {
  660. GptHeader *header = GetGptHeader(gpt);
  661. uint8_t *entries;
  662. uint32_t stride = header->size_of_entry;
  663. require(stride);
  664. require(entry_index < header->number_of_entries);
  665. if (secondary == PRIMARY) {
  666. entries = gpt->primary_entries;
  667. } else if (secondary == SECONDARY) {
  668. entries = gpt->secondary_entries;
  669. } else { /* ANY_VALID */
  670. require(secondary == ANY_VALID);
  671. if (gpt->valid_entries & MASK_PRIMARY) {
  672. entries = gpt->primary_entries;
  673. } else {
  674. require(gpt->valid_entries & MASK_SECONDARY);
  675. entries = gpt->secondary_entries;
  676. }
  677. }
  678. return (GptEntry*)(&entries[stride * entry_index]);
  679. }
  680. void SetLegacyBoot(struct drive *drive, int secondary, uint32_t entry_index,
  681. int legacy_boot) {
  682. require(legacy_boot >= 0 && legacy_boot <= CGPT_ATTRIBUTE_MAX_LEGACY_BOOT);
  683. GptEntry *entry;
  684. entry = GetEntry(&drive->gpt, secondary, entry_index);
  685. SetEntryLegacyBoot(entry, legacy_boot);
  686. }
  687. int GetLegacyBoot(struct drive *drive, int secondary, uint32_t entry_index) {
  688. GptEntry *entry;
  689. entry = GetEntry(&drive->gpt, secondary, entry_index);
  690. return GetEntryLegacyBoot(entry);
  691. }
  692. void SetPriority(struct drive *drive, int secondary, uint32_t entry_index,
  693. int priority) {
  694. require(priority >= 0 && priority <= CGPT_ATTRIBUTE_MAX_PRIORITY);
  695. GptEntry *entry;
  696. entry = GetEntry(&drive->gpt, secondary, entry_index);
  697. SetEntryPriority(entry, priority);
  698. }
  699. int GetPriority(struct drive *drive, int secondary, uint32_t entry_index) {
  700. GptEntry *entry;
  701. entry = GetEntry(&drive->gpt, secondary, entry_index);
  702. return GetEntryPriority(entry);
  703. }
  704. void SetTries(struct drive *drive, int secondary, uint32_t entry_index,
  705. int tries) {
  706. require(tries >= 0 && tries <= CGPT_ATTRIBUTE_MAX_TRIES);
  707. GptEntry *entry;
  708. entry = GetEntry(&drive->gpt, secondary, entry_index);
  709. SetEntryTries(entry, tries);
  710. }
  711. int GetTries(struct drive *drive, int secondary, uint32_t entry_index) {
  712. GptEntry *entry;
  713. entry = GetEntry(&drive->gpt, secondary, entry_index);
  714. return GetEntryTries(entry);
  715. }
  716. void SetSuccessful(struct drive *drive, int secondary, uint32_t entry_index,
  717. int success) {
  718. require(success >= 0 && success <= CGPT_ATTRIBUTE_MAX_SUCCESSFUL);
  719. GptEntry *entry;
  720. entry = GetEntry(&drive->gpt, secondary, entry_index);
  721. SetEntrySuccessful(entry, success);
  722. }
  723. int GetSuccessful(struct drive *drive, int secondary, uint32_t entry_index) {
  724. GptEntry *entry;
  725. entry = GetEntry(&drive->gpt, secondary, entry_index);
  726. return GetEntrySuccessful(entry);
  727. }
  728. void SetRaw(struct drive *drive, int secondary, uint32_t entry_index,
  729. uint32_t raw) {
  730. GptEntry *entry;
  731. entry = GetEntry(&drive->gpt, secondary, entry_index);
  732. entry->attrs.fields.gpt_att = (uint16_t)raw;
  733. }
  734. void UpdateAllEntries(struct drive *drive) {
  735. RepairEntries(&drive->gpt, MASK_PRIMARY);
  736. RepairHeader(&drive->gpt, MASK_PRIMARY);
  737. drive->gpt.modified |= (GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1 |
  738. GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES2);
  739. UpdateCrc(&drive->gpt);
  740. }
  741. int IsUnused(struct drive *drive, int secondary, uint32_t index) {
  742. GptEntry *entry;
  743. entry = GetEntry(&drive->gpt, secondary, index);
  744. return GuidIsZero(&entry->type);
  745. }
  746. int IsKernel(struct drive *drive, int secondary, uint32_t index) {
  747. GptEntry *entry;
  748. entry = GetEntry(&drive->gpt, secondary, index);
  749. return GuidEqual(&entry->type, &guid_chromeos_kernel);
  750. }
  751. #define TOSTRING(A) #A
  752. const char *GptError(int errnum) {
  753. const char *error_string[] = {
  754. TOSTRING(GPT_SUCCESS),
  755. TOSTRING(GPT_ERROR_NO_VALID_KERNEL),
  756. TOSTRING(GPT_ERROR_INVALID_HEADERS),
  757. TOSTRING(GPT_ERROR_INVALID_ENTRIES),
  758. TOSTRING(GPT_ERROR_INVALID_SECTOR_SIZE),
  759. TOSTRING(GPT_ERROR_INVALID_SECTOR_NUMBER),
  760. TOSTRING(GPT_ERROR_INVALID_UPDATE_TYPE)
  761. };
  762. if (errnum < 0 || errnum >= ARRAY_COUNT(error_string))
  763. return "<illegal value>";
  764. return error_string[errnum];
  765. }
  766. /* Update CRC value if necessary. */
  767. void UpdateCrc(GptData *gpt) {
  768. GptHeader *primary_header, *secondary_header;
  769. primary_header = (GptHeader*)gpt->primary_header;
  770. secondary_header = (GptHeader*)gpt->secondary_header;
  771. if (gpt->modified & GPT_MODIFIED_ENTRIES1 &&
  772. memcmp(primary_header, GPT_HEADER_SIGNATURE2,
  773. GPT_HEADER_SIGNATURE_SIZE)) {
  774. size_t entries_size = primary_header->size_of_entry *
  775. primary_header->number_of_entries;
  776. primary_header->entries_crc32 =
  777. Crc32(gpt->primary_entries, entries_size);
  778. }
  779. if (gpt->modified & GPT_MODIFIED_ENTRIES2) {
  780. size_t entries_size = secondary_header->size_of_entry *
  781. secondary_header->number_of_entries;
  782. secondary_header->entries_crc32 =
  783. Crc32(gpt->secondary_entries, entries_size);
  784. }
  785. if (gpt->modified & GPT_MODIFIED_HEADER1) {
  786. primary_header->header_crc32 = 0;
  787. primary_header->header_crc32 = Crc32(
  788. (const uint8_t *)primary_header, sizeof(GptHeader));
  789. }
  790. if (gpt->modified & GPT_MODIFIED_HEADER2) {
  791. secondary_header->header_crc32 = 0;
  792. secondary_header->header_crc32 = Crc32(
  793. (const uint8_t *)secondary_header, sizeof(GptHeader));
  794. }
  795. }
  796. /* Two headers are NOT bitwise identical. For example, my_lba pointers to header
  797. * itself so that my_lba in primary and secondary is definitely different.
  798. * Only the following fields should be identical.
  799. *
  800. * first_usable_lba
  801. * last_usable_lba
  802. * number_of_entries
  803. * size_of_entry
  804. * disk_uuid
  805. *
  806. * If any of above field are not matched, overwrite secondary with primary since
  807. * we always trust primary.
  808. * If any one of header is invalid, copy from another. */
  809. int IsSynonymous(const GptHeader* a, const GptHeader* b) {
  810. if ((a->first_usable_lba == b->first_usable_lba) &&
  811. (a->last_usable_lba == b->last_usable_lba) &&
  812. (a->number_of_entries == b->number_of_entries) &&
  813. (a->size_of_entry == b->size_of_entry) &&
  814. (!memcmp(&a->disk_uuid, &b->disk_uuid, sizeof(Guid))))
  815. return 1;
  816. return 0;
  817. }
  818. /* Primary entries and secondary entries should be bitwise identical.
  819. * If two entries tables are valid, compare them. If not the same,
  820. * overwrites secondary with primary (primary always has higher priority),
  821. * and marks secondary as modified.
  822. * If only one is valid, overwrites invalid one.
  823. * If all are invalid, does nothing.
  824. * This function returns bit masks for GptData.modified field.
  825. * Note that CRC is NOT re-computed in this function.
  826. */
  827. uint8_t RepairEntries(GptData *gpt, const uint32_t valid_entries) {
  828. /* If we have an alternate GPT header signature, don't overwrite
  829. * the secondary GPT with the primary one as that might wipe the
  830. * partition table. Also don't overwrite the primary one with the
  831. * secondary one as that will stop Windows from booting. */
  832. GptHeader* h = (GptHeader*)(gpt->primary_header);
  833. if (!memcmp(h->signature, GPT_HEADER_SIGNATURE2, GPT_HEADER_SIGNATURE_SIZE))
  834. return 0;
  835. if (gpt->valid_headers & MASK_PRIMARY) {
  836. h = (GptHeader*)gpt->primary_header;
  837. } else if (gpt->valid_headers & MASK_SECONDARY) {
  838. h = (GptHeader*)gpt->secondary_header;
  839. } else {
  840. /* We cannot trust any header, don't update entries. */
  841. return 0;
  842. }
  843. size_t entries_size = h->number_of_entries * h->size_of_entry;
  844. if (valid_entries == MASK_BOTH) {
  845. if (memcmp(gpt->primary_entries, gpt->secondary_entries, entries_size)) {
  846. memcpy(gpt->secondary_entries, gpt->primary_entries, entries_size);
  847. return GPT_MODIFIED_ENTRIES2;
  848. }
  849. } else if (valid_entries == MASK_PRIMARY) {
  850. memcpy(gpt->secondary_entries, gpt->primary_entries, entries_size);
  851. return GPT_MODIFIED_ENTRIES2;
  852. } else if (valid_entries == MASK_SECONDARY) {
  853. memcpy(gpt->primary_entries, gpt->secondary_entries, entries_size);
  854. return GPT_MODIFIED_ENTRIES1;
  855. }
  856. return 0;
  857. }
  858. /* The above five fields are shared between primary and secondary headers.
  859. * We can recover one header from another through copying those fields. */
  860. void CopySynonymousParts(GptHeader* target, const GptHeader* source) {
  861. target->first_usable_lba = source->first_usable_lba;
  862. target->last_usable_lba = source->last_usable_lba;
  863. target->number_of_entries = source->number_of_entries;
  864. target->size_of_entry = source->size_of_entry;
  865. memcpy(&target->disk_uuid, &source->disk_uuid, sizeof(Guid));
  866. }
  867. /* This function repairs primary and secondary headers if possible.
  868. * If both headers are valid (CRC32 is correct) but
  869. * a) indicate inconsistent usable LBA ranges,
  870. * b) inconsistent partition entry size and number,
  871. * c) inconsistent disk_uuid,
  872. * we will use the primary header to overwrite secondary header.
  873. * If primary is invalid (CRC32 is wrong), then we repair it from secondary.
  874. * If secondary is invalid (CRC32 is wrong), then we repair it from primary.
  875. * This function returns the bitmasks for modified header.
  876. * Note that CRC value is NOT re-computed in this function. UpdateCrc() will
  877. * do it later.
  878. */
  879. uint8_t RepairHeader(GptData *gpt, const uint32_t valid_headers) {
  880. GptHeader *primary_header, *secondary_header;
  881. primary_header = (GptHeader*)gpt->primary_header;
  882. secondary_header = (GptHeader*)gpt->secondary_header;
  883. if (valid_headers == MASK_BOTH) {
  884. if (!IsSynonymous(primary_header, secondary_header)) {
  885. CopySynonymousParts(secondary_header, primary_header);
  886. return GPT_MODIFIED_HEADER2;
  887. }
  888. } else if (valid_headers == MASK_PRIMARY) {
  889. memcpy(secondary_header, primary_header, sizeof(GptHeader));
  890. secondary_header->my_lba = gpt->gpt_drive_sectors - 1; /* the last sector */
  891. secondary_header->alternate_lba = primary_header->my_lba;
  892. secondary_header->entries_lba = secondary_header->my_lba -
  893. CalculateEntriesSectors(primary_header);
  894. return GPT_MODIFIED_HEADER2;
  895. } else if (valid_headers == MASK_SECONDARY) {
  896. memcpy(primary_header, secondary_header, sizeof(GptHeader));
  897. primary_header->my_lba = GPT_PMBR_SECTORS; /* the second sector on drive */
  898. primary_header->alternate_lba = secondary_header->my_lba;
  899. /* TODO (namnguyen): Preserve (header, entries) padding space. */
  900. primary_header->entries_lba = primary_header->my_lba + GPT_HEADER_SECTORS;
  901. return GPT_MODIFIED_HEADER1;
  902. }
  903. return 0;
  904. }
  905. int CgptGetNumNonEmptyPartitions(CgptShowParams *params) {
  906. struct drive drive;
  907. int gpt_retval;
  908. int retval;
  909. if (params == NULL)
  910. return CGPT_FAILED;
  911. if (CGPT_OK != DriveOpen(params->drive_name, &drive, O_RDONLY,
  912. params->drive_size))
  913. return CGPT_FAILED;
  914. if (GPT_SUCCESS != (gpt_retval = GptSanityCheck(&drive.gpt))) {
  915. Error("GptSanityCheck() returned %d: %s\n",
  916. gpt_retval, GptError(gpt_retval));
  917. retval = CGPT_FAILED;
  918. goto done;
  919. }
  920. params->num_partitions = 0;
  921. int numEntries = GetNumberOfEntries(&drive);
  922. int i;
  923. for(i = 0; i < numEntries; i++) {
  924. GptEntry *entry = GetEntry(&drive.gpt, ANY_VALID, i);
  925. if (GuidIsZero(&entry->type))
  926. continue;
  927. params->num_partitions++;
  928. }
  929. retval = CGPT_OK;
  930. done:
  931. DriveClose(&drive, 0);
  932. return retval;
  933. }
  934. int GuidEqual(const Guid *guid1, const Guid *guid2) {
  935. return (0 == memcmp(guid1, guid2, sizeof(Guid)));
  936. }
  937. int GuidIsZero(const Guid *gp) {
  938. return GuidEqual(gp, &guid_unused);
  939. }
  940. void PMBRToStr(struct pmbr *pmbr, char *str, unsigned int buflen) {
  941. char buf[GUID_STRLEN];
  942. if (GuidIsZero(&pmbr->boot_guid)) {
  943. require(snprintf(str, buflen, "PMBR") < buflen);
  944. } else {
  945. GuidToStr(&pmbr->boot_guid, buf, sizeof(buf));
  946. require(snprintf(str, buflen, "PMBR (Boot GUID: %s)", buf) < buflen);
  947. }
  948. }
  949. /* Optional */
  950. int __GenerateGuid(Guid *newguid) { return CGPT_FAILED; };
  951. #ifndef HAVE_MACOS
  952. int GenerateGuid(Guid *newguid) __attribute__((weak, alias("__GenerateGuid")));
  953. #endif