Merge tag 'efi-2021-04-rc5-2' of https://source.denx.de/u-boot/custodians/u-boot-efi

Pull request efi-2021-04-rc5-2

Bug fixes:

* re-enable loading UEFI binaries via UART
* fix a NULL dereference in EFI console
diff --git a/cmd/load.c b/cmd/load.c
index 5bbc39b..b7894d7 100644
--- a/cmd/load.c
+++ b/cmd/load.c
@@ -11,12 +11,14 @@
 #include <command.h>
 #include <console.h>
 #include <cpu_func.h>
+#include <efi_loader.h>
 #include <env.h>
+#include <exports.h>
 #include <flash.h>
 #include <image.h>
-#include <s_record.h>
+#include <mapmem.h>
 #include <net.h>
-#include <exports.h>
+#include <s_record.h>
 #include <serial.h>
 #include <xyzModem.h>
 #include <asm/cache.h>
@@ -996,6 +998,10 @@
 			}
 
 		}
+		if (IS_ENABLED(CONFIG_CMD_BOOTEFI))
+			efi_set_bootdev("Uart", "", "",
+					map_sysmem(offset, 0), size);
+
 	} else {
 		printf("%s\n", xyzModem_error(err));
 	}
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_console.c b/lib/efi_loader/efi_console.c
index c400355..6040f3a 100644
--- a/lib/efi_loader/efi_console.c
+++ b/lib/efi_loader/efi_console.c
@@ -254,7 +254,7 @@
 }
 
 /**
- * query_console_serial() - query console size
+ * query_console_serial() - query serial console size
  *
  * When using a serial console or the net console we can only devise the
  * terminal size by querying the terminal using ECMA-48 control sequences.
@@ -300,6 +300,37 @@
 }
 
 /**
+ * query_vidconsole() - query video console size
+ *
+ *
+ * @rows:	pointer to return number of rows
+ * @cols:	pointer to return number of columns
+ * Returns:	0 on success
+ */
+static int __maybe_unused query_vidconsole(int *rows, int *cols)
+{
+	const char *stdout_name = env_get("stdout");
+	struct stdio_dev *stdout_dev;
+	struct udevice *dev;
+	struct vidconsole_priv *priv;
+
+	if (!stdout_name || strncmp(stdout_name, "vidconsole", 10))
+		return -ENODEV;
+	stdout_dev = stdio_get_by_name("vidconsole");
+	if (!stdout_dev)
+		return -ENODEV;
+	dev = stdout_dev->priv;
+	if (!dev)
+		return -ENODEV;
+	priv = dev_get_uclass_priv(dev);
+	if (!priv)
+		return -ENODEV;
+	*rows = priv->rows;
+	*cols = priv->cols;
+	return 0;
+}
+
+/**
  * query_console_size() - update the mode table.
  *
  * By default the only mode available is 80x25. If the console has at least 50
@@ -308,21 +339,15 @@
  */
 static void query_console_size(void)
 {
-	const char *stdout_name = env_get("stdout");
 	int rows = 25, cols = 80;
+	int ret = -ENODEV;
 
-	if (stdout_name && !strncmp(stdout_name, "vidconsole", 10) &&
-	    IS_ENABLED(CONFIG_DM_VIDEO)) {
-		struct stdio_dev *stdout_dev =
-			stdio_get_by_name("vidconsole");
-		struct udevice *dev = stdout_dev->priv;
-		struct vidconsole_priv *priv =
-			dev_get_uclass_priv(dev);
-		rows = priv->rows;
-		cols = priv->cols;
-	} else if (query_console_serial(&rows, &cols)) {
+	if IS_ENABLED(CONFIG_DM_VIDEO)
+		ret = query_vidconsole(&rows, &cols);
+	if (ret)
+		ret = query_console_serial(&rows, &cols);
+	if (ret)
 		return;
-	}
 
 	/* Test if we can have Mode 1 */
 	if (cols >= 80 && rows >= 50) {
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;