1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * EFI device path interface 4 * 5 * Copyright (c) 2017 Heinrich Schuchardt 6 */ 7 8#include <blk.h> 9#include <efi_loader.h> 10#include <malloc.h> 11 12#define MAC_OUTPUT_LEN 22 13#define UNKNOWN_OUTPUT_LEN 23 14 15#define MAX_NODE_LEN 512 16#define MAX_PATH_LEN 1024 17 18const efi_guid_t efi_guid_device_path_to_text_protocol = 19 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID; 20 21/** 22 * efi_str_to_u16() - convert ASCII string to UTF-16 23 * 24 * A u16 buffer is allocated from pool. The ASCII string is copied to the u16 25 * buffer. 26 * 27 * @str: ASCII string 28 * Return: UTF-16 string. NULL if out of memory. 29 */ 30static u16 *efi_str_to_u16(char *str) 31{ 32 efi_uintn_t len; 33 u16 *out, *dst; 34 35 len = sizeof(u16) * (utf8_utf16_strlen(str) + 1); 36 out = efi_alloc(len); 37 if (!out) 38 return NULL; 39 dst = out; 40 utf8_utf16_strcpy(&dst, str); 41 return out; 42} 43 44static char *dp_unknown(char *s, struct efi_device_path *dp) 45{ 46 s += sprintf(s, "UNKNOWN(%04x,%04x)", dp->type, dp->sub_type); 47 return s; 48} 49 50static char *dp_hardware(char *s, struct efi_device_path *dp) 51{ 52 switch (dp->sub_type) { 53 case DEVICE_PATH_SUB_TYPE_MEMORY: { 54 struct efi_device_path_memory *mdp = 55 (struct efi_device_path_memory *)dp; 56 s += sprintf(s, "MemoryMapped(0x%x,0x%llx,0x%llx)", 57 mdp->memory_type, 58 mdp->start_address, 59 mdp->end_address); 60 break; 61 } 62 case DEVICE_PATH_SUB_TYPE_VENDOR: { 63 int i, n; 64 struct efi_device_path_vendor *vdp = 65 (struct efi_device_path_vendor *)dp; 66 67 s += sprintf(s, "VenHw(%pUl", &vdp->guid); 68 n = (int)vdp->dp.length - sizeof(struct efi_device_path_vendor); 69 /* Node must fit into MAX_NODE_LEN) */ 70 if (n > 0 && n < MAX_NODE_LEN / 2 - 22) { 71 s += sprintf(s, ","); 72 for (i = 0; i < n; ++i) 73 s += sprintf(s, "%02x", vdp->vendor_data[i]); 74 } 75 s += sprintf(s, ")"); 76 break; 77 } 78 case DEVICE_PATH_SUB_TYPE_CONTROLLER: { 79 struct efi_device_path_controller *cdp = 80 (struct efi_device_path_controller *)dp; 81 82 s += sprintf(s, "Ctrl(0x%0x)", cdp->controller_number); 83 break; 84 } 85 default: 86 s = dp_unknown(s, dp); 87 break; 88 } 89 return s; 90} 91 92static char *dp_acpi(char *s, struct efi_device_path *dp) 93{ 94 switch (dp->sub_type) { 95 case DEVICE_PATH_SUB_TYPE_ACPI_DEVICE: { 96 struct efi_device_path_acpi_path *adp = 97 (struct efi_device_path_acpi_path *)dp; 98 99 s += sprintf(s, "Acpi(PNP%04X,%d)", EISA_PNP_NUM(adp->hid), 100 adp->uid); 101 break; 102 } 103 default: 104 s = dp_unknown(s, dp); 105 break; 106 } 107 return s; 108} 109 110static char *dp_msging(char *s, struct efi_device_path *dp) 111{ 112 switch (dp->sub_type) { 113 case DEVICE_PATH_SUB_TYPE_MSG_ATAPI: { 114 struct efi_device_path_atapi *ide = 115 (struct efi_device_path_atapi *)dp; 116 s += sprintf(s, "Ata(%d,%d,%d)", ide->primary_secondary, 117 ide->slave_master, ide->logical_unit_number); 118 break; 119 } 120 case DEVICE_PATH_SUB_TYPE_MSG_SCSI: { 121 struct efi_device_path_scsi *ide = 122 (struct efi_device_path_scsi *)dp; 123 s += sprintf(s, "Scsi(%u,%u)", ide->target_id, 124 ide->logical_unit_number); 125 break; 126 } 127 case DEVICE_PATH_SUB_TYPE_MSG_UART: { 128 struct efi_device_path_uart *uart = 129 (struct efi_device_path_uart *)dp; 130 const char parity_str[6] = {'D', 'N', 'E', 'O', 'M', 'S'}; 131 const char *stop_bits_str[4] = { "D", "1", "1.5", "2" }; 132 133 s += sprintf(s, "Uart(%lld,%d,", uart->baud_rate, 134 uart->data_bits); 135 136 /* 137 * Parity and stop bits can either both use keywords or both use 138 * numbers but numbers and keywords should not be mixed. Let's 139 * go for keywords as this is what EDK II does. For illegal 140 * values fall back to numbers. 141 */ 142 if (uart->parity < 6) 143 s += sprintf(s, "%c,", parity_str[uart->parity]); 144 else 145 s += sprintf(s, "%d,", uart->parity); 146 if (uart->stop_bits < 4) 147 s += sprintf(s, "%s)", stop_bits_str[uart->stop_bits]); 148 else 149 s += sprintf(s, "%d)", uart->stop_bits); 150 break; 151 } 152 case DEVICE_PATH_SUB_TYPE_MSG_USB: { 153 struct efi_device_path_usb *udp = 154 (struct efi_device_path_usb *)dp; 155 s += sprintf(s, "USB(0x%x,0x%x)", udp->parent_port_number, 156 udp->usb_interface); 157 break; 158 } 159 case DEVICE_PATH_SUB_TYPE_MSG_MAC_ADDR: { 160 int i, n = sizeof(struct efi_mac_addr); 161 struct efi_device_path_mac_addr *mdp = 162 (struct efi_device_path_mac_addr *)dp; 163 164 if (mdp->if_type <= 1) 165 n = 6; 166 s += sprintf(s, "MAC("); 167 for (i = 0; i < n; ++i) 168 s += sprintf(s, "%02x", mdp->mac.addr[i]); 169 s += sprintf(s, ",%u)", mdp->if_type); 170 171 break; 172 } 173 case DEVICE_PATH_SUB_TYPE_MSG_USB_CLASS: { 174 struct efi_device_path_usb_class *ucdp = 175 (struct efi_device_path_usb_class *)dp; 176 177 s += sprintf(s, "UsbClass(0x%x,0x%x,0x%x,0x%x,0x%x)", 178 ucdp->vendor_id, ucdp->product_id, 179 ucdp->device_class, ucdp->device_subclass, 180 ucdp->device_protocol); 181 182 break; 183 } 184 case DEVICE_PATH_SUB_TYPE_MSG_SATA: { 185 struct efi_device_path_sata *sdp = 186 (struct efi_device_path_sata *) dp; 187 188 s += sprintf(s, "Sata(0x%x,0x%x,0x%x)", 189 sdp->hba_port, 190 sdp->port_multiplier_port, 191 sdp->logical_unit_number); 192 break; 193 } 194 case DEVICE_PATH_SUB_TYPE_MSG_NVME: { 195 struct efi_device_path_nvme *ndp = 196 (struct efi_device_path_nvme *)dp; 197 u32 ns_id; 198 199 memcpy(&ns_id, &ndp->ns_id, sizeof(ns_id)); 200 s += sprintf(s, "NVMe(0x%x,", ns_id); 201 202 /* Display byte 7 first, byte 0 last */ 203 for (int i = 0; i < 8; ++i) 204 s += sprintf(s, "%s%02x", i ? "-" : "", 205 ndp->eui64[i ^ 7]); 206 s += sprintf(s, ")"); 207 208 break; 209 } 210 case DEVICE_PATH_SUB_TYPE_MSG_URI: { 211 struct efi_device_path_uri *udp = 212 (struct efi_device_path_uri *)dp; 213 int n; 214 215 n = (int)udp->dp.length - sizeof(struct efi_device_path_uri); 216 217 s += sprintf(s, "Uri("); 218 if (n > 0 && n < MAX_NODE_LEN - 6) 219 s += snprintf(s, n, "%s", (char *)udp->uri); 220 s += sprintf(s, ")"); 221 break; 222 } 223 case DEVICE_PATH_SUB_TYPE_MSG_SD: 224 case DEVICE_PATH_SUB_TYPE_MSG_MMC: { 225 const char *typename = 226 (dp->sub_type == DEVICE_PATH_SUB_TYPE_MSG_SD) ? 227 "SD" : "eMMC"; 228 struct efi_device_path_sd_mmc_path *sddp = 229 (struct efi_device_path_sd_mmc_path *)dp; 230 s += sprintf(s, "%s(%u)", typename, sddp->slot_number); 231 break; 232 } 233 default: 234 s = dp_unknown(s, dp); 235 break; 236 } 237 return s; 238} 239 240/* 241 * Convert a media device path node to text. 242 * 243 * @s output buffer 244 * @dp device path node 245 * Return: next unused buffer address 246 */ 247static char *dp_media(char *s, struct efi_device_path *dp) 248{ 249 switch (dp->sub_type) { 250 case DEVICE_PATH_SUB_TYPE_HARD_DRIVE_PATH: { 251 struct efi_device_path_hard_drive_path *hddp = 252 (struct efi_device_path_hard_drive_path *)dp; 253 void *sig = hddp->partition_signature; 254 u64 start; 255 u64 end; 256 257 /* Copy from packed structure to aligned memory */ 258 memcpy(&start, &hddp->partition_start, sizeof(start)); 259 memcpy(&end, &hddp->partition_end, sizeof(end)); 260 261 switch (hddp->signature_type) { 262 case SIG_TYPE_MBR: { 263 u32 signature; 264 265 memcpy(&signature, sig, sizeof(signature)); 266 s += sprintf( 267 s, "HD(%d,MBR,0x%08x,0x%llx,0x%llx)", 268 hddp->partition_number, signature, start, end); 269 break; 270 } 271 case SIG_TYPE_GUID: 272 s += sprintf( 273 s, "HD(%d,GPT,%pUl,0x%llx,0x%llx)", 274 hddp->partition_number, sig, start, end); 275 break; 276 default: 277 s += sprintf( 278 s, "HD(%d,0x%02x,0,0x%llx,0x%llx)", 279 hddp->partition_number, hddp->partmap_type, 280 start, end); 281 break; 282 } 283 284 break; 285 } 286 case DEVICE_PATH_SUB_TYPE_CDROM_PATH: { 287 struct efi_device_path_cdrom_path *cddp = 288 (struct efi_device_path_cdrom_path *)dp; 289 s += sprintf(s, "CDROM(%u,0x%llx,0x%llx)", cddp->boot_entry, 290 cddp->partition_start, cddp->partition_size); 291 break; 292 } 293 case DEVICE_PATH_SUB_TYPE_VENDOR_PATH: { 294 int i, n; 295 struct efi_device_path_vendor *vdp = 296 (struct efi_device_path_vendor *)dp; 297 298 s += sprintf(s, "VenMedia(%pUl", &vdp->guid); 299 n = (int)vdp->dp.length - sizeof(struct efi_device_path_vendor); 300 /* Node must fit into MAX_NODE_LEN) */ 301 if (n > 0 && n < MAX_NODE_LEN / 2 - 24) { 302 s += sprintf(s, ","); 303 for (i = 0; i < n; ++i) 304 s += sprintf(s, "%02x", vdp->vendor_data[i]); 305 } 306 s += sprintf(s, ")"); 307 break; 308 } 309 case DEVICE_PATH_SUB_TYPE_FILE_PATH: { 310 struct efi_device_path_file_path *fp = 311 (struct efi_device_path_file_path *)dp; 312 u16 *buffer; 313 int slen = dp->length - sizeof(*dp); 314 315 /* two bytes for \0, extra byte if dp->length is odd */ 316 buffer = calloc(1, slen + 3); 317 if (!buffer) { 318 log_err("Out of memory\n"); 319 return s; 320 } 321 memcpy(buffer, fp->str, dp->length - sizeof(*dp)); 322 s += snprintf(s, MAX_NODE_LEN - 1, "%ls", buffer); 323 free(buffer); 324 break; 325 } 326 default: 327 s = dp_unknown(s, dp); 328 break; 329 } 330 return s; 331} 332 333/* 334 * Converts a single node to a char string. 335 * 336 * @buffer output buffer 337 * @dp device path or node 338 * Return: end of string 339 */ 340static char *efi_convert_single_device_node_to_text( 341 char *buffer, 342 struct efi_device_path *dp) 343{ 344 char *str = buffer; 345 346 switch (dp->type) { 347 case DEVICE_PATH_TYPE_HARDWARE_DEVICE: 348 str = dp_hardware(str, dp); 349 break; 350 case DEVICE_PATH_TYPE_ACPI_DEVICE: 351 str = dp_acpi(str, dp); 352 break; 353 case DEVICE_PATH_TYPE_MESSAGING_DEVICE: 354 str = dp_msging(str, dp); 355 break; 356 case DEVICE_PATH_TYPE_MEDIA_DEVICE: 357 str = dp_media(str, dp); 358 break; 359 case DEVICE_PATH_TYPE_END: 360 break; 361 default: 362 str = dp_unknown(str, dp); 363 } 364 365 *str = '\0'; 366 return str; 367} 368 369/* 370 * This function implements the ConvertDeviceNodeToText service of the 371 * EFI_DEVICE_PATH_TO_TEXT_PROTOCOL. 372 * See the Unified Extensible Firmware Interface (UEFI) specification 373 * for details. 374 * 375 * device_node device node to be converted 376 * display_only true if the shorter text representation shall be used 377 * allow_shortcuts true if shortcut forms may be used 378 * Return: text representation of the device path 379 * NULL if out of memory of device_path is NULL 380 */ 381static uint16_t EFIAPI *efi_convert_device_node_to_text( 382 struct efi_device_path *device_node, 383 bool display_only, 384 bool allow_shortcuts) 385{ 386 char str[MAX_NODE_LEN]; 387 uint16_t *text = NULL; 388 389 EFI_ENTRY("%p, %d, %d", device_node, display_only, allow_shortcuts); 390 391 if (!device_node) 392 goto out; 393 efi_convert_single_device_node_to_text(str, device_node); 394 395 text = efi_str_to_u16(str); 396 397out: 398 EFI_EXIT(EFI_SUCCESS); 399 return text; 400} 401 402/* 403 * This function implements the ConvertDevicePathToText service of the 404 * EFI_DEVICE_PATH_TO_TEXT_PROTOCOL. 405 * See the Unified Extensible Firmware Interface (UEFI) specification 406 * for details. 407 * 408 * device_path device path to be converted 409 * display_only true if the shorter text representation shall be used 410 * allow_shortcuts true if shortcut forms may be used 411 * Return: text representation of the device path 412 * NULL if out of memory of device_path is NULL 413 */ 414static uint16_t EFIAPI *efi_convert_device_path_to_text( 415 struct efi_device_path *device_path, 416 bool display_only, 417 bool allow_shortcuts) 418{ 419 uint16_t *text = NULL; 420 char buffer[MAX_PATH_LEN]; 421 char *str = buffer; 422 423 EFI_ENTRY("%p, %d, %d", device_path, display_only, allow_shortcuts); 424 425 if (!device_path) 426 goto out; 427 while (device_path && str + MAX_NODE_LEN < buffer + MAX_PATH_LEN) { 428 if (device_path->type == DEVICE_PATH_TYPE_END) { 429 if (device_path->sub_type != 430 DEVICE_PATH_SUB_TYPE_INSTANCE_END) 431 break; 432 *str++ = ','; 433 } else { 434 *str++ = '/'; 435 str = efi_convert_single_device_node_to_text( 436 str, device_path); 437 } 438 *(u8 **)&device_path += device_path->length; 439 } 440 441 *str = 0; 442 text = efi_str_to_u16(buffer); 443 444out: 445 EFI_EXIT(EFI_SUCCESS); 446 return text; 447} 448 449/* helper for debug prints.. efi_free_pool() the result. */ 450uint16_t *efi_dp_str(struct efi_device_path *dp) 451{ 452 return EFI_CALL(efi_convert_device_path_to_text(dp, true, true)); 453} 454 455const struct efi_device_path_to_text_protocol efi_device_path_to_text = { 456 .convert_device_node_to_text = efi_convert_device_node_to_text, 457 .convert_device_path_to_text = efi_convert_device_path_to_text, 458}; 459