blob: 5f62184da1cd5d9e11b77a8886f6ce4b4acb1598 [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;
Heinrich Schuchardt8adf8d82022-10-07 16:21:28 +020030 struct efi_handler *handler;
Heinrich Schuchardta8cb98f2021-01-15 19:02:49 +010031 efi_status_t ret;
32
Heinrich Schuchardt8adf8d82022-10-07 16:21:28 +020033 ret = efi_search_protocol(handle, &efi_guid_loaded_image, &handler);
Heinrich Schuchardta8cb98f2021-01-15 19:02:49 +010034 if (ret != EFI_SUCCESS)
35 return EFI_INVALID_PARAMETER;
36
Dan Carpenter81040de2023-07-27 10:15:01 +030037 loaded_image_info = handler->protocol_interface;
Heinrich Schuchardta8cb98f2021-01-15 19:02:49 +010038 loaded_image_info->load_options = load_options;
39 loaded_image_info->load_options_size = load_options_size;
40
Heinrich Schuchardt8adf8d82022-10-07 16:21:28 +020041 return EFI_SUCCESS;
Heinrich Schuchardta8cb98f2021-01-15 19:02:49 +010042}
43
44/**
45 * efi_deserialize_load_option() - parse serialized data
46 *
47 * Parse serialized data describing a load option and transform it to the
48 * efi_load_option structure.
49 *
50 * @lo: pointer to target
51 * @data: serialized data
52 * @size: size of the load option, on return size of the optional data
53 * Return: status code
54 */
55efi_status_t efi_deserialize_load_option(struct efi_load_option *lo, u8 *data,
56 efi_uintn_t *size)
57{
58 efi_uintn_t len;
59
60 len = sizeof(u32);
61 if (*size < len + 2 * sizeof(u16))
62 return EFI_INVALID_PARAMETER;
63 lo->attributes = get_unaligned_le32(data);
64 data += len;
65 *size -= len;
66
67 len = sizeof(u16);
68 lo->file_path_length = get_unaligned_le16(data);
69 data += len;
70 *size -= len;
71
72 lo->label = (u16 *)data;
73 len = u16_strnlen(lo->label, *size / sizeof(u16) - 1);
74 if (lo->label[len])
75 return EFI_INVALID_PARAMETER;
76 len = (len + 1) * sizeof(u16);
77 if (*size < len)
78 return EFI_INVALID_PARAMETER;
79 data += len;
80 *size -= len;
81
82 len = lo->file_path_length;
83 if (*size < len)
84 return EFI_INVALID_PARAMETER;
85 lo->file_path = (struct efi_device_path *)data;
86 if (efi_dp_check_length(lo->file_path, len) < 0)
87 return EFI_INVALID_PARAMETER;
88 data += len;
89 *size -= len;
90
91 lo->optional_data = data;
92
93 return EFI_SUCCESS;
94}
95
96/**
97 * efi_serialize_load_option() - serialize load option
98 *
99 * Serialize efi_load_option structure into byte stream for BootXXXX.
100 *
101 * @data: buffer for serialized data
102 * @lo: load option
103 * Return: size of allocated buffer
104 */
105unsigned long efi_serialize_load_option(struct efi_load_option *lo, u8 **data)
106{
107 unsigned long label_len;
108 unsigned long size;
109 u8 *p;
110
Heinrich Schuchardt99d21932022-04-02 11:47:01 +0200111 label_len = u16_strsize(lo->label);
Heinrich Schuchardta8cb98f2021-01-15 19:02:49 +0100112
113 /* total size */
114 size = sizeof(lo->attributes);
115 size += sizeof(lo->file_path_length);
116 size += label_len;
117 size += lo->file_path_length;
118 if (lo->optional_data)
119 size += (utf8_utf16_strlen((const char *)lo->optional_data)
120 + 1) * sizeof(u16);
121 p = malloc(size);
122 if (!p)
123 return 0;
124
125 /* copy data */
126 *data = p;
127 memcpy(p, &lo->attributes, sizeof(lo->attributes));
128 p += sizeof(lo->attributes);
129
130 memcpy(p, &lo->file_path_length, sizeof(lo->file_path_length));
131 p += sizeof(lo->file_path_length);
132
133 memcpy(p, lo->label, label_len);
134 p += label_len;
135
136 memcpy(p, lo->file_path, lo->file_path_length);
137 p += lo->file_path_length;
138
139 if (lo->optional_data) {
140 utf8_utf16_strcpy((u16 **)&p, (const char *)lo->optional_data);
141 p += sizeof(u16); /* size of trailing \0 */
142 }
143 return size;
144}