xref: /rk3399_rockchip-uboot/lib/efi_loader/efi_device_path_to_text.c (revision 09c5ab909c8abfe6a0ee654149345254c0dda13d)
1 /*
2  *  EFI device path interface
3  *
4  *  Copyright (c) 2017 Heinrich Schuchardt
5  *
6  *  SPDX-License-Identifier:     GPL-2.0+
7  */
8 
9 #include <common.h>
10 #include <efi_loader.h>
11 
12 #define MAC_OUTPUT_LEN 22
13 #define UNKNOWN_OUTPUT_LEN 23
14 
15 const efi_guid_t efi_guid_device_path_to_text_protocol =
16 		EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID;
17 
18 static uint16_t *efi_convert_device_node_to_text(
19 		struct efi_device_path_protocol *device_node,
20 		bool display_only,
21 		bool allow_shortcuts)
22 {
23 	unsigned long buffer_size;
24 	efi_status_t r;
25 	uint16_t *buffer = NULL;
26 	int i;
27 
28 	switch (device_node->type) {
29 	case DEVICE_PATH_TYPE_END:
30 		return NULL;
31 	case DEVICE_PATH_TYPE_MESSAGING_DEVICE:
32 		switch (device_node->sub_type) {
33 		case DEVICE_PATH_SUB_TYPE_MSG_MAC_ADDR: {
34 			struct efi_device_path_mac_addr *dp =
35 				(struct efi_device_path_mac_addr *)device_node;
36 
37 			if (dp->if_type != 0 && dp->if_type != 1)
38 				break;
39 			r = efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES,
40 					      2 * MAC_OUTPUT_LEN,
41 					      (void **)&buffer);
42 			if (r != EFI_SUCCESS)
43 				return NULL;
44 			sprintf((char *)buffer,
45 				"MAC(%02x%02x%02x%02x%02x%02x,0x%1x)",
46 				dp->mac.addr[0], dp->mac.addr[1],
47 				dp->mac.addr[2], dp->mac.addr[3],
48 				dp->mac.addr[4], dp->mac.addr[5],
49 				dp->if_type);
50 			for (i = MAC_OUTPUT_LEN - 1; i >= 0; --i)
51 				buffer[i] = ((uint8_t *)buffer)[i];
52 			break;
53 			}
54 		}
55 	case DEVICE_PATH_TYPE_MEDIA_DEVICE:
56 		switch (device_node->sub_type) {
57 		case DEVICE_PATH_SUB_TYPE_FILE_PATH:
58 			buffer_size = device_node->length - 4;
59 			r = efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES,
60 					      buffer_size, (void **) &buffer);
61 			if (r != EFI_SUCCESS)
62 				return NULL;
63 			memcpy(buffer, device_node->data, buffer_size);
64 			break;
65 		}
66 	}
67 
68 	/*
69 	 * For all node types that we do not yet support return
70 	 * 'UNKNOWN(type,subtype)'.
71 	 */
72 	if (!buffer) {
73 		r = efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES,
74 				      2 * UNKNOWN_OUTPUT_LEN,
75 				      (void **)&buffer);
76 		if (r != EFI_SUCCESS)
77 			return NULL;
78 		sprintf((char *)buffer,
79 			"UNKNOWN(%04x,%04x)",
80 			device_node->type,
81 			device_node->sub_type);
82 		for (i = UNKNOWN_OUTPUT_LEN - 1; i >= 0; --i)
83 			buffer[i] = ((uint8_t *)buffer)[i];
84 	}
85 
86 	return buffer;
87 }
88 
89 static uint16_t EFIAPI *efi_convert_device_node_to_text_ext(
90 		struct efi_device_path_protocol *device_node,
91 		bool display_only,
92 		bool allow_shortcuts)
93 {
94 	uint16_t *buffer;
95 
96 	EFI_ENTRY("%p, %d, %d", device_node, display_only, allow_shortcuts);
97 
98 	buffer = efi_convert_device_node_to_text(device_node, display_only,
99 						 allow_shortcuts);
100 
101 	EFI_EXIT(EFI_SUCCESS);
102 	return buffer;
103 }
104 
105 static uint16_t EFIAPI *efi_convert_device_path_to_text(
106 		struct efi_device_path_protocol *device_path,
107 		bool display_only,
108 		bool allow_shortcuts)
109 {
110 	uint16_t *buffer;
111 
112 	EFI_ENTRY("%p, %d, %d", device_path, display_only, allow_shortcuts);
113 
114 	/*
115 	 * Our device paths are all of depth one. So its is sufficient to
116 	 * to convert the first node.
117 	 */
118 	buffer = efi_convert_device_node_to_text(device_path, display_only,
119 						 allow_shortcuts);
120 
121 	EFI_EXIT(EFI_SUCCESS);
122 	return buffer;
123 }
124 
125 const struct efi_device_path_to_text_protocol efi_device_path_to_text = {
126 	.convert_device_node_to_text = efi_convert_device_node_to_text_ext,
127 	.convert_device_path_to_text = efi_convert_device_path_to_text,
128 };
129