1cc5b7081Sxypron.glpk@gmx.de /*
2cc5b7081Sxypron.glpk@gmx.de * EFI device path interface
3cc5b7081Sxypron.glpk@gmx.de *
4cc5b7081Sxypron.glpk@gmx.de * Copyright (c) 2017 Heinrich Schuchardt
5cc5b7081Sxypron.glpk@gmx.de *
6cc5b7081Sxypron.glpk@gmx.de * SPDX-License-Identifier: GPL-2.0+
7cc5b7081Sxypron.glpk@gmx.de */
8cc5b7081Sxypron.glpk@gmx.de
9cc5b7081Sxypron.glpk@gmx.de #include <common.h>
10cc5b7081Sxypron.glpk@gmx.de #include <efi_loader.h>
11cc5b7081Sxypron.glpk@gmx.de
1209c5ab90Sxypron.glpk@gmx.de #define MAC_OUTPUT_LEN 22
1309c5ab90Sxypron.glpk@gmx.de #define UNKNOWN_OUTPUT_LEN 23
14cc5b7081Sxypron.glpk@gmx.de
15cc5b7081Sxypron.glpk@gmx.de const efi_guid_t efi_guid_device_path_to_text_protocol =
16cc5b7081Sxypron.glpk@gmx.de EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID;
17cc5b7081Sxypron.glpk@gmx.de
efi_convert_device_node_to_text(struct efi_device_path_protocol * device_node,bool display_only,bool allow_shortcuts)1809c5ab90Sxypron.glpk@gmx.de static uint16_t *efi_convert_device_node_to_text(
19cc5b7081Sxypron.glpk@gmx.de struct efi_device_path_protocol *device_node,
20cc5b7081Sxypron.glpk@gmx.de bool display_only,
21cc5b7081Sxypron.glpk@gmx.de bool allow_shortcuts)
22cc5b7081Sxypron.glpk@gmx.de {
23cc5b7081Sxypron.glpk@gmx.de unsigned long buffer_size;
24cc5b7081Sxypron.glpk@gmx.de efi_status_t r;
25cc5b7081Sxypron.glpk@gmx.de uint16_t *buffer = NULL;
2609c5ab90Sxypron.glpk@gmx.de int i;
27cc5b7081Sxypron.glpk@gmx.de
2809c5ab90Sxypron.glpk@gmx.de switch (device_node->type) {
2909c5ab90Sxypron.glpk@gmx.de case DEVICE_PATH_TYPE_END:
3009c5ab90Sxypron.glpk@gmx.de return NULL;
3109c5ab90Sxypron.glpk@gmx.de case DEVICE_PATH_TYPE_MESSAGING_DEVICE:
3209c5ab90Sxypron.glpk@gmx.de switch (device_node->sub_type) {
3309c5ab90Sxypron.glpk@gmx.de case DEVICE_PATH_SUB_TYPE_MSG_MAC_ADDR: {
3409c5ab90Sxypron.glpk@gmx.de struct efi_device_path_mac_addr *dp =
3509c5ab90Sxypron.glpk@gmx.de (struct efi_device_path_mac_addr *)device_node;
3609c5ab90Sxypron.glpk@gmx.de
3709c5ab90Sxypron.glpk@gmx.de if (dp->if_type != 0 && dp->if_type != 1)
3809c5ab90Sxypron.glpk@gmx.de break;
3909c5ab90Sxypron.glpk@gmx.de r = efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES,
4009c5ab90Sxypron.glpk@gmx.de 2 * MAC_OUTPUT_LEN,
4109c5ab90Sxypron.glpk@gmx.de (void **)&buffer);
4209c5ab90Sxypron.glpk@gmx.de if (r != EFI_SUCCESS)
4309c5ab90Sxypron.glpk@gmx.de return NULL;
4409c5ab90Sxypron.glpk@gmx.de sprintf((char *)buffer,
4509c5ab90Sxypron.glpk@gmx.de "MAC(%02x%02x%02x%02x%02x%02x,0x%1x)",
4609c5ab90Sxypron.glpk@gmx.de dp->mac.addr[0], dp->mac.addr[1],
4709c5ab90Sxypron.glpk@gmx.de dp->mac.addr[2], dp->mac.addr[3],
4809c5ab90Sxypron.glpk@gmx.de dp->mac.addr[4], dp->mac.addr[5],
4909c5ab90Sxypron.glpk@gmx.de dp->if_type);
5009c5ab90Sxypron.glpk@gmx.de for (i = MAC_OUTPUT_LEN - 1; i >= 0; --i)
5109c5ab90Sxypron.glpk@gmx.de buffer[i] = ((uint8_t *)buffer)[i];
5209c5ab90Sxypron.glpk@gmx.de break;
5309c5ab90Sxypron.glpk@gmx.de }
5409c5ab90Sxypron.glpk@gmx.de }
55*6cfd5f13SRob Clark break;
5609c5ab90Sxypron.glpk@gmx.de case DEVICE_PATH_TYPE_MEDIA_DEVICE:
5709c5ab90Sxypron.glpk@gmx.de switch (device_node->sub_type) {
5809c5ab90Sxypron.glpk@gmx.de case DEVICE_PATH_SUB_TYPE_FILE_PATH:
5909c5ab90Sxypron.glpk@gmx.de buffer_size = device_node->length - 4;
60cc5b7081Sxypron.glpk@gmx.de r = efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES,
61cc5b7081Sxypron.glpk@gmx.de buffer_size, (void **) &buffer);
6209c5ab90Sxypron.glpk@gmx.de if (r != EFI_SUCCESS)
6309c5ab90Sxypron.glpk@gmx.de return NULL;
6409c5ab90Sxypron.glpk@gmx.de memcpy(buffer, device_node->data, buffer_size);
65cc5b7081Sxypron.glpk@gmx.de break;
66cc5b7081Sxypron.glpk@gmx.de }
67*6cfd5f13SRob Clark break;
68cc5b7081Sxypron.glpk@gmx.de }
69cc5b7081Sxypron.glpk@gmx.de
7009c5ab90Sxypron.glpk@gmx.de /*
7109c5ab90Sxypron.glpk@gmx.de * For all node types that we do not yet support return
7209c5ab90Sxypron.glpk@gmx.de * 'UNKNOWN(type,subtype)'.
7309c5ab90Sxypron.glpk@gmx.de */
7409c5ab90Sxypron.glpk@gmx.de if (!buffer) {
7509c5ab90Sxypron.glpk@gmx.de r = efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES,
7609c5ab90Sxypron.glpk@gmx.de 2 * UNKNOWN_OUTPUT_LEN,
7709c5ab90Sxypron.glpk@gmx.de (void **)&buffer);
7809c5ab90Sxypron.glpk@gmx.de if (r != EFI_SUCCESS)
7909c5ab90Sxypron.glpk@gmx.de return NULL;
8009c5ab90Sxypron.glpk@gmx.de sprintf((char *)buffer,
8109c5ab90Sxypron.glpk@gmx.de "UNKNOWN(%04x,%04x)",
8209c5ab90Sxypron.glpk@gmx.de device_node->type,
8309c5ab90Sxypron.glpk@gmx.de device_node->sub_type);
8409c5ab90Sxypron.glpk@gmx.de for (i = UNKNOWN_OUTPUT_LEN - 1; i >= 0; --i)
8509c5ab90Sxypron.glpk@gmx.de buffer[i] = ((uint8_t *)buffer)[i];
86cc5b7081Sxypron.glpk@gmx.de }
87cc5b7081Sxypron.glpk@gmx.de
88cc5b7081Sxypron.glpk@gmx.de return buffer;
89cc5b7081Sxypron.glpk@gmx.de }
90cc5b7081Sxypron.glpk@gmx.de
efi_convert_device_node_to_text_ext(struct efi_device_path_protocol * device_node,bool display_only,bool allow_shortcuts)9109c5ab90Sxypron.glpk@gmx.de static uint16_t EFIAPI *efi_convert_device_node_to_text_ext(
9209c5ab90Sxypron.glpk@gmx.de struct efi_device_path_protocol *device_node,
9309c5ab90Sxypron.glpk@gmx.de bool display_only,
9409c5ab90Sxypron.glpk@gmx.de bool allow_shortcuts)
9509c5ab90Sxypron.glpk@gmx.de {
9609c5ab90Sxypron.glpk@gmx.de uint16_t *buffer;
9709c5ab90Sxypron.glpk@gmx.de
9809c5ab90Sxypron.glpk@gmx.de EFI_ENTRY("%p, %d, %d", device_node, display_only, allow_shortcuts);
9909c5ab90Sxypron.glpk@gmx.de
10009c5ab90Sxypron.glpk@gmx.de buffer = efi_convert_device_node_to_text(device_node, display_only,
10109c5ab90Sxypron.glpk@gmx.de allow_shortcuts);
10209c5ab90Sxypron.glpk@gmx.de
10309c5ab90Sxypron.glpk@gmx.de EFI_EXIT(EFI_SUCCESS);
10409c5ab90Sxypron.glpk@gmx.de return buffer;
10509c5ab90Sxypron.glpk@gmx.de }
10609c5ab90Sxypron.glpk@gmx.de
efi_convert_device_path_to_text(struct efi_device_path_protocol * device_path,bool display_only,bool allow_shortcuts)10709c5ab90Sxypron.glpk@gmx.de static uint16_t EFIAPI *efi_convert_device_path_to_text(
10809c5ab90Sxypron.glpk@gmx.de struct efi_device_path_protocol *device_path,
10909c5ab90Sxypron.glpk@gmx.de bool display_only,
11009c5ab90Sxypron.glpk@gmx.de bool allow_shortcuts)
11109c5ab90Sxypron.glpk@gmx.de {
11209c5ab90Sxypron.glpk@gmx.de uint16_t *buffer;
11309c5ab90Sxypron.glpk@gmx.de
11409c5ab90Sxypron.glpk@gmx.de EFI_ENTRY("%p, %d, %d", device_path, display_only, allow_shortcuts);
11509c5ab90Sxypron.glpk@gmx.de
11609c5ab90Sxypron.glpk@gmx.de /*
11709c5ab90Sxypron.glpk@gmx.de * Our device paths are all of depth one. So its is sufficient to
11809c5ab90Sxypron.glpk@gmx.de * to convert the first node.
11909c5ab90Sxypron.glpk@gmx.de */
12009c5ab90Sxypron.glpk@gmx.de buffer = efi_convert_device_node_to_text(device_path, display_only,
12109c5ab90Sxypron.glpk@gmx.de allow_shortcuts);
12209c5ab90Sxypron.glpk@gmx.de
12309c5ab90Sxypron.glpk@gmx.de EFI_EXIT(EFI_SUCCESS);
12409c5ab90Sxypron.glpk@gmx.de return buffer;
12509c5ab90Sxypron.glpk@gmx.de }
12609c5ab90Sxypron.glpk@gmx.de
127cc5b7081Sxypron.glpk@gmx.de const struct efi_device_path_to_text_protocol efi_device_path_to_text = {
12809c5ab90Sxypron.glpk@gmx.de .convert_device_node_to_text = efi_convert_device_node_to_text_ext,
129cc5b7081Sxypron.glpk@gmx.de .convert_device_path_to_text = efi_convert_device_path_to_text,
130cc5b7081Sxypron.glpk@gmx.de };
131