summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2019-06-05 15:53:18 -0400
committerTom Rini <trini@konsulko.com>2019-06-05 15:53:18 -0400
commitdbbb1c43f26cb28b64df80b72fffbaf2801e8a30 (patch)
tree6f60c48458e4fb975b0e602cff637c2e65a270cf
parent2253e40caef5b45bcae2ccdb238f9cf037eefc0b (diff)
parent4b27a761321fd17536e02644d0ec0373150eb570 (diff)
Merge tag 'efi-2019-07-rc4-2' of git://git.denx.de/u-boot-efi
Pull request for UEFI sub-system for v2019.07-rc4-2 Support for managing the non-volatile attribute of UEFI variables is added though we do not have a backend for persistence yet. Error messages for changes of UEFI variables are provided. UEFI boottime service implementations are corrected.
-rw-r--r--arch/arm/mach-rockchip/rk_timer.c7
-rw-r--r--cmd/efidebug.c3
-rw-r--r--cmd/nvedit.c3
-rw-r--r--cmd/nvedit_efi.c15
-rw-r--r--include/time.h9
-rw-r--r--lib/efi_loader/efi_bootmgr.c3
-rw-r--r--lib/efi_loader/efi_boottime.c55
-rw-r--r--lib/efi_loader/efi_console.c1
-rw-r--r--lib/efi_loader/efi_memory.c11
-rw-r--r--lib/efi_loader/efi_variable.c12
-rw-r--r--lib/time.c2
11 files changed, 100 insertions, 21 deletions
diff --git a/arch/arm/mach-rockchip/rk_timer.c b/arch/arm/mach-rockchip/rk_timer.c
index f20e64f48e..29d379fa0a 100644
--- a/arch/arm/mach-rockchip/rk_timer.c
+++ b/arch/arm/mach-rockchip/rk_timer.c
@@ -20,13 +20,6 @@ static uint64_t rockchip_get_ticks(void)
return timebase_h << 32 | timebase_l;
}
-static uint64_t usec_to_tick(unsigned int usec)
-{
- uint64_t tick = usec;
- tick *= CONFIG_SYS_TIMER_RATE / (1000 * 1000);
- return tick;
-}
-
void rockchip_udelay(unsigned int usec)
{
uint64_t tmp;
diff --git a/cmd/efidebug.c b/cmd/efidebug.c
index c4ac9dd634..e657226254 100644
--- a/cmd/efidebug.c
+++ b/cmd/efidebug.c
@@ -558,6 +558,7 @@ static int do_efi_boot_add(cmd_tbl_t *cmdtp, int flag,
}
ret = EFI_CALL(RT->set_variable(var_name16, &guid,
+ EFI_VARIABLE_NON_VOLATILE |
EFI_VARIABLE_BOOTSERVICE_ACCESS |
EFI_VARIABLE_RUNTIME_ACCESS,
size, data));
@@ -909,6 +910,7 @@ static int do_efi_boot_next(cmd_tbl_t *cmdtp, int flag,
guid = efi_global_variable_guid;
size = sizeof(u16);
ret = EFI_CALL(RT->set_variable(L"BootNext", &guid,
+ EFI_VARIABLE_NON_VOLATILE |
EFI_VARIABLE_BOOTSERVICE_ACCESS |
EFI_VARIABLE_RUNTIME_ACCESS,
size, &bootnext));
@@ -964,6 +966,7 @@ static int do_efi_boot_order(cmd_tbl_t *cmdtp, int flag,
guid = efi_global_variable_guid;
ret = EFI_CALL(RT->set_variable(L"BootOrder", &guid,
+ EFI_VARIABLE_NON_VOLATILE |
EFI_VARIABLE_BOOTSERVICE_ACCESS |
EFI_VARIABLE_RUNTIME_ACCESS,
size, bootorder));
diff --git a/cmd/nvedit.c b/cmd/nvedit.c
index 24a6cf7824..52c242b4f6 100644
--- a/cmd/nvedit.c
+++ b/cmd/nvedit.c
@@ -1344,8 +1344,9 @@ U_BOOT_CMD_COMPLETE(
setenv, CONFIG_SYS_MAXARGS, 0, do_env_set,
"set environment variables",
#if defined(CONFIG_CMD_NVEDIT_EFI)
- "-e name [value ...]\n"
+ "-e [-nv] name [value ...]\n"
" - set UEFI variable 'name' to 'value' ...'\n"
+ " 'nv' option makes the variable non-volatile\n"
" - delete UEFI variable 'name' if 'value' not specified\n"
#endif
"setenv [-f] name value ...\n"
diff --git a/cmd/nvedit_efi.c b/cmd/nvedit_efi.c
index ff8eaa1aad..60a8ac84c8 100644
--- a/cmd/nvedit_efi.c
+++ b/cmd/nvedit_efi.c
@@ -349,6 +349,7 @@ int do_env_set_efi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
u16 *var_name16 = NULL, *p;
size_t len;
efi_guid_t guid;
+ u32 attributes;
efi_status_t ret;
if (argc == 1)
@@ -362,6 +363,16 @@ int do_env_set_efi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
return CMD_RET_FAILURE;
}
+ attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_RUNTIME_ACCESS;
+ if (!strcmp(argv[1], "-nv")) {
+ attributes |= EFI_VARIABLE_NON_VOLATILE;
+ argc--;
+ argv++;
+ if (argc == 1)
+ return CMD_RET_SUCCESS;
+ }
+
var_name = argv[1];
if (argc == 2) {
/* delete */
@@ -391,9 +402,7 @@ int do_env_set_efi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
utf8_utf16_strncpy(&p, var_name, len + 1);
guid = efi_global_variable_guid;
- ret = EFI_CALL(efi_set_variable(var_name16, &guid,
- EFI_VARIABLE_BOOTSERVICE_ACCESS |
- EFI_VARIABLE_RUNTIME_ACCESS,
+ ret = EFI_CALL(efi_set_variable(var_name16, &guid, attributes,
size, value));
if (ret == EFI_SUCCESS) {
ret = CMD_RET_SUCCESS;
diff --git a/include/time.h b/include/time.h
index 9fd0d73fb4..1e9b369be7 100644
--- a/include/time.h
+++ b/include/time.h
@@ -4,6 +4,7 @@
#define _TIME_H
#include <linux/typecheck.h>
+#include <linux/types.h>
unsigned long get_timer(unsigned long base);
@@ -21,6 +22,14 @@ unsigned long timer_get_us(void);
*/
void timer_test_add_offset(unsigned long offset);
+/**
+ * usec_to_tick() - convert microseconds to clock ticks
+ *
+ * @usec: duration in microseconds
+ * Return: duration in clock ticks
+ */
+uint64_t usec_to_tick(unsigned long usec);
+
/*
* These inlines deal with timer wrapping correctly. You are
* strongly encouraged to use them
diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c
index 43791422c8..b2102c5b5a 100644
--- a/lib/efi_loader/efi_bootmgr.c
+++ b/lib/efi_loader/efi_bootmgr.c
@@ -210,7 +210,8 @@ efi_status_t efi_bootmgr_load(efi_handle_t *handle)
ret = EFI_CALL(efi_set_variable(
L"BootNext",
(efi_guid_t *)&efi_global_variable_guid,
- 0, 0, &bootnext));
+ EFI_VARIABLE_NON_VOLATILE, 0,
+ &bootnext));
/* load BootNext */
if (ret == EFI_SUCCESS) {
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index 5c6bc691a5..7d1d6e9213 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -1153,11 +1153,15 @@ static efi_status_t efi_get_drivers(efi_handle_t handle,
++count;
}
}
+ *number_of_drivers = 0;
+ if (!count) {
+ *driver_handle_buffer = NULL;
+ return EFI_SUCCESS;
+ }
/*
* Create buffer. In case of duplicate driver assignments the buffer
* will be too large. But that does not harm.
*/
- *number_of_drivers = 0;
*driver_handle_buffer = calloc(count, sizeof(efi_handle_t));
if (!*driver_handle_buffer)
return EFI_OUT_OF_RESOURCES;
@@ -1213,7 +1217,8 @@ static efi_status_t efi_disconnect_all_drivers
&driver_handle_buffer);
if (ret != EFI_SUCCESS)
return ret;
-
+ if (!number_of_drivers)
+ return EFI_SUCCESS;
ret = EFI_NOT_FOUND;
while (number_of_drivers) {
r = EFI_CALL(efi_disconnect_controller(
@@ -1985,8 +1990,14 @@ out:
*/
static efi_status_t EFIAPI efi_stall(unsigned long microseconds)
{
+ u64 end_tick;
+
EFI_ENTRY("%ld", microseconds);
- udelay(microseconds);
+
+ end_tick = get_ticks() + usec_to_tick(microseconds);
+ while (get_ticks() < end_tick)
+ efi_timer_check();
+
return EFI_EXIT(EFI_SUCCESS);
}
@@ -2868,12 +2879,46 @@ efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle,
* @image_obj: handle of the loaded image
* @loaded_image_protocol: loaded image protocol
*/
-static void efi_delete_image(struct efi_loaded_image_obj *image_obj,
- struct efi_loaded_image *loaded_image_protocol)
+static efi_status_t efi_delete_image
+ (struct efi_loaded_image_obj *image_obj,
+ struct efi_loaded_image *loaded_image_protocol)
{
+ struct efi_object *efiobj;
+ efi_status_t r, ret = EFI_SUCCESS;
+
+close_next:
+ list_for_each_entry(efiobj, &efi_obj_list, link) {
+ struct efi_handler *protocol;
+
+ list_for_each_entry(protocol, &efiobj->protocols, link) {
+ struct efi_open_protocol_info_item *info;
+
+ list_for_each_entry(info, &protocol->open_infos, link) {
+ if (info->info.agent_handle !=
+ (efi_handle_t)image_obj)
+ continue;
+ r = EFI_CALL(efi_close_protocol
+ (efiobj, protocol->guid,
+ info->info.agent_handle,
+ info->info.controller_handle
+ ));
+ if (r != EFI_SUCCESS)
+ ret = r;
+ /*
+ * Closing protocols may results in further
+ * items being deleted. To play it safe loop
+ * over all elements again.
+ */
+ goto close_next;
+ }
+ }
+ }
+
efi_free_pages((uintptr_t)loaded_image_protocol->image_base,
efi_size_in_pages(loaded_image_protocol->image_size));
efi_delete_handle(&image_obj->header);
+
+ return ret;
}
/**
diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c
index b2cb18e6d6..3b7578f3aa 100644
--- a/lib/efi_loader/efi_console.c
+++ b/lib/efi_loader/efi_console.c
@@ -430,6 +430,7 @@ static efi_status_t EFIAPI efi_cout_enable_cursor(
EFI_ENTRY("%p, %d", this, enable);
printf(ESC"[?25%c", enable ? 'h' : 'l');
+ efi_con_mode.cursor_visible = !!enable;
return EFI_EXIT(EFI_SUCCESS);
}
diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
index 76dcaa48f4..386cf924fe 100644
--- a/lib/efi_loader/efi_memory.c
+++ b/lib/efi_loader/efi_memory.c
@@ -230,6 +230,7 @@ uint64_t efi_add_memory_map(uint64_t start, uint64_t pages, int memory_type,
struct efi_mem_list *newlist;
bool carve_again;
uint64_t carved_pages = 0;
+ struct efi_event *evt;
EFI_PRINT("%s: 0x%llx 0x%llx %d %s\n", __func__,
start, pages, memory_type, overlap_only_ram ? "yes" : "no");
@@ -315,6 +316,16 @@ uint64_t efi_add_memory_map(uint64_t start, uint64_t pages, int memory_type,
/* And make sure memory is listed in descending order */
efi_mem_sort();
+ /* Notify that the memory map was changed */
+ list_for_each_entry(evt, &efi_events, link) {
+ if (evt->group &&
+ !guidcmp(evt->group,
+ &efi_guid_event_group_memory_map_change)) {
+ efi_signal_event(evt, false);
+ break;
+ }
+ }
+
return start;
}
diff --git a/lib/efi_loader/efi_variable.c b/lib/efi_loader/efi_variable.c
index 50bc10537f..e56053194d 100644
--- a/lib/efi_loader/efi_variable.c
+++ b/lib/efi_loader/efi_variable.c
@@ -125,6 +125,8 @@ static const char *parse_attr(const char *str, u32 *attrp)
if ((s = prefix(str, "ro"))) {
attr |= READ_ONLY;
+ } else if ((s = prefix(str, "nv"))) {
+ attr |= EFI_VARIABLE_NON_VOLATILE;
} else if ((s = prefix(str, "boot"))) {
attr |= EFI_VARIABLE_BOOTSERVICE_ACCESS;
} else if ((s = prefix(str, "run"))) {
@@ -468,7 +470,7 @@ efi_status_t EFIAPI efi_set_variable(u16 *variable_name,
}
}
- val = malloc(2 * data_size + strlen("{ro,run,boot}(blob)") + 1);
+ val = malloc(2 * data_size + strlen("{ro,run,boot,nv}(blob)") + 1);
if (!val) {
ret = EFI_OUT_OF_RESOURCES;
goto out;
@@ -480,12 +482,16 @@ efi_status_t EFIAPI efi_set_variable(u16 *variable_name,
* store attributes
* TODO: several attributes are not supported
*/
- attributes &= (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS);
+ attributes &= (EFI_VARIABLE_NON_VOLATILE |
+ EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_RUNTIME_ACCESS);
s += sprintf(s, "{");
while (attributes) {
u32 attr = 1 << (ffs(attributes) - 1);
- if (attr == EFI_VARIABLE_BOOTSERVICE_ACCESS)
+ if (attr == EFI_VARIABLE_NON_VOLATILE)
+ s += sprintf(s, "nv");
+ else if (attr == EFI_VARIABLE_BOOTSERVICE_ACCESS)
s += sprintf(s, "boot");
else if (attr == EFI_VARIABLE_RUNTIME_ACCESS)
s += sprintf(s, "run");
diff --git a/lib/time.c b/lib/time.c
index 9c55da6f1b..f5751ab162 100644
--- a/lib/time.c
+++ b/lib/time.c
@@ -139,7 +139,7 @@ unsigned long __weak notrace timer_get_us(void)
return tick_to_time(get_ticks() * 1000);
}
-static uint64_t usec_to_tick(unsigned long usec)
+uint64_t usec_to_tick(unsigned long usec)
{
uint64_t tick = usec;
tick *= get_tbclk();