2 * EFI device path interface
4 * Copyright (c) 2017 Heinrich Schuchardt
6 * SPDX-License-Identifier: GPL-2.0+
10 #include <efi_loader.h>
12 #define MAC_OUTPUT_LEN 22
13 #define UNKNOWN_OUTPUT_LEN 23
15 const efi_guid_t efi_guid_device_path_to_text_protocol
=
16 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID
;
18 static char *dp_unknown(char *s
, struct efi_device_path
*dp
)
20 s
+= sprintf(s
, "/UNKNOWN(%04x,%04x)", dp
->type
, dp
->sub_type
);
24 static char *dp_hardware(char *s
, struct efi_device_path
*dp
)
26 switch (dp
->sub_type
) {
27 case DEVICE_PATH_SUB_TYPE_MEMORY
: {
28 struct efi_device_path_memory
*mdp
=
29 (struct efi_device_path_memory
*)dp
;
30 s
+= sprintf(s
, "/MemoryMapped(0x%x,0x%llx,0x%llx)",
36 case DEVICE_PATH_SUB_TYPE_VENDOR
: {
37 struct efi_device_path_vendor
*vdp
=
38 (struct efi_device_path_vendor
*)dp
;
39 s
+= sprintf(s
, "/VenHw(%pUl)", &vdp
->guid
);
43 s
= dp_unknown(s
, dp
);
49 static char *dp_acpi(char *s
, struct efi_device_path
*dp
)
51 switch (dp
->sub_type
) {
52 case DEVICE_PATH_SUB_TYPE_ACPI_DEVICE
: {
53 struct efi_device_path_acpi_path
*adp
=
54 (struct efi_device_path_acpi_path
*)dp
;
55 s
+= sprintf(s
, "/Acpi(PNP%04x", EISA_PNP_NUM(adp
->hid
));
57 s
+= sprintf(s
, ",%d", adp
->uid
);
62 s
= dp_unknown(s
, dp
);
68 static char *dp_msging(char *s
, struct efi_device_path
*dp
)
70 switch (dp
->sub_type
) {
71 case DEVICE_PATH_SUB_TYPE_MSG_USB
: {
72 struct efi_device_path_usb
*udp
=
73 (struct efi_device_path_usb
*)dp
;
74 s
+= sprintf(s
, "/Usb(0x%x,0x%x)", udp
->parent_port_number
,
78 case DEVICE_PATH_SUB_TYPE_MSG_MAC_ADDR
: {
79 struct efi_device_path_mac_addr
*mdp
=
80 (struct efi_device_path_mac_addr
*)dp
;
82 if (mdp
->if_type
!= 0 && mdp
->if_type
!= 1)
85 s
+= sprintf(s
, "/MAC(%02x%02x%02x%02x%02x%02x,0x%1x)",
86 mdp
->mac
.addr
[0], mdp
->mac
.addr
[1],
87 mdp
->mac
.addr
[2], mdp
->mac
.addr
[3],
88 mdp
->mac
.addr
[4], mdp
->mac
.addr
[5],
93 case DEVICE_PATH_SUB_TYPE_MSG_USB_CLASS
: {
94 struct efi_device_path_usb_class
*ucdp
=
95 (struct efi_device_path_usb_class
*)dp
;
97 s
+= sprintf(s
, "/USBClass(%x,%x,%x,%x,%x)",
98 ucdp
->vendor_id
, ucdp
->product_id
,
99 ucdp
->device_class
, ucdp
->device_subclass
,
100 ucdp
->device_protocol
);
104 case DEVICE_PATH_SUB_TYPE_MSG_SD
:
105 case DEVICE_PATH_SUB_TYPE_MSG_MMC
: {
106 const char *typename
=
107 (dp
->sub_type
== DEVICE_PATH_SUB_TYPE_MSG_SD
) ?
109 struct efi_device_path_sd_mmc_path
*sddp
=
110 (struct efi_device_path_sd_mmc_path
*)dp
;
111 s
+= sprintf(s
, "/%s(Slot%u)", typename
, sddp
->slot_number
);
115 s
= dp_unknown(s
, dp
);
121 static char *dp_media(char *s
, struct efi_device_path
*dp
)
123 switch (dp
->sub_type
) {
124 case DEVICE_PATH_SUB_TYPE_HARD_DRIVE_PATH
: {
125 struct efi_device_path_hard_drive_path
*hddp
=
126 (struct efi_device_path_hard_drive_path
*)dp
;
127 void *sig
= hddp
->partition_signature
;
129 switch (hddp
->signature_type
) {
131 s
+= sprintf(s
, "/HD(Part%d,Sig%08x)",
132 hddp
->partition_number
,
136 s
+= sprintf(s
, "/HD(Part%d,Sig%pUl)",
137 hddp
->partition_number
, sig
);
139 s
+= sprintf(s
, "/HD(Part%d,MBRType=%02x,SigType=%02x)",
140 hddp
->partition_number
, hddp
->partmap_type
,
141 hddp
->signature_type
);
146 case DEVICE_PATH_SUB_TYPE_CDROM_PATH
: {
147 struct efi_device_path_cdrom_path
*cddp
=
148 (struct efi_device_path_cdrom_path
*)dp
;
149 s
+= sprintf(s
, "/CDROM(0x%x)", cddp
->boot_entry
);
152 case DEVICE_PATH_SUB_TYPE_FILE_PATH
: {
153 struct efi_device_path_file_path
*fp
=
154 (struct efi_device_path_file_path
*)dp
;
155 int slen
= (dp
->length
- sizeof(*dp
)) / 2;
156 s
+= sprintf(s
, "/%-*ls", slen
, fp
->str
);
160 s
= dp_unknown(s
, dp
);
166 static uint16_t *efi_convert_device_node_to_text(
167 struct efi_device_path
*dp
,
169 bool allow_shortcuts
)
173 char buf
[512]; /* this ought be be big enough for worst case */
179 case DEVICE_PATH_TYPE_HARDWARE_DEVICE
:
180 str
= dp_hardware(str
, dp
);
182 case DEVICE_PATH_TYPE_ACPI_DEVICE
:
183 str
= dp_acpi(str
, dp
);
185 case DEVICE_PATH_TYPE_MESSAGING_DEVICE
:
186 str
= dp_msging(str
, dp
);
188 case DEVICE_PATH_TYPE_MEDIA_DEVICE
:
189 str
= dp_media(str
, dp
);
192 str
= dp_unknown(str
, dp
);
195 dp
= efi_dp_next(dp
);
201 r
= efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES
, 2 * len
, (void **)&out
);
202 if (r
!= EFI_SUCCESS
)
205 ascii2unicode(out
, buf
);
211 /* helper for debug prints.. efi_free_pool() the result. */
212 uint16_t *efi_dp_str(struct efi_device_path
*dp
)
214 return efi_convert_device_node_to_text(dp
, true, true);
218 static uint16_t EFIAPI
*efi_convert_device_node_to_text_ext(
219 struct efi_device_path
*device_node
,
221 bool allow_shortcuts
)
225 EFI_ENTRY("%p, %d, %d", device_node
, display_only
, allow_shortcuts
);
227 buffer
= efi_convert_device_node_to_text(device_node
, display_only
,
230 EFI_EXIT(EFI_SUCCESS
);
234 static uint16_t EFIAPI
*efi_convert_device_path_to_text(
235 struct efi_device_path
*device_path
,
237 bool allow_shortcuts
)
241 EFI_ENTRY("%p, %d, %d", device_path
, display_only
, allow_shortcuts
);
244 * Our device paths are all of depth one. So its is sufficient to
245 * to convert the first node.
247 buffer
= efi_convert_device_node_to_text(device_path
, display_only
,
250 EFI_EXIT(EFI_SUCCESS
);
254 const struct efi_device_path_to_text_protocol efi_device_path_to_text
= {
255 .convert_device_node_to_text
= efi_convert_device_node_to_text_ext
,
256 .convert_device_path_to_text
= efi_convert_device_path_to_text
,