1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  *  EFI boot manager
4  *
5  *  Copyright (c) 2018 AKASHI Takahiro, et.al.
6  */
7 
8 #define LOG_CATEGORY LOGC_EFI
9 
10 #include <charset.h>
11 #include <log.h>
12 #include <malloc.h>
13 #include <efi_loader.h>
14 #include <asm/unaligned.h>
15 
16 /**
17  * efi_set_load_options() - set the load options of a loaded image
18  *
19  * @handle:		the image handle
20  * @load_options_size:	size of load options
21  * @load_options:	pointer to load options
22  * Return:		status code
23  */
efi_set_load_options(efi_handle_t handle,efi_uintn_t load_options_size,void * load_options)24 efi_status_t efi_set_load_options(efi_handle_t handle,
25 				  efi_uintn_t load_options_size,
26 				  void *load_options)
27 {
28 	struct efi_loaded_image *loaded_image_info;
29 	struct efi_handler *handler;
30 	efi_status_t ret;
31 
32 	ret = efi_search_protocol(handle, &efi_guid_loaded_image, &handler);
33 	if (ret != EFI_SUCCESS)
34 		return EFI_INVALID_PARAMETER;
35 
36 	loaded_image_info = handler->protocol_interface;
37 	loaded_image_info->load_options = load_options;
38 	loaded_image_info->load_options_size = load_options_size;
39 
40 	return EFI_SUCCESS;
41 }
42 
43 /**
44  * efi_deserialize_load_option() - parse serialized data
45  *
46  * Parse serialized data describing a load option and transform it to the
47  * efi_load_option structure.
48  *
49  * @lo:		pointer to target
50  * @data:	serialized data
51  * @size:	size of the load option, on return size of the optional data
52  * Return:	status code
53  */
efi_deserialize_load_option(struct efi_load_option * lo,u8 * data,efi_uintn_t * size)54 efi_status_t efi_deserialize_load_option(struct efi_load_option *lo, u8 *data,
55 					 efi_uintn_t *size)
56 {
57 	efi_uintn_t len;
58 
59 	len = sizeof(u32);
60 	if (*size < len + 2 * sizeof(u16))
61 		return EFI_INVALID_PARAMETER;
62 	lo->attributes = get_unaligned_le32(data);
63 	data += len;
64 	*size -= len;
65 
66 	len = sizeof(u16);
67 	lo->file_path_length = get_unaligned_le16(data);
68 	data += len;
69 	*size -= len;
70 
71 	lo->label = (u16 *)data;
72 	len = u16_strnlen(lo->label, *size / sizeof(u16) - 1);
73 	if (lo->label[len])
74 		return EFI_INVALID_PARAMETER;
75 	len = (len + 1) * sizeof(u16);
76 	if (*size < len)
77 		return EFI_INVALID_PARAMETER;
78 	data += len;
79 	*size -= len;
80 
81 	len = lo->file_path_length;
82 	if (*size < len)
83 		return EFI_INVALID_PARAMETER;
84 	lo->file_path = (struct efi_device_path *)data;
85 	if (efi_dp_check_length(lo->file_path, len) < 0)
86 		return EFI_INVALID_PARAMETER;
87 	data += len;
88 	*size -= len;
89 
90 	lo->optional_data = data;
91 
92 	return EFI_SUCCESS;
93 }
94 
95 /**
96  * efi_serialize_load_option() - serialize load option
97  *
98  * Serialize efi_load_option structure into byte stream for BootXXXX.
99  *
100  * @data:	buffer for serialized data
101  * @lo:		load option
102  * Return:	size of allocated buffer
103  */
efi_serialize_load_option(struct efi_load_option * lo,u8 ** data)104 unsigned long efi_serialize_load_option(struct efi_load_option *lo, u8 **data)
105 {
106 	unsigned long label_len;
107 	unsigned long size;
108 	u8 *p;
109 
110 	label_len = u16_strsize(lo->label);
111 
112 	/* total size */
113 	size = sizeof(lo->attributes);
114 	size += sizeof(lo->file_path_length);
115 	size += label_len;
116 	size += lo->file_path_length;
117 	if (lo->optional_data)
118 		size += (utf8_utf16_strlen((const char *)lo->optional_data)
119 					   + 1) * sizeof(u16);
120 	p = malloc(size);
121 	if (!p)
122 		return 0;
123 
124 	/* copy data */
125 	*data = p;
126 	memcpy(p, &lo->attributes, sizeof(lo->attributes));
127 	p += sizeof(lo->attributes);
128 
129 	memcpy(p, &lo->file_path_length, sizeof(lo->file_path_length));
130 	p += sizeof(lo->file_path_length);
131 
132 	memcpy(p, lo->label, label_len);
133 	p += label_len;
134 
135 	memcpy(p, lo->file_path, lo->file_path_length);
136 	p += lo->file_path_length;
137 
138 	if (lo->optional_data) {
139 		utf8_utf16_strcpy((u16 **)&p, (const char *)lo->optional_data);
140 		p += sizeof(u16); /* size of trailing \0 */
141 	}
142 	return size;
143 }
144