/**
 * 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++) {
		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;
		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;
			label_count++;
		}
		state->parts[i + 1].has_info = true;
	}
	kfree(ptes);
	kfree(gpt);
	strlcat(state->pp_buf, "\n", PAGE_SIZE);
	return 1;
}
Example #2
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_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;
}
/*
 * We allow each variable to be edited via rewriting the
 * entire efi variable structure.
 */
static ssize_t
efivar_store_raw(struct efivar_entry *entry, const char *buf, size_t count)
{
	struct efi_variable *new_var, *var = &entry->var;
	struct efivars *efivars = entry->efivars;
	efi_status_t status = EFI_NOT_FOUND;

	if (count != sizeof(struct efi_variable))
		return -EINVAL;

	new_var = (struct efi_variable *)buf;
	/*
	 * If only updating the variable data, then the name
	 * and guid should remain the same
	 */
	if (memcmp(new_var->VariableName, var->VariableName, sizeof(var->VariableName)) ||
		efi_guidcmp(new_var->VendorGuid, var->VendorGuid)) {
		printk(KERN_ERR "efivars: Cannot edit the wrong variable!\n");
		return -EINVAL;
	}

	if ((new_var->DataSize <= 0) || (new_var->Attributes == 0)){
		printk(KERN_ERR "efivars: DataSize & Attributes must be valid!\n");
		return -EINVAL;
	}

	if ((new_var->Attributes & ~EFI_VARIABLE_MASK) != 0 ||
	    validate_var(new_var, new_var->Data, new_var->DataSize) == false) {
		printk(KERN_ERR "efivars: Malformed variable content\n");
		return -EINVAL;
	}

	spin_lock(&efivars->lock);
	status = efivars->ops->set_variable(new_var->VariableName,
					    &new_var->VendorGuid,
					    new_var->Attributes,
					    new_var->DataSize,
					    new_var->Data);

	spin_unlock(&efivars->lock);

	if (status != EFI_SUCCESS) {
		printk(KERN_WARNING "efivars: set_variable() failed: status=%lx\n",
			status);
		return -EIO;
	}

	memcpy(&entry->var, new_var, count);
	return count;
}
Example #4
0
static int efi_pstore_read_func(struct efivar_entry *entry, void *data)
{
	efi_guid_t vendor = LINUX_EFI_CRASH_GUID;
	struct pstore_read_data *cb_data = data;
	char name[DUMP_NAME_LEN];
	int i;
	int cnt;
	unsigned int part;
	unsigned long time, size;

	if (efi_guidcmp(entry->var.VendorGuid, vendor))
		return 0;

	for (i = 0; i < DUMP_NAME_LEN; i++)
		name[i] = entry->var.VariableName[i];

	if (sscanf(name, "dump-type%u-%u-%d-%lu",
		   cb_data->type, &part, &cnt, &time) == 4) {
		*cb_data->id = generic_id(time, part, cnt);
		*cb_data->count = cnt;
		cb_data->timespec->tv_sec = time;
		cb_data->timespec->tv_nsec = 0;
	} else if (sscanf(name, "dump-type%u-%u-%lu",
			  cb_data->type, &part, &time) == 3) {
		/*
		 * Check if an old format,
		 * which doesn't support holding
		 * multiple logs, remains.
		 */
		*cb_data->id = generic_id(time, part, 0);
		*cb_data->count = 0;
		cb_data->timespec->tv_sec = time;
		cb_data->timespec->tv_nsec = 0;
	} else
		return 0;

	entry->var.DataSize = 1024;
	__efivar_entry_get(entry, &entry->var.Attributes,
			   &entry->var.DataSize, entry->var.Data);
	size = entry->var.DataSize;

	*cb_data->buf = kmalloc(size, GFP_KERNEL);
	if (*cb_data->buf == NULL)
		return -ENOMEM;
	memcpy(*cb_data->buf, entry->var.Data, size);
	return size;
}
/*
 * A number of config table entries get remapped to virtual addresses
 * after entering EFI virtual mode. However, the kexec kernel requires
 * their physical addresses therefore we pass them via setup_data and
 * correct those entries to their respective physical addresses here.
 *
 * Currently only handles smbios which is necessary for some firmware
 * implementation.
 */
