/** * efi_partition(struct parsed_partitions *state) * @state * * Description: called from check.c, if the disk contains GPT * partitions, sets up partition entries in the kernel. * * If the first block on the disk is a legacy MBR, * it will get handled by msdos_partition(). * If it's a Protective MBR, we'll handle it here. * * We do not create a Linux partition for GPT, but * only for the actual data partitions. * Returns: * -1 if unable to read the partition table * 0 if this isn't our partition table * 1 if successful * */ int efi_partition(struct parsed_partitions *state) { gpt_header *gpt = NULL; gpt_entry *ptes = NULL; u32 i; unsigned ssz = bdev_logical_block_size(state->bdev) / 512; if (!find_valid_gpt(state, &gpt, &ptes) || !gpt || !ptes) { kfree(gpt); kfree(ptes); return 0; } pr_debug("GUID Partition Table is valid! Yea!\n"); for (i = 0; i < le32_to_cpu(gpt->num_partition_entries) && i < state->limit-1; i++) { u64 start = le64_to_cpu(ptes[i].starting_lba); u64 size = le64_to_cpu(ptes[i].ending_lba) - le64_to_cpu(ptes[i].starting_lba) + 1ULL; if (!is_pte_valid(&ptes[i], last_lba(state->bdev))) continue; put_partition(state, i+1, start * ssz, size * ssz); /* If this is a RAID volume, tell md */ if (!efi_guidcmp(ptes[i].partition_type_guid, PARTITION_LINUX_RAID_GUID)) state->parts[i + 1].flags = ADDPART_FLAG_RAID; } kfree(ptes); kfree(gpt); printk("\n"); return 1; }
/** * efi_partition(struct parsed_partitions *state, struct block_device *bdev) * @state * @bdev * * Description: called from check.c, if the disk contains GPT * partitions, sets up partition entries in the kernel. * * If the first block on the disk is a legacy MBR, * it will get handled by msdos_partition(). * If it's a Protective MBR, we'll handle it here. * * We do not create a Linux partition for GPT, but * only for the actual data partitions. * Returns: * -1 if unable to read the partition table * 0 if this isn't our partition table * 1 if successful * */ int efi_partition(struct parsed_partitions *state, struct block_device *bdev) { gpt_header *gpt = NULL; gpt_entry *ptes = NULL; u32 i; if (!find_valid_gpt(bdev, &gpt, &ptes) || !gpt || !ptes) { kfree(gpt); kfree(ptes); return 0; } Dprintk("GUID Partition Table is valid! Yea!\n"); for (i = 0; i < le32_to_cpu(gpt->num_partition_entries) && i < state->limit-1; i++) { if (!is_pte_valid(&ptes[i], last_lba(bdev))) continue; put_partition(state, i+1, le64_to_cpu(ptes[i].starting_lba), (le64_to_cpu(ptes[i].ending_lba) - le64_to_cpu(ptes[i].starting_lba) + 1ULL)); /* If this is a RAID volume, tell md */ if (!efi_guidcmp(ptes[i].partition_type_guid, PARTITION_LINUX_RAID_GUID)) state->parts[i+1].flags = 1; } kfree(ptes); kfree(gpt); printk("\n"); return 1; }
int get_partition_num_efi(block_dev_desc_t *dev_desc) { ALLOC_CACHE_ALIGN_BUFFER_PAD(gpt_header, gpt_head, 1, dev_desc->blksz); gpt_entry *gpt_pte = NULL; int i; if (!dev_desc) { printf("%s: Invalid Argument(s)\n", __func__); return 0; } /* This function validates AND fills in the GPT header and PTE */ if (is_gpt_valid(dev_desc, GPT_PRIMARY_PARTITION_TABLE_LBA, gpt_head, &gpt_pte) != 1) { printf("%s: *** ERROR: Invalid GPT ***\n", __func__); return 0; } for (i = 0; i < le32_to_cpu(gpt_head->num_partition_entries); i++) if (!is_pte_valid(&gpt_pte[i])) break; /* Remember to free pte */ free(gpt_pte); return i; }
/** * efi_partition(struct parsed_partitions *state) * @state * * Description: called from check.c, if the disk contains GPT * partitions, sets up partition entries in the kernel. * * If the first block on the disk is a legacy MBR, * it will get handled by msdos_partition(). * If it's a Protective MBR, we'll handle it here. * * We do not create a Linux partition for GPT, but * only for the actual data partitions. * Returns: * -1 if unable to read the partition table * 0 if this isn't our partition table * 1 if successful * */ int efi_partition(struct parsed_partitions *state) { gpt_header *gpt = NULL; gpt_entry *ptes = NULL; u32 i; unsigned ssz = bdev_logical_block_size(state->bdev) / 512; u8 unparsed_guid[37]; if (!find_valid_gpt(state, &gpt, &ptes) || !gpt || !ptes) { kfree(gpt); kfree(ptes); return 0; } pr_debug("GUID Partition Table is valid! Yea!\n"); for (i = 0; i < le32_to_cpu(gpt->num_partition_entries) && i < state->limit-1; i++) { struct partition_meta_info *info; unsigned label_count = 0; unsigned label_max; u64 start = le64_to_cpu(ptes[i].starting_lba); u64 size = le64_to_cpu(ptes[i].ending_lba) - le64_to_cpu(ptes[i].starting_lba) + 1ULL; if (!is_pte_valid(&ptes[i], last_lba(state->bdev))) continue; put_partition(state, i+1, start * ssz, size * ssz); /* If this is a RAID volume, tell md */ if (!efi_guidcmp(ptes[i].partition_type_guid, PARTITION_LINUX_RAID_GUID)) state->parts[i + 1].flags = ADDPART_FLAG_RAID; info = &state->parts[i + 1].info; /* Instead of doing a manual swap to big endian, reuse the * common ASCII hex format as the interim. */ efi_guid_unparse(&ptes[i].unique_partition_guid, unparsed_guid); part_pack_uuid(unparsed_guid, info->uuid); /* Naively convert UTF16-LE to 7 bits. */ label_max = min(sizeof(info->volname) - 1, sizeof(ptes[i].partition_name)); info->volname[label_max] = 0; while (label_count < label_max) { u8 c = ptes[i].partition_name[label_count] & 0xff; if (c && !isprint(c)) c = '!'; info->volname[label_count] = c; label_count++; } state->parts[i + 1].has_info = true; } kfree(ptes); kfree(gpt); strlcat(state->pp_buf, "\n", PAGE_SIZE); return 1; }
int get_partition_info_efi(block_dev_desc_t * dev_desc, int part, disk_partition_t * info) { ALLOC_CACHE_ALIGN_BUFFER_PAD(gpt_header, gpt_head, 1, dev_desc->blksz); gpt_entry *gpt_pte = NULL; /* "part" argument must be at least 1 */ if (!dev_desc || !info || part < 1) { printf("%s: Invalid Argument(s)\n", __func__); return -1; } /* This function validates AND fills in the GPT header and PTE */ if (is_gpt_valid(dev_desc, GPT_PRIMARY_PARTITION_TABLE_LBA, gpt_head, &gpt_pte) != 1) { printf("%s: *** ERROR: Invalid GPT ***\n", __func__); if (is_gpt_valid(dev_desc, (dev_desc->lba - 1), gpt_head, &gpt_pte) != 1) { printf("%s: *** ERROR: Invalid Backup GPT ***\n", __func__); return -1; } else { printf("%s: *** Using Backup GPT ***\n", __func__); } } if (part > le32_to_cpu(gpt_head->num_partition_entries) || !is_pte_valid(&gpt_pte[part - 1])) { debug("%s: *** ERROR: Invalid partition number %d ***\n", __func__, part); free(gpt_pte); return -1; } /* The 'lbaint_t' casting may limit the maximum disk size to 2 TB */ info->start = (lbaint_t)le64_to_cpu(gpt_pte[part - 1].starting_lba); /* The ending LBA is inclusive, to calculate size, add 1 to it */ info->size = (lbaint_t)le64_to_cpu(gpt_pte[part - 1].ending_lba) + 1 - info->start; info->blksz = dev_desc->blksz; sprintf((char *)info->name, "%s", print_efiname(&gpt_pte[part - 1])); sprintf((char *)info->type, "U-Boot"); info->bootable = is_bootable(&gpt_pte[part - 1]); #ifdef CONFIG_PARTITION_UUIDS uuid_bin_to_str(gpt_pte[part - 1].unique_partition_guid.b, info->uuid, UUID_STR_FORMAT_GUID); #endif debug("%s: start 0x" LBAF ", size 0x" LBAF ", name %s\n", __func__, info->start, info->size, info->name); /* Remember to free pte */ free(gpt_pte); return 0; }
void print_part_efi(block_dev_desc_t * dev_desc) { ALLOC_CACHE_ALIGN_BUFFER_PAD(gpt_header, gpt_head, 1, dev_desc->blksz); gpt_entry *gpt_pte = NULL; int i = 0; char uuid[37]; unsigned char *uuid_bin; if (!dev_desc) { printf("%s: Invalid Argument(s)\n", __func__); return; } /* This function validates AND fills in the GPT header and PTE */ if (is_gpt_valid(dev_desc, GPT_PRIMARY_PARTITION_TABLE_LBA, gpt_head, &gpt_pte) != 1) { printf("%s: *** ERROR: Invalid GPT ***\n", __func__); if (is_gpt_valid(dev_desc, (dev_desc->lba - 1), gpt_head, &gpt_pte) != 1) { printf("%s: *** ERROR: Invalid Backup GPT ***\n", __func__); return; } else { printf("%s: *** Using Backup GPT ***\n", __func__); } } debug("%s: gpt-entry at %p\n", __func__, gpt_pte); printf("Part\tStart LBA\tEnd LBA\t\tName\n"); printf("\tAttributes\n"); printf("\tType GUID\n"); printf("\tPartition GUID\n"); for (i = 0; i < le32_to_cpu(gpt_head->num_partition_entries); i++) { /* Stop at the first non valid PTE */ if (!is_pte_valid(&gpt_pte[i])) break; printf("%3d\t0x%08llx\t0x%08llx\t\"%s\"\n", (i + 1), le64_to_cpu(gpt_pte[i].starting_lba), le64_to_cpu(gpt_pte[i].ending_lba), print_efiname(&gpt_pte[i])); printf("\tattrs:\t0x%016llx\n", gpt_pte[i].attributes.raw); uuid_bin = (unsigned char *)gpt_pte[i].partition_type_guid.b; uuid_bin_to_str(uuid_bin, uuid, UUID_STR_FORMAT_GUID); printf("\ttype:\t%s\n", uuid); uuid_bin = (unsigned char *)gpt_pte[i].unique_partition_guid.b; uuid_bin_to_str(uuid_bin, uuid, UUID_STR_FORMAT_GUID); printf("\tguid:\t%s\n", uuid); } /* Remember to free pte */ free(gpt_pte); return; }
int get_partition_info_efi(block_dev_desc_t * dev_desc, int part, disk_partition_t * info) { gpt_header gpt_head; gpt_entry *pgpt_pte = NULL; /* "part" argument must be at least 1 */ if (!dev_desc || !info || part < 1) { printf("%s: Invalid Argument(s)\n", __FUNCTION__); return -1; } /* This function validates AND fills in the GPT header and PTE */ if (is_gpt_valid(dev_desc, GPT_PRIMARY_PARTITION_TABLE_LBA, &(gpt_head), &pgpt_pte) != 1) { printf("%s: *** ERROR: Invalid GPT ***\n", __FUNCTION__); return -1; } /* valid entry? */ if (part > le32_to_int(gpt_head.num_partition_entries)) return -1; if (!is_pte_valid(&pgpt_pte[part - 1])) return -1; /* The ulong casting limits the maximum disk size to 2 TB */ info->start = (ulong) le64_to_int(pgpt_pte[part - 1].starting_lba); /* The ending LBA is inclusive, to calculate size, add 1 to it */ info->size = ((ulong)le64_to_int(pgpt_pte[part - 1].ending_lba) + 1) - info->start; info->blksz = GPT_BLOCK_SIZE; sprintf((char *)info->name, "%s%d", GPT_ENTRY_NAME, part); if (is_pte_env(&pgpt_pte[part - 1])) sprintf((char *)info->type, BOOT_PART_ENV); else sprintf((char *)info->type, BOOT_PART_TYPE); debug("%s: start 0x%lX, size 0x%lX, name %s", __FUNCTION__, info->start, info->size, info->name); /* Remember to free pte */ if (pgpt_pte != NULL) { debug("%s: Freeing pgpt_pte\n", __FUNCTION__); free(pgpt_pte); } return 0; }
void print_part_efi(block_dev_desc_t * dev_desc) { gpt_header gpt_head; gpt_entry *pgpt_pte; int i = 0; unsigned char name[ARRAY_SIZE(pgpt_pte->partition_name) + 1]; if (!dev_desc) { printf("%s: Invalid Argument(s)\n", __FUNCTION__); return; } /* This function validates AND fills in the GPT header and PTE */ if (is_gpt_valid(dev_desc, GPT_PRIMARY_PARTITION_TABLE_LBA, &(gpt_head), &pgpt_pte) != 1) { printf("%s: *** ERROR: Invalid GPT ***\n", __FUNCTION__); return; } debug("%s: gpt-entry at 0x%p\n", __func__, pgpt_pte); printf("Part Start LBA End LBA Name\n"); for (i = 0; i < le32_to_int(gpt_head.num_partition_entries); i++) { if (is_pte_valid(&pgpt_pte[i])) { unicode2asc(pgpt_pte[i].partition_name, name, sizeof(name)); printf("%s%d 0x%08llX 0x%08llX %s\n", GPT_ENTRY_NAME, (i + 1), le64_to_int(pgpt_pte[i].starting_lba), le64_to_int(pgpt_pte[i].ending_lba), name); } else { break; /* Stop at the first non valid PTE */ } } /* Remember to free pte */ if (pgpt_pte != NULL) { debug("%s: Freeing pgpt_pte\n", __FUNCTION__); free(pgpt_pte); } return; }
int find_part_efi(block_dev_desc_t * dev_desc, char *name, disk_partition_t * info) { ALLOC_CACHE_ALIGN_BUFFER(gpt_header, gpt_head, 1); gpt_entry *gpt_pte = NULL; int i = 0, pos = 0; /* "part" argument must be at least 1 */ if (!dev_desc || !info ) { printf("%s: Invalid Argument(s)\n", __func__); return -1; } /* This function validates AND fills in the GPT header and PTE */ if (is_gpt_valid(dev_desc, GPT_PRIMARY_PARTITION_TABLE_LBA, gpt_head, &gpt_pte) != 1) { printf("%s: *** ERROR: Invalid Primary GPT ***\n", __func__); if (is_gpt_valid(dev_desc, (dev_desc->lba - 1), gpt_head, &gpt_pte) != 1) { printf("%s: *** ERROR: Invalid Backup GPT ***\n", __func__); return -1; } } for (i = 0; i < le32_to_int(gpt_head->num_partition_entries); i++) { if (is_pte_valid(&gpt_pte[i]) && !(strcmp(name, print_efiname(&gpt_pte[i])))) { /* The ulong casting limits the maximum disk size to 2 TB */ info->start = (ulong) le64_to_int(gpt_pte[i].starting_lba); /* The ending LBA is inclusive, to calculate size, add 1 to it */ info->size = ((ulong)le64_to_int(gpt_pte[i].ending_lba) + 1) - info->start; info->blksz = GPT_BLOCK_SIZE; sprintf((char *)info->name, "%s", print_efiname(&gpt_pte[i])); sprintf((char *)info->type, "U-Boot"); pos = i + 1; } } /* Remember to free pte */ free(gpt_pte); return pos; }
/** * efi_partition(struct parsed_partitions *state) * @state * * Description: called from check.c, if the disk contains GPT * partitions, sets up partition entries in the kernel. * * If the first block on the disk is a legacy MBR, * it will get handled by msdos_partition(). * If it's a Protective MBR, we'll handle it here. * * We do not create a Linux partition for GPT, but * only for the actual data partitions. * Returns: * -1 if unable to read the partition table * 0 if this isn't our partition table * 1 if successful * */ int efi_partition(struct parsed_partitions *state) { gpt_header *gpt = NULL; gpt_entry *ptes = NULL; u32 i; unsigned ssz = bdev_logical_block_size(state->bdev) / 512; if (!find_valid_gpt(state, &gpt, &ptes) || !gpt || !ptes) { kfree(gpt); kfree(ptes); return 0; } pr_debug("GUID Partition Table is valid! Yea!\n"); for (i = 0; i < le32_to_cpu(gpt->num_partition_entries) && i < state->limit-1; i++) { u64 start = le64_to_cpu(ptes[i].starting_lba); u64 size = le64_to_cpu(ptes[i].ending_lba) - le64_to_cpu(ptes[i].starting_lba) + 1ULL; u8 name[sizeof(ptes->partition_name) / sizeof(efi_char16_t)]; int len; if (!is_pte_valid(&ptes[i], last_lba(state->bdev))) continue; len = utf16s_to_utf8s(ptes[i].partition_name, sizeof(ptes[i].partition_name) / sizeof(efi_char16_t), UTF16_LITTLE_ENDIAN, name, sizeof(name)); put_named_partition(state, i+1, start * ssz, size * ssz, name, len); /* If this is a RAID volume, tell md */ if (!efi_guidcmp(ptes[i].partition_type_guid, PARTITION_LINUX_RAID_GUID)) state->parts[i + 1].flags = ADDPART_FLAG_RAID; } kfree(ptes); kfree(gpt); strlcat(state->pp_buf, "\n", PAGE_SIZE); return 1; }
/** * efi_partition(struct parsed_partitions *state, struct block_device *bdev) * @state * @bdev * * Description: called from check.c, if the disk contains GPT * partitions, sets up partition entries in the kernel. * * If the first block on the disk is a legacy MBR, * it will get handled by msdos_partition(). * If it's a Protective MBR, we'll handle it here. * * We do not create a Linux partition for GPT, but * only for the actual data partitions. * Returns: * -1 if unable to read the partition table * 0 if this isn't our partition table * 1 if successful * */ int efi_partition(struct parsed_partitions *state, struct block_device *bdev) { gpt_header *gpt = NULL; gpt_entry *ptes = NULL; u32 i; unsigned ssz = bdev_hardsect_size(bdev) / 512; if (!find_valid_gpt(bdev, &gpt, &ptes) || !gpt || !ptes) { kfree(gpt); kfree(ptes); return 0; } Dprintk("GUID Partition Table is valid! Yea!\n"); for (i = 0; i < le32_to_cpu(gpt->num_partition_entries) && i < state->limit-1; i++) { u64 start = le64_to_cpu(ptes[i].starting_lba); u64 size = le64_to_cpu(ptes[i].ending_lba) - le64_to_cpu(ptes[i].starting_lba) + 1ULL; if (!is_pte_valid(&ptes[i], last_lba(bdev))) continue; put_partition(state, i+1, start * ssz, size * ssz); /* If this is a RAID volume, tell md */ if (!efi_guidcmp(ptes[i].partition_type_guid, PARTITION_LINUX_RAID_GUID)) state->parts[i+1].flags = 1; /* If this is a EFI System partition, tell hotplug */ if (!efi_guidcmp(ptes[i].partition_type_guid, PARTITION_SYSTEM_GUID)) state->parts[i+1].is_efi_system_partition = 1; } kfree(ptes); kfree(gpt); printk("\n"); return 1; }
void print_part_efi(block_dev_desc_t * dev_desc) { ALLOC_CACHE_ALIGN_BUFFER(gpt_header, gpt_head, 1); gpt_entry *gpt_pte = NULL; int i = 0; if (!dev_desc) { printf("%s: Invalid Argument(s)\n", __func__); return; } /* This function validates AND fills in the GPT header and PTE */ if (is_gpt_valid(dev_desc, GPT_PRIMARY_PARTITION_TABLE_LBA, gpt_head, &gpt_pte) != 1) { printf("%s: *** ERROR: Invalid Primary GPT ***\n", __func__); if (is_gpt_valid(dev_desc, (dev_desc->lba - 1), gpt_head, &gpt_pte) != 1) { printf("%s: *** ERROR: Invalid Backup GPT ***\n", __func__); return -1; } } debug("%s: gpt-entry at %p\n", __func__, gpt_pte); printf("Part\tName\t\t\tStart LBA\tEnd LBA\n"); for (i = 0; i < le32_to_int(gpt_head->num_partition_entries); i++) { if (is_pte_valid(&gpt_pte[i])) { printf("%3d\t%-18s\t0x%08llX\t0x%08llX\n", (i + 1), print_efiname(&gpt_pte[i]), le64_to_int(gpt_pte[i].starting_lba), le64_to_int(gpt_pte[i].ending_lba)); } else { break; /* Stop at the first non valid PTE */ } } /* Remember to free pte */ free(gpt_pte); return; }
void print_part_efi(block_dev_desc_t * dev_desc) { gpt_header gpt_head; gpt_entry *pgpt_pte = NULL; int i = 0; if (!dev_desc) { printf("%s: Invalid Argument(s)\n", __FUNCTION__); return; } /* This function validates AND fills in the GPT header and PTE */ if (is_gpt_valid(dev_desc, GPT_PRIMARY_PARTITION_TABLE_LBA, &(gpt_head), &pgpt_pte) != 1) { printf("%s: *** ERROR: Invalid GPT ***\n", __FUNCTION__); return; } debug("%s: gpt-entry at 0x%08X\n", __FUNCTION__, (unsigned int)pgpt_pte); printf("Part Start LBA End LBA\n"); for (i = 0; i < le32_to_int(gpt_head.num_partition_entries); i++) { if (is_pte_valid(&(pgpt_pte)[i])) { printf("%s%d 0x%llX 0x%llX\n", GPT_ENTRY_NAME, (i + 1), le64_to_int((pgpt_pte)[i].starting_lba), le64_to_int((pgpt_pte)[i].ending_lba)); } else { break; /* Stop at the first non valid PTE */ } } /* Remember to free pte */ if (pgpt_pte != NULL) { debug("%s: Freeing pgpt_pte\n", __FUNCTION__); free(pgpt_pte); } return; }
/** * find_valid_gpt() - Search disk for valid GPT headers and PTEs * @state * @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. * Validity depends on PMBR being valid (or being overridden by the * 'gpt' kernel command line option) and finding either the Primary * GPT header and PTEs valid, or the Alternate GPT header and PTEs * valid. If the Primary GPT header is not valid, the Alternate GPT header * is not checked unless the 'gpt' kernel command line option is passed. * This protects against devices which misreport their size, and forces * the user to decide to use the Alternate GPT. */ static int find_valid_gpt(struct parsed_partitions *state, gpt_header **gpt, gpt_entry **ptes) { int good_pgpt = 0, good_agpt = 0, good_pmbr = 0; gpt_header *pgpt = NULL, *agpt = NULL; gpt_entry *pptes = NULL, *aptes = NULL; legacy_mbr *legacymbr; u64 lastlba; if (!ptes) return 0; lastlba = last_lba(state->bdev); #if 0 // merged from msm8960-gb by ZTE_BOOT_JIA_20120105 jia.jia if (!force_gpt) { #else if (force_gpt) { #endif /* This will be added to the EFI Spec. per Intel after v1.02. */ legacymbr = kzalloc(sizeof (*legacymbr), GFP_KERNEL); if (legacymbr) { read_lba(state, 0, (u8 *) legacymbr, sizeof (*legacymbr)); good_pmbr = is_pmbr_valid(legacymbr); kfree(legacymbr); } if (!good_pmbr) goto fail; } good_pgpt = is_gpt_valid(state, GPT_PRIMARY_PARTITION_TABLE_LBA, &pgpt, &pptes); if (good_pgpt) good_agpt = is_gpt_valid(state, le64_to_cpu(pgpt->alternate_lba), &agpt, &aptes); if (!good_agpt && force_gpt) good_agpt = is_gpt_valid(state, lastlba, &agpt, &aptes); /* The obviously unsuccessful case */ if (!good_pgpt && !good_agpt) goto fail; compare_gpts(pgpt, agpt, lastlba); /* The good cases */ if (good_pgpt) { *gpt = pgpt; *ptes = pptes; kfree(agpt); kfree(aptes); if (!good_agpt) { printk(KERN_WARNING "Alternate GPT is invalid, " "using primary GPT.\n"); } return 1; } else if (good_agpt) { *gpt = agpt; *ptes = aptes; kfree(pgpt); kfree(pptes); printk(KERN_WARNING "Primary GPT is invalid, using alternate GPT.\n"); return 1; } fail: kfree(pgpt); kfree(agpt); kfree(pptes); kfree(aptes); *gpt = NULL; *ptes = NULL; return 0; } /** * efi_partition(struct parsed_partitions *state) * @state * * Description: called from check.c, if the disk contains GPT * partitions, sets up partition entries in the kernel. * * If the first block on the disk is a legacy MBR, * it will get handled by msdos_partition(). * If it's a Protective MBR, we'll handle it here. * * We do not create a Linux partition for GPT, but * only for the actual data partitions. * Returns: * -1 if unable to read the partition table * 0 if this isn't our partition table * 1 if successful * */ int efi_partition(struct parsed_partitions *state) { gpt_header *gpt = NULL; gpt_entry *ptes = NULL; u32 i; unsigned ssz = bdev_logical_block_size(state->bdev) / 512; u8 unparsed_guid[37]; if (!find_valid_gpt(state, &gpt, &ptes) || !gpt || !ptes) { kfree(gpt); kfree(ptes); return 0; } pr_debug("GUID Partition Table is valid! Yea!\n"); for (i = 0; i < le32_to_cpu(gpt->num_partition_entries) && i < state->limit-1; i++) { struct partition_meta_info *info; unsigned label_count = 0; unsigned label_max; u64 start = le64_to_cpu(ptes[i].starting_lba); u64 size = le64_to_cpu(ptes[i].ending_lba) - le64_to_cpu(ptes[i].starting_lba) + 1ULL; if (!is_pte_valid(&ptes[i], last_lba(state->bdev))) continue; put_partition(state, i+1, start * ssz, size * ssz); /* If this is a RAID volume, tell md */ if (!efi_guidcmp(ptes[i].partition_type_guid, PARTITION_LINUX_RAID_GUID)) state->parts[i + 1].flags = ADDPART_FLAG_RAID; info = &state->parts[i + 1].info; /* Instead of doing a manual swap to big endian, reuse the * common ASCII hex format as the interim. */ efi_guid_unparse(&ptes[i].unique_partition_guid, unparsed_guid); part_pack_uuid(unparsed_guid, info->uuid); /* Naively convert UTF16-LE to 7 bits. */ label_max = min(sizeof(info->volname) - 1, sizeof(ptes[i].partition_name)); info->volname[label_max] = 0; while (label_count < label_max) { u8 c = ptes[i].partition_name[label_count] & 0xff; if (c && !isprint(c)) c = '!'; info->volname[label_count] = c; label_count++; } state->parts[i + 1].has_info = true; } kfree(ptes); kfree(gpt); strlcat(state->pp_buf, "\n", PAGE_SIZE); return 1; }
/** * efi_partition(struct parsed_partitions *state) * @state * * Description: called from check.c, if the disk contains GPT * partitions, sets up partition entries in the kernel. * * If the first block on the disk is a legacy MBR, * it will get handled by msdos_partition(). * If it's a Protective MBR, we'll handle it here. * * We do not create a Linux partition for GPT, but * only for the actual data partitions. * Returns: * -1 if unable to read the partition table * 0 if this isn't our partition table * 1 if successful * */ int efi_partition(struct parsed_partitions *state) { char* partition_name = NULL; gpt_header *gpt = NULL; gpt_entry *ptes = NULL; u32 i; unsigned ssz = bdev_logical_block_size(state->bdev) / 512; partition_name = kzalloc(sizeof(ptes->partition_name), GFP_KERNEL); if (!partition_name) return 0; if (!find_valid_gpt(state, &gpt, &ptes) || !gpt || !ptes) { kfree(gpt); kfree(ptes); kfree(partition_name); return 0; } pr_debug("GUID Partition Table is valid! Yea!\n"); proc_create("emmc", 0666, NULL, &emmc_partition_fops); gpt_info.num_of_partitions = le32_to_cpu(gpt->num_partition_entries); gpt_info.erase_size = bdev_erase_size(state->bdev) * ssz; /* * Not certain if there is a chance this function is called again with * a different GPT. In case there is, free previously allocated memory */ kfree(gpt_info.partitions); gpt_info.partitions = kzalloc(gpt_info.num_of_partitions * sizeof(*gpt_info.partitions), GFP_KERNEL); for (i = 0; i < le32_to_cpu(gpt->num_partition_entries) && i < state->limit-1; i++) { int partition_name_len; struct partition_meta_info *info; unsigned label_count = 0; unsigned label_max; u64 start = le64_to_cpu(ptes[i].starting_lba); u64 size = le64_to_cpu(ptes[i].ending_lba) - le64_to_cpu(ptes[i].starting_lba) + 1ULL; gpt_info.partitions[i].size = size * ssz; if (!is_pte_valid(&ptes[i], last_lba(state->bdev))) continue; partition_name_len = utf16s_to_utf8s(ptes[i].partition_name, sizeof(ptes[i].partition_name), UTF16_LITTLE_ENDIAN, partition_name, sizeof(ptes[i].partition_name)); #ifdef CONFIG_APANIC_ON_MMC if(strncmp(partition_name,CONFIG_APANIC_PLABEL,partition_name_len) == 0) { apanic_partition_start = start * ssz; apanic_partition_size = size * ssz; pr_debug("apanic partition found starts at %lu \r\n", apanic_partition_start); pr_debug("apanic partition size = %lu\n", apanic_partition_size); } #endif put_partition(state, i+1, start * ssz, size * ssz); /* If this is a RAID volume, tell md */ if (!efi_guidcmp(ptes[i].partition_type_guid, PARTITION_LINUX_RAID_GUID)) state->parts[i + 1].flags = ADDPART_FLAG_RAID; info = &state->parts[i + 1].info; efi_guid_unparse(&ptes[i].unique_partition_guid, info->uuid); /* Naively convert UTF16-LE to 7 bits. */ label_max = min(sizeof(info->volname) - 1, sizeof(ptes[i].partition_name)); info->volname[label_max] = 0; while (label_count < label_max) { u8 c = ptes[i].partition_name[label_count] & 0xff; if (c && !isprint(c)) c = '!'; info->volname[label_count] = c; if (label_count <= partition_name_len) gpt_info.partitions[i].volname[label_count] = c; label_count++; } state->parts[i + 1].has_info = true; #ifdef CONFIG_APANIC_ON_MMC if(strncmp(info->volname,CONFIG_APANIC_PLABEL,label_count) == 0) { apanic_partition_start = start * ssz; pr_debug("apanic partition found starts at %lu \r\n", apanic_partition_start); } #endif } kfree(ptes); kfree(gpt); kfree(partition_name); strlcat(state->pp_buf, "\n", PAGE_SIZE); return 1; }
/** * efi_partition(struct parsed_partitions *state, struct block_device *bdev) * @state * @bdev * * Description: called from check.c, if the disk contains GPT * partitions, sets up partition entries in the kernel. * * If the first block on the disk is a legacy MBR, * it will get handled by msdos_partition(). * If it's a Protective MBR, we'll handle it here. * * We do not create a Linux partition for GPT, but * only for the actual data partitions. * Returns: * -1 if unable to read the partition table * 0 if this isn't our partition table * 1 if successful * */ int efi_partition(struct parsed_partitions *state, struct block_device *bdev) { gpt_header *gpt = NULL; gpt_entry *ptes = NULL; u32 i; unsigned ssz = bdev_logical_block_size(bdev) / 512; u8 unparsed_guid[37]; if (!find_valid_gpt(bdev, &gpt, &ptes) || !gpt || !ptes) { kfree(gpt); kfree(ptes); return 0; } pr_debug("GUID Partition Table is valid! Yea!\n"); for (i = 0; i < le32_to_cpu(gpt->num_partition_entries) && i < state->limit-1; i++) { struct partition_meta_info *info; unsigned label_count = 0; unsigned label_max; u64 start = le64_to_cpu(ptes[i].starting_lba); u64 size = le64_to_cpu(ptes[i].ending_lba) - le64_to_cpu(ptes[i].starting_lba) + 1ULL; if (!is_pte_valid(&ptes[i], last_lba(bdev))) continue; put_partition(state, i+1, start * ssz, size * ssz); /* If this is a RAID volume, tell md */ if (!efi_guidcmp(ptes[i].partition_type_guid, PARTITION_LINUX_RAID_GUID)) state->parts[i+1].flags = 1; info = &state->parts[i + 1].info; /* The EFI specification diverges from RFC 4122 with respect to * the packed storage of its UUIDs. efi_guid_unparse unpacks to * a common ASCII representation, which allows part_pack_uuid to * pack it in the standard big endian layout for use by the rest * of the kernel. */ efi_guid_unparse(&ptes[i].unique_partition_guid, unparsed_guid); part_pack_uuid(unparsed_guid, info->uuid); /* Naively convert UTF16-LE to 7 bits. */ label_max = min(sizeof(info->volname) - 1, sizeof(ptes[i].partition_name)); info->volname[label_max] = 0; while (label_count < label_max) { u8 c = ptes[i].partition_name[label_count] & 0xff; if (c && !isprint(c)) c = '!'; info->volname[label_count] = c; label_count++; } state->parts[i + 1].has_info = true; } kfree(ptes); kfree(gpt); printk("\n"); return 1; }