summaryrefslogtreecommitdiff
path: root/sys/arch/armv7/stand
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2019-10-25 10:06:41 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2019-10-25 10:06:41 +0000
commit4fc0d014dfc71ee9f760b687a8685e5765d07f43 (patch)
tree2396741fa2ffa1c6c72271af5ac129dfa8945ec6 /sys/arch/armv7/stand
parent5b38111c405857c323d6a7892398993e48caa3b1 (diff)
Make it possible to switch to framebuffer "glass" console in case it
isn't the default already. Same change as we made on arm64 two months ago. ok patrick@
Diffstat (limited to 'sys/arch/armv7/stand')
-rw-r--r--sys/arch/armv7/stand/efiboot/Makefile4
-rw-r--r--sys/arch/armv7/stand/efiboot/conf.c5
-rw-r--r--sys/arch/armv7/stand/efiboot/efiboot.c186
-rw-r--r--sys/arch/armv7/stand/efiboot/efiboot.h6
-rw-r--r--sys/arch/armv7/stand/efiboot/fdt.c71
-rw-r--r--sys/arch/armv7/stand/efiboot/fdt.h5
6 files changed, 266 insertions, 11 deletions
diff --git a/sys/arch/armv7/stand/efiboot/Makefile b/sys/arch/armv7/stand/efiboot/Makefile
index 9b054df13a8..43f78b723ec 100644
--- a/sys/arch/armv7/stand/efiboot/Makefile
+++ b/sys/arch/armv7/stand/efiboot/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.12 2019/08/03 15:22:20 deraadt Exp $
+# $OpenBSD: Makefile,v 1.13 2019/10/25 10:06:40 kettenis Exp $
NOMAN= #
@@ -34,7 +34,7 @@ SRCS+= ufs.c
SRCS+= arp.c ether.c globals.c in_cksum.c net.c netif.c netudp.c tftp.c
.PATH: ${S}/lib/libkern/arch/arm ${S}/lib/libkern
-SRCS+= divsi3.S divdi3.c moddi3.c qdivrem.c strlcpy.c strlen.c
+SRCS+= divsi3.S divdi3.c moddi3.c qdivrem.c strlcat.c strlcpy.c strlen.c
SRCS+= __aeabi_ldivmod.S
.PATH: ${S}/lib/libz
diff --git a/sys/arch/armv7/stand/efiboot/conf.c b/sys/arch/armv7/stand/efiboot/conf.c
index e0615de7a3a..b107e4009ca 100644
--- a/sys/arch/armv7/stand/efiboot/conf.c
+++ b/sys/arch/armv7/stand/efiboot/conf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: conf.c,v 1.19 2019/08/13 09:00:20 patrick Exp $ */
+/* $OpenBSD: conf.c,v 1.20 2019/10/25 10:06:40 kettenis Exp $ */
/*
* Copyright (c) 1996 Michael Shalayeff
@@ -36,7 +36,7 @@
#include "efidev.h"
#include "efipxe.h"
-const char version[] = "1.6";
+const char version[] = "1.7";
int debug = 0;
struct fs_ops file_system[] = {
@@ -57,6 +57,7 @@ int ndevs = nitems(devsw);
struct consdev constab[] = {
{ efi_cons_probe, efi_cons_init, efi_cons_getc, efi_cons_putc },
+ { efi_fb_probe, efi_fb_init, efi_cons_getc, efi_cons_putc },
{ NULL }
};
struct consdev *cn_tab;
diff --git a/sys/arch/armv7/stand/efiboot/efiboot.c b/sys/arch/armv7/stand/efiboot/efiboot.c
index f6ccb141b87..b26734ca581 100644
--- a/sys/arch/armv7/stand/efiboot/efiboot.c
+++ b/sys/arch/armv7/stand/efiboot/efiboot.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: efiboot.c,v 1.24 2019/04/25 20:19:30 naddy Exp $ */
+/* $OpenBSD: efiboot.c,v 1.25 2019/10/25 10:06:40 kettenis Exp $ */
/*
* Copyright (c) 2015 YASUOKA Masahiko <yasuoka@yasuoka.net>
@@ -52,6 +52,7 @@ UINT32 mmap_version;
static EFI_GUID imgp_guid = LOADED_IMAGE_PROTOCOL;
static EFI_GUID blkio_guid = BLOCK_IO_PROTOCOL;
static EFI_GUID devp_guid = DEVICE_PATH_PROTOCOL;
+static EFI_GUID gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
int efi_device_path_depth(EFI_DEVICE_PATH *dp, int);
int efi_device_path_ncmp(EFI_DEVICE_PATH *, EFI_DEVICE_PATH *, int);
@@ -94,11 +95,19 @@ efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *systab)
static SIMPLE_TEXT_OUTPUT_INTERFACE *conout;
static SIMPLE_INPUT_INTERFACE *conin;
+/*
+ * The device majors for these don't match the ones used by the
+ * kernel. That's fine. They're just used as an index into the cdevs
+ * array and never passed on to the kernel.
+ */
+static dev_t serial = makedev(0, 0);
+static dev_t framebuffer = makedev(1, 0);
+
void
efi_cons_probe(struct consdev *cn)
{
cn->cn_pri = CN_MIDPRI;
- cn->cn_dev = makedev(12, 0);
+ cn->cn_dev = serial;
}
void
@@ -159,6 +168,32 @@ efi_cons_putc(dev_t dev, int c)
conout->OutputString(conout, buf);
}
+void
+efi_fb_probe(struct consdev *cn)
+{
+ cn->cn_pri = CN_LOWPRI;
+ cn->cn_dev = framebuffer;
+}
+
+void
+efi_fb_init(struct consdev *cn)
+{
+ conin = ST->ConIn;
+ conout = ST->ConOut;
+}
+
+int
+efi_fb_getc(dev_t dev)
+{
+ return efi_cons_getc(dev);
+}
+
+void
+efi_fb_putc(dev_t dev, int c)
+{
+ efi_cons_putc(dev, c);
+}
+
static void
efi_heap_init(void)
{
@@ -285,6 +320,130 @@ struct board_id board_id_table[] = {
{ "ti,omap4-panda", 2791 },
};
+void
+efi_framebuffer(void)
+{
+ EFI_GRAPHICS_OUTPUT *gop;
+ EFI_STATUS status;
+ void *node, *child;
+ uint32_t acells, scells;
+ uint64_t base, size;
+ uint32_t reg[4];
+ uint32_t width, height, stride;
+ char *format;
+ char *prop;
+
+ /*
+ * Don't create a "simple-framebuffer" node if we already have
+ * one. Besides "/chosen", we also check under "/" since that
+ * is where the Raspberry Pi firmware puts it.
+ */
+ node = fdt_find_node("/chosen");
+ for (child = fdt_child_node(node); child;
+ child = fdt_next_node(child)) {
+ if (!fdt_node_is_compatible(child, "simple-framebuffer"))
+ continue;
+ if (fdt_node_property(child, "status", &prop) &&
+ strcmp(prop, "okay") == 0)
+ return;
+ }
+ node = fdt_find_node("/");
+ for (child = fdt_child_node(node); child;
+ child = fdt_next_node(child)) {
+ if (!fdt_node_is_compatible(child, "simple-framebuffer"))
+ continue;
+ if (fdt_node_property(child, "status", &prop) &&
+ strcmp(prop, "okay") == 0)
+ return;
+ }
+
+ status = EFI_CALL(BS->LocateProtocol, &gop_guid, NULL, (void **)&gop);
+ if (status != EFI_SUCCESS)
+ return;
+
+ /* Paranoia! */
+ if (gop == NULL || gop->Mode == NULL || gop->Mode->Info == NULL)
+ return;
+
+ /* We only support 32-bit pixel modes for now. */
+ switch (gop->Mode->Info->PixelFormat) {
+ case PixelRedGreenBlueReserved8BitPerColor:
+ format = "x8b8g8r8";
+ break;
+ case PixelBlueGreenRedReserved8BitPerColor:
+ format = "x8r8g8b8";
+ break;
+ default:
+ return;
+ }
+
+ base = gop->Mode->FrameBufferBase;
+ size = gop->Mode->FrameBufferSize;
+ width = htobe32(gop->Mode->Info->HorizontalResolution);
+ height = htobe32(gop->Mode->Info->VerticalResolution);
+ stride = htobe32(gop->Mode->Info->PixelsPerScanLine * 4);
+
+ node = fdt_find_node("/");
+ if (fdt_node_property_int(node, "#address-cells", &acells) != 1)
+ acells = 1;
+ if (fdt_node_property_int(node, "#size-cells", &scells) != 1)
+ scells = 1;
+ if (acells > 2 || scells > 2)
+ return;
+ if (acells >= 1)
+ reg[0] = htobe32(base);
+ if (acells == 2) {
+ reg[1] = reg[0];
+ reg[0] = htobe32(base >> 32);
+ }
+ if (scells >= 1)
+ reg[acells] = htobe32(size);
+ if (scells == 2) {
+ reg[acells + 1] = reg[acells];
+ reg[acells] = htobe32(size >> 32);
+ }
+
+ node = fdt_find_node("/chosen");
+ fdt_node_add_node(node, "framebuffer", &child);
+ fdt_node_add_property(child, "status", "okay", strlen("okay") + 1);
+ fdt_node_add_property(child, "format", format, strlen(format) + 1);
+ fdt_node_add_property(child, "stride", &stride, 4);
+ fdt_node_add_property(child, "height", &height, 4);
+ fdt_node_add_property(child, "width", &width, 4);
+ fdt_node_add_property(child, "reg", reg, (acells + scells) * 4);
+ fdt_node_add_property(child, "compatible",
+ "simple-framebuffer", strlen("simple-framebuffer") + 1);
+}
+
+void
+efi_console(void)
+{
+ char path[128];
+ void *node, *child;
+ char *prop;
+
+ if (cn_tab->cn_dev != framebuffer)
+ return;
+
+ /* Find the desired framebuffer node. */
+ node = fdt_find_node("/chosen");
+ for (child = fdt_child_node(node); child;
+ child = fdt_next_node(child)) {
+ if (!fdt_node_is_compatible(child, "simple-framebuffer"))
+ continue;
+ if (fdt_node_property(child, "status", &prop) &&
+ strcmp(prop, "okay") == 0)
+ break;
+ }
+ if (child == NULL)
+ return;
+
+ /* Point stdout-path at the framebuffer node. */
+ strlcpy(path, "/chosen/", sizeof(path));
+ strlcat(path, fdt_node_name(child), sizeof(path));
+ fdt_node_add_property(node, "stdout-path", path, strlen(path) + 1);
+}
+
char *bootmac = NULL;
static EFI_GUID fdt_guid = FDT_TABLE_GUID;
@@ -338,6 +497,9 @@ efi_makebootargs(char *bootargs, uint32_t *board_id)
fdt_node_add_property(node, "openbsd,uefi-mmap-desc-size", zero, 4);
fdt_node_add_property(node, "openbsd,uefi-mmap-desc-ver", zero, 4);
+ efi_framebuffer();
+ efi_console();
+
fdt_finalize();
node = fdt_find_node("/");
@@ -506,21 +668,39 @@ devboot(dev_t dev, char *p)
strlcpy(p, "tftp0a", 7);
}
+const char cdevs[][4] = { "com", "fb" };
+const int ncdevs = nitems(cdevs);
+
int
cnspeed(dev_t dev, int sp)
{
return 115200;
}
+char ttyname_buf[8];
+
char *
ttyname(int fd)
{
- return "com0";
+ snprintf(ttyname_buf, sizeof ttyname_buf, "%s%d",
+ cdevs[major(cn_tab->cn_dev)], minor(cn_tab->cn_dev));
+
+ return ttyname_buf;
}
dev_t
ttydev(char *name)
{
+ int i, unit = -1;
+ char *no = name + strlen(name) - 1;
+
+ while (no >= name && *no >= '0' && *no <= '9')
+ unit = (unit < 0 ? 0 : (unit * 10)) + *no-- - '0';
+ if (no < name || unit < 0)
+ return NODEV;
+ for (i = 0; i < ncdevs; i++)
+ if (strncmp(name, cdevs[i], no - name + 1) == 0)
+ return makedev(i, unit);
return NODEV;
}
diff --git a/sys/arch/armv7/stand/efiboot/efiboot.h b/sys/arch/armv7/stand/efiboot/efiboot.h
index 166be1c0526..b478d15c602 100644
--- a/sys/arch/armv7/stand/efiboot/efiboot.h
+++ b/sys/arch/armv7/stand/efiboot/efiboot.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: efiboot.h,v 1.4 2018/03/31 18:19:12 patrick Exp $ */
+/* $OpenBSD: efiboot.h,v 1.5 2019/10/25 10:06:40 kettenis Exp $ */
/*
* Copyright (c) 2015 YASUOKA Masahiko <yasuoka@yasuoka.net>
@@ -24,3 +24,7 @@ void efi_cons_probe(struct consdev *);
void efi_cons_init(struct consdev *);
int efi_cons_getc(dev_t);
void efi_cons_putc(dev_t, int);
+void efi_fb_probe(struct consdev *);
+void efi_fb_init(struct consdev *);
+int efi_fb_getc(dev_t);
+void efi_fb_putc(dev_t, int);
diff --git a/sys/arch/armv7/stand/efiboot/fdt.c b/sys/arch/armv7/stand/efiboot/fdt.c
index 7c1ba49f249..df353f696a3 100644
--- a/sys/arch/armv7/stand/efiboot/fdt.c
+++ b/sys/arch/armv7/stand/efiboot/fdt.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: fdt.c,v 1.5 2017/05/07 11:25:58 kettenis Exp $ */
+/* $OpenBSD: fdt.c,v 1.6 2019/10/25 10:06:40 kettenis Exp $ */
/*
* Copyright (c) 2009 Dariusz Swiderski <sfires@sfires.net>
@@ -148,7 +148,8 @@ fdt_add_str(char *name)
if (tree.memory > tree.strings)
tree.memory += len;
tree.end += len;
- memcpy(end, name, len);
+ memset(end, 0, len);
+ memcpy(end, name, strlen(name));
return (end - tree.strings);
}
@@ -293,6 +294,43 @@ fdt_node_add_property(void *node, char *name, void *data, int len)
return fdt_node_set_property(node, name, data, len);
}
+int
+fdt_node_add_node(void *node, char *name, void **child)
+{
+ size_t len = roundup(strlen(name) + 1, sizeof(uint32_t)) + 8;
+ uint32_t *ptr = (uint32_t *)node;
+
+ if (!tree_inited)
+ return 0;
+
+ if (betoh32(*ptr) != FDT_NODE_BEGIN)
+ return 0;
+
+ ptr = skip_node_name(ptr + 1);
+ ptr = skip_props(ptr);
+
+ /* skip children */
+ while (betoh32(*ptr) == FDT_NODE_BEGIN)
+ ptr = skip_node(ptr);
+
+ memmove((char *)ptr + len, ptr, tree.end - (char *)ptr);
+ tree.struct_size += len;
+ if (tree.strings > tree.tree)
+ tree.strings += len;
+ if (tree.memory > tree.tree)
+ tree.memory += len;
+ tree.end += len;
+
+ *child = ptr;
+ *ptr++ = htobe32(FDT_NODE_BEGIN);
+ memset(ptr, 0, len - 8);
+ memcpy(ptr, name, strlen(name));
+ ptr += (len - 8) / sizeof(uint32_t);
+ *ptr++ = htobe32(FDT_NODE_END);
+
+ return 1;
+}
+
/*
* Retrieves next node, skipping all the children nodes of the pointed node,
* returns pointer to next node, no matter if it exists or not.
@@ -356,6 +394,35 @@ fdt_next_node(void *node)
}
/*
+ * Retrieves node property as integers and puts them in the given
+ * integer array.
+ */
+int
+fdt_node_property_ints(void *node, char *name, int *out, int outlen)
+{
+ int *data;
+ int i, inlen;
+
+ inlen = fdt_node_property(node, name, (char **)&data) / sizeof(int);
+ if (inlen <= 0)
+ return -1;
+
+ for (i = 0; i < inlen && i < outlen; i++)
+ out[i] = betoh32(data[i]);
+
+ return i;
+}
+
+/*
+ * Retrieves node property as an integer.
+ */
+int
+fdt_node_property_int(void *node, char *name, int *out)
+{
+ return fdt_node_property_ints(node, name, out, 1);
+}
+
+/*
* Retrieves next node, skipping all the children nodes of the pointed node
*/
void *
diff --git a/sys/arch/armv7/stand/efiboot/fdt.h b/sys/arch/armv7/stand/efiboot/fdt.h
index 747cf7c29ed..8e9f7eccd2c 100644
--- a/sys/arch/armv7/stand/efiboot/fdt.h
+++ b/sys/arch/armv7/stand/efiboot/fdt.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: fdt.h,v 1.3 2017/05/07 11:25:58 kettenis Exp $ */
+/* $OpenBSD: fdt.h,v 1.4 2019/10/25 10:06:40 kettenis Exp $ */
/*
* Copyright (c) 2009 Dariusz Swiderski <sfires@sfires.net>
@@ -57,8 +57,11 @@ void *fdt_child_node(void *);
char *fdt_node_name(void *);
void *fdt_find_node(char *);
int fdt_node_property(void *, char *, char **);
+int fdt_node_property_int(void *, char *, int *);
+int fdt_node_property_ints(void *, char *, int *, int);
int fdt_node_set_property(void *, char *, void *, int);
int fdt_node_add_property(void *, char *, void *, int);
+int fdt_node_add_node(void *, char *, void **);
void *fdt_parent_node(void *);
int fdt_node_is_compatible(void *, const char *);
#ifdef DEBUG