int __init efi_reuse_config(u64 tables, int nr_tables)
{
	int i, sz, ret = 0;
	void *p, *tablep;
	struct efi_setup_data *data;

	if (!efi_setup)
		return 0;

	if (!efi_enabled(EFI_64BIT))
		return 0;

	data = early_memremap(efi_setup, sizeof(*data));
	if (!data) {
		ret = -ENOMEM;
		goto out;
	}

	if (!data->smbios)
		goto out_memremap;

	sz = sizeof(efi_config_table_64_t);

	p = tablep = early_memremap(tables, nr_tables * sz);
	if (!p) {
		pr_err("Could not map Configuration table!\n");
		ret = -ENOMEM;
		goto out_memremap;
	}

	for (i = 0; i < efi.systab->nr_tables; i++) {
		efi_guid_t guid;

		guid = ((efi_config_table_64_t *)p)->guid;

		if (!efi_guidcmp(guid, SMBIOS_TABLE_GUID))
			((efi_config_table_64_t *)p)->table = data->smbios;
		p += sz;
	}
	early_memunmap(tablep, nr_tables * sz);

out_memremap:
	early_memunmap(data, sizeof(*data));
out:
	return ret;
}
Example #6
0
void *get_fdt(efi_system_table_t *sys_table)
{
	efi_guid_t fdt_guid = DEVICE_TREE_GUID;
	efi_config_table_t *tables;
	void *fdt;
	int i;

	tables = (efi_config_table_t *) sys_table->tables;
	fdt = NULL;

	for (i = 0; i < sys_table->nr_tables; i++)
		if (efi_guidcmp(tables[i].guid, fdt_guid) == 0) {
			fdt = (void *) tables[i].table;
			break;
	 }

	return fdt;
}
Example #7
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;

	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;
}
Example #8
0
static bool variable_is_present(efi_char16_t *variable_name, efi_guid_t *vendor,
				struct list_head *head)
{
	struct efivar_entry *entry, *n;
	unsigned long strsize1, strsize2;
	bool found = false;

