Skip to content

Commit 2f0750e

Browse files
robclarkJosephChen2017
authored andcommitted
UPSTREAM: efi_loader: refactor boot device and loaded_image handling
Get rid of the hacky fake boot-device and duplicate device-path constructing (which needs to match what efi_disk and efi_net do). Instead convert over to use efi_device_path helpers to construct device-paths, and use that to look up the actual boot device. Also, extract out a helper to plug things in properly to the loaded_image. In a following patch we'll want to re-use this in efi_load_image() to handle the case of loading an image from a file_path. Signed-off-by: Rob Clark <[email protected]> Signed-off-by: Alexander Graf <[email protected]> (cherry picked from commit 95c5553) Change-Id: Iaa6a9865f2cbd15d6537d200bd86662fa4baf5a0 Signed-off-by: Jeffy Chen <[email protected]>
1 parent a0955e7 commit 2f0750e

File tree

4 files changed

+100
-147
lines changed

4 files changed

+100
-147
lines changed

cmd/bootefi.c

Lines changed: 59 additions & 142 deletions
Original file line numberDiff line numberDiff line change
@@ -22,97 +22,14 @@ DECLARE_GLOBAL_DATA_PTR;
2222

2323
static uint8_t efi_obj_list_initalized;
2424

25-
/*
26-
* When booting using the "bootefi" command, we don't know which
27-
* physical device the file came from. So we create a pseudo-device
28-
* called "bootefi" with the device path /bootefi.
29-
*
30-
* In addition to the originating device we also declare the file path
31-
* of "bootefi" based loads to be /bootefi.
32-
*/
33-
static struct efi_device_path_file_path bootefi_image_path[] = {
34-
{
35-
.dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE,
36-
.dp.sub_type = DEVICE_PATH_SUB_TYPE_FILE_PATH,
37-
.dp.length = sizeof(bootefi_image_path[0]),
38-
.str = { 'b','o','o','t','e','f','i' },
39-
}, {
40-
.dp.type = DEVICE_PATH_TYPE_END,
41-
.dp.sub_type = DEVICE_PATH_SUB_TYPE_END,
42-
.dp.length = sizeof(bootefi_image_path[0]),
43-
}
44-
};
45-
46-
static struct efi_device_path_file_path bootefi_device_path[] = {
47-
{
48-
.dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE,
49-
.dp.sub_type = DEVICE_PATH_SUB_TYPE_FILE_PATH,
50-
.dp.length = sizeof(bootefi_image_path[0]),
51-
.str = { 'b','o','o','t','e','f','i' },
52-
}, {
53-
.dp.type = DEVICE_PATH_TYPE_END,
54-
.dp.sub_type = DEVICE_PATH_SUB_TYPE_END,
55-
.dp.length = sizeof(bootefi_image_path[0]),
56-
}
57-
};
58-
59-
/* The EFI loaded_image interface for the image executed via "bootefi" */
60-
static struct efi_loaded_image loaded_image_info = {
61-
.device_handle = bootefi_device_path,
62-
.file_path = bootefi_image_path,
63-
};
64-
65-
/* The EFI object struct for the image executed via "bootefi" */
66-
static struct efi_object loaded_image_info_obj = {
67-
.handle = &loaded_image_info,
68-
.protocols = {
69-
{
70-
/*
71-
* When asking for the loaded_image interface, just
72-
* return handle which points to loaded_image_info
73-
*/
74-
.guid = &efi_guid_loaded_image,
75-
.protocol_interface = &loaded_image_info,
76-
},
77-
{
78-
/*
79-
* When asking for the device path interface, return
80-
* bootefi_device_path
81-
*/
82-
.guid = &efi_guid_device_path,
83-
.protocol_interface = bootefi_device_path,
84-
},
85-
{
86-
.guid = &efi_guid_console_control,
87-
.protocol_interface = (void *) &efi_console_control
88-
},
89-
{
90-
.guid = &efi_guid_device_path_to_text_protocol,
91-
.protocol_interface = (void *) &efi_device_path_to_text
92-
},
93-
},
94-
};
95-
96-
/* The EFI object struct for the device the "bootefi" image was loaded from */
97-
static struct efi_object bootefi_device_obj = {
98-
.handle = bootefi_device_path,
99-
.protocols = {
100-
{
101-
/* When asking for the device path interface, return
102-
* bootefi_device_path */
103-
.guid = &efi_guid_device_path,
104-
.protocol_interface = bootefi_device_path
105-
}
106-
},
107-
};
25+
static struct efi_device_path *bootefi_image_path;
26+
static struct efi_device_path *bootefi_device_path;
10827

