Home | History | Annotate | Download | only in efi_loader
      1 // SPDX-License-Identifier: GPL-2.0+
      2 /*
      3  *  EFI device path interface
      4  *
      5  *  Copyright (c) 2017 Leif Lindholm
      6  */
      7 
      8 #include <common.h>
      9 #include <efi_loader.h>
     10 
     11 const efi_guid_t efi_guid_device_path_utilities_protocol =
     12 		EFI_DEVICE_PATH_UTILITIES_PROTOCOL_GUID;
     13 
     14 /*
     15  * Get size of a device path.
     16  *
     17  * This function implements the GetDevicePathSize service of the device path
     18  * utilities protocol. The device path length includes the end of path tag
     19  * which may be an instance end.
     20  *
     21  * See the Unified Extensible Firmware Interface (UEFI) specification
     22  * for details.
     23  *
     24  * @device_path		device path
     25  * @return		size in bytes
     26  */
     27 static efi_uintn_t EFIAPI get_device_path_size(
     28 	const struct efi_device_path *device_path)
     29 {
     30 	efi_uintn_t sz = 0;
     31 
     32 	EFI_ENTRY("%pD", device_path);
     33 	/* size includes the END node: */
     34 	if (device_path)
     35 		sz = efi_dp_size(device_path) + sizeof(struct efi_device_path);
     36 	return EFI_EXIT(sz);
     37 }
     38 
     39 /*
     40  * Duplicate a device path.
     41  *
     42  * This function implements the DuplicateDevicePath service of the device path
     43  * utilities protocol.
     44  *
     45  * The UEFI spec does not indicate what happens to the end tag. We follow the
     46  * EDK2 logic: In case the device path ends with an end of instance tag, the
     47  * copy will also end with an end of instance tag.
     48  *
     49  * See the Unified Extensible Firmware Interface (UEFI) specification
     50  * for details.
     51  *
     52  * @device_path		device path
     53  * @return		copy of the device path
     54  */
     55 static struct efi_device_path * EFIAPI duplicate_device_path(
     56 	const struct efi_device_path *device_path)
     57 {
     58 	EFI_ENTRY("%pD", device_path);
     59 	return EFI_EXIT(efi_dp_dup(device_path));
     60 }
     61 
     62 /*
     63  * Append device path.
     64  *
     65  * This function implements the AppendDevicePath service of the device path
     66  * utilities protocol.
     67  *
     68  * See the Unified Extensible Firmware Interface (UEFI) specification
     69  * for details.
     70  *
     71  * @src1		1st device path
     72  * @src2		2nd device path
     73  * @return		concatenated device path
     74  */
     75 static struct efi_device_path * EFIAPI append_device_path(
     76 	const struct efi_device_path *src1,
     77 	const struct efi_device_path *src2)
     78 {
     79 	EFI_ENTRY("%pD, %pD", src1, src2);
     80 	return EFI_EXIT(efi_dp_append(src1, src2));
     81 }
     82 
     83 /*
     84  * Append device path node.
     85  *
     86  * This function implements the AppendDeviceNode service of the device path
     87  * utilities protocol.
     88  *
     89  * See the Unified Extensible Firmware Interface (UEFI) specification
     90  * for details.
     91  *
     92  * @device_path		device path
     93  * @device_node		device node
     94  * @return		concatenated device path
     95  */
     96 static struct efi_device_path * EFIAPI append_device_node(
     97 	const struct efi_device_path *device_path,
     98 	const struct efi_device_path *device_node)
     99 {
    100 	EFI_ENTRY("%pD, %p", device_path, device_node);
    101 	return EFI_EXIT(efi_dp_append_node(device_path, device_node));
    102 }
    103 
    104 /*
    105  * Append device path instance.
    106  *
    107  * This function implements the AppendDevicePathInstance service of the device
    108  * path utilities protocol.
    109  *
    110  * See the Unified Extensible Firmware Interface (UEFI) specification
    111  * for details.
    112  *
    113  * @device_path			1st device path
    114  * @device_path_instance	2nd device path
    115  * @return			concatenated device path
    116  */
    117 static struct efi_device_path * EFIAPI append_device_path_instance(
    118 	const struct efi_device_path *device_path,
    119 	const struct efi_device_path *device_path_instance)
    120 {
    121 	EFI_ENTRY("%pD, %pD", device_path, device_path_instance);
    122 	return EFI_EXIT(efi_dp_append_instance(device_path,
    123 					       device_path_instance));
    124 }
    125 
    126 /*
    127  * Get next device path instance.
    128  *
    129  * This function implements the GetNextDevicePathInstance service of the device
    130  * path utilities protocol.
    131  *
    132  * See the Unified Extensible Firmware Interface (UEFI) specification
    133  * for details.
    134  *
    135  * @device_path_instance	next device path instance
    136  * @device_path_instance_size	size of the device path instance
    137  * @return			concatenated device path
    138  */
    139 static struct efi_device_path * EFIAPI get_next_device_path_instance(
    140 	struct efi_device_path **device_path_instance,
    141 	efi_uintn_t *device_path_instance_size)
    142 {
    143 	EFI_ENTRY("%pD, %p", device_path_instance, device_path_instance_size);
    144 	return EFI_EXIT(efi_dp_get_next_instance(device_path_instance,
    145 						 device_path_instance_size));
    146 }
    147 
    148 /*
    149  * Check if a device path contains more than one instance.
    150  *
    151  * This function implements the AppendDeviceNode service of the device path
    152  * utilities protocol.
    153  *
    154  * See the Unified Extensible Firmware Interface (UEFI) specification
    155  * for details.
    156  *
    157  * @device_path		device path
    158  * @device_node		device node
    159  * @return		concatenated device path
    160  */
    161 static bool EFIAPI is_device_path_multi_instance(
    162 	const struct efi_device_path *device_path)
    163 {
    164 	EFI_ENTRY("%pD", device_path);
    165 	return EFI_EXIT(efi_dp_is_multi_instance(device_path));
    166 }
    167 
    168 /*
    169  * Create device node.
    170  *
    171  * This function implements the CreateDeviceNode service of the device path
    172  * utilities protocol.
    173  *
    174  * See the Unified Extensible Firmware Interface (UEFI) specification
    175  * for details.
    176  *
    177  * @node_type		node type
    178  * @node_sub_type	node sub type
    179  * @node_length		node length
    180  * @return		device path node
    181  */
    182 static struct efi_device_path * EFIAPI create_device_node(
    183 	uint8_t node_type, uint8_t node_sub_type, uint16_t node_length)
    184 {
    185 	EFI_ENTRY("%u, %u, %u", node_type, node_sub_type, node_length);
    186 	return EFI_EXIT(efi_dp_create_device_node(node_type, node_sub_type,
    187 			node_length));
    188 }
    189 
    190 const struct efi_device_path_utilities_protocol efi_device_path_utilities = {
    191 	.get_device_path_size = get_device_path_size,
    192 	.duplicate_device_path = duplicate_device_path,
    193 	.append_device_path = append_device_path,
    194 	.append_device_node = append_device_node,
    195 	.append_device_path_instance = append_device_path_instance,
    196 	.get_next_device_path_instance = get_next_device_path_instance,
    197 	.is_device_path_multi_instance = is_device_path_multi_instance,
    198 	.create_device_node = create_device_node,
    199 };
    200