	strsize1 = ucs2_strsize(variable_name, 1024);
	list_for_each_entry_safe(entry, n, head, list) {
		strsize2 = ucs2_strsize(entry->var.VariableName, 1024);
		if (strsize1 == strsize2 &&
			!memcmp(variable_name, &(entry->var.VariableName),
				strsize2) &&
			!efi_guidcmp(entry->var.VendorGuid,
				*vendor)) {
			found = true;
			break;
		}
	}
Example #9
0
/*
 * We allow each variable to be edited via rewriting the
 * entire efi variable structure.
 */
static ssize_t
efivar_store_raw(struct efivar_entry *entry, const char *buf, size_t count)
{
	struct efi_variable *new_var, *var = &entry->var;
	int err;

	if (count != sizeof(struct efi_variable))
		return -EINVAL;

	new_var = (struct efi_variable *)buf;
	/*
	 * If only updating the variable data, then the name
	 * and guid should remain the same
	 */
	if (memcmp(new_var->VariableName, var->VariableName, sizeof(var->VariableName)) ||
		efi_guidcmp(new_var->VendorGuid, var->VendorGuid)) {
		printk(KERN_ERR "efivars: Cannot edit the wrong variable!\n");
		return -EINVAL;
	}

	if ((new_var->DataSize <= 0) || (new_var->Attributes == 0)){
		printk(KERN_ERR "efivars: DataSize & Attributes must be valid!\n");
		return -EINVAL;
	}

	if ((new_var->Attributes & ~EFI_VARIABLE_MASK) != 0 ||
	    efivar_validate(new_var, new_var->Data, new_var->DataSize) == false) {
		printk(KERN_ERR "efivars: Malformed variable content\n");
		return -EINVAL;
	}

	memcpy(&entry->var, new_var, count);

	err = efivar_entry_set(entry, new_var->Attributes,
			       new_var->DataSize, new_var->Data, false);
	if (err) {
		printk(KERN_WARNING "efivars: set_variable() failed: status=%d\n", err);
		return -EIO;
	}

	return count;
}
Example #10
0
void __init early_sn_setup(void)
{
	efi_system_table_t *efi_systab;
	efi_config_table_t *config_tables;
	struct ia64_sal_systab *sal_systab;
	struct ia64_sal_desc_entry_point *ep;
	char *p;
	int i, j;

	/*
	 * Parse enough of the SAL tables to locate the SAL entry point. Since, console
	 * IO on SN2 is done via SAL calls, early_printk won't work without this.
	 *
	 * This code duplicates some of the ACPI table parsing that is in efi.c & sal.c.
	 * Any changes to those file may have to be made hereas well.
	 */
	efi_systab = (efi_system_table_t *) __va(ia64_boot_param->efi_systab);
	config_tables = __va(efi_systab->tables);
	for (i = 0; i < efi_systab->nr_tables; i++) {
		if (efi_guidcmp(config_tables[i].guid, SAL_SYSTEM_TABLE_GUID) ==
		    0) {
			sal_systab = __va(config_tables[i].table);
			p = (char *)(sal_systab + 1);
			for (j = 0; j < sal_systab->entry_count; j++) {
				if (*p == SAL_DESC_ENTRY_POINT) {
					ep = (struct ia64_sal_desc_entry_point
					      *)p;
					ia64_sal_handler_init(__va
							      (ep->sal_proc),
							      __va(ep->gp));
					return;
				}
				p += SAL_DESC_SIZE(*p);
			}
		}
	}
	/* Uh-oh, SAL not available?? */
	printk(KERN_ERR "failed to find SAL entry point\n");
}
Example #11
0
unsigned long
hcdp_early_uart (void)
{
	efi_system_table_t *systab;
	efi_config_table_t *config_tables;
	unsigned long addr = 0;
	hcdp_t *hcdp = 0;
	hcdp_dev_t *dev;
	int i;

	systab = (efi_system_table_t *) ia64_boot_param->efi_systab;
	if (!systab)
		return 0;
	systab = __va(systab);

	config_tables = (efi_config_table_t *) systab->tables;
	if (!config_tables)
		return 0;
	config_tables = __va(config_tables);

	for (i = 0; i < systab->nr_tables; i++) {
		if (efi_guidcmp(config_tables[i].guid, HCDP_TABLE_GUID) == 0) {
			hcdp = (hcdp_t *) config_tables[i].table;
			break;
		}
	}
	if (!hcdp)
		return 0;
	hcdp = __va(hcdp);

	for (i = 0, dev = hcdp->hcdp_dev; i < hcdp->num_entries; i++, dev++) {
		if (dev->type == HCDP_DEV_CONSOLE) {
			addr = (u64) dev->base_addr.addrhi << 32 | dev->base_addr.addrlo;
			break;
		}
	}
	return addr;
}
Example #12
0
void *get_fdt(efi_system_table_t *sys_table, unsigned long *fdt_size)
{
	efi_guid_t fdt_guid = DEVICE_TREE_GUID;
	efi_config_table_t *tables;
	void *fdt;
	int i;

	tables = (efi_config_table_t *) sys_table->tables;
	fdt = NULL;

	for (i = 0; i < sys_table->nr_tables; i++)
		if (efi_guidcmp(tables[i].guid, fdt_guid) == 0) {
			fdt = (void *) tables[i].table;
			if (fdt_check_header(fdt) != 0) {
				pr_efi_err(sys_table, "Invalid header detected on UEFI supplied FDT, ignoring ...\n");
				return NULL;
			}
			*fdt_size = fdt_totalsize(fdt);
			break;
	 }

	return fdt;
}
Example #13
0
/**
 * read_gpt_pt() 
 * @fd
 * @all - slice with start/size of whole disk
 *
 *  0 if this isn't our partition table
 *  number of partitions if successful
 *
 */
int
read_gpt_pt (int fd, struct slice all, struct slice *sp, int ns)
{
	gpt_header *gpt = NULL;
	gpt_entry *ptes = NULL;
	uint32_t i;
	int n = 0;
        int last_used_index=-1;
	int sector_size_mul = get_sector_size(fd)/512;

	if (!find_valid_gpt (fd, &gpt, &ptes) || !gpt || !ptes) {
		if (gpt)
			free (gpt);
		if (ptes)
			free (ptes);
		return 0;
	}

	for (i = 0; i < __le32_to_cpu(gpt->num_partition_entries) && i < ns; i++) {
		if (!efi_guidcmp (NULL_GUID, ptes[i].partition_type_guid)) {
			sp[n].start = 0;
			sp[n].size = 0;
			n++;
		} else {
			sp[n].start = sector_size_mul *
				      __le64_to_cpu(ptes[i].starting_lba);
			sp[n].size  = sector_size_mul *
				      (__le64_to_cpu(ptes[i].ending_lba) -
				       __le64_to_cpu(ptes[i].starting_lba) + 1);
                        last_used_index=n;
			n++;
		}
	}
	free (ptes);
	free (gpt);
	return last_used_index+1;
}
Example #14
0
/*
 * Clean up an entry with the same name
 */
static int efi_pstore_erase_func(struct efivar_entry *entry, void *data)
{
	struct pstore_erase_data *ed = data;
	efi_guid_t vendor = LINUX_EFI_CRASH_GUID;
	efi_char16_t efi_name_old[DUMP_NAME_LEN];
	efi_char16_t *efi_name = ed->name;
	unsigned long ucs2_len = ucs2_strlen(ed->name);
	char name_old[DUMP_NAME_LEN];
	int i;

	if (efi_guidcmp(entry->var.VendorGuid, vendor))
		return 0;

	if (ucs2_strncmp(entry->var.VariableName,
			  efi_name, (size_t)ucs2_len)) {
		/*
		 * Check if an old format, which doesn't support
		 * holding multiple logs, remains.
		 */
		sprintf(name_old, "dump-type%u-%u-%lu", ed->type,
			(unsigned int)ed->id, ed->time.tv_sec);

		for (i = 0; i < DUMP_NAME_LEN; i++)
			efi_name_old[i] = name_old[i];

		if (ucs2_strncmp(entry->var.VariableName, efi_name_old,
				  ucs2_strlen(efi_name_old)))
			return 0;
	}

	/* found */
	__efivar_entry_delete(entry);
	list_del(&entry->list);

	return 1;
}
static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type,
			       struct timespec *timespec,
			       char **buf, struct pstore_info *psi)
{
	efi_guid_t vendor = LINUX_EFI_CRASH_GUID;
	struct efivars *efivars = psi->data;
	char name[DUMP_NAME_LEN];
	int i;
	unsigned int part, size;
	unsigned long time;

	while (&efivars->walk_entry->list != &efivars->list) {
		if (!efi_guidcmp(efivars->walk_entry->var.VendorGuid,
				 vendor)) {
			for (i = 0; i < DUMP_NAME_LEN; i++) {
				name[i] = efivars->walk_entry->var.VariableName[i];
			}
			if (sscanf(name, "dump-type%u-%u-%lu", type, &part, &time) == 3) {
				*id = part;
				timespec->tv_sec = time;
				timespec->tv_nsec = 0;
				get_var_data_locked(efivars, &efivars->walk_entry->var);
				size = efivars->walk_entry->var.DataSize;
				*buf = kmalloc(size, GFP_KERNEL);
				if (*buf == NULL)
					return -ENOMEM;
				memcpy(*buf, efivars->walk_entry->var.Data,
				       size);
				efivars->walk_entry = list_entry(efivars->walk_entry->list.next,
					           struct efivar_entry, list);
				return size;
			}
		}
		efivars->walk_entry = list_entry(efivars->walk_entry->list.next,
						 struct efivar_entry, list);
	}
/**
 * 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;
	}

    /* Add static partitions for SOS and LNX if specified in kernel config (Tegra platform) */
    #ifdef CONFIG_TEGRA_BOOTBLOCK_EXPOSE
    printk(KERN_NOTICE "Adding SOS as MMC partition %i: offset %i bytes, size: %i bytes\n", i+1, CONFIG_BOOTBLOCK_EXPOSE_SOS_OFFSET * 512, CONFIG_BOOTBLOCK_EXPOSE_SOS_SIZE * 512);
    put_partition(state, i+1, CONFIG_BOOTBLOCK_EXPOSE_SOS_OFFSET * ssz, CONFIG_BOOTBLOCK_EXPOSE_SOS_SIZE * ssz);
    printk(KERN_NOTICE "Adding LNX as MMC partition %i: offset %i bytes, size: %i bytes\n", i+2, CONFIG_BOOTBLOCK_EXPOSE_LNX_OFFSET * 512, CONFIG_BOOTBLOCK_EXPOSE_LNX_SIZE * 512);
    put_partition(state, i+2, CONFIG_BOOTBLOCK_EXPOSE_LNX_OFFSET * ssz, CONFIG_BOOTBLOCK_EXPOSE_LNX_SIZE * ssz);
    #endif

	kfree(ptes);
	kfree(gpt);
	strlcat(state->pp_buf, "\n", PAGE_SIZE);
	return 1;
}
/**
 * compare_gpts() - Search disk for valid GPT headers and PTEs
 * @pgpt is the primary GPT header
 * @agpt is the alternate GPT header
 * @lastlba is the last LBA number
 * Description: Returns nothing.  Sanity checks pgpt and agpt fields
 * and prints warnings on discrepancies.
 * 
 */
