示例#1
0
static int
unparse_media_hard_drive_path(char *buffer, EFI_DEVICE_PATH *path)
{
	HARDDRIVE_DEVICE_PATH *hd = (HARDDRIVE_DEVICE_PATH *)path;
	char text_uuid[40], *sig=text_uuid;
	char a[16], b[16], c[16];
	
	switch (hd->signature_type) {
	case 0x00:
		sprintf(sig, "None");
		break;
	case 0x01:
		sprintf(sig, "%08x", *(uint32_t *)memcpy(a, &hd->signature,
							 sizeof(hd->signature)));
		break;
	case 0x02: /* GPT */
                efi_guid_unparse((efi_guid_t *)hd->signature, sig);
		break;
	default:
		break;
	}

	return sprintf(buffer, "HD(%x,%" PRIx64 ",%" PRIx64 ",%s)",
		       get(a, hd->part_num),
		       get(b, hd->start),
		       get(c, hd->size),
		       sig);
}
示例#2
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;
}
示例#3
0
static void
fill_bootvar_name(char *dest, size_t len, const char *name)
{
    efi_guid_t guid = EFI_GLOBAL_VARIABLE;
    char text_uuid[40];
    efi_guid_unparse(&guid, text_uuid);
    snprintf(dest, len, "%s-%s", name, text_uuid);
}
示例#4
0
static int
unparse_vendor_path(char *buffer, VENDOR_DEVICE_PATH *path)
{
	char text_guid[40], *p = buffer;
	unsigned char *q = (uint8_t *)path + 20;
	efi_guid_unparse(&path->vendor_guid, text_guid);
	p += sprintf(p, "Vendor(%s,", text_guid);
	p += unparse_raw(p, q, path->length - 20);
	p += sprintf(p, ")");
	return p - buffer;
}
示例#5
0
static ssize_t
efivar_guid_read(struct efivar_entry *entry, char *buf)
{
	struct efi_variable *var = &entry->var;
	char *str = buf;

	if (!entry || !buf)
		return 0;

	efi_guid_unparse(&var->VendorGuid, str);
	str += strlen(str);
	str += sprintf(str, "\n");

	return str - buf;
}
示例#6
0
/**
 * efivar_create_sysfs_entry - create a new entry in sysfs
 * @new_var: efivar entry to create
 *
 * Returns 1 on failure, 0 on success
 */
static int
efivar_create_sysfs_entry(struct efivar_entry *new_var)
{
	int i, short_name_size;
	char *short_name;
	unsigned long variable_name_size;
	efi_char16_t *variable_name;

	variable_name = new_var->var.VariableName;
	variable_name_size = ucs2_strlen(variable_name) * sizeof(efi_char16_t);

	/*
	 * Length of the variable bytes in ASCII, plus the '-' separator,
	 * plus the GUID, plus trailing NUL
	 */
	short_name_size = variable_name_size / sizeof(efi_char16_t)
				+ 1 + EFI_VARIABLE_GUID_LEN + 1;

	short_name = kzalloc(short_name_size, GFP_KERNEL);

	if (!short_name)
		return 1;

	/* Convert Unicode to normal chars (assume top bits are 0),
	   ala UTF-8 */
	for (i=0; i < (int)(variable_name_size / sizeof(efi_char16_t)); i++) {
		short_name[i] = variable_name[i] & 0xFF;
	}
	/* This is ugly, but necessary to separate one vendor's
	   private variables from another's.         */

	*(short_name + strlen(short_name)) = '-';
	efi_guid_unparse(&new_var->var.VendorGuid,
			 short_name + strlen(short_name));

	new_var->kobj.kset = efivars_kset;

	i = kobject_init_and_add(&new_var->kobj, &efivar_ktype,
				   NULL, "%s", short_name);
	kfree(short_name);
	if (i)
		return 1;

	kobject_uevent(&new_var->kobj, KOBJ_ADD);
	efivar_entry_add(new_var, &efivar_sysfs_list);

	return 0;
}
示例#7
0
static int
unparse_media_path(char *buffer, EFI_DEVICE_PATH *path)
{

	CDROM_DEVICE_PATH *cdrom = (CDROM_DEVICE_PATH *)path;
	MEDIA_PROTOCOL_DEVICE_PATH *media = (MEDIA_PROTOCOL_DEVICE_PATH *)path;
	FILE_PATH_DEVICE_PATH *file = (FILE_PATH_DEVICE_PATH *)path;
	char text_guid[40], *p = buffer;
	char file_name[80];
	memset(file_name, 0, sizeof(file_name));
	char a[16], b[16], c[16];

	switch (path->subtype) {
	case 1:
		return unparse_media_hard_drive_path(buffer, path);
		break;
	case 2:
		return sprintf(buffer, "CD-ROM(%x,%" PRIx64 ",%" PRIx64 ")",
			       get(a, cdrom->boot_entry), get(b, cdrom->start), get(c, cdrom->size));
		break;
	case 3:
		return unparse_vendor_path(buffer, (VENDOR_DEVICE_PATH *)path);
		break;
	case 4:
		efichar_to_char(file_name, file->path_name, 80);
		return sprintf(p, "File(%s)", file_name);
		break;
	case 5:
		efi_guid_unparse(&media->guid, text_guid);
		return sprintf(buffer, "Media(%s)", text_guid);
		break;
	default:
		break;
	}
	return 0;
}
示例#8
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;
}
示例#9
0
static int efivarfs_callback(efi_char16_t *name16, efi_guid_t vendor,
			     unsigned long name_size, void *data)
{
	struct super_block *sb = (struct super_block *)data;
	struct efivar_entry *entry;
	struct inode *inode = NULL;
	struct dentry *dentry, *root = sb->s_root;
	unsigned long size = 0;
	char *name;
	int len;
	int err = -ENOMEM;
	bool is_removable = false;

	entry = kmalloc(sizeof(*entry), GFP_KERNEL);
	if (!entry)
		return err;

	memcpy(entry->var.VariableName, name16, name_size);
	memcpy(&(entry->var.VendorGuid), &vendor, sizeof(efi_guid_t));

	len = ucs2_utf8size(entry->var.VariableName);

	/* name, plus '-', plus GUID, plus NUL*/
	name = kmalloc(len + 1 + EFI_VARIABLE_GUID_LEN + 1, GFP_KERNEL);
	if (!name)
		goto fail;

	ucs2_as_utf8(name, entry->var.VariableName, len);

	if (efivar_variable_is_removable(entry->var.VendorGuid, name, len))
		is_removable = true;

	name[len] = '-';

	efi_guid_unparse(&entry->var.VendorGuid, name + len + 1);

	name[len + EFI_VARIABLE_GUID_LEN+1] = '\0';

	inode = efivarfs_get_inode(sb, root->d_inode, S_IFREG | 0644, 0,
				   is_removable);
	if (!inode)
		goto fail_name;

	dentry = efivarfs_alloc_dentry(root, name);
	if (IS_ERR(dentry)) {
		err = PTR_ERR(dentry);
		goto fail_inode;
	}

	/* copied by the above to local storage in the dentry. */
	kfree(name);

	efivar_entry_size(entry, &size);
	efivar_entry_add(entry, &efivarfs_list);

	mutex_lock(&inode->i_mutex);
	inode->i_private = entry;
	i_size_write(inode, size + sizeof(entry->var.Attributes));
	mutex_unlock(&inode->i_mutex);
	d_add(dentry, inode);

	return 0;

fail_inode:
	iput(inode);
fail_name:
	kfree(name);
fail:
	kfree(entry);
	return err;
}
/**
 * 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;
}
示例#11
0
/**
 * 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;
}