diff options
Diffstat (limited to 'lib/efi_loader/efi_device_path_to_text.c')
-rw-r--r-- | lib/efi_loader/efi_device_path_to_text.c | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/lib/efi_loader/efi_device_path_to_text.c b/lib/efi_loader/efi_device_path_to_text.c new file mode 100644 index 00000000000..4b2f43f0c8a --- /dev/null +++ b/lib/efi_loader/efi_device_path_to_text.c @@ -0,0 +1,130 @@ +/* + * EFI device path interface + * + * Copyright (c) 2017 Heinrich Schuchardt + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <efi_loader.h> + +#define MAC_OUTPUT_LEN 22 +#define UNKNOWN_OUTPUT_LEN 23 + +const efi_guid_t efi_guid_device_path_to_text_protocol = + EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID; + +static uint16_t *efi_convert_device_node_to_text( + struct efi_device_path_protocol *device_node, + bool display_only, + bool allow_shortcuts) +{ + unsigned long buffer_size; + efi_status_t r; + uint16_t *buffer = NULL; + int i; + + switch (device_node->type) { + case DEVICE_PATH_TYPE_END: + return NULL; + case DEVICE_PATH_TYPE_MESSAGING_DEVICE: + switch (device_node->sub_type) { + case DEVICE_PATH_SUB_TYPE_MSG_MAC_ADDR: { + struct efi_device_path_mac_addr *dp = + (struct efi_device_path_mac_addr *)device_node; + + if (dp->if_type != 0 && dp->if_type != 1) + break; + r = efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES, + 2 * MAC_OUTPUT_LEN, + (void **)&buffer); + if (r != EFI_SUCCESS) + return NULL; + sprintf((char *)buffer, + "MAC(%02x%02x%02x%02x%02x%02x,0x%1x)", + dp->mac.addr[0], dp->mac.addr[1], + dp->mac.addr[2], dp->mac.addr[3], + dp->mac.addr[4], dp->mac.addr[5], + dp->if_type); + for (i = MAC_OUTPUT_LEN - 1; i >= 0; --i) + buffer[i] = ((uint8_t *)buffer)[i]; + break; + } + } + break; + case DEVICE_PATH_TYPE_MEDIA_DEVICE: + switch (device_node->sub_type) { + case DEVICE_PATH_SUB_TYPE_FILE_PATH: + buffer_size = device_node->length - 4; + r = efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES, + buffer_size, (void **) &buffer); + if (r != EFI_SUCCESS) + return NULL; + memcpy(buffer, device_node->data, buffer_size); + break; + } + break; + } + + /* + * For all node types that we do not yet support return + * 'UNKNOWN(type,subtype)'. + */ + if (!buffer) { + r = efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES, + 2 * UNKNOWN_OUTPUT_LEN, + (void **)&buffer); + if (r != EFI_SUCCESS) + return NULL; + sprintf((char *)buffer, + "UNKNOWN(%04x,%04x)", + device_node->type, + device_node->sub_type); + for (i = UNKNOWN_OUTPUT_LEN - 1; i >= 0; --i) + buffer[i] = ((uint8_t *)buffer)[i]; + } + + return buffer; +} + +static uint16_t EFIAPI *efi_convert_device_node_to_text_ext( + struct efi_device_path_protocol *device_node, + bool display_only, + bool allow_shortcuts) +{ + uint16_t *buffer; + + EFI_ENTRY("%p, %d, %d", device_node, display_only, allow_shortcuts); + + buffer = efi_convert_device_node_to_text(device_node, display_only, + allow_shortcuts); + + EFI_EXIT(EFI_SUCCESS); + return buffer; +} + +static uint16_t EFIAPI *efi_convert_device_path_to_text( + struct efi_device_path_protocol *device_path, + bool display_only, + bool allow_shortcuts) +{ + uint16_t *buffer; + + EFI_ENTRY("%p, %d, %d", device_path, display_only, allow_shortcuts); + + /* + * Our device paths are all of depth one. So its is sufficient to + * to convert the first node. + */ + buffer = efi_convert_device_node_to_text(device_path, display_only, + allow_shortcuts); + + EFI_EXIT(EFI_SUCCESS); + return buffer; +} + +const struct efi_device_path_to_text_protocol efi_device_path_to_text = { + .convert_device_node_to_text = efi_convert_device_node_to_text_ext, + .convert_device_path_to_text = efi_convert_device_path_to_text, +}; |