10928
/* Initialize and populate EFI object list */
11029
static void efi_init_obj_list(void)
11130
{
11231
efi_obj_list_initalized = 1;
11332

114-
list_add_tail(&loaded_image_info_obj.link, &efi_obj_list);
115-
list_add_tail(&bootefi_device_obj.link, &efi_obj_list);
11633
efi_console_register();
11734
#ifdef CONFIG_PARTITIONS
11835
efi_disk_register();
@@ -121,13 +38,7 @@ static void efi_init_obj_list(void)
12138
efi_gop_register();
12239
#endif
12340
#ifdef CONFIG_NET
124-
void *nethandle = loaded_image_info.device_handle;
125-
efi_net_register(&nethandle);
126-
127-
if (!memcmp(bootefi_device_path[0].str, "N\0e\0t", 6))
128-
loaded_image_info.device_handle = nethandle;
129-
else
130-
loaded_image_info.device_handle = bootefi_device_path;
41+
efi_net_register();
13142
#endif
13243
#ifdef CONFIG_GENERATE_SMBIOS_TABLE
13344
efi_smbios_register();
@@ -210,14 +121,27 @@ static unsigned long efi_run_in_el2(asmlinkage ulong (*entry)(
210121
* Load an EFI payload into a newly allocated piece of memory, register all
211122
* EFI objects it would want to access and jump to it.
212123
*/
213-
static unsigned long do_bootefi_exec(void *efi, void *fdt)
124+
static unsigned long do_bootefi_exec(void *efi, void *fdt,
125+
struct efi_device_path *device_path,
126+
struct efi_device_path *image_path)
214127
{
128+
struct efi_loaded_image loaded_image_info = {};
129+
struct efi_object loaded_image_info_obj = {};
130+
ulong ret;
131+
215132
ulong (*entry)(void *image_handle, struct efi_system_table *st)
216133
asmlinkage;
217134
ulong fdt_pages, fdt_size, fdt_start, fdt_end;
218135
const efi_guid_t fdt_guid = EFI_FDT_GUID;
219136
bootm_headers_t img = { 0 };
220137

138+
/* Initialize and populate EFI object list */
139+
if (!efi_obj_list_initalized)
140+
efi_init_obj_list();
141+
142+
efi_setup_loaded_image(&loaded_image_info, &loaded_image_info_obj,
143+
device_path, image_path);
144+
221145
/*
222146
* gd lives in a fixed register which may get clobbered while we execute
223147
* the payload. So save it here and restore it on every callback entry
@@ -252,18 +176,18 @@ static unsigned long do_bootefi_exec(void *efi, void *fdt)
252176

253177
/* Load the EFI payload */
254178
entry = efi_load_pe(efi, &loaded_image_info);
255-
if (!entry)
256-
return -ENOENT;
257-
258-
/* Initialize and populate EFI object list */
259-
if (!efi_obj_list_initalized)
260-
efi_init_obj_list();
179+
if (!entry) {
180+
ret = -ENOENT;
181+
goto exit;
182+
}
261183

262184
/* Call our payload! */
263185
debug("%s:%d Jumping to 0x%lx\n", __func__, __LINE__, (long)entry);
264186

265187
if (setjmp(&loaded_image_info.exit_jmp)) {
266-
return loaded_image_info.exit_status;
188+
ret = loaded_image_info.exit_status;
189+
EFI_EXIT(ret);
190+
goto exit;
267191
}
268192

269193
#ifdef CONFIG_ARM64
@@ -282,7 +206,13 @@ static unsigned long do_bootefi_exec(void *efi, void *fdt)
282206
}
283207
#endif
284208

285-
return efi_do_enter(&loaded_image_info, &systab, entry);
209+
ret = efi_do_enter(&loaded_image_info, &systab, entry);
210+
211+
exit:
212+
/* image has returned, loaded-image obj goes *poof*: */
213+
list_del(&loaded_image_info_obj.link);
214+
215+
return ret;
286216
}
287217

288218

@@ -319,7 +249,8 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
319249
}
320250

321251
printf("## Starting EFI application at %08lx ...\n", addr);
322-
r = do_bootefi_exec((void *)addr, (void*)fdt_addr);
252+
r = do_bootefi_exec((void *)addr, (void *)fdt_addr,
253+
bootefi_device_path, bootefi_image_path);
323254
printf("## Application terminated, r = %lu\n",
324255
r & ~EFI_ERROR_MASK);
325256

@@ -348,58 +279,44 @@ U_BOOT_CMD(
348279
bootefi_help_text
349280
);
350281

351-
void efi_set_bootdev(const char *dev, const char *devnr, const char *path)
282+
static int parse_partnum(const char *devnr)
352283
{
353-
__maybe_unused struct blk_desc *desc;
354-
char devname[32] = { 0 }; /* dp->str is u16[32] long */
355-
char *colon, *s;
356-
357-
#if defined(CONFIG_BLK) || CONFIG_IS_ENABLED(ISO_PARTITION)
358-
desc = blk_get_dev(dev, simple_strtol(devnr, NULL, 10));
359-
#endif
360-
361-
#ifdef CONFIG_BLK
362-
if (desc) {
363-
snprintf(devname, sizeof(devname), "%s", desc->bdev->name);
364-
} else
365-
#endif
366-
367-
{
368-
/* Assemble the condensed device name we use in efi_disk.c */
369-
snprintf(devname, sizeof(devname), "%s%s", dev, devnr);
284+
const char *str = strchr(devnr, ':');
285+
if (str) {
286+
str++;
287+
return simple_strtoul(str, NULL, 16);
370288
}
289+
return 0;
290+
}
371291

372-
colon = strchr(devname, ':');
373-
374-
#if CONFIG_IS_ENABLED(ISO_PARTITION)
375-
/* For ISOs we create partition block devices */
376-
if (desc && (desc->type != DEV_TYPE_UNKNOWN) &&
377-
(desc->part_type == PART_TYPE_ISO)) {
378-
if (!colon)
379-
snprintf(devname, sizeof(devname), "%s:1", devname);
292+
void efi_set_bootdev(const char *dev, const char *devnr, const char *path)
293+
{
294+
char filename[32] = { 0 }; /* dp->str is u16[32] long */
295+
char *s;
380296

381-
colon = NULL;
382-
}
383-
#endif
297+
if (strcmp(dev, "Net")) {
298+
struct blk_desc *desc;
299+
int part;
384300

385-
if (colon)
386-
*colon = '\0';
301+
desc = blk_get_dev(dev, simple_strtol(devnr, NULL, 10));
302+
part = parse_partnum(devnr);
387303

388-
/* Patch bootefi_device_path to the target device */
389-
memset(bootefi_device_path[0].str, 0, sizeof(bootefi_device_path[0].str));
390-
ascii2unicode(bootefi_device_path[0].str, devname);
304+
bootefi_device_path = efi_dp_from_part(desc, part);
305+
} else {
306+
#ifdef CONFIG_NET
307+
bootefi_device_path = efi_dp_from_eth();
308+
#endif
309+
}
391310

392-
/* Patch bootefi_image_path to the target file path */
393-
memset(bootefi_image_path[0].str, 0, sizeof(bootefi_image_path[0].str));
394311
if (strcmp(dev, "Net")) {
395312
/* Add leading / to fs paths, because they're absolute */
396-
snprintf(devname, sizeof(devname), "/%s", path);
313+
snprintf(filename, sizeof(filename), "/%s", path);
397314
} else {
398-
snprintf(devname, sizeof(devname), "%s", path);
315+
snprintf(filename, sizeof(filename), "%s", path);
399316
}
400317
/* DOS style file path: */
401-
s = devname;
318+
s = filename;
402319
while ((s = strchr(s, '/')))
403320
*s++ = '\\';
404-
ascii2unicode(bootefi_image_path[0].str, devname);
321+
bootefi_image_path = efi_dp_from_file(NULL, 0, filename);
405322
}

include/efi_loader.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ int efi_disk_register(void);
134134
/* Called by bootefi to make GOP (graphical) interface available */
135135
int efi_gop_register(void);
136136
/* Called by bootefi to make the network interface available */
137-
int efi_net_register(void **handle);
137+
int efi_net_register(void);
138138
/* Called by bootefi to make SMBIOS tables available */
139139
void efi_smbios_register(void);
140140

@@ -191,6 +191,9 @@ uint64_t efi_add_memory_map(uint64_t start, uint64_t pages, int memory_type,
191191
int efi_memory_init(void);
192192
/* Adds new or overrides configuration table entry to the system table */
193193
efi_status_t efi_install_configuration_table(const efi_guid_t *guid, void *table);
194+
void efi_setup_loaded_image(struct efi_loaded_image *info, struct efi_object *obj,
195+
struct efi_device_path *device_path,
196+
struct efi_device_path *file_path);
194197

195198
#ifdef CONFIG_EFI_LOADER_BOUNCE_BUFFER
196199
extern void *efi_bounce_buffer;

lib/efi_loader/efi_boottime.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -726,6 +726,42 @@ static efi_status_t EFIAPI efi_install_configuration_table_ext(efi_guid_t *guid,
726726
return EFI_EXIT(efi_install_configuration_table(guid, table));
727727
}
728728

729+
/* Initialize a loaded_image_info + loaded_image_info object with correct
730+
* protocols, boot-device, etc.
731+
*/
732+
void efi_setup_loaded_image(struct efi_loaded_image *info, struct efi_object *obj,
733+
struct efi_device_path *device_path,
734+
struct efi_device_path *file_path)
735+
{
736+
obj->handle = info;
737+
738+
/*
739+
* When asking for the device path interface, return
740+
* bootefi_device_path
741+
*/
742+
obj->protocols[0].guid = &efi_guid_device_path;
743+
obj->protocols[0].protocol_interface = device_path;
744+
745+
/*
746+
* When asking for the loaded_image interface, just
747+
* return handle which points to loaded_image_info
748+
*/
749+
obj->protocols[1].guid = &efi_guid_loaded_image;
750+
obj->protocols[1].protocol_interface = info;
751+
752+
obj->protocols[2].guid = &efi_guid_console_control;
753+
obj->protocols[2].protocol_interface = (void *)&efi_console_control;
754+
755+
obj->protocols[3].guid = &efi_guid_device_path_to_text_protocol;
756+
obj->protocols[3].protocol_interface =
757+
(void *)&efi_device_path_to_text;
758+
759+
info->file_path = file_path;
760+
info->device_handle = efi_dp_find_obj(device_path, NULL);
761+
762+
list_add_tail(&obj->link, &efi_obj_list);
763+
}
764+
729765
static efi_status_t EFIAPI efi_load_image(bool boot_policy,
730766
efi_handle_t parent_image,
731767
struct efi_device_path *file_path,

lib/efi_loader/efi_net.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ void efi_net_set_dhcp_ack(void *pkt, int len)
210210
}
211211

212212
/* This gets called from do_bootefi_exec(). */
213-
int efi_net_register(void **handle)
213+
int efi_net_register(void)
214214
{
215215
struct efi_net_obj *netobj;
216216
struct efi_device_path_mac_addr dp_net = {
@@ -268,8 +268,5 @@ int efi_net_register(void **handle)
268268
/* Hook net up to the device list */
269269
list_add_tail(&netobj->parent.link, &efi_obj_list);
270270

271-
if (handle)
272-
*handle = &netobj->net;
273-
274271
return 0;
275272
}

0 commit comments

Comments
 (0)