summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2021-03-20 08:55:18 -0400
committerTom Rini <trini@konsulko.com>2021-03-20 08:55:18 -0400
commit1f9c3f13f6ad8595a0fb5ab2cb830583cdc0b60a (patch)
tree5ca30add717db7f20f70ff53acfb0875df805634
parent65f2e55b578779dcddc94f625762e08b11e4b018 (diff)
parent76b0a19022e22a5bbb84cd76d516bdb625a70417 (diff)
downloadu-boot-WIP/20Mar2021.tar.gz
Merge tag 'efi-2021-04-rc5-2' of https://source.denx.de/u-boot/custodians/u-boot-efiWIP/20Mar2021
Pull request efi-2021-04-rc5-2 Bug fixes: * re-enable loading UEFI binaries via UART * fix a NULL dereference in EFI console
-rw-r--r--cmd/load.c10
-rw-r--r--include/efi_api.h10
-rw-r--r--lib/efi_loader/efi_console.c51
-rw-r--r--lib/efi_loader/efi_device_path.c41
-rw-r--r--lib/efi_loader/efi_device_path_to_text.c13
5 files changed, 101 insertions, 24 deletions
diff --git a/cmd/load.c b/cmd/load.c
index 5bbc39baea..b7894d7db0 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 @@ static ulong load_serial_ymodem(ulong offset, int mode)
}
}
+ 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 48e48a6263..4ccde1d24d 100644
--- a/include/efi_api.h
+++ b/include/efi_api.h
@@ -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;
diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c
index c4003554c2..6040f3a99a 100644
--- a/lib/efi_loader/efi_console.c
+++ b/lib/efi_loader/efi_console.c
@@ -254,7 +254,7 @@ static bool cout_mode_matches(struct cout_mode *mode, int rows, int cols)
}
/**
- * 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 @@ out:
}
/**
+ * 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 @@ out:
*/
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 c9315dd458..398dbc699b 100644
--- a/lib/efi_loader/efi_device_path.c
+++ b/lib/efi_loader/efi_device_path.c
@@ -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;
diff --git a/lib/efi_loader/efi_device_path_to_text.c b/lib/efi_loader/efi_device_path_to_text.c
index edc9fdc387..43554cd771 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 @@ 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;