efi_loader: EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE
authorHeinrich Schuchardt <xypron.glpk@gmx.de>
Thu, 11 Jul 2019 18:15:09 +0000 (20:15 +0200)
committerHeinrich Schuchardt <xypron.glpk@gmx.de>
Tue, 16 Jul 2019 22:17:16 +0000 (22:17 +0000)
Implement the EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.

This requires allocating the event and the event list from runtime data.

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
lib/efi_loader/efi_boottime.c
lib/efi_loader/efi_runtime.c

index c2f89805c76776fe4a2bff2f9d6aea1a9b882469..62e499467179e9773bc915742ca8ab173cf4f38d 100644 (file)
@@ -25,7 +25,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);
@@ -650,6 +650,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 +664,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 +677,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 +989,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);
 }
 
@@ -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);
@@ -1971,6 +1978,12 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle,
        /* 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 */
index 94765569b67e5d03fffea8ccd18855c28609fadb..9f4ba2f9772da98a728c2b669cf1039df9266316 100644 (file)
@@ -391,8 +391,10 @@ efi_status_t __weak __efi_runtime EFIAPI efi_set_time(struct efi_time *time)
  */
 static bool efi_is_runtime_service_pointer(void *p)
 {
-       return p >= (void *)&efi_runtime_services.get_time &&
-              p <= (void *)&efi_runtime_services.query_variable_info;
+       return (p >= (void *)&efi_runtime_services.get_time &&
+               p <= (void *)&efi_runtime_services.query_variable_info) ||
+              p == (void *)&efi_events.prev ||
+              p == (void *)&efi_events.next;
 }
 
 /**
@@ -577,6 +579,7 @@ static efi_status_t EFIAPI efi_set_virtual_address_map(
        int n = memory_map_size / descriptor_size;
        int i;
        int rt_code_sections = 0;
+       struct efi_event *event;
 
        EFI_ENTRY("%lx %lx %x %p", memory_map_size, descriptor_size,
                  descriptor_version, virtmap);
@@ -610,6 +613,13 @@ static efi_status_t EFIAPI efi_set_virtual_address_map(
                return EFI_EXIT(EFI_INVALID_PARAMETER);
        }
 
+       /* Notify EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE */
+       list_for_each_entry(event, &efi_events, link) {
+               if (event->notify_function)
+                       EFI_CALL_VOID(event->notify_function(
+                                       event, event->notify_context));
+       }
+
        /* Rebind mmio pointers */
        for (i = 0; i < n; i++) {
                struct efi_mem_desc *map = (void*)virtmap +