efi_loader: EFI_PXE_BASE_CODE_PROTOCOL stub
[oweals/u-boot.git] / lib / efi_loader / efi_boottime.c
index bf2df80c838d7e56fd3cce5f81e38e6a58a195fe..b9bff894cbba0be5fc43c515fb2e7f6ef0a25d04 100644 (file)
@@ -8,7 +8,6 @@
 #include <common.h>
 #include <div64.h>
 #include <efi_loader.h>
-#include <environment.h>
 #include <malloc.h>
 #include <linux/libfdt_env.h>
 #include <u-boot/crc.h>
@@ -25,7 +24,7 @@ static efi_uintn_t efi_tpl = TPL_APPLICATION;
 LIST_HEAD(efi_obj_list);
 
 /* List of all events */
-LIST_HEAD(efi_events);
+__efi_runtime_data LIST_HEAD(efi_events);
 
 /* List of queued events */
 LIST_HEAD(efi_event_queue);
@@ -39,14 +38,6 @@ LIST_HEAD(efi_register_notify_events);
 /* Handle of the currently executing image */
 static efi_handle_t current_image;
 
-/*
- * If we're running on nasty systems (32bit ARM booting into non-EFI Linux)
- * we need to do trickery with caches. Since we don't want to break the EFI
- * aware boot path, only apply hacks when loading exiting directly (breaking
- * direct Linux EFI booting along the way - oh well).
- */
-static bool efi_is_direct_boot = true;
-
 #ifdef CONFIG_ARM
 /*
  * The "gd" pointer lives in a register on ARM and AArch64 that we declare
@@ -596,7 +587,7 @@ efi_status_t efi_remove_all_protocols(const efi_handle_t handle)
 /**
  * efi_delete_handle() - delete handle
  *
- * @obj: handle to delete
+ * @handle: handle to delete
  */
 void efi_delete_handle(efi_handle_t handle)
 {
@@ -628,6 +619,7 @@ static efi_status_t efi_is_event(const struct efi_event *event)
 
 /**
  * efi_create_event() - create an event
+ *
  * @type:            type of the event to create
  * @notify_tpl:      task priority level of the event
  * @notify_function: notification function of the event
@@ -650,6 +642,8 @@ efi_status_t efi_create_event(uint32_t type, efi_uintn_t notify_tpl,
                              struct efi_event **event)
 {
        struct efi_event *evt;
+       efi_status_t ret;
+       int pool_type;
 
        if (event == NULL)
                return EFI_INVALID_PARAMETER;
@@ -662,7 +656,10 @@ efi_status_t efi_create_event(uint32_t type, efi_uintn_t notify_tpl,
        case EVT_NOTIFY_WAIT:
        case EVT_TIMER | EVT_NOTIFY_WAIT:
        case EVT_SIGNAL_EXIT_BOOT_SERVICES:
+               pool_type = EFI_BOOT_SERVICES_DATA;
+               break;
        case EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE:
+               pool_type = EFI_RUNTIME_SERVICES_DATA;
                break;
        default:
                return EFI_INVALID_PARAMETER;
@@ -672,9 +669,11 @@ efi_status_t efi_create_event(uint32_t type, efi_uintn_t notify_tpl,
            (!notify_function || is_valid_tpl(notify_tpl) != EFI_SUCCESS))
                return EFI_INVALID_PARAMETER;
 
-       evt = calloc(1, sizeof(struct efi_event));
-       if (!evt)
-               return EFI_OUT_OF_RESOURCES;
+       ret = efi_allocate_pool(pool_type, sizeof(struct efi_event),
+                               (void **)&evt);
+       if (ret != EFI_SUCCESS)
+               return ret;
+       memset(evt, 0, sizeof(struct efi_event));
        evt->type = type;
        evt->notify_tpl = notify_tpl;
        evt->notify_function = notify_function;
@@ -982,7 +981,7 @@ static efi_status_t EFIAPI efi_close_event(struct efi_event *event)
                list_del(&event->queue_link);
 
        list_del(&event->link);
-       free(event);
+       efi_free_pool(event);
        return EFI_EXIT(EFI_SUCCESS);
 }
 
@@ -1411,9 +1410,9 @@ out:
 
 /**
  * efi_search() - determine if an EFI handle implements a protocol
+ *
  * @search_type: selection criterion
  * @protocol:    GUID of the protocol
- * @search_key:  registration key
  * @handle:      handle
  *
  * See the documentation of the LocateHandle service in the UEFI specification.
@@ -1675,7 +1674,7 @@ static efi_status_t EFIAPI efi_install_configuration_table_ext(efi_guid_t *guid,
  * Initialize a loaded_image_info and loaded_image_info object with correct
  * protocols, boot-device, etc.
  *
- * In case of an error *handle_ptr and *info_ptr are set to NULL and an error
+ * In case of an error \*handle_ptr and \*info_ptr are set to NULL and an error
  * code is returned.
  *
  * @device_path:       device path of the loaded image
@@ -1903,13 +1902,21 @@ error:
  */
 static void efi_exit_caches(void)
 {
-#if defined(CONFIG_ARM) && !defined(CONFIG_ARM64)
+#if defined(CONFIG_EFI_GRUB_ARM32_WORKAROUND)
        /*
-        * Grub on 32bit ARM needs to have caches disabled before jumping into
-        * a zImage, but does not know of all cache layers. Give it a hand.
+        * Boooting Linux via GRUB prior to version 2.04 fails on 32bit ARM if
+        * caches are enabled.
+        *
+        * TODO:
+        * According to the UEFI spec caches that can be managed via CP15
+        * operations should be enabled. Caches requiring platform information
+        * to manage should be disabled. This should not happen in
+        * ExitBootServices() but before invoking any UEFI binary is invoked.
+        *
+        * We want to keep the current workaround while GRUB prior to version
+        * 2.04 is still in use.
         */
-       if (efi_is_direct_boot)
-               cleanup_before_linux();
+       cleanup_before_linux();
 #endif
 }
 
@@ -1932,7 +1939,7 @@ static void efi_exit_caches(void)
 static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle,
                                                  efi_uintn_t map_key)
 {
-       struct efi_event *evt;
+       struct efi_event *evt, *next_event;
        efi_status_t ret = EFI_SUCCESS;
 
        EFI_ENTRY("%p, %zx", image_handle, map_key);
@@ -1968,10 +1975,20 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle,
        /* Make sure that notification functions are not called anymore */
        efi_tpl = TPL_HIGH_LEVEL;
 
-       /* TODO: Should persist EFI variables here */
+       /* Notify variable services */
+       efi_variables_boot_exit_notify();
+
+       /* Remove all events except EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE */
+       list_for_each_entry_safe(evt, next_event, &efi_events, link) {
+               if (evt->type != EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE)
+                       list_del(&evt->link);
+       }
 
        board_quiesce_devices();
 
+       /* Patch out unsupported runtime function */
+       efi_runtime_detach();
+
        /* Fix up caches for EFI payloads if necessary */
        efi_exit_caches();
 
@@ -2875,8 +2892,6 @@ efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle,
        if (ret != EFI_SUCCESS)
                return EFI_EXIT(EFI_INVALID_PARAMETER);
 
-       efi_is_direct_boot = false;
-
        image_obj->exit_data_size = exit_data_size;
        image_obj->exit_data = exit_data;
 
@@ -3030,9 +3045,9 @@ out:
 /**
  * efi_update_exit_data() - fill exit data parameters of StartImage()
  *
- * @image_obj          image handle
- * @exit_data_size     size of the exit data buffer
- * @exit_data          buffer with data returned by UEFI payload
+ * @image_obj:         image handle
+ * @exit_data_size:    size of the exit data buffer
+ * @exit_data:         buffer with data returned by UEFI payload
  * Return:             status code
  */
 static efi_status_t efi_update_exit_data(struct efi_loaded_image_obj *image_obj,