cgptlib_internal.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517
  1. /* Copyright (c) 2013 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. #include "sysincludes.h"
  6. #include "cgptlib.h"
  7. #include "cgptlib_internal.h"
  8. #include "crc32.h"
  9. #include "gpt.h"
  10. #include "gpt_misc.h"
  11. #include "utility.h"
  12. const static int SECTOR_SIZE = 512;
  13. size_t CalculateEntriesSectors(GptHeader* h)
  14. {
  15. size_t bytes = h->number_of_entries * h->size_of_entry;
  16. size_t ret = (bytes + SECTOR_SIZE - 1) / SECTOR_SIZE;
  17. return ret;
  18. }
  19. int CheckParameters(GptData *gpt)
  20. {
  21. /* Currently, we only support 512-byte sectors. */
  22. if (gpt->sector_bytes != SECTOR_SIZE)
  23. return GPT_ERROR_INVALID_SECTOR_SIZE;
  24. /*
  25. * gpt_drive_sectors should be reasonable. It cannot be unset, and it
  26. * cannot differ from streaming_drive_sectors if the GPT structs are
  27. * stored on same device.
  28. */
  29. if (gpt->gpt_drive_sectors == 0 ||
  30. (!(gpt->flags & GPT_FLAG_EXTERNAL) &&
  31. gpt->gpt_drive_sectors != gpt->streaming_drive_sectors)) {
  32. return GPT_ERROR_INVALID_SECTOR_NUMBER;
  33. }
  34. /*
  35. * Sector count of a drive should be reasonable. If the given value is
  36. * too small to contain basic GPT structure (PMBR + Headers + Entries),
  37. * the value is wrong.
  38. */
  39. if (gpt->gpt_drive_sectors <
  40. (1 + 2 * (1 + MIN_NUMBER_OF_ENTRIES /
  41. (SECTOR_SIZE / sizeof(GptEntry)))))
  42. return GPT_ERROR_INVALID_SECTOR_NUMBER;
  43. return GPT_SUCCESS;
  44. }
  45. uint32_t HeaderCrc(GptHeader *h)
  46. {
  47. uint32_t crc32, original_crc32;
  48. /* Original CRC is calculated with the CRC field 0. */
  49. original_crc32 = h->header_crc32;
  50. h->header_crc32 = 0;
  51. crc32 = Crc32((const uint8_t *)h, h->size);
  52. h->header_crc32 = original_crc32;
  53. return crc32;
  54. }
  55. int CheckHeader(GptHeader *h, int is_secondary,
  56. uint64_t streaming_drive_sectors,
  57. uint64_t gpt_drive_sectors, uint32_t flags)
  58. {
  59. if (!h)
  60. return 1;
  61. /*
  62. * Make sure we're looking at a header of reasonable size before
  63. * attempting to calculate CRC.
  64. */
  65. if (memcmp(h->signature, GPT_HEADER_SIGNATURE,
  66. GPT_HEADER_SIGNATURE_SIZE) &&
  67. memcmp(h->signature, GPT_HEADER_SIGNATURE2,
  68. GPT_HEADER_SIGNATURE_SIZE))
  69. return 1;
  70. if (h->revision != GPT_HEADER_REVISION)
  71. return 1;
  72. if (h->size < MIN_SIZE_OF_HEADER || h->size > MAX_SIZE_OF_HEADER)
  73. return 1;
  74. /* Check CRC before looking at remaining fields */
  75. if (HeaderCrc(h) != h->header_crc32)
  76. return 1;
  77. /* Reserved fields must be zero. */
  78. if (h->reserved_zero)
  79. return 1;
  80. /* Could check that padding is zero, but that doesn't matter to us. */
  81. /*
  82. * If entry size is different than our struct, we won't be able to
  83. * parse it. Technically, any size 2^N where N>=7 is valid.
  84. */
  85. if (h->size_of_entry != sizeof(GptEntry))
  86. return 1;
  87. if ((h->number_of_entries < MIN_NUMBER_OF_ENTRIES) ||
  88. (h->number_of_entries > MAX_NUMBER_OF_ENTRIES) ||
  89. (!(flags & GPT_FLAG_EXTERNAL) &&
  90. h->number_of_entries != MAX_NUMBER_OF_ENTRIES))
  91. return 1;
  92. /*
  93. * Check locations for the header and its entries. The primary
  94. * immediately follows the PMBR, and is followed by its entries. The
  95. * secondary is at the end of the drive, preceded by its entries.
  96. */
  97. if (is_secondary) {
  98. if (h->my_lba != gpt_drive_sectors - GPT_HEADER_SECTORS)
  99. return 1;
  100. if (h->entries_lba != h->my_lba - CalculateEntriesSectors(h))
  101. return 1;
  102. } else {
  103. if (h->my_lba != GPT_PMBR_SECTORS)
  104. return 1;
  105. if (h->entries_lba < h->my_lba + 1)
  106. return 1;
  107. }
  108. /* FirstUsableLBA <= LastUsableLBA. */
  109. if (h->first_usable_lba > h->last_usable_lba)
  110. return 1;
  111. if (flags & GPT_FLAG_EXTERNAL) {
  112. if (h->last_usable_lba >= streaming_drive_sectors) {
  113. return 1;
  114. }
  115. return 0;
  116. }
  117. /*
  118. * FirstUsableLBA must be after the end of the primary GPT table array.
  119. * LastUsableLBA must be before the start of the secondary GPT table
  120. * array.
  121. */
  122. /* TODO(namnguyen): Also check for padding between header & entries. */
  123. if (h->first_usable_lba < 2 + CalculateEntriesSectors(h))
  124. return 1;
  125. if (h->last_usable_lba >=
  126. streaming_drive_sectors - 1 - CalculateEntriesSectors(h))
  127. return 1;
  128. /* Success */
  129. return 0;
  130. }
  131. int IsKernelEntry(const GptEntry *e)
  132. {
  133. static Guid chromeos_kernel = GPT_ENT_TYPE_CHROMEOS_KERNEL;
  134. return !memcmp(&e->type, &chromeos_kernel, sizeof(Guid));
  135. }
  136. int CheckEntries(GptEntry *entries, GptHeader *h)
  137. {
  138. if (!entries)
  139. return GPT_ERROR_INVALID_ENTRIES;
  140. GptEntry *entry;
  141. uint32_t crc32;
  142. uint32_t i;
  143. /* Check CRC before examining entries. */
  144. crc32 = Crc32((const uint8_t *)entries,
  145. h->size_of_entry * h->number_of_entries);
  146. if (crc32 != h->entries_crc32)
  147. return GPT_ERROR_CRC_CORRUPTED;
  148. /* Check all entries. */
  149. for (i = 0, entry = entries; i < h->number_of_entries; i++, entry++) {
  150. GptEntry *e2;
  151. uint32_t i2;
  152. if (IsUnusedEntry(entry))
  153. continue;
  154. /* Entry must be in valid region. */
  155. if ((entry->starting_lba < h->first_usable_lba) ||
  156. (entry->ending_lba > h->last_usable_lba) ||
  157. (entry->ending_lba < entry->starting_lba))
  158. return GPT_ERROR_OUT_OF_REGION;
  159. /* Entry must not overlap other entries. */
  160. for (i2 = 0, e2 = entries; i2 < h->number_of_entries;
  161. i2++, e2++) {
  162. if (i2 == i || IsUnusedEntry(e2))
  163. continue;
  164. if ((entry->starting_lba >= e2->starting_lba) &&
  165. (entry->starting_lba <= e2->ending_lba))
  166. return GPT_ERROR_START_LBA_OVERLAP;
  167. if ((entry->ending_lba >= e2->starting_lba) &&
  168. (entry->ending_lba <= e2->ending_lba))
  169. return GPT_ERROR_END_LBA_OVERLAP;
  170. /* UniqueGuid field must be unique. */
  171. if (0 == memcmp(&entry->unique, &e2->unique,
  172. sizeof(Guid)))
  173. return GPT_ERROR_DUP_GUID;
  174. }
  175. }
  176. /* Success */
  177. return 0;
  178. }
  179. int HeaderFieldsSame(GptHeader *h1, GptHeader *h2)
  180. {
  181. if (memcmp(h1->signature, h2->signature, sizeof(h1->signature)))
  182. return 1;
  183. if (h1->revision != h2->revision)
  184. return 1;
  185. if (h1->size != h2->size)
  186. return 1;
  187. if (h1->reserved_zero != h2->reserved_zero)
  188. return 1;
  189. if (h1->first_usable_lba != h2->first_usable_lba)
  190. return 1;
  191. if (h1->last_usable_lba != h2->last_usable_lba)
  192. return 1;
  193. if (memcmp(&h1->disk_uuid, &h2->disk_uuid, sizeof(Guid)))
  194. return 1;
  195. if (h1->number_of_entries != h2->number_of_entries)
  196. return 1;
  197. if (h1->size_of_entry != h2->size_of_entry)
  198. return 1;
  199. if (h1->entries_crc32 != h2->entries_crc32)
  200. return 1;
  201. return 0;
  202. }
  203. int GptSanityCheck(GptData *gpt)
  204. {
  205. int retval;
  206. GptHeader *header1 = (GptHeader *)(gpt->primary_header);
  207. GptHeader *header2 = (GptHeader *)(gpt->secondary_header);
  208. GptEntry *entries1 = (GptEntry *)(gpt->primary_entries);
  209. GptEntry *entries2 = (GptEntry *)(gpt->secondary_entries);
  210. GptHeader *goodhdr = NULL;
  211. gpt->valid_headers = 0;
  212. gpt->valid_entries = 0;
  213. gpt->ignored = 0;
  214. retval = CheckParameters(gpt);
  215. if (retval != GPT_SUCCESS)
  216. return retval;
  217. /* Check both headers; we need at least one valid header. */
  218. if (0 == CheckHeader(header1, 0, gpt->streaming_drive_sectors,
  219. gpt->gpt_drive_sectors, gpt->flags)) {
  220. gpt->valid_headers |= MASK_PRIMARY;
  221. goodhdr = header1;
  222. } else if (header1 && !memcmp(header1->signature,
  223. GPT_HEADER_SIGNATURE_IGNORED, GPT_HEADER_SIGNATURE_SIZE)) {
  224. gpt->ignored |= MASK_PRIMARY;
  225. }
  226. if (0 == CheckHeader(header2, 1, gpt->streaming_drive_sectors,
  227. gpt->gpt_drive_sectors, gpt->flags)) {
  228. gpt->valid_headers |= MASK_SECONDARY;
  229. if (!goodhdr)
  230. goodhdr = header2;
  231. } else if (header2 && !memcmp(header2->signature,
  232. GPT_HEADER_SIGNATURE_IGNORED, GPT_HEADER_SIGNATURE_SIZE)) {
  233. gpt->ignored |= MASK_SECONDARY;
  234. }
  235. if (!gpt->valid_headers)
  236. return GPT_ERROR_INVALID_HEADERS;
  237. /*
  238. * Check if entries are valid.
  239. *
  240. * Note that we use the same header in both checks. This way we'll
  241. * catch the case where (header1,entries1) and (header2,entries2) are
  242. * both valid, but (entries1 != entries2).
  243. */
  244. if (0 == CheckEntries(entries1, goodhdr))
  245. gpt->valid_entries |= MASK_PRIMARY;
  246. if (0 == CheckEntries(entries2, goodhdr))
  247. gpt->valid_entries |= MASK_SECONDARY;
  248. /*
  249. * If both headers are good but neither entries were good, check the
  250. * entries with the secondary header.
  251. */
  252. if (MASK_BOTH == gpt->valid_headers && !gpt->valid_entries) {
  253. if (0 == CheckEntries(entries1, header2))
  254. gpt->valid_entries |= MASK_PRIMARY;
  255. if (0 == CheckEntries(entries2, header2))
  256. gpt->valid_entries |= MASK_SECONDARY;
  257. if (gpt->valid_entries) {
  258. /*
  259. * Sure enough, header2 had a good CRC for one of the
  260. * entries. Mark header1 invalid, so we'll update its
  261. * entries CRC.
  262. */
  263. gpt->valid_headers &= ~MASK_PRIMARY;
  264. goodhdr = header2;
  265. }
  266. }
  267. if (!gpt->valid_entries)
  268. return GPT_ERROR_INVALID_ENTRIES;
  269. /*
  270. * Now that we've determined which header contains a good CRC for
  271. * the entries, make sure the headers are otherwise identical.
  272. */
  273. if (MASK_BOTH == gpt->valid_headers &&
  274. 0 != HeaderFieldsSame(header1, header2))
  275. gpt->valid_headers &= ~MASK_SECONDARY;
  276. /*
  277. * When we're ignoring a GPT, make it look in memory like the other one
  278. * and pretend that everything is fine (until we try to save).
  279. */
  280. if (MASK_NONE != gpt->ignored) {
  281. GptRepair(gpt);
  282. gpt->modified = 0;
  283. }
  284. return GPT_SUCCESS;
  285. }
  286. void GptRepair(GptData *gpt)
  287. {
  288. GptHeader *header1 = (GptHeader *)(gpt->primary_header);
  289. GptHeader *header2 = (GptHeader *)(gpt->secondary_header);
  290. GptEntry *entries1 = (GptEntry *)(gpt->primary_entries);
  291. GptEntry *entries2 = (GptEntry *)(gpt->secondary_entries);
  292. int entries_size;
  293. /* Need at least one good header and one good set of entries. */
  294. if (MASK_NONE == gpt->valid_headers || MASK_NONE == gpt->valid_entries)
  295. return;
  296. /* Repair headers if necessary */
  297. if (MASK_PRIMARY == gpt->valid_headers) {
  298. /* Primary is good, secondary is bad */
  299. memcpy(header2, header1, sizeof(GptHeader));
  300. header2->my_lba = gpt->gpt_drive_sectors - GPT_HEADER_SECTORS;
  301. header2->alternate_lba = GPT_PMBR_SECTORS; /* Second sector. */
  302. header2->entries_lba = header2->my_lba - CalculateEntriesSectors(header1);
  303. header2->header_crc32 = HeaderCrc(header2);
  304. gpt->modified |= GPT_MODIFIED_HEADER2;
  305. }
  306. else if (MASK_SECONDARY == gpt->valid_headers) {
  307. /* Secondary is good, primary is bad */
  308. memcpy(header1, header2, sizeof(GptHeader));
  309. header1->my_lba = GPT_PMBR_SECTORS; /* Second sector. */
  310. header1->alternate_lba =
  311. gpt->streaming_drive_sectors - GPT_HEADER_SECTORS;
  312. /* TODO (namnguyen): Preserve (header, entries) padding. */
  313. header1->entries_lba = header1->my_lba + 1;
  314. header1->header_crc32 = HeaderCrc(header1);
  315. gpt->modified |= GPT_MODIFIED_HEADER1;
  316. }
  317. gpt->valid_headers = MASK_BOTH;
  318. /* Repair entries if necessary */
  319. entries_size = header1->size_of_entry * header1->number_of_entries;
  320. if (MASK_PRIMARY == gpt->valid_entries) {
  321. /* Primary is good, secondary is bad */
  322. memcpy(entries2, entries1, entries_size);
  323. gpt->modified |= GPT_MODIFIED_ENTRIES2;
  324. }
  325. else if (MASK_SECONDARY == gpt->valid_entries) {
  326. /* Secondary is good, primary is bad */
  327. memcpy(entries1, entries2, entries_size);
  328. gpt->modified |= GPT_MODIFIED_ENTRIES1;
  329. }
  330. gpt->valid_entries = MASK_BOTH;
  331. }
  332. int GetEntryLegacyBoot(const GptEntry *e)
  333. {
  334. return e->attrs.fields.legacy_boot;
  335. }
  336. int GetEntrySuccessful(const GptEntry *e)
  337. {
  338. return (e->attrs.fields.gpt_att & CGPT_ATTRIBUTE_SUCCESSFUL_MASK) >>
  339. CGPT_ATTRIBUTE_SUCCESSFUL_OFFSET;
  340. }
  341. int GetEntryPriority(const GptEntry *e)
  342. {
  343. int ret = VbExOverrideGptEntryPriority(e);
  344. /* Ensure that the override priority is valid. */
  345. if ((ret > 0) && (ret < 16))
  346. return ret;
  347. return (e->attrs.fields.gpt_att & CGPT_ATTRIBUTE_PRIORITY_MASK) >>
  348. CGPT_ATTRIBUTE_PRIORITY_OFFSET;
  349. }
  350. int GetEntryTries(const GptEntry *e)
  351. {
  352. return (e->attrs.fields.gpt_att & CGPT_ATTRIBUTE_TRIES_MASK) >>
  353. CGPT_ATTRIBUTE_TRIES_OFFSET;
  354. }
  355. void SetEntryLegacyBoot(GptEntry *e, int legacy_boot)
  356. {
  357. e->attrs.fields.legacy_boot = legacy_boot;
  358. }
  359. void SetEntrySuccessful(GptEntry *e, int successful)
  360. {
  361. if (successful)
  362. e->attrs.fields.gpt_att |= CGPT_ATTRIBUTE_SUCCESSFUL_MASK;
  363. else
  364. e->attrs.fields.gpt_att &= ~CGPT_ATTRIBUTE_SUCCESSFUL_MASK;
  365. }
  366. void SetEntryPriority(GptEntry *e, int priority)
  367. {
  368. e->attrs.fields.gpt_att &= ~CGPT_ATTRIBUTE_PRIORITY_MASK;
  369. e->attrs.fields.gpt_att |=
  370. (priority << CGPT_ATTRIBUTE_PRIORITY_OFFSET) &
  371. CGPT_ATTRIBUTE_PRIORITY_MASK;
  372. }
  373. void SetEntryTries(GptEntry *e, int tries)
  374. {
  375. e->attrs.fields.gpt_att &= ~CGPT_ATTRIBUTE_TRIES_MASK;
  376. e->attrs.fields.gpt_att |= (tries << CGPT_ATTRIBUTE_TRIES_OFFSET) &
  377. CGPT_ATTRIBUTE_TRIES_MASK;
  378. }
  379. void GetCurrentKernelUniqueGuid(GptData *gpt, void *dest)
  380. {
  381. GptEntry *entries = (GptEntry *)gpt->primary_entries;
  382. GptEntry *e = entries + gpt->current_kernel;
  383. memcpy(dest, &e->unique, sizeof(Guid));
  384. }
  385. void GptModified(GptData *gpt) {
  386. GptHeader *header = (GptHeader *)gpt->primary_header;
  387. /* Update the CRCs */
  388. header->entries_crc32 = Crc32(gpt->primary_entries,
  389. header->size_of_entry *
  390. header->number_of_entries);
  391. header->header_crc32 = HeaderCrc(header);
  392. gpt->modified |= GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1;
  393. /*
  394. * Use the repair function to update the other copy of the GPT. This
  395. * is a tad inefficient, but is much faster than the disk I/O to update
  396. * the GPT on disk so it doesn't matter.
  397. */
  398. gpt->valid_headers = MASK_PRIMARY;
  399. gpt->valid_entries = MASK_PRIMARY;
  400. GptRepair(gpt);
  401. }
  402. const char *GptErrorText(int error_code)
  403. {
  404. switch(error_code) {
  405. case GPT_SUCCESS:
  406. return "none";
  407. case GPT_ERROR_NO_VALID_KERNEL:
  408. return "Invalid kernel";
  409. case GPT_ERROR_INVALID_HEADERS:
  410. return "Invalid headers";
  411. case GPT_ERROR_INVALID_ENTRIES:
  412. return "Invalid entries";
  413. case GPT_ERROR_INVALID_SECTOR_SIZE:
  414. return "Invalid sector size";
  415. case GPT_ERROR_INVALID_SECTOR_NUMBER:
  416. return "Invalid sector number";
  417. case GPT_ERROR_INVALID_UPDATE_TYPE:
  418. return "Invalid update type";
  419. case GPT_ERROR_CRC_CORRUPTED:
  420. return "Entries' crc corrupted";
  421. case GPT_ERROR_OUT_OF_REGION:
  422. return "Entry outside of valid region";
  423. case GPT_ERROR_START_LBA_OVERLAP:
  424. return "Starting LBA overlaps";
  425. case GPT_ERROR_END_LBA_OVERLAP:
  426. return "Ending LBA overlaps";
  427. case GPT_ERROR_DUP_GUID:
  428. return "Duplicated GUID";
  429. case GPT_ERROR_INVALID_FLASH_GEOMETRY:
  430. return "Invalid flash geometry";
  431. case GPT_ERROR_NO_SUCH_ENTRY:
  432. return "No entry found";
  433. default:
  434. break;
  435. };
  436. return "Unknown";
  437. }