diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2019-10-25 10:06:41 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2019-10-25 10:06:41 +0000 |
commit | 4fc0d014dfc71ee9f760b687a8685e5765d07f43 (patch) | |
tree | 2396741fa2ffa1c6c72271af5ac129dfa8945ec6 /sys/arch/armv7/stand | |
parent | 5b38111c405857c323d6a7892398993e48caa3b1 (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/Makefile | 4 | ||||
-rw-r--r-- | sys/arch/armv7/stand/efiboot/conf.c | 5 | ||||
-rw-r--r-- | sys/arch/armv7/stand/efiboot/efiboot.c | 186 | ||||
-rw-r--r-- | sys/arch/armv7/stand/efiboot/efiboot.h | 6 | ||||
-rw-r--r-- | sys/arch/armv7/stand/efiboot/fdt.c | 71 | ||||
-rw-r--r-- | sys/arch/armv7/stand/efiboot/fdt.h | 5 |
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 |