static void
compare_gpts(gpt_header *pgpt, gpt_header *agpt, u64 lastlba)
{
	int error_found = 0;
	if (!pgpt || !agpt)
		return;
	if (le64_to_cpu(pgpt->my_lba) != le64_to_cpu(agpt->alternate_lba)) {
		printk(KERN_WARNING
		       "GPT:Primary header LBA != Alt. header alternate_lba\n");
		printk(KERN_WARNING "GPT:%lld != %lld\n",
		       (unsigned long long)le64_to_cpu(pgpt->my_lba),
                       (unsigned long long)le64_to_cpu(agpt->alternate_lba));
		error_found++;
	}
	if (le64_to_cpu(pgpt->alternate_lba) != le64_to_cpu(agpt->my_lba)) {
		printk(KERN_WARNING
		       "GPT:Primary header alternate_lba != Alt. header my_lba\n");
		printk(KERN_WARNING "GPT:%lld != %lld\n",
		       (unsigned long long)le64_to_cpu(pgpt->alternate_lba),
                       (unsigned long long)le64_to_cpu(agpt->my_lba));
		error_found++;
	}
	if (le64_to_cpu(pgpt->first_usable_lba) !=
            le64_to_cpu(agpt->first_usable_lba)) {
		printk(KERN_WARNING "GPT:first_usable_lbas don't match.\n");
		printk(KERN_WARNING "GPT:%lld != %lld\n",
		       (unsigned long long)le64_to_cpu(pgpt->first_usable_lba),
                       (unsigned long long)le64_to_cpu(agpt->first_usable_lba));
		error_found++;
	}
	if (le64_to_cpu(pgpt->last_usable_lba) !=
            le64_to_cpu(agpt->last_usable_lba)) {
		printk(KERN_WARNING "GPT:last_usable_lbas don't match.\n");
		printk(KERN_WARNING "GPT:%lld != %lld\n",
		       (unsigned long long)le64_to_cpu(pgpt->last_usable_lba),
                       (unsigned long long)le64_to_cpu(agpt->last_usable_lba));
		error_found++;
	}
	if (efi_guidcmp(pgpt->disk_guid, agpt->disk_guid)) {
		printk(KERN_WARNING "GPT:disk_guids don't match.\n");
		error_found++;
	}
	if (le32_to_cpu(pgpt->num_partition_entries) !=
            le32_to_cpu(agpt->num_partition_entries)) {
		printk(KERN_WARNING "GPT:num_partition_entries don't match: "
		       "0x%x != 0x%x\n",
		       le32_to_cpu(pgpt->num_partition_entries),
		       le32_to_cpu(agpt->num_partition_entries));
		error_found++;
	}
	if (le32_to_cpu(pgpt->sizeof_partition_entry) !=
            le32_to_cpu(agpt->sizeof_partition_entry)) {
		printk(KERN_WARNING
		       "GPT:sizeof_partition_entry values don't match: "
		       "0x%x != 0x%x\n",
                       le32_to_cpu(pgpt->sizeof_partition_entry),
		       le32_to_cpu(agpt->sizeof_partition_entry));
		error_found++;
	}
	if (le32_to_cpu(pgpt->partition_entry_array_crc32) !=
            le32_to_cpu(agpt->partition_entry_array_crc32)) {
		printk(KERN_WARNING
		       "GPT:partition_entry_array_crc32 values don't match: "
		       "0x%x != 0x%x\n",
                       le32_to_cpu(pgpt->partition_entry_array_crc32),
		       le32_to_cpu(agpt->partition_entry_array_crc32));
		error_found++;
	}
	if (le64_to_cpu(pgpt->alternate_lba) != lastlba) {
		printk(KERN_WARNING
		       "GPT:Primary header thinks Alt. header is not at the end of the disk.\n");
		printk(KERN_WARNING "GPT:%lld != %lld\n",
			(unsigned long long)le64_to_cpu(pgpt->alternate_lba),
			(unsigned long long)lastlba);
		error_found++;
	}

	if (le64_to_cpu(agpt->my_lba) != lastlba) {
		printk(KERN_WARNING
		       "GPT:Alternate GPT header not at the end of the disk.\n");
		printk(KERN_WARNING "GPT:%lld != %lld\n",
			(unsigned long long)le64_to_cpu(agpt->my_lba),
			(unsigned long long)lastlba);
		error_found++;
	}

	if (error_found)
		printk(KERN_WARNING
		       "GPT: Use GNU Parted to correct GPT errors.\n");
	return;
}
Example #18
0
static int 
mca_make_slidx(void *buffer, slidx_table_t *slidx)
{
	int platform_err = 0;
	int record_len = ((sal_log_record_header_t*)buffer)->len;
	u32 ercd_pos;
	int sects;
	sal_log_section_hdr_t *sp;

	/*
	 * Initialize index referring current record
	 */
	INIT_LIST_HEAD(&(slidx->proc_err));
	INIT_LIST_HEAD(&(slidx->mem_dev_err));
	INIT_LIST_HEAD(&(slidx->sel_dev_err));
	INIT_LIST_HEAD(&(slidx->pci_bus_err));
	INIT_LIST_HEAD(&(slidx->smbios_dev_err));
	INIT_LIST_HEAD(&(slidx->pci_comp_err));
	INIT_LIST_HEAD(&(slidx->plat_specific_err));
	INIT_LIST_HEAD(&(slidx->host_ctlr_err));
	INIT_LIST_HEAD(&(slidx->plat_bus_err));
	INIT_LIST_HEAD(&(slidx->unsupported));

	/*
	 * Extract a Record Header
	 */
	slidx->header = buffer;

	/*
	 * Extract each section records
	 * (arranged from "int ia64_log_platform_info_print()")
	 */
	for (ercd_pos = sizeof(sal_log_record_header_t), sects = 0;
		ercd_pos < record_len; ercd_pos += sp->len, sects++) {
		sp = (sal_log_section_hdr_t *)((char*)buffer + ercd_pos);
		if (!efi_guidcmp(sp->guid, SAL_PROC_DEV_ERR_SECT_GUID)) {
			LOG_INDEX_ADD_SECT_PTR(slidx->proc_err, sp);
		} else if (!efi_guidcmp(sp->guid, SAL_PLAT_MEM_DEV_ERR_SECT_GUID)) {
			platform_err = 1;
			LOG_INDEX_ADD_SECT_PTR(slidx->mem_dev_err, sp);
		} else if (!efi_guidcmp(sp->guid, SAL_PLAT_SEL_DEV_ERR_SECT_GUID)) {
			platform_err = 1;
			LOG_INDEX_ADD_SECT_PTR(slidx->sel_dev_err, sp);
		} else if (!efi_guidcmp(sp->guid, SAL_PLAT_PCI_BUS_ERR_SECT_GUID)) {
			platform_err = 1;
			LOG_INDEX_ADD_SECT_PTR(slidx->pci_bus_err, sp);
		} else if (!efi_guidcmp(sp->guid, SAL_PLAT_SMBIOS_DEV_ERR_SECT_GUID)) {
			platform_err = 1;
			LOG_INDEX_ADD_SECT_PTR(slidx->smbios_dev_err, sp);
		} else if (!efi_guidcmp(sp->guid, SAL_PLAT_PCI_COMP_ERR_SECT_GUID)) {
			platform_err = 1;
			LOG_INDEX_ADD_SECT_PTR(slidx->pci_comp_err, sp);
		} else if (!efi_guidcmp(sp->guid, SAL_PLAT_SPECIFIC_ERR_SECT_GUID)) {
			platform_err = 1;
			LOG_INDEX_ADD_SECT_PTR(slidx->plat_specific_err, sp);
		} else if (!efi_guidcmp(sp->guid, SAL_PLAT_HOST_CTLR_ERR_SECT_GUID)) {
			platform_err = 1;
			LOG_INDEX_ADD_SECT_PTR(slidx->host_ctlr_err, sp);
		} else if (!efi_guidcmp(sp->guid, SAL_PLAT_BUS_ERR_SECT_GUID)) {
			platform_err = 1;
			LOG_INDEX_ADD_SECT_PTR(slidx->plat_bus_err, sp);
		} else {
			LOG_INDEX_ADD_SECT_PTR(slidx->unsupported, sp);
		}
	}
	slidx->n_sections = sects;

	return platform_err;
}
Example #19
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;
}
Example #20
0
/**
 * compare_gpts() - Search disk for valid GPT headers and PTEs
 * @pgpt is the primary GPT header
 * @agpt is the alternate GPT header
 * @lastlba is the last LBA number
 * Description: Returns nothing.  Sanity checks pgpt and agpt fields
 * and prints warnings on discrepancies.
 * 
 */
