2018-05-07 21:02:21 +00:00
|
|
|
// SPDX-License-Identifier: GPL-2.0+
|
2017-07-11 20:06:25 +00:00
|
|
|
/*
|
|
|
|
* EFI device path interface
|
|
|
|
*
|
|
|
|
* Copyright (c) 2017 Heinrich Schuchardt
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <common.h>
|
2020-05-10 17:39:58 +00:00
|
|
|
#include <blk.h>
|
2017-07-11 20:06:25 +00:00
|
|
|
#include <efi_loader.h>
|
2022-01-29 18:01:07 +00:00
|
|
|
#include <malloc.h>
|
2017-07-11 20:06:25 +00:00
|
|
|
|
2017-07-21 17:12:08 +00:00
|
|
|
#define MAC_OUTPUT_LEN 22
|
|
|
|
#define UNKNOWN_OUTPUT_LEN 23
|
2017-07-11 20:06:25 +00:00
|
|
|
|
2017-11-26 13:05:09 +00:00
|
|
|
#define MAX_NODE_LEN 512
|
|
|
|
#define MAX_PATH_LEN 1024
|
|
|
|
|
2017-07-11 20:06:25 +00:00
|
|
|
const efi_guid_t efi_guid_device_path_to_text_protocol =
|
|
|
|
EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID;
|
|
|
|
|
2018-09-20 17:57:54 +00:00
|
|
|
/**
|
|
|
|
* efi_str_to_u16() - convert ASCII string to UTF-16
|
|
|
|
*
|
|
|
|
* A u16 buffer is allocated from pool. The ASCII string is copied to the u16
|
|
|
|
* buffer.
|
|
|
|
*
|
|
|
|
* @str: ASCII string
|
|
|
|
* Return: UTF-16 string. NULL if out of memory.
|
|
|
|
*/
|
2017-11-26 13:05:09 +00:00
|
|
|
static u16 *efi_str_to_u16(char *str)
|
|
|
|
{
|
|
|
|
efi_uintn_t len;
|
2019-09-07 19:05:45 +00:00
|
|
|
u16 *out, *dst;
|
2017-11-26 13:05:09 +00:00
|
|
|
|
2019-09-07 19:05:45 +00:00
|
|
|
len = sizeof(u16) * (utf8_utf16_strlen(str) + 1);
|
2023-03-19 08:20:23 +00:00
|
|
|
out = efi_alloc(len);
|
|
|
|
if (!out)
|
2017-11-26 13:05:09 +00:00
|
|
|
return NULL;
|
2019-09-07 19:05:45 +00:00
|
|
|
dst = out;
|
|
|
|
utf8_utf16_strcpy(&dst, str);
|
2017-11-26 13:05:09 +00:00
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
2017-09-13 22:05:30 +00:00
|
|
|
static char *dp_unknown(char *s, struct efi_device_path *dp)
|
|
|
|
{
|
2017-11-26 13:05:09 +00:00
|
|
|
s += sprintf(s, "UNKNOWN(%04x,%04x)", dp->type, dp->sub_type);
|
2017-09-13 22:05:30 +00:00
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *dp_hardware(char *s, struct efi_device_path *dp)
|
|
|
|
{
|
|
|
|
switch (dp->sub_type) {
|
2017-10-10 12:23:06 +00:00
|
|
|
case DEVICE_PATH_SUB_TYPE_MEMORY: {
|
|
|
|
struct efi_device_path_memory *mdp =
|
|
|
|
(struct efi_device_path_memory *)dp;
|
2017-11-26 13:05:09 +00:00
|
|
|
s += sprintf(s, "MemoryMapped(0x%x,0x%llx,0x%llx)",
|
2017-10-10 12:23:06 +00:00
|
|
|
mdp->memory_type,
|
|
|
|
mdp->start_address,
|
|
|
|
mdp->end_address);
|
|
|
|
break;
|
|
|
|
}
|
2017-09-13 22:05:30 +00:00
|
|
|
case DEVICE_PATH_SUB_TYPE_VENDOR: {
|
2019-09-04 10:52:01 +00:00
|
|
|
int i, n;
|
2017-09-13 22:05:30 +00:00
|
|
|
struct efi_device_path_vendor *vdp =
|
|
|
|
(struct efi_device_path_vendor *)dp;
|
2019-09-04 10:52:01 +00:00
|
|
|
|
|
|
|
s += sprintf(s, "VenHw(%pUl", &vdp->guid);
|
|
|
|
n = (int)vdp->dp.length - sizeof(struct efi_device_path_vendor);
|
2021-02-23 20:15:35 +00:00
|
|
|
/* Node must fit into MAX_NODE_LEN) */
|
|
|
|
if (n > 0 && n < MAX_NODE_LEN / 2 - 22) {
|
2019-09-04 10:52:01 +00:00
|
|
|
s += sprintf(s, ",");
|
|
|
|
for (i = 0; i < n; ++i)
|
|
|
|
s += sprintf(s, "%02x", vdp->vendor_data[i]);
|
|
|
|
}
|
|
|
|
s += sprintf(s, ")");
|
2017-09-13 22:05:30 +00:00
|
|
|
break;
|
|
|
|
}
|
2023-03-19 15:18:08 +00:00
|
|
|
case DEVICE_PATH_SUB_TYPE_CONTROLLER: {
|
|
|
|
struct efi_device_path_controller *cdp =
|
|
|
|
(struct efi_device_path_controller *)dp;
|
|
|
|
|
|
|
|
s += sprintf(s, "Ctrl(0x%0x)", cdp->controller_number);
|
|
|
|
break;
|
|
|
|
}
|
2017-09-13 22:05:30 +00:00
|
|
|
default:
|
|
|
|
s = dp_unknown(s, dp);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *dp_acpi(char *s, struct efi_device_path *dp)
|
|
|
|
{
|
|
|
|
switch (dp->sub_type) {
|
|
|
|
case DEVICE_PATH_SUB_TYPE_ACPI_DEVICE: {
|
|
|
|
struct efi_device_path_acpi_path *adp =
|
|
|
|
(struct efi_device_path_acpi_path *)dp;
|
2019-05-11 21:11:48 +00:00
|
|
|
|
2019-05-16 05:37:22 +00:00
|
|
|
s += sprintf(s, "Acpi(PNP%04X,%d)", EISA_PNP_NUM(adp->hid),
|
|
|
|
adp->uid);
|
2017-09-13 22:05:30 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
s = dp_unknown(s, dp);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *dp_msging(char *s, struct efi_device_path *dp)
|
|
|
|
{
|
|
|
|
switch (dp->sub_type) {
|
2017-12-11 11:56:44 +00:00
|
|
|
case DEVICE_PATH_SUB_TYPE_MSG_ATAPI: {
|
|
|
|
struct efi_device_path_atapi *ide =
|
|
|
|
(struct efi_device_path_atapi *)dp;
|
|
|
|
s += sprintf(s, "Ata(%d,%d,%d)", ide->primary_secondary,
|
|
|
|
ide->slave_master, ide->logical_unit_number);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case DEVICE_PATH_SUB_TYPE_MSG_SCSI: {
|
|
|
|
struct efi_device_path_scsi *ide =
|
|
|
|
(struct efi_device_path_scsi *)dp;
|
|
|
|
s += sprintf(s, "Scsi(%u,%u)", ide->target_id,
|
|
|
|
ide->logical_unit_number);
|
|
|
|
break;
|
|
|
|
}
|
2021-03-19 01:49:54 +00:00
|
|
|
case DEVICE_PATH_SUB_TYPE_MSG_UART: {
|
|
|
|
struct efi_device_path_uart *uart =
|
|
|
|
(struct efi_device_path_uart *)dp;
|
2022-02-04 15:36:49 +00:00
|
|
|
const char parity_str[6] = {'D', 'N', 'E', 'O', 'M', 'S'};
|
|
|
|
const char *stop_bits_str[4] = { "D", "1", "1.5", "2" };
|
|
|
|
|
|
|
|
s += sprintf(s, "Uart(%lld,%d,", uart->baud_rate,
|
|
|
|
uart->data_bits);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Parity and stop bits can either both use keywords or both use
|
|
|
|
* numbers but numbers and keywords should not be mixed. Let's
|
|
|
|
* go for keywords as this is what EDK II does. For illegal
|
|
|
|
* values fall back to numbers.
|
|
|
|
*/
|
|
|
|
if (uart->parity < 6)
|
|
|
|
s += sprintf(s, "%c,", parity_str[uart->parity]);
|
|
|
|
else
|
|
|
|
s += sprintf(s, "%d,", uart->parity);
|
|
|
|
if (uart->stop_bits < 4)
|
|
|
|
s += sprintf(s, "%s)", stop_bits_str[uart->stop_bits]);
|
|
|
|
else
|
2021-03-19 01:49:54 +00:00
|
|
|
s += sprintf(s, "%d)", uart->stop_bits);
|
|
|
|
break;
|
|
|
|
}
|
2017-09-13 22:05:30 +00:00
|
|
|
case DEVICE_PATH_SUB_TYPE_MSG_USB: {
|
|
|
|
struct efi_device_path_usb *udp =
|
|
|
|
(struct efi_device_path_usb *)dp;
|
2017-12-11 11:56:41 +00:00
|
|
|
s += sprintf(s, "USB(0x%x,0x%x)", udp->parent_port_number,
|
2017-09-13 22:05:30 +00:00
|
|
|
udp->usb_interface);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case DEVICE_PATH_SUB_TYPE_MSG_MAC_ADDR: {
|
2019-09-04 11:32:05 +00:00
|
|
|
int i, n = sizeof(struct efi_mac_addr);
|
2017-09-13 22:05:30 +00:00
|
|
|
struct efi_device_path_mac_addr *mdp =
|
|
|
|
(struct efi_device_path_mac_addr *)dp;
|
|
|
|
|
2019-09-04 11:32:05 +00:00
|
|
|
if (mdp->if_type <= 1)
|
|
|
|
n = 6;
|
|
|
|
s += sprintf(s, "MAC(");
|
|
|
|
for (i = 0; i < n; ++i)
|
|
|
|
s += sprintf(s, "%02x", mdp->mac.addr[i]);
|
|
|
|
s += sprintf(s, ",%u)", mdp->if_type);
|
2017-09-13 22:05:30 +00:00
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case DEVICE_PATH_SUB_TYPE_MSG_USB_CLASS: {
|
|
|
|
struct efi_device_path_usb_class *ucdp =
|
|
|
|
(struct efi_device_path_usb_class *)dp;
|
|
|
|
|
2019-09-04 12:30:41 +00:00
|
|
|
s += sprintf(s, "UsbClass(0x%x,0x%x,0x%x,0x%x,0x%x)",
|
2017-09-13 22:05:30 +00:00
|
|
|
ucdp->vendor_id, ucdp->product_id,
|
|
|
|
ucdp->device_class, ucdp->device_subclass,
|
|
|
|
ucdp->device_protocol);
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
efi_loader: device path for SATA devices
Provide device path nodes for SATA devices.
This avoids creation of two handles with the same device path indicating
our root node.
This is what the device paths for a SATA drive with four partitions could
like:
/VenHw(..)/Sata(0x0,0xffff,0x0)
/VenHw(..)/Sata(0x0,0xffff,0x0)/HD(1,MBR,0x81ea591f,0x800,0x63ff830)
/VenHw(..)/Sata(0x0,0xffff,0x0)/HD(2,MBR,0x81ea591f,0x6400800,0x9ff830)
/VenHw(..)/Sata(0x0,0xffff,0x0)/HD(3,MBR,0x81ea591f,0x6e00800,0x16ef2ab0)
/VenHw(..)/Sata(0x0,0xffff,0x0)/HD(4,MBR,0x81ea591f,0x1dcf3800,0x1dcedab0)
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
2020-05-20 21:12:02 +00:00
|
|
|
case DEVICE_PATH_SUB_TYPE_MSG_SATA: {
|
|
|
|
struct efi_device_path_sata *sdp =
|
|
|
|
(struct efi_device_path_sata *) dp;
|
|
|
|
|
|
|
|
s += sprintf(s, "Sata(0x%x,0x%x,0x%x)",
|
|
|
|
sdp->hba_port,
|
|
|
|
sdp->port_multiplier_port,
|
|
|
|
sdp->logical_unit_number);
|
|
|
|
break;
|
|
|
|
}
|
2019-10-03 14:24:17 +00:00
|
|
|
case DEVICE_PATH_SUB_TYPE_MSG_NVME: {
|
|
|
|
struct efi_device_path_nvme *ndp =
|
|
|
|
(struct efi_device_path_nvme *)dp;
|
|
|
|
u32 ns_id;
|
|
|
|
|
|
|
|
memcpy(&ns_id, &ndp->ns_id, sizeof(ns_id));
|
|
|
|
s += sprintf(s, "NVMe(0x%x,", ns_id);
|
efi_loader: fix display of NVMe EUI-64
UEFI specification 2.9A requires to display the EUI-64 "in hexadecimal
format with byte 7 first (i.e., on the left) and byte 0 last".
This is in contrast to what the NVMe specification wants.
But it is what EDK II has been implementing.
Here is an example with the patch applied:
qemu-system-aarch64 -machine virt -cpu cortex-a72 -nographic \
-bios denx/u-boot.bin \
-device nvme,id=nvme1,serial=9ff81223 \
-device nvme-ns,bus=nvme1,drive=nvme1n0,eui64=0x123456789ABCDEF0 \
-drive file=arm64.img,if=none,format=raw,id=nvme1n0
=> nvme scan
=> efidebug devices
Device Path
====================
/VenHw(…)/NVMe(0x1,f0-de-bc-9a-78-56-34-12)
Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
2022-02-23 08:06:24 +00:00
|
|
|
|
|
|
|
/* Display byte 7 first, byte 0 last */
|
|
|
|
for (int i = 0; i < 8; ++i)
|
2019-10-03 14:24:17 +00:00
|
|
|
s += sprintf(s, "%s%02x", i ? "-" : "",
|
efi_loader: fix display of NVMe EUI-64
UEFI specification 2.9A requires to display the EUI-64 "in hexadecimal
format with byte 7 first (i.e., on the left) and byte 0 last".
This is in contrast to what the NVMe specification wants.
But it is what EDK II has been implementing.
Here is an example with the patch applied:
qemu-system-aarch64 -machine virt -cpu cortex-a72 -nographic \
-bios denx/u-boot.bin \
-device nvme,id=nvme1,serial=9ff81223 \
-device nvme-ns,bus=nvme1,drive=nvme1n0,eui64=0x123456789ABCDEF0 \
-drive file=arm64.img,if=none,format=raw,id=nvme1n0
=> nvme scan
=> efidebug devices
Device Path
====================
/VenHw(…)/NVMe(0x1,f0-de-bc-9a-78-56-34-12)
Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
2022-02-23 08:06:24 +00:00
|
|
|
ndp->eui64[i ^ 7]);
|
2019-10-03 14:24:17 +00:00
|
|
|
s += sprintf(s, ")");
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
2021-08-05 21:10:05 +00:00
|
|
|
case DEVICE_PATH_SUB_TYPE_MSG_URI: {
|
|
|
|
struct efi_device_path_uri *udp =
|
|
|
|
(struct efi_device_path_uri *)dp;
|
|
|
|
int n;
|
|
|
|
|
|
|
|
n = (int)udp->dp.length - sizeof(struct efi_device_path_uri);
|
|
|
|
|
|
|
|
s += sprintf(s, "Uri(");
|
|
|
|
if (n > 0 && n < MAX_NODE_LEN - 6)
|
|
|
|
s += snprintf(s, n, "%s", (char *)udp->uri);
|
|
|
|
s += sprintf(s, ")");
|
|
|
|
break;
|
|
|
|
}
|
2017-09-13 22:05:30 +00:00
|
|
|
case DEVICE_PATH_SUB_TYPE_MSG_SD:
|
|
|
|
case DEVICE_PATH_SUB_TYPE_MSG_MMC: {
|
|
|
|
const char *typename =
|
|
|
|
(dp->sub_type == DEVICE_PATH_SUB_TYPE_MSG_SD) ?
|
2017-12-11 11:56:41 +00:00
|
|
|
"SD" : "eMMC";
|
2017-09-13 22:05:30 +00:00
|
|
|
struct efi_device_path_sd_mmc_path *sddp =
|
|
|
|
(struct efi_device_path_sd_mmc_path *)dp;
|
2017-12-11 11:56:41 +00:00
|
|
|
s += sprintf(s, "%s(%u)", typename, sddp->slot_number);
|
2017-09-13 22:05:30 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
s = dp_unknown(s, dp);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
2017-12-11 11:56:41 +00:00
|
|
|
/*
|
|
|
|
* Convert a media device path node to text.
|
|
|
|
*
|
|
|
|
* @s output buffer
|
|
|
|
* @dp device path node
|
2022-01-19 17:05:50 +00:00
|
|
|
* Return: next unused buffer address
|
2017-12-11 11:56:41 +00:00
|
|
|
*/
|
2017-09-13 22:05:30 +00:00
|
|
|
static char *dp_media(char *s, struct efi_device_path *dp)
|
|
|
|
{
|
|
|
|
switch (dp->sub_type) {
|
|
|
|
case DEVICE_PATH_SUB_TYPE_HARD_DRIVE_PATH: {
|
|
|
|
struct efi_device_path_hard_drive_path *hddp =
|
|
|
|
(struct efi_device_path_hard_drive_path *)dp;
|
|
|
|
void *sig = hddp->partition_signature;
|
2017-12-11 11:56:41 +00:00
|
|
|
u64 start;
|
|
|
|
u64 end;
|
|
|
|
|
|
|
|
/* Copy from packed structure to aligned memory */
|
|
|
|
memcpy(&start, &hddp->partition_start, sizeof(start));
|
|
|
|
memcpy(&end, &hddp->partition_end, sizeof(end));
|
2017-09-13 22:05:30 +00:00
|
|
|
|
|
|
|
switch (hddp->signature_type) {
|
2017-12-11 11:56:41 +00:00
|
|
|
case SIG_TYPE_MBR: {
|
|
|
|
u32 signature;
|
|
|
|
|
|
|
|
memcpy(&signature, sig, sizeof(signature));
|
|
|
|
s += sprintf(
|
|
|
|
s, "HD(%d,MBR,0x%08x,0x%llx,0x%llx)",
|
|
|
|
hddp->partition_number, signature, start, end);
|
2017-09-13 22:05:30 +00:00
|
|
|
break;
|
2017-12-11 11:56:41 +00:00
|
|
|
}
|
2017-09-13 22:05:30 +00:00
|
|
|
case SIG_TYPE_GUID:
|
2017-12-11 11:56:41 +00:00
|
|
|
s += sprintf(
|
|
|
|
s, "HD(%d,GPT,%pUl,0x%llx,0x%llx)",
|
|
|
|
hddp->partition_number, sig, start, end);
|
2017-11-30 14:02:45 +00:00
|
|
|
break;
|
2017-09-13 22:05:30 +00:00
|
|
|
default:
|
2017-12-11 11:56:41 +00:00
|
|
|
s += sprintf(
|
|
|
|
s, "HD(%d,0x%02x,0,0x%llx,0x%llx)",
|
|
|
|
hddp->partition_number, hddp->partmap_type,
|
|
|
|
start, end);
|
2017-11-30 14:02:45 +00:00
|
|
|
break;
|
2017-09-13 22:05:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case DEVICE_PATH_SUB_TYPE_CDROM_PATH: {
|
|
|
|
struct efi_device_path_cdrom_path *cddp =
|
|
|
|
(struct efi_device_path_cdrom_path *)dp;
|
2019-09-04 11:56:01 +00:00
|
|
|
s += sprintf(s, "CDROM(%u,0x%llx,0x%llx)", cddp->boot_entry,
|
|
|
|
cddp->partition_start, cddp->partition_size);
|
2017-09-13 22:05:30 +00:00
|
|
|
break;
|
|
|
|
}
|
2021-02-03 17:46:07 +00:00
|
|
|
case DEVICE_PATH_SUB_TYPE_VENDOR_PATH: {
|
|
|
|
int i, n;
|
|
|
|
struct efi_device_path_vendor *vdp =
|
|
|
|
(struct efi_device_path_vendor *)dp;
|
|
|
|
|
|
|
|
s += sprintf(s, "VenMedia(%pUl", &vdp->guid);
|
|
|
|
n = (int)vdp->dp.length - sizeof(struct efi_device_path_vendor);
|
2021-02-23 20:15:35 +00:00
|
|
|
/* Node must fit into MAX_NODE_LEN) */
|
|
|
|
if (n > 0 && n < MAX_NODE_LEN / 2 - 24) {
|
2021-02-03 17:46:07 +00:00
|
|
|
s += sprintf(s, ",");
|
|
|
|
for (i = 0; i < n; ++i)
|
|
|
|
s += sprintf(s, "%02x", vdp->vendor_data[i]);
|
|
|
|
}
|
|
|
|
s += sprintf(s, ")");
|
|
|
|
break;
|
|
|
|
}
|
2017-09-13 22:05:30 +00:00
|
|
|
case DEVICE_PATH_SUB_TYPE_FILE_PATH: {
|
|
|
|
struct efi_device_path_file_path *fp =
|
|
|
|
(struct efi_device_path_file_path *)dp;
|
2022-01-29 18:01:07 +00:00
|
|
|
u16 *buffer;
|
|
|
|
int slen = dp->length - sizeof(*dp);
|
|
|
|
|
|
|
|
/* two bytes for \0, extra byte if dp->length is odd */
|
|
|
|
buffer = calloc(1, slen + 3);
|
|
|
|
if (!buffer) {
|
|
|
|
log_err("Out of memory\n");
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
memcpy(buffer, fp->str, dp->length - sizeof(*dp));
|
|
|
|
s += snprintf(s, MAX_NODE_LEN - 1, "%ls", buffer);
|
|
|
|
free(buffer);
|
2017-09-13 22:05:30 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
s = dp_unknown(s, dp);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
2017-11-26 13:05:09 +00:00
|
|
|
/*
|
|
|
|
* Converts a single node to a char string.
|
|
|
|
*
|
|
|
|
* @buffer output buffer
|
|
|
|
* @dp device path or node
|
2022-01-19 17:05:50 +00:00
|
|
|
* Return: end of string
|
2017-11-26 13:05:09 +00:00
|
|
|
*/
|
|
|
|
static char *efi_convert_single_device_node_to_text(
|
|
|
|
char *buffer,
|
|
|
|
struct efi_device_path *dp)
|
2017-07-11 20:06:25 +00:00
|
|
|
{
|
2017-11-26 13:05:09 +00:00
|
|
|
char *str = buffer;
|
2017-07-11 20:06:25 +00:00
|
|
|
|
2017-11-26 13:05:09 +00:00
|
|
|
switch (dp->type) {
|
|
|
|
case DEVICE_PATH_TYPE_HARDWARE_DEVICE:
|
|
|
|
str = dp_hardware(str, dp);
|
|
|
|
break;
|
|
|
|
case DEVICE_PATH_TYPE_ACPI_DEVICE:
|
|
|
|
str = dp_acpi(str, dp);
|
|
|
|
break;
|
|
|
|
case DEVICE_PATH_TYPE_MESSAGING_DEVICE:
|
|
|
|
str = dp_msging(str, dp);
|
|
|
|
break;
|
|
|
|
case DEVICE_PATH_TYPE_MEDIA_DEVICE:
|
|
|
|
str = dp_media(str, dp);
|
|
|
|
break;
|
2018-01-14 16:05:57 +00:00
|
|
|
case DEVICE_PATH_TYPE_END:
|
|
|
|
break;
|
2017-11-26 13:05:09 +00:00
|
|
|
default:
|
|
|
|
str = dp_unknown(str, dp);
|
2017-07-11 20:06:25 +00:00
|
|
|
}
|
|
|
|
|
2017-11-26 13:05:09 +00:00
|
|
|
*str = '\0';
|
|
|
|
return str;
|
2017-07-11 20:06:25 +00:00
|
|
|
}
|
|
|
|
|
2017-11-23 21:21:58 +00:00
|
|
|
/*
|
|
|
|
* This function implements the ConvertDeviceNodeToText service of the
|
|
|
|
* EFI_DEVICE_PATH_TO_TEXT_PROTOCOL.
|
|
|
|
* See the Unified Extensible Firmware Interface (UEFI) specification
|
|
|
|
* for details.
|
|
|
|
*
|
|
|
|
* device_node device node to be converted
|
2018-10-18 19:51:38 +00:00
|
|
|
* display_only true if the shorter text representation shall be used
|
2017-11-23 21:21:58 +00:00
|
|
|
* allow_shortcuts true if shortcut forms may be used
|
2022-01-19 17:05:50 +00:00
|
|
|
* Return: text representation of the device path
|
2017-11-23 21:21:58 +00:00
|
|
|
* NULL if out of memory of device_path is NULL
|
|
|
|
*/
|
2017-11-26 13:05:09 +00:00
|
|
|
static uint16_t EFIAPI *efi_convert_device_node_to_text(
|
2017-09-13 22:05:29 +00:00
|
|
|
struct efi_device_path *device_node,
|
2017-07-21 17:12:08 +00:00
|
|
|
bool display_only,
|
|
|
|
bool allow_shortcuts)
|
|
|
|
{
|
2017-11-26 13:05:09 +00:00
|
|
|
char str[MAX_NODE_LEN];
|
|
|
|
uint16_t *text = NULL;
|
2017-07-21 17:12:08 +00:00
|
|
|
|
|
|
|
EFI_ENTRY("%p, %d, %d", device_node, display_only, allow_shortcuts);
|
|
|
|
|
2017-11-26 13:05:09 +00:00
|
|
|
if (!device_node)
|
|
|
|
goto out;
|
|
|
|
efi_convert_single_device_node_to_text(str, device_node);
|
|
|
|
|
|
|
|
text = efi_str_to_u16(str);
|
2017-07-21 17:12:08 +00:00
|
|
|
|
2017-11-26 13:05:09 +00:00
|
|
|
out:
|
2017-07-21 17:12:08 +00:00
|
|
|
EFI_EXIT(EFI_SUCCESS);
|
2017-11-26 13:05:09 +00:00
|
|
|
return text;
|
2017-07-21 17:12:08 +00:00
|
|
|
}
|
|
|
|
|
2017-11-23 21:21:58 +00:00
|
|
|
/*
|
|
|
|
* This function implements the ConvertDevicePathToText service of the
|
|
|
|
* EFI_DEVICE_PATH_TO_TEXT_PROTOCOL.
|
|
|
|
* See the Unified Extensible Firmware Interface (UEFI) specification
|
|
|
|
* for details.
|
|
|
|
*
|
|
|
|
* device_path device path to be converted
|
2018-10-18 19:51:38 +00:00
|
|
|
* display_only true if the shorter text representation shall be used
|
2017-11-23 21:21:58 +00:00
|
|
|
* allow_shortcuts true if shortcut forms may be used
|
2022-01-19 17:05:50 +00:00
|
|
|
* Return: text representation of the device path
|
2017-11-23 21:21:58 +00:00
|
|
|
* NULL if out of memory of device_path is NULL
|
|
|
|
*/
|
2017-07-21 17:12:08 +00:00
|
|
|
static uint16_t EFIAPI *efi_convert_device_path_to_text(
|
2017-09-13 22:05:29 +00:00
|
|
|
struct efi_device_path *device_path,
|
2017-07-21 17:12:08 +00:00
|
|
|
bool display_only,
|
|
|
|
bool allow_shortcuts)
|
|
|
|
{
|
2017-11-26 13:05:09 +00:00
|
|
|
uint16_t *text = NULL;
|
|
|
|
char buffer[MAX_PATH_LEN];
|
|
|
|
char *str = buffer;
|
2017-07-21 17:12:08 +00:00
|
|
|
|
|
|
|
EFI_ENTRY("%p, %d, %d", device_path, display_only, allow_shortcuts);
|
|
|
|
|
2017-11-26 13:05:09 +00:00
|
|
|
if (!device_path)
|
|
|
|
goto out;
|
2021-02-18 17:30:43 +00:00
|
|
|
while (device_path && str + MAX_NODE_LEN < buffer + MAX_PATH_LEN) {
|
|
|
|
if (device_path->type == DEVICE_PATH_TYPE_END) {
|
|
|
|
if (device_path->sub_type !=
|
|
|
|
DEVICE_PATH_SUB_TYPE_INSTANCE_END)
|
|
|
|
break;
|
|
|
|
*str++ = ',';
|
|
|
|
} else {
|
|
|
|
*str++ = '/';
|
|
|
|
str = efi_convert_single_device_node_to_text(
|
|
|
|
str, device_path);
|
|
|
|
}
|
|
|
|
*(u8 **)&device_path += device_path->length;
|
2017-11-26 13:05:09 +00:00
|
|
|
}
|
|
|
|
|
2022-07-26 05:45:18 +00:00
|
|
|
*str = 0;
|
2017-11-26 13:05:09 +00:00
|
|
|
text = efi_str_to_u16(buffer);
|
2017-07-21 17:12:08 +00:00
|
|
|
|
2017-11-26 13:05:09 +00:00
|
|
|
out:
|
2017-07-21 17:12:08 +00:00
|
|
|
EFI_EXIT(EFI_SUCCESS);
|
2017-11-26 13:05:09 +00:00
|
|
|
return text;
|
2017-07-21 17:12:08 +00:00
|
|
|
}
|
|
|
|
|
2017-11-26 13:05:08 +00:00
|
|
|
/* helper for debug prints.. efi_free_pool() the result. */
|
|
|
|
uint16_t *efi_dp_str(struct efi_device_path *dp)
|
|
|
|
{
|
|
|
|
return EFI_CALL(efi_convert_device_path_to_text(dp, true, true));
|
|
|
|
}
|
|
|
|
|
2017-07-11 20:06:25 +00:00
|
|
|
const struct efi_device_path_to_text_protocol efi_device_path_to_text = {
|
2017-11-26 13:05:09 +00:00
|
|
|
.convert_device_node_to_text = efi_convert_device_node_to_text,
|
2017-07-11 20:06:25 +00:00
|
|
|
.convert_device_path_to_text = efi_convert_device_path_to_text,
|
|
|
|
};
|