Merge tag 'efi-2019-07-rc4-2' of git://git.denx.de/u-boot-efi
authorTom Rini <trini@konsulko.com>
Wed, 5 Jun 2019 19:53:18 +0000 (15:53 -0400)
committerTom Rini <trini@konsulko.com>
Wed, 5 Jun 2019 19:53:18 +0000 (15:53 -0400)
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.

arch/arm/mach-rockchip/rk_timer.c
cmd/efidebug.c
cmd/nvedit.c
cmd/nvedit_efi.c
include/time.h
lib/efi_loader/efi_bootmgr.c
lib/efi_loader/efi_boottime.c
lib/efi_loader/efi_console.c
lib/efi_loader/efi_memory.c
lib/efi_loader/efi_variable.c
lib/time.c

index f20e64f48ece7ceb6d937286ed174eb7afd87593..29d379fa0abc11ea3ef1b055cd448cb868393d73 100644 (file)
@@ -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;
index c4ac9dd634e2628fe19472a47fd435d0114fae7a..e6572262545557ac02b3d0ad3555f11a93a436b0 100644 (file)
@@ -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));
index 24a6cf7824ad2816b723d33a3a24537564b2bc77..52c242b4f62277e8bff19a9536d32179b949f08e 100644 (file)
@@ -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"
index ff8eaa1aad2df4c2b23678daee3f52017e44b38d..60a8ac84c8113a5e51a04ca312a17f52354b9dc5 100644 (file)
@@ -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;
index 9fd0d73fb4e4342dc7650c1b4dcb114772b257ea..1e9b369be7cb029f0eafa6ad9180affe73b36b6e 100644 (file)
@@ -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
index 43791422c8191d3081e0b71fdbe96abb91ab7779..b2102c5b5af24697e65aa9b3a97f5295f657751c 100644 (file)
@@ -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) {
index 5c6bc691a5c4154214b05a5245444bf0164d1d62..7d1d6e92138ed297251104b5d2f91cdd888875ab 100644 (file)
@@ -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;
 }
 
 /**
index b2cb18e6d67021c194dff39914c5b401a6e1967d..3b7578f3aa4f6d7c218afd3cd3c398f0ec3199a3 100644 (file)
@@ -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);
 }
index 76dcaa48f494dbf95c3ea09a33da520238166b4c..386cf924fe26a3c457c60878de55d5dfcb60e544 100644 (file)
@@ -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;
 }
 
index 50bc10537f404002f6927d1cce0133a797ea9fd2..e56053194daec46642103607904e85ed4f37aa3c 100644 (file)
@@ -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");
index 9c55da6f1b3914adde3bf67107896a962bc29d44..f5751ab162b69643404f37f08d0472b3105824e9 100644 (file)
@@ -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();