/** * is_gpt_valid() - tests one GPT header and PTEs for validity * * lba is the logical block address of the GPT header to test * gpt is a GPT header ptr, filled on return. * ptes is a PTEs ptr, filled on return. * * Description: returns 1 if valid, 0 on error. * If valid, returns pointers to PTEs. */ static int is_gpt_valid(block_dev_desc_t *dev_desc, u64 lba, gpt_header *pgpt_head, gpt_entry **pgpt_pte) { if (!dev_desc || !pgpt_head) { printf("%s: Invalid Argument(s)\n", __func__); return 0; } /* Read GPT Header from device */ if (dev_desc->block_read(dev_desc->dev, (lbaint_t)lba, 1, pgpt_head) != 1) { printf("*** ERROR: Can't read GPT header ***\n"); return 0; } if (validate_gpt_header(pgpt_head, (lbaint_t)lba, dev_desc->lba)) return 0; /* Read and allocate Partition Table Entries */ *pgpt_pte = alloc_read_gpt_entries(dev_desc, pgpt_head); if (*pgpt_pte == NULL) { printf("GPT: Failed to allocate memory for PTE\n"); return 0; } if (validate_gpt_entries(pgpt_head, *pgpt_pte)) { free(*pgpt_pte); return 0; } /* We're done, all's well */ return 1; }
/** * is_gpt_valid() - tests one GPT header and PTEs for validity * @state * @lba is the logical block address of the GPT header to test * @gpt is a GPT header ptr, filled on return. * @ptes is a PTEs ptr, filled on return. * * Description: returns 1 if valid, 0 on error. * If valid, returns pointers to newly allocated GPT header and PTEs. */ static int is_gpt_valid(struct parsed_partitions *state, u64 lba, gpt_header **gpt, gpt_entry **ptes) { u32 crc, origcrc; u64 lastlba; if (!ptes) return 0; if (!(*gpt = alloc_read_gpt_header(state, lba))) return 0; /* Check the GUID Partition Table signature */ if (le64_to_cpu((*gpt)->signature) != GPT_HEADER_SIGNATURE) { pr_debug("GUID Partition Table Header signature is wrong:" "%lld != %lld\n", (unsigned long long)le64_to_cpu((*gpt)->signature), (unsigned long long)GPT_HEADER_SIGNATURE); goto fail; } /* Check the GUID Partition Table header size is too big */ if (le32_to_cpu((*gpt)->header_size) > bdev_logical_block_size(state->bdev)) { pr_debug("GUID Partition Table Header size is too large: %u > %u\n", le32_to_cpu((*gpt)->header_size), bdev_logical_block_size(state->bdev)); goto fail; } /* Check the GUID Partition Table header size is too small */ if (le32_to_cpu((*gpt)->header_size) < sizeof(gpt_header)) { pr_debug("GUID Partition Table Header size is too small: %u < %zu\n", le32_to_cpu((*gpt)->header_size), sizeof(gpt_header)); goto fail; } /* Check the GUID Partition Table CRC */ origcrc = le32_to_cpu((*gpt)->header_crc32); (*gpt)->header_crc32 = 0; crc = efi_crc32((const unsigned char *) (*gpt), le32_to_cpu((*gpt)->header_size)); if (crc != origcrc) { pr_debug("GUID Partition Table Header CRC is wrong: %x != %x\n", crc, origcrc); goto fail; } (*gpt)->header_crc32 = cpu_to_le32(origcrc); /* Check that the my_lba entry points to the LBA that contains * the GUID Partition Table */ if (le64_to_cpu((*gpt)->my_lba) != lba) { pr_debug("GPT my_lba incorrect: %lld != %lld\n", (unsigned long long)le64_to_cpu((*gpt)->my_lba), (unsigned long long)lba); goto fail; } /* Check the first_usable_lba and last_usable_lba are * within the disk. */ lastlba = last_lba(state->bdev); if (le64_to_cpu((*gpt)->first_usable_lba) > lastlba) { pr_debug("GPT: first_usable_lba incorrect: %lld > %lld\n", (unsigned long long)le64_to_cpu((*gpt)->first_usable_lba), (unsigned long long)lastlba); goto fail; } if (le64_to_cpu((*gpt)->last_usable_lba) > lastlba) { pr_debug("GPT: last_usable_lba incorrect: %lld > %lld\n", (unsigned long long)le64_to_cpu((*gpt)->last_usable_lba), (unsigned long long)lastlba); goto fail; } /* Check that sizeof_partition_entry has the correct value */ if (le32_to_cpu((*gpt)->sizeof_partition_entry) != sizeof(gpt_entry)) { pr_debug("GUID Partitition Entry Size check failed.\n"); goto fail; } if (!(*ptes = alloc_read_gpt_entries(state, *gpt))) goto fail; /* Check the GUID Partition Entry Array CRC */ crc = efi_crc32((const unsigned char *) (*ptes), le32_to_cpu((*gpt)->num_partition_entries) * le32_to_cpu((*gpt)->sizeof_partition_entry)); if (crc != le32_to_cpu((*gpt)->partition_entry_array_crc32)) { pr_debug("GUID Partitition Entry Array CRC check failed.\n"); goto fail_ptes; } /* We're done, all's well */ return 1; fail_ptes: kfree(*ptes); *ptes = NULL; fail: kfree(*gpt); *gpt = NULL; if (!force_gpt) BUG_ON(1); return 0; }
/** * is_gpt_valid() - tests one GPT header and PTEs for validity * * lba is the logical block address of the GPT header to test * gpt is a GPT header ptr, filled on return. * ptes is a PTEs ptr, filled on return. * * Description: returns 1 if valid, 0 on error. * If valid, returns pointers to PTEs. */ static int is_gpt_valid(block_dev_desc_t * dev_desc, unsigned long long lba, gpt_header * pgpt_head, gpt_entry ** pgpt_pte) { unsigned char crc32_backup[4] = { 0 }; unsigned long calc_crc32; unsigned long long lastlba; if (!dev_desc || !pgpt_head) { printf("%s: Invalid Argument(s)\n", __FUNCTION__); return 0; } /* Read GPT Header from device */ if (dev_desc->block_read(dev_desc->dev, lba, 1, pgpt_head) != 1) { printf("*** ERROR: Can't read GPT header ***\n"); return 0; } /* Check the GPT header signature */ if (le64_to_int(pgpt_head->signature) != GPT_HEADER_SIGNATURE) { printf("GUID Partition Table Header signature is wrong:" "0x%llX != 0x%llX\n", (unsigned long long)le64_to_int(pgpt_head->signature), (unsigned long long)GPT_HEADER_SIGNATURE); return 0; } /* Check the GUID Partition Table CRC */ memcpy(crc32_backup, pgpt_head->header_crc32, sizeof(crc32_backup)); memset(pgpt_head->header_crc32, 0, sizeof(pgpt_head->header_crc32)); calc_crc32 = efi_crc32((const unsigned char *)pgpt_head, le32_to_int(pgpt_head->header_size)); memcpy(pgpt_head->header_crc32, crc32_backup, sizeof(crc32_backup)); if (calc_crc32 != le32_to_int(crc32_backup)) { printf("GUID Partition Table Header CRC is wrong:" "0x%08lX != 0x%08lX\n", le32_to_int(crc32_backup), calc_crc32); return 0; } /* Check that the my_lba entry points to the LBA that contains the GPT */ if (le64_to_int(pgpt_head->my_lba) != lba) { printf("GPT: my_lba incorrect: %llX != %llX\n", (unsigned long long)le64_to_int(pgpt_head->my_lba), (unsigned long long)lba); return 0; } /* Check the first_usable_lba and last_usable_lba are within the disk. */ lastlba = (unsigned long long)dev_desc->lba; if (le64_to_int(pgpt_head->first_usable_lba) > lastlba) { printf("GPT: first_usable_lba incorrect: %llX > %llX\n", le64_to_int(pgpt_head->first_usable_lba), lastlba); return 0; } if (le64_to_int(pgpt_head->last_usable_lba) > lastlba) { printf("GPT: last_usable_lba incorrect: %llX > %llX\n", le64_to_int(pgpt_head->last_usable_lba), lastlba); return 0; } debug("GPT: first_usable_lba: %llX last_usable_lba %llX last lba %llX\n", le64_to_int(pgpt_head->first_usable_lba), le64_to_int(pgpt_head->last_usable_lba), lastlba); /* Read and allocate Partition Table Entries */ *pgpt_pte = alloc_read_gpt_entries(dev_desc, pgpt_head); if (*pgpt_pte == NULL) { printf("GPT: Failed to allocate memory for PTE\n"); return 0; } /* Check the GUID Partition Table Entry Array CRC */ calc_crc32 = efi_crc32((const unsigned char *)*pgpt_pte, le32_to_int(pgpt_head->num_partition_entries) * le32_to_int(pgpt_head->sizeof_partition_entry)); if (calc_crc32 != le32_to_int(pgpt_head->partition_entry_array_crc32)) { printf("GUID Partition Table Entry Array CRC is wrong:" "0x%08lX != 0x%08lX\n", le32_to_int(pgpt_head->partition_entry_array_crc32), calc_crc32); if (*pgpt_pte != NULL) { free(*pgpt_pte); } return 0; } /* We're done, all's well */ return 1; }
/** * is_gpt_valid() - tests one GPT header and PTEs for validity * @bdev * @lba is the logical block address of the GPT header to test * @gpt is a GPT header ptr, filled on return. * @ptes is a PTEs ptr, filled on return. * * Description: returns 1 if valid, 0 on error. * If valid, returns pointers to newly allocated GPT header and PTEs. */ static int is_gpt_valid(struct block_device *bdev, u64 lba, gpt_header **gpt, gpt_entry **ptes) { u32 crc, origcrc; u64 lastlba; if (!bdev || !gpt || !ptes) return 0; if (!(*gpt = alloc_read_gpt_header(bdev, lba))) return 0; /* Check the GUID Partition Table signature */ if (le64_to_cpu((*gpt)->signature) != GPT_HEADER_SIGNATURE) { Dprintk("GUID Partition Table Header signature is wrong:" "%lld != %lld\n", (unsigned long long)le64_to_cpu((*gpt)->signature), (unsigned long long)GPT_HEADER_SIGNATURE); goto fail; } /* Check the GUID Partition Table CRC */ origcrc = le32_to_cpu((*gpt)->header_crc32); (*gpt)->header_crc32 = 0; crc = efi_crc32((const unsigned char *) (*gpt), le32_to_cpu((*gpt)->header_size)); if (crc != origcrc) { Dprintk ("GUID Partition Table Header CRC is wrong: %x != %x\n", crc, origcrc); goto fail; } (*gpt)->header_crc32 = cpu_to_le32(origcrc); /* Check that the my_lba entry points to the LBA that contains * the GUID Partition Table */ if (le64_to_cpu((*gpt)->my_lba) != lba) { Dprintk("GPT my_lba incorrect: %lld != %lld\n", (unsigned long long)le64_to_cpu((*gpt)->my_lba), (unsigned long long)lba); goto fail; } /* Check the first_usable_lba and last_usable_lba are * within the disk. */ lastlba = last_lba(bdev); if (le64_to_cpu((*gpt)->first_usable_lba) > lastlba) { Dprintk("GPT: first_usable_lba incorrect: %lld > %lld\n", (unsigned long long)le64_to_cpu((*gpt)->first_usable_lba), (unsigned long long)lastlba); goto fail; } if (le64_to_cpu((*gpt)->last_usable_lba) > lastlba) { Dprintk("GPT: last_usable_lba incorrect: %lld > %lld\n", (unsigned long long)le64_to_cpu((*gpt)->last_usable_lba), (unsigned long long)lastlba); goto fail; } if (!(*ptes = alloc_read_gpt_entries(bdev, *gpt))) goto fail; /* Check the GUID Partition Entry Array CRC */ crc = efi_crc32((const unsigned char *) (*ptes), le32_to_cpu((*gpt)->num_partition_entries) * le32_to_cpu((*gpt)->sizeof_partition_entry)); if (crc != le32_to_cpu((*gpt)->partition_entry_array_crc32)) { Dprintk("GUID Partitition Entry Array CRC check failed.\n"); goto fail_ptes; } /* We're done, all's well */ return 1; fail_ptes: kfree(*ptes); *ptes = NULL; fail: kfree(*gpt); *gpt = NULL; return 0; }
/** * is_gpt_valid() - tests one GPT header and PTEs for validity * @fd is an open file descriptor to the whole disk * @lba is the logical block address of the GPT header to test * @gpt is a GPT header ptr, filled on return. * @ptes is a PTEs ptr, filled on return. * * Description: returns 1 if valid, 0 on error. * If valid, returns pointers to newly allocated GPT header and PTEs. */ static int is_gpt_valid(int fd, uint64_t lba, gpt_header ** gpt, gpt_entry ** ptes) { int rc = 0; /* default to not valid */ uint32_t crc, origcrc; if (!gpt || !ptes) return 0; if (!(*gpt = alloc_read_gpt_header(fd, lba))) return 0; /* Check the GUID Partition Table signature */ if (__le64_to_cpu((*gpt)->signature) != GPT_HEADER_SIGNATURE) { /* printf("GUID Partition Table Header signature is wrong: %" PRIx64" != %" PRIx64 "\n", __le64_to_cpu((*gpt)->signature), GUID_PT_HEADER_SIGNATURE); */ free(*gpt); *gpt = NULL; return rc; } /* Check the GUID Partition Table Header CRC */ origcrc = __le32_to_cpu((*gpt)->header_crc32); (*gpt)->header_crc32 = 0; crc = efi_crc32(*gpt, __le32_to_cpu((*gpt)->header_size)); if (crc != origcrc) { // printf( "GPTH CRC check failed, %x != %x.\n", origcrc, crc); (*gpt)->header_crc32 = __cpu_to_le32(origcrc); free(*gpt); *gpt = NULL; return 0; } (*gpt)->header_crc32 = __cpu_to_le32(origcrc); /* Check that the my_lba entry points to the LBA * that contains the GPT we read */ if (__le64_to_cpu((*gpt)->my_lba) != lba) { // printf( "my_lba % PRIx64 "x != lba %"PRIx64 "x.\n", __le64_to_cpu((*gpt)->my_lba), lba); free(*gpt); *gpt = NULL; return 0; } if (!(*ptes = alloc_read_gpt_entries(fd, *gpt))) { free(*gpt); *gpt = NULL; return 0; } /* Check the GUID Partition Entry Array CRC */ crc = efi_crc32(*ptes, __le32_to_cpu((*gpt)->num_partition_entries) * __le32_to_cpu((*gpt)->sizeof_partition_entry)); if (crc != __le32_to_cpu((*gpt)->partition_entry_array_crc32)) { // printf("GUID Partitition Entry Array CRC check failed.\n"); free(*gpt); *gpt = NULL; free(*ptes); *ptes = NULL; return 0; } /* We're done, all's well */ return 1; }
/** * is_gpt_valid() - tests one GPT header and PTEs for validity * @bdev * @lba is the logical block address of the GPT header to test * @gpt is a GPT header ptr, filled on return. * @ptes is a PTEs ptr, filled on return. * * Description: returns 1 if valid, 0 on error. * If valid, returns pointers to newly allocated GPT header and PTEs. */ static int is_gpt_valid(struct block_device *bdev, u64 lba, gpt_header **gpt, gpt_entry **ptes) { u32 crc, origcrc; if (!bdev || !gpt || !ptes) return 0; if (!(*gpt = alloc_read_gpt_header(bdev, lba))) return 0; /* Check the GUID Partition Table signature */ if (le64_to_cpu((*gpt)->signature) != GPT_HEADER_SIGNATURE) { Dprintk("GUID Partition Table Header signature is wrong: %" PRIx64 " != %" PRIx64 "\n", le64_to_cpu((*gpt)->signature), GPT_HEADER_SIGNATURE); kfree(*gpt); *gpt = NULL; return 0; } /* Check the GUID Partition Table CRC */ origcrc = le32_to_cpu((*gpt)->header_crc32); (*gpt)->header_crc32 = 0; crc = efi_crc32((const unsigned char *) (*gpt), le32_to_cpu((*gpt)->header_size)); if (crc != origcrc) { Dprintk ("GUID Partition Table Header CRC is wrong: %x != %x\n", crc, origcrc); kfree(*gpt); *gpt = NULL; return 0; } (*gpt)->header_crc32 = cpu_to_le32(origcrc); /* Check that the my_lba entry points to the LBA that contains * the GUID Partition Table */ if (le64_to_cpu((*gpt)->my_lba) != lba) { Dprintk("GPT my_lba incorrect: %" PRIx64 " != %" PRIx64 "\n", le64_to_cpu((*gpt)->my_lba), lba); kfree(*gpt); *gpt = NULL; return 0; } if (!(*ptes = alloc_read_gpt_entries(bdev, *gpt))) { kfree(*gpt); *gpt = NULL; return 0; } /* Check the GUID Partition Entry Array CRC */ crc = efi_crc32((const unsigned char *) (*ptes), le32_to_cpu((*gpt)->num_partition_entries) * le32_to_cpu((*gpt)->sizeof_partition_entry)); if (crc != le32_to_cpu((*gpt)->partition_entry_array_crc32)) { Dprintk("GUID Partitition Entry Array CRC check failed.\n"); kfree(*gpt); *gpt = NULL; kfree(*ptes); *ptes = NULL; return 0; } /* We're done, all's well */ return 1; }