summaryrefslogtreecommitdiff
path: root/lib/efi_loader/efi_device_path_to_text.c
blob: 4b2f43f0c8a65e037eed759426ffa8cb13ff66d4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
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,
};