From b5349f742a7684aabd3fb8f0e20c67ba033deec7 Mon Sep 17 00:00:00 2001 From: "xypron.glpk@gmx.de" Date: Tue, 11 Jul 2017 22:06:14 +0200 Subject: efi_loader: refactor efi_open_protocol efi_open_protocol was implemented to call a protocol specific open function to retrieve the protocol interface. The UEFI specification does not know of such a function. It is not possible to implement InstallProtocolInterface with the current design. With the patch the protocol interface itself is stored in the list of installed protocols of an efi_object instead of an open function. Signed-off-by: Heinrich Schuchardt [agraf: fix efi gop support] Signed-off-by: Alexander Graf --- cmd/bootefi.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) (limited to 'cmd') diff --git a/cmd/bootefi.c b/cmd/bootefi.c index 771300ee94b..2a56ad7f58e 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -54,14 +54,6 @@ static struct efi_device_path_file_path bootefi_device_path[] = { } }; -static efi_status_t EFIAPI bootefi_open_dp(void *handle, efi_guid_t *protocol, - void **protocol_interface, void *agent_handle, - void *controller_handle, uint32_t attributes) -{ - *protocol_interface = bootefi_device_path; - return EFI_SUCCESS; -} - /* The EFI loaded_image interface for the image executed via "bootefi" */ static struct efi_loaded_image loaded_image_info = { .device_handle = bootefi_device_path, @@ -78,7 +70,7 @@ static struct efi_object loaded_image_info_obj = { * return handle which points to loaded_image_info */ .guid = &efi_guid_loaded_image, - .open = &efi_return_handle, + .protocol_interface = &loaded_image_info, }, { /* @@ -86,7 +78,7 @@ static struct efi_object loaded_image_info_obj = { * bootefi_device_path */ .guid = &efi_guid_device_path, - .open = &bootefi_open_dp, + .protocol_interface = bootefi_device_path, }, }, }; @@ -99,7 +91,7 @@ static struct efi_object bootefi_device_obj = { /* When asking for the device path interface, return * bootefi_device_path */ .guid = &efi_guid_device_path, - .open = &bootefi_open_dp, + .protocol_interface = bootefi_device_path } }, }; -- cgit v1.3.1 From 88adae5ef057845f6bc69c63123df4332fe835b1 Mon Sep 17 00:00:00 2001 From: "xypron.glpk@gmx.de" Date: Tue, 11 Jul 2017 22:06:24 +0200 Subject: efi_loader: reimplement efi_locate_protocol The UEFI specification requires that LocateProtol finds the first handle supporting the protocol and to return a pointer to its interface. So we have to assign the protocols to an efi_object and not use any separate storage. Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- cmd/bootefi.c | 4 ++++ include/efi_loader.h | 10 ---------- lib/efi_loader/efi_boottime.c | 32 ++++++++++++++++++++------------ 3 files changed, 24 insertions(+), 22 deletions(-) (limited to 'cmd') diff --git a/cmd/bootefi.c b/cmd/bootefi.c index 2a56ad7f58e..8453d90b2c0 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -80,6 +80,10 @@ static struct efi_object loaded_image_info_obj = { .guid = &efi_guid_device_path, .protocol_interface = bootefi_device_path, }, + { + .guid = &efi_guid_console_control, + .protocol_interface = (void *) &efi_console_control + }, }, }; diff --git a/include/efi_loader.h b/include/efi_loader.h index 989e5809ba7..6ea6e9ee4dc 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -36,16 +36,6 @@ extern const efi_guid_t efi_guid_loaded_image; extern unsigned int __efi_runtime_start, __efi_runtime_stop; extern unsigned int __efi_runtime_rel_start, __efi_runtime_rel_stop; -/* - * While UEFI objects can have callbacks, you can also call functions on - * protocols (classes) themselves. This struct maps a protocol GUID to its - * interface (usually a struct with callback functions). - */ -struct efi_class_map { - const efi_guid_t *guid; - const void *interface; -}; - /* * When the UEFI payload wants to open a protocol on an object to get its * interface (usually a struct with callback functions), this struct maps the diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 6f093290eb6..339fe55cde9 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -786,27 +786,35 @@ out: return EFI_EXIT(r); } -static struct efi_class_map efi_class_maps[] = { - { - .guid = &efi_guid_console_control, - .interface = &efi_console_control - }, -}; - static efi_status_t EFIAPI efi_locate_protocol(efi_guid_t *protocol, void *registration, void **protocol_interface) { + struct list_head *lhandle; int i; EFI_ENTRY("%p, %p, %p", protocol, registration, protocol_interface); - for (i = 0; i < ARRAY_SIZE(efi_class_maps); i++) { - struct efi_class_map *curmap = &efi_class_maps[i]; - if (!guidcmp(protocol, curmap->guid)) { - *protocol_interface = (void*)curmap->interface; - return EFI_EXIT(EFI_SUCCESS); + + if (!protocol || !protocol_interface) + return EFI_EXIT(EFI_INVALID_PARAMETER); + + list_for_each(lhandle, &efi_obj_list) { + struct efi_object *efiobj; + + efiobj = list_entry(lhandle, struct efi_object, link); + for (i = 0; i < ARRAY_SIZE(efiobj->protocols); i++) { + struct efi_handler *handler = &efiobj->protocols[i]; + + if (!handler->guid) + continue; + if (!guidcmp(handler->guid, protocol)) { + *protocol_interface = + handler->protocol_interface; + return EFI_EXIT(EFI_SUCCESS); + } } } + *protocol_interface = NULL; return EFI_EXIT(EFI_NOT_FOUND); } -- cgit v1.3.1 From cc5b70812f5e3b13ea9072c2dacc939818ef8e66 Mon Sep 17 00:00:00 2001 From: "xypron.glpk@gmx.de" Date: Tue, 11 Jul 2017 22:06:25 +0200 Subject: efi_loader: implement EFI_DEVICE_PATH_TO_TEXT_PROTOCOL ConvertPathToText is implemented for * type 4 - media device path * subtype 4 - file path This is the kind of device path we hand out for block devices. All other cases may be implemented later. Signed-off-by: Heinrich Schuchardt [agraf: fix whitespace] Signed-off-by: Alexander Graf --- cmd/bootefi.c | 4 ++ include/efi_api.h | 24 ++++++++++++ include/efi_loader.h | 2 + lib/efi_loader/Makefile | 2 +- lib/efi_loader/efi_device_path_to_text.c | 67 ++++++++++++++++++++++++++++++++ 5 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 lib/efi_loader/efi_device_path_to_text.c (limited to 'cmd') diff --git a/cmd/bootefi.c b/cmd/bootefi.c index 8453d90b2c0..dcae2531638 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -84,6 +84,10 @@ static struct efi_object loaded_image_info_obj = { .guid = &efi_guid_console_control, .protocol_interface = (void *) &efi_console_control }, + { + .guid = &efi_guid_device_path_to_text_protocol, + .protocol_interface = (void *) &efi_device_path_to_text + }, }, }; diff --git a/include/efi_api.h b/include/efi_api.h index 42cd47ff080..ea63e80b47c 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -395,6 +395,30 @@ struct efi_console_control_protocol uint16_t *password); }; +#define EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID \ + EFI_GUID(0x8b843e20, 0x8132, 0x4852, \ + 0x90, 0xcc, 0x55, 0x1a, 0x4e, 0x4a, 0x7f, 0x1c) + +struct efi_device_path_protocol +{ + uint8_t type; + uint8_t sub_type; + uint16_t length; + uint8_t data[]; +}; + +struct efi_device_path_to_text_protocol +{ + uint16_t *(EFIAPI *convert_device_node_to_text)( + struct efi_device_path_protocol *device_node, + bool display_only, + bool allow_shortcuts); + uint16_t *(EFIAPI *convert_device_path_to_text)( + struct efi_device_path_protocol *device_path, + bool display_only, + bool allow_shortcuts); +}; + #define EFI_GOP_GUID \ EFI_GUID(0x9042a9de, 0x23dc, 0x4a38, \ 0x96, 0xfb, 0x7a, 0xde, 0xd0, 0x80, 0x51, 0x6a) diff --git a/include/efi_loader.h b/include/efi_loader.h index 6ea6e9ee4dc..d7847d23e53 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -28,10 +28,12 @@ extern struct efi_system_table systab; extern const struct efi_simple_text_output_protocol efi_con_out; extern const struct efi_simple_input_interface efi_con_in; extern const struct efi_console_control_protocol efi_console_control; +extern const struct efi_device_path_to_text_protocol efi_device_path_to_text; extern const efi_guid_t efi_guid_console_control; extern const efi_guid_t efi_guid_device_path; extern const efi_guid_t efi_guid_loaded_image; +extern const efi_guid_t efi_guid_device_path_to_text_protocol; extern unsigned int __efi_runtime_start, __efi_runtime_stop; extern unsigned int __efi_runtime_rel_start, __efi_runtime_rel_stop; diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile index fa8b91a5269..3fc2371896c 100644 --- a/lib/efi_loader/Makefile +++ b/lib/efi_loader/Makefile @@ -15,7 +15,7 @@ always := $(efiprogs-y) obj-$(CONFIG_CMD_BOOTEFI_HELLO) += helloworld_efi.o obj-y += efi_image_loader.o efi_boottime.o efi_runtime.o efi_console.o -obj-y += efi_memory.o +obj-y += efi_memory.o efi_device_path_to_text.o obj-$(CONFIG_LCD) += efi_gop.o obj-$(CONFIG_PARTITIONS) += efi_disk.o obj-$(CONFIG_NET) += efi_net.o diff --git a/lib/efi_loader/efi_device_path_to_text.c b/lib/efi_loader/efi_device_path_to_text.c new file mode 100644 index 00000000000..a7a513047fe --- /dev/null +++ b/lib/efi_loader/efi_device_path_to_text.c @@ -0,0 +1,67 @@ +/* + * EFI device path interface + * + * Copyright (c) 2017 Heinrich Schuchardt + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include + +#define MEDIA_DEVICE_PATH 4 +#define FILE_PATH_MEDIA_DEVICE_PATH 4 + +const efi_guid_t efi_guid_device_path_to_text_protocol = + EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID; + +uint16_t *efi_convert_device_node_to_text( + struct efi_device_path_protocol *device_node, + bool display_only, + bool allow_shortcuts) +{ + EFI_ENTRY("%p, %d, %d", device_node, display_only, allow_shortcuts); + + EFI_EXIT(EFI_UNSUPPORTED); + return NULL; +} + +uint16_t *efi_convert_device_path_to_text( + struct efi_device_path_protocol *device_path, + bool display_only, + bool allow_shortcuts) +{ + EFI_ENTRY("%p, %d, %d", device_path, display_only, allow_shortcuts); + + unsigned long buffer_size; + efi_status_t r; + uint16_t *buffer = NULL; + + switch (device_path->type) { + case MEDIA_DEVICE_PATH: + switch (device_path->sub_type) { + case FILE_PATH_MEDIA_DEVICE_PATH: + buffer_size = device_path->length - 4; + r = efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES, + buffer_size, (void **) &buffer); + if (r == EFI_SUCCESS) + memcpy(buffer, device_path->data, buffer_size); + break; + } + } + + if (buffer) { + EFI_EXIT(EFI_SUCCESS); + } else { + debug("type %d, subtype %d\n", + device_path->type, device_path->sub_type); + EFI_EXIT(EFI_UNSUPPORTED); + } + + return buffer; +} + +const struct efi_device_path_to_text_protocol efi_device_path_to_text = { + .convert_device_node_to_text = efi_convert_device_node_to_text, + .convert_device_path_to_text = efi_convert_device_path_to_text, +}; -- cgit v1.3.1 From b06d8ac39e0f36db4221367623f1908317daa60f Mon Sep 17 00:00:00 2001 From: "xypron.glpk@gmx.de" Date: Tue, 4 Jul 2017 23:15:21 +0200 Subject: bootefi: allow return without EFI_BOOT_SERVICES.Exit The Unified Extensible Firmware Interface Specification, version 2.7, defines in chapter 2.1.2 - UEFI Application that an EFI application may either directly return or call EFI_BOOT_SERVICES.Exit(). Unfortunately U-Boot makes the incorrect assumption that EFI_BOOT_SERVICES.Exit() is always called. So the following application leads to a memory exception on the aarch64 architecture when returning: EFI_STATUS efi_main( EFI_HANDLE handle, EFI_SYSTEM_TABlE systable) { return EFI_SUCCESS; } With this patch the entry point is stored in the image handle. The new wrapper function do_enter is used to call the EFI entry point. Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- cmd/bootefi.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) (limited to 'cmd') diff --git a/cmd/bootefi.c b/cmd/bootefi.c index dcae2531638..e6487dad211 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -147,15 +147,28 @@ static void *copy_fdt(void *fdt) return new_fdt; } +static ulong efi_do_enter(void *image_handle, + struct efi_system_table *st, + asmlinkage ulong (*entry)(void *image_handle, + struct efi_system_table *st)) +{ + efi_status_t ret = EFI_LOAD_ERROR; + + if (entry) + ret = entry(image_handle, st); + st->boottime->exit(image_handle, ret, 0, NULL); + return ret; +} + #ifdef CONFIG_ARM64 -static unsigned long efi_run_in_el2(ulong (*entry)(void *image_handle, - struct efi_system_table *st), void *image_handle, - struct efi_system_table *st) +static unsigned long efi_run_in_el2(asmlinkage ulong (*entry)( + void *image_handle, struct efi_system_table *st), + void *image_handle, struct efi_system_table *st) { /* Enable caches again */ dcache_enable(); - return entry(image_handle, st); + return efi_do_enter(image_handle, st, entry); } #endif @@ -260,7 +273,7 @@ static unsigned long do_bootefi_exec(void *efi, void *fdt) } #endif - return entry(&loaded_image_info, &systab); + return efi_do_enter(&loaded_image_info, &systab, entry); } -- cgit v1.3.1 From 1da1bac477581fdb8aa093b6ed842874ffc5916d Mon Sep 17 00:00:00 2001 From: "xypron.glpk@gmx.de" Date: Tue, 4 Jul 2017 23:15:23 +0200 Subject: efi_loader: provide meaningful status code Currenty any EFI status other than EFI_SUCCESS is reported as Application terminated, r = -22 With the patch the status code returned by the EFI application is printed. Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- cmd/bootefi.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'cmd') diff --git a/cmd/bootefi.c b/cmd/bootefi.c index e6487dad211..08c60e6fa9d 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -253,8 +253,7 @@ static unsigned long do_bootefi_exec(void *efi, void *fdt) debug("%s:%d Jumping to 0x%lx\n", __func__, __LINE__, (long)entry); if (setjmp(&loaded_image_info.exit_jmp)) { - efi_status_t status = loaded_image_info.exit_status; - return status == EFI_SUCCESS ? 0 : -EINVAL; + return loaded_image_info.exit_status; } #ifdef CONFIG_ARM64 @@ -282,7 +281,7 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { char *saddr, *sfdt; unsigned long addr, fdt_addr = 0; - int r = 0; + unsigned long r; if (argc < 2) return CMD_RET_USAGE; @@ -307,12 +306,13 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) printf("## Starting EFI application at %08lx ...\n", addr); r = do_bootefi_exec((void *)addr, (void*)fdt_addr); - printf("## Application terminated, r = %d\n", r); + printf("## Application terminated, r = %lu\n", + r & ~EFI_ERROR_MASK); - if (r != 0) - r = 1; - - return r; + if (r != EFI_SUCCESS) + return 1; + else + return 0; } #ifdef CONFIG_SYS_LONGHELP -- cgit v1.3.1 From 91be9a77b758f5c785787260a1ed8f1b751ff49a Mon Sep 17 00:00:00 2001 From: "xypron.glpk@gmx.de" Date: Tue, 18 Jul 2017 20:17:22 +0200 Subject: efi_console: set up events Set up a timer event and the WaitForKey event. In the notify function of the timer event check for console input and signal the WaitForKey event accordingly. Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- cmd/bootefi.c | 1 + include/efi_loader.h | 6 +++++- lib/efi_loader/efi_boottime.c | 2 +- lib/efi_loader/efi_console.c | 40 +++++++++++++++++++++++++++++++++++++++- 4 files changed, 46 insertions(+), 3 deletions(-) (limited to 'cmd') diff --git a/cmd/bootefi.c b/cmd/bootefi.c index 08c60e6fa9d..e9f14d54af3 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -226,6 +226,7 @@ static unsigned long do_bootefi_exec(void *efi, void *fdt) INIT_LIST_HEAD(&efi_obj_list); list_add_tail(&loaded_image_info_obj.link, &efi_obj_list); list_add_tail(&bootefi_device_obj.link, &efi_obj_list); + efi_console_register(); #ifdef CONFIG_PARTITIONS efi_disk_register(); #endif diff --git a/include/efi_loader.h b/include/efi_loader.h index 342e960d145..2abb6b87e17 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -26,7 +26,7 @@ extern struct efi_runtime_services efi_runtime_services; extern struct efi_system_table systab; extern const struct efi_simple_text_output_protocol efi_con_out; -extern const struct efi_simple_input_interface efi_con_in; +extern struct efi_simple_input_interface efi_con_in; extern const struct efi_console_control_protocol efi_console_control; extern const struct efi_device_path_to_text_protocol efi_device_path_to_text; @@ -90,6 +90,8 @@ struct efi_event { /* This list contains all UEFI objects we know of */ extern struct list_head efi_obj_list; +/* Called by bootefi to make console interface available */ +int efi_console_register(void); /* Called by bootefi to make all disk storage accessible as EFI objects */ int efi_disk_register(void); /* Called by bootefi to make GOP (graphical) interface available */ @@ -125,6 +127,8 @@ efi_status_t efi_create_event(enum efi_event_type type, UINTN notify_tpl, /* Call this to set a timer */ efi_status_t efi_set_timer(struct efi_event *event, int type, uint64_t trigger_time); +/* Call this to signal an event */ +void efi_signal_event(struct efi_event *event); /* Generic EFI memory allocator, call this to get memory */ void *efi_alloc(uint64_t len, int memory_type); diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 4cd06b3c4c2..b8dfceae0c0 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -81,7 +81,7 @@ efi_status_t efi_exit_func(efi_status_t ret) return ret; } -static void efi_signal_event(struct efi_event *event) +void efi_signal_event(struct efi_event *event) { if (event->signaled) return; diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c index 8ef7326fef2..dbe98ac08b8 100644 --- a/lib/efi_loader/efi_console.c +++ b/lib/efi_loader/efi_console.c @@ -421,8 +421,46 @@ static efi_status_t EFIAPI efi_cin_read_key_stroke( return EFI_EXIT(EFI_SUCCESS); } -const struct efi_simple_input_interface efi_con_in = { +struct efi_simple_input_interface efi_con_in = { .reset = efi_cin_reset, .read_key_stroke = efi_cin_read_key_stroke, .wait_for_key = NULL, }; + +static struct efi_event *console_timer_event; + +static void efi_key_notify(struct efi_event *event, void *context) +{ +} + +static void efi_console_timer_notify(struct efi_event *event, void *context) +{ + EFI_ENTRY("%p, %p", event, context); + if (tstc()) + efi_signal_event(efi_con_in.wait_for_key); + EFI_EXIT(EFI_SUCCESS); +} + +/* This gets called from do_bootefi_exec(). */ +int efi_console_register(void) +{ + efi_status_t r; + r = efi_create_event(EVT_NOTIFY_WAIT, TPL_CALLBACK, + efi_key_notify, NULL, &efi_con_in.wait_for_key); + if (r != EFI_SUCCESS) { + printf("ERROR: Failed to register WaitForKey event\n"); + return r; + } + r = efi_create_event(EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_CALLBACK, + efi_console_timer_notify, NULL, + &console_timer_event); + if (r != EFI_SUCCESS) { + printf("ERROR: Failed to register console event\n"); + return r; + } + /* 5000 ns cycle is sufficient for 2 MBaud */ + r = efi_set_timer(console_timer_event, EFI_TIMER_PERIODIC, 50); + if (r != EFI_SUCCESS) + printf("ERROR: Failed to set console timer\n"); + return r; +} -- cgit v1.3.1 From 3e433e960887a480f520d4b82ff8d3df3e037ffb Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Mon, 24 Jul 2017 07:59:09 -0400 Subject: efi_loader: EFI file paths should be DOS style shim.efi, for example, actually tries to parse this, but is expecting backslashes. Signed-off-by: Rob Clark Signed-off-by: Alexander Graf --- cmd/bootefi.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'cmd') diff --git a/cmd/bootefi.c b/cmd/bootefi.c index e9f14d54af3..954245740b8 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -339,7 +339,7 @@ void efi_set_bootdev(const char *dev, const char *devnr, const char *path) { __maybe_unused struct blk_desc *desc; char devname[32] = { 0 }; /* dp->str is u16[32] long */ - char *colon; + char *colon, *s; #if defined(CONFIG_BLK) || CONFIG_IS_ENABLED(ISO_PARTITION) desc = blk_get_dev(dev, simple_strtol(devnr, NULL, 10)); @@ -384,5 +384,9 @@ void efi_set_bootdev(const char *dev, const char *devnr, const char *path) } else { snprintf(devname, sizeof(devname), "%s", path); } + /* DOS style file path: */ + s = devname; + while ((s = strchr(s, '/'))) + *s++ = '\\'; ascii2unicode(bootefi_image_path[0].str, devname); } -- cgit v1.3.1 From ca9193d2b163cd274144edddd29be20cdb5f99a3 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Fri, 21 Jul 2017 15:00:27 -0400 Subject: efi_loader: gop: fixes for CONFIG_DM_VIDEO without CONFIG_LCD Make EFI GOP support work with DM_VIDEO but without legacy LCD. Signed-off-by: Rob Clark Signed-off-by: Alexander Graf --- cmd/bootefi.c | 2 +- lib/efi_loader/Makefile | 1 + lib/efi_loader/efi_gop.c | 7 ++++++- 3 files changed, 8 insertions(+), 2 deletions(-) (limited to 'cmd') diff --git a/cmd/bootefi.c b/cmd/bootefi.c index 954245740b8..b6dedec463b 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -230,7 +230,7 @@ static unsigned long do_bootefi_exec(void *efi, void *fdt) #ifdef CONFIG_PARTITIONS efi_disk_register(); #endif -#ifdef CONFIG_LCD +#if defined(CONFIG_LCD) || defined(CONFIG_DM_VIDEO) efi_gop_register(); #endif #ifdef CONFIG_NET diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile index 3fc2371896c..30bf343a365 100644 --- a/lib/efi_loader/Makefile +++ b/lib/efi_loader/Makefile @@ -17,6 +17,7 @@ obj-$(CONFIG_CMD_BOOTEFI_HELLO) += helloworld_efi.o obj-y += efi_image_loader.o efi_boottime.o efi_runtime.o efi_console.o obj-y += efi_memory.o efi_device_path_to_text.o obj-$(CONFIG_LCD) += efi_gop.o +obj-$(CONFIG_DM_VIDEO) += efi_gop.o obj-$(CONFIG_PARTITIONS) += efi_disk.o obj-$(CONFIG_NET) += efi_net.o obj-$(CONFIG_GENERATE_SMBIOS_TABLE) += efi_smbios.o diff --git a/lib/efi_loader/efi_gop.c b/lib/efi_loader/efi_gop.c index db1fd18a348..806cfaeea18 100644 --- a/lib/efi_loader/efi_gop.c +++ b/lib/efi_loader/efi_gop.c @@ -28,6 +28,7 @@ struct efi_gop_obj { struct efi_gop_mode mode; /* Fields we only have acces to during init */ u32 bpix; + void *fb; }; static efi_status_t EFIAPI gop_query_mode(struct efi_gop *this, u32 mode_number, @@ -71,7 +72,7 @@ static efi_status_t EFIAPI gop_blt(struct efi_gop *this, void *buffer, if (operation != EFI_BLT_BUFFER_TO_VIDEO) return EFI_EXIT(EFI_INVALID_PARAMETER); - fb = (void*)gd->fb_base; + fb = gopobj->fb; line_len16 = gopobj->info.width * sizeof(u16); line_len32 = gopobj->info.width * sizeof(u32); @@ -130,6 +131,7 @@ int efi_gop_register(void) struct efi_gop_obj *gopobj; u32 bpix, col, row; u64 fb_base, fb_size; + void *fb; #ifdef CONFIG_DM_VIDEO struct udevice *vdev; @@ -144,6 +146,7 @@ int efi_gop_register(void) row = video_get_ysize(vdev); fb_base = (uintptr_t)priv->fb; fb_size = priv->fb_size; + fb = priv->fb; #else int line_len; @@ -152,6 +155,7 @@ int efi_gop_register(void) row = panel_info.vl_row; fb_base = gd->fb_base; fb_size = lcd_get_size(&line_len); + fb = gd->fb_base; #endif switch (bpix) { @@ -200,6 +204,7 @@ int efi_gop_register(void) gopobj->info.pixels_per_scanline = col; gopobj->bpix = bpix; + gopobj->fb = fb; /* Hook up to the device list */ list_add_tail(&gopobj->parent.link, &efi_obj_list); -- cgit v1.3.1 From 7cbc12415dad707b94d755311126059e5cdc65e3 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Wed, 19 Jul 2017 19:37:22 +0200 Subject: efi_loader: initalize EFI object list only once If several EFI applications are executed in sequence we want to keep the content of the EFI object list. Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- cmd/bootefi.c | 62 ++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 36 insertions(+), 26 deletions(-) (limited to 'cmd') diff --git a/cmd/bootefi.c b/cmd/bootefi.c index b6dedec463b..9526f6c60d7 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -20,6 +20,8 @@ DECLARE_GLOBAL_DATA_PTR; +static uint8_t efi_obj_list_initalized; + /* * When booting using the "bootefi" command, we don't know which * physical device the file came from. So we create a pseudo-device @@ -104,6 +106,38 @@ static struct efi_object bootefi_device_obj = { }, }; +/* Initialize and populate EFI object list */ +static void efi_init_obj_list(void) +{ + efi_obj_list_initalized = 1; + + list_add_tail(&loaded_image_info_obj.link, &efi_obj_list); + list_add_tail(&bootefi_device_obj.link, &efi_obj_list); + efi_console_register(); +#ifdef CONFIG_PARTITIONS + efi_disk_register(); +#endif +#if defined(CONFIG_LCD) || defined(CONFIG_DM_VIDEO) + efi_gop_register(); +#endif +#ifdef CONFIG_NET + void *nethandle = loaded_image_info.device_handle; + efi_net_register(&nethandle); + + if (!memcmp(bootefi_device_path[0].str, "N\0e\0t", 6)) + loaded_image_info.device_handle = nethandle; + else + loaded_image_info.device_handle = bootefi_device_path; +#endif +#ifdef CONFIG_GENERATE_SMBIOS_TABLE + efi_smbios_register(); +#endif + + /* Initialize EFI runtime services */ + efi_reset_system_init(); + efi_get_time_init(); +} + static void *copy_fdt(void *fdt) { u64 fdt_size = fdt_totalsize(fdt); @@ -223,32 +257,8 @@ static unsigned long do_bootefi_exec(void *efi, void *fdt) return -ENOENT; /* Initialize and populate EFI object list */ - INIT_LIST_HEAD(&efi_obj_list); - list_add_tail(&loaded_image_info_obj.link, &efi_obj_list); - list_add_tail(&bootefi_device_obj.link, &efi_obj_list); - efi_console_register(); -#ifdef CONFIG_PARTITIONS - efi_disk_register(); -#endif -#if defined(CONFIG_LCD) || defined(CONFIG_DM_VIDEO) - efi_gop_register(); -#endif -#ifdef CONFIG_NET - void *nethandle = loaded_image_info.device_handle; - efi_net_register(&nethandle); - - if (!memcmp(bootefi_device_path[0].str, "N\0e\0t", 6)) - loaded_image_info.device_handle = nethandle; - else - loaded_image_info.device_handle = bootefi_device_path; -#endif -#ifdef CONFIG_GENERATE_SMBIOS_TABLE - efi_smbios_register(); -#endif - - /* Initialize EFI runtime services */ - efi_reset_system_init(); - efi_get_time_init(); + if (!efi_obj_list_initalized) + efi_init_obj_list(); /* Call our payload! */ debug("%s:%d Jumping to 0x%lx\n", __func__, __LINE__, (long)entry); -- cgit v1.3.1 From f4f9993f7ed0384f110324bb048a6cafb535378a Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Wed, 26 Jul 2017 13:41:05 +0200 Subject: efi_loader: Fix configuration table override Before commit 7cbc12415d ("efi_loader: initalize EFI object list only once") we recreated the world on every bootefi invocation. That included the object tree as well as the configuration tables. Now however we don't recreate them, which means we must not explicitly override the configuration tables, as otherwise we may lose our SMBIOS table from the configuration table list on second bootefi invocation. This patch makes bootefi call our normal configuration table modification APIs to add/remove the FDT instead of recreating all tables from scratch. That way the SMBIOS table gets preserved across multiple invocations. Signed-off-by: Alexander Graf --- cmd/bootefi.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'cmd') diff --git a/cmd/bootefi.c b/cmd/bootefi.c index 9526f6c60d7..d20775eccd9 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -215,6 +215,7 @@ static unsigned long do_bootefi_exec(void *efi, void *fdt) ulong (*entry)(void *image_handle, struct efi_system_table *st) asmlinkage; ulong fdt_pages, fdt_size, fdt_start, fdt_end; + const efi_guid_t fdt_guid = EFI_FDT_GUID; bootm_headers_t img = { 0 }; /* @@ -233,9 +234,7 @@ static unsigned long do_bootefi_exec(void *efi, void *fdt) } /* Link to it in the efi tables */ - systab.tables[0].guid = EFI_FDT_GUID; - systab.tables[0].table = fdt; - systab.nr_tables = 1; + efi_install_configuration_table(&fdt_guid, fdt); /* And reserve the space in the memory map */ fdt_start = ((ulong)fdt) & ~EFI_PAGE_MASK; @@ -248,7 +247,7 @@ static unsigned long do_bootefi_exec(void *efi, void *fdt) EFI_BOOT_SERVICES_DATA, true); } else { printf("WARNING: Invalid device tree, expect boot to fail\n"); - systab.nr_tables = 0; + efi_install_configuration_table(&fdt_guid, NULL); } /* Load the EFI payload */ -- cgit v1.3.1