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 case DEVICE_PATH_TYPE_MEDIA_DEVICE: 56 switch (device_node->sub_type) { 57 case DEVICE_PATH_SUB_TYPE_FILE_PATH: 58 buffer_size = device_node->length - 4; 59 r = efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES, 60 buffer_size, (void **) &buffer); 61 if (r != EFI_SUCCESS) 62 return NULL; 63 memcpy(buffer, device_node->data, buffer_size); 64 break; 65 } 66 } 67 68 /* 69 * For all node types that we do not yet support return 70 * 'UNKNOWN(type,subtype)'. 71 */ 72 if (!buffer) { 73 r = efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES, 74 2 * UNKNOWN_OUTPUT_LEN, 75 (void **)&buffer); 76 if (r != EFI_SUCCESS) 77 return NULL; 78 sprintf((char *)buffer, 79 "UNKNOWN(%04x,%04x)", 80 device_node->type, 81 device_node->sub_type); 82 for (i = UNKNOWN_OUTPUT_LEN - 1; i >= 0; --i) 83 buffer[i] = ((uint8_t *)buffer)[i]; 84 } 85 86 return buffer; 87 } 88 89 static uint16_t EFIAPI *efi_convert_device_node_to_text_ext( 90 struct efi_device_path_protocol *device_node, 91 bool display_only, 92 bool allow_shortcuts) 93 { 94 uint16_t *buffer; 95 96 EFI_ENTRY("%p, %d, %d", device_node, display_only, allow_shortcuts); 97 98 buffer = efi_convert_device_node_to_text(device_node, display_only, 99 allow_shortcuts); 100 101 EFI_EXIT(EFI_SUCCESS); 102 return buffer; 103 } 104 105 static uint16_t EFIAPI *efi_convert_device_path_to_text( 106 struct efi_device_path_protocol *device_path, 107 bool display_only, 108 bool allow_shortcuts) 109 { 110 uint16_t *buffer; 111 112 EFI_ENTRY("%p, %d, %d", device_path, display_only, allow_shortcuts); 113 114 /* 115 * Our device paths are all of depth one. So its is sufficient to 116 * to convert the first node. 117 */ 118 buffer = efi_convert_device_node_to_text(device_path, display_only, 119 allow_shortcuts); 120 121 EFI_EXIT(EFI_SUCCESS); 122 return buffer; 123 } 124 125 const struct efi_device_path_to_text_protocol efi_device_path_to_text = { 126 .convert_device_node_to_text = efi_convert_device_node_to_text_ext, 127 .convert_device_path_to_text = efi_convert_device_path_to_text, 128 }; 129