summaryrefslogtreecommitdiff
path: root/lib/efi_loader/efi_device_path_to_text.c
blob: 612e38061795c38cc955deb4ba2731d350e418f1 (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
/*
 *  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;
			}
		}
	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;
		}
	}

	/*
	 * 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,
};