static void
compare_gpts(gpt_header *pgpt, gpt_header *agpt, uint64_t lastlba)
{
	int error_found = 0;
	if (!pgpt || !agpt)
		return;
	if (__le64_to_cpu(pgpt->my_lba) != __le64_to_cpu(agpt->alternate_lba)) {
		fprintf(stderr, 
		       "GPT:Primary header LBA != Alt. header alternate_lba\n");
		fprintf(stderr,  "GPT:%" PRIx64 "x != %" PRIx64 "x\n",
		       __le64_to_cpu(pgpt->my_lba),
                       __le64_to_cpu(agpt->alternate_lba));
		error_found++;
	}
	if (__le64_to_cpu(pgpt->alternate_lba) != __le64_to_cpu(agpt->my_lba)) {
		fprintf(stderr, 
		       "GPT:Primary header alternate_lba != Alt. header my_lba\n");
		fprintf(stderr,  "GPT:%" PRIx64 " != %" PRIx64 "\n",
		       __le64_to_cpu(pgpt->alternate_lba),
                       __le64_to_cpu(agpt->my_lba));
		error_found++;
	}
	if (__le64_to_cpu(pgpt->first_usable_lba) !=
            __le64_to_cpu(agpt->first_usable_lba)) {
		fprintf(stderr,  "GPT:first_usable_lbas don't match.\n");
		fprintf(stderr,  "GPT:%" PRIx64 " != %" PRIx64 "\n",
		       __le64_to_cpu(pgpt->first_usable_lba),
                       __le64_to_cpu(agpt->first_usable_lba));
		error_found++;
	}
	if (__le64_to_cpu(pgpt->last_usable_lba) !=
            __le64_to_cpu(agpt->last_usable_lba)) {
		fprintf(stderr,  "GPT:last_usable_lbas don't match.\n");
		fprintf(stderr,  "GPT:%" PRIx64 " != %" PRIx64 "\n",
		       __le64_to_cpu(pgpt->last_usable_lba),
                       __le64_to_cpu(agpt->last_usable_lba));
		error_found++;
	}
	if (efi_guidcmp(pgpt->disk_guid, agpt->disk_guid)) {
		fprintf(stderr,  "GPT:disk_guids don't match.\n");
		error_found++;
	}
	if (__le32_to_cpu(pgpt->num_partition_entries) !=
            __le32_to_cpu(agpt->num_partition_entries)) {
		fprintf(stderr,  "GPT:num_partition_entries don't match: "
		       "0x%x != 0x%x\n",
		       __le32_to_cpu(pgpt->num_partition_entries),
		       __le32_to_cpu(agpt->num_partition_entries));
		error_found++;
	}
	if (__le32_to_cpu(pgpt->sizeof_partition_entry) !=
            __le32_to_cpu(agpt->sizeof_partition_entry)) {
		fprintf(stderr, 
		       "GPT:sizeof_partition_entry values don't match: "
		       "0x%x != 0x%x\n",
                       __le32_to_cpu(pgpt->sizeof_partition_entry),
		       __le32_to_cpu(agpt->sizeof_partition_entry));
		error_found++;
	}
	if (__le32_to_cpu(pgpt->partition_entry_array_crc32) !=
            __le32_to_cpu(agpt->partition_entry_array_crc32)) {
		fprintf(stderr, 
		       "GPT:partition_entry_array_crc32 values don't match: "
		       "0x%x != 0x%x\n",
                       __le32_to_cpu(pgpt->partition_entry_array_crc32),
		       __le32_to_cpu(agpt->partition_entry_array_crc32));
		error_found++;
	}
	if (__le64_to_cpu(pgpt->alternate_lba) != lastlba) {
		fprintf(stderr, 
		       "GPT:Primary header thinks Alt. header is not at the end of the disk.\n");
		fprintf(stderr,  "GPT:%" PRIx64 " != %" PRIx64 "\n",
		       __le64_to_cpu(pgpt->alternate_lba), lastlba);
		error_found++;
	}

	if (__le64_to_cpu(agpt->my_lba) != lastlba) {
		fprintf(stderr, 
		       "GPT:Alternate GPT header not at the end of the disk.\n");
		fprintf(stderr,  "GPT:%" PRIx64 " != %" PRIx64 "\n",
		       __le64_to_cpu(agpt->my_lba), lastlba);
		error_found++;
	}

	if (error_found)
		fprintf(stderr, 
		       "GPT: Use GNU Parted to correct GPT errors.\n");
	return;
}
Example #21
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;
	u8 unparsed_guid[37];

	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");

	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;

		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;
		/* 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;

#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)
 * @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;
}
Example #23
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;
}
Example #24
0
/**
 * compare_gpts() - Search disk for valid GPT headers and PTEs
 * @pgpt is the primary GPT header
 * @agpt is the alternate GPT header
 * @lastlba is the last LBA number
 * Description: Returns nothing.  Sanity checks pgpt and agpt fields
 * and prints warnings on discrepancies.
 * 
 */
