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