diff options
Diffstat (limited to 'stand/efi')
46 files changed, 459 insertions, 876 deletions
diff --git a/stand/efi/Makefile.inc b/stand/efi/Makefile.inc index c2d803ddc1ab..9077c7ddebf7 100644 --- a/stand/efi/Makefile.inc +++ b/stand/efi/Makefile.inc @@ -21,8 +21,6 @@ CFLAGS+= -fPIC .if ${MACHINE_CPUARCH} == "amd64" EFI_TARGET= efi-app-x86_64 -.elif ${MACHINE_CPUARCH} == "i386" -EFI_TARGET= efi-app-ia32 .else EFI_TARGET= binary .endif diff --git a/stand/efi/boot1/Makefile b/stand/efi/boot1/Makefile index daedc627e5dc..b4d1a1ed085e 100644 --- a/stand/efi/boot1/Makefile +++ b/stand/efi/boot1/Makefile @@ -74,7 +74,7 @@ LDFLAGS+= -Wl,--no-dynamic-linker .if ${MACHINE_CPUARCH} == "aarch64" CFLAGS+= -mgeneral-regs-only .endif -.if ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_CPUARCH} == "i386" +.if ${MACHINE_CPUARCH} == "amd64" CFLAGS+= -fPIC LDFLAGS+= -Wl,-znocombreloc .endif @@ -82,9 +82,8 @@ LDFLAGS+= -Wl,-znocombreloc LIBEFI= ${BOOTOBJ}/efi/libefi/libefi.a # -# Add libsa for the runtime functions used by the compiler - for example -# __aeabi_* (arm) or __divdi3 (i386). -# as well as required string and memory functions for all platforms. +# Add libsa for the runtime functions used by the compiler as well as required +# string and memory functions for all platforms. # DPADD+= ${LIBEFI} ${LIBSA} LDADD+= ${LIBEFI} ${LIBSA} diff --git a/stand/efi/boot1/Makefile.depend b/stand/efi/boot1/Makefile.depend index ffc5430cceec..995af7195891 100644 --- a/stand/efi/boot1/Makefile.depend +++ b/stand/efi/boot1/Makefile.depend @@ -2,12 +2,8 @@ # Autogenerated - do NOT edit! DIRDEPS = \ - include \ - include/xlocale \ - lib/libmd \ stand/efi/libefi \ stand/libsa \ - stand/zfs \ .include <dirdeps.mk> diff --git a/stand/efi/boot1/boot1.c b/stand/efi/boot1/boot1.c index 088821ecd1f8..2f9801c8ea92 100644 --- a/stand/efi/boot1/boot1.c +++ b/stand/efi/boot1/boot1.c @@ -96,6 +96,26 @@ try_boot(const boot_module_t *mod, dev_info_t *dev, void *loaderbuf, size_t load buf = NULL; } + /* + * See if there's any env variables the module wants to set. If so, + * append it to any config present. + */ + if (mod->extra_env != NULL) { + const char *env = mod->extra_env(); + if (env != NULL) { + size_t newlen = cmdsize + strlen(env) + 1; + + cmd = realloc(cmd, newlen); + if (cmd == NULL) + goto errout; + if (cmdsize > 0) + strlcat(cmd, " ", newlen); + strlcat(cmd, env, newlen); + cmdsize = strlen(cmd); + free(__DECONST(char *, env)); + } + } + if ((status = BS->LoadImage(TRUE, IH, efi_devpath_last_node(dev->devpath), loaderbuf, loadersize, &loaderhandle)) != EFI_SUCCESS) { printf("Failed to load image provided by %s, size: %zu, (%lu)\n", diff --git a/stand/efi/boot1/boot_module.h b/stand/efi/boot1/boot_module.h index 99046fb53577..4ecfa4c72a83 100644 --- a/stand/efi/boot1/boot_module.h +++ b/stand/efi/boot1/boot_module.h @@ -94,6 +94,9 @@ typedef struct boot_module_t /* valid devices as found by probe. */ dev_info_t *(*devices)(void); + + /* return any environment variables to pass to next stage */ + const char *(*extra_env)(void); } boot_module_t; extern const boot_module_t *boot_modules[]; diff --git a/stand/efi/boot1/zfs_module.c b/stand/efi/boot1/zfs_module.c index 7aaca72e30f1..234b50084839 100644 --- a/stand/efi/boot1/zfs_module.c +++ b/stand/efi/boot1/zfs_module.c @@ -40,6 +40,8 @@ static dev_info_t *devices; +static char zfs_bootonce[VDEV_PAD_SIZE]; + uint64_t ldi_get_size(void *priv) { @@ -165,6 +167,16 @@ load(const char *filepath, dev_info_t *devinfo, void **bufp, size_t *bufsize) return (EFI_NOT_FOUND); } + /* + * OK. We've found a filesystem. Any attempt to use it should clear the + * 'once' flag. Prior to now, we'd not be able to clear it anyway. We + * don't care if we can't find the files to boot, or if there's a + * problem with it: we've tried to use it once we're able to mount the + * ZFS dataset. + */ + *zfs_bootonce = '\0'; + zfs_get_bootonce_spa(spa, OS_BOOTONCE, zfs_bootonce, sizeof(zfs_bootonce)); + if ((err = zfs_lookup(&zmount, filepath, &dn)) != 0) { if (err == ENOENT) { DPRINTF("Failed to find '%s' on pool '%s' (%d)\n", @@ -220,6 +232,18 @@ status(void) printf("\n"); } +static const char * +extra_env(void) +{ + char *rv = NULL; /* So we return NULL if asprintf fails */ + + if (*zfs_bootonce == '\0') + return NULL; + asprintf(&rv, "zfs-bootonce=%s", zfs_bootonce); + return (rv); +} + + static void init(void) { @@ -241,5 +265,6 @@ const boot_module_t zfs_module = .probe = probe, .load = load, .status = status, - .devices = _devices + .devices = _devices, + .extra_env = extra_env, }; diff --git a/stand/efi/fdt/efi_fdt.c b/stand/efi/fdt/efi_fdt.c index cf3cbabee722..21107bb2ccbf 100644 --- a/stand/efi/fdt/efi_fdt.c +++ b/stand/efi/fdt/efi_fdt.c @@ -1,6 +1,5 @@ /*- * Copyright (c) 2014 The FreeBSD Foundation - * All rights reserved. * * This software was developed by Andrew Turner under * sponsorship from the FreeBSD Foundation. diff --git a/stand/efi/gptboot/gptboot.efi.8 b/stand/efi/gptboot/gptboot.efi.8 index 134c5353e9f1..b4231fbf6d0c 100644 --- a/stand/efi/gptboot/gptboot.efi.8 +++ b/stand/efi/gptboot/gptboot.efi.8 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd April 6, 2021 +.Dd April 13, 2023 .Dt GPTBOOT.EFI 8 .Os .Sh NAME @@ -274,7 +274,7 @@ gpart set -a bootonce -i 2 ada0 appeared in .Fx 13.0 .Sh AUTHORS -This manual page written by +This manual page was written by .An Warner Losh Aq imp@FreeBSD.org . It is based heavily on the .Xr gptboot 8 diff --git a/stand/efi/include/efilib.h b/stand/efi/include/efilib.h index 903e1f0d00e5..df4ae6503760 100644 --- a/stand/efi/include/efilib.h +++ b/stand/efi/include/efilib.h @@ -85,9 +85,6 @@ efi_exit_boot_services(UINTN key) } int efi_getdev(void **vdev, const char *devspec, const char **path); -char *efi_fmtdev(void *vdev); -int efi_setcurrdev(struct env_var *ev, int flags, const void *value); - int efi_register_handles(struct devsw *, EFI_HANDLE *, EFI_HANDLE *, int); EFI_HANDLE efi_find_handle(struct devsw *, int); @@ -100,6 +97,7 @@ void efi_close_devpath(EFI_HANDLE); EFI_HANDLE efi_devpath_handle(EFI_DEVICE_PATH *); EFI_DEVICE_PATH *efi_devpath_last_node(EFI_DEVICE_PATH *); EFI_DEVICE_PATH *efi_devpath_trim(EFI_DEVICE_PATH *); +EFI_DEVICE_PATH *efi_devpath_next_instance(EFI_DEVICE_PATH *); bool efi_devpath_match(EFI_DEVICE_PATH *, EFI_DEVICE_PATH *); bool efi_devpath_match_node(EFI_DEVICE_PATH *, EFI_DEVICE_PATH *); bool efi_devpath_is_prefix(EFI_DEVICE_PATH *, EFI_DEVICE_PATH *); diff --git a/stand/efi/libefi/Makefile b/stand/efi/libefi/Makefile index 8f1a30d86900..cf42e2b711f6 100644 --- a/stand/efi/libefi/Makefile +++ b/stand/efi/libefi/Makefile @@ -11,6 +11,7 @@ SRCS= delay.c \ efi_console.c \ efi_driver_utils.c \ efichar.c \ + eficom.c \ efienv.c \ efihttp.c \ efinet.c \ @@ -25,7 +26,7 @@ SRCS= delay.c \ .PATH: ${SYSDIR}/teken SRCS+= teken.c -.if ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_CPUARCH} == "i386" +.if ${MACHINE_CPUARCH} == "amd64" SRCS+= time.c .elif ${MACHINE_CPUARCH} == "arm" || ${MACHINE_CPUARCH} == "riscv" SRCS+= time_event.c diff --git a/stand/efi/libefi/devicename.c b/stand/efi/libefi/devicename.c index cdf4830697fd..ec821821bdf5 100644 --- a/stand/efi/libefi/devicename.c +++ b/stand/efi/libefi/devicename.c @@ -39,8 +39,6 @@ __FBSDID("$FreeBSD$"); #include <efilib.h> #include <efizfs.h> -static int efi_parsedev(struct devdesc **, const char *, const char **); - /* * Point (dev) at an allocated device specifier for the device matching the * path in (devspec). If it contains an explicit device specification, @@ -57,159 +55,11 @@ efi_getdev(void **vdev, const char *devspec, const char **path) * use the current device instead. */ if (devspec == NULL || *devspec == '/' || !strchr(devspec, ':')) { - rv = efi_parsedev(dev, getenv("currdev"), NULL); + rv = devparse(dev, getenv("currdev"), NULL); if (rv == 0 && path != NULL) *path = devspec; return (rv); } - /* Parse the device name off the beginning of the devspec. */ - return (efi_parsedev(dev, devspec, path)); -} - -/* - * Point (dev) at an allocated device specifier matching the string version - * at the beginning of (devspec). Return a pointer to the remaining - * text in (path). - * - * In all cases, the beginning of (devspec) is compared to the names - * of known devices in the device switch, and then any following text - * is parsed according to the rules applied to the device type. - * - * For disk-type devices, the syntax is: - * - * fs<unit>: - */ -static int -efi_parsedev(struct devdesc **dev, const char *devspec, const char **path) -{ - struct devdesc *idev; - struct devsw *dv; - int i, unit, err; - char *cp; - const char *np; - - /* minimum length check */ - if (strlen(devspec) < 2) - return (EINVAL); - - /* look for a device that matches */ - for (i = 0; devsw[i] != NULL; i++) { - dv = devsw[i]; - if (!strncmp(devspec, dv->dv_name, strlen(dv->dv_name))) - break; - } - if (devsw[i] == NULL) - return (ENOENT); - - np = devspec + strlen(dv->dv_name); - idev = NULL; - err = 0; - - switch (dv->dv_type) { - case DEVT_NONE: - break; - - case DEVT_DISK: - idev = malloc(sizeof(struct disk_devdesc)); - if (idev == NULL) - return (ENOMEM); - - err = disk_parsedev((struct disk_devdesc *)idev, np, path); - if (err != 0) - goto fail; - break; - -#ifdef EFI_ZFS_BOOT - case DEVT_ZFS: - idev = malloc(sizeof(struct zfs_devdesc)); - if (idev == NULL) - return (ENOMEM); - - err = zfs_parsedev((struct zfs_devdesc*)idev, np, path); - if (err != 0) - goto fail; - break; -#endif - default: - idev = malloc(sizeof(struct devdesc)); - if (idev == NULL) - return (ENOMEM); - - unit = 0; - cp = (char *)np; - - if (*np != '\0' && *np != ':') { - errno = 0; - unit = strtol(np, &cp, 0); - if (errno != 0 || cp == np) { - err = EUNIT; - goto fail; - } - } - if (*cp != '\0' && *cp != ':') { - err = EINVAL; - goto fail; - } - - idev->d_unit = unit; - if (path != NULL) - *path = (*cp == 0) ? cp : cp + 1; - break; - } - - idev->d_dev = dv; - - if (dev != NULL) - *dev = idev; - else - free(idev); - return (0); - -fail: - free(idev); - return (err); -} - -char * -efi_fmtdev(void *vdev) -{ - struct devdesc *dev = (struct devdesc *)vdev; - static char buf[SPECNAMELEN + 1]; - - switch(dev->d_dev->dv_type) { - case DEVT_NONE: - strcpy(buf, "(no device)"); - break; - - case DEVT_DISK: - return (disk_fmtdev(vdev)); - -#ifdef EFI_ZFS_BOOT - case DEVT_ZFS: - return (zfs_fmtdev(dev)); -#endif - default: - sprintf(buf, "%s%d:", dev->d_dev->dv_name, dev->d_unit); - break; - } - - return (buf); -} - -/* - * Set currdev to suit the value being supplied in (value) - */ -int -efi_setcurrdev(struct env_var *ev, int flags, const void *value) -{ - struct devdesc *ncurr; - int rv; - - rv = efi_parsedev(&ncurr, value, NULL); - if (rv != 0) - return (rv); - free(ncurr); - - return (mount_currdev(ev, flags, value)); + return (devparse(dev, devspec, path)); } diff --git a/stand/efi/libefi/devpath.c b/stand/efi/libefi/devpath.c index c25ae73e463c..94bb07540376 100644 --- a/stand/efi/libefi/devpath.c +++ b/stand/efi/libefi/devpath.c @@ -575,6 +575,23 @@ efi_devpath_last_node(EFI_DEVICE_PATH *devpath) return (devpath); } +/* + * Walk device path nodes, return next instance or end node. + */ +EFI_DEVICE_PATH * +efi_devpath_next_instance(EFI_DEVICE_PATH *devpath) +{ + while (!IsDevicePathEnd(devpath)) { + devpath = NextDevicePathNode(devpath); + if (IsDevicePathEndType(devpath) && + devpath->SubType == END_INSTANCE_DEVICE_PATH_SUBTYPE) { + devpath = NextDevicePathNode(devpath); + break; + } + } + return (devpath); +} + EFI_DEVICE_PATH * efi_devpath_trim(EFI_DEVICE_PATH *devpath) { diff --git a/stand/efi/loader/efiserialio.c b/stand/efi/libefi/eficom.c index 8b3f8e83e0b3..f5969cc5d42a 100644 --- a/stand/efi/loader/efiserialio.c +++ b/stand/efi/libefi/eficom.c @@ -34,25 +34,20 @@ __FBSDID("$FreeBSD$"); #include <efi.h> #include <efilib.h> -#include "loader_efi.h" - static EFI_GUID serial = SERIAL_IO_PROTOCOL; #define COMC_TXWAIT 0x40000 /* transmit timeout */ -#ifndef COMSPEED -#define COMSPEED 9600 -#endif - #define PNP0501 0x501 /* 16550A-compatible COM port */ struct serial { + uint64_t newbaudrate; uint64_t baudrate; - uint8_t databits; + uint32_t timeout; + uint32_t receivefifodepth; + uint32_t databits; EFI_PARITY_TYPE parity; EFI_STOP_BITS_TYPE stopbits; - uint8_t ignore_cd; /* boolean */ - uint8_t rtsdtr_off; /* boolean */ int ioaddr; /* index in handles array */ EFI_HANDLE currdev; /* current serial device */ EFI_HANDLE condev; /* EFI Console device */ @@ -72,16 +67,30 @@ static int comc_speed_set(struct env_var *, int, const void *); static struct serial *comc_port; extern struct console efi_console; +struct console eficom = { + .c_name = "eficom", + .c_desc = "serial port", + .c_flags = 0, + .c_probe = comc_probe, + .c_init = comc_init, + .c_out = comc_putchar, + .c_in = comc_getchar, + .c_ready = comc_ischar, +}; + +#if defined(__aarch64__) && __FreeBSD_version < 1500000 +static void comc_probe_compat(struct console *); struct console comconsole = { .c_name = "comconsole", .c_desc = "serial port", .c_flags = 0, - .c_probe = comc_probe, + .c_probe = comc_probe_compat, .c_init = comc_init, .c_out = comc_putchar, .c_in = comc_getchar, .c_ready = comc_ischar, }; +#endif static EFI_STATUS efi_serial_init(EFI_HANDLE **handlep, int *nhandles) @@ -245,6 +254,11 @@ comc_get_con_serial_handle(const char *name) return (NULL); } +/* + * Called from cons_probe() to see if this device is available. + * Return immediately on x86, except for hyperv, since it interferes with + * common configurations otherwise (yes, this is just firewalling the bug). + */ static void comc_probe(struct console *sc) { @@ -256,19 +270,28 @@ comc_probe(struct console *sc) char *env, *buf, *ep; size_t sz; +#ifdef __amd64__ + /* + * This driver tickles issues on a number of different firmware loads. + * It is only required for HyperV, and is only known to work on HyperV, + * so only allow it on HyperV. + */ + env = getenv("smbios.bios.version"); + if (env == NULL || strncmp(env, "Hyper-V", 7) != 0) { + return; + } +#endif + if (comc_port == NULL) { - comc_port = malloc(sizeof (struct serial)); + comc_port = calloc(1, sizeof (struct serial)); if (comc_port == NULL) return; } - comc_port->baudrate = COMSPEED; - comc_port->ioaddr = 0; /* default port */ - comc_port->databits = 8; /* 8,n,1 */ - comc_port->parity = NoParity; /* 8,n,1 */ - comc_port->stopbits = OneStopBit; /* 8,n,1 */ - comc_port->ignore_cd = 1; /* ignore cd */ - comc_port->rtsdtr_off = 0; /* rts-dtr is on */ - comc_port->sio = NULL; + + /* Use defaults from firmware */ + comc_port->databits = 8; + comc_port->parity = DefaultParity; + comc_port->stopbits = DefaultStopBits; handle = NULL; env = getenv("efi_com_port"); @@ -292,8 +315,28 @@ comc_probe(struct console *sc) (void**)&comc_port->sio, IH, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); - if (EFI_ERROR(status)) + if (EFI_ERROR(status)) { comc_port->sio = NULL; + } else { + comc_port->newbaudrate = + comc_port->baudrate = comc_port->sio->Mode->BaudRate; + comc_port->timeout = comc_port->sio->Mode->Timeout; + comc_port->receivefifodepth = + comc_port->sio->Mode->ReceiveFifoDepth; + comc_port->databits = comc_port->sio->Mode->DataBits; + comc_port->parity = comc_port->sio->Mode->Parity; + comc_port->stopbits = comc_port->sio->Mode->StopBits; + } + } + + /* + * If there's no sio, then the device isn't there, so just return since + * the present flags aren't yet set. + */ + if (comc_port->sio == NULL) { + free(comc_port); + comc_port = NULL; + return; } if (env != NULL) @@ -303,8 +346,12 @@ comc_probe(struct console *sc) comc_port_set, env_nounset); env = getenv("efi_com_speed"); + if (env == NULL) + /* fallback to comconsole setting */ + env = getenv("comconsole_speed"); + if (comc_parse_intval(env, &val) == CMD_OK) - comc_port->baudrate = val; + comc_port->newbaudrate = val; if (env != NULL) unsetenv("efi_com_speed"); @@ -312,19 +359,43 @@ comc_probe(struct console *sc) env_setenv("efi_com_speed", EV_VOLATILE, value, comc_speed_set, env_nounset); - comconsole.c_flags = 0; - if (comc_setup()) + if (comc_setup()) { sc->c_flags = C_PRESENTIN | C_PRESENTOUT; + } else { + sc->c_flags &= ~(C_PRESENTIN | C_PRESENTOUT); + free(comc_port); + comc_port = NULL; + } } +#if defined(__aarch64__) && __FreeBSD_version < 1500000 +static void +comc_probe_compat(struct console *sc) +{ + comc_probe(&eficom); + if (eficom.c_flags & (C_PRESENTIN | C_PRESENTOUT)) { + printf("comconsole: comconsole device name is deprecated, switch to eficom\n"); + } + /* + * Note: We leave the present bits unset in sc to avoid ghosting. + */ +} +#endif + +/* + * Called when the console is selected in cons_change. If we didn't detect the + * device, comc_port will be NULL, and comc_setup will fail. It may be called + * even when the device isn't present as a 'fallback' console or when listed + * specifically in console env, so we have to reset the c_flags in those case to + * say it's not present. + */ static int comc_init(int arg __unused) { - if (comc_setup()) return (CMD_OK); - comconsole.c_flags = 0; + eficom.c_flags &= ~(C_ACTIVEIN | C_ACTIVEOUT); return (CMD_ERROR); } @@ -426,7 +497,7 @@ comc_port_set(struct env_var *ev, int flags, const void *value) EFI_HANDLE handle; EFI_STATUS status; - if (value == NULL) + if (value == NULL || comc_port == NULL) return (CMD_ERROR); if (comc_parse_intval(value, &port) != CMD_OK) @@ -461,16 +532,15 @@ comc_speed_set(struct env_var *ev, int flags, const void *value) { unsigned speed; - if (value == NULL) + if (value == NULL || comc_port == NULL) return (CMD_ERROR); if (comc_parse_intval(value, &speed) != CMD_OK) return (CMD_ERROR); - comc_port->baudrate = speed; - (void) comc_setup(); - - env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL); + comc_port->newbaudrate = speed; + if (comc_setup()) + env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL); return (CMD_OK); } @@ -483,33 +553,52 @@ static bool comc_setup(void) { EFI_STATUS status; - UINT32 control; + char *ev; - /* port is not usable */ - if (comc_port->sio == NULL) + /* + * If the device isn't active, or there's no port present. + */ + if ((eficom.c_flags & (C_ACTIVEIN | C_ACTIVEOUT)) == 0 || comc_port == NULL) return (false); - status = comc_port->sio->Reset(comc_port->sio); - if (EFI_ERROR(status)) - return (false); + if (comc_port->sio->Reset != NULL) { + status = comc_port->sio->Reset(comc_port->sio); + if (EFI_ERROR(status)) + return (false); + } - status = comc_port->sio->SetAttributes(comc_port->sio, - comc_port->baudrate, 0, 0, comc_port->parity, - comc_port->databits, comc_port->stopbits); - if (EFI_ERROR(status)) - return (false); + /* + * Avoid setting the baud rate on Hyper-V. Also, only set the baud rate + * if the baud rate has changed from the default. And pass in '0' or + * DefaultFoo when we're not changing those values. Some EFI + * implementations get cranky when you set things to the values reported + * back even when they are unchanged. + */ + if (comc_port->sio->SetAttributes != NULL && + comc_port->newbaudrate != comc_port->baudrate) { + ev = getenv("smbios.bios.version"); + if (ev != NULL && strncmp(ev, "Hyper-V", 7) != 0) { + status = comc_port->sio->SetAttributes(comc_port->sio, + comc_port->newbaudrate, 0, 0, DefaultParity, 0, + DefaultStopBits); + if (EFI_ERROR(status)) + return (false); + comc_port->baudrate = comc_port->newbaudrate; + } + } - status = comc_port->sio->GetControl(comc_port->sio, &control); - if (EFI_ERROR(status)) - return (false); - if (comc_port->rtsdtr_off) { - control &= ~(EFI_SERIAL_REQUEST_TO_SEND | - EFI_SERIAL_DATA_TERMINAL_READY); - } else { +#ifdef EFI_FORCE_RTS + if (comc_port->sio->GetControl != NULL && comc_port->sio->SetControl != NULL) { + UINT32 control; + + status = comc_port->sio->GetControl(comc_port->sio, &control); + if (EFI_ERROR(status)) + return (false); control |= EFI_SERIAL_REQUEST_TO_SEND; + (void) comc_port->sio->SetControl(comc_port->sio, control); } - (void) comc_port->sio->SetControl(comc_port->sio, control); +#endif /* Mark this port usable. */ - comconsole.c_flags |= (C_PRESENTIN | C_PRESENTOUT); + eficom.c_flags |= (C_PRESENTIN | C_PRESENTOUT); return (true); } diff --git a/stand/efi/libefi/efihttp.c b/stand/efi/libefi/efihttp.c index 05d338fbaf04..b71ebd4274f0 100644 --- a/stand/efi/libefi/efihttp.c +++ b/stand/efi/libefi/efihttp.c @@ -1,5 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2019 Intel Corporation * @@ -94,7 +94,7 @@ struct devsw efihttp_dev = { .dv_close = efihttp_dev_close, .dv_ioctl = noioctl, .dv_print = NULL, - .dv_cleanup = NULL, + .dv_cleanup = nullsys, }; struct fs_ops efihttp_fsops = { diff --git a/stand/efi/libefi/efinet.c b/stand/efi/libefi/efinet.c index c52b11d32ec8..a6582bd2c1b5 100644 --- a/stand/efi/libefi/efinet.c +++ b/stand/efi/libefi/efinet.c @@ -351,7 +351,7 @@ struct devsw efinet_dev = { .dv_close = NULL, /* Will be set in efinet_dev_init */ .dv_ioctl = noioctl, .dv_print = efinet_dev_print, - .dv_cleanup = NULL + .dv_cleanup = nullsys, }; static int diff --git a/stand/efi/libefi/efipart.c b/stand/efi/libefi/efipart.c index 7807c17077a6..9a4d2b22ed20 100644 --- a/stand/efi/libefi/efipart.c +++ b/stand/efi/libefi/efipart.c @@ -78,7 +78,7 @@ struct devsw efipart_fddev = { .dv_close = efipart_close, .dv_ioctl = efipart_ioctl, .dv_print = efipart_printfd, - .dv_cleanup = NULL + .dv_cleanup = nullsys, }; struct devsw efipart_cddev = { @@ -90,7 +90,7 @@ struct devsw efipart_cddev = { .dv_close = efipart_close, .dv_ioctl = efipart_ioctl, .dv_print = efipart_printcd, - .dv_cleanup = NULL + .dv_cleanup = nullsys, }; struct devsw efipart_hddev = { @@ -102,7 +102,9 @@ struct devsw efipart_hddev = { .dv_close = efipart_close, .dv_ioctl = efipart_ioctl, .dv_print = efipart_printhd, - .dv_cleanup = NULL + .dv_cleanup = nullsys, + .dv_fmtdev = disk_fmtdev, + .dv_parsedev = disk_parsedev, }; static pdinfo_list_t fdinfo = STAILQ_HEAD_INITIALIZER(fdinfo); diff --git a/stand/efi/libefi/efizfs.c b/stand/efi/libefi/efizfs.c index 7f3986d47140..4fa336df1d59 100644 --- a/stand/efi/libefi/efizfs.c +++ b/stand/efi/libefi/efizfs.c @@ -115,7 +115,7 @@ efi_zfs_probe(void) snprintf(devname, sizeof(devname), "%s%dp%d:", efipart_hddev.dv_name, hd->pd_unit, pd->pd_unit); guid = 0; - if (zfs_probe_dev(devname, &guid) == 0) { + if (zfs_probe_dev(devname, &guid, false) == 0) { insert_zfs(pd->pd_handle, guid); if (pd->pd_handle == boot_img->DeviceHandle) pool_guid = guid; diff --git a/stand/efi/loader/Makefile b/stand/efi/loader/Makefile index 1edb5674712e..2de55a29813f 100644 --- a/stand/efi/loader/Makefile +++ b/stand/efi/loader/Makefile @@ -39,6 +39,8 @@ CFLAGS.bootinfo.c += -I$(SRCTOP)/sys/teken CFLAGS.bootinfo.c += -I${SRCTOP}/contrib/pnglite CFLAGS.framebuffer.c += -I$(SRCTOP)/sys/teken CFLAGS.framebuffer.c += -I${SRCTOP}/contrib/pnglite +CFLAGS.main.c += -I$(SRCTOP)/sys/teken +CFLAGS.main.c += -I${SRCTOP}/contrib/pnglite CFLAGS.gfx_fb.c += -I$(SRCTOP)/sys/teken CFLAGS.gfx_fb.c += -I${SRCTOP}/sys/cddl/contrib/opensolaris/common/lz4 CFLAGS.gfx_fb.c += -I${SRCTOP}/contrib/pnglite @@ -66,6 +68,7 @@ CFLAGS+= -DEFI .if defined(HAVE_FDT) && ${MK_FDT} != "no" .include "${BOOTSRC}/fdt.mk" LIBEFI_FDT= ${BOOTOBJ}/efi/fdt/libefi_fdt.a +HELP_FILES+= ${FDTSRC}/help.fdt .endif # Include bcache code. @@ -81,6 +84,7 @@ CFLAGS+= -DEFI_SECUREBOOT NEWVERSWHAT= "EFI loader" ${MACHINE} VERSION_FILE= ${.CURDIR}/../loader/version +HELP_FILENAME= loader.help.efi # Always add MI sources .include "${BOOTSRC}/loader.mk" @@ -103,7 +107,7 @@ LDFLAGS+= -Wl,-T${LDSCRIPT},-Bsymbolic,-znotext -pie LDFLAGS+= -Wl,--no-dynamic-linker .endif -CLEANFILES+= loader.efi +CLEANFILES+= ${LOADER}.efi ${LOADER}.efi: ${PROG} if ${NM} ${.ALLSRC} | grep ' U '; then \ diff --git a/stand/efi/loader/arch/amd64/amd64_tramp.S b/stand/efi/loader/arch/amd64/amd64_tramp.S index 877705407f92..7e15eeb4a035 100644 --- a/stand/efi/loader/arch/amd64/amd64_tramp.S +++ b/stand/efi/loader/arch/amd64/amd64_tramp.S @@ -1,6 +1,5 @@ /*- * Copyright (c) 2013 The FreeBSD Foundation - * All rights reserved. * * This software was developed by Benno Rice under sponsorship from * the FreeBSD Foundation. diff --git a/stand/efi/loader/arch/amd64/elf64_freebsd.c b/stand/efi/loader/arch/amd64/elf64_freebsd.c index 4bdf675cd5a3..290d1c4696da 100644 --- a/stand/efi/loader/arch/amd64/elf64_freebsd.c +++ b/stand/efi/loader/arch/amd64/elf64_freebsd.c @@ -119,12 +119,6 @@ elf64_exec(struct preloaded_file *fp) /* * Report the RSDP to the kernel. While this can be found with * a BIOS boot, the RSDP may be elsewhere when booted from UEFI. - * The old code used the 'hints' method to communite this to - * the kernel. However, while convenient, the 'hints' method - * is fragile and does not work when static hints are compiled - * into the kernel. Instead, move to setting different tunables - * that start with acpi. The old 'hints' can be removed before - * we branch for FreeBSD 12. */ rsdp = efi_get_table(&acpi20_guid); @@ -133,29 +127,23 @@ elf64_exec(struct preloaded_file *fp) } if (rsdp != NULL) { sprintf(buf, "0x%016llx", (unsigned long long)rsdp); - setenv("hint.acpi.0.rsdp", buf, 1); setenv("acpi.rsdp", buf, 1); revision = rsdp->Revision; if (revision == 0) revision = 1; sprintf(buf, "%d", revision); - setenv("hint.acpi.0.revision", buf, 1); setenv("acpi.revision", buf, 1); strncpy(buf, rsdp->OemId, sizeof(rsdp->OemId)); buf[sizeof(rsdp->OemId)] = '\0'; - setenv("hint.acpi.0.oem", buf, 1); setenv("acpi.oem", buf, 1); sprintf(buf, "0x%016x", rsdp->RsdtPhysicalAddress); - setenv("hint.acpi.0.rsdt", buf, 1); setenv("acpi.rsdt", buf, 1); if (revision >= 2) { /* XXX extended checksum? */ sprintf(buf, "0x%016llx", (unsigned long long)rsdp->XsdtPhysicalAddress); - setenv("hint.acpi.0.xsdt", buf, 1); setenv("acpi.xsdt", buf, 1); sprintf(buf, "%d", rsdp->Length); - setenv("hint.acpi.0.xsdt_length", buf, 1); setenv("acpi.xsdt_length", buf, 1); } } diff --git a/stand/efi/loader/arch/amd64/exc.S b/stand/efi/loader/arch/amd64/exc.S index 0035d4a37e20..19981e6e7152 100644 --- a/stand/efi/loader/arch/amd64/exc.S +++ b/stand/efi/loader/arch/amd64/exc.S @@ -1,6 +1,5 @@ /*- * Copyright (c) 2016 The FreeBSD Foundation - * All rights reserved. * * This software was developed by Konstantin Belousov under sponsorship * from the FreeBSD Foundation. diff --git a/stand/efi/loader/arch/amd64/trap.c b/stand/efi/loader/arch/amd64/trap.c index e8cf188cf22f..81357e558185 100644 --- a/stand/efi/loader/arch/amd64/trap.c +++ b/stand/efi/loader/arch/amd64/trap.c @@ -1,6 +1,5 @@ /*- * Copyright (c) 2016 The FreeBSD Foundation - * All rights reserved. * * This software was developed by Konstantin Belousov under sponsorship * from the FreeBSD Foundation. @@ -79,11 +78,21 @@ static uint32_t loader_tss; /* Loader TSS segment */ static struct region_descriptor fw_gdt; /* Descriptor of pristine GDT */ static EFI_PHYSICAL_ADDRESS loader_gdt_pa; /* Address of loader shadow GDT */ +struct frame { + struct frame *fr_savfp; + uintptr_t fr_savpc; +}; + void report_exc(struct trapframe *tf); void report_exc(struct trapframe *tf) { + struct frame *fp; + uintptr_t pc, base; + char buf[80]; + int ret; + base = (uintptr_t)boot_img->ImageBase; /* * printf() depends on loader runtime and UEFI firmware health * to produce the console output, in case of exception, the @@ -109,6 +118,33 @@ report_exc(struct trapframe *tf) tf->tf_rdi, tf->tf_rsi, tf->tf_rdx, tf->tf_rcx, tf->tf_r8, tf->tf_r9, tf->tf_rax, tf->tf_rbx, tf->tf_rbp, tf->tf_r10, tf->tf_r11, tf->tf_r12, tf->tf_r13, tf->tf_r14, tf->tf_r15); + + fp = (struct frame *)tf->tf_rbp; + pc = tf->tf_rip; + + printf("Stack trace:\n"); + pager_open(); + while (fp != NULL || pc != 0) { + char *source = "PC"; + + if (pc >= base && pc < base + boot_img->ImageSize) { + pc -= base; + source = "loader PC"; + } + (void) snprintf(buf, sizeof (buf), "FP %016lx: %s 0x%016lx\n", + (uintptr_t)fp, source, pc); + if (pager_output(buf)) + break; + + if (fp != NULL) + fp = fp->fr_savfp; + + if (fp != NULL) + pc = fp->fr_savpc; + else + pc = 0; + } + pager_close(); printf("Machine stopped.\n"); } diff --git a/stand/efi/loader/arch/arm/Makefile.inc b/stand/efi/loader/arch/arm/Makefile.inc index 284e517bfbb8..74e6616e991b 100644 --- a/stand/efi/loader/arch/arm/Makefile.inc +++ b/stand/efi/loader/arch/arm/Makefile.inc @@ -1,7 +1,6 @@ # $FreeBSD$ SRCS+= exec.c \ - efiserialio.c \ start.S HAVE_FDT=yes diff --git a/stand/efi/loader/arch/arm/exec.c b/stand/efi/loader/arch/arm/exec.c index a110f3d07cbc..2fecb2ea043a 100644 --- a/stand/efi/loader/arch/arm/exec.c +++ b/stand/efi/loader/arch/arm/exec.c @@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$"); #include "bootstrap.h" #include "loader_efi.h" -extern vm_offset_t md_load(char *, vm_offset_t *); extern int bi_load(char *, vm_offset_t *, vm_offset_t *, bool); static int diff --git a/stand/efi/loader/arch/arm64/Makefile.inc b/stand/efi/loader/arch/arm64/Makefile.inc index 9978d9c4ea9c..a71bcc2e1a1f 100644 --- a/stand/efi/loader/arch/arm64/Makefile.inc +++ b/stand/efi/loader/arch/arm64/Makefile.inc @@ -3,7 +3,6 @@ HAVE_FDT=yes SRCS+= exec.c \ - efiserialio.c \ start.S .PATH: ${BOOTSRC}/arm64/libarm64 diff --git a/stand/efi/loader/arch/arm64/exec.c b/stand/efi/loader/arch/arm64/exec.c index 6cf4a4fd8e4d..a8cd80cd0fc6 100644 --- a/stand/efi/loader/arch/arm64/exec.c +++ b/stand/efi/loader/arch/arm64/exec.c @@ -81,6 +81,13 @@ elf64_exec(struct preloaded_file *fp) int err, revision; void (*entry)(vm_offset_t); + /* + * Report the RSDP to the kernel. The old code used the 'hints' method + * to communicate this to the kernel, but this is now considered legacy. + * Instead, move to setting different tunables that start with acpi. + * The old 'hints' can be removed before we branch for FreeBSD 15. + */ + rsdp = efi_get_table(&acpi20_guid); if (rsdp == NULL) { rsdp = efi_get_table(&acpi_guid); @@ -88,23 +95,29 @@ elf64_exec(struct preloaded_file *fp) if (rsdp != NULL) { sprintf(buf, "0x%016llx", (unsigned long long)rsdp); setenv("hint.acpi.0.rsdp", buf, 1); + setenv("acpi.rsdp", buf, 1); revision = rsdp->Revision; if (revision == 0) revision = 1; sprintf(buf, "%d", revision); setenv("hint.acpi.0.revision", buf, 1); + setenv("acpi.revision", buf, 1); strncpy(buf, rsdp->OemId, sizeof(rsdp->OemId)); buf[sizeof(rsdp->OemId)] = '\0'; setenv("hint.acpi.0.oem", buf, 1); + setenv("acpi.oem", buf, 1); sprintf(buf, "0x%016x", rsdp->RsdtPhysicalAddress); setenv("hint.acpi.0.rsdt", buf, 1); + setenv("acpi.rsdt", buf, 1); if (revision >= 2) { /* XXX extended checksum? */ sprintf(buf, "0x%016llx", (unsigned long long)rsdp->XsdtPhysicalAddress); setenv("hint.acpi.0.xsdt", buf, 1); + setenv("acpi.xsdt", buf, 1); sprintf(buf, "%d", rsdp->Length); setenv("hint.acpi.0.xsdt_length", buf, 1); + setenv("acpi.xsdt_length", buf, 1); } } diff --git a/stand/efi/loader/arch/arm64/ldscript.arm64 b/stand/efi/loader/arch/arm64/ldscript.arm64 index d0ed320a319c..c10448f4180e 100644 --- a/stand/efi/loader/arch/arm64/ldscript.arm64 +++ b/stand/efi/loader/arch/arm64/ldscript.arm64 @@ -16,7 +16,9 @@ SECTIONS *(.gnu.warning) *(.plt) } =0xD4200000 - . = ALIGN(16); + . = ALIGN(4096); + _etext = .; + __data_start = .; .data : { *(.rodata .rodata.* .gnu.linkonce.r.*) *(.rodata1) @@ -78,6 +80,7 @@ SECTIONS . = ALIGN(16); .dynsym : { *(.dynsym) } _edata = .; + __data_size = . - __data_start; /* Unused sections */ .interp : { *(.interp) } diff --git a/stand/efi/loader/arch/arm64/start.S b/stand/efi/loader/arch/arm64/start.S index 675d4e153f36..0b8537fed30e 100644 --- a/stand/efi/loader/arch/arm64/start.S +++ b/stand/efi/loader/arch/arm64/start.S @@ -34,11 +34,14 @@ #define IMAGE_FILE_MACHINE_ARM64 0xaa64 +#define IMAGE_FILE_EXECUTABLE 0x0002 + #define IMAGE_SCN_CNT_CODE 0x00000020 #define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 #define IMAGE_SCN_MEM_DISCARDABLE 0x02000000 #define IMAGE_SCN_MEM_EXECUTE 0x20000000 #define IMAGE_SCN_MEM_READ 0x40000000 +#define IMAGE_SCN_MEM_WRITE 0x80000000 .section .peheader,"a" efi_start: @@ -60,22 +63,22 @@ coff_head: .long 0 /* No symbol table */ .long 0 /* No symbols */ .short section_table - optional_header /* Optional header size */ - .short 0 /* Characteristics TODO: Fill in */ + .short IMAGE_FILE_EXECUTABLE /* Characteristics */ optional_header: .short 0x020b /* PE32+ (64-bit addressing) */ .byte 0 /* Major linker version */ .byte 0 /* Minor linker version */ - .long _edata - _end_header /* Code size */ - .long 0 /* No initialized data */ + .long _etext - _end_header /* Code size */ + .long __data_size /* Initialized data size */ .long 0 /* No uninitialized data */ .long _start - efi_start /* Entry point */ .long _end_header - efi_start /* Start of code */ optional_windows_header: .quad 0 /* Image base */ - .long 32 /* Section Alignment */ - .long 8 /* File alignment */ + .long 4096 /* Section Alignment */ + .long 512 /* File alignment */ .short 0 /* Major OS version */ .short 0 /* Minor OS version */ .short 0 /* Major image version */ @@ -104,36 +107,37 @@ optional_windows_header: .quad 0 section_table: - /* We need a .reloc section for EFI */ - .ascii ".reloc" + .ascii ".text" + .byte 0 .byte 0 .byte 0 /* Pad to 8 bytes */ - .long 0 /* Virtual size */ - .long 0 /* Virtual address */ - .long 0 /* Size of raw data */ - .long 0 /* Pointer to raw data */ + .long _etext - _end_header /* Virtual size */ + .long _end_header - efi_start /* Virtual address */ + .long _etext - _end_header /* Size of raw data */ + .long _end_header - efi_start /* Pointer to raw data */ .long 0 /* Pointer to relocations */ .long 0 /* Pointer to line numbers */ .short 0 /* Number of relocations */ .short 0 /* Number of line numbers */ - .long (IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | \ - IMAGE_SCN_MEM_DISCARDABLE) /* Characteristics */ + .long (IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | \ + IMAGE_SCN_MEM_READ) /* Characteristics */ - /* The contents of the loader */ - .ascii ".text" + .ascii ".data" .byte 0 .byte 0 .byte 0 /* Pad to 8 bytes */ - .long _edata - _end_header /* Virtual size */ - .long _end_header - efi_start /* Virtual address */ - .long _edata - _end_header /* Size of raw data */ - .long _end_header - efi_start /* Pointer to raw data */ + .long __data_size /* Virtual size */ + .long __data_start - efi_start /* Virtual address */ + .long __data_size /* Size of raw data */ + .long __data_start - efi_start /* Pointer to raw data */ .long 0 /* Pointer to relocations */ .long 0 /* Pointer to line numbers */ .short 0 /* Number of relocations */ .short 0 /* Number of line numbers */ - .long (IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | \ - IMAGE_SCN_MEM_READ) /* Characteristics */ + .long (IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | \ + IMAGE_SCN_MEM_WRITE) /* Characteristics */ + + .align 12 _end_header: .text diff --git a/stand/efi/loader/arch/i386/Makefile.inc b/stand/efi/loader/arch/i386/Makefile.inc deleted file mode 100644 index fcdb6324b2f0..000000000000 --- a/stand/efi/loader/arch/i386/Makefile.inc +++ /dev/null @@ -1,13 +0,0 @@ -# $FreeBSD$ - -SRCS+= start.S \ - elf32_freebsd.c \ - exec.c - -.PATH: ${BOOTSRC}/i386/libi386 -SRCS+= nullconsole.c \ - comconsole.c \ - spinconsole.c - -CFLAGS+= -fPIC -LDFLAGS+= -Wl,-znocombreloc diff --git a/stand/efi/loader/arch/i386/elf32_freebsd.c b/stand/efi/loader/arch/i386/elf32_freebsd.c deleted file mode 100644 index 97d114f09610..000000000000 --- a/stand/efi/loader/arch/i386/elf32_freebsd.c +++ /dev/null @@ -1,103 +0,0 @@ -/*- - * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/exec.h> -#include <sys/linker.h> -#include <string.h> -#include <machine/bootinfo.h> -#include <machine/elf.h> -#include <stand.h> - -#include <efi.h> -#include <efilib.h> - -#include "bootstrap.h" -#include "../libi386/libi386.h" -#include "../btx/lib/btxv86.h" - -extern void __exec(caddr_t addr, ...); -extern int bi_load(char *args, vm_offset_t *modulep, vm_offset_t *kernendp, - bool exit_bs); - -static int elf32_exec(struct preloaded_file *amp); -static int elf32_obj_exec(struct preloaded_file *amp); - -struct file_format i386_elf = { elf32_loadfile, elf32_exec }; -struct file_format i386_elf_obj = { elf32_obj_loadfile, elf32_obj_exec }; - -struct file_format *file_formats[] = { - &i386_elf, - &i386_elf_obj, - NULL -}; - -/* - * There is an ELF kernel and one or more ELF modules loaded. - * We wish to start executing the kernel image, so make such - * preparations as are required, and do so. - */ -static int -elf32_exec(struct preloaded_file *fp) -{ - struct file_metadata *md; - Elf_Ehdr *ehdr; - vm_offset_t entry, bootinfop, modulep, kernend; - int boothowto, err, bootdev; - - if ((md = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL) - return(EFTYPE); - ehdr = (Elf_Ehdr *)&(md->md_data); - - efi_time_fini(); - - entry = ehdr->e_entry & 0xffffff; - - printf("Start @ 0x%x ...\n", entry); - - err = bi_load(fp->f_args, &modulep, &kernend, true); - if (err != 0) { - efi_time_init(); - return(err); - } - - /* At this point we've called ExitBootServices, so we can't call - * printf or any other function that uses Boot Services */ - - dev_cleanup(); - __exec((void *)entry, boothowto, bootdev, 0, 0, 0, bootinfop, modulep, kernend); - - panic("exec returned"); -} - -static int -elf32_obj_exec(struct preloaded_file *fp) -{ - return (EFTYPE); -} diff --git a/stand/efi/loader/arch/i386/exec.c b/stand/efi/loader/arch/i386/exec.c deleted file mode 100644 index 579f5593b24b..000000000000 --- a/stand/efi/loader/arch/i386/exec.c +++ /dev/null @@ -1,49 +0,0 @@ -/*- - * Copyright (c) 2010 Rui Paulo <rpaulo@FreeBSD.org> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <stand.h> -#include <machine/elf.h> -#include "../btx/lib/btxv86.h" - -#include "../../common/bootstrap.h" - -uint32_t __base; -struct __v86 __v86; - -void -__v86int() -{ - printf("%s\n", __func__); - exit(1); -} - -void -__exec(caddr_t addr, ...) -{ -} diff --git a/stand/efi/loader/arch/i386/i386_copy.c b/stand/efi/loader/arch/i386/i386_copy.c deleted file mode 100644 index 2c4b0deb49cf..000000000000 --- a/stand/efi/loader/arch/i386/i386_copy.c +++ /dev/null @@ -1,58 +0,0 @@ -/*- - * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -/* - * MD primitives supporting placement of module data - * - * XXX should check load address/size against memory top. - */ -#include <stand.h> - -#include "libi386.h" -#include "btxv86.h" - -ssize_t -i386_copyin(const void *src, vm_offset_t dest, const size_t len) -{ - bcopy(src, PTOV(dest), len); - return(len); -} - -ssize_t -i386_copyout(const vm_offset_t src, void *dest, const size_t len) -{ - bcopy(PTOV(src), dest, len); - return(len); -} - -ssize_t -i386_readin(readin_handle_t fd, vm_offset_t dest, const size_t len) -{ - return (VECTX_READ(fd, PTOV(dest), len)); -} diff --git a/stand/efi/loader/arch/i386/ldscript.i386 b/stand/efi/loader/arch/i386/ldscript.i386 deleted file mode 100644 index e17212a1bddd..000000000000 --- a/stand/efi/loader/arch/i386/ldscript.i386 +++ /dev/null @@ -1,77 +0,0 @@ -/* $FreeBSD$ */ -OUTPUT_FORMAT("elf32-i386-freebsd", "elf32-i386-freebsd", "elf32-i386-freebsd") -OUTPUT_ARCH(i386) -ENTRY(_start) -SECTIONS -{ - /* Read-only sections, merged into text segment: */ - . = 0; - ImageBase = .; - . = SIZEOF_HEADERS; - . = ALIGN(4096); - .text : { - *(.text .stub .text.* .gnu.linkonce.t.*) - /* .gnu.warning sections are handled specially by elf32.em. */ - *(.gnu.warning) - *(.plt) - } =0xCCCCCCCC - . = ALIGN(4096); - .data : { - *(.rodata .rodata.* .gnu.linkonce.r.*) - *(.rodata1) - *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) - *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) - *(.opd) - *(.data .data.* .gnu.linkonce.d.*) - *(.data1) - *(.plabel) - *(.dynbss) - *(.bss .bss.* .gnu.linkonce.b.*) - *(COMMON) - } - . = ALIGN(4096); - set_Xcommand_set : { - __start_set_Xcommand_set = .; - *(set_Xcommand_set) - __stop_set_Xcommand_set = .; - } - set_Xficl_compile_set : { - __start_set_Xficl_compile_set = .; - *(set_Xficl_compile_set) - __stop_set_Xficl_compile_set = .; - } - . = ALIGN(4096); - __gp = .; - .sdata : { - *(.got.plt .got) - *(.sdata .sdata.* .gnu.linkonce.s.*) - *(dynsbss) - *(.sbss .sbss.* .gnu.linkonce.sb.*) - *(.scommon) - } - . = ALIGN(4096); - .dynamic : { *(.dynamic) } - . = ALIGN(4096); - .rel.dyn : { - *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) - *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) - *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) - *(.rel.got) - *(.rel.sdata .rel.sdata.* .rel.gnu.linkonce.s.*) - *(.rel.sbss .rel.sbss.* .rel.gnu.linkonce.sb.*) - *(.rel.sdata2 .rel.sdata2.* .rel.gnu.linkonce.s2.*) - *(.rel.sbss2 .rel.sbss2.* .rel.gnu.linkonce.sb2.*) - *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) - *(.rel.plt) - *(.relset_*) - *(.rel.dyn .rel.dyn.*) - } - . = ALIGN(4096); - .reloc : { *(.reloc) } - . = ALIGN(4096); - .hash : { *(.hash) } - . = ALIGN(4096); - .dynsym : { *(.dynsym) } - . = ALIGN(4096); - .dynstr : { *(.dynstr) } -} diff --git a/stand/efi/loader/arch/i386/start.S b/stand/efi/loader/arch/i386/start.S deleted file mode 100644 index b597f419d4a1..000000000000 --- a/stand/efi/loader/arch/i386/start.S +++ /dev/null @@ -1,68 +0,0 @@ -/*- - * Copyright (c) 2008-2010 Rui Paulo <rpaulo@FreeBSD.org> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ - - .text - -#include <machine/asm.h> - -#define EFI_SUCCESS 0 - -/* - * EFI entry point. - * _start(EFI_IMAGE image_handle, EFI_SYSTEM_TABLE *system_table); - * - * We calculate the base address along with _DYNAMIC, relocate us and finally - * pass control to efi_main. - */ - -ENTRY(_start) - pushl %ebp - movl %esp, %ebp - - pushl 12(%ebp) /* image_handle */ - pushl 8(%ebp) /* system_table */ - call 0f -0: popl %eax - movl %eax, %ebx - addl $ImageBase-0b, %eax - addl $_DYNAMIC-0b, %ebx - pushl %ebx /* dynamic */ - pushl %eax /* ImageBase */ - call self_reloc - popl %ebx /* remove ImageBase from the stack */ - popl %ebx /* remove dynamic from the stack */ - call efi_main -1: leave - ret -END(_start) - - .data - .section .reloc, "a" - .long 0 - .long 10 - .word 0 diff --git a/stand/efi/loader/arch/riscv/Makefile.inc b/stand/efi/loader/arch/riscv/Makefile.inc index 333b789e935d..032c8a43bd51 100644 --- a/stand/efi/loader/arch/riscv/Makefile.inc +++ b/stand/efi/loader/arch/riscv/Makefile.inc @@ -3,5 +3,4 @@ HAVE_FDT=yes SRCS+= exec.c \ - efiserialio.c \ start.S diff --git a/stand/efi/loader/arch/riscv/start.S b/stand/efi/loader/arch/riscv/start.S index e63ce68d86ba..50bac6553ea1 100644 --- a/stand/efi/loader/arch/riscv/start.S +++ b/stand/efi/loader/arch/riscv/start.S @@ -1,5 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2020 Mitchell Horne <mhorne@FreeBSD.org> * diff --git a/stand/efi/loader/bootinfo.c b/stand/efi/loader/bootinfo.c index c7b682819a98..d79f59343af1 100644 --- a/stand/efi/loader/bootinfo.c +++ b/stand/efi/loader/bootinfo.c @@ -40,17 +40,24 @@ __FBSDID("$FreeBSD$"); #include <machine/metadata.h> #include <machine/psl.h> +#ifdef EFI #include <efi.h> #include <efilib.h> +#else +#include "kboot.h" +#endif #include "bootstrap.h" -#include "loader_efi.h" +#include "modinfo.h" #if defined(__amd64__) #include <machine/specialreg.h> #endif +#ifdef EFI +#include "loader_efi.h" #include "gfx_fb.h" +#endif #if defined(LOADER_FDT_SUPPORT) #include <fdt_platform.h> @@ -66,11 +73,14 @@ int bi_load(char *args, vm_offset_t *modulep, vm_offset_t *kernendp, static int bi_getboothowto(char *kargs) { +#ifdef EFI const char *sw, *tmp; char *opts; - char *console; - int howto, speed, port; + int speed, port; char buf[50]; +#endif + char *console; + int howto; howto = boot_parse_cmdline(kargs); howto |= boot_env_to_howto(); @@ -81,6 +91,7 @@ bi_getboothowto(char *kargs) howto |= RB_SERIAL; if (strcmp(console, "nullconsole") == 0) howto |= RB_MUTE; +#ifdef EFI #if defined(__i386__) || defined(__amd64__) if (strcmp(console, "efi") == 0 && getenv("efi_8250_uid") != NULL && @@ -108,10 +119,17 @@ bi_getboothowto(char *kargs) if (tmp != NULL) speed = strtol(tmp, NULL, 0); tmp = getenv("efi_com_port"); - if (tmp == NULL) - tmp = getenv("comconsole_port"); if (tmp != NULL) port = strtol(tmp, NULL, 0); + if (port <= 0) { + tmp = getenv("comconsole_port"); + if (tmp != NULL) + port = strtol(tmp, NULL, 0); + else { + if (port == 0) + port = 0x3f8; + } + } if (speed != -1 && port != -1) { snprintf(buf, sizeof(buf), "io:%d,br:%d", port, speed); @@ -120,139 +138,13 @@ bi_getboothowto(char *kargs) } } #endif +#endif } return (howto); } -/* - * Copy the environment into the load area starting at (addr). - * Each variable is formatted as <name>=<value>, with a single nul - * separating each variable, and a double nul terminating the environment. - */ -static vm_offset_t -bi_copyenv(vm_offset_t start) -{ - struct env_var *ep; - vm_offset_t addr, last; - size_t len; - - addr = last = start; - - /* Traverse the environment. */ - for (ep = environ; ep != NULL; ep = ep->ev_next) { - len = strlen(ep->ev_name); - if ((size_t)archsw.arch_copyin(ep->ev_name, addr, len) != len) - break; - addr += len; - if (archsw.arch_copyin("=", addr, 1) != 1) - break; - addr++; - if (ep->ev_value != NULL) { - len = strlen(ep->ev_value); - if ((size_t)archsw.arch_copyin(ep->ev_value, addr, len) != len) - break; - addr += len; - } - if (archsw.arch_copyin("", addr, 1) != 1) - break; - last = ++addr; - } - - if (archsw.arch_copyin("", last++, 1) != 1) - last = start; - return(last); -} - -/* - * Copy module-related data into the load area, where it can be - * used as a directory for loaded modules. - * - * Module data is presented in a self-describing format. Each datum - * is preceded by a 32-bit identifier and a 32-bit size field. - * - * Currently, the following data are saved: - * - * MOD_NAME (variable) module name (string) - * MOD_TYPE (variable) module type (string) - * MOD_ARGS (variable) module parameters (string) - * MOD_ADDR sizeof(vm_offset_t) module load address - * MOD_SIZE sizeof(size_t) module size - * MOD_METADATA (variable) type-specific metadata - */ -#define COPY32(v, a, c) { \ - uint32_t x = (v); \ - if (c) \ - archsw.arch_copyin(&x, a, sizeof(x)); \ - a += sizeof(x); \ -} - -#define MOD_STR(t, a, s, c) { \ - COPY32(t, a, c); \ - COPY32(strlen(s) + 1, a, c); \ - if (c) \ - archsw.arch_copyin(s, a, strlen(s) + 1); \ - a += roundup(strlen(s) + 1, sizeof(u_long)); \ -} - -#define MOD_NAME(a, s, c) MOD_STR(MODINFO_NAME, a, s, c) -#define MOD_TYPE(a, s, c) MOD_STR(MODINFO_TYPE, a, s, c) -#define MOD_ARGS(a, s, c) MOD_STR(MODINFO_ARGS, a, s, c) - -#define MOD_VAR(t, a, s, c) { \ - COPY32(t, a, c); \ - COPY32(sizeof(s), a, c); \ - if (c) \ - archsw.arch_copyin(&s, a, sizeof(s)); \ - a += roundup(sizeof(s), sizeof(u_long)); \ -} - -#define MOD_ADDR(a, s, c) MOD_VAR(MODINFO_ADDR, a, s, c) -#define MOD_SIZE(a, s, c) MOD_VAR(MODINFO_SIZE, a, s, c) - -#define MOD_METADATA(a, mm, c) { \ - COPY32(MODINFO_METADATA | mm->md_type, a, c); \ - COPY32(mm->md_size, a, c); \ - if (c) \ - archsw.arch_copyin(mm->md_data, a, mm->md_size); \ - a += roundup(mm->md_size, sizeof(u_long)); \ -} - -#define MOD_END(a, c) { \ - COPY32(MODINFO_END, a, c); \ - COPY32(0, a, c); \ -} - -static vm_offset_t -bi_copymodules(vm_offset_t addr) -{ - struct preloaded_file *fp; - struct file_metadata *md; - int c; - uint64_t v; - - c = addr != 0; - /* Start with the first module on the list, should be the kernel. */ - for (fp = file_findfile(NULL, NULL); fp != NULL; fp = fp->f_next) { - MOD_NAME(addr, fp->f_name, c); /* This must come first. */ - MOD_TYPE(addr, fp->f_type, c); - if (fp->f_args) - MOD_ARGS(addr, fp->f_args, c); - v = fp->f_addr; -#if defined(__arm__) - v -= __elfN(relocation_offset); -#endif - MOD_ADDR(addr, v, c); - v = fp->f_size; - MOD_SIZE(addr, v, c); - for (md = fp->f_metadata; md != NULL; md = md->md_next) - if (!(md->md_type & MODINFOMD_NOCOPY)) - MOD_METADATA(addr, md, c); - } - MOD_END(addr, c); - return(addr); -} - +#ifdef EFI static EFI_STATUS efi_do_vmap(EFI_MEMORY_DESCRIPTOR *mm, UINTN sz, UINTN mmsz, UINT32 mmver) { @@ -309,16 +201,19 @@ bi_load_efi_data(struct preloaded_file *kfp, bool exit_bs) efifb.fb_mask_blue = gfx_state.tg_fb.fb_mask_blue; efifb.fb_mask_reserved = gfx_state.tg_fb.fb_mask_reserved; - printf("EFI framebuffer information:\n"); - printf("addr, size 0x%jx, 0x%jx\n", efifb.fb_addr, efifb.fb_size); - printf("dimensions %d x %d\n", efifb.fb_width, efifb.fb_height); - printf("stride %d\n", efifb.fb_stride); - printf("masks 0x%08x, 0x%08x, 0x%08x, 0x%08x\n", - efifb.fb_mask_red, efifb.fb_mask_green, efifb.fb_mask_blue, - efifb.fb_mask_reserved); + if (efifb.fb_addr != 0) { + printf("EFI framebuffer information:\n"); + printf("addr, size 0x%jx, 0x%jx\n", + efifb.fb_addr, efifb.fb_size); + printf("dimensions %d x %d\n", + efifb.fb_width, efifb.fb_height); + printf("stride %d\n", efifb.fb_stride); + printf("masks 0x%08x, 0x%08x, 0x%08x, 0x%08x\n", + efifb.fb_mask_red, efifb.fb_mask_green, efifb.fb_mask_blue, + efifb.fb_mask_reserved); - if (efifb.fb_addr != 0) file_addmetadata(kfp, MODINFOMD_EFI_FB, sizeof(efifb), &efifb); + } #endif do_vmap = true; @@ -421,6 +316,7 @@ bi_load_efi_data(struct preloaded_file *kfp, bool exit_bs) return (0); } +#endif /* * Load the information expected by an amd64 kernel. @@ -443,6 +339,7 @@ bi_load(char *args, vm_offset_t *modulep, vm_offset_t *kernendp, bool exit_bs) vm_offset_t size; char *rootdevname; int howto; + bool is64 = sizeof(long) == 8; #if defined(LOADER_FDT_SUPPORT) vm_offset_t dtbp; int dtb_size; @@ -462,7 +359,6 @@ bi_load(char *args, vm_offset_t *modulep, vm_offset_t *kernendp, bool exit_bs) #endif }; #endif - howto = bi_getboothowto(args); /* @@ -478,11 +374,11 @@ bi_load(char *args, vm_offset_t *modulep, vm_offset_t *kernendp, bool exit_bs) } /* Try reading the /etc/fstab file to select the root device */ - getrootmount(efi_fmtdev((void *)rootdev)); + getrootmount(devformat(rootdev)); addr = 0; for (xp = file_findfile(NULL, NULL); xp != NULL; xp = xp->f_next) { - if (addr < (xp->f_addr + xp->f_size)) + if (addr < xp->f_addr + xp->f_size) addr = xp->f_addr + xp->f_size; } @@ -496,7 +392,7 @@ bi_load(char *args, vm_offset_t *modulep, vm_offset_t *kernendp, bool exit_bs) /* Copy our environment. */ envp = addr; - addr = bi_copyenv(addr); + addr = md_copyenv(addr); /* Pad to a page boundary. */ addr = roundup(addr, PAGE_SIZE); @@ -534,13 +430,19 @@ bi_load(char *args, vm_offset_t *modulep, vm_offset_t *kernendp, bool exit_bs) #ifdef MODINFOMD_MODULEP file_addmetadata(kfp, MODINFOMD_MODULEP, sizeof(module), &module); #endif +#ifdef EFI file_addmetadata(kfp, MODINFOMD_FW_HANDLE, sizeof(ST), &ST); +#endif #ifdef LOADER_GELI_SUPPORT geli_export_key_metadata(kfp); #endif +#ifdef EFI bi_load_efi_data(kfp, exit_bs); +#else + bi_loadsmap(kfp); +#endif - size = bi_copymodules(0); + size = md_copymodules(0, is64); /* Find the size of the modules */ kernend = roundup(addr + size, PAGE_SIZE); *kernendp = kernend; @@ -565,7 +467,7 @@ bi_load(char *args, vm_offset_t *modulep, vm_offset_t *kernendp, bool exit_bs) #endif /* Copy module list and metadata. */ - (void)bi_copymodules(addr); + (void)md_copymodules(addr, is64); return (0); } diff --git a/stand/efi/loader/conf.c b/stand/efi/loader/conf.c index 863c9188c72c..163b5835e4a7 100644 --- a/stand/efi/loader/conf.c +++ b/stand/efi/loader/conf.c @@ -80,16 +80,25 @@ struct netif_driver *netif_drivers[] = { }; extern struct console efi_console; +extern struct console eficom; +#if defined(__aarch64__) && __FreeBSD_version < 1500000 +/* Hack for backward compatibility -- but only for a while */ +extern struct console comconsole; +#endif +#if defined(__amd64__) extern struct console comconsole; -#if defined(__amd64__) || defined(__i386__) extern struct console nullconsole; extern struct console spinconsole; #endif struct console *consoles[] = { &efi_console, + &eficom, +#if defined(__aarch64__) && __FreeBSD_version < 1500000 + &comconsole, +#endif +#if defined(__amd64__) &comconsole, -#if defined(__amd64__) || defined(__i386__) &nullconsole, &spinconsole, #endif diff --git a/stand/efi/loader/copy.c b/stand/efi/loader/copy.c index 47e613ccc2f3..6a4e65f2dbc3 100644 --- a/stand/efi/loader/copy.c +++ b/stand/efi/loader/copy.c @@ -1,6 +1,5 @@ /*- * Copyright (c) 2013 The FreeBSD Foundation - * All rights reserved. * * This software was developed by Benno Rice under sponsorship from * the FreeBSD Foundation. @@ -42,7 +41,7 @@ __FBSDID("$FreeBSD$"); #define M(x) ((x) * 1024 * 1024) #define G(x) (1UL * (x) * 1024 * 1024 * 1024) -#if defined(__i386__) || defined(__amd64__) +#if defined(__amd64__) #include <machine/cpufunc.h> #include <machine/specialreg.h> #include <machine/vmparam.h> @@ -174,7 +173,7 @@ efi_verify_staging_size(unsigned long *nr_pages) out: free(map); } -#endif /* __i386__ || __amd64__ */ +#endif /* __amd64__ */ #if defined(__arm__) #define DEFAULT_EFI_STAGING_SIZE 32 @@ -201,7 +200,7 @@ out: static u_long staging_slop = EFI_STAGING_SLOP; EFI_PHYSICAL_ADDRESS staging, staging_end, staging_base; -int stage_offset_set = 0; +bool stage_offset_set = false; ssize_t stage_offset; static void @@ -209,7 +208,7 @@ efi_copy_free(void) { BS->FreePages(staging_base, (staging_end - staging_base) / EFI_PAGE_SIZE); - stage_offset_set = 0; + stage_offset_set = false; stage_offset = 0; } @@ -285,9 +284,9 @@ command_staging_slop(int argc, char *argv[]) COMMAND_SET(staging_slop, "staging_slop", "set staging slop", command_staging_slop); -#if defined(__i386__) || defined(__amd64__) +#if defined(__amd64__) /* - * The staging area must reside in the the first 1GB or 4GB physical + * The staging area must reside in the first 1GB or 4GB physical * memory: see elf64_exec() in * boot/efi/loader/arch/amd64/elf64_freebsd.c. */ @@ -296,11 +295,7 @@ get_staging_max(void) { EFI_PHYSICAL_ADDRESS res; -#if defined(__i386__) - res = G(1); -#elif defined(__amd64__) res = copy_staging == COPY_STAGING_ENABLE ? G(1) : G(4); -#endif return (res); } #define EFI_ALLOC_METHOD AllocateMaxAddress @@ -320,7 +315,7 @@ efi_copy_init(void) ess = DEFAULT_EFI_STAGING_SIZE; nr_pages = EFI_SIZE_TO_PAGES(M(1) * ess); -#if defined(__i386__) || defined(__amd64__) +#if defined(__amd64__) /* * We'll decrease nr_pages, if it's too big. Currently we only * apply this to FreeBSD VM running on Hyper-V. Why? Please see @@ -331,7 +326,7 @@ efi_copy_init(void) staging = get_staging_max(); #endif - status = BS->AllocatePages(EFI_ALLOC_METHOD, EfiLoaderData, + status = BS->AllocatePages(EFI_ALLOC_METHOD, EfiLoaderCode, nr_pages, &staging); if (EFI_ERROR(status)) { printf("failed to allocate staging area: %lu\n", @@ -388,9 +383,8 @@ efi_check_space(vm_offset_t end) end += staging_slop; nr_pages = EFI_SIZE_TO_PAGES(end - staging_end); -#if defined(__i386__) || defined(__amd64__) +#if defined(__amd64__) /* - * i386 needs all memory to be allocated under the 1G boundary. * amd64 needs all memory to be allocated under the 1G or 4G boundary. */ if (end > get_staging_max()) @@ -399,7 +393,7 @@ efi_check_space(vm_offset_t end) /* Try to allocate more space after the previous allocation */ addr = staging_end; - status = BS->AllocatePages(AllocateAddress, EfiLoaderData, nr_pages, + status = BS->AllocatePages(AllocateAddress, EfiLoaderCode, nr_pages, &addr); if (!EFI_ERROR(status)) { staging_end = staging_end + nr_pages * EFI_PAGE_SIZE; @@ -416,7 +410,7 @@ before_staging: addr = rounddown2(addr, M(2)); #endif nr_pages = EFI_SIZE_TO_PAGES(staging_base - addr); - status = BS->AllocatePages(AllocateAddress, EfiLoaderData, nr_pages, + status = BS->AllocatePages(AllocateAddress, EfiLoaderCode, nr_pages, &addr); if (!EFI_ERROR(status)) { /* @@ -436,10 +430,10 @@ expand: #if EFI_STAGING_2M_ALIGN nr_pages += M(2) / EFI_PAGE_SIZE; #endif -#if defined(__i386__) || defined(__amd64__) +#if defined(__amd64__) new_base = get_staging_max(); #endif - status = BS->AllocatePages(EFI_ALLOC_METHOD, EfiLoaderData, + status = BS->AllocatePages(EFI_ALLOC_METHOD, EfiLoaderCode, nr_pages, &new_base); if (!EFI_ERROR(status)) { #if EFI_STAGING_2M_ALIGN @@ -479,7 +473,7 @@ efi_copyin(const void *src, vm_offset_t dest, const size_t len) if (!stage_offset_set) { stage_offset = (vm_offset_t)staging - dest; - stage_offset_set = 1; + stage_offset_set = true; } /* XXX: Callers do not check for failure. */ @@ -510,7 +504,7 @@ efi_readin(readin_handle_t fd, vm_offset_t dest, const size_t len) if (!stage_offset_set) { stage_offset = (vm_offset_t)staging - dest; - stage_offset_set = 1; + stage_offset_set = true; } if (!efi_check_space(dest + stage_offset + len)) { diff --git a/stand/efi/loader/framebuffer.c b/stand/efi/loader/framebuffer.c index d5504c9cff35..9dfe547d7557 100644 --- a/stand/efi/loader/framebuffer.c +++ b/stand/efi/loader/framebuffer.c @@ -1,6 +1,5 @@ /*- * Copyright (c) 2013 The FreeBSD Foundation - * All rights reserved. * * This software was developed by Benno Rice under sponsorship from * the FreeBSD Foundation. @@ -536,6 +535,21 @@ efifb_get_edid(edid_res_list_t *res) return (rv); } +bool +efi_has_gop(void) +{ + EFI_STATUS status; + EFI_HANDLE *hlist; + UINTN hsize; + + hsize = 0; + hlist = NULL; + status = BS->LocateHandle(ByProtocol, &gop_guid, NULL, &hsize, hlist); + + return (status == EFI_BUFFER_TOO_SMALL); +} + + int efi_find_framebuffer(teken_gfx_t *gfx_state) { diff --git a/stand/efi/loader/framebuffer.h b/stand/efi/loader/framebuffer.h index 008df7f6c167..a9377984de2b 100644 --- a/stand/efi/loader/framebuffer.h +++ b/stand/efi/loader/framebuffer.h @@ -1,6 +1,5 @@ /*- * Copyright (c) 2013 The FreeBSD Foundation - * All rights reserved. * * This software was developed by Benno Rice under sponsorship from * the FreeBSD Foundation. @@ -28,11 +27,13 @@ * $FreeBSD$ */ +#include <teken.h> #include <gfx_fb.h> #ifndef _EFIFB_H_ #define _EFIFB_H_ +bool efi_has_gop(void); int efi_find_framebuffer(teken_gfx_t *gfx_state); #endif /* _EFIFB_H_ */ diff --git a/stand/efi/loader/loader_efi.h b/stand/efi/loader/loader_efi.h index 8254d16b1592..49434698fa03 100644 --- a/stand/efi/loader/loader_efi.h +++ b/stand/efi/loader/loader_efi.h @@ -1,6 +1,5 @@ /*- * Copyright (c) 2013 The FreeBSD Foundation - * All rights reserved. * * This software was developed by Benno Rice under sponsorship from * the FreeBSD Foundation. @@ -33,6 +32,7 @@ #include <stand.h> #include <readin.h> +#include <efi.h> #ifdef __amd64__ enum { @@ -43,6 +43,8 @@ enum { extern int copy_staging; #endif +extern EFI_LOADED_IMAGE *boot_img; + int efi_autoload(void); int efi_copy_init(void); diff --git a/stand/efi/loader/main.c b/stand/efi/loader/main.c index eb143989190d..8419331f7a19 100644 --- a/stand/efi/loader/main.c +++ b/stand/efi/loader/main.c @@ -60,6 +60,7 @@ __FBSDID("$FreeBSD$"); #include <smbios.h> #include "efizfs.h" +#include "framebuffer.h" #include "loader_efi.h" @@ -185,25 +186,11 @@ out: } static void -set_currdev(const char *devname) -{ - - env_setenv("currdev", EV_VOLATILE, devname, efi_setcurrdev, - env_nounset); - /* - * Don't execute hook here; the loaddev hook makes it immutable - * once we've determined what the proper currdev is. - */ - env_setenv("loaddev", EV_VOLATILE | EV_NOHOOK, devname, env_noset, - env_nounset); -} - -static void set_currdev_devdesc(struct devdesc *currdev) { const char *devname; - devname = efi_fmtdev(currdev); + devname = devformat(currdev); printf("Setting currdev to %s\n", devname); set_currdev(devname); } @@ -265,32 +252,29 @@ probe_zfs_currdev(uint64_t guid) { char *devname; struct zfs_devdesc currdev; - char *buf = NULL; - bool rv; + bool bootable; currdev.dd.d_dev = &zfs_dev; currdev.dd.d_unit = 0; currdev.pool_guid = guid; currdev.root_guid = 0; set_currdev_devdesc((struct devdesc *)&currdev); - devname = efi_fmtdev(&currdev); + devname = devformat(&currdev.dd); init_zfs_boot_options(devname); - rv = sanity_check_currdev(); - if (rv) { - buf = malloc(VDEV_PAD_SIZE); - if (buf != NULL) { - if (zfs_get_bootonce(&currdev, OS_BOOTONCE, buf, - VDEV_PAD_SIZE) == 0) { - printf("zfs bootonce: %s\n", buf); - set_currdev(buf); - setenv("zfs-bootonce", buf, 1); - } - free(buf); - (void) zfs_attach_nvstore(&currdev); + bootable = sanity_check_currdev(); + if (bootable) { + char buf[VDEV_PAD_SIZE]; + + if (zfs_get_bootonce(&currdev, OS_BOOTONCE, buf, sizeof(buf)) == 0) { + printf("zfs bootonce: %s\n", buf); + set_currdev(buf); + setenv("zfs-bootonce", buf, 1); } + (void)zfs_attach_nvstore(&currdev); } - return (rv); + + return (bootable); } #endif @@ -701,8 +685,7 @@ interactive_interrupt(const char *msg) static int parse_args(int argc, CHAR16 *argv[]) { - int i, j, howto; - bool vargood; + int i, howto; char var[128]; /* @@ -719,7 +702,7 @@ parse_args(int argc, CHAR16 *argv[]) * method is flawed for non-ASCII characters). */ howto = 0; - for (i = 1; i < argc; i++) { + for (i = 0; i < argc; i++) { cpy16to8(argv[i], var, sizeof(var)); howto |= boot_parse_arg(var); } @@ -760,8 +743,20 @@ parse_uefi_con_out(void) if (rv != EFI_SUCCESS) rv = efi_global_getenv("ConOutDev", buf, &sz); if (rv != EFI_SUCCESS) { - /* If we don't have any ConOut default to serial */ - how = RB_SERIAL; + /* + * If we don't have any ConOut default to both. If we have GOP + * make video primary, otherwise just make serial primary. In + * either case, try to use both the 'efi' console which will use + * the GOP, if present and serial. If there's an EFI BIOS that + * omits this, but has a serial port redirect, we'll + * unavioidably get doubled characters (but we'll be right in + * all the other more common cases). + */ + if (efi_has_gop()) + how = RB_MULTIPLE; + else + how = RB_MULTIPLE | RB_SERIAL; + setenv("console", "efi,comconsole", 1); goto out; } ep = buf + sz; @@ -935,6 +930,22 @@ main(int argc, CHAR16 *argv[]) archsw.arch_readin = efi_readin; archsw.arch_zfs_probe = efi_zfs_probe; +#if !defined(__arm__) + for (k = 0; k < ST->NumberOfTableEntries; k++) { + guid = &ST->ConfigurationTable[k].VendorGuid; + if (!memcmp(guid, &smbios, sizeof(EFI_GUID)) || + !memcmp(guid, &smbios3, sizeof(EFI_GUID))) { + char buf[40]; + + snprintf(buf, sizeof(buf), "%p", + ST->ConfigurationTable[k].VendorTable); + setenv("hint.smbios.0.mem", buf, 1); + smbios_detect(ST->ConfigurationTable[k].VendorTable); + break; + } + } +#endif + /* Get our loaded image protocol interface structure. */ (void) OpenProtocolByHandle(IH, &imgid, (void **)&boot_img); @@ -949,13 +960,16 @@ main(int argc, CHAR16 *argv[]) setenv("console", "efi", 1); uhowto = parse_uefi_con_out(); #if defined(__riscv) + /* + * This workaround likely is papering over a real issue + */ if ((uhowto & RB_SERIAL) != 0) setenv("console", "comconsole", 1); #endif cons_probe(); /* Set up currdev variable to have hooks in place. */ - env_setenv("currdev", EV_VOLATILE, "", efi_setcurrdev, env_nounset); + env_setenv("currdev", EV_VOLATILE, "", gen_setcurrdev, env_nounset); /* Init the time source */ efi_time_init(); @@ -975,9 +989,7 @@ main(int argc, CHAR16 *argv[]) "failures\n", i); } - for (i = 0; devsw[i] != NULL; i++) - if (devsw[i]->dv_init != NULL) - (devsw[i]->dv_init)(); + devinit(); /* * Detect console settings two different ways: one via the command @@ -1185,21 +1197,6 @@ main(int argc, CHAR16 *argv[]) autoload_font(false); /* Set up the font list for console. */ efi_init_environment(); -#if !defined(__arm__) - for (k = 0; k < ST->NumberOfTableEntries; k++) { - guid = &ST->ConfigurationTable[k].VendorGuid; - if (!memcmp(guid, &smbios, sizeof(EFI_GUID))) { - char buf[40]; - - snprintf(buf, sizeof(buf), "%p", - ST->ConfigurationTable[k].VendorTable); - setenv("hint.smbios.0.mem", buf, 1); - smbios_detect(ST->ConfigurationTable[k].VendorTable); - break; - } - } -#endif - interact(); /* doesn't return */ return (EFI_SUCCESS); /* keep compiler happy */ @@ -1280,15 +1277,6 @@ command_reboot(int argc, char *argv[]) return (CMD_ERROR); } -COMMAND_SET(quit, "quit", "exit the loader", command_quit); - -static int -command_quit(int argc, char *argv[]) -{ - exit(0); - return (CMD_OK); -} - COMMAND_SET(memmap, "memmap", "print memory map", command_memmap); static int diff --git a/stand/efi/loader_4th/Makefile b/stand/efi/loader_4th/Makefile index 3659f7efe673..a85fcdbb70b9 100644 --- a/stand/efi/loader_4th/Makefile +++ b/stand/efi/loader_4th/Makefile @@ -1,6 +1,7 @@ # $FreeBSD$ LOADER_INTERP=4th +INSTALL_LOADER_HELP_FILE=no .include "../loader/Makefile" diff --git a/stand/efi/loader_4th/Makefile.depend b/stand/efi/loader_4th/Makefile.depend new file mode 100644 index 000000000000..e69de29bb2d1 --- /dev/null +++ b/stand/efi/loader_4th/Makefile.depend diff --git a/stand/efi/loader_lua/Makefile b/stand/efi/loader_lua/Makefile index 3a4268440cf6..3766588015ad 100644 --- a/stand/efi/loader_lua/Makefile +++ b/stand/efi/loader_lua/Makefile @@ -1,6 +1,7 @@ # $FreeBSD$ LOADER_INTERP=lua +INSTALL_LOADER_HELP_FILE=no .include "../loader/Makefile" |