1 /* 2 * EFI device path interface 3 * 4 * Copyright (c) 2017 Heinrich Schuchardt 5 * 6 * SPDX-License-Identifier: GPL-2.0+ 7 */ 8 9 #include <common.h> 10 #include <efi_loader.h> 11 12 #define MAC_OUTPUT_LEN 22 13 #define UNKNOWN_OUTPUT_LEN 23 14 15 const efi_guid_t efi_guid_device_path_to_text_protocol = 16 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID; 17 18 static uint16_t *efi_convert_device_node_to_text( 19 struct efi_device_path_protocol *device_node, 20 bool display_only, 21 bool allow_shortcuts) 22 { 23 unsigned long buffer_size; 24 efi_status_t r; 25 uint16_t *buffer = NULL; 26 int i; 27 28 switch (device_node->type) { 29 case DEVICE_PATH_TYPE_END: 30 return NULL; 31 case DEVICE_PATH_TYPE_MESSAGING_DEVICE: 32 switch (device_node->sub_type) { 33 case DEVICE_PATH_SUB_TYPE_MSG_MAC_ADDR: { 34 struct efi_device_path_mac_addr *dp = 35 (struct efi_device_path_mac_addr *)device_node; 36 37 if (dp->if_type != 0 && dp->if_type != 1) 38 break; 39 r = efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES, 40 2 * MAC_OUTPUT_LEN, 41 (void **)&buffer); 42 if (r != EFI_SUCCESS) 43 return NULL; 44 sprintf((char *)buffer, 45 "MAC(%02x%02x%02x%02x%02x%02x,0x%1x)", 46 dp->mac.addr[0], dp->mac.addr[1], 47 dp->mac.addr[2], dp->mac.addr[3], 48 dp->mac.addr[4], dp->mac.addr[5], 49 dp->if_type); 50 for (i = MAC_OUTPUT_LEN - 1; i >= 0; --i) 51 buffer[i] = ((uint8_t *)buffer)[i]; 52 break; 53 } 54 } 55 break; 56 case DEVICE_PATH_TYPE_MEDIA_DEVICE: 57 switch (device_node->sub_type) { 58 case DEVICE_PATH_SUB_TYPE_FILE_PATH: 59 buffer_size = device_node->length - 4; 60 r = efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES, 61 buffer_size, (void **) &buffer); 62 if (r != EFI_SUCCESS) 63 return NULL; 64 memcpy(buffer, device_node->data, buffer_size); 65 break; 66 } 67 break; 68 } 69 70 /* 71 * For all node types that we do not yet support return 72 * 'UNKNOWN(type,subtype)'. 73 */ 74 if (!buffer) { 75 r = efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES, 76 2 * UNKNOWN_OUTPUT_LEN, 77 (void **)&buffer); 78 if (r != EFI_SUCCESS) 79 return NULL; 80 sprintf((char *)buffer, 81 "UNKNOWN(%04x,%04x)", 82 device_node->type, 83 device_node->sub_type); 84 for (i = UNKNOWN_OUTPUT_LEN - 1; i >= 0; --i) 85 buffer[i] = ((uint8_t *)buffer)[i]; 86 } 87 88 return buffer; 89 } 90 91 static uint16_t EFIAPI *efi_convert_device_node_to_text_ext( 92 struct efi_device_path_protocol *device_node, 93 bool display_only, 94 bool allow_shortcuts) 95 { 96 uint16_t *buffer; 97 98 EFI_ENTRY("%p, %d, %d", device_node, display_only, allow_shortcuts); 99 100 buffer = efi_convert_device_node_to_text(device_node, display_only, 101 allow_shortcuts); 102 103 EFI_EXIT(EFI_SUCCESS); 104 return buffer; 105 } 106 107 static uint16_t EFIAPI *efi_convert_device_path_to_text( 108 struct efi_device_path_protocol *device_path, 109 bool display_only, 110 bool allow_shortcuts) 111 { 112 uint16_t *buffer; 113 114 EFI_ENTRY("%p, %d, %d", device_path, display_only, allow_shortcuts); 115 116 /* 117 * Our device paths are all of depth one. So its is sufficient to 118 * to convert the first node. 119 */ 120 buffer = efi_convert_device_node_to_text(device_path, display_only, 121 allow_shortcuts); 122 123 EFI_EXIT(EFI_SUCCESS); 124 return buffer; 125 } 126 127 const struct efi_device_path_to_text_protocol efi_device_path_to_text = { 128 .convert_device_node_to_text = efi_convert_device_node_to_text_ext, 129 .convert_device_path_to_text = efi_convert_device_path_to_text, 130 }; 131