/* * EFI device path interface * * Copyright (c) 2017 Heinrich Schuchardt * * SPDX-License-Identifier: GPL-2.0+ */ #include #include #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, };