summaryrefslogtreecommitdiffstats
path: root/master/jmm/efi-load-drivers-bis
diff options
context:
space:
mode:
Diffstat (limited to 'master/jmm/efi-load-drivers-bis')
-rw-r--r--master/jmm/efi-load-drivers-bis467
1 files changed, 467 insertions, 0 deletions
diff --git a/master/jmm/efi-load-drivers-bis b/master/jmm/efi-load-drivers-bis
new file mode 100644
index 0000000..9cef5f7
--- /dev/null
+++ b/master/jmm/efi-load-drivers-bis
@@ -0,0 +1,467 @@
+diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
+index fa1d0c7..16526d0 100644
+--- a/grub-core/kern/efi/efi.c
++++ b/grub-core/kern/efi/efi.c
+@@ -37,6 +37,10 @@ grub_efi_system_table_t *grub_efi_system_table;
+ static grub_efi_guid_t console_control_guid = GRUB_EFI_CONSOLE_CONTROL_GUID;
+ static grub_efi_guid_t loaded_image_guid = GRUB_EFI_LOADED_IMAGE_GUID;
+ static grub_efi_guid_t device_path_guid = GRUB_EFI_DEVICE_PATH_GUID;
++static grub_efi_guid_t driver_binding_guid = GRUB_EFI_DRIVER_BINDING_GUID;
++static grub_efi_guid_t driver_configuration_guid = GRUB_EFI_DRIVER_CONFIGURATION_GUID;
++static grub_efi_guid_t driver_diagnostics_guid = GRUB_EFI_DRIVER_DIAGNOSTICS_GUID;
++static grub_efi_guid_t component_name_guid = GRUB_EFI_COMPONENT_NAME_GUID;
+
+ void *
+ grub_efi_locate_protocol (grub_efi_guid_t *protocol, void *registration)
+@@ -740,3 +744,303 @@ grub_efi_print_device_path (grub_efi_device_path_t *dp)
+ dp = (grub_efi_device_path_t *) ((char *) dp + len);
+ }
+ }
++
++
++grub_efi_status_t grub_efi_free_pool (void *ptr)
++{
++ grub_efi_boot_services_t *b;
++ b = grub_efi_system_table->boot_services;
++
++ return efi_call_1 (b->free_pool, ptr);
++}
++
++void * grub_efi_allocate_pool (grub_efi_memory_type_t type, grub_efi_uintn_t len)
++{
++ grub_efi_boot_services_t *b;
++ grub_efi_status_t status;
++ void *ret;
++ b = grub_efi_system_table->boot_services;
++
++ status = efi_call_3 (b->allocate_pool, type, len, &ret);
++
++ if (status != GRUB_EFI_SUCCESS)
++ return (void *) 0;
++
++ return ret;
++}
++
++
++static int grub_efi_guid_cmp (grub_efi_guid_t * a, grub_efi_guid_t * b)
++{
++ return grub_memcmp (a, b, sizeof (grub_efi_guid_t));
++}
++
++
++
++grub_efi_status_t
++grub_efi_scan_handle_database (grub_efi_handle_t driver_binding_handle,
++ grub_efi_uint32_t *
++ driver_binding_i,
++ grub_efi_handle_t controller_handle,
++ grub_efi_uint32_t * controller_i,
++ grub_efi_uintn_t * handle_count,
++ grub_efi_handle_t ** handle_buffer,
++ grub_efi_uint32_t ** handle_type)
++{
++ grub_efi_boot_services_t *b;
++ grub_efi_status_t status;
++ grub_efi_uintn_t i, j, k;
++ grub_efi_guid_t **protocol_guid_array;
++ grub_efi_uintn_t array_count;
++ grub_efi_uintn_t protocol_index;
++ grub_efi_open_protocol_information_entry_t *open_info;
++ grub_efi_uintn_t open_info_count;
++ grub_efi_boolean_t driver_binding_i_valid;
++ grub_efi_boolean_t controller_i_valid;
++
++ b = grub_efi_system_table->boot_services;
++
++ driver_binding_i_valid = 0;
++ if (driver_binding_i != NULL)
++ {
++ *driver_binding_i = 0xffffffff;
++ }
++
++ controller_i_valid = 0;
++ if (controller_i != NULL)
++ {
++ *controller_i = 0xffffffff;
++ }
++ *handle_count = 0;
++ *handle_buffer = NULL;
++ *handle_type = NULL;
++
++ //
++ // Retrieve the list of all handles from the handle database
++ //
++ status = efi_call_5 (b->locate_handle_buffer,
++ GRUB_EFI_ALL_HANDLES,
++ NULL, NULL, handle_count, handle_buffer);
++
++ if (status != GRUB_EFI_SUCCESS)
++ goto error;
++
++ *handle_type = grub_malloc (*handle_count * sizeof (grub_efi_uint32_t));
++ if (!*handle_type)
++ goto error;
++
++ for (i = 0; i < *handle_count; i++)
++ {
++
++ //
++ // Assume that the handle type is unknown
++ //
++ (*handle_type)[i] = GRUB_EFI_HANDLE_TYPE_UNKNOWN;
++
++ if (driver_binding_handle != NULL && driver_binding_i != NULL
++ && (*handle_buffer)[i] == driver_binding_handle)
++ {
++ *driver_binding_i = (grub_efi_uint32_t) i;
++ driver_binding_i_valid = 1;
++ }
++
++ if (controller_handle != NULL && controller_i != NULL
++ && (*handle_buffer)[i] == controller_handle)
++ {
++ *controller_i = (grub_efi_uint32_t) i;
++ controller_i_valid = 1;
++ }
++ }
++
++ for (i = 0; i < *handle_count; i++)
++ {
++
++ //
++ // Retrieve the list of all the protocols on each handle
++ //
++ status = efi_call_3 (b->protocols_per_handle,
++ (*handle_buffer)[i],
++ &protocol_guid_array, &array_count);
++
++ if (status != GRUB_EFI_SUCCESS)
++ continue;
++
++ for (protocol_index = 0; protocol_index < array_count; protocol_index++)
++ {
++
++ if (grub_efi_guid_cmp
++ (protocol_guid_array[protocol_index], &loaded_image_guid) == 0)
++ {
++ (*handle_type)[i] |= GRUB_EFI_HANDLE_TYPE_IMAGE_HANDLE;
++ }
++
++ if (grub_efi_guid_cmp
++ (protocol_guid_array[protocol_index],
++ &driver_binding_guid) == 0)
++ {
++ (*handle_type)[i] |= GRUB_EFI_HANDLE_TYPE_DRIVER_BINDING_HANDLE;
++ }
++
++ if (grub_efi_guid_cmp
++ (protocol_guid_array[protocol_index],
++ &driver_configuration_guid) == 0)
++ {
++ (*handle_type)[i] |=
++ GRUB_EFI_HANDLE_TYPE_DRIVER_CONFIGURATION_HANDLE;
++ }
++
++ if (grub_efi_guid_cmp
++ (protocol_guid_array[protocol_index],
++ &driver_diagnostics_guid) == 0)
++ {
++ (*handle_type)[i] |=
++ GRUB_EFI_HANDLE_TYPE_DRIVER_DIAGNOSTICS_HANDLE;
++ }
++
++ if (grub_efi_guid_cmp
++ (protocol_guid_array[protocol_index],
++ &component_name_guid) == 0)
++ {
++ (*handle_type)[i] |= GRUB_EFI_HANDLE_TYPE_COMPONENT_NAME_HANDLE;
++ }
++
++ if (grub_efi_guid_cmp
++ (protocol_guid_array[protocol_index], &device_path_guid) == 0)
++ {
++ (*handle_type)[i] |= GRUB_EFI_HANDLE_TYPE_DEVICE_HANDLE;
++ }
++
++ //
++ // Retrieve the list of agents that have opened each protocol
++ //
++ status = efi_call_4 (b->open_protocol_information,
++ (*handle_buffer)[i],
++ protocol_guid_array[protocol_index],
++ &open_info, &open_info_count);
++
++ if (status != GRUB_EFI_SUCCESS)
++ continue;
++
++ for (j = 0; j < open_info_count; j++)
++ {
++
++ if (driver_binding_handle != NULL
++ && open_info[j].agent_handle == driver_binding_handle)
++ {
++ if ((open_info[j].
++ attributes & GRUB_EFI_OPEN_PROTOCOL_BY_DRIVER) ==
++ GRUB_EFI_OPEN_PROTOCOL_BY_DRIVER)
++ {
++ //
++ // Mark the device handle as being managed by the driver specified by driver_binding_handle
++ //
++ (*handle_type)[i] |=
++ (GRUB_EFI_HANDLE_TYPE_DEVICE_HANDLE |
++ GRUB_EFI_HANDLE_TYPE_CONTROLLER_HANDLE);
++ //
++ // Mark the driver_binding_handle as being a driver that is managing at least one controller
++ //
++ if (driver_binding_i_valid)
++ {
++ (*handle_type)[*driver_binding_i] |=
++ GRUB_EFI_HANDLE_TYPE_DEVICE_DRIVER;
++ }
++ }
++ if ((open_info[j].
++ attributes &
++ GRUB_EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) ==
++ GRUB_EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER)
++ {
++ //
++ // Mark the driver_binding_handle as being a driver that is managing at least one child controller
++ //
++ if (driver_binding_i_valid)
++ {
++ (*handle_type)[*driver_binding_i] |=
++ GRUB_EFI_HANDLE_TYPE_BUS_DRIVER;
++ }
++ }
++
++ if (controller_handle != NULL
++ && (*handle_buffer)[i] == controller_handle)
++ {
++ if ((open_info[j].
++ attributes &
++ GRUB_EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) ==
++ GRUB_EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER)
++ {
++ for (k = 0; k < *handle_count; k++)
++ {
++ if ((*handle_buffer)[k] ==
++ open_info[j].controller_handle)
++ {
++ (*handle_type)[k] |=
++ (GRUB_EFI_HANDLE_TYPE_DEVICE_HANDLE |
++ GRUB_EFI_HANDLE_TYPE_CHILD_HANDLE);
++ }
++ }
++ }
++ }
++ }
++
++
++ if (driver_binding_handle == NULL
++ && open_info[j].controller_handle == controller_handle)
++ {
++ if ((open_info[j].
++ attributes & GRUB_EFI_OPEN_PROTOCOL_BY_DRIVER) ==
++ GRUB_EFI_OPEN_PROTOCOL_BY_DRIVER)
++ {
++ for (k = 0; k < *handle_count; k++)
++ {
++ if ((*handle_buffer)[k] ==
++ open_info[j].agent_handle)
++ {
++ (*handle_type)[k] |=
++ GRUB_EFI_HANDLE_TYPE_DEVICE_DRIVER;
++ }
++ }
++ }
++ if ((open_info[j].
++ attributes &
++ GRUB_EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) ==
++ GRUB_EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER)
++ {
++ (*handle_type)[i] |= GRUB_EFI_HANDLE_TYPE_PARENT_HANDLE;
++ for (k = 0; k < *handle_count; k++)
++ {
++ if ((*handle_buffer)[k] ==
++ open_info[j].agent_handle)
++ {
++ (*handle_type)[k] |=
++ GRUB_EFI_HANDLE_TYPE_BUS_DRIVER;
++ }
++ }
++ }
++ }
++
++ }
++ grub_efi_free_pool (open_info);
++
++ }
++ grub_efi_free_pool (protocol_guid_array);
++ }
++
++ return GRUB_EFI_SUCCESS;
++
++error:
++ if (*handle_type != NULL)
++ grub_free (*handle_type);
++
++ if (*handle_buffer != NULL)
++ grub_efi_free_pool (*handle_buffer);
++ *handle_count = 0;
++ *handle_buffer = NULL;
++ *handle_type = NULL;
++
++ return status;
++}
++
++
++
++
+diff --git a/grub-core/kern/efi/init.c b/grub-core/kern/efi/init.c
+index 1b0a872..a83bf2e 100644
+--- a/grub-core/kern/efi/init.c
++++ b/grub-core/kern/efi/init.c
+@@ -26,6 +26,66 @@
+ #include <grub/mm.h>
+ #include <grub/kernel.h>
+
++static void bind_all_drivers (void)
++{
++ grub_efi_uintn_t n_all_handles;
++ grub_efi_handle_t *all_handles;
++ grub_efi_status_t status;
++ grub_efi_boot_services_t *b;
++ grub_efi_uintn_t handle_count;
++ grub_efi_handle_t *handle_buffer;
++ grub_efi_uint32_t *handle_type;
++ unsigned int i, j;
++
++ b = grub_efi_system_table->boot_services;
++
++ all_handles =
++ grub_efi_locate_handle (GRUB_EFI_ALL_HANDLES, NULL, NULL, &n_all_handles);
++
++ if (!all_handles)
++ return;
++
++ for (i = 0; i < n_all_handles; ++i)
++ {
++ int is_device = 1;
++
++ status =
++ grub_efi_scan_handle_database (NULL, NULL, all_handles[i], NULL,
++ &handle_count, &handle_buffer,
++ &handle_type);
++
++ if (status != GRUB_EFI_SUCCESS)
++ continue;
++
++ if (handle_type[i] & GRUB_EFI_HANDLE_TYPE_DRIVER_BINDING_HANDLE)
++ is_device = 0;
++ if (handle_type[i] & GRUB_EFI_HANDLE_TYPE_IMAGE_HANDLE)
++ is_device = 0;
++
++ if (is_device)
++ {
++ int is_parent = 0;
++ for (j = 0; j < handle_count; ++j)
++ {
++ if (handle_type[j] & GRUB_EFI_HANDLE_TYPE_PARENT_HANDLE)
++ is_parent = 1;
++ }
++
++ if ((!is_parent)
++ && (handle_type[i] & GRUB_EFI_HANDLE_TYPE_DEVICE_HANDLE))
++ {
++ efi_call_4 (b->connect_controller, all_handles[i], NULL, NULL, 1);
++ }
++ }
++
++ grub_free (handle_type);
++ grub_efi_free_pool (handle_buffer);
++ }
++
++ grub_free (all_handles);
++}
++
++
+ void
+ grub_efi_init (void)
+ {
+@@ -39,6 +99,8 @@ grub_efi_init (void)
+ efi_call_4 (grub_efi_system_table->boot_services->set_watchdog_timer,
+ 0, 0, 0, NULL);
+
++ bind_all_drivers();
++
+ grub_efidisk_init ();
+ }
+
+diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
+index 535a3e3..d8bce06 100644
+--- a/include/grub/efi/api.h
++++ b/include/grub/efi/api.h
+@@ -119,6 +119,26 @@
+ { 0x82, 0x79, 0xa8, 0x4b, 0x79, 0x61, 0x78, 0x98 } \
+ }
+
++#define GRUB_EFI_DRIVER_BINDING_GUID \
++ { 0x18a031ab, 0xb443, 0x4d1a, \
++ {0xa5, 0xc0, 0xc, 0x9, 0x26, 0x1e, 0x9f, 0x71 } \
++ }
++
++#define GRUB_EFI_DRIVER_CONFIGURATION_GUID \
++ { 0x107a772b, 0xd5e1, 0x11d4, \
++ {0x9a, 0x46, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \
++ }
++
++#define GRUB_EFI_DRIVER_DIAGNOSTICS_GUID \
++ { 0x0784924f, 0xe296, 0x11d4, \
++ { 0x9a, 0x49, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \
++ }
++
++#define GRUB_EFI_COMPONENT_NAME_GUID \
++ { 0x107a772c, 0xd5e1, 0x11d4, \
++ {0x9a, 0x46, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \
++ }
++
+ struct grub_efi_sal_system_table
+ {
+ grub_uint32_t signature;
+diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h
+index e9c57dd..a5b557b 100644
+--- a/include/grub/efi/efi.h
++++ b/include/grub/efi/efi.h
+@@ -68,6 +68,32 @@ void grub_efi_init (void);
+ void grub_efi_fini (void);
+ void grub_efi_set_prefix (void);
+
++grub_efi_status_t EXPORT_FUNC(grub_efi_scan_handle_database) (
++ grub_efi_handle_t driver_binding_handle,
++ grub_efi_uint32_t *driver_binding_handle_index,
++ grub_efi_handle_t controller_handle,
++ grub_efi_uint32_t *controller_handle_index,
++ grub_efi_uintn_t *handle_count,
++ grub_efi_handle_t **handle_buffer,
++ grub_efi_uint32_t **handle_type);
++
++#define GRUB_EFI_HANDLE_TYPE_UNKNOWN 0x000
++#define GRUB_EFI_HANDLE_TYPE_IMAGE_HANDLE 0x001
++#define GRUB_EFI_HANDLE_TYPE_DRIVER_BINDING_HANDLE 0x002
++#define GRUB_EFI_HANDLE_TYPE_DEVICE_DRIVER 0x004
++#define GRUB_EFI_HANDLE_TYPE_BUS_DRIVER 0x008
++#define GRUB_EFI_HANDLE_TYPE_DRIVER_CONFIGURATION_HANDLE 0x010
++#define GRUB_EFI_HANDLE_TYPE_DRIVER_DIAGNOSTICS_HANDLE 0x020
++#define GRUB_EFI_HANDLE_TYPE_COMPONENT_NAME_HANDLE 0x040
++#define GRUB_EFI_HANDLE_TYPE_DEVICE_HANDLE 0x080
++#define GRUB_EFI_HANDLE_TYPE_PARENT_HANDLE 0x100
++#define GRUB_EFI_HANDLE_TYPE_CONTROLLER_HANDLE 0x200
++#define GRUB_EFI_HANDLE_TYPE_CHILD_HANDLE 0x400
++
++void *EXPORT_FUNC(grub_efi_allocate_pool) (grub_efi_memory_type_t type, grub_efi_uintn_t len);
++grub_efi_status_t EXPORT_FUNC(grub_efi_free_pool) (void *);
++
++
+ /* Variables. */
+ extern grub_efi_system_table_t *EXPORT_VAR(grub_efi_system_table);
+ extern grub_efi_handle_t EXPORT_VAR(grub_efi_image_handle);