static void
compare_gpts(gpt_header *pgpt, gpt_header *agpt, u64 lastlba)
{
	int error_found = 0;
	if (!pgpt || !agpt)
		return;
	if (le64_to_cpu(pgpt->my_lba) != le64_to_cpu(agpt->alternate_lba)) {
//		printk(KERN_WARNING
;
//		printk(KERN_WARNING "GPT:%lld != %lld\n",
//		       (unsigned long long)le64_to_cpu(pgpt->my_lba),
;
		error_found++;
	}
	if (le64_to_cpu(pgpt->alternate_lba) != le64_to_cpu(agpt->my_lba)) {
//		printk(KERN_WARNING
;
//		printk(KERN_WARNING "GPT:%lld != %lld\n",
//		       (unsigned long long)le64_to_cpu(pgpt->alternate_lba),
;
		error_found++;
	}
	if (le64_to_cpu(pgpt->first_usable_lba) !=
            le64_to_cpu(agpt->first_usable_lba)) {
;
//		printk(KERN_WARNING "GPT:%lld != %lld\n",
//		       (unsigned long long)le64_to_cpu(pgpt->first_usable_lba),
;
		error_found++;
	}
	if (le64_to_cpu(pgpt->last_usable_lba) !=
            le64_to_cpu(agpt->last_usable_lba)) {
;
//		printk(KERN_WARNING "GPT:%lld != %lld\n",
//		       (unsigned long long)le64_to_cpu(pgpt->last_usable_lba),
;
		error_found++;
	}
	if (efi_guidcmp(pgpt->disk_guid, agpt->disk_guid)) {
;
		error_found++;
	}
	if (le32_to_cpu(pgpt->num_partition_entries) !=
            le32_to_cpu(agpt->num_partition_entries)) {
//		printk(KERN_WARNING "GPT:num_partition_entries don't match: "
//		       "0x%x != 0x%x\n",
//		       le32_to_cpu(pgpt->num_partition_entries),
;
		error_found++;
	}
	if (le32_to_cpu(pgpt->sizeof_partition_entry) !=
            le32_to_cpu(agpt->sizeof_partition_entry)) {
//		printk(KERN_WARNING
//		       "GPT:sizeof_partition_entry values don't match: "
//		       "0x%x != 0x%x\n",
//                       le32_to_cpu(pgpt->sizeof_partition_entry),
;
		error_found++;
	}
	if (le32_to_cpu(pgpt->partition_entry_array_crc32) !=
            le32_to_cpu(agpt->partition_entry_array_crc32)) {
//		printk(KERN_WARNING
//		       "GPT:partition_entry_array_crc32 values don't match: "
//		       "0x%x != 0x%x\n",
//                       le32_to_cpu(pgpt->partition_entry_array_crc32),
;
		error_found++;
	}
	if (le64_to_cpu(pgpt->alternate_lba) != lastlba) {
//		printk(KERN_WARNING
;
//		printk(KERN_WARNING "GPT:%lld != %lld\n",
//			(unsigned long long)le64_to_cpu(pgpt->alternate_lba),
;
		error_found++;
	}

	if (le64_to_cpu(agpt->my_lba) != lastlba) {
//		printk(KERN_WARNING
;
//		printk(KERN_WARNING "GPT:%lld != %lld\n",
//			(unsigned long long)le64_to_cpu(agpt->my_lba),
;
		error_found++;
	}

	if (error_found)
//		printk(KERN_WARNING
;
	return;
}
Example #25
0
/*
 * This is kind of ugly, but older rev HCDP tables don't provide interrupt
 * polarity and trigger information.  Linux/ia64 discovers these properties
 * later via ACPI names, but we don't have that luxury in Xen/ia64.  Since
 * all future platforms should have newer PCDP tables, this should be a
 * fixed list of boxes in the field, so we can hardcode based on the model.
 */
