Files
u-boot/lib/efi_loader/efi_device_path.c
Simon Glass a48a8929de efi: Move most of efi_device_path into lib/efi
Most of these utility functions are useful for the app, so move them
into the common directory.

Move the GUIDs used by this file from their various other location, so
they are available to the app, even if it doesn't enabled EFI_LOADER

Fix the rather large number of checkpath warnings in this file, except
for the lwip one, best left to the maintainer to sort out.

One noteable change is adding a return value to dp_fill() for the case
where an option is not enabled but its uclass is referenced. This
presuambly never happens during execution, since if the uclass is not
supported there can be no device in that uclass and therefore nothing
will ever request its path. So just handle this like an invalid device.

Signed-off-by: Simon Glass <sjg@chromium.org>
2025-08-08 16:59:10 -06:00

101 lines
2.3 KiB
C

// SPDX-License-Identifier: GPL-2.0+
/*
* EFI device path from u-boot device-model mapping
*
* (C) Copyright 2017 Rob Clark
*/
#define LOG_CATEGORY LOGC_EFI
#include <blk.h>
#include <dm.h>
#include <dm/root.h>
#include <efi_device_path.h>
#include <log.h>
#include <mapmem.h>
#include <net.h>
#include <usb.h>
#include <mmc.h>
#include <nvme.h>
#include <efi_loader.h>
#include <part.h>
#include <u-boot/uuid.h>
#include <asm-generic/unaligned.h>
#include <linux/compat.h> /* U16_MAX */
/**
* find_handle() - find handle by device path and installed protocol
*
* If @rem is provided, the handle with the longest partial match is returned.
*
* @dp: device path to search
* @guid: GUID of protocol that must be installed on path or NULL
* @short_path: use short form device path for matching
* @rem: pointer to receive remaining device path
* Return: matching handle
*/
static efi_handle_t find_handle(struct efi_device_path *dp,
const efi_guid_t *guid, bool short_path,
struct efi_device_path **rem)
{
efi_handle_t handle, best_handle = NULL;
efi_uintn_t len, best_len = 0;
len = efi_dp_instance_size(dp);
list_for_each_entry(handle, &efi_obj_list, link) {
struct efi_handler *handler;
struct efi_device_path *dp_current;
efi_uintn_t len_current;
efi_status_t ret;
if (guid) {
ret = efi_search_protocol(handle, guid, &handler);
if (ret != EFI_SUCCESS)
continue;
}
ret = efi_search_protocol(handle, &efi_guid_device_path,
&handler);
if (ret != EFI_SUCCESS)
continue;
dp_current = handler->protocol_interface;
if (short_path) {
dp_current = efi_dp_shorten(dp_current);
if (!dp_current)
continue;
}
len_current = efi_dp_instance_size(dp_current);
if (rem) {
if (len_current > len)
continue;
} else {
if (len_current != len)
continue;
}
if (memcmp(dp_current, dp, len_current))
continue;
if (!rem)
return handle;
if (len_current > best_len) {
best_len = len_current;
best_handle = handle;
*rem = (void*)((u8 *)dp + len_current);
}
}
return best_handle;
}
efi_handle_t efi_dp_find_obj(struct efi_device_path *dp,
const efi_guid_t *guid,
struct efi_device_path **rem)
{
efi_handle_t handle;
handle = find_handle(dp, guid, false, rem);
if (!handle)
/* Match short form device path */
handle = find_handle(dp, guid, true, rem);
return handle;
}