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