efi_loader: Uart device path
When uploading an EFI binary via the UART we need to assign a device path.
* Provide devicepath node to text conversion for Uart() node.
* Provide function to create Uart() device path.
* Add UART support to efi_dp_from_name().
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
diff --git a/include/efi_api.h b/include/efi_api.h
index 48e48a6..4ccde1d 100644
--- a/include/efi_api.h
+++ b/include/efi_api.h
@@ -523,6 +523,7 @@
# define DEVICE_PATH_SUB_TYPE_MSG_SCSI 0x02
# define DEVICE_PATH_SUB_TYPE_MSG_USB 0x05
# define DEVICE_PATH_SUB_TYPE_MSG_MAC_ADDR 0x0b
+# define DEVICE_PATH_SUB_TYPE_MSG_UART 0x0e
# define DEVICE_PATH_SUB_TYPE_MSG_USB_CLASS 0x0f
# define DEVICE_PATH_SUB_TYPE_MSG_SATA 0x12
# define DEVICE_PATH_SUB_TYPE_MSG_NVME 0x17
@@ -542,6 +543,15 @@
u16 logical_unit_number;
} __packed;
+struct efi_device_path_uart {
+ struct efi_device_path dp;
+ u32 reserved;
+ u64 baud_rate;
+ u8 data_bits;
+ u8 parity;
+ u8 stop_bits;
+} __packed;
+
struct efi_device_path_usb {
struct efi_device_path dp;
u8 parent_port_number;
diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c
index c9315dd..398dbc6 100644
--- a/lib/efi_loader/efi_device_path.c
+++ b/lib/efi_loader/efi_device_path.c
@@ -960,6 +960,28 @@
return start;
}
+struct efi_device_path *efi_dp_from_uart(void)
+{
+ void *buf, *pos;
+ struct efi_device_path_uart *uart;
+ size_t dpsize = sizeof(ROOT) + sizeof(*uart) + sizeof(END);
+
+ buf = dp_alloc(dpsize);
+ if (!buf)
+ return NULL;
+ pos = buf;
+ memcpy(pos, &ROOT, sizeof(ROOT));
+ pos += sizeof(ROOT);
+ uart = pos;
+ uart->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
+ uart->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_UART;
+ uart->dp.length = sizeof(*uart);
+ pos += sizeof(*uart);
+ memcpy(pos, &END, sizeof(END));
+
+ return buf;
+}
+
#ifdef CONFIG_NET
struct efi_device_path *efi_dp_from_eth(void)
{
@@ -1086,7 +1108,6 @@
struct efi_device_path **device,
struct efi_device_path **file)
{
- int is_net;
struct blk_desc *desc = NULL;
struct disk_partition fs_partition;
int part = 0;
@@ -1096,8 +1117,15 @@
if (path && !file)
return EFI_INVALID_PARAMETER;
- is_net = !strcmp(dev, "Net");
- if (!is_net) {
+ if (!strcmp(dev, "Net")) {
+#ifdef CONFIG_NET
+ if (device)
+ *device = efi_dp_from_eth();
+#endif
+ } else if (!strcmp(dev, "Uart")) {
+ if (device)
+ *device = efi_dp_from_uart();
+ } else {
part = blk_get_device_part_str(dev, devnr, &desc, &fs_partition,
1);
if (part < 0 || !desc)
@@ -1105,11 +1133,6 @@
if (device)
*device = efi_dp_from_part(desc, part);
- } else {
-#ifdef CONFIG_NET
- if (device)
- *device = efi_dp_from_eth();
-#endif
}
if (!path)
@@ -1120,7 +1143,7 @@
s = filename;
while ((s = strchr(s, '/')))
*s++ = '\\';
- *file = efi_dp_from_file(is_net ? NULL : desc, part, filename);
+ *file = efi_dp_from_file(desc, part, filename);
if (!*file)
return EFI_INVALID_PARAMETER;
diff --git a/lib/efi_loader/efi_device_path_to_text.c b/lib/efi_loader/efi_device_path_to_text.c
index edc9fdc..43554cd 100644
--- a/lib/efi_loader/efi_device_path_to_text.c
+++ b/lib/efi_loader/efi_device_path_to_text.c
@@ -118,6 +118,19 @@
ide->logical_unit_number);
break;
}
+ case DEVICE_PATH_SUB_TYPE_MSG_UART: {
+ struct efi_device_path_uart *uart =
+ (struct efi_device_path_uart *)dp;
+ s += sprintf(s, "Uart(%lld,%d,%d,", uart->baud_rate,
+ uart->data_bits, uart->parity);
+ switch (uart->stop_bits) {
+ case 2:
+ s += sprintf(s, "1.5)");
+ default:
+ s += sprintf(s, "%d)", uart->stop_bits);
+ }
+ break;
+ }
case DEVICE_PATH_SUB_TYPE_MSG_USB: {
struct efi_device_path_usb *udp =
(struct efi_device_path_usb *)dp;