/*
 * Get size of a device path.
 *
 * This function implements the GetDevicePathSize service of the device path
 * utilities protocol. The device path length includes the end of path tag
 * which may be an instance end.
 *
 * See the Unified Extensible Firmware Interface (UEFI) specification
 * for details.
 *
 * @device_path		device path
 * @return		size in bytes
 */
static efi_uintn_t EFIAPI get_device_path_size(
	const struct efi_device_path *device_path)
{
	efi_uintn_t sz = 0;

	EFI_ENTRY("%pD", device_path);
	/* size includes the END node: */
	if (device_path)
		sz = efi_dp_size(device_path) + sizeof(struct efi_device_path);
	return EFI_EXIT(sz);
}
示例#2
0
/**
 * do_efi_boot_add() - set UEFI load option
 *
 * @cmdtp:	Command table
 * @flag:	Command flag
 * @argc:	Number of arguments
 * @argv:	Argument array
 * Return:	CMD_RET_SUCCESS on success,
 *		CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
 *
 * Implement efidebug "boot add" sub-command.
 * Create or change UEFI load option.
 *   - boot add <id> <label> <interface> <devnum>[:<part>] <file> <options>
 */
static int do_efi_boot_add(cmd_tbl_t *cmdtp, int flag,
			   int argc, char * const argv[])
{
	int id;
	char *endp;
	char var_name[9];
	u16 var_name16[9], *p;
	efi_guid_t guid;
	size_t label_len, label_len16;
	u16 *label;
	struct efi_device_path *device_path = NULL, *file_path = NULL;
	struct efi_load_option lo;
	void *data = NULL;
	efi_uintn_t size;
	int ret;

	if (argc < 6 || argc > 7)
		return CMD_RET_USAGE;

	id = (int)simple_strtoul(argv[1], &endp, 16);
	if (*endp != '\0' || id > 0xffff)
		return CMD_RET_USAGE;

	sprintf(var_name, "Boot%04X", id);
	p = var_name16;
	utf8_utf16_strncpy(&p, var_name, 9);

	guid = efi_global_variable_guid;

	/* attributes */
	lo.attributes = LOAD_OPTION_ACTIVE; /* always ACTIVE */

	/* label */
	label_len = strlen(argv[2]);
	label_len16 = utf8_utf16_strnlen(argv[2], label_len);
	label = malloc((label_len16 + 1) * sizeof(u16));
	if (!label)
		return CMD_RET_FAILURE;
	lo.label = label; /* label will be changed below */
	utf8_utf16_strncpy(&label, argv[2], label_len);

	/* file path */
	ret = efi_dp_from_name(argv[3], argv[4], argv[5], &device_path,
			       &file_path);
	if (ret != EFI_SUCCESS) {
		printf("Cannot create device path for \"%s %s\"\n",
		       argv[3], argv[4]);
		ret = CMD_RET_FAILURE;
		goto out;
	}
	lo.file_path = file_path;
	lo.file_path_length = efi_dp_size(file_path)
				+ sizeof(struct efi_device_path); /* for END */

	/* optional data */
	lo.optional_data = (u8 *)(argc == 6 ? "" : argv[6]);

	size = efi_serialize_load_option(&lo, (u8 **)&data);
	if (!size) {
		ret = CMD_RET_FAILURE;
		goto out;
	}

	ret = EFI_CALL(RT->set_variable(var_name16, &guid,
					EFI_VARIABLE_BOOTSERVICE_ACCESS |
					EFI_VARIABLE_RUNTIME_ACCESS,
					size, data));
	ret = (ret == EFI_SUCCESS ? CMD_RET_SUCCESS : CMD_RET_FAILURE);
out:
	free(data);
	efi_free_pool(device_path);
	efi_free_pool(file_path);
	free(lo.label);

	return ret;
}