
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org --- include/efi_loader.h | 4 +- lib/efi_loader/efi_device_path.c | 136 ++++++++++++++------- lib/efi_loader/efi_device_path_to_text.c | 55 +++++++++ lib/efi_loader/efi_device_path_utilities.c | 14 +++ 4 files changed, 164 insertions(+), 45 deletions(-)
diff --git a/include/efi_loader.h b/include/efi_loader.h index 4df965455c21..2773df4a26e9 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -386,8 +386,8 @@ extern void *efi_bounce_buffer; struct efi_device_path *efi_dp_next(const struct efi_device_path *dp); int efi_dp_match(const struct efi_device_path *a, const struct efi_device_path *b); -struct efi_object *efi_dp_find_obj(struct efi_device_path *dp, - struct efi_device_path **rem); +efi_handle_t efi_dp_find_obj(struct efi_device_path *dp, + struct efi_device_path **rem); /* get size of the first device path instance excluding end node */ efi_uintn_t efi_dp_instance_size(const struct efi_device_path *dp); /* size of multi-instance device path excluding end node */ diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c index d94982314a3e..a85a2d0ff6ba 100644 --- a/lib/efi_loader/efi_device_path.c +++ b/lib/efi_loader/efi_device_path.c @@ -140,69 +140,92 @@ static struct efi_device_path *shorten_path(struct efi_device_path *dp) return dp; }
-static struct efi_object *find_obj(struct efi_device_path *dp, bool short_path, - struct efi_device_path **rem) +struct dp_param { + struct efi_device_path *dp; + bool short_path; + struct efi_device_path **rem; + struct udevice *dev; +}; + +static int find_obj_cb(struct udevice *dev, void *arg) { - struct efi_object *efiobj; + struct dp_param *param = arg; + struct efi_device_path *dp = param->dp; + bool short_path = param->short_path; + struct efi_device_path **rem = param->rem; efi_uintn_t dp_size = efi_dp_instance_size(dp);
- list_for_each_entry(efiobj, &efi_obj_list, link) { - struct efi_handler *handler; - struct efi_device_path *obj_dp; - efi_status_t ret; - - ret = efi_search_protocol(efiobj, - &efi_guid_device_path, &handler); - if (ret != EFI_SUCCESS) - continue; - obj_dp = handler->protocol_interface; - - do { - if (efi_dp_match(dp, obj_dp) == 0) { - if (rem) { - /* - * Allow partial matches, but inform - * the caller. - */ - *rem = ((void *)dp) + - efi_dp_instance_size(obj_dp); - return efiobj; - } else { - /* Only return on exact matches */ - if (efi_dp_instance_size(obj_dp) == - dp_size) - return efiobj; - } + struct udevice *protocol; + struct efi_handler *handler; + struct efi_device_path *obj_dp; + efi_status_t ret; + + ret = efi_search_protocol(dev, &efi_guid_device_path, &protocol); + if (ret != EFI_SUCCESS) + return 0; + + handler = protocol->uclass_platdata; + obj_dp = handler->protocol_interface; + do { + if (efi_dp_match(dp, obj_dp) == 0) { + if (rem) { + /* + * Allow partial matches, but inform + * the caller. + */ + *rem = ((void *)dp) + + efi_dp_instance_size(obj_dp); + param->dev = dev; + return 1; }
- obj_dp = shorten_path(efi_dp_next(obj_dp)); - } while (short_path && obj_dp); - } + /* Only return on exact matches */ + if (efi_dp_instance_size(obj_dp) == dp_size) { + param->dev = dev; + return 1; + } + } + + obj_dp = shorten_path(efi_dp_next(obj_dp)); + } while (short_path && obj_dp); + + return 0; +} + +static struct udevice *find_obj(struct efi_device_path *dp, bool short_path, + struct efi_device_path **rem) +{ + struct dp_param dp_param; + efi_status_t ret; + + ret = efi_foreach_dev(find_obj_cb, &dp_param); + if (ret) + return NULL;
- return NULL; + return dp_param.dev; }
/* * Find an efiobj from device-path, if 'rem' is not NULL, returns the * remaining part of the device path after the matched object. */ -struct efi_object *efi_dp_find_obj(struct efi_device_path *dp, - struct efi_device_path **rem) +efi_handle_t efi_dp_find_obj(struct efi_device_path *dp, + struct efi_device_path **rem) { - struct efi_object *efiobj; + struct udevice *dev;
/* Search for an exact match first */ - efiobj = find_obj(dp, false, NULL); + dev = find_obj(dp, false, NULL);
/* Then for a fuzzy match */ - if (!efiobj) - efiobj = find_obj(dp, false, rem); + if (!dev) + dev = find_obj(dp, false, rem);
/* And now for a fuzzy short match */ - if (!efiobj) - efiobj = find_obj(dp, true, rem); + if (!dev) + dev = find_obj(dp, true, rem);
- return efiobj; + return dev; }
/* @@ -992,3 +1015,30 @@ efi_status_t efi_dp_from_name(const char *dev, const char *devnr,
return EFI_SUCCESS; } + +extern +char *efi_convert_device_path_to_str(struct efi_device_path *device_path, + bool display_only, + bool allow_shortcuts); + +static int efi_device_path_probe(struct udevice *dev) +{ + struct efi_handler *handler; + struct efi_device_path *dp; + char *name; + + handler = dev->uclass_platdata; + dp = handler->protocol_interface; + name = efi_convert_device_path_to_str(dp, true, true); + device_set_name(dev, name); + + /* TODO: free at unprobe */ + + return 0; +} + +U_BOOT_DRIVER(efi_device_path) = { + .name = "efi_device_path", + .id = UCLASS_EFI_PROTOCOL, + .probe = efi_device_path_probe, +}; diff --git a/lib/efi_loader/efi_device_path_to_text.c b/lib/efi_loader/efi_device_path_to_text.c index e219f84b28d2..3d518000eb59 100644 --- a/lib/efi_loader/efi_device_path_to_text.c +++ b/lib/efi_loader/efi_device_path_to_text.c @@ -6,6 +6,7 @@ */
#include <common.h> +#include <dm.h> #include <efi_loader.h>
#define MAC_OUTPUT_LEN 22 @@ -295,6 +296,47 @@ out: return text; }
+/* Temprarily used in probe() for device path protocol driver */ +char *efi_convert_device_path_to_str(struct efi_device_path *device_path, + bool display_only, + bool allow_shortcuts) +{ + char *text = NULL; + char buffer[MAX_PATH_LEN]; + char *str = buffer; + + if (!device_path) + goto out; + + while (device_path && + str + MAX_NODE_LEN < buffer + MAX_PATH_LEN) { + if (display_only) { + /* Only first 8 characters */ + struct efi_device_path *next; + + next = efi_dp_next(device_path); + if (next) { + device_path = next; + continue; + } + + str = efi_convert_single_device_node_to_text(str, + device_path); + str[9] = '\0'; + break; + } + + *str++ = '/'; + str = efi_convert_single_device_node_to_text(str, device_path); + device_path = efi_dp_next(device_path); + } + + text = strdup(buffer); + +out: + return text; +} + /* * This function implements the ConvertDevicePathToText service of the * EFI_DEVICE_PATH_TO_TEXT_PROTOCOL. @@ -344,3 +386,16 @@ const struct efi_device_path_to_text_protocol efi_device_path_to_text = { .convert_device_node_to_text = efi_convert_device_node_to_text, .convert_device_path_to_text = efi_convert_device_path_to_text, }; + +static int efi_device_path_to_text_probe(struct udevice *dev) +{ + device_set_name(dev, "DEVICE_PATH_TO_TEXT"); + + return 0; +} + +U_BOOT_DRIVER(efi_device_path_to_text) = { + .name = "efi_device_path_to_text", + .id = UCLASS_EFI_PROTOCOL, + .probe = efi_device_path_to_text_probe, +}; diff --git a/lib/efi_loader/efi_device_path_utilities.c b/lib/efi_loader/efi_device_path_utilities.c index 94015329c8cb..7d7f0c46b18f 100644 --- a/lib/efi_loader/efi_device_path_utilities.c +++ b/lib/efi_loader/efi_device_path_utilities.c @@ -6,6 +6,7 @@ */
#include <common.h> +#include <dm.h> #include <efi_loader.h>
const efi_guid_t efi_guid_device_path_utilities_protocol = @@ -197,3 +198,16 @@ const struct efi_device_path_utilities_protocol efi_device_path_utilities = { .is_device_path_multi_instance = is_device_path_multi_instance, .create_device_node = create_device_node, }; + +static int efi_device_path_utils_probe(struct udevice *dev) +{ + device_set_name(dev, "DEVICE_PATH_UTILITIES"); + + return 0; +} + +U_BOOT_DRIVER(efi_device_path_utils) = { + .name = "efi_device_path_utils", + .id = UCLASS_EFI_PROTOCOL, + .probe = efi_device_path_utils_probe, +};