コード例 #1
0
ファイル: efi.c プロジェクト: 274914765/C
/**
 * 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;
}
コード例 #2
0
ファイル: efi.c プロジェクト: zhangyongsu/linux-kernel-source
/**
 * 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;
}
コード例 #3
0
/**
 * read_lba(): Read bytes from disk, starting at given LBA
 * @state
 * @lba
 * @buffer
 * @size_t
 *
 * Description: Reads @count bytes from @state->bdev into @buffer.
 * Returns number of bytes read on success, 0 on error.
 */
static size_t read_lba(struct parsed_partitions *state,
		       u64 lba, u8 *buffer, size_t count)
{
	size_t totalreadcount = 0;
	struct block_device *bdev = state->bdev;
	sector_t n = lba * (bdev_logical_block_size(bdev) / 512);

	if (!buffer || lba > last_lba(bdev))
                return 0;

	while (count) {
		int copied = 512;
		Sector sect;
		unsigned char *data = read_part_sector(state, n++, &sect);
		if (!data)
			break;
		if (copied > count)
			copied = count;
		memcpy(buffer, data, copied);
		put_dev_sector(sect);
		buffer += copied;
		totalreadcount +=copied;
		count -= copied;
	}
	return totalreadcount;
}
コード例 #4
0
ファイル: gpt.c プロジェクト: unakatsuo/multipath-tools
static ssize_t
read_lba(int fd, uint64_t lba, void *buffer, size_t bytes)
{
	int sector_size = get_sector_size(fd);
	off_t offset = lba * sector_size;
	uint64_t lastlba;
        ssize_t bytesread;

	lseek(fd, offset, SEEK_SET);
	bytesread = read(fd, buffer, bytes);

	lastlba = last_lba(fd);
	if (!lastlba)
		return bytesread;

        /* Kludge.  This is necessary to read/write the last
           block of an odd-sized disk, until Linux 2.5.x kernel fixes.
           This is only used by gpt.c, and only to read
           one sector, so we don't have to be fancy.
        */
        if (!bytesread && !(lastlba & 1) && lba == lastlba) {
                bytesread = read_lastoddsector(fd, lba, buffer, bytes);
        }
        return bytesread;
}
コード例 #5
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;
}
コード例 #6
0
ファイル: gpt.c プロジェクト: btian1/efivar
static ssize_t
read_lba(int fd, uint64_t lba, void *buffer, size_t bytes)
{
	int sector_size = get_sector_size(fd);
	off_t offset = lba * sector_size;
	ssize_t bytesread;
	void *iobuf;
	size_t iobuf_size;
	int rc;
	off_t new_offset;

	iobuf_size = lcm(bytes, sector_size);
	rc = posix_memalign(&iobuf, sector_size, iobuf_size);
	if (rc)
		return rc;
	memset(iobuf, 0, bytes);

	new_offset = lseek(fd, offset, SEEK_SET);
	if (new_offset == (off_t)-1) {
		free(iobuf);
		return 0;
	}
	bytesread = read(fd, iobuf, iobuf_size);
	memcpy(buffer, iobuf, bytes);
	free(iobuf);

	/* Kludge.  This is necessary to read/write the last
	   block of an odd-sized disk, until Linux 2.5.x kernel fixes.
	   This is only used by gpt.c, and only to read
	   one sector, so we don't have to be fancy.
	*/
	if (!bytesread && !(last_lba(fd) & 1) && lba == last_lba(fd)) {
		bytesread = read_lastoddsector(fd, lba, buffer, bytes);
	}
	return bytesread;
}
コード例 #7
0
ファイル: efi.c プロジェクト: AdiPat/android_kernel_tegra_n1
/**
 * 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;
}
コード例 #8
0
ファイル: efi.c プロジェクト: OpenHMR/Open-HMR600
/**
 * 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;
}
コード例 #9
0
ファイル: efi.c プロジェクト: 274914765/C
/**
 * read_lba(): Read bytes from disk, starting at given LBA
 * @bdev
 * @lba
 * @buffer
 * @size_t
 *
 * Description:  Reads @count bytes from @bdev into @buffer.
 * Returns number of bytes read on success, 0 on error.
 */
static size_t
read_lba(struct block_device *bdev, u64 lba, u8 * buffer, size_t count)
{
    size_t totalreadcount = 0;

    if (!bdev || !buffer || lba > last_lba(bdev))
                return 0;

    while (count) {
        int copied = 512;
        Sector sect;
        unsigned char *data = read_dev_sector(bdev, lba++, &sect);
        if (!data)
            break;
        if (copied > count)
            copied = count;
        memcpy(buffer, data, copied);
        put_dev_sector(sect);
        buffer += copied;
        totalreadcount +=copied;
        count -= copied;
    }
    return totalreadcount;
}
コード例 #10
0
/**
 * 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 (!force_gpt) {
                /* 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);
			// panic before kfree to check the buffer content
			if (!good_pmbr && !memcmp(state->pp_buf, " mmcblk0", 8))
				BUG_ON(1);
                        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:
	// panic before kfree to check the buffer content
	if (!memcmp(state->pp_buf, " mmcblk0", 8))
		BUG_ON(1);
        kfree(pgpt);
        kfree(agpt);
        kfree(pptes);
        kfree(aptes);
        *gpt = NULL;
        *ptes = NULL;
        return 0;
}
コード例 #11
0
/**
 * 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;
}
コード例 #12
0
ファイル: gpt.c プロジェクト: btian1/efivar
/**
 * find_valid_gpt() - Search disk for valid GPT headers and PTEs
 * @fd  is an open file descriptor to the whole disk
 * @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 finding either the Primary GPT header and PTEs valid,
 * or the Alternate GPT header and PTEs valid, and the PMBR valid.
 */
