drivers/firmware/efi/dev-path-parser.c

Source file repositories/reference/linux-study-clean/drivers/firmware/efi/dev-path-parser.c

File Facts

System
Linux kernel
Corpus path
drivers/firmware/efi/dev-path-parser.c
Extension
.c
Size
5395 bytes
Lines
182
Domain
Driver Families
Bucket
drivers/firmware
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

*	while (!IS_ERR_OR_NULL(dev = efi_get_device_by_path(&node, &len))) {
 *		// do something with dev
 *		put_device(dev);
 *	}
 *	if (IS_ERR(dev))
 *		// report error
 *
 * Devices can only be found if they're already instantiated. Most buses
 * instantiate devices in the "subsys" initcall level, hence the earliest
 * initcall level in which this function should be called is "fs".
 *
 * Returns the device on success or
 *	%ERR_PTR(-ENODEV) if no device was found,
 *	%ERR_PTR(-EINVAL) if a node is malformed or exceeds @len,
 *	%ERR_PTR(-ENOTSUPP) if support for a node type is not yet implemented.
 */
struct device * __init efi_get_device_by_path(const struct efi_dev_path **node,
					      size_t *len)
{
	struct device *parent = NULL, *child;
	long ret = 0;

	if (!*len)
		return NULL;

	while (!ret) {
		if (*len < 4 || *len < (*node)->header.length)
			ret = -EINVAL;
		else if ((*node)->header.type		== EFI_DEV_ACPI &&
			 (*node)->header.sub_type	== EFI_DEV_BASIC_ACPI)
			ret = parse_acpi_path(*node, parent, &child);
		else if ((*node)->header.type		== EFI_DEV_HW &&
			 (*node)->header.sub_type	== EFI_DEV_PCI)
			ret = parse_pci_path(*node, parent, &child);
		else if (((*node)->header.type		== EFI_DEV_END_PATH ||
			  (*node)->header.type		== EFI_DEV_END_PATH2))
			ret = parse_end_path(*node, parent, &child);
		else
			ret = -ENOTSUPP;

		put_device(parent);
		if (ret < 0)
			return ERR_PTR(ret);

		parent = child;
		*node  = (void *)*node + (*node)->header.length;
		*len  -= (*node)->header.length;
	}

	if (ret == EFI_DEV_END_ENTIRE)
		*len = 0;

	return child;
}

Annotation

Implementation Notes