static void __init
pcdp_hp_irq_fixup(struct pcdp *pcdp, struct pcdp_uart *uart)
{
	efi_system_table_t *systab;
	efi_config_table_t *tables;
	struct acpi20_table_rsdp *rsdp = NULL;
	struct acpi_table_xsdt *xsdt;
	struct acpi_table_header *hdr;
	int i;

	if (pcdp->rev >= 3 || strcmp((char *)pcdp->oemid, "HP"))
		return;

	/*
	 * Manually walk firmware provided tables to get to the XSDT.
	 * The OEM table ID on the XSDT is the platform model string.
	 * We only care about ACPI 2.0 tables as that's all HP provides.
	 */
	systab = __va(ia64_boot_param->efi_systab);

	if (!systab || systab->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
		return;

	tables = __va(systab->tables);

	for (i = 0 ; i < (int)systab->nr_tables && !rsdp ; i++) {
		if (efi_guidcmp(tables[i].guid, ACPI_20_TABLE_GUID) == 0)
			rsdp =
			     (struct acpi20_table_rsdp *)__va(tables[i].table);
	}

	if (!rsdp || strncmp(rsdp->signature, RSDP_SIG, sizeof(RSDP_SIG) - 1))
		return;

	xsdt = (struct acpi_table_xsdt *)__va(rsdp->xsdt_address);
	hdr = &xsdt->header;

	if (strncmp(hdr->signature, XSDT_SIG, sizeof(XSDT_SIG) - 1))
		return;

	/* Sanity check; are we still looking at HP firmware tables? */
	if (strcmp(hdr->oem_id, "HP"))
		return;

	if (!strcmp(hdr->oem_table_id, "zx2000") ||
	    !strcmp(hdr->oem_table_id, "zx6000") ||
	    !strcmp(hdr->oem_table_id, "rx2600") ||
	    !strcmp(hdr->oem_table_id, "cx2600")) {

		ns16550_com1.irq = ns16550_com1_gsi = uart->gsi;
		ns16550_com1_polarity = IOSAPIC_POL_HIGH;
		ns16550_com1_trigger = IOSAPIC_EDGE;

	} else if (!strcmp(hdr->oem_table_id, "rx2620") ||
	           !strcmp(hdr->oem_table_id, "cx2620") ||
	           !strcmp(hdr->oem_table_id, "rx1600") ||
	           !strcmp(hdr->oem_table_id, "rx1620")) {

		ns16550_com1.irq = ns16550_com1_gsi = uart->gsi;
		ns16550_com1_polarity = IOSAPIC_POL_LOW;
		ns16550_com1_trigger = IOSAPIC_LEVEL;
	}
}