blob: 01984235e248d0e172e7c6401a36c8c4cfb13f6b [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
Heinrich Schuchardta8cb98f2021-01-15 19:02:49 +010010#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 */
24efi_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;
Heinrich Schuchardt8adf8d82022-10-07 16:21:28 +020029 struct efi_handler *handler;
Heinrich Schuchardta8cb98f2021-01-15 19:02:49 +010030 efi_status_t ret;
31
Heinrich Schuchardt8adf8d82022-10-07 16:21:28 +020032 ret = efi_search_protocol(handle, &efi_guid_loaded_image, &handler);
Heinrich Schuchardta8cb98f2021-01-15 19:02:49 +010033 if (ret != EFI_SUCCESS)
34 return EFI_INVALID_PARAMETER;
35
Dan Carpenter81040de2023-07-27 10:15:01 +030036 loaded_image_info = handler->protocol_interface;
Heinrich Schuchardta8cb98f2021-01-15 19:02:49 +010037 loaded_image_info->load_options = load_options;
38 loaded_image_info->load_options_size = load_options_size;
39
Heinrich Schuchardt8adf8d82022-10-07 16:21:28 +020040 return EFI_SUCCESS;
Heinrich Schuchardta8cb98f2021-01-15 19:02:49 +010041}
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 */
54efi_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 */
104unsigned 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
Heinrich Schuchardt99d21932022-04-02 11:47:01 +0200110 label_len = u16_strsize(lo->label);
Heinrich Schuchardta8cb98f2021-01-15 19:02:49 +0100111
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}