+static int validate_gpt_header(gpt_header *gpt_h, lbaint_t lba,
+ lbaint_t lastlba)
+{
+ uint32_t crc32_backup = 0;
+ uint32_t calc_crc32;
+
+ /* Check the GPT header signature */
+ if (le64_to_cpu(gpt_h->signature) != GPT_HEADER_SIGNATURE) {
+ printf("%s signature is wrong: 0x%llX != 0x%llX\n",
+ "GUID Partition Table Header",
+ le64_to_cpu(gpt_h->signature),
+ GPT_HEADER_SIGNATURE);
+ return -1;
+ }
+
+ /* Check the GUID Partition Table CRC */
+ memcpy(&crc32_backup, &gpt_h->header_crc32, sizeof(crc32_backup));
+ memset(&gpt_h->header_crc32, 0, sizeof(gpt_h->header_crc32));
+
+ calc_crc32 = efi_crc32((const unsigned char *)gpt_h,
+ le32_to_cpu(gpt_h->header_size));
+
+ memcpy(&gpt_h->header_crc32, &crc32_backup, sizeof(crc32_backup));
+
+ if (calc_crc32 != le32_to_cpu(crc32_backup)) {
+ printf("%s CRC is wrong: 0x%x != 0x%x\n",
+ "GUID Partition Table Header",
+ le32_to_cpu(crc32_backup), calc_crc32);
+ return -1;
+ }
+
+ /*
+ * Check that the my_lba entry points to the LBA that contains the GPT
+ */
+ if (le64_to_cpu(gpt_h->my_lba) != lba) {
+ printf("GPT: my_lba incorrect: %llX != " LBAF "\n",
+ le64_to_cpu(gpt_h->my_lba),
+ lba);
+ return -1;
+ }
+
+ /*
+ * Check that the first_usable_lba and that the last_usable_lba are
+ * within the disk.
+ */
+ if (le64_to_cpu(gpt_h->first_usable_lba) > lastlba) {
+ printf("GPT: first_usable_lba incorrect: %llX > " LBAF "\n",
+ le64_to_cpu(gpt_h->first_usable_lba), lastlba);
+ return -1;
+ }
+ if (le64_to_cpu(gpt_h->last_usable_lba) > lastlba) {
+ printf("GPT: last_usable_lba incorrect: %llX > " LBAF "\n",
+ le64_to_cpu(gpt_h->last_usable_lba), lastlba);
+ return -1;
+ }
+
+ debug("GPT: first_usable_lba: %llX last_usable_lba: %llX last lba: "
+ LBAF "\n", le64_to_cpu(gpt_h->first_usable_lba),
+ le64_to_cpu(gpt_h->last_usable_lba), lastlba);
+
+ return 0;
+}
+
+static int validate_gpt_entries(gpt_header *gpt_h, gpt_entry *gpt_e)
+{
+ uint32_t calc_crc32;
+
+ /* Check the GUID Partition Table Entry Array CRC */
+ calc_crc32 = efi_crc32((const unsigned char *)gpt_e,
+ le32_to_cpu(gpt_h->num_partition_entries) *
+ le32_to_cpu(gpt_h->sizeof_partition_entry));
+
+ if (calc_crc32 != le32_to_cpu(gpt_h->partition_entry_array_crc32)) {
+ printf("%s: 0x%x != 0x%x\n",
+ "GUID Partition Table Entry Array CRC is wrong",
+ le32_to_cpu(gpt_h->partition_entry_array_crc32),
+ calc_crc32);
+ return -1;
+ }
+
+ return 0;
+}
+
+static void prepare_backup_gpt_header(gpt_header *gpt_h)
+{
+ uint32_t calc_crc32;
+ uint64_t val;
+
+ /* recalculate the values for the Backup GPT Header */
+ val = le64_to_cpu(gpt_h->my_lba);
+ gpt_h->my_lba = gpt_h->alternate_lba;
+ gpt_h->alternate_lba = cpu_to_le64(val);
+ gpt_h->partition_entry_lba =
+ cpu_to_le64(le64_to_cpu(gpt_h->last_usable_lba) + 1);
+ gpt_h->header_crc32 = 0;
+
+ calc_crc32 = efi_crc32((const unsigned char *)gpt_h,
+ le32_to_cpu(gpt_h->header_size));
+ gpt_h->header_crc32 = cpu_to_le32(calc_crc32);
+}
+