efi_loader: Uart device path
authorHeinrich Schuchardt <xypron.glpk@gmx.de>
Fri, 19 Mar 2021 01:49:54 +0000 (02:49 +0100)
committerHeinrich Schuchardt <xypron.glpk@gmx.de>
Thu, 25 Mar 2021 19:09:17 +0000 (20:09 +0100)
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>
include/efi_api.h
lib/efi_loader/efi_device_path.c
lib/efi_loader/efi_device_path_to_text.c

index 48e48a6..4ccde1d 100644 (file)
@@ -523,6 +523,7 @@ struct efi_device_path_acpi_path {
 #  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 @@ struct efi_device_path_scsi {
        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;
index c9315dd..398dbc6 100644 (file)
@@ -960,6 +960,28 @@ struct efi_device_path *efi_dp_from_file(struct blk_desc *desc, int part,
        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 @@ efi_status_t efi_dp_from_name(const char *dev, const char *devnr,
                              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 @@ efi_status_t efi_dp_from_name(const char *dev, const char *devnr,
        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 @@ efi_status_t efi_dp_from_name(const char *dev, const char *devnr,
 
                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 @@ efi_status_t efi_dp_from_name(const char *dev, const char *devnr,
        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;
index edc9fdc..43554cd 100644 (file)
@@ -118,6 +118,19 @@ static char *dp_msging(char *s, struct efi_device_path *dp)
                             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;