static int
find_valid_gpt(int fd, gpt_header ** gpt, gpt_entry ** ptes,
	       int ignore_pmbr_err)
{
	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 = NULL;
	uint64_t lastlba;
	int ret = -1;

	errno = EINVAL;

	if (!gpt || !ptes)
		return -1;

	lastlba = last_lba(fd);
	good_pgpt = is_gpt_valid(fd, GPT_PRIMARY_PARTITION_TABLE_LBA,
				 &pgpt, &pptes);
	if (good_pgpt) {
		good_agpt = is_gpt_valid(fd,
					 __le64_to_cpu(pgpt->alternate_lba),
					 &agpt, &aptes);
		if (!good_agpt) {
			good_agpt = is_gpt_valid(fd, lastlba, &agpt, &aptes);
		}
	} else {
		good_agpt = is_gpt_valid(fd, lastlba, &agpt, &aptes);
	}

	/* The obviously unsuccessful case */
	if (!good_pgpt && !good_agpt) {
		goto fail;
	}

	/* This will be added to the EFI Spec. per Intel after v1.02. */
	legacymbr = malloc(sizeof (*legacymbr));
	if (legacymbr) {
		memset(legacymbr, 0, sizeof (*legacymbr));
		read_lba(fd, 0, (uint8_t *) legacymbr, sizeof (*legacymbr));
		good_pmbr = is_pmbr_valid(legacymbr);
		free(legacymbr);
		legacymbr=NULL;
	}

	/* Failure due to bad PMBR */
	if ((good_pgpt || good_agpt) && !good_pmbr && !ignore_pmbr_err) {
		if (report_errors)
			fprintf(stderr,
			      "Primary GPT is invalid, using alternate GPT.\n");
		goto fail;
	}

	/* Would fail due to bad PMBR, but force GPT anyhow */
	if ((good_pgpt || good_agpt) && !good_pmbr && ignore_pmbr_err &&
	    report_errors) {
		fprintf(stderr,
		 "  Warning: Disk has a valid GPT signature but invalid PMBR.\n"
		 "  Use GNU Parted to correct disk.\n"
		 "  gpt option taken, disk treated as GPT.\n");
	}

	compare_gpts(pgpt, agpt, lastlba);

	/* The good cases */
	if (good_pgpt && (good_pmbr || ignore_pmbr_err)) {
		*gpt  = pgpt;
		*ptes = pptes;
	} else if (good_agpt && (good_pmbr || ignore_pmbr_err)) {
		*gpt  = agpt;
		*ptes = aptes;
	}

	ret = 0;
	errno = 0;
 fail:
	if (pgpt && (pgpt != *gpt || ret < 0)) {
		free(pgpt);
		pgpt=NULL;
	}
	if (pptes && (pptes != *ptes || ret < 0)) {
		free(pptes);
		pptes=NULL;
	}
	if (agpt && (agpt != *gpt || ret < 0)) {
		free(agpt);
		agpt=NULL;
	}
	if (aptes && (aptes != *ptes || ret < 0)) {
		free(aptes);
		aptes=NULL;
	}
	if (ret < 0) {
		*gpt = NULL;
		*ptes = NULL;
	}
	return ret;
}
コード例 #13
0
ファイル: efi.c プロジェクト: ArthySundaram/firstrepo
/**
 * 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;
}
コード例 #14
0
ファイル: efi.c プロジェクト: 274914765/C
/**
 * find_valid_gpt() - Search disk for valid GPT headers and PTEs
 * @bdev
 * @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 block_device *bdev, 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 (!bdev || !gpt || !ptes)
        return 0;

    lastlba = last_lba(bdev);
        if (!force_gpt) {
                /* This will be added to the EFI Spec. per Intel after v1.02. */
                legacymbr = kzalloc(sizeof (*legacymbr), GFP_KERNEL);
                if (legacymbr) {
                        read_lba(bdev, 0, (u8 *) legacymbr,
                                 sizeof (*legacymbr));
                        good_pmbr = is_pmbr_valid(legacymbr);
                        kfree(legacymbr);
                }
                if (!good_pmbr)
                        goto fail;
        }

    good_pgpt = is_gpt_valid(bdev, GPT_PRIMARY_PARTITION_TABLE_LBA,
                 &pgpt, &pptes);
        if (good_pgpt)
        good_agpt = is_gpt_valid(bdev,
                     le64_to_cpu(pgpt->alternate_lba),
                     &agpt, &aptes);
        if (!good_agpt && force_gpt)
                good_agpt = is_gpt_valid(bdev, 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;
}
コード例 #15
0
ファイル: efi.c プロジェクト: 274914765/C
/**
 * 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;
}
コード例 #16
0
ファイル: gpt.c プロジェクト: Claruarius/stblinux-2.6.37
/**
 * find_valid_gpt() - Search disk for valid GPT headers and PTEs
 * @fd  is an open file descriptor to the whole disk
 * @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 finding either the Primary GPT header and PTEs valid,
 * or the Alternate GPT header and PTEs valid, and the PMBR valid.
 */
static int
find_valid_gpt(int fd, gpt_header ** gpt, gpt_entry ** ptes)
{
        extern int force_gpt;
	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 = NULL;
	uint64_t lastlba;
	if (!gpt || !ptes)
		return 0;

	lastlba = last_lba(fd);
	good_pgpt = is_gpt_valid(fd, GPT_PRIMARY_PARTITION_TABLE_LBA,
				 &pgpt, &pptes);
        if (good_pgpt) {
		good_agpt = is_gpt_valid(fd,
                                         __le64_to_cpu(pgpt->alternate_lba),
					 &agpt, &aptes);
                if (!good_agpt) {
                        good_agpt = is_gpt_valid(fd, lastlba,
                                                 &agpt, &aptes);
                }
        }
        else {
                good_agpt = is_gpt_valid(fd, lastlba,
                                         &agpt, &aptes);
        }

        /* The obviously unsuccessful case */
        if (!good_pgpt && !good_agpt) {
                goto fail;
        }

	/* This will be added to the EFI Spec. per Intel after v1.02. */
        legacymbr = malloc(sizeof (*legacymbr));
        if (legacymbr) {
                memset(legacymbr, 0, sizeof (*legacymbr));
                read_lba(fd, 0, (uint8_t *) legacymbr,
                         sizeof (*legacymbr));
                good_pmbr = is_pmbr_valid(legacymbr);
                free(legacymbr);
                legacymbr=NULL;
        }

        /* Failure due to bad PMBR */
        if ((good_pgpt || good_agpt) && !good_pmbr && !force_gpt) {
                fprintf(stderr,
                       "  Warning: Disk has a valid GPT signature "
                       "but invalid PMBR.\n"
                       "  Assuming this disk is *not* a GPT disk anymore.\n"
                       "  Use gpt kernel option to override.  "
                       "Use GNU Parted to correct disk.\n");
                goto fail;
        }

        /* Would fail due to bad PMBR, but force GPT anyhow */
        if ((good_pgpt || good_agpt) && !good_pmbr && force_gpt) {
                fprintf(stderr, 
                       "  Warning: Disk has a valid GPT signature but "
                       "invalid PMBR.\n"
                       "  Use GNU Parted to correct disk.\n"
                       "  gpt option taken, disk treated as GPT.\n");
        }

        compare_gpts(pgpt, agpt, lastlba);

        /* The good cases */
        if (good_pgpt && (good_pmbr || force_gpt)) {
                *gpt  = pgpt;
                *ptes = pptes;
                if (agpt)  { free(agpt);   agpt = NULL; }
                if (aptes) { free(aptes); aptes = NULL; }
                if (!good_agpt) {
                        fprintf(stderr, 
			       "Alternate GPT is invalid, "
                               "using primary GPT.\n");
                }
                return 1;
        }
        else if (good_agpt && (good_pmbr || force_gpt)) {
                *gpt  = agpt;
                *ptes = aptes;
                if (pgpt)  { free(pgpt);   pgpt = NULL; }
                if (pptes) { free(pptes); pptes = NULL; }
                fprintf(stderr, 
                       "Primary GPT is invalid, using alternate GPT.\n");
                return 1;
        }

 fail:
        if (pgpt)  { free(pgpt);   pgpt=NULL; }
        if (agpt)  { free(agpt);   agpt=NULL; }
        if (pptes) { free(pptes); pptes=NULL; }
        if (aptes) { free(aptes); aptes=NULL; }
        *gpt = NULL;
        *ptes = NULL;
        return 0;
}
コード例 #17
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)
{
	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;
}
コード例 #18
0
/**
 * 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;
}
コード例 #19
0
ファイル: efi.c プロジェクト: abhishekr700/Nemesis_Kernel
/**
 * 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;

	char *blk_name = NULL;
	blk_name = ((state->bdev)->bd_disk)->disk_name;
	printk(KERN_NOTICE "%s: %s", __func__, blk_name);

	if (!ptes)
		return 0;

	lastlba = last_lba(state->bdev);

        if ((!force_gpt) || (!strcmp(blk_name, "mmcblk1"))) {
                /* 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;
}