aboutsummaryrefslogtreecommitdiff
path: root/stand
diff options
context:
space:
mode:
Diffstat (limited to 'stand')
-rw-r--r--stand/Makefile5
-rw-r--r--stand/arm64/libarm64/cache.c2
-rw-r--r--stand/arm64/libarm64/cache.h1
-rw-r--r--stand/common/bootstrap.h1
-rw-r--r--stand/common/commands.c9
-rw-r--r--stand/common/dev_net.c18
-rw-r--r--stand/common/disk.c7
-rw-r--r--stand/common/disk.h3
-rw-r--r--stand/common/interp.c43
-rw-r--r--stand/common/load_elf.c16
-rw-r--r--stand/common/md.c19
-rw-r--r--stand/common/metadata.c132
-rw-r--r--stand/common/modinfo.c189
-rw-r--r--stand/common/modinfo.h12
-rw-r--r--stand/common/vdisk.c3
-rw-r--r--stand/efi/fdt/efi_fdt.c1
-rw-r--r--stand/efi/include/efilib.h1
-rw-r--r--stand/efi/libefi/devicename.c26
-rw-r--r--stand/efi/libefi/efihttp.c2
-rw-r--r--stand/efi/libefi/efinet.c2
-rw-r--r--stand/efi/libefi/efipart.c7
-rw-r--r--stand/efi/loader/Makefile4
-rw-r--r--stand/efi/loader/arch/amd64/amd64_tramp.S1
-rw-r--r--stand/efi/loader/arch/amd64/elf64_freebsd.c12
-rw-r--r--stand/efi/loader/arch/amd64/exc.S1
-rw-r--r--stand/efi/loader/arch/amd64/trap.c38
-rw-r--r--stand/efi/loader/arch/arm64/exec.c15
-rw-r--r--stand/efi/loader/bootinfo.c137
-rw-r--r--stand/efi/loader/copy.c11
-rw-r--r--stand/efi/loader/framebuffer.c16
-rw-r--r--stand/efi/loader/framebuffer.h3
-rw-r--r--stand/efi/loader/loader_efi.h4
-rw-r--r--stand/efi/loader/main.c35
-rw-r--r--stand/fdt/fdt_loader_cmd.c1
-rw-r--r--stand/i386/boot0/Makefile7
-rw-r--r--stand/i386/boot2/boot2.c2
-rw-r--r--stand/i386/libfirewire/firewire.c18
-rw-r--r--stand/i386/libi386/biosacpi.c12
-rw-r--r--stand/i386/libi386/biosdisk.c39
-rw-r--r--stand/i386/libi386/bootinfo.c28
-rw-r--r--stand/i386/libi386/bootinfo32.c129
-rw-r--r--stand/i386/libi386/bootinfo64.c96
-rw-r--r--stand/i386/libi386/devicename.c27
-rw-r--r--stand/i386/libi386/libi386.h29
-rw-r--r--stand/i386/libi386/pxe.c2
-rw-r--r--stand/i386/libi386/vidconsole.c1
-rw-r--r--stand/i386/loader/Makefile23
-rw-r--r--stand/i386/loader/main.c28
-rw-r--r--stand/i386/pxeldr/Makefile2
-rw-r--r--stand/i386/zfsboot/zfsboot.c23
-rw-r--r--stand/kboot/Makefile17
-rw-r--r--stand/kboot/arch/aarch64/Makefile.inc12
-rw-r--r--stand/kboot/arch/aarch64/exec.c188
-rw-r--r--stand/kboot/arch/aarch64/host_syscall.S18
-rw-r--r--stand/kboot/arch/aarch64/ldscript.aarch6472
-rw-r--r--stand/kboot/arch/aarch64/load_addr.c0
-rw-r--r--stand/kboot/arch/aarch64/start_arch.h36
-rw-r--r--stand/kboot/arch/aarch64/stat_arch.h29
-rw-r--r--stand/kboot/arch/aarch64/syscall_nr.h22
-rw-r--r--stand/kboot/arch/aarch64/tramp.S67
-rw-r--r--stand/kboot/arch/amd64/Makefile.inc5
-rw-r--r--stand/kboot/arch/amd64/start_arch.h34
-rw-r--r--stand/kboot/arch/amd64/stat_arch.h31
-rw-r--r--stand/kboot/arch/amd64/syscall_nr.h29
-rw-r--r--stand/kboot/arch/amd64/termios_arch.h1
-rw-r--r--stand/kboot/arch/powerpc64/Makefile.inc8
-rw-r--r--stand/kboot/arch/powerpc64/conf.c118
-rw-r--r--stand/kboot/arch/powerpc64/ppc64_elf_freebsd.c17
-rw-r--r--stand/kboot/arch/powerpc64/start_arch.h30
-rw-r--r--stand/kboot/arch/powerpc64/stat_arch.h27
-rw-r--r--stand/kboot/arch/powerpc64/syscall_nr.h30
-rw-r--r--stand/kboot/arch/powerpc64/termios_arch.h184
-rw-r--r--stand/kboot/conf.c (renamed from stand/kboot/arch/amd64/conf.c)0
-rw-r--r--stand/kboot/crt1.c74
-rw-r--r--stand/kboot/host_syscall.h149
-rw-r--r--stand/kboot/host_syscalls.c127
-rw-r--r--stand/kboot/hostcons.c11
-rw-r--r--stand/kboot/hostdisk.c19
-rw-r--r--stand/kboot/init.c129
-rw-r--r--stand/kboot/kboot.h12
-rw-r--r--stand/kboot/kbootfdt.c78
-rw-r--r--stand/kboot/main.c36
-rw-r--r--stand/kboot/termios.c66
-rw-r--r--stand/kboot/termios.h24
-rw-r--r--stand/kboot/termios_gen.h169
-rw-r--r--stand/liblua/lutils.c19
-rw-r--r--stand/libofw/ofw_disk.c20
-rw-r--r--stand/libsa/Makefile34
-rw-r--r--stand/libsa/arp.c2
-rw-r--r--stand/libsa/bootp.c29
-rw-r--r--stand/libsa/bzipfs.c16
-rw-r--r--stand/libsa/dev.c11
-rw-r--r--stand/libsa/dosfs.c5
-rw-r--r--stand/libsa/ext2fs.c16
-rw-r--r--stand/libsa/geli/Makefile.inc17
-rw-r--r--stand/libsa/geli/geliboot_internal.h2
-rw-r--r--stand/libsa/geli/gelidev.c3
-rw-r--r--stand/libsa/gzipfs.c16
-rw-r--r--stand/libsa/libsa.369
-rw-r--r--stand/libsa/netif.c2
-rw-r--r--stand/libsa/nfs.c16
-rw-r--r--stand/libsa/pkgfs.c16
-rw-r--r--stand/libsa/rarp.c4
-rw-r--r--stand/libsa/smbios.c9
-rw-r--r--stand/libsa/splitfs.c16
-rw-r--r--stand/libsa/stand.h10
-rw-r--r--stand/libsa/tftp.c1
-rw-r--r--stand/libsa/ufs.c14
-rw-r--r--stand/libsa/zfs/Makefile.inc135
-rw-r--r--stand/libsa/zfs/blake3_impl_hack.c35
-rw-r--r--stand/libsa/zfs/devicename_stubs.c2
-rw-r--r--stand/libsa/zfs/libzfs.h2
-rw-r--r--stand/libsa/zfs/spl/sys/blake3.h17
-rw-r--r--stand/libsa/zfs/spl/sys/zfs_context.h32
-rw-r--r--stand/libsa/zfs/zfs.c39
-rw-r--r--stand/libsa/zfs/zfsimpl.c1
-rw-r--r--stand/libsa/zfs/zstd_shim.c45
-rw-r--r--stand/loader.mk1
-rw-r--r--stand/lua/menu.lua17
-rw-r--r--stand/man/loader.efi.8303
-rw-r--r--stand/powerpc/ofw/ldscript.powerpc1
-rw-r--r--stand/powerpc/ofw/ldscript.powerpcle1
-rw-r--r--stand/uboot/devicename.c23
-rw-r--r--stand/uboot/libuboot.h1
-rw-r--r--stand/uboot/main.c16
-rw-r--r--stand/uboot/uboot_disk.c19
-rw-r--r--stand/uboot/uboot_fdt.c1
-rw-r--r--stand/usb/storage/umass_loader.c1
-rw-r--r--stand/userboot/userboot/bootinfo.c28
-rw-r--r--stand/userboot/userboot/bootinfo32.c104
-rw-r--r--stand/userboot/userboot/bootinfo64.c98
-rw-r--r--stand/userboot/userboot/devicename.c34
-rw-r--r--stand/userboot/userboot/host.c18
-rw-r--r--stand/userboot/userboot/libuserboot.h2
-rw-r--r--stand/userboot/userboot/main.c4
-rw-r--r--stand/userboot/userboot/userboot_disk.c19
136 files changed, 2886 insertions, 1572 deletions
diff --git a/stand/Makefile b/stand/Makefile
index 1597f6832c07..4d241c623d97 100644
--- a/stand/Makefile
+++ b/stand/Makefile
@@ -94,3 +94,8 @@ SUBDIR_DEPEND_uboot+= fdt
SUBDIR_PARALLEL= yes
.include <bsd.subdir.mk>
+
+# Simplified way to build-test the most important build combinations for the
+# loader.
+universe:
+ sh ${SRCTOP}/tools/boot/universe.sh
diff --git a/stand/arm64/libarm64/cache.c b/stand/arm64/libarm64/cache.c
index 105e08cb4257..e0c627f36a60 100644
--- a/stand/arm64/libarm64/cache.c
+++ b/stand/arm64/libarm64/cache.c
@@ -1,6 +1,5 @@
/*-
* Copyright (c) 2014 The FreeBSD Foundation
- * All rights reserved.
*
* This software was developed by Semihalf under
* the sponsorship of the FreeBSD Foundation.
@@ -35,7 +34,6 @@ __FBSDID("$FreeBSD$");
#include <machine/atomic.h>
#include <stand.h>
-#include <efi.h>
#include "bootstrap.h"
#include "cache.h"
diff --git a/stand/arm64/libarm64/cache.h b/stand/arm64/libarm64/cache.h
index 5e560c4d578d..9778a28837cb 100644
--- a/stand/arm64/libarm64/cache.h
+++ b/stand/arm64/libarm64/cache.h
@@ -1,6 +1,5 @@
/*-
* Copyright (c) 2014 The FreeBSD Foundation
- * All rights reserved.
*
* This software was developed by Semihalf under
* the sponsorship of the FreeBSD Foundation.
diff --git a/stand/common/bootstrap.h b/stand/common/bootstrap.h
index 9c62a49b0da7..cb1c96dc3b69 100644
--- a/stand/common/bootstrap.h
+++ b/stand/common/bootstrap.h
@@ -52,6 +52,7 @@ extern char command_errbuf[COMMAND_ERRBUFSZ];
void interact(void);
void interp_emit_prompt(void);
int interp_builtin_cmd(int argc, char *argv[]);
+bool interp_has_builtin_cmd(const char *cmd);
/* Called by interp.c for interp_*.c embedded interpreters */
int interp_include(const char *); /* Execute commands from filename */
diff --git a/stand/common/commands.c b/stand/common/commands.c
index 0d21ed44c681..d86c1a4a6f96 100644
--- a/stand/common/commands.c
+++ b/stand/common/commands.c
@@ -576,3 +576,12 @@ command_readtest(int argc, char *argv[])
}
COMMAND_SET(readtest, "readtest", "Time a file read", command_readtest);
+
+static int
+command_quit(int argc, char *argv[])
+{
+ exit(0);
+ return (CMD_OK);
+}
+
+COMMAND_SET(quit, "quit", "exit the loader", command_quit);
diff --git a/stand/common/dev_net.c b/stand/common/dev_net.c
index 70b571047d56..24bfbe9636e3 100644
--- a/stand/common/dev_net.c
+++ b/stand/common/dev_net.c
@@ -86,15 +86,15 @@ static int net_print(int);
static int net_getparams(int sock);
struct devsw netdev = {
- "net",
- DEVT_NET,
- net_init,
- net_strategy,
- net_open,
- net_close,
- noioctl,
- net_print,
- net_cleanup
+ .dv_name = "net",
+ .dv_type = DEVT_NET,
+ .dv_init = net_init,
+ .dv_strategy = net_strategy,
+ .dv_open = net_open,
+ .dv_close = net_close,
+ .dv_ioctl = noioctl,
+ .dv_print = net_print,
+ .dv_cleanup = net_cleanup,
};
static struct uri_scheme {
diff --git a/stand/common/disk.c b/stand/common/disk.c
index 733b7b0d57e7..15daf7e358c6 100644
--- a/stand/common/disk.c
+++ b/stand/common/disk.c
@@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$");
#include <stdarg.h>
#include <bootstrap.h>
#include <part.h>
+#include <assert.h>
#include "disk.h"
@@ -385,12 +386,14 @@ disk_close(struct disk_devdesc *dev)
return (0);
}
-char*
-disk_fmtdev(struct disk_devdesc *dev)
+char *
+disk_fmtdev(struct devdesc *vdev)
{
+ struct disk_devdesc *dev = (struct disk_devdesc *)vdev;
static char buf[128];
char *cp;
+ assert(vdev->d_dev->dv_type == DEVT_DISK);
cp = buf + sprintf(buf, "%s%d", dev->dd.d_dev->dv_name, dev->dd.d_unit);
if (dev->d_slice > D_SLICENONE) {
#ifdef LOADER_GPT_SUPPORT
diff --git a/stand/common/disk.h b/stand/common/disk.h
index 83109981e0a8..806673349cb8 100644
--- a/stand/common/disk.h
+++ b/stand/common/disk.h
@@ -116,7 +116,8 @@ extern int ptblread(void *, void *, size_t, uint64_t);
* Print information about slices on a disk.
*/
extern int disk_print(struct disk_devdesc *, char *, int);
-extern char* disk_fmtdev(struct disk_devdesc *);
extern int disk_parsedev(struct disk_devdesc *, const char *, const char **);
+char *disk_fmtdev(struct devdesc *vdev);
+
#endif /* _DISK_H */
diff --git a/stand/common/interp.c b/stand/common/interp.c
index ab68694d61b7..8b779fb7a5e9 100644
--- a/stand/common/interp.c
+++ b/stand/common/interp.c
@@ -39,6 +39,8 @@ __FBSDID("$FreeBSD$");
#define MAXARGS 20 /* maximum number of arguments allowed */
+const char * volatile interp_identifier;
+
/*
* Interactive mode
*/
@@ -46,7 +48,6 @@ void
interact(void)
{
static char input[256]; /* big enough? */
- const char * volatile interp_identifier;
TSENTER();
@@ -151,6 +152,19 @@ interp_emit_prompt(void)
free(pr);
}
+static struct bootblk_command *
+interp_lookup_cmd(const char *cmd)
+{
+ struct bootblk_command **cmdp;
+
+ /* search the command set for the command */
+ SET_FOREACH(cmdp, Xcommand_set) {
+ if (((*cmdp)->c_name != NULL) && !strcmp(cmd, (*cmdp)->c_name))
+ return (*cmdp);
+ }
+ return (NULL);
+}
+
/*
* Perform a builtin command
*/
@@ -158,27 +172,30 @@ int
interp_builtin_cmd(int argc, char *argv[])
{
int result;
- struct bootblk_command **cmdp;
- bootblk_cmd_t *cmd;
+ struct bootblk_command *cmd;
if (argc < 1)
- return(CMD_OK);
+ return (CMD_OK);
/* set return defaults; a successful command will override these */
command_errmsg = command_errbuf;
strcpy(command_errbuf, "no error message");
- cmd = NULL;
result = CMD_ERROR;
- /* search the command set for the command */
- SET_FOREACH(cmdp, Xcommand_set) {
- if (((*cmdp)->c_name != NULL) && !strcmp(argv[0], (*cmdp)->c_name))
- cmd = (*cmdp)->c_fn;
- }
- if (cmd != NULL) {
- result = (cmd)(argc, argv);
+ cmd = interp_lookup_cmd(argv[0]);
+ if (cmd != NULL && cmd->c_fn) {
+ result = cmd->c_fn(argc, argv);
} else {
command_errmsg = "unknown command";
}
- return(result);
+ return (result);
+}
+
+/*
+ * Return true if the builtin command exists
+ */
+bool
+interp_has_builtin_cmd(const char *cmd)
+{
+ return (interp_lookup_cmd(cmd) != NULL);
}
diff --git a/stand/common/load_elf.c b/stand/common/load_elf.c
index fd9985f51bf9..463578ec3a6b 100644
--- a/stand/common/load_elf.c
+++ b/stand/common/load_elf.c
@@ -98,6 +98,7 @@ const char *__elfN(moduletype) = "elf module";
uint64_t __elfN(relocation_offset) = 0;
+#ifdef __powerpc__
extern void elf_wrong_field_size(void);
#define CONVERT_FIELD(b, f, e) \
switch (sizeof((b)->f)) { \
@@ -203,7 +204,22 @@ static int elf_section_header_convert(const Elf_Ehdr *ehdr, Elf_Shdr *shdr)
}
#undef CONVERT_SWITCH
#undef CONVERT_FIELD
+#else
+static int elf_header_convert(Elf_Ehdr *ehdr)
+{
+ return (0);
+}
+
+static int elf_program_header_convert(const Elf_Ehdr *ehdr, Elf_Phdr *phdr)
+{
+ return (0);
+}
+static int elf_section_header_convert(const Elf_Ehdr *ehdr, Elf_Shdr *shdr)
+{
+ return (0);
+}
+#endif
#ifdef __amd64__
static bool
diff --git a/stand/common/md.c b/stand/common/md.c
index 5585218b3276..9f95d3cdfd2d 100644
--- a/stand/common/md.c
+++ b/stand/common/md.c
@@ -66,15 +66,16 @@ static int md_close(struct open_file *);
static int md_print(int);
struct devsw md_dev = {
- "md",
- DEVT_DISK,
- md_init,
- md_strategy,
- md_open,
- md_close,
- noioctl,
- md_print,
- NULL
+ .dv_name = "md",
+ .dv_type = DEVT_DISK,
+ .dv_init = md_init,
+ .dv_strategy = md_strategy,
+ .dv_open = md_open,
+ .dv_close = md_close,
+ .dv_ioctl = noioctl,
+ .dv_print = md_print,
+ .dv_cleanup = nullsys,
+ .dv_fmtdev = disk_fmtdev,
};
static int
diff --git a/stand/common/metadata.c b/stand/common/metadata.c
index a9c81added02..a69c6d824d44 100644
--- a/stand/common/metadata.c
+++ b/stand/common/metadata.c
@@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$");
#include <machine/metadata.h>
#include "bootstrap.h"
+#include "modinfo.h"
#ifdef LOADER_GELI_SUPPORT
#include "geliboot.h"
@@ -65,136 +66,6 @@ md_getboothowto(char *kargs)
}
/*
- * 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
-md_copyenv(vm_offset_t addr)
-{
- struct env_var *ep;
-
- /* traverse the environment */
- for (ep = environ; ep != NULL; ep = ep->ev_next) {
- archsw.arch_copyin(ep->ev_name, addr, strlen(ep->ev_name));
- addr += strlen(ep->ev_name);
- archsw.arch_copyin("=", addr, 1);
- addr++;
- if (ep->ev_value != NULL) {
- archsw.arch_copyin(ep->ev_value, addr, strlen(ep->ev_value));
- addr += strlen(ep->ev_value);
- }
- archsw.arch_copyin("", addr, 1);
- addr++;
- }
- archsw.arch_copyin("", addr, 1);
- addr++;
- return(addr);
-}
-
-/*
- * 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
- */
-
-static int align;
-
-#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, align); \
-}
-
-#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), align); \
-}
-
-#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, align); \
-}
-
-#define MOD_END(a, c) { \
- COPY32(MODINFO_END, a, c); \
- COPY32(0, a, c); \
-}
-
-static vm_offset_t
-md_copymodules(vm_offset_t addr, int kern64)
-{
- struct preloaded_file *fp;
- struct file_metadata *md;
- uint64_t scratch64;
- uint32_t scratch32;
- int c;
-
- 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 field must come first */
- MOD_TYPE(addr, fp->f_type, c);
- if (fp->f_args)
- MOD_ARGS(addr, fp->f_args, c);
- if (kern64) {
- scratch64 = fp->f_addr;
- MOD_ADDR(addr, scratch64, c);
- scratch64 = fp->f_size;
- MOD_SIZE(addr, scratch64, c);
- } else {
- scratch32 = fp->f_addr;
-#ifdef __arm__
- scratch32 -= __elfN(relocation_offset);
-#endif
- MOD_ADDR(addr, scratch32, c);
- MOD_SIZE(addr, fp->f_size, 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);
-}
-
-/*
* Load the information expected by a kernel.
*
* - The 'boothowto' argument is constructed
@@ -235,7 +106,6 @@ md_load_dual(char *args, vm_offset_t *modulep, vm_offset_t *dtb, int kern64)
};
#endif
- align = kern64 ? 8 : 4;
howto = md_getboothowto(args);
/*
diff --git a/stand/common/modinfo.c b/stand/common/modinfo.c
new file mode 100644
index 000000000000..0c00b2070274
--- /dev/null
+++ b/stand/common/modinfo.c
@@ -0,0 +1,189 @@
+/*-
+ * 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.
+ *
+ * from: FreeBSD: src/sys/boot/sparc64/loader/metadata.c,v 1.6
+ */
+#include <stand.h>
+#include <sys/param.h>
+#include <sys/linker.h>
+#include <sys/boot.h>
+#include <sys/reboot.h>
+#if defined(LOADER_FDT_SUPPORT)
+#include <fdt_platform.h>
+#endif
+
+#ifdef __arm__
+#include <machine/elf.h>
+#endif
+#include <machine/metadata.h>
+
+#include "bootstrap.h"
+#include "modinfo.h"
+
+/*
+ * 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
+ *
+ * Clients are required to define a MOD_ALIGN(l) macro which rounds the passed
+ * in length to the required alignment for the kernel being booted.
+ */
+
+#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 += MOD_ALIGN(strlen(s) + 1); \
+}
+
+#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 += MOD_ALIGN(sizeof(s)); \
+}
+
+#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 += MOD_ALIGN(mm->md_size); \
+}
+
+#define MOD_END(a, c) { \
+ COPY32(MODINFO_END, a, c); \
+ COPY32(0, a, c); \
+}
+
+#define MOD_ALIGN(l) roundup(l, align)
+
+vm_offset_t
+md_copymodules(vm_offset_t addr, bool kern64)
+{
+ struct preloaded_file *fp;
+ struct file_metadata *md;
+ uint64_t scratch64;
+ uint32_t scratch32;
+ int c;
+ int align;
+
+ align = kern64 ? sizeof(uint64_t) : sizeof(uint32_t);
+ 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 field must come first */
+ MOD_TYPE(addr, fp->f_type, c);
+ if (fp->f_args)
+ MOD_ARGS(addr, fp->f_args, c);
+ if (kern64) {
+ scratch64 = fp->f_addr;
+ MOD_ADDR(addr, scratch64, c);
+ scratch64 = fp->f_size;
+ MOD_SIZE(addr, scratch64, c);
+ } else {
+ scratch32 = fp->f_addr;
+#ifdef __arm__
+ scratch32 -= __elfN(relocation_offset);
+#endif
+ MOD_ADDR(addr, scratch32, c);
+ MOD_SIZE(addr, fp->f_size, 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);
+}
+
+/*
+ * 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.
+ */
+vm_offset_t
+md_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);
+}
diff --git a/stand/common/modinfo.h b/stand/common/modinfo.h
new file mode 100644
index 000000000000..e4739df0b68f
--- /dev/null
+++ b/stand/common/modinfo.h
@@ -0,0 +1,12 @@
+/*-
+ * Copyright (c) 2022, Netflix, Inc.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+#ifndef COMMON_MODINFO_H
+#define COMMON_MODINFO_H
+
+vm_offset_t md_copymodules(vm_offset_t addr, bool kern64);
+vm_offset_t md_copyenv(vm_offset_t addr);
+
+#endif /* COMMON_MODINFO_H */
diff --git a/stand/common/vdisk.c b/stand/common/vdisk.c
index 521ad498b194..c4220787b1ac 100644
--- a/stand/common/vdisk.c
+++ b/stand/common/vdisk.c
@@ -52,7 +52,8 @@ struct devsw vdisk_dev = {
.dv_close = vdisk_close,
.dv_ioctl = vdisk_ioctl,
.dv_print = vdisk_print,
- .dv_cleanup = NULL
+ .dv_cleanup = nullsys,
+ .dv_fmtdev = disk_fmtdev,
};
typedef STAILQ_HEAD(vdisk_info_list, vdisk_info) vdisk_info_list_t;
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/include/efilib.h b/stand/efi/include/efilib.h
index 903e1f0d00e5..bbef44fca4b3 100644
--- a/stand/efi/include/efilib.h
+++ b/stand/efi/include/efilib.h
@@ -85,7 +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);
diff --git a/stand/efi/libefi/devicename.c b/stand/efi/libefi/devicename.c
index cdf4830697fd..67a2e24d9da1 100644
--- a/stand/efi/libefi/devicename.c
+++ b/stand/efi/libefi/devicename.c
@@ -171,32 +171,6 @@ fail:
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)
*/
diff --git a/stand/efi/libefi/efihttp.c b/stand/efi/libefi/efihttp.c
index 05d338fbaf04..728f95a47b42 100644
--- a/stand/efi/libefi/efihttp.c
+++ b/stand/efi/libefi/efihttp.c
@@ -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..88587192a1b7 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,8 @@ 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,
};
static pdinfo_list_t fdinfo = STAILQ_HEAD_INITIALIZER(fdinfo);
diff --git a/stand/efi/loader/Makefile b/stand/efi/loader/Makefile
index 1edb5674712e..2aaba4fbb377 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
@@ -103,7 +105,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/arm64/exec.c b/stand/efi/loader/arch/arm64/exec.c
index 6cf4a4fd8e4d..3cf1c1857f51 100644
--- a/stand/efi/loader/arch/arm64/exec.c
+++ b/stand/efi/loader/arch/arm64/exec.c
@@ -81,6 +81,15 @@ 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 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 15.
+ */
+
rsdp = efi_get_table(&acpi20_guid);
if (rsdp == NULL) {
rsdp = efi_get_table(&acpi_guid);
@@ -88,23 +97,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/bootinfo.c b/stand/efi/loader/bootinfo.c
index c7b682819a98..558f7bdae91e 100644
--- a/stand/efi/loader/bootinfo.c
+++ b/stand/efi/loader/bootinfo.c
@@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$");
#include <efilib.h>
#include "bootstrap.h"
+#include "modinfo.h"
#include "loader_efi.h"
#if defined(__amd64__)
@@ -125,134 +126,6 @@ bi_getboothowto(char *kargs)
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);
-}
-
static EFI_STATUS
efi_do_vmap(EFI_MEMORY_DESCRIPTOR *mm, UINTN sz, UINTN mmsz, UINT32 mmver)
{
@@ -478,7 +351,7 @@ 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) {
@@ -496,7 +369,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);
@@ -540,7 +413,7 @@ bi_load(char *args, vm_offset_t *modulep, vm_offset_t *kernendp, bool exit_bs)
#endif
bi_load_efi_data(kfp, exit_bs);
- size = bi_copymodules(0);
+ size = md_copymodules(0, true);
kernend = roundup(addr + size, PAGE_SIZE);
*kernendp = kernend;
@@ -565,7 +438,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, true);
return (0);
}
diff --git a/stand/efi/loader/copy.c b/stand/efi/loader/copy.c
index 47e613ccc2f3..d5e24439ed49 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.
@@ -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;
}
@@ -287,7 +286,7 @@ COMMAND_SET(staging_slop, "staging_slop", "set staging slop",
#if defined(__i386__) || 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.
*/
@@ -479,7 +478,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 +509,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..5edc06c9e0d5 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"
@@ -203,7 +204,7 @@ 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);
}
@@ -273,7 +274,7 @@ probe_zfs_currdev(uint64_t guid)
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();
@@ -719,7 +720,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 +761,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;
@@ -949,6 +962,9 @@ 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
@@ -1280,15 +1296,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/fdt/fdt_loader_cmd.c b/stand/fdt/fdt_loader_cmd.c
index c14b99768d70..8703d5f05e3c 100644
--- a/stand/fdt/fdt_loader_cmd.c
+++ b/stand/fdt/fdt_loader_cmd.c
@@ -1,6 +1,5 @@
/*-
* Copyright (c) 2009-2010 The FreeBSD Foundation
- * All rights reserved.
*
* This software was developed by Semihalf under sponsorship from
* the FreeBSD Foundation.
diff --git a/stand/i386/boot0/Makefile b/stand/i386/boot0/Makefile
index 82eb9eefee76..1453f17751b9 100644
--- a/stand/i386/boot0/Makefile
+++ b/stand/i386/boot0/Makefile
@@ -42,6 +42,13 @@ BOOT_BOOT0_ORG?= 0x600
ORG=${BOOT_BOOT0_ORG}
# Comm settings for boot0sio.
+#
+# boot0sio uses BIOS INT $0x14 for serial ports, we can only support these
+# baudrates due to INT14's limited interface. In addition, if
+# BOOT_BOOT0_COMCONSOLE_SPEED=0, then the baud rate and frame format will remain
+# unchanged. Some BIOSes initialize the serial ports to 115200, and this may
+# allow boot0sio access at that rate if so.
+#
# Bit(s) Description
# 7-5 data rate (110,150,300,600,1200,2400,4800,9600 bps)
# 4-3 parity (00 or 10 = none, 01 = odd, 11 = even)
diff --git a/stand/i386/boot2/boot2.c b/stand/i386/boot2/boot2.c
index 898a8c27df19..0c35fe9b7d93 100644
--- a/stand/i386/boot2/boot2.c
+++ b/stand/i386/boot2/boot2.c
@@ -355,7 +355,7 @@ load(void)
}
static int
-parse()
+parse(void)
{
char *arg, *ep, *p, *q;
const char *cp;
diff --git a/stand/i386/libfirewire/firewire.c b/stand/i386/libfirewire/firewire.c
index b9cb1ec0b19a..c4e4bdaa065f 100644
--- a/stand/i386/libfirewire/firewire.c
+++ b/stand/i386/libfirewire/firewire.c
@@ -76,15 +76,15 @@ static void fw_cleanup(void);
void fw_enable(void);
struct devsw fwohci = {
- "FW1394", /* 7 chars at most */
- DEVT_NET,
- fw_init,
- fw_strategy,
- fw_open,
- fw_close,
- noioctl,
- fw_print,
- fw_cleanup
+ .dv_name = "FW1394", /* 7 chars at most */
+ .dv_type = DEVT_NET,
+ .dv_init = fw_init,
+ .dv_strategy = fw_strategy,
+ .dv_open = fw_open,
+ .dv_close = fw_close,
+ .dv_ioctl = noioctl,
+ .dv_print = fw_print,
+ .dv_cleanup = fw_cleanup,
};
static struct fwohci_softc fwinfo[MAX_OHCI];
diff --git a/stand/i386/libi386/biosacpi.c b/stand/i386/libi386/biosacpi.c
index 236c3fc45e7b..3bda472f3fc6 100644
--- a/stand/i386/libi386/biosacpi.c
+++ b/stand/i386/libi386/biosacpi.c
@@ -63,36 +63,24 @@ biosacpi_detect(void)
/*
* 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.
*/
sprintf(buf, "0x%08x", VTOP(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%08x", rsdp->RsdtPhysicalAddress);
- setenv("hint.acpi.0.rsdt", buf, 1);
setenv("acpi.rsdt", buf, 1);
if (revision >= 2) {
/* XXX extended checksum? */
sprintf(buf, "0x%016llx", 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/i386/libi386/biosdisk.c b/stand/i386/libi386/biosdisk.c
index 2c52617f255d..bc819d8e312e 100644
--- a/stand/i386/libi386/biosdisk.c
+++ b/stand/i386/libi386/biosdisk.c
@@ -165,7 +165,7 @@ struct devsw biosfd = {
.dv_close = bd_close,
.dv_ioctl = bd_ioctl,
.dv_print = fd_print,
- .dv_cleanup = NULL
+ .dv_cleanup = nullsys,
};
struct devsw bioscd = {
@@ -177,7 +177,7 @@ struct devsw bioscd = {
.dv_close = bd_close,
.dv_ioctl = bd_ioctl,
.dv_print = cd_print,
- .dv_cleanup = NULL
+ .dv_cleanup = nullsys,
};
struct devsw bioshd = {
@@ -189,7 +189,8 @@ struct devsw bioshd = {
.dv_close = bd_close,
.dv_ioctl = bd_ioctl,
.dv_print = bd_print,
- .dv_cleanup = NULL
+ .dv_cleanup = nullsys,
+ .dv_fmtdev = disk_fmtdev,
};
static bdinfo_list_t *
@@ -1031,7 +1032,8 @@ bd_realstrategy(void *devdata, int rw, daddr_t dblk, size_t size,
d_offset = dev->d_offset;
}
if (disk_blocks == 0)
- disk_blocks = bd->bd_sectors - d_offset;
+ disk_blocks = bd->bd_sectors * (bd->bd_sectorsize /
+ BIOSDISK_SECSIZE) - d_offset;
/* Validate source block address. */
if (dblk < d_offset || dblk >= d_offset + disk_blocks)
@@ -1285,35 +1287,6 @@ bd_io(struct disk_devdesc *dev, bdinfo_t *bd, daddr_t dblk, int blks,
}
/*
- * Return the BIOS geometry of a given "fixed drive" in a format
- * suitable for the legacy bootinfo structure. Since the kernel is
- * expecting raw int 0x13/0x8 values for N_BIOS_GEOM drives, we
- * prefer to get the information directly, rather than rely on being
- * able to put it together from information already maintained for
- * different purposes and for a probably different number of drives.
- *
- * For valid drives, the geometry is expected in the format (31..0)
- * "000000cc cccccccc hhhhhhhh 00ssssss"; and invalid drives are
- * indicated by returning the geometry of a "1.2M" PC-format floppy
- * disk. And, incidentally, what is returned is not the geometry as
- * such but the highest valid cylinder, head, and sector numbers.
- */
-uint32_t
-bd_getbigeom(int bunit)
-{
-
- v86.ctl = V86_FLAGS;
- v86.addr = DISK_BIOS;
- v86.eax = CMD_READ_PARAM;
- v86.edx = 0x80 + bunit;
- v86int();
- if (V86_CY(v86.efl))
- return (0x4f010f);
- return (((v86.ecx & 0xc0) << 18) | ((v86.ecx & 0xff00) << 8) |
- (v86.edx & 0xff00) | (v86.ecx & 0x3f));
-}
-
-/*
* Return a suitable dev_t value for (dev).
*
* In the case where it looks like (dev) is a SCSI disk, we allow the number of
diff --git a/stand/i386/libi386/bootinfo.c b/stand/i386/libi386/bootinfo.c
index bdf409b00ec0..92238d4fab44 100644
--- a/stand/i386/libi386/bootinfo.c
+++ b/stand/i386/libi386/bootinfo.c
@@ -103,31 +103,3 @@ bi_setboothowto(int howto)
boot_howto_to_env(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.
- */
-vm_offset_t
-bi_copyenv(vm_offset_t addr)
-{
- struct env_var *ep;
-
- /* traverse the environment */
- for (ep = environ; ep != NULL; ep = ep->ev_next) {
- i386_copyin(ep->ev_name, addr, strlen(ep->ev_name));
- addr += strlen(ep->ev_name);
- i386_copyin("=", addr, 1);
- addr++;
- if (ep->ev_value != NULL) {
- i386_copyin(ep->ev_value, addr, strlen(ep->ev_value));
- addr += strlen(ep->ev_value);
- }
- i386_copyin("", addr, 1);
- addr++;
- }
- i386_copyin("", addr, 1);
- addr++;
- return(addr);
-}
diff --git a/stand/i386/libi386/bootinfo32.c b/stand/i386/libi386/bootinfo32.c
index 23b02693cf48..169d2dfb81f4 100644
--- a/stand/i386/libi386/bootinfo32.c
+++ b/stand/i386/libi386/bootinfo32.c
@@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$");
#include <machine/bootinfo.h>
#include <machine/metadata.h>
#include "bootstrap.h"
+#include "modinfo.h"
#include "libi386.h"
#include "btxv86.h"
@@ -41,91 +42,7 @@ __FBSDID("$FreeBSD$");
#include "geliboot.h"
#endif
-static struct bootinfo bi;
-
-/*
- * 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) \
- i386_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) \
- i386_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) \
- i386_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) \
- i386_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_copymodules32(vm_offset_t addr)
-{
- struct preloaded_file *fp;
- struct file_metadata *md;
- int c;
-
- 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 field must come first */
- MOD_TYPE(addr, fp->f_type, c);
- if (fp->f_args)
- MOD_ARGS(addr, fp->f_args, c);
- MOD_ADDR(addr, fp->f_addr, c);
- MOD_SIZE(addr, fp->f_size, 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);
-}
+static struct bootinfo *bi;
/*
* Load the information expected by an i386 kernel.
@@ -167,18 +84,19 @@ bi_load32(char *args, int *howtop, int *bootdevp, vm_offset_t *bip, vm_offset_t
}
/* Try reading the /etc/fstab file to select the root device */
- getrootmount(i386_fmtdev((void *)rootdev));
+ getrootmount(devformat(&rootdev->dd));
/* Do legacy rootdev guessing */
/* XXX - use a default bootdev of 0. Is this ok??? */
bootdevnr = 0;
+ bi = calloc(sizeof(*bi), 1);
switch(rootdev->dd.d_dev->dv_type) {
case DEVT_CD:
case DEVT_DISK:
/* pass in the BIOS device number of the current disk */
- bi.bi_bios_dev = bd_unit2bios(rootdev);
+ bi->bi_bios_dev = bd_unit2bios(rootdev);
bootdevnr = bd_getdev(rootdev);
break;
@@ -191,7 +109,7 @@ bi_load32(char *args, int *howtop, int *bootdevp, vm_offset_t *bip, vm_offset_t
rootdev->dd.d_dev->dv_type);
}
if (bootdevnr == -1) {
- printf("root device %s invalid\n", i386_fmtdev(rootdev));
+ printf("root device %s invalid\n", devformat(&rootdev->dd));
return (EINVAL);
}
free(rootdev);
@@ -209,7 +127,7 @@ bi_load32(char *args, int *howtop, int *bootdevp, vm_offset_t *bip, vm_offset_t
/* copy our environment */
envp = addr;
- addr = bi_copyenv(addr);
+ addr = md_copyenv(addr);
/* pad to a page boundary */
addr = roundup(addr, PAGE_SIZE);
@@ -231,7 +149,7 @@ bi_load32(char *args, int *howtop, int *bootdevp, vm_offset_t *bip, vm_offset_t
/* Figure out the size and location of the metadata */
*modulep = addr;
- size = bi_copymodules32(0);
+ size = md_copymodules(0, false);
kernend = roundup(addr + size, PAGE_SIZE);
*kernendp = kernend;
@@ -240,7 +158,7 @@ bi_load32(char *args, int *howtop, int *bootdevp, vm_offset_t *bip, vm_offset_t
bcopy(&kernend, md->md_data, sizeof kernend);
/* copy module list and metadata */
- (void)bi_copymodules32(addr);
+ (void)md_copymodules(addr, false);
ssym = esym = 0;
md = file_findmetadata(kfp, MODINFOMD_SSYM);
@@ -255,27 +173,22 @@ bi_load32(char *args, int *howtop, int *bootdevp, vm_offset_t *bip, vm_offset_t
/* legacy bootinfo structure */
kernelname = getenv("kernelname");
i386_getdev(NULL, kernelname, &kernelpath);
- bi.bi_version = BOOTINFO_VERSION;
- bi.bi_kernelname = 0; /* XXX char * -> kernel name */
- bi.bi_nfs_diskless = 0; /* struct nfs_diskless * */
- bi.bi_n_bios_used = 0; /* XXX would have to hook biosdisk driver for these */
- for (i = 0; i < N_BIOS_GEOM; i++)
- bi.bi_bios_geom[i] = bd_getbigeom(i);
- bi.bi_size = sizeof(bi);
- bi.bi_memsizes_valid = 1;
- bi.bi_basemem = bios_basemem / 1024;
- bi.bi_extmem = bios_extmem / 1024;
- bi.bi_envp = envp;
- bi.bi_modulep = *modulep;
- bi.bi_kernend = kernend;
- bi.bi_kernelname = VTOP(kernelpath);
- bi.bi_symtab = ssym; /* XXX this is only the primary kernel symtab */
- bi.bi_esymtab = esym;
+ bi->bi_version = BOOTINFO_VERSION;
+ bi->bi_size = sizeof(*bi);
+ bi->bi_memsizes_valid = 1;
+ bi->bi_basemem = bios_basemem / 1024;
+ bi->bi_extmem = bios_extmem / 1024;
+ bi->bi_envp = envp;
+ bi->bi_modulep = *modulep;
+ bi->bi_kernend = kernend;
+ bi->bi_kernelname = VTOP(kernelpath);
+ bi->bi_symtab = ssym; /* XXX this is only the primary kernel symtab */
+ bi->bi_esymtab = esym;
/* legacy boot arguments */
*howtop = howto | RB_BOOTINFO;
*bootdevp = bootdevnr;
- *bip = VTOP(&bi);
+ *bip = VTOP(bi);
return(0);
}
diff --git a/stand/i386/libi386/bootinfo64.c b/stand/i386/libi386/bootinfo64.c
index 1ffa4188d926..bc8830d09098 100644
--- a/stand/i386/libi386/bootinfo64.c
+++ b/stand/i386/libi386/bootinfo64.c
@@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
#include <machine/psl.h>
#include <machine/specialreg.h>
#include "bootstrap.h"
+#include "modinfo.h"
#include "libi386.h"
#include "btxv86.h"
@@ -45,93 +46,6 @@ __FBSDID("$FreeBSD$");
#endif
/*
- * 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) \
- i386_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) \
- i386_copyin(s, a, strlen(s) + 1); \
- a += roundup(strlen(s) + 1, sizeof(uint64_t));\
-}
-
-#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) \
- i386_copyin(&s, a, sizeof(s)); \
- a += roundup(sizeof(s), sizeof(uint64_t)); \
-}
-
-#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) \
- i386_copyin(mm->md_data, a, mm->md_size); \
- a += roundup(mm->md_size, sizeof(uint64_t));\
-}
-
-#define MOD_END(a, c) { \
- COPY32(MODINFO_END, a, c); \
- COPY32(0, a, c); \
-}
-
-static vm_offset_t
-bi_copymodules64(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 field 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;
- 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);
-}
-
-/*
* Check to see if this CPU supports long mode.
*/
static int
@@ -216,7 +130,7 @@ bi_load64(char *args, vm_offset_t *modulep,
}
/* Try reading the /etc/fstab file to select the root device */
- getrootmount(i386_fmtdev((void *)rootdev));
+ getrootmount(devformat(&rootdev->dd));
addr = 0;
/* find the last module in the chain */
@@ -249,11 +163,11 @@ bi_load64(char *args, vm_offset_t *modulep,
#endif
bi_load_vbe_data(kfp);
- size = bi_copymodules64(0);
+ size = md_copymodules(0, true);
/* copy our environment */
envp = roundup(addr + size, PAGE_SIZE);
- addr = bi_copyenv(envp);
+ addr = md_copyenv(envp);
/* set kernend */
kernend = roundup(addr, PAGE_SIZE);
@@ -268,7 +182,7 @@ bi_load64(char *args, vm_offset_t *modulep,
bcopy(&envp, md->md_data, sizeof envp);
/* copy module list and metadata */
- (void)bi_copymodules64(*modulep);
+ (void)md_copymodules(*modulep, true);
return(0);
}
diff --git a/stand/i386/libi386/devicename.c b/stand/i386/libi386/devicename.c
index 061f2ba9ce9f..73445aeba172 100644
--- a/stand/i386/libi386/devicename.c
+++ b/stand/i386/libi386/devicename.c
@@ -171,33 +171,6 @@ i386_parsedev(struct i386_devdesc **dev, const char *devspec, const char **path)
return(err);
}
-
-char *
-i386_fmtdev(void *vdev)
-{
- struct i386_devdesc *dev = (struct i386_devdesc *)vdev;
- static char buf[128]; /* XXX device length constant? */
-
- switch(dev->dd.d_dev->dv_type) {
- case DEVT_NONE:
- strcpy(buf, "(no device)");
- break;
-
- case DEVT_CD:
- case DEVT_NET:
- sprintf(buf, "%s%d:", dev->dd.d_dev->dv_name, dev->dd.d_unit);
- break;
-
- case DEVT_DISK:
- return (disk_fmtdev(vdev));
-
- case DEVT_ZFS:
- return(zfs_fmtdev(vdev));
- }
- return(buf);
-}
-
-
/*
* Set currdev to suit the value being supplied in (value)
*/
diff --git a/stand/i386/libi386/libi386.h b/stand/i386/libi386/libi386.h
index a52a1190e7ec..0115f30e31c7 100644
--- a/stand/i386/libi386/libi386.h
+++ b/stand/i386/libi386/libi386.h
@@ -27,25 +27,23 @@
*/
+#include "disk.h"
+#ifdef LOADER_ZFS_SUPPORT
+#include "libzfs.h"
+#endif
/*
* i386 fully-qualified device descriptor.
*/
-struct i386_devdesc {
- struct devdesc dd; /* Must be first. */
- union
- {
- struct
+struct i386_devdesc
+{
+ union
{
- int slice;
- int partition;
- off_t offset;
- } biosdisk;
- struct
- {
- uint64_t pool_guid;
- uint64_t root_guid;
- } zfs;
- } d_kind;
+ struct devdesc dd;
+ struct disk_devdesc disk;
+#ifdef LOADER_ZFS_SUPPORT
+ struct zfs_devdesc zfs;
+#endif
+ };
};
/*
@@ -148,7 +146,6 @@ int i386_autoload(void);
void bi_load_vbe_data(struct preloaded_file *kfp);
int bi_getboothowto(char *kargs);
void bi_setboothowto(int howto);
-vm_offset_t bi_copyenv(vm_offset_t addr);
int bi_load32(char *args, int *howtop, int *bootdevp, vm_offset_t *bip,
vm_offset_t *modulep, vm_offset_t *kernend);
int bi_load64(char *args, vm_offset_t *modulep,
diff --git a/stand/i386/libi386/pxe.c b/stand/i386/libi386/pxe.c
index e80a1961e191..3c6c5468fe37 100644
--- a/stand/i386/libi386/pxe.c
+++ b/stand/i386/libi386/pxe.c
@@ -119,7 +119,7 @@ struct devsw pxedisk = {
.dv_close = NULL, /* Will be set in pxe_init */
.dv_ioctl = noioctl,
.dv_print = pxe_print,
- .dv_cleanup = pxe_cleanup
+ .dv_cleanup = pxe_cleanup,
};
/*
diff --git a/stand/i386/libi386/vidconsole.c b/stand/i386/libi386/vidconsole.c
index 1ec6b4f5393a..7e798a1b8504 100644
--- a/stand/i386/libi386/vidconsole.c
+++ b/stand/i386/libi386/vidconsole.c
@@ -36,7 +36,6 @@ __FBSDID("$FreeBSD$");
#include <btxv86.h>
#include <gfx_fb.h>
#include <teken.h>
-#include <stdbool.h>
#include "vbe.h"
#include <dev/vt/hw/vga/vt_vga_reg.h>
diff --git a/stand/i386/loader/Makefile b/stand/i386/loader/Makefile
index 571e3b2cb653..3195cb00c6be 100644
--- a/stand/i386/loader/Makefile
+++ b/stand/i386/loader/Makefile
@@ -19,6 +19,22 @@ PROG= ${LOADER}.sym
INTERNALPROG=
NEWVERSWHAT?= "bootstrap loader" x86
VERSION_FILE= ${.CURDIR}/../loader/version
+#
+# There's 640k - 40k maximum space, less however much memory the BIOS uses. A
+# non-random survey suggests that 20k-25k is a good value for 'most' machines.
+# We also need to subtract maximum stack usage (20-25k).
+#
+# So 640k - 40k - 25k - 25k = 550k = 563,200 bytes, but use 550,000 below for
+# some extra buffer for more complex setups and/or wider BIOS lomem variation.
+#
+# Some systems use more stack or have BIOS reserve more RAM (or both), and will
+# need to set this lower in /etc/src.conf if the above buffer is too small.
+#
+# sudo dd if=/dev/mem bs=1 iseek=0x413 count=2 | hd -d
+#
+# will tell you how many kiB of lomem are available.
+#
+LOADERSIZE?= 550000 # Largest known safe size for loader.bin
.PATH: ${BOOTSRC}/i386/loader
@@ -79,12 +95,15 @@ CFLAGS+= -I${BOOTSRC}/i386
8x16.c: ${SRCTOP}/contrib/terminus/ter-u16b.bdf
vtfontcvt -f compressed-source -o ${.TARGET} ${.ALLSRC}
+
${LOADER}: ${LOADER}.bin ${BTXLDR} ${BTXKERN}
btxld -v -f aout -e ${LOADER_ADDRESS} -o ${.TARGET} -l ${BTXLDR} \
-b ${BTXKERN} ${LOADER}.bin
${LOADER}.bin: ${LOADER}.sym
${STRIPBIN} -R .comment -R .note -o ${.TARGET} ${.ALLSRC}
+ @set -- `ls -l ${.TARGET}` ; x=$$((${LOADERSIZE}-$$5)); \
+ echo "$$x bytes available"; test $$x -ge 0
.if ${MK_LOADER_ZFS} == "yes" && ${LOADER_INTERP} == ${LOADER_DEFAULT_INTERP}
LINKS+= ${BINDIR}/${LOADER} ${BINDIR}/zfsloader
@@ -98,8 +117,8 @@ FILESMODE_${LOADER}= ${BINMODE} -b
# Note: crt0.o needs to be first for pxeboot(8) to work. It assumes that the
# startup code is located at the start of the loader and will jump
# there. Although btx is more flexible than this, the emulated boot2 environment
-# that pxeloader provides has none of that flexibility because it lacks access
-# to the a.out/elf headers and assumes an entry point of 0.
+# that pxeldr provides has none of that flexibility assumes an entry point of
+# 0. In addition, pxeldr and cdboot assume that it is loading an a.out file.
#
# We must add it to the LDFLAGS instead of the OBJS because the former won't try
# to clean it. When it is in OBJS, this cleaning can lead to races where
diff --git a/stand/i386/loader/main.c b/stand/i386/loader/main.c
index cb716d7a9f21..15d1c312b278 100644
--- a/stand/i386/loader/main.c
+++ b/stand/i386/loader/main.c
@@ -308,8 +308,8 @@ extract_currdev(void)
new_currdev.dd.d_unit = 0;
} else {
/* we don't know what our boot device is */
- new_currdev.d_kind.biosdisk.slice = -1;
- new_currdev.d_kind.biosdisk.partition = 0;
+ new_currdev.disk.d_slice = -1;
+ new_currdev.disk.d_partition = 0;
biosdev = -1;
}
#ifdef LOADER_ZFS_SUPPORT
@@ -322,8 +322,8 @@ extract_currdev(void)
zargs->size >=
offsetof(struct zfs_boot_args, primary_pool)) {
/* sufficient data is provided */
- new_currdev.d_kind.zfs.pool_guid = zargs->pool;
- new_currdev.d_kind.zfs.root_guid = zargs->root;
+ new_currdev.zfs.pool_guid = zargs->pool;
+ new_currdev.zfs.root_guid = zargs->root;
if (zargs->size >= sizeof(*zargs) &&
zargs->primary_vdev != 0) {
sprintf(buf, "%llu", zargs->primary_pool);
@@ -333,8 +333,8 @@ extract_currdev(void)
}
} else {
/* old style zfsboot block */
- new_currdev.d_kind.zfs.pool_guid = kargs->zfspool;
- new_currdev.d_kind.zfs.root_guid = 0;
+ new_currdev.zfs.pool_guid = kargs->zfspool;
+ new_currdev.zfs.root_guid = 0;
}
new_currdev.dd.d_dev = &zfs_dev;
@@ -350,14 +350,12 @@ extract_currdev(void)
#endif
} else if ((initial_bootdev & B_MAGICMASK) != B_DEVMAGIC) {
/* The passed-in boot device is bad */
- new_currdev.d_kind.biosdisk.slice = -1;
- new_currdev.d_kind.biosdisk.partition = 0;
+ new_currdev.disk.d_slice = -1;
+ new_currdev.disk.d_partition = 0;
biosdev = -1;
} else {
- new_currdev.d_kind.biosdisk.slice =
- B_SLICE(initial_bootdev) - 1;
- new_currdev.d_kind.biosdisk.partition =
- B_PARTITION(initial_bootdev);
+ new_currdev.disk.d_slice = B_SLICE(initial_bootdev) - 1;
+ new_currdev.disk.d_partition = B_PARTITION(initial_bootdev);
biosdev = initial_bootinfo->bi_bios_dev;
/*
@@ -389,12 +387,12 @@ extract_currdev(void)
#ifdef LOADER_ZFS_SUPPORT
if (new_currdev.dd.d_dev->dv_type == DEVT_ZFS)
- init_zfs_boot_options(zfs_fmtdev(&new_currdev));
+ init_zfs_boot_options(devformat(&new_currdev.dd));
#endif
- env_setenv("currdev", EV_VOLATILE, i386_fmtdev(&new_currdev),
+ env_setenv("currdev", EV_VOLATILE, devformat(&new_currdev.dd),
i386_setcurrdev, env_nounset);
- env_setenv("loaddev", EV_VOLATILE, i386_fmtdev(&new_currdev),
+ env_setenv("loaddev", EV_VOLATILE, devformat(&new_currdev.dd),
env_noset, env_nounset);
}
diff --git a/stand/i386/pxeldr/Makefile b/stand/i386/pxeldr/Makefile
index 2184d391937f..790f5ed8f0e9 100644
--- a/stand/i386/pxeldr/Makefile
+++ b/stand/i386/pxeldr/Makefile
@@ -38,6 +38,8 @@ LDFLAGS+=${LDFLAGS_BIN}
CLEANFILES+= ${LOADER}
+# Note: pxeldr.S assumes a.out and will require changes for ELF if the output
+# format is changed to ELF.
${LOADER}: ${LOADERBIN} ${BTXLDR} ${BTXKERN}
btxld -v -f aout -e ${LOADER_ADDRESS} -o ${.TARGET} -l ${BTXLDR} \
-b ${BTXKERN} ${LOADERBIN}
diff --git a/stand/i386/zfsboot/zfsboot.c b/stand/i386/zfsboot/zfsboot.c
index 8dd3066f15e5..930a6fb530af 100644
--- a/stand/i386/zfsboot/zfsboot.c
+++ b/stand/i386/zfsboot/zfsboot.c
@@ -222,11 +222,11 @@ main(void)
devdesc.d_partition >= 0 ? devdesc.d_partition : 0xff);
/*
- * zfs_fmtdev() can be called only after dv_init
+ * devformat() can be called only after dv_init
*/
if (bdev != NULL && bdev->dd.d_dev->dv_type == DEVT_ZFS) {
/* set up proper device name string for ZFS */
- strncpy(boot_devname, zfs_fmtdev(bdev), sizeof (boot_devname));
+ strncpy(boot_devname, devformat(&bdev->dd), sizeof (boot_devname));
if (zfs_get_bootonce(bdev, OS_BOOTONCE, cmd,
sizeof(cmd)) == 0) {
nvlist_t *benv;
@@ -467,8 +467,8 @@ load(void)
if (bdev->dd.d_dev->dv_type == DEVT_ZFS) {
zfsargs.size = sizeof(zfsargs);
- zfsargs.pool = bdev->d_kind.zfs.pool_guid;
- zfsargs.root = bdev->d_kind.zfs.root_guid;
+ zfsargs.pool = bdev->zfs.pool_guid;
+ zfsargs.root = bdev->zfs.root_guid;
#ifdef LOADER_GELI_SUPPORT
export_geli_boot_data(&zfsargs.gelidata);
#endif
@@ -481,8 +481,8 @@ load(void)
__exec((caddr_t)addr, RB_BOOTINFO | (opts & RBX_MASK),
bootdev,
KARGS_FLAGS_ZFS | KARGS_FLAGS_EXTARG,
- (uint32_t)bdev->d_kind.zfs.pool_guid,
- (uint32_t)(bdev->d_kind.zfs.pool_guid >> 32),
+ (uint32_t)bdev->zfs.pool_guid,
+ (uint32_t)(bdev->zfs.pool_guid >> 32),
VTOP(&bootinfo),
zfsargs);
} else {
@@ -528,13 +528,12 @@ mount_root(char *arg)
free(bdev);
bdev = ddesc;
if (bdev->dd.d_dev->dv_type == DEVT_DISK) {
- if (bdev->d_kind.biosdisk.partition == -1)
+ if (bdev->disk.d_partition == -1)
part = 0xff;
else
- part = bdev->d_kind.biosdisk.partition;
+ part = bdev->disk.d_partition;
bootdev = MAKEBOOTDEV(dev_maj[bdev->dd.d_dev->dv_type],
- bdev->d_kind.biosdisk.slice + 1,
- bdev->dd.d_unit, part);
+ bdev->disk.d_slice + 1, bdev->dd.d_unit, part);
bootinfo.bi_bios_dev = bd_unit2bios(bdev);
}
strncpy(boot_devname, root, sizeof (boot_devname));
@@ -714,8 +713,8 @@ i386_zfs_probe(void)
if (pool_guid != 0 && bdev == NULL) {
bdev = malloc(sizeof (struct i386_devdesc));
bzero(bdev, sizeof (struct i386_devdesc));
- bdev->dd.d_dev = &zfs_dev;
- bdev->d_kind.zfs.pool_guid = pool_guid;
+ bdev->zfs.dd.d_dev = &zfs_dev;
+ bdev->zfs.pool_guid = pool_guid;
}
}
}
diff --git a/stand/kboot/Makefile b/stand/kboot/Makefile
index 24ab77af66db..518e945a596e 100644
--- a/stand/kboot/Makefile
+++ b/stand/kboot/Makefile
@@ -1,5 +1,6 @@
# $FreeBSD$
+LOADER_DISK_SUPPORT?= yes
LOADER_CD9660_SUPPORT?= yes
LOADER_MSDOS_SUPPORT?= no
LOADER_EXT2FS_SUPPORT?= yes
@@ -17,12 +18,26 @@ NEWVERSWHAT= "kboot loader" ${MACHINE_ARCH}
INSTALLFLAGS= -b
# Architecture-specific loader code
-SRCS= vers.c main.c host_syscalls.c hostcons.c hostdisk.c kbootfdt.c gfx_fb_stub.c
+SRCS= \
+ conf.c \
+ crt1.c \
+ gfx_fb_stub.c \
+ host_syscalls.c \
+ hostcons.c \
+ hostdisk.c \
+ init.c \
+ kbootfdt.c \
+ main.c \
+ termios.c \
+ vers.c \
CFLAGS.gfx_fb_stub.c += -I${SRCTOP}/contrib/pnglite -I${SRCTOP}/sys/teken
.include "${BOOTSRC}/fdt.mk"
+# Note: Since we're producing a userland binary, we key off of MACHINE_ARCH
+# instead of the more normal MACHINE since the changes between different flavors
+# of MACHINE_ARCH are large enough in Linux that it's easier that way.
.PATH: ${.CURDIR}/arch/${MACHINE_ARCH}
.include "${.CURDIR}/arch/${MACHINE_ARCH}/Makefile.inc"
diff --git a/stand/kboot/arch/aarch64/Makefile.inc b/stand/kboot/arch/aarch64/Makefile.inc
new file mode 100644
index 000000000000..5573d264ec4e
--- /dev/null
+++ b/stand/kboot/arch/aarch64/Makefile.inc
@@ -0,0 +1,12 @@
+SRCS+= host_syscall.S tramp.S exec.c load_addr.c
+
+.PATH: ${BOOTSRC}/arm64/libarm64
+CFLAGS+=-I${BOOTSRC}/arm64/libarm64
+SRCS+= cache.c
+
+CFLAGS+= -I${SYSDIR}/contrib/dev/acpica/include
+# load address. set in linker script
+RELOC?= 0x0
+CFLAGS+= -DRELOC=${RELOC}
+
+LDFLAGS= -nostdlib -static -T ${.CURDIR}/arch/${MACHINE_ARCH}/ldscript.${MACHINE_ARCH}
diff --git a/stand/kboot/arch/aarch64/exec.c b/stand/kboot/arch/aarch64/exec.c
new file mode 100644
index 000000000000..56a206c0f09f
--- /dev/null
+++ b/stand/kboot/arch/aarch64/exec.c
@@ -0,0 +1,188 @@
+/*-
+ * Copyright (c) 2006 Marcel Moolenaar
+ * 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 <string.h>
+
+#include <sys/param.h>
+#include <sys/linker.h>
+#include <machine/elf.h>
+
+#include <bootstrap.h>
+
+#ifdef EFI
+#include <efi.h>
+#include <efilib.h>
+
+#include "loader_efi.h"
+
+#endif
+
+#include "bootstrap.h"
+
+#include "platform/acfreebsd.h"
+#include "acconfig.h"
+#define ACPI_SYSTEM_XFACE
+#include "actypes.h"
+#include "actbl.h"
+
+#include "cache.h"
+
+#ifdef EFI
+static EFI_GUID acpi_guid = ACPI_TABLE_GUID;
+static EFI_GUID acpi20_guid = ACPI_20_TABLE_GUID;
+#endif
+
+static int elf64_exec(struct preloaded_file *amp);
+static int elf64_obj_exec(struct preloaded_file *amp);
+
+/* Stub out temporarily */
+static int
+bi_load(char *args, vm_offset_t *modulep, vm_offset_t *kernendp,
+ bool exit_bs)
+{
+ return EINVAL;
+}
+
+static struct file_format arm64_elf = {
+ elf64_loadfile,
+ elf64_exec
+};
+
+struct file_format *file_formats[] = {
+ &arm64_elf,
+ NULL
+};
+
+static int
+elf64_exec(struct preloaded_file *fp)
+{
+ vm_offset_t modulep, kernendp;
+ vm_offset_t clean_addr;
+ size_t clean_size;
+ struct file_metadata *md;
+ Elf_Ehdr *ehdr;
+ void (*entry)(vm_offset_t);
+ int err;
+#ifdef EFI
+ ACPI_TABLE_RSDP *rsdp;
+ char buf[24];
+ int revision;
+#endif
+ /*
+ * Report the RSDP to the kernel. 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 15.
+ */
+#ifdef EFI
+ rsdp = efi_get_table(&acpi20_guid);
+ if (rsdp == NULL) {
+ rsdp = efi_get_table(&acpi_guid);
+ }
+ 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);
+ }
+ }
+#else
+#endif
+
+ if ((md = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL)
+ return(EFTYPE);
+
+ ehdr = (Elf_Ehdr *)&(md->md_data);
+#ifdef EFI
+ entry = efi_translate(ehdr->e_entry);
+
+ efi_time_fini();
+#else
+ entry = (void *)ehdr->e_entry;
+#endif
+ err = bi_load(fp->f_args, &modulep, &kernendp, true);
+ if (err != 0) {
+#ifdef EFI
+ efi_time_init();
+#endif
+ return (err);
+ }
+
+ dev_cleanup();
+
+ /* Clean D-cache under kernel area and invalidate whole I-cache */
+#ifdef EFI
+ clean_addr = (vm_offset_t)efi_translate(fp->f_addr);
+ clean_size = (vm_offset_t)efi_translate(kernendp) - clean_addr;
+#else
+ clean_addr = (vm_offset_t)fp->f_addr;
+ clean_size = (vm_offset_t)kernendp - clean_addr;
+#endif
+
+ cpu_flush_dcache((void *)clean_addr, clean_size);
+ cpu_inval_icache();
+
+ (*entry)(modulep);
+
+ panic("exec returned");
+}
+
+static int
+elf64_obj_exec(struct preloaded_file *fp)
+{
+
+ printf("%s called for preloaded file %p (=%s):\n", __func__, fp,
+ fp->f_name);
+ return (ENOSYS);
+}
+
diff --git a/stand/kboot/arch/aarch64/host_syscall.S b/stand/kboot/arch/aarch64/host_syscall.S
new file mode 100644
index 000000000000..db3ecf0f885d
--- /dev/null
+++ b/stand/kboot/arch/aarch64/host_syscall.S
@@ -0,0 +1,18 @@
+#include <machine/asm.h>
+
+/*
+ * Emulate the Linux system call interface. System call number in x8.
+ * Args in x0, x1, x2, x3, x4 and x5. Return in x0.
+ */
+ENTRY(host_syscall)
+ mov x8, x0
+ mov x0, x1
+ mov x1, x2
+ mov x2, x3
+ mov x3, x4
+ mov x4, x5
+ mov x5, x6
+ svc 0
+ ret
+/* Note: We're exposing the raw return value to the caller */
+END(host_syscall)
diff --git a/stand/kboot/arch/aarch64/ldscript.aarch64 b/stand/kboot/arch/aarch64/ldscript.aarch64
new file mode 100644
index 000000000000..d7107fe8c18a
--- /dev/null
+++ b/stand/kboot/arch/aarch64/ldscript.aarch64
@@ -0,0 +1,72 @@
+/* $FreeBSD$ */
+OUTPUT_FORMAT("elf64-aarch64", "elf64-aarch64", "elf64-aarch64")
+OUTPUT_ARCH(aarch64)
+ENTRY(_start)
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ . = 0x401000;
+ ImageBase = .;
+ .hash : { *(.hash) } /* this MUST come first! */
+ . = ALIGN(4096);
+ .eh_frame :
+ {
+ *(.eh_frame)
+ }
+ . = 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);
+ .rela.dyn : {
+ *(.rela.data*)
+ *(.rela.got)
+ *(.rela.stab)
+ *(.relaset_*)
+ }
+ . = ALIGN(4096);
+ .reloc : { *(.reloc) }
+ . = ALIGN(4096);
+ .dynsym : { *(.dynsym) }
+ . = ALIGN(4096);
+ .dynstr : { *(.dynstr) }
+}
diff --git a/stand/kboot/arch/aarch64/load_addr.c b/stand/kboot/arch/aarch64/load_addr.c
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/stand/kboot/arch/aarch64/load_addr.c
diff --git a/stand/kboot/arch/aarch64/start_arch.h b/stand/kboot/arch/aarch64/start_arch.h
new file mode 100644
index 000000000000..467ba054c9f0
--- /dev/null
+++ b/stand/kboot/arch/aarch64/start_arch.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2022, Netflix, Inc.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+/*
+ * Provides a _start routine that calls a _start_c routine that takes a pointer
+ * to the stack as documented in crt1.c. We skip the pointer to _DYNAMIC since
+ * we don't support dynamic libraries, at all. And while _start_c is our own
+ * thing and doesn't have a second arg, we comport to the calling conventions
+ * that glibc and musl have by passing x1 as 0 for the dynamic pointer. We
+ * likely could call main directly with only a few more lines of code, but this
+ * is simple enough and concentrates all the expressable in C stuff there. We
+ * also generate eh_frames should we need to debug things (it doesn't change the
+ * genreated code, but leaves enough breadcrumbs to keep gdb happy)
+ */
+
+__asm__(
+".text\n" /* ENTRY(_start) -- can't expand and stringify, so by hand */
+".align 2\n"
+".global _start\n"
+".type _start, #function\n"
+"_start:\n"
+".cfi_startproc\n"
+/*
+ * Linux zeros all registers so x29 (frame pointer) and x30 (link register) are 0.
+ */
+" mov x0, sp\n" /* Pointer to argc, etc kernel left on the stack */
+" and sp, x0, #-16\n" /* Align stack to 16-byte boundary */
+" b _start_c\n" /* Our MI code takes it from here */
+/* NORETURN */
+".ltorg\n" /* END(_start) */
+".cfi_endproc\n"
+".size _start, .-_start\n"
+);
diff --git a/stand/kboot/arch/aarch64/stat_arch.h b/stand/kboot/arch/aarch64/stat_arch.h
new file mode 100644
index 000000000000..2462caed8682
--- /dev/null
+++ b/stand/kboot/arch/aarch64/stat_arch.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2005-2020 Rich Felker, et al.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Note: From the musl project
+ */
+
+struct host_kstat {
+ host_dev_t st_dev;
+ host_ino_t st_ino;
+ host_mode_t st_mode;
+ host_nlink_t st_nlink;
+ host_uid_t st_uid;
+ host_gid_t st_gid;
+ host_dev_t st_rdev;
+ unsigned long __pad;
+ host_off_t st_size;
+ host_blksize_t st_blksize;
+ int __pad2;
+ host_blkcnt_t st_blocks;
+ long st_atime_sec;
+ long st_atime_nsec;
+ long st_mtime_sec;
+ long st_mtime_nsec;
+ long st_ctime_sec;
+ long st_ctime_nsec;
+ unsigned __pad_for_future[2];
+};
diff --git a/stand/kboot/arch/aarch64/syscall_nr.h b/stand/kboot/arch/aarch64/syscall_nr.h
new file mode 100644
index 000000000000..83069dd8dc76
--- /dev/null
+++ b/stand/kboot/arch/aarch64/syscall_nr.h
@@ -0,0 +1,22 @@
+#define SYS_close 57
+#define SYS_dup 23
+#define SYS_exit 93
+#define SYS_fstat 80
+#define SYS_getdents64 61
+#define SYS_getpid 172
+#define SYS_gettimeofday 169
+#define SYS_ioctl 29
+#define SYS_lseek 62
+#define SYS_kexec_load 104
+#define SYS_mkdirat 34
+#define SYS_mmap 222
+#define SYS_mount 40
+#define SYS_munmap 215
+#define SYS_newfstatat 79
+#define SYS_openat 56
+#define SYS_pselect6 72
+#define SYS_read 63
+#define SYS_reboot 142
+#define SYS_symlinkat 36
+#define SYS_uname 160
+#define SYS_write 64
diff --git a/stand/kboot/arch/aarch64/tramp.S b/stand/kboot/arch/aarch64/tramp.S
new file mode 100644
index 000000000000..1edb6823bdc9
--- /dev/null
+++ b/stand/kboot/arch/aarch64/tramp.S
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2022, Netflix, Inc.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+/*
+ * This is the trampoline that starts the FreeBSD kernel. Since the Linux kernel
+ * calls this routine with no args, and has a different environment than the boot
+ * loader provides and that the kernel expects, this code is responsible for setting
+ * all that up and calling the normal kernel entry point. It's analogous ot the
+ * "purgatory" code in the linux kernel. Details about these operations are
+ * contained in comments below. On aarch64, the kernel will start all the APs so
+ * we don't have to worry about them here.
+ */
+
+/*
+ * Keep in sync with exec.c. Kexec starts aarch64_tramp w/o any
+ * parameters, so store them here.
+ *
+ * struct trampoline_data {
+ * uint64_t entry; // 0 (PA where kernel loaded)
+ * uint64_t modulep; // 8 module metadata
+ * };
+ *
+ * The aarch64 _start routine assumes:
+ * MMU on with an identity map, or off
+ * D-Cache: off
+ * I-Cache: on or off
+ * We are loaded at a 2MiB aligned address
+ * Module data (modulep) pointer in x0
+ *
+ * Unlike EFI, we don't support copying the staging area. We tell Linunx to land
+ * the kernel in its final location with the needed alignment, etc.
+ *
+ * This trampoline installs sets up the arguments the kernel expects, flushes
+ * the cache lines and jumps to the kernel _start address. We pass the modulep
+ * pointer in x0, as _start expects.
+ */
+ .text
+ .globl aarch64_tramp
+aarch64_tramp:
+ b 1f /* skip over our saved args */
+ .p2align 3
+trampoline_data:
+#define TRAMP_ENTRY 0
+#define TRAMP_MODULEP 8
+#define TRAMP_TOTAL 16
+ .space TRAMP_TOTAL
+#define TMPSTACKSIZE 48 /* 16 bytes for args +8 for pushq/popfq + 24 spare */
+1:
+ adr x2, trampoline_data
+ ldr x1, [x2, #TRAMP_ENTRY]
+ ldr x0, [x2, #TRAMP_MODULEP]
+ br x1
+
+ .p2align 4
+ .space TMPSTACKSIZE
+aarch64_tramp_end: /* padding doubles as stack */
+
+ .data
+ .globl aarch64_tramp_size
+aarch64_tramp_size:
+ .long aarch64_tramp_end-aarch64_tramp
+ .globl aarch64_tramp_data_offset
+aarch64_tramp_data_offset:
+ .long trampoline_data-aarch64_tramp
diff --git a/stand/kboot/arch/amd64/Makefile.inc b/stand/kboot/arch/amd64/Makefile.inc
index fb954e798599..79ddbd67f5b6 100644
--- a/stand/kboot/arch/amd64/Makefile.inc
+++ b/stand/kboot/arch/amd64/Makefile.inc
@@ -1,8 +1,5 @@
-SRCS+= conf.c host_syscall.S amd64_tramp.S elf64_freebsd.c
+SRCS+= host_syscall.S amd64_tramp.S elf64_freebsd.c
CFLAGS+= -I${SYSDIR}/contrib/dev/acpica/include
-# load address. set in linker script
-RELOC?= 0x0
-CFLAGS+= -DRELOC=${RELOC}
LDFLAGS= -nostdlib -static -T ${.CURDIR}/arch/${MACHINE_ARCH}/ldscript.amd64
diff --git a/stand/kboot/arch/amd64/start_arch.h b/stand/kboot/arch/amd64/start_arch.h
new file mode 100644
index 000000000000..818a5b277c10
--- /dev/null
+++ b/stand/kboot/arch/amd64/start_arch.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2022, Netflix, Inc.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+/*
+ * Provides a _start routine that calls a _start_c routine that takes a pointer
+ * to the stack as documented in crt1.c. We skip the pointer to _DYNAMIC since
+ * we don't support dynamic libraries, at all. And while _start_c is our own
+ * thing, we comport to the calling conventions that glibc and musl have and
+ * make sure the second argument (%esi) is 0 for _DYNAMIC placeholder. We
+ * likely could call main directly with only a few more lines of code, but this
+ * is simple enough and concentrates all the expressable in C stuff there. We
+ * also generate eh_frames should we need to debug things (it doesn't change the
+ * genreated code, but leaves enough breadcrumbs to keep gdb happy).
+ */
+
+__asm__(
+".text\n" /* ENTRY(_start) */
+".p2align 4,0x90\n"
+".global _start\n"
+".type _start, @function\n"
+"_start:\n"
+".cfi_startproc\n"
+" xor %rbp, %rbp\n" /* Clear out the stack frame pointer */
+" mov %rsp, %rdi\n" /* Pass pointer to current stack with argc, argv and envp on it */
+" xor %rsi, %rsi\n" /* No dynamic pointer for us, to keep it simple */
+" andq $-16, %rsp\n" /* Align stack to 16-byte boundary */
+" call _start_c\n" /* Our MI code takes it from here and won't return */
+/* NORETURN */
+".size _start, . - _start\n" /* END(_start) */
+".cfi_endproc"
+);
diff --git a/stand/kboot/arch/amd64/stat_arch.h b/stand/kboot/arch/amd64/stat_arch.h
new file mode 100644
index 000000000000..81f3738f3ea6
--- /dev/null
+++ b/stand/kboot/arch/amd64/stat_arch.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2005-2020 Rich Felker, et al.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Note: From the musl project
+ */
+
+struct host_kstat {
+ host_dev_t st_dev;
+ host_ino_t st_ino;
+ host_nlink_t st_nlink;
+
+ host_mode_t st_mode;
+ host_uid_t st_uid;
+ host_gid_t st_gid;
+ unsigned int __pad0;
+ host_dev_t st_rdev;
+ host_off_t st_size;
+ host_blksize_t st_blksize;
+ host_blkcnt_t st_blocks;
+
+ long st_atime_sec;
+ long st_atime_nsec;
+ long st_mtime_sec;
+ long st_mtime_nsec;
+ long st_ctime_sec;
+ long st_ctime_nsec;
+ long __pad_for_future[3];
+};
+
diff --git a/stand/kboot/arch/amd64/syscall_nr.h b/stand/kboot/arch/amd64/syscall_nr.h
index 193368364bf3..2cf26d7ca4dc 100644
--- a/stand/kboot/arch/amd64/syscall_nr.h
+++ b/stand/kboot/arch/amd64/syscall_nr.h
@@ -1,15 +1,22 @@
-#define SYS_read 0
-#define SYS_write 1
-#define SYS_open 2
#define SYS_close 3
+#define SYS_dup 32
+#define SYS_exit 60
+#define SYS_getdents64 217
+#define SYS_getpid 39
#define SYS_gettimeofday 96
-#define SYS_reboot 169
+#define SYS_ioctl 16
+#define SYS_kexec_load 246
+#define SYS_lseek 8
+#define SYS_mkdirat 258
#define SYS_mmap 9
+#define SYS_mount 165
+#define SYS_munmap 11
+#define SYS_newfstat 5
+#define SYS_newfstatat 262
+#define SYS_openat 257
+#define SYS_pselect6 270
+#define SYS_read 0
+#define SYS_reboot 169
+#define SYS_symlinkat 266
#define SYS_uname 63
-#define SYS_lseek 8
-#define SYS_getdents 78
-#define SYS_select 23
-#define __NR_kexec_load 246
-
-#define KEXEC_ARCH_X86_64 62
-#define KEXEC_ARCH KEXEC_ARCH_X86_64
+#define SYS_write 1
diff --git a/stand/kboot/arch/amd64/termios_arch.h b/stand/kboot/arch/amd64/termios_arch.h
new file mode 100644
index 000000000000..0d5ae3718498
--- /dev/null
+++ b/stand/kboot/arch/amd64/termios_arch.h
@@ -0,0 +1 @@
+#include "termios_gen.h"
diff --git a/stand/kboot/arch/powerpc64/Makefile.inc b/stand/kboot/arch/powerpc64/Makefile.inc
index 3c2fb6e18a16..b62a12506969 100644
--- a/stand/kboot/arch/powerpc64/Makefile.inc
+++ b/stand/kboot/arch/powerpc64/Makefile.inc
@@ -1,14 +1,8 @@
CFLAGS+= -mcpu=powerpc64
-SRCS+= conf.c ppc64_elf_freebsd.c host_syscall.S kerneltramp.S
+SRCS+= ppc64_elf_freebsd.c host_syscall.S kerneltramp.S
SRCS+= ucmpdi2.c
-# load address. set in linker script
-RELOC?= 0x0
-CFLAGS+= -DRELOC=${RELOC}
-
LDFLAGS= -nostdlib -static -T ${.CURDIR}/arch/${MACHINE_ARCH}/ldscript.powerpc
MK_PIE= no
-# Maybe bogus?
-CFLAGS+= -DAIM
diff --git a/stand/kboot/arch/powerpc64/conf.c b/stand/kboot/arch/powerpc64/conf.c
deleted file mode 100644
index 9862611c68d8..000000000000
--- a/stand/kboot/arch/powerpc64/conf.c
+++ /dev/null
@@ -1,118 +0,0 @@
-/*-
- * Copyright (C) 1999 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 <stand.h>
-#include "bootstrap.h"
-
-#if defined(LOADER_NET_SUPPORT)
-#include "dev_net.h"
-#endif
-
-extern struct devsw hostdisk;
-
-/*
- * We could use linker sets for some or all of these, but
- * then we would have to control what ended up linked into
- * the bootstrap. So it's easier to conditionalise things
- * here.
- *
- * XXX rename these arrays to be consistent and less namespace-hostile
- */
-
-/* Exported for libsa */
-struct devsw *devsw[] = {
-#if defined(LOADER_DISK_SUPPORT) || defined(LOADER_CD9660_SUPPORT)
- &hostdisk,
-#endif
-#if defined(LOADER_NET_SUPPORT)
- &netdev,
-#endif
- NULL
-};
-
-struct fs_ops *file_system[] = {
-#if defined(LOADER_UFS_SUPPORT)
- &ufs_fsops,
-#endif
-#if defined(LOADER_CD9660_SUPPORT)
- &cd9660_fsops,
-#endif
-#if defined(LOADER_EXT2FS_SUPPORT)
- &ext2fs_fsops,
-#endif
-#if defined(LOADER_NFS_SUPPORT)
- &nfs_fsops,
-#endif
-#if defined(LOADER_TFTP_SUPPORT)
- &tftp_fsops,
-#endif
-#if defined(LOADER_GZIP_SUPPORT)
- &gzipfs_fsops,
-#endif
-#if defined(LOADER_BZIP2_SUPPORT)
- &bzipfs_fsops,
-#endif
- &dosfs_fsops,
- NULL
-};
-
-extern struct netif_driver kbootnet;
-
-struct netif_driver *netif_drivers[] = {
-#if 0 /* XXX */
-#if defined(LOADER_NET_SUPPORT)
- &kbootnet,
-#endif
-#endif
- NULL,
-};
-
-/* Exported for PowerPC only */
-/*
- * Sort formats so that those that can detect based on arguments
- * rather than reading the file go first.
- */
-
-extern struct file_format ppc_elf64;
-
-struct file_format *file_formats[] = {
- &ppc_elf64,
- NULL
-};
-
-/*
- * Consoles
- */
-extern struct console hostconsole;
-
-struct console *consoles[] = {
- &hostconsole,
- NULL
-};
-
diff --git a/stand/kboot/arch/powerpc64/ppc64_elf_freebsd.c b/stand/kboot/arch/powerpc64/ppc64_elf_freebsd.c
index adbdc7fca915..5851d71fdc13 100644
--- a/stand/kboot/arch/powerpc64/ppc64_elf_freebsd.c
+++ b/stand/kboot/arch/powerpc64/ppc64_elf_freebsd.c
@@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$");
#include <stand.h>
#include "bootstrap.h"
+#include "syscall_nr.h"
#include "host_syscall.h"
extern char end[];
@@ -152,12 +153,12 @@ ppc64_elf_exec(struct preloaded_file *fp)
panic("architecture did not provide kexec segment mapping");
archsw.arch_kexec_kseg_get(&nseg, &kseg);
- error = kexec_load(trampolinebase, nseg, (uintptr_t)kseg);
+ error = host_kexec_load(trampolinebase, nseg, kseg, HOST_KEXEC_ARCH_PPC64);
if (error != 0)
panic("kexec_load returned error: %d", error);
- error = host_reboot(0xfee1dead, 672274793,
- 0x45584543 /* LINUX_REBOOT_CMD_KEXEC */, (uintptr_t)NULL);
+ error = host_reboot(HOST_REBOOT_MAGIC1, HOST_REBOOT_MAGIC2, HOST_REBOOT_CMD_KEXEC,
+ (uintptr_t)NULL);
if (error != 0)
panic("reboot returned error: %d", error);
@@ -169,3 +170,13 @@ struct file_format ppc_elf64 =
ppc64_elf_loadfile,
ppc64_elf_exec
};
+
+/*
+ * Sort formats so that those that can detect based on arguments rather than
+ * reading the file first.
+ */
+
+struct file_format *file_formats[] = {
+ &ppc_elf64,
+ NULL
+};
diff --git a/stand/kboot/arch/powerpc64/start_arch.h b/stand/kboot/arch/powerpc64/start_arch.h
new file mode 100644
index 000000000000..498de29ad0fe
--- /dev/null
+++ b/stand/kboot/arch/powerpc64/start_arch.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2022 Netflix, Inc
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+/*
+ * Due to the PowerPC ABI, We can call main directly from here, so do so.
+ *
+ * Note: there may be some static initializers that aren't called, but we don't
+ * worry about that elsewhere. This is a stripped down environment.
+ *
+ * I think we could also do something like
+ *
+ * mflr r0
+ * stw r0,4(r1)
+ * stwu r1,-16(r1)
+ * b _start_c
+ *
+ * But my powerpc assembler fu is quite lacking...
+ */
+
+#define __unused __attribute__((__unused__))
+
+void
+_start(int argc, const char **argv, char **env, void *obj __unused,
+ void (*cleanup)(void) __unused)
+{
+ main(argc, argv, env);
+}
diff --git a/stand/kboot/arch/powerpc64/stat_arch.h b/stand/kboot/arch/powerpc64/stat_arch.h
new file mode 100644
index 000000000000..be5584951afb
--- /dev/null
+++ b/stand/kboot/arch/powerpc64/stat_arch.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2005-2020 Rich Felker, et al.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Note: From the musl project
+ */
+
+struct host_kstat {
+ host_dev_t st_dev;
+ host_ino_t st_ino;
+ host_nlink_t st_nlink;
+ host_mode_t st_mode;
+ host_uid_t st_uid;
+ host_gid_t st_gid;
+ host_dev_t st_rdev;
+ host_off_t st_size;
+ host_blksize_t st_blksize;
+ host_blkcnt_t st_blocks;
+ long st_atime_sec;
+ long st_atime_nsec;
+ long st_mtime_sec;
+ long st_mtime_nsec;
+ long st_ctime_sec;
+ long st_ctime_nsec;
+ long __pad_for_future[3];
+};
diff --git a/stand/kboot/arch/powerpc64/syscall_nr.h b/stand/kboot/arch/powerpc64/syscall_nr.h
index 2854124153a2..71f2452c9124 100644
--- a/stand/kboot/arch/powerpc64/syscall_nr.h
+++ b/stand/kboot/arch/powerpc64/syscall_nr.h
@@ -1,15 +1,23 @@
-#define SYS_read 3
-#define SYS_write 4
-#define SYS_open 5
#define SYS_close 6
+#define SYS_dup 41
+#define SYS_exit 1
+#define SYS_fstat 108
+#define SYS_getdents64 202
+#define SYS_getpid 20
#define SYS_gettimeofday 78
-#define SYS_reboot 88
+#define SYS_ioctl 54
+#define SYS_kexec_load 268
+#define SYS_llseek 140
+#define SYS_mkdirat 287
#define SYS_mmap 90
+#define SYS_mount 21
+#define SYS_munmap 91
+#define SYS_newfstat SYS_fstat
+#define SYS_newfstatat 291
+#define SYS_openat 286
+#define SYS_pselect6 280
+#define SYS_read 3
+#define SYS_reboot 88
+#define SYS_symlinkat 295
#define SYS_uname 120
-#define SYS_llseek 140
-#define SYS_getdents 141
-#define SYS_select 142
-#define __NR_kexec_load 268
-
-#define KEXEC_ARCH_PPC64 21
-#define KEXEC_ARCH KEXEC_ARCH_PPC64
+#define SYS_write 4
diff --git a/stand/kboot/arch/powerpc64/termios_arch.h b/stand/kboot/arch/powerpc64/termios_arch.h
new file mode 100644
index 000000000000..62b801ff16da
--- /dev/null
+++ b/stand/kboot/arch/powerpc64/termios_arch.h
@@ -0,0 +1,184 @@
+#undef HOST_NCCS
+#define HOST_NCCS 19
+struct host_termios {
+ host_tcflag_t c_iflag;
+ host_tcflag_t c_oflag;
+ host_tcflag_t c_cflag;
+ host_tcflag_t c_lflag;
+ host_cc_t c_cc[HOST_NCCS];
+ host_cc_t c_line;
+ host_speed_t __c_ispeed;
+ host_speed_t __c_ospeed;
+};
+
+#define HOST_VINTR 0
+#define HOST_VQUIT 1
+#define HOST_VERASE 2
+#define HOST_VKILL 3
+#define HOST_VEOF 4
+#define HOST_VMIN 5
+#define HOST_VEOL 6
+#define HOST_VTIME 7
+#define HOST_VEOL2 8
+#define HOST_VSWTC 9
+#define HOST_VWERASE 10
+#define HOST_VREPRINT 11
+#define HOST_VSUSP 12
+#define HOST_VSTART 13
+#define HOST_VSTOP 14
+#define HOST_VLNEXT 15
+#define HOST_VDISCARD 16
+
+#define HOST_IGNBRK 0000001
+#define HOST_BRKINT 0000002
+#define HOST_IGNPAR 0000004
+#define HOST_PARMRK 0000010
+#define HOST_INPCK 0000020
+#define HOST_ISTRIP 0000040
+#define HOST_INLCR 0000100
+#define HOST_IGNCR 0000200
+#define HOST_ICRNL 0000400
+#define HOST_IXON 0001000
+#define HOST_IXOFF 0002000
+#define HOST_IXANY 0004000
+#define HOST_IUCLC 0010000
+#define HOST_IMAXBEL 0020000
+#define HOST_IUTF8 0040000
+
+#define HOST_OPOST 0000001
+#define HOST_ONLCR 0000002
+#define HOST_OLCUC 0000004
+#define HOST_OCRNL 0000010
+#define HOST_ONOCR 0000020
+#define HOST_ONLRET 0000040
+#define HOST_OFILL 0000100
+#define HOST_OFDEL 0000200
+#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) || defined(_XOPEN_SOURCE)
+#define HOST_NLDLY 0001400
+#define HOST_NL0 0000000
+#define HOST_NL1 0000400
+#define HOST_NL2 0001000
+#define HOST_NL3 0001400
+#define HOST_TABDLY 0006000
+#define HOST_TAB0 0000000
+#define HOST_TAB1 0002000
+#define HOST_TAB2 0004000
+#define HOST_TAB3 0006000
+#define HOST_CRDLY 0030000
+#define HOST_CR0 0000000
+#define HOST_CR1 0010000
+#define HOST_CR2 0020000
+#define HOST_CR3 0030000
+#define HOST_FFDLY 0040000
+#define HOST_FF0 0000000
+#define HOST_FF1 0040000
+#define HOST_BSDLY 0100000
+#define HOST_BS0 0000000
+#define HOST_BS1 0100000
+#endif
+
+#define HOST_VTDLY 0200000
+#define HOST_VT0 0000000
+#define HOST_VT1 0200000
+
+#define HOST_B0 0000000
+#define HOST_B50 0000001
+#define HOST_B75 0000002
+#define HOST_B110 0000003
+#define HOST_B134 0000004
+#define HOST_B150 0000005
+#define HOST_B200 0000006
+#define HOST_B300 0000007
+#define HOST_B600 0000010
+#define HOST_B1200 0000011
+#define HOST_B1800 0000012
+#define HOST_B2400 0000013
+#define HOST_B4800 0000014
+#define HOST_B9600 0000015
+#define HOST_B19200 0000016
+#define HOST_B38400 0000017
+
+#define HOST_B57600 00020
+#define HOST_B115200 00021
+#define HOST_B230400 00022
+#define HOST_B460800 00023
+#define HOST_B500000 00024
+#define HOST_B576000 00025
+#define HOST_B921600 00026
+#define HOST_B1000000 00027
+#define HOST_B1152000 00030
+#define HOST_B1500000 00031
+#define HOST_B2000000 00032
+#define HOST_B2500000 00033
+#define HOST_B3000000 00034
+#define HOST_B3500000 00035
+#define HOST_B4000000 00036
+
+#define HOST_CSIZE 00001400
+#define HOST_CS5 00000000
+#define HOST_CS6 00000400
+#define HOST_CS7 00001000
+#define HOST_CS8 00001400
+#define HOST_CSTOPB 00002000
+#define HOST_CREAD 00004000
+#define HOST_PARENB 00010000
+#define HOST_PARODD 00020000
+#define HOST_HUPCL 00040000
+#define HOST_CLOCAL 00100000
+
+#define HOST_ECHOE 0x00000002
+#define HOST_ECHOK 0x00000004
+#define HOST_ECHO 0x00000008
+#define HOST_ECHONL 0x00000010
+#define HOST_ISIG 0x00000080
+#define HOST_ICANON 0x00000100
+#define HOST_IEXTEN 0x00000400
+#define HOST_TOSTOP 0x00400000
+#define HOST_NOFLSH 0x80000000
+
+#define HOST_TCOOFF 0
+#define HOST_TCOON 1
+#define HOST_TCIOFF 2
+#define HOST_TCION 3
+
+#define HOST_TCIFLUSH 0
+#define HOST_TCOFLUSH 1
+#define HOST_TCIOFLUSH 2
+
+#define HOST_TCSANOW 0
+#define HOST_TCSADRAIN 1
+#define HOST_TCSAFLUSH 2
+
+#define HOST_EXTA 0000016
+#define HOST_EXTB 0000017
+#define HOST_CBAUD 00377
+#define HOST_CBAUDEX 0000020
+#define HOST_CIBAUD 077600000
+#define HOST_CMSPAR 010000000000
+#define HOST_CRTSCTS 020000000000
+
+#define HOST_XCASE 0x00004000
+#define HOST_ECHOCTL 0x00000040
+#define HOST_ECHOPRT 0x00000020
+#define HOST_ECHOKE 0x00000001
+#define HOST_FLUSHO 0x00800000
+#define HOST_PENDIN 0x20000000
+#define HOST_EXTPROC 0x10000000
+
+#define HOST_XTABS 00006000
+#define HOST_TIOCSER_TEMT 1
+
+#define _IOC(a,b,c,d) ( ((a)<<29) | ((b)<<8) | (c) | ((d)<<16) )
+#define _IOC_NONE 1U
+#define _IOC_WRITE 4U
+#define _IOC_READ 2U
+
+#define _IO(a,b) _IOC(_IOC_NONE,(a),(b),0)
+#define _IOW(a,b,c) _IOC(_IOC_WRITE,(a),(b),sizeof(c))
+#define _IOR(a,b,c) _IOC(_IOC_READ,(a),(b),sizeof(c))
+#define _IOWR(a,b,c) _IOC(_IOC_READ|_IOC_WRITE,(a),(b),sizeof(c))
+
+#define HOST_TCGETS _IOR('t', 19, char[44])
+#define HOST_TCSETS _IOW('t', 20, char[44])
+#define HOST_TCSETSW _IOW('t', 21, char[44])
+#define HOST_TCSETSF _IOW('t', 22, char[44])
diff --git a/stand/kboot/arch/amd64/conf.c b/stand/kboot/conf.c
index b840d008a347..b840d008a347 100644
--- a/stand/kboot/arch/amd64/conf.c
+++ b/stand/kboot/conf.c
diff --git a/stand/kboot/crt1.c b/stand/kboot/crt1.c
new file mode 100644
index 000000000000..2fbe00262da7
--- /dev/null
+++ b/stand/kboot/crt1.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2022, Netflix, Inc.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+/*
+ * MI part of the C startup code. We take a long * pointer (we assume long is
+ * the same size as a pointer, as the Linux world is wont to do). We get a
+ * pointer to the stack with the main args on it. We don't bother decoding the
+ * aux vector, but may need to do so in the future.
+ *
+ * The long *p points to:
+ *
+ * +--------------------+
+ * | argc | Small address
+ * +--------------------+
+ * | argv[0] | argv
+ * +--------------------+
+ * | argv[1] |
+ * +--------------------+
+ * ...
+ * +--------------------+
+ * | NULL | &argv[argc]
+ * +--------------------+
+ * | envp[0] | envp
+ * +--------------------+
+ * | envp[1] |
+ * +--------------------+
+ * ...
+ * +--------------------+
+ * | NULL |
+ * +--------------------+
+ * | aux type | AT_xxxx
+ * +--------------------+
+ * | aux value |
+ * +--------------------+
+ * | aux type | AT_xxxx
+ * +--------------------+
+ * | aux value |
+ * +--------------------+
+ * | aux type | AT_xxxx
+ * +--------------------+
+ * | aux value |
+ * +--------------------+
+ *...
+ * +--------------------+
+ * | NULL |
+ * +--------------------+
+ *
+ * The AUX vector contains additional information for the process to know from
+ * the kernel (not parsed currently). AT_xxxx constants are small (< 50).
+ */
+
+extern void _start_c(long *);
+extern int main(int, const char **, char **);
+
+#include "start_arch.h"
+
+void
+_start_c(long *p)
+{
+ int argc;
+ const char **argv;
+ char **envp;
+
+ argc = p[0];
+ argv = (const char **)(p + 1);
+ envp = (char **)argv + argc + 1;
+
+ /* Note: we don't ensure that fd 0, 1, and 2 are sane at this level */
+ /* Also note: we expect main to exit, not return off the end */
+ main(argc, argv, envp);
+}
diff --git a/stand/kboot/host_syscall.h b/stand/kboot/host_syscall.h
index f6f22a736d53..0029004f675a 100644
--- a/stand/kboot/host_syscall.h
+++ b/stand/kboot/host_syscall.h
@@ -32,13 +32,47 @@
long host_syscall(int number, ...);
-ssize_t host_read(int fd, void *buf, size_t nbyte);
-ssize_t host_write(int fd, const void *buf, size_t nbyte);
-int host_open(const char *path, int flags, int mode);
-ssize_t host_llseek(int fd, int32_t offset_high, int32_t offset_lo, uint64_t *result, int whence);
-int host_close(int fd);
-void *host_mmap(void *addr, size_t len, int prot, int flags, int fd, off_t off);
-#define host_getmem(size) host_mmap(0, size, 3 /* RW */, 0x22 /* ANON */, -1, 0);
+/*
+ * Sizes taken from musl's include/alltypes.h.in and expanded for LP64 hosts
+ */
+typedef uint64_t host_dev_t;
+typedef uint64_t host_ino_t;
+typedef int64_t host_nlink_t;
+typedef unsigned int host_mode_t;
+typedef unsigned int host_uid_t;
+typedef unsigned int host_gid_t;
+typedef int64_t host_off_t;
+typedef long host_blksize_t;
+typedef int64_t host_blkcnt_t;
+
+#include "stat_arch.h"
+
+/*
+ * Constants for open, fcntl, etc
+ *
+ * Note: Some of these are arch dependent on Linux, but are the same for
+ * powerpc, x86, arm*, and riscv. We should be futureproof, though, since these
+ * are the 'generic' values and only older architectures (no longer supported by
+ * FreeBSD) vary.
+ *
+ * These are from tools/include/uapi/asm-generic/fcntl.h and use the octal
+ * notation. Beware, hex is used in other places creating potential confsion.
+ */
+#define HOST_O_RDONLY 0
+#define HOST_O_WRONLY 1
+#define HOST_O_RDWR 2
+#define HOST_O_CREAT 00100
+#define HOST_O_EXCL 00200
+#define HOST_O_NOCTTY 00400
+#define HOST_O_TRUNC 01000
+#define HOST_O_APPEND 02000
+#define HOST_O_NONBLOCK 04000
+
+#define HOST_AT_FDCWD -100 /* Relative to current directory */
+
+/*
+ * Data types
+ */
struct old_utsname {
char sysname[65];
char nodename[65];
@@ -46,16 +80,109 @@ struct old_utsname {
char version[65];
char machine[65];
};
-int host_uname(struct old_utsname *);
+
struct host_timeval {
time_t tv_sec;
long tv_usec;
};
+
+/*
+ * Must match Linux's values see linux/tools/include/uapi/asm-generic/mman-common.h
+ * and linux/tools/include/linux/mman.h
+ *
+ * And pre-pend HOST_ here.
+ */
+#define HOST_PROT_READ 0x1
+#define HOST_PROT_WRITE 0x2
+#define HOST_PROT_EXEC 0x4
+
+#define HOST_MAP_SHARED 0x01
+#define HOST_MAP_PRIVATE 0x02
+#define HOST_MAP_FIXED 0x10
+#define HOST_MAP_ANONYMOUS 0x20
+
+/* Mount flags from uapi */
+#define MS_RELATIME (1 << 21)
+
+#define HOST_REBOOT_MAGIC1 0xfee1dead
+#define HOST_REBOOT_MAGIC2 672274793
+#define HOST_REBOOT_CMD_KEXEC 0x45584543
+
+/*
+ * Values from linux/tools/include/uapi/linux/kexec.h
+ */
+
+/*
+ * Values match ELF architecture types.
+ */
+#define HOST_KEXEC_ARCH_X86_64 (62 << 16)
+#define HOST_KEXEC_ARCH_PPC64 (21 << 16)
+#define HOST_KEXEC_ARCH_ARM (40 << 16)
+#define HOST_KEXEC_ARCH_AARCH64 (183 << 16)
+#define HOST_KEXEC_ARCH_RISCV (243 << 16)
+
+/* Arbitrary cap on segments */
+#define HOST_KEXEC_SEGMENT_MAX 16
+
+struct host_kexec_segment {
+ void *buf;
+ int bufsz;
+ void *mem;
+ int memsz;
+};
+
+struct host_dirent64 {
+ uint64_t d_ino; /* 64-bit inode number */
+ int64_t d_off; /* 64-bit offset to next structure */
+ unsigned short d_reclen; /* Size of this dirent */
+ unsigned char d_type; /* File type */
+ char d_name[]; /* Filename (null-terminated) */
+};
+
+/* d_type values */
+#define HOST_DT_UNKNOWN 0
+#define HOST_DT_FIFO 1
+#define HOST_DT_CHR 2
+#define HOST_DT_DIR 4
+#define HOST_DT_BLK 6
+#define HOST_DT_REG 8
+#define HOST_DT_LNK 10
+#define HOST_DT_SOCK 12
+#define HOST_DT_WHT 14
+
+/*
+ * System Calls
+ */
+int host_close(int fd);
+int host_dup(int fd);
+int host_exit(int code);
+int host_fstat(int fd, struct host_kstat *sb);
+int host_getdents64(int fd, void *dirp, int count);
+int host_getpid(void);
int host_gettimeofday(struct host_timeval *a, void *b);
+int host_ioctl(int fd, unsigned long request, unsigned long arg);
+int host_kexec_load(unsigned long entry, unsigned long nsegs, struct host_kexec_segment *segs, unsigned long flags);
+ssize_t host_llseek(int fd, int32_t offset_high, int32_t offset_lo, uint64_t *result, int whence);
+int host_mkdir(const char *, host_mode_t);
+void *host_mmap(void *addr, size_t len, int prot, int flags, int fd, off_t off);
+int host_mount(const char *src, const char *target, const char *type,
+ unsigned long flags, void *data);
+int host_munmap(void *addr, size_t len);
+int host_open(const char *path, int flags, int mode);
+ssize_t host_read(int fd, void *buf, size_t nbyte);
+int host_reboot(int, int, int, uintptr_t);
int host_select(int nfds, long *readfds, long *writefds, long *exceptfds,
struct host_timeval *timeout);
-int kexec_load(uint32_t start, int nsegs, uint32_t segs);
-int host_reboot(int, int, int, uintptr_t);
-int host_getdents(int fd, void *dirp, int count);
+int host_stat(const char *path, struct host_kstat *sb);
+int host_symlink(const char *path1, const char *path2);
+int host_uname(struct old_utsname *);
+ssize_t host_write(int fd, const void *buf, size_t nbyte);
+
+/*
+ * Wrappers / one-liners
+ */
+#define host_getmem(size) \
+ host_mmap(0, size, HOST_PROT_READ | HOST_PROT_WRITE, \
+ HOST_MAP_PRIVATE | HOST_MAP_ANONYMOUS, -1, 0);
#endif
diff --git a/stand/kboot/host_syscalls.c b/stand/kboot/host_syscalls.c
index 53be0c166374..1ffa04948fdf 100644
--- a/stand/kboot/host_syscalls.c
+++ b/stand/kboot/host_syscalls.c
@@ -2,24 +2,68 @@
#include "syscall_nr.h"
#include <stand.h>
-ssize_t
-host_read(int fd, void *buf, size_t nbyte)
+/*
+ * Various trivial wrappers for Linux system calls. Please keep sorted
+ * alphabetically.
+ */
+
+int
+host_close(int fd)
{
- return host_syscall(SYS_read, fd, (uintptr_t)buf, nbyte);
- /* XXX original overrode errors */
+ return host_syscall(SYS_close, fd);
}
-ssize_t
-host_write(int fd, const void *buf, size_t nbyte)
+int
+host_dup(int fd)
{
- return host_syscall(SYS_write, fd, (uintptr_t)buf, nbyte);
+ return host_syscall(SYS_dup, fd);
}
-
+
int
-host_open(const char *path, int flags, int mode)
+host_exit(int code)
{
- return host_syscall(SYS_open, (uintptr_t)path, flags, mode);
- /* XXX original overrode errors */
+ return host_syscall(SYS_exit, code);
+}
+
+/* Same system call with different names on different Linux architectures due to history */
+int
+host_fstat(int fd, struct host_kstat *sb)
+{
+#ifdef SYS_newfstat
+ return host_syscall(SYS_newfstat, fd, (uintptr_t)sb);
+#else
+ return host_syscall(SYS_fstat, fd, (uintptr_t)sb);
+#endif
+}
+
+int
+host_getdents64(int fd, void *dirp, int count)
+{
+ return host_syscall(SYS_getdents64, fd, (uintptr_t)dirp, count);
+}
+
+int
+host_getpid(void)
+{
+ return host_syscall(SYS_getpid);
+}
+
+int
+host_gettimeofday(struct host_timeval *a, void *b)
+{
+ return host_syscall(SYS_gettimeofday, (uintptr_t)a, (uintptr_t)b);
+}
+
+int
+host_ioctl(int fd, unsigned long request, unsigned long arg)
+{
+ return host_syscall(SYS_ioctl, fd, request, arg);
+}
+
+int
+host_kexec_load(unsigned long entry, unsigned long nsegs, struct host_kexec_segment *segs, unsigned long flags)
+{
+ return host_syscall(SYS_kexec_load, entry, nsegs, segs, flags);
}
ssize_t
@@ -37,9 +81,9 @@ host_llseek(int fd, int32_t offset_high, int32_t offset_lo, uint64_t *result, in
}
int
-host_close(int fd)
+host_mkdir(const char *path, host_mode_t mode)
{
- return host_syscall(SYS_close, fd);
+ return host_syscall(SYS_mkdirat, HOST_AT_FDCWD, (uintptr_t)path, mode);
}
void *
@@ -49,38 +93,73 @@ host_mmap(void *addr, size_t len, int prot, int flags, int fd, off_t off)
}
int
-host_uname(struct old_utsname *uts)
+host_mount(const char *src, const char *target, const char *type, unsigned long flags,
+ void *data)
{
- return host_syscall(SYS_uname, (uintptr_t)uts);
+ return host_syscall(SYS_mount, src, target, type, flags, data);
}
int
-host_gettimeofday(struct host_timeval *a, void *b)
+host_munmap(void *addr, size_t len)
{
- return host_syscall(SYS_gettimeofday, (uintptr_t)a, (uintptr_t)b);
+ return host_syscall(SYS_munmap, (uintptr_t)addr, len);
+}
+
+int
+host_open(const char *path, int flags, int mode)
+{
+ return host_syscall(SYS_openat, HOST_AT_FDCWD, (uintptr_t)path, flags, mode);
+ /* XXX original overrode errors */
+}
+
+ssize_t
+host_read(int fd, void *buf, size_t nbyte)
+{
+ return host_syscall(SYS_read, fd, (uintptr_t)buf, nbyte);
+ /* XXX original overrode errors */
+}
+
+int
+host_reboot(int magic1, int magic2, int cmd, uintptr_t arg)
+{
+ return host_syscall(SYS_reboot, magic1, magic2, cmd, arg);
}
int
host_select(int nfds, long *readfds, long *writefds, long *exceptfds,
struct host_timeval *timeout)
{
- return host_syscall(SYS_select, nfds, (uintptr_t)readfds, (uintptr_t)writefds, (uintptr_t)exceptfds, (uintptr_t)timeout, 0);
+ struct timespec ts = { .tv_sec = timeout->tv_sec, .tv_nsec = timeout->tv_usec * 1000 };
+
+ /*
+ * Note, final arg is a sigset_argpack since most arch can only have 6
+ * syscall args. Since we're not masking signals, though, we can just
+ * pass a NULL.
+ */
+ return host_syscall(SYS_pselect6, nfds, (uintptr_t)readfds, (uintptr_t)writefds,
+ (uintptr_t)exceptfds, (uintptr_t)&ts, (uintptr_t)NULL);
}
int
-kexec_load(uint32_t start, int nsegs, uint32_t segs)
+host_stat(const char *path, struct host_kstat *sb)
{
- return host_syscall(__NR_kexec_load, start, nsegs, segs, KEXEC_ARCH << 16);
+ return host_syscall(SYS_newfstatat, HOST_AT_FDCWD, (uintptr_t)path, (uintptr_t)sb, 0);
}
int
-host_reboot(int magic1, int magic2, int cmd, uintptr_t arg)
+host_symlink(const char *path1, const char *path2)
{
- return host_syscall(SYS_reboot, magic1, magic2, cmd, arg);
+ return host_syscall(SYS_symlinkat, HOST_AT_FDCWD, path1, path2);
}
int
-host_getdents(int fd, void *dirp, int count)
+host_uname(struct old_utsname *uts)
{
- return host_syscall(SYS_getdents, fd, (uintptr_t)dirp, count);
+ return host_syscall(SYS_uname, (uintptr_t)uts);
+}
+
+ssize_t
+host_write(int fd, const void *buf, size_t nbyte)
+{
+ return host_syscall(SYS_write, fd, (uintptr_t)buf, nbyte);
}
diff --git a/stand/kboot/hostcons.c b/stand/kboot/hostcons.c
index 31dceb019973..80d4a1c4319b 100644
--- a/stand/kboot/hostcons.c
+++ b/stand/kboot/hostcons.c
@@ -29,6 +29,7 @@ __FBSDID("$FreeBSD$");
#include <sys/types.h>
#include "bootstrap.h"
#include "host_syscall.h"
+#include "termios.h"
static void hostcons_probe(struct console *cp);
static int hostcons_init(int arg);
@@ -47,6 +48,8 @@ struct console hostconsole = {
hostcons_poll,
};
+static struct host_termios old_settings;
+
static void
hostcons_probe(struct console *cp)
{
@@ -57,9 +60,12 @@ hostcons_probe(struct console *cp)
static int
hostcons_init(int arg)
{
+ struct host_termios new_settings;
- /* XXX: set nonblocking */
- /* tcsetattr(~(ICANON | ECHO)) */
+ host_tcgetattr(0, &old_settings);
+ new_settings = old_settings;
+ host_cfmakeraw(&new_settings);
+ host_tcsetattr(0, HOST_TCSANOW, &new_settings);
return (0);
}
@@ -94,4 +100,3 @@ hostcons_poll()
ret = host_select(32, &fds, NULL, NULL, &tv);
return (ret > 0);
}
-
diff --git a/stand/kboot/hostdisk.c b/stand/kboot/hostdisk.c
index 3c36f2d3bce6..00f133274f10 100644
--- a/stand/kboot/hostdisk.c
+++ b/stand/kboot/hostdisk.c
@@ -30,6 +30,7 @@ __FBSDID("$FreeBSD$");
#include <stdarg.h>
#include "bootstrap.h"
#include "host_syscall.h"
+#include "disk.h"
static int hostdisk_init(void);
static int hostdisk_strategy(void *devdata, int flag, daddr_t dblk,
@@ -40,14 +41,16 @@ static int hostdisk_ioctl(struct open_file *f, u_long cmd, void *data);
static int hostdisk_print(int verbose);
struct devsw hostdisk = {
- "/dev",
- DEVT_DISK,
- hostdisk_init,
- hostdisk_strategy,
- hostdisk_open,
- hostdisk_close,
- hostdisk_ioctl,
- hostdisk_print,
+ .dv_name = "/dev",
+ .dv_type = DEVT_DISK,
+ .dv_init = hostdisk_init,
+ .dv_strategy = hostdisk_strategy,
+ .dv_open = hostdisk_open,
+ .dv_close = hostdisk_close,
+ .dv_ioctl = hostdisk_ioctl,
+ .dv_print = hostdisk_print,
+ .dv_cleanup = nullsys,
+ .dv_fmtdev = disk_fmtdev,
};
static int
diff --git a/stand/kboot/init.c b/stand/kboot/init.c
new file mode 100644
index 000000000000..e707f65096d7
--- /dev/null
+++ b/stand/kboot/init.c
@@ -0,0 +1,129 @@
+/*-
+ * Copyright (c) 2022, Netflix, Inc.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+/*
+ * Mini-init(8) so we can run as init/pid 1 in a LinuxBoot environment.
+ */
+
+#include "stand.h"
+#include "host_syscall.h"
+#include "kboot.h"
+
+/*
+ * Create a 'standard' early boot environment. Cribbed from the things that
+ * sysvinit, u-root, and initramfs-tools do. This is a minimal environment
+ * for modern Linux systems, though the /tmp, /run and /var stuff can likely
+ * be done inside the initrd image itself (as can creating the mount points
+ * for /proc, /dev and /sys).
+ *
+ * Note: We ignore errors here. There's no stderr to report them to yet. These
+ * operations generally can't fail, but if they do, we may not have the ability
+ * to report them later.
+ */
+static void
+init_fs_env(void)
+{
+ /*
+ * Create directories for mandatory filesystems and mount them.
+ */
+ host_mkdir("/proc", 0555);
+ host_mount("proc", "/proc", "proc", MS_RELATIME, "");
+ host_mkdir("/sys", 0555);
+ host_mount("sysfs", "/sys", "sysfs", MS_RELATIME, "");
+ host_mkdir("/dev", 0755);
+ host_mount("devtmpfs", "/dev", "devtmpfs", MS_RELATIME,
+ "mode=0755,nr_inodes=0");
+
+ /*
+ * Create compat links: /dev/fd lives in /proc, and needs some help to
+ * get setup.
+ */
+ host_symlink("/proc/self/fd", "/dev/fd");
+ host_symlink("fd/0", "/dev/stdin");
+ host_symlink("fd/1", "/dev/stdout");
+ host_symlink("fd/2", "/dev/stderr");
+
+
+ /*
+ * Unsure if we need this, but create a sane /tmp just in case that's useful.
+ * and point /run over to it.
+ */
+ host_mkdir("/tmp", 01777);
+ host_mount("tmpfs", "/tmp", "tmpfs", MS_RELATIME, "size=10%,mode=1777");
+ host_symlink("/tmp", "/run");
+
+ /*
+ * Unsure the loader needs /var and /var/log, but they are easy to
+ * create.
+ */
+ host_mkdir("/var", 0555);
+ host_mkdir("/var/lock", 0555);
+ host_symlink("/tmp", "/var/tmp");
+}
+
+static void
+init_tty(void)
+{
+ int fd;
+
+ /*
+ * sysvinit asks the linux kernel to convert the CTRL-ALT-DEL to a SIGINT,
+ * but we skip that.
+ */
+
+ /*
+ * Setup /dev/console as stdin/out/err
+ */
+ host_close(0);
+ host_close(1);
+ host_close(2);
+ fd = host_open("/dev/console", HOST_O_RDWR | HOST_O_NOCTTY, 0);
+ host_dup(fd);
+ host_dup(fd);
+#if 0
+ /*
+ * I think we may need to put it in 'raw' mode, but maybe not. Linux
+ * sysvinit sets it into 'sane' mode with several tweaks. Not enabled at
+ * the moment since host console initialization seems sufficient.
+ */
+ struct host_termios tty;
+
+ host_cfmakeraw(&tty);
+ host_tcsetattr(fd, HOST_TCANOW, &tty);
+ host_tcflush(fd, HOST_TCIOFLUSH)
+#endif
+}
+
+static void
+init_sig(void)
+{
+ /*
+ * since we're running as init, we need to catch some signals
+ */
+
+ /*
+ * setup signals here
+ *
+ * sysvinit catches a lot of signals, but the boot loader needn't catch
+ * so many since we don't do as much as it does. If we need to, put the
+ * signal catching / ignoring code here. If we implement a 'shell'
+ * function to spawn a sub-shell, we'll likely need to do a lot more.
+ */
+}
+
+void
+do_init(void)
+{
+ /*
+ * Only pid 1 is init
+ */
+ if (host_getpid() != 1)
+ return;
+
+ init_fs_env();
+ init_tty();
+ init_sig();
+}
diff --git a/stand/kboot/kboot.h b/stand/kboot/kboot.h
new file mode 100644
index 000000000000..01de346234f3
--- /dev/null
+++ b/stand/kboot/kboot.h
@@ -0,0 +1,12 @@
+/*-
+ * Copyright (c) 2022, Netflix, Inc.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#ifndef KBOOT_H
+#define KBOOT_H
+
+void do_init(void);
+
+#endif /* KBOOT_H */
diff --git a/stand/kboot/kbootfdt.c b/stand/kboot/kbootfdt.c
index 14bc94326fe6..e4e8e7cfbf04 100644
--- a/stand/kboot/kbootfdt.c
+++ b/stand/kboot/kbootfdt.c
@@ -40,57 +40,49 @@ add_node_to_fdt(void *buffer, const char *path, int fdt_offset)
void *propbuf;
ssize_t proplen;
- struct host_dent {
- unsigned long d_fileno;
- unsigned long d_off;
- unsigned short d_reclen;
- char d_name[];
- /* uint8_t d_type; */
- };
char dents[2048];
- struct host_dent *dent;
+ struct host_dirent64 *dent;
int d_type;
fd = host_open(path, O_RDONLY, 0);
while (1) {
- dentsize = host_getdents(fd, dents, sizeof(dents));
- if (dentsize <= 0)
- break;
- for (dent = (struct host_dent *)dents;
- (char *)dent < dents + dentsize;
- dent = (struct host_dent *)((void *)dent + dent->d_reclen)) {
- sprintf(subpath, "%s/%s", path, dent->d_name);
- if (strcmp(dent->d_name, ".") == 0 ||
- strcmp(dent->d_name, "..") == 0)
- continue;
- d_type = *((char *)(dent) + dent->d_reclen - 1);
- if (d_type == 4 /* DT_DIR */) {
- child_offset = fdt_add_subnode(buffer, fdt_offset,
- dent->d_name);
- if (child_offset < 0) {
- printf("Error %d adding node %s/%s, skipping\n",
- child_offset, path, dent->d_name);
+ dentsize = host_getdents64(fd, dents, sizeof(dents));
+ if (dentsize <= 0)
+ break;
+ for (dent = (struct host_dirent64 *)dents;
+ (char *)dent < dents + dentsize;
+ dent = (struct host_dirent64 *)((void *)dent + dent->d_reclen)) {
+ sprintf(subpath, "%s/%s", path, dent->d_name);
+ if (strcmp(dent->d_name, ".") == 0 ||
+ strcmp(dent->d_name, "..") == 0)
continue;
+ d_type = dent->d_type;
+ if (d_type == 4 /* DT_DIR */) {
+ child_offset = fdt_add_subnode(buffer, fdt_offset,
+ dent->d_name);
+ if (child_offset < 0) {
+ printf("Error %d adding node %s/%s, skipping\n",
+ child_offset, path, dent->d_name);
+ continue;
+ }
+ add_node_to_fdt(buffer, subpath, child_offset);
+ } else {
+ propbuf = malloc(1024);
+ proplen = 0;
+ pfd = host_open(subpath, O_RDONLY, 0);
+ if (pfd > 0) {
+ proplen = host_read(pfd, propbuf, 1024);
+ host_close(pfd);
+ }
+ error = fdt_setprop(buffer, fdt_offset, dent->d_name,
+ propbuf, proplen);
+ free(propbuf);
+ if (error)
+ printf("Error %d adding property %s to "
+ "node %d\n", error, dent->d_name,
+ fdt_offset);
}
-
- add_node_to_fdt(buffer, subpath, child_offset);
- } else {
- propbuf = malloc(1024);
- proplen = 0;
- pfd = host_open(subpath, O_RDONLY, 0);
- if (pfd > 0) {
- proplen = host_read(pfd, propbuf, 1024);
- host_close(pfd);
- }
- error = fdt_setprop(buffer, fdt_offset, dent->d_name,
- propbuf, proplen);
- free(propbuf);
- if (error)
- printf("Error %d adding property %s to "
- "node %d\n", error, dent->d_name,
- fdt_offset);
}
- }
}
host_close(fd);
diff --git a/stand/kboot/main.c b/stand/kboot/main.c
index 9b99c859070b..be08528049e6 100644
--- a/stand/kboot/main.c
+++ b/stand/kboot/main.c
@@ -34,7 +34,7 @@ __FBSDID("$FreeBSD$");
#include <machine/cpufunc.h>
#include <bootstrap.h>
#include "host_syscall.h"
-
+#include "kboot.h"
struct arch_switch archsw;
extern void *_end;
@@ -212,11 +212,17 @@ kboot_get_kernel_machine_bits(void)
int
kboot_getdev(void **vdev, const char *devspec, const char **path)
{
- int i;
+ int i, rv;
const char *devpath, *filepath;
struct devsw *dv;
struct devdesc *desc;
+ if (devspec == NULL) {
+ rv = kboot_getdev(vdev, getenv("currdev"), NULL);
+ if (rv == 0 && path != NULL)
+ *path = devspec;
+ return (rv);
+ }
if (strchr(devspec, ':') != NULL) {
devpath = devspec;
filepath = strchr(devspec, ':') + 1;
@@ -255,8 +261,11 @@ main(int argc, const char **argv)
const size_t heapsize = 15*1024*1024;
const char *bootdev;
+ /* Give us a sane world if we're running as init */
+ do_init();
+
/*
- * Set the heap to one page after the end of the loader.
+ * Setup the heap 15MB should be plenty
*/
heapbase = host_getmem(heapsize);
setheap(heapbase, heapbase + heapsize);
@@ -297,7 +306,7 @@ main(int argc, const char **argv)
void
exit(int code)
{
- while (1); /* XXX: host_exit */
+ host_exit(code);
__unreachable();
}
@@ -334,22 +343,17 @@ time(time_t *tloc)
return (rv);
}
-struct kexec_segment {
- void *buf;
- int bufsz;
- void *mem;
- int memsz;
-};
-
-struct kexec_segment loaded_segments[128];
+struct host_kexec_segment loaded_segments[HOST_KEXEC_SEGMENT_MAX];
int nkexec_segments = 0;
static ssize_t
get_phys_buffer(vm_offset_t dest, const size_t len, void **buf)
{
int i = 0;
- const size_t segsize = 4*1024*1024;
+ const size_t segsize = 8*1024*1024;
+ if (nkexec_segments == HOST_KEXEC_SEGMENT_MAX)
+ panic("Tried to load too many kexec segments");
for (i = 0; i < nkexec_segments; i++) {
if (dest >= (vm_offset_t)loaded_segments[i].mem &&
dest < (vm_offset_t)loaded_segments[i].mem +
@@ -479,12 +483,6 @@ kboot_kseg_get(int *nseg, void **ptr)
*ptr = &loaded_segments[0];
}
-void
-_start(int argc, const char **argv, char **env)
-{
- main(argc, argv);
-}
-
/*
* Since proper fdt command handling function is defined in fdt_loader_cmd.c,
* and declaring it as extern is in contradiction with COMMAND_SET() macro
diff --git a/stand/kboot/termios.c b/stand/kboot/termios.c
new file mode 100644
index 000000000000..ec62170a44c9
--- /dev/null
+++ b/stand/kboot/termios.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2005-2020 Rich Felker, et al.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Note: From the musl project, stripped down and repackaged with HOST_/host_ prepended
+ */
+
+#include <sys/types.h>
+#include "termios.h"
+#include "host_syscall.h"
+
+int
+host_tcgetattr(int fd, struct host_termios *tio)
+{
+ if (host_ioctl(fd, HOST_TCGETS, (uintptr_t)tio))
+ return -1;
+ return 0;
+}
+
+int
+host_tcsetattr(int fd, int act, const struct host_termios *tio)
+{
+ if (act < 0 || act > 2) {
+// errno = EINVAL; /* XXX ?? */
+ return -1;
+ }
+ return host_ioctl(fd, HOST_TCSETS+act, (uintptr_t)tio);
+}
+
+void
+host_cfmakeraw(struct host_termios *t)
+{
+ t->c_iflag &= ~(HOST_IGNBRK | HOST_BRKINT | HOST_PARMRK | HOST_ISTRIP |
+ HOST_INLCR | HOST_IGNCR | HOST_ICRNL | HOST_IXON);
+ t->c_oflag &= ~HOST_OPOST;
+ t->c_lflag &= ~(HOST_ECHO | HOST_ECHONL | HOST_ICANON | HOST_ISIG |
+ HOST_IEXTEN);
+ t->c_cflag &= ~(HOST_CSIZE | HOST_PARENB);
+ t->c_cflag |= HOST_CS8;
+ t->c_cc[HOST_VMIN] = 1;
+ t->c_cc[HOST_VTIME] = 0;
+}
+
+int host_cfsetospeed(struct host_termios *tio, host_speed_t speed)
+{
+ if (speed & ~HOST_CBAUD) {
+// errno = EINVAL; /* XXX ? */
+ return -1;
+ }
+ tio->c_cflag &= ~HOST_CBAUD;
+ tio->c_cflag |= speed;
+ return 0;
+}
+
+int host_cfsetispeed(struct host_termios *tio, host_speed_t speed)
+{
+ return speed ? host_cfsetospeed(tio, speed) : 0;
+}
+
+int
+host_cfsetspeed(struct host_termios *tio, host_speed_t speed)
+{
+ return host_cfsetospeed(tio, speed); /* weak alias in musl */
+}
+
diff --git a/stand/kboot/termios.h b/stand/kboot/termios.h
new file mode 100644
index 000000000000..f5763292e7d5
--- /dev/null
+++ b/stand/kboot/termios.h
@@ -0,0 +1,24 @@
+#ifndef _TERMIOS_H
+#define _TERMIOS_H
+
+typedef unsigned char host_cc_t;
+typedef unsigned int host_speed_t;
+typedef unsigned int host_tcflag_t;
+
+#define HOST_NCCS 32
+
+#include "termios_arch.h"
+
+#define HOST_TCSANOW 0
+#define HOST_TCSADRAIN 1
+#define HOST_TCSAFLUSH 2
+
+int host_tcgetattr (int, struct host_termios *);
+int host_tcsetattr (int, int, const struct host_termios *);
+
+void host_cfmakeraw(struct host_termios *);
+int host_cfsetispeed(struct host_termios *, host_speed_t);
+int host_cfsetospeed(struct host_termios *, host_speed_t);
+int host_cfsetspeed(struct host_termios *, host_speed_t);
+
+#endif
diff --git a/stand/kboot/termios_gen.h b/stand/kboot/termios_gen.h
new file mode 100644
index 000000000000..041205e6dd0a
--- /dev/null
+++ b/stand/kboot/termios_gen.h
@@ -0,0 +1,169 @@
+struct host_termios {
+ host_tcflag_t c_iflag;
+ host_tcflag_t c_oflag;
+ host_tcflag_t c_cflag;
+ host_tcflag_t c_lflag;
+ host_cc_t c_line;
+ host_cc_t c_cc[HOST_NCCS];
+ host_speed_t __c_ispeed;
+ host_speed_t __c_ospeed;
+};
+
+#define HOST_VINTR 0
+#define HOST_VQUIT 1
+#define HOST_VERASE 2
+#define HOST_VKILL 3
+#define HOST_VEOF 4
+#define HOST_VTIME 5
+#define HOST_VMIN 6
+#define HOST_VSWTC 7
+#define HOST_VSTART 8
+#define HOST_VSTOP 9
+#define HOST_VSUSP 10
+#define HOST_VEOL 11
+#define HOST_VREPRINT 12
+#define HOST_VDISCARD 13
+#define HOST_VWERASE 14
+#define HOST_VLNEXT 15
+#define HOST_VEOL2 16
+
+#define HOST_IGNBRK 0000001
+#define HOST_BRKINT 0000002
+#define HOST_IGNPAR 0000004
+#define HOST_PARMRK 0000010
+#define HOST_INPCK 0000020
+#define HOST_ISTRIP 0000040
+#define HOST_INLCR 0000100
+#define HOST_IGNCR 0000200
+#define HOST_ICRNL 0000400
+#define HOST_IUCLC 0001000
+#define HOST_IXON 0002000
+#define HOST_IXANY 0004000
+#define HOST_IXOFF 0010000
+#define HOST_IMAXBEL 0020000
+#define HOST_IUTF8 0040000
+
+#define HOST_OPOST 0000001
+#define HOST_OLCUC 0000002
+#define HOST_ONLCR 0000004
+#define HOST_OCRNL 0000010
+#define HOST_ONOCR 0000020
+#define HOST_ONLRET 0000040
+#define HOST_OFILL 0000100
+#define HOST_OFDEL 0000200
+#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) || defined(_XOPEN_SOURCE)
+#define HOST_NLDLY 0000400
+#define HOST_NL0 0000000
+#define HOST_NL1 0000400
+#define HOST_CRDLY 0003000
+#define HOST_CR0 0000000
+#define HOST_CR1 0001000
+#define HOST_CR2 0002000
+#define HOST_CR3 0003000
+#define HOST_TABDLY 0014000
+#define HOST_TAB0 0000000
+#define HOST_TAB1 0004000
+#define HOST_TAB2 0010000
+#define HOST_TAB3 0014000
+#define HOST_BSDLY 0020000
+#define HOST_BS0 0000000
+#define HOST_BS1 0020000
+#define HOST_FFDLY 0100000
+#define HOST_FF0 0000000
+#define HOST_FF1 0100000
+#endif
+
+#define HOST_VTDLY 0040000
+#define HOST_VT0 0000000
+#define HOST_VT1 0040000
+
+#define HOST_B0 0000000
+#define HOST_B50 0000001
+#define HOST_B75 0000002
+#define HOST_B110 0000003
+#define HOST_B134 0000004
+#define HOST_B150 0000005
+#define HOST_B200 0000006
+#define HOST_B300 0000007
+#define HOST_B600 0000010
+#define HOST_B1200 0000011
+#define HOST_B1800 0000012
+#define HOST_B2400 0000013
+#define HOST_B4800 0000014
+#define HOST_B9600 0000015
+#define HOST_B19200 0000016
+#define HOST_B38400 0000017
+
+#define HOST_B57600 0010001
+#define HOST_B115200 0010002
+#define HOST_B230400 0010003
+#define HOST_B460800 0010004
+#define HOST_B500000 0010005
+#define HOST_B576000 0010006
+#define HOST_B921600 0010007
+#define HOST_B1000000 0010010
+#define HOST_B1152000 0010011
+#define HOST_B1500000 0010012
+#define HOST_B2000000 0010013
+#define HOST_B2500000 0010014
+#define HOST_B3000000 0010015
+#define HOST_B3500000 0010016
+#define HOST_B4000000 0010017
+
+#define HOST_CSIZE 0000060
+#define HOST_CS5 0000000
+#define HOST_CS6 0000020
+#define HOST_CS7 0000040
+#define HOST_CS8 0000060
+#define HOST_CSTOPB 0000100
+#define HOST_CREAD 0000200
+#define HOST_PARENB 0000400
+#define HOST_PARODD 0001000
+#define HOST_HUPCL 0002000
+#define HOST_CLOCAL 0004000
+
+#define HOST_ISIG 0000001
+#define HOST_ICANON 0000002
+#define HOST_ECHO 0000010
+#define HOST_ECHOE 0000020
+#define HOST_ECHOK 0000040
+#define HOST_ECHONL 0000100
+#define HOST_NOFLSH 0000200
+#define HOST_TOSTOP 0000400
+#define HOST_IEXTEN 0100000
+
+#define HOST_TCOOFF 0
+#define HOST_TCOON 1
+#define HOST_TCIOFF 2
+#define HOST_TCION 3
+
+#define HOST_TCIFLUSH 0
+#define HOST_TCOFLUSH 1
+#define HOST_TCIOFLUSH 2
+
+#define HOST_TCSANOW 0
+#define HOST_TCSADRAIN 1
+#define HOST_TCSAFLUSH 2
+
+#define HOST_EXTA 0000016
+#define HOST_EXTB 0000017
+#define HOST_CBAUD 0010017
+#define HOST_CBAUDEX 0010000
+#define HOST_CIBAUD 002003600000
+#define HOST_CMSPAR 010000000000
+#define HOST_CRTSCTS 020000000000
+
+#define HOST_XCASE 0000004
+#define HOST_ECHOCTL 0001000
+#define HOST_ECHOPRT 0002000
+#define HOST_ECHOKE 0004000
+#define HOST_FLUSHO 0010000
+#define HOST_PENDIN 0040000
+#define HOST_EXTPROC 0200000
+
+#define HOST_XTABS 0014000
+
+#define HOST_TCGETS 0x5401
+#define HOST_TCSETS 0x5402
+#define HOST_TCSETSW 0x5403
+#define HOST_TCSETSF 0x5404
diff --git a/stand/liblua/lutils.c b/stand/liblua/lutils.c
index 9243edd07e8f..1649ac9fd508 100644
--- a/stand/liblua/lutils.c
+++ b/stand/liblua/lutils.c
@@ -64,6 +64,21 @@ lua_command(lua_State *L)
}
static int
+lua_has_command(lua_State *L)
+{
+ const char *cmd;
+
+ if (lua_gettop(L) != 1) {
+ lua_pushnil(L);
+ return 1;
+ }
+ cmd = luaL_checkstring(L, 1);
+ lua_pushinteger(L, interp_has_builtin_cmd(cmd));
+
+ return 1;
+}
+
+static int
lua_perform(lua_State *L)
{
int argc;
@@ -539,9 +554,9 @@ static const struct luaL_Reg loaderlib[] = {
REG_SIMPLE(interpret),
REG_SIMPLE(parse),
REG_SIMPLE(getenv),
+ REG_SIMPLE(has_command),
REG_SIMPLE(perform),
- /* Also registered as the global 'printc' */
- REG_SIMPLE(printc),
+ REG_SIMPLE(printc), /* Also registered as the global 'printc' */
REG_SIMPLE(setenv),
REG_SIMPLE(time),
REG_SIMPLE(unsetenv),
diff --git a/stand/libofw/ofw_disk.c b/stand/libofw/ofw_disk.c
index 2c3bd568a268..5585b463c737 100644
--- a/stand/libofw/ofw_disk.c
+++ b/stand/libofw/ofw_disk.c
@@ -39,7 +39,7 @@ __FBSDID("$FreeBSD$");
#include <stand.h>
#include <sys/disk.h>
-#include "bootstrap.h"
+#include "disk.h"
#include "libofw.h"
static int ofwd_init(void);
@@ -51,14 +51,16 @@ static int ofwd_ioctl(struct open_file *f, u_long cmd, void *data);
static int ofwd_print(int verbose);
struct devsw ofwdisk = {
- "block",
- DEVT_DISK,
- ofwd_init,
- ofwd_strategy,
- ofwd_open,
- ofwd_close,
- ofwd_ioctl,
- ofwd_print
+ .dv_name = "block",
+ .dv_type = DEVT_DISK,
+ .dv_init = ofwd_init,
+ .dv_strategy = ofwd_strategy,
+ .dv_open = ofwd_open,
+ .dv_close = ofwd_close,
+ .dv_ioctl = ofwd_ioctl,
+ .dv_print = ofwd_print,
+ .dv_cleanup = nullsys,
+ .dv_fmtdev = disk_fmtdev,
};
/*
diff --git a/stand/libsa/Makefile b/stand/libsa/Makefile
index 6f2eaf3d959e..14b38298c3f0 100644
--- a/stand/libsa/Makefile
+++ b/stand/libsa/Makefile
@@ -89,15 +89,18 @@ SRCS+= _setjmp.S
# NOTE: to actually test this functionality after libbz2 upgrade compile
# loader(8) with LOADER_BZIP2_SUPPORT defined
.PATH: ${SRCTOP}/contrib/bzip2
-CFLAGS+= -DBZ_NO_STDIO -DBZ_NO_COMPRESS
-
-SRCS+=bzlib.c crctable.c decompress.c huffman.c randtable.c
+.for i in bzlib.c crctable.c decompress.c huffman.c randtable.c
+CFLAGS.${i}+= -DBZ_NO_STDIO -DBZ_NO_COMPRESS
+SRCS+=${i}
+.endfor
# decompression functionality from zlib
.PATH: ${SRCTOP}/sys/contrib/zlib
-CFLAGS+=-DHAVE_MEMCPY -I${SRCTOP}/sys/contrib/zlib
-SRCS+= adler32.c crc32.c
-SRCS+= infback.c inffast.c inflate.c inftrees.c zutil.c
+ZLIB_CFLAGS=-DHAVE_MEMCPY -I${SRCTOP}/sys/contrib/zlib
+.for i in adler32.c crc32.c infback.c inffast.c inflate.c inftrees.c zutil.c
+CFLAGS.${i}+=${ZLIB_CFLAGS}
+SRCS+= ${i}
+.endfor
# lz4 decompression functionality
.PATH: ${SRCTOP}/sys/cddl/contrib/opensolaris/common/lz4
@@ -167,10 +170,20 @@ SRCS+= time.c
.PATH: ${SRCTOP}/sys/ufs/ffs
SRCS+=ffs_subr.c ffs_tables.c
-CFLAGS.dosfs.c+= -I${LDRSRC}
-CFLAGS.tftp.c+= -I${LDRSRC}
-CFLAGS.ufs.c+= -I${LDRSRC}
-CFLAGS.bzipfs.c+= -I${SRCTOP}/contrib/bzip2
+#
+# i386 has a constrained space for its /boot/loader, so compile out the
+# extensive messages diagnosing bad superblocks. i386 doesn't support UEFI
+# booting, so doing it always makes sense natively there. When we compile
+# for 32-bit on amd64, LIBSA_CPUARCH is also i386 and we use libsa32 only
+# for the BIOS /boot/loader which has the same constraints.
+#
+.if ${LIBSA_CPUARCH} == "i386"
+CFLAGS.ffs_subr.c+= -DSTANDALONE_SMALL
+.endif
+
+CFLAGS.gzipfs.c+= ${ZLIB_CFLAGS}
+CFLAGS.pkgfs.c+= ${ZLIB_CFLAGS}
+CFLAGS.bzipfs.c+= -I${SRCTOP}/contrib/bzip2 -DBZ_NO_STDIO -DBZ_NO_COMPRESS
# explicit_bzero and calculate_crc32c
.PATH: ${SYSDIR}/libkern
@@ -182,6 +195,7 @@ SRCS+= explicit_bzero.c crc32_libkern.c
.endif
.if ${MK_LOADER_VERIEXEC} == "yes" && ${MK_BEARSSL} == "yes"
+# XXX Note that these pollutes CFLAGS in a way that's not easy to fix
.include "${SRCTOP}/lib/libbearssl/Makefile.libsa.inc"
.include "${SRCTOP}/lib/libsecureboot/Makefile.libsa.inc"
.endif
diff --git a/stand/libsa/arp.c b/stand/libsa/arp.c
index 7d49559b4e04..9152cb2773dd 100644
--- a/stand/libsa/arp.c
+++ b/stand/libsa/arp.c
@@ -178,7 +178,7 @@ arprecv(struct iodesc *d, void **pkt, void **payload, time_t tleft, void *extra)
if (n == -1 || n < sizeof(struct ether_arp)) {
#ifdef ARP_DEBUG
if (debug)
- printf("bad len=%d\n", n);
+ printf("bad len=%zd\n", n);
#endif
free(ptr);
return (-1);
diff --git a/stand/libsa/bootp.c b/stand/libsa/bootp.c
index f092db3de968..b00c713d1c30 100644
--- a/stand/libsa/bootp.c
+++ b/stand/libsa/bootp.c
@@ -670,12 +670,14 @@ setenv_(u_char *cp, u_char *ep, struct dhcp_opt *opts)
/* if not found we end up on the default entry */
/*
- * Copy data into the buffer. libstand does not have snprintf so we
- * need to be careful with sprintf(). With strings, the source is
- * always <256 char so shorter than the buffer so we are safe; with
- * other arguments, the longest string is inet_ntoa which is 16 bytes
- * so we make sure to have always enough room in the string before
- * trying an sprint.
+ * Copy data into the buffer. While the code uses snprintf, it's also
+ * careful never to insert strings that would be truncated. inet_ntoa is
+ * tricky to know the size, so it assumes we can always insert it
+ * because we reserve 16 bytes at the end of the string for its worst
+ * case. Other cases are covered because they will write fewer than
+ * these reserved bytes at the end. Source strings can't overflow (as
+ * noted below) because buf is 256 bytes and all strings are limited by
+ * the protocol to be 256 bytes or smaller.
*/
vp = buf;
*vp = '\0';
@@ -695,14 +697,14 @@ setenv_(u_char *cp, u_char *ep, struct dhcp_opt *opts)
if (vp != buf)
*vp++ = FLD_SEP;
bcopy(cp, &in_ip.s_addr, sizeof(in_ip.s_addr));
- sprintf(vp, "%s", inet_ntoa(in_ip));
+ snprintf(vp, endv - vp, "%s", inet_ntoa(in_ip));
vp += strlen(vp);
}
break;
case __BYTES: /* opaque byte string */
for (; size > 0 && vp < endv; size -= 1, cp += 1) {
- sprintf(vp, "%02x", *cp);
+ snprintf(vp, endv - vp, "%02x", *cp);
vp += strlen(vp);
}
break;
@@ -725,7 +727,7 @@ setenv_(u_char *cp, u_char *ep, struct dhcp_opt *opts)
v = cp[0];
if (vp != buf)
*vp++ = FLD_SEP;
- sprintf(vp, "%u", v);
+ snprintf(vp, endv - vp, "%u", v);
vp += strlen(vp);
}
break;
@@ -750,21 +752,22 @@ setenv_(u_char *cp, u_char *ep, struct dhcp_opt *opts)
vp = s; /* prepare for next round */
}
buf[0] = '\0'; /* option already done */
+ break;
}
if (tp - tags < sizeof(tags) - 5) { /* add tag to the list */
if (tp != tags)
*tp++ = FLD_SEP;
- sprintf(tp, "%d", tag);
+ snprintf(tp, sizeof(tags) - (tp - tags), "%d", tag);
tp += strlen(tp);
}
if (buf[0]) {
char env[128]; /* the string name */
if (op->tag == 0)
- sprintf(env, op->desc, opts[0].desc, tag);
+ snprintf(env, sizeof(env), op->desc, opts[0].desc, tag);
else
- sprintf(env, "%s%s", opts[0].desc, op->desc);
+ snprintf(env, sizeof(env), "%s%s", opts[0].desc, op->desc);
/*
* Do not replace existing values in the environment, so that
* locally-obtained values can override server-provided values.
@@ -774,7 +777,7 @@ setenv_(u_char *cp, u_char *ep, struct dhcp_opt *opts)
}
if (tp != tags) {
char env[128]; /* the string name */
- sprintf(env, "%stags", opts[0].desc);
+ snprintf(env, sizeof(env), "%stags", opts[0].desc);
setenv(env, tags, 1);
}
}
diff --git a/stand/libsa/bzipfs.c b/stand/libsa/bzipfs.c
index 1cd71f7913a0..efa2806ce1d4 100644
--- a/stand/libsa/bzipfs.c
+++ b/stand/libsa/bzipfs.c
@@ -70,14 +70,14 @@ static int bzf_stat(struct open_file *f, struct stat *sb);
#ifndef REGRESSION
struct fs_ops bzipfs_fsops = {
- "bzip",
- bzf_open,
- bzf_close,
- bzf_read,
- null_write,
- bzf_seek,
- bzf_stat,
- null_readdir
+ .fs_name = "bzip",
+ .fo_open = bzf_open,
+ .fo_close = bzf_close,
+ .fo_read = bzf_read,
+ .fo_write = null_write,
+ .fo_seek = bzf_seek,
+ .fo_stat = bzf_stat,
+ .fo_readdir = null_readdir,
};
#endif
diff --git a/stand/libsa/dev.c b/stand/libsa/dev.c
index 1d1dd075580e..2ccdce22d596 100644
--- a/stand/libsa/dev.c
+++ b/stand/libsa/dev.c
@@ -56,3 +56,14 @@ noioctl(struct open_file *f __unused, u_long cmd __unused, void *data __unused)
{
return (EINVAL);
}
+
+char *
+devformat(struct devdesc *d)
+{
+ static char name[DEV_DEVLEN];
+
+ if (d->d_dev->dv_fmtdev != NULL)
+ return (d->d_dev->dv_fmtdev(d));
+ snprintf(name, sizeof(name), "%s%d:", d->d_dev->dv_name, d->d_unit);
+ return (name);
+}
diff --git a/stand/libsa/dosfs.c b/stand/libsa/dosfs.c
index 452a79ae12dc..e50f8f25e16a 100644
--- a/stand/libsa/dosfs.c
+++ b/stand/libsa/dosfs.c
@@ -38,7 +38,6 @@ __FBSDID("$FreeBSD$");
#include <stddef.h>
#include "stand.h"
-#include "disk.h"
#include "dosfs.h"
@@ -314,7 +313,7 @@ dos_open(const char *path, struct open_file *fd)
u_int size, clus;
int err;
- dev = disk_fmtdev(fd->f_devdata);
+ dev = devformat((struct devdesc *)fd->f_devdata);
STAILQ_FOREACH(mnt, &mnt_list, dos_link) {
if (strcmp(dev, mnt->dos_dev) == 0)
break;
@@ -322,7 +321,7 @@ dos_open(const char *path, struct open_file *fd)
if (mnt == NULL) {
/* Allocate mount structure, associate with open */
- if ((fs = malloc(sizeof(DOS_FS))) == NULL)
+ if ((fs = calloc(1, sizeof(DOS_FS))) == NULL)
return (errno);
if ((err = dos_mount_impl(fs, fd))) {
free(fs);
diff --git a/stand/libsa/ext2fs.c b/stand/libsa/ext2fs.c
index b81654552af3..3e91d9fd516f 100644
--- a/stand/libsa/ext2fs.c
+++ b/stand/libsa/ext2fs.c
@@ -108,14 +108,14 @@ static int dtmap[] = { DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR,
DT_UNKNOWN : dtmap[x]
struct fs_ops ext2fs_fsops = {
- "ext2fs",
- ext2fs_open,
- ext2fs_close,
- ext2fs_read,
- null_write,
- ext2fs_seek,
- ext2fs_stat,
- ext2fs_readdir
+ .fs_name = "ext2fs",
+ .fo_open = ext2fs_open,
+ .fo_close = ext2fs_close,
+ .fo_read = ext2fs_read,
+ .fo_write = null_write,
+ .fo_seek = ext2fs_seek,
+ .fo_stat = ext2fs_stat,
+ .fo_readdir = ext2fs_readdir,
};
#define EXT2_SBSIZE 1024
diff --git a/stand/libsa/geli/Makefile.inc b/stand/libsa/geli/Makefile.inc
index 734bcf6be5e6..c60cb37c59df 100644
--- a/stand/libsa/geli/Makefile.inc
+++ b/stand/libsa/geli/Makefile.inc
@@ -3,14 +3,13 @@
.PATH: ${SASRC}/geli
-CFLAGS+= -I${LDRSRC}
-
# Our password input method
-SRCS+= pwgets.c
+SRCS+= pwgets.c
# sha256 and sha512 from sys/crypto
.PATH: ${SYSDIR}/crypto/sha2
-CFLAGS+= -DWEAK_REFS
+CFLAGS.sha256.c+= -DWEAK_REFS
+CFLAGS.sha512.c+= -DWEAK_REFS
SRCS+= sha256c.c sha512c.c
# md5 from libmd
@@ -25,13 +24,15 @@ CFLAGS.${i}+= -DNDEBUG
SRCS+= ${i}
.endfor
+
# local GELI Implementation
.PATH: ${SYSDIR}/geom/eli
-SRCS+= \
- geliboot.c \
+.for i in gelidev.c geli_metadata.c
+CFLAGS.${i}+= -I${LDRSRC}
+SRCS+= ${i}
+.endfor
+SRCS+= geliboot.c \
geliboot_crypto.c \
- gelidev.c \
- geli_metadata.c \
g_eli_hmac.c \
g_eli_key.c \
g_eli_key_cache.c \
diff --git a/stand/libsa/geli/geliboot_internal.h b/stand/libsa/geli/geliboot_internal.h
index 2af74466179f..74ca17f0b9b6 100644
--- a/stand/libsa/geli/geliboot_internal.h
+++ b/stand/libsa/geli/geliboot_internal.h
@@ -40,8 +40,6 @@
#include <geom/eli/g_eli.h>
#include <geom/eli/pkcs5v2.h>
-#include <bootstrap.h>
-
/* Pull in the md5, sha256, and sha512 implementations */
#include <sys/md5.h>
#include <crypto/sha2/sha256.h>
diff --git a/stand/libsa/geli/gelidev.c b/stand/libsa/geli/gelidev.c
index d312d7b17e0e..5f1143399fb3 100644
--- a/stand/libsa/geli/gelidev.c
+++ b/stand/libsa/geli/gelidev.c
@@ -62,6 +62,7 @@ static struct devsw geli_devsw = {
.dv_ioctl = geli_dev_ioctl,
.dv_print = geli_dev_print,
.dv_cleanup = geli_dev_cleanup,
+ .dv_fmtdev = disk_fmtdev,
};
/*
@@ -305,7 +306,7 @@ geli_probe_and_attach(struct open_file *f)
hlastblk = (hmediasize / DEV_BSIZE) - 1;
/* Taste the host provider. If it's not geli-encrypted just return. */
- gdev = geli_taste(diskdev_read, hdesc, hlastblk, disk_fmtdev(hdesc));
+ gdev = geli_taste(diskdev_read, hdesc, hlastblk, devformat(&hdesc->dd));
if (gdev == NULL)
return;
diff --git a/stand/libsa/gzipfs.c b/stand/libsa/gzipfs.c
index 8154b0f95a9a..1486df039aac 100644
--- a/stand/libsa/gzipfs.c
+++ b/stand/libsa/gzipfs.c
@@ -52,14 +52,14 @@ static off_t zf_seek(struct open_file *f, off_t offset, int where);
static int zf_stat(struct open_file *f, struct stat *sb);
struct fs_ops gzipfs_fsops = {
- "zip",
- zf_open,
- zf_close,
- zf_read,
- null_write,
- zf_seek,
- zf_stat,
- null_readdir
+ .fs_name = "zip",
+ .fo_open = zf_open,
+ .fo_close = zf_close,
+ .fo_read = zf_read,
+ .fo_write = null_write,
+ .fo_seek = zf_seek,
+ .fo_stat = zf_stat,
+ .fo_readdir = null_readdir,
};
static int
diff --git a/stand/libsa/libsa.3 b/stand/libsa/libsa.3
index f1bfcd7b5be7..7bd7a848cd3d 100644
--- a/stand/libsa/libsa.3
+++ b/stand/libsa/libsa.3
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd February 22, 2018
+.Dd September 9, 2022
.Dt LIBSA 3
.Os
.Sh NAME
@@ -502,6 +502,12 @@ Returns -1 on error, 0 at EOF, or 1 if the user elects to quit while reading.
.Sh MISC
.Bl -hang -width 10n
.It Xo
+.Ft char *
+.Fn devformat "struct devdesc *"
+.Xc
+.Pp
+Format the specified device as a string.
+.It Xo
.Ft void
.Fn twiddle void
.Xc
@@ -615,7 +621,7 @@ The device driver itself will already have been called for the close; this call
should clean up any allocation made by devopen only.
.It Xo
.Ft void
-.Fn abort
+.Fn __abort
.Xc
.Pp
Calls
@@ -687,6 +693,65 @@ pointers should be terminated with a NULL.
Devices are exported by the supporting code via the array
.Vt struct devsw *devsw[]
which is a NULL terminated array of pointers to device switch structures.
+.Sh DRIVER INTERFACE
+The driver needs to provide a common set of entry points that are
+used by
+.Nm libsa
+to interface with the device.
+.Bd -literal
+struct devsw {
+ const char dv_name[DEV_NAMLEN];
+ int dv_type;
+ int (*dv_init)(void);
+ int (*dv_strategy)(void *devdata, int rw, daddr_t blk,
+ size_t size, char *buf, size_t *rsize);
+ int (*dv_open)(struct open_file *f, ...);
+ int (*dv_close)(struct open_file *f);
+ int (*dv_ioctl)(struct open_file *f, u_long cmd, void *data);
+ int (*dv_print)(int verbose);
+ void (*dv_cleanup)(void);
+ void (*dv_fmtdev)(struct devdesc *);
+};
+.Ed
+.Bl -tag -width ".Fn dv_strategy"
+.It Fn dv_name
+The device's name.
+.It Fn dv_type
+Type of device.
+The supported types are:
+.Bl -tag -width "DEVT_NONE"
+.It DEVT_NONE
+.It DEVT_DISK
+.It DEVT_NET
+.It DEVT_CD
+.It DEVT_ZFS
+.It DEVT_FD
+.El
+Each type may have its own associated (struct type_devdesc),
+which has the generic (struct devdesc) as its first member.
+.It Fn dv_init
+Driver initialization routine.
+This routine should probe for available units.
+Drivers are responsible for maintaining lists of units for later enumeration.
+No other driver routines may be called before
+.Fn dv_init
+returns.
+.It Fn dv_open
+The driver open routine.
+.It Fn dv_close
+The driver close routine.
+.It Fn dv_ioctl
+The driver ioctl routine.
+.It Fn dv_print
+Prints information about the available devices.
+Information should be presented with
+.Fn pager_output .
+.It Fn dv_cleanup
+Cleans up any memory used by the device before the next stage is run.
+.It Fn dv_fmtdev
+Converts the specified devdesc to the canonical string representation
+for that device.
+.El
.Sh HISTORY
The
.Nm
diff --git a/stand/libsa/netif.c b/stand/libsa/netif.c
index 4e91e11a9413..91d07dcf96a4 100644
--- a/stand/libsa/netif.c
+++ b/stand/libsa/netif.c
@@ -91,7 +91,7 @@ netif_match(struct netif *nif, void *machdep_hint)
{
struct netif_driver *drv = nif->nif_driver;
-#if NETIF_DEBUG
+#ifdef NETIF_DEBUG
if (netif_debug)
printf("%s%d: netif_match (%d)\n", drv->netif_bname,
nif->nif_unit, nif->nif_sel);
diff --git a/stand/libsa/nfs.c b/stand/libsa/nfs.c
index 5757395caba2..8957fce51a6f 100644
--- a/stand/libsa/nfs.c
+++ b/stand/libsa/nfs.c
@@ -133,14 +133,14 @@ static int nfs_readdir(struct open_file *f, struct dirent *d);
struct nfs_iodesc nfs_root_node;
struct fs_ops nfs_fsops = {
- "nfs",
- nfs_open,
- nfs_close,
- nfs_read,
- null_write,
- nfs_seek,
- nfs_stat,
- nfs_readdir
+ .fs_name = "nfs",
+ .fo_open = nfs_open,
+ .fo_close = nfs_close,
+ .fo_read = nfs_read,
+ .fo_write = null_write,
+ .fo_seek = nfs_seek,
+ .fo_stat = nfs_stat,
+ .fo_readdir = nfs_readdir,
};
static int nfs_read_size = NFSREAD_MIN_SIZE;
diff --git a/stand/libsa/pkgfs.c b/stand/libsa/pkgfs.c
index ffa16309ee6a..9d98e48d9a84 100644
--- a/stand/libsa/pkgfs.c
+++ b/stand/libsa/pkgfs.c
@@ -49,14 +49,14 @@ static int pkg_readdir(struct open_file *, struct dirent *);
static off_t pkg_atol(const char *, unsigned);
struct fs_ops pkgfs_fsops = {
- "pkg",
- pkg_open,
- pkg_close,
- pkg_read,
- null_write,
- pkg_seek,
- pkg_stat,
- pkg_readdir
+ .fs_name = "pkg",
+ .fo_open = pkg_open,
+ .fo_close = pkg_close,
+ .fo_read = pkg_read,
+ .fo_write = null_write,
+ .fo_seek = pkg_seek,
+ .fo_stat = pkg_stat,
+ .fo_readdir = pkg_readdir,
};
#define PKG_BUFSIZE 512
diff --git a/stand/libsa/rarp.c b/stand/libsa/rarp.c
index a81994e51b5c..72aa2650f15e 100644
--- a/stand/libsa/rarp.c
+++ b/stand/libsa/rarp.c
@@ -83,7 +83,7 @@ rarp_getipaddress(int sock)
}
#ifdef RARP_DEBUG
if (debug)
- printf("rarp: d=%x\n", (u_int)d);
+ printf("rarp: d=%lx\n", (long)d);
#endif
bzero((char*)&wbuf.data, sizeof(wbuf.data));
@@ -161,7 +161,7 @@ rarprecv(struct iodesc *d, void **pkt, void **payload, time_t tleft,
if (n == -1 || n < sizeof(struct ether_arp)) {
#ifdef RARP_DEBUG
if (debug)
- printf("bad len=%d\n", n);
+ printf("bad len=%zd\n", n);
#endif
free(ptr);
return (-1);
diff --git a/stand/libsa/smbios.c b/stand/libsa/smbios.c
index 5582a2f3ce90..61bd82f9d6f0 100644
--- a/stand/libsa/smbios.c
+++ b/stand/libsa/smbios.c
@@ -298,6 +298,8 @@ smbios_parse_table(const caddr_t addr)
{
caddr_t cp;
int proc, size, osize, type;
+ uint8_t bios_minor, bios_major;
+ char buf[16];
type = SMBIOS_GET8(addr, 0); /* 3.1.2 Structure Header Format */
switch(type) {
@@ -305,6 +307,13 @@ smbios_parse_table(const caddr_t addr)
smbios_setenv("smbios.bios.vendor", addr, 0x04);
smbios_setenv("smbios.bios.version", addr, 0x05);
smbios_setenv("smbios.bios.reldate", addr, 0x08);
+ bios_major = SMBIOS_GET8(addr, 0x14);
+ bios_minor = SMBIOS_GET8(addr, 0x15);
+ if (bios_minor != 0xFF && bios_major != 0xFF) {
+ snprintf(buf, sizeof(buf), "%u.%u",
+ bios_major, bios_minor);
+ setenv("smbios.bios.revision", buf, 1);
+ }
break;
case 1: /* 3.3.2 System Information (Type 1) */
diff --git a/stand/libsa/splitfs.c b/stand/libsa/splitfs.c
index af28704bc465..30762563d135 100644
--- a/stand/libsa/splitfs.c
+++ b/stand/libsa/splitfs.c
@@ -52,14 +52,14 @@ static off_t splitfs_seek(struct open_file *f, off_t offset, int where);
static int splitfs_stat(struct open_file *f, struct stat *sb);
struct fs_ops splitfs_fsops = {
- "split",
- splitfs_open,
- splitfs_close,
- splitfs_read,
- null_write,
- splitfs_seek,
- splitfs_stat,
- null_readdir
+ .fs_name = "split",
+ .fo_open = splitfs_open,
+ .fo_close = splitfs_close,
+ .fo_read = splitfs_read,
+ .fo_write = null_write,
+ .fo_seek = splitfs_seek,
+ .fo_stat = splitfs_stat,
+ .fo_readdir = null_readdir,
};
static void
diff --git a/stand/libsa/stand.h b/stand/libsa/stand.h
index 097d8ba28d0b..5ffff54c7ca7 100644
--- a/stand/libsa/stand.h
+++ b/stand/libsa/stand.h
@@ -139,9 +139,12 @@ extern struct fs_ops efihttp_fsops;
/*
* Device switch
*/
+#define DEV_NAMLEN 8 /* Length of name of device class */
+#define DEV_DEVLEN 128 /* Length of longest device instance name */
+struct devdesc;
struct devsw {
- const char dv_name[8];
- int dv_type; /* opaque type constant, arch-dependant */
+ const char dv_name[DEV_NAMLEN];
+ int dv_type; /* opaque type constant */
#define DEVT_NONE 0
#define DEVT_DISK 1
#define DEVT_NET 2
@@ -156,6 +159,7 @@ struct devsw {
int (*dv_ioctl)(struct open_file *f, u_long cmd, void *data);
int (*dv_print)(int verbose); /* print device information */
void (*dv_cleanup)(void);
+ char * (*dv_fmtdev)(struct devdesc *);
};
/*
@@ -176,6 +180,8 @@ struct devdesc {
void *d_opendata;
};
+char *devformat(struct devdesc *d);
+
struct open_file {
int f_flags; /* see F_* below */
struct devsw *f_dev; /* pointer to device operations */
diff --git a/stand/libsa/tftp.c b/stand/libsa/tftp.c
index c520a9e3b3b1..903537b4bbe5 100644
--- a/stand/libsa/tftp.c
+++ b/stand/libsa/tftp.c
@@ -55,7 +55,6 @@ __FBSDID("$FreeBSD$");
#include <string.h>
-#include <bootstrap.h>
#include "stand.h"
#include "net.h"
#include "netif.h"
diff --git a/stand/libsa/ufs.c b/stand/libsa/ufs.c
index 12703a3e18aa..769fe9120ee6 100644
--- a/stand/libsa/ufs.c
+++ b/stand/libsa/ufs.c
@@ -81,7 +81,6 @@ __FBSDID("$FreeBSD$");
#include <ufs/ufs/dir.h>
#include <ufs/ffs/fs.h>
#include "stand.h"
-#include "disk.h"
#include "string.h"
static int ufs_open(const char *path, struct open_file *f);
@@ -152,7 +151,10 @@ static int search_directory(char *, struct open_file *, ino_t *);
static int ufs_use_sa_read(void *, off_t, void **, int);
/* from ffs_subr.c */
-int ffs_sbget(void *, struct fs **, off_t, char *,
+int ffs_sbget(void *devfd, struct fs **fsp, off_t sblock, int flags,
+ char *filltype,
+ int (*readfunc)(void *devfd, off_t loc, void **bufp, int size));
+int ffs_sbsearch(void *, struct fs **, int, char *,
int (*)(void *, off_t, void **, int));
/*
@@ -520,7 +522,7 @@ ufs_open(const char *upath, struct open_file *f)
return (errno);
f->f_fsdata = (void *)fp;
- dev = disk_fmtdev(f->f_devdata);
+ dev = devformat((struct devdesc *)f->f_devdata);
/* Is this device mounted? */
STAILQ_FOREACH(mnt, &mnt_list, um_link) {
if (strcmp(dev, mnt->um_dev) == 0)
@@ -530,8 +532,8 @@ ufs_open(const char *upath, struct open_file *f)
if (mnt == NULL) {
/* read super block */
twiddle(1);
- if ((rc = ffs_sbget(f, &fs, STDSB_NOHASHFAIL, "stand",
- ufs_use_sa_read)) != 0) {
+ if ((rc = ffs_sbget(f, &fs, UFS_STDSB, UFS_NOHASHFAIL, "stand",
+ ufs_use_sa_read)) != 0) {
goto out;
}
} else {
@@ -739,7 +741,7 @@ ufs_close(struct open_file *f)
}
free(fp->f_buf);
- dev = disk_fmtdev(f->f_devdata);
+ dev = devformat((struct devdesc *)f->f_devdata);
STAILQ_FOREACH(mnt, &mnt_list, um_link) {
if (strcmp(dev, mnt->um_dev) == 0)
break;
diff --git a/stand/libsa/zfs/Makefile.inc b/stand/libsa/zfs/Makefile.inc
index 2a06db0d2f5d..dfd136a02a48 100644
--- a/stand/libsa/zfs/Makefile.inc
+++ b/stand/libsa/zfs/Makefile.inc
@@ -3,94 +3,83 @@
.PATH: ${ZFSSRC}
.PATH: ${SYSDIR}/crypto/skein
.PATH: ${ZFSOSSRC}/spl
+.PATH: ${OZFS}/module/zstd
.PATH: ${OZFS}/module/zstd/lib/common
.PATH: ${OZFS}/module/zstd/lib/compress
.PATH: ${OZFS}/module/zstd/lib/decompress
-ZFSSRC= zfs.c nvlist.c skein.c skein_block.c list.c
-ZFSSRC+= zstd_shim.c
-ZFSSRC+= entropy_common.c error_private.c
-ZFSSRC+= fse_compress.c fse_decompress.c hist.c
-ZFSSRC+= huf_compress.c huf_decompress.c pool.c xxhash.c
-ZFSSRC+= zstd_common.c zstd_compress.c zstd_compress_literals.c
-ZFSSRC+= zstd_compress_sequences.c zstd_compress_superblock.c
-ZFSSRC+= zstd_ddict.c zstd_decompress.c zstd_decompress_block.c
-ZFSSRC+= zstd_double_fast.c zstd_fast.c zstd_lazy.c zstd_ldm.c
-ZFSSRC+= zstd_opt.c
+.PATH: ${OZFS}/module/icp/algs/blake3
+ZFS_SRC= zfs.c nvlist.c skein.c skein_block.c list.c
+ZFS_SRC+= zfs_zstd.c
+ZFS_SRC+= blake3.c blake3_generic.c blake3_impl_hack.c
+ZSTD_SRC+= entropy_common.c error_private.c
+ZSTD_SRC+= fse_decompress.c hist.c
+ZSTD_SRC+= huf_decompress.c pool.c xxhash.c
+ZSTD_SRC+= zstd_common.c
+ZSTD_SRC+= zstd_ddict.c zstd_decompress.c zstd_decompress_block.c
+ZSTD_SRC+= zstd_double_fast.c zstd_fast.c zstd_lazy.c zstd_ldm.c
-CFLAGS+= -DHAS_ZSTD_ZFS
-SRCS+= ${ZFSSRC}
+SRCS+= ${ZFS_SRC} ${ZSTD_SRC}
-CFLAGS+= -I${LDRSRC}
-CFLAGS+= -I${SYSDIR}/cddl/boot/zfs
-CFLAGS+= -I${SYSDIR}/crypto/skein
+#
+# Any file that needs the FreeBSD overrides that are in
+# include/os/freebssd/spl/XXX needs to have these added to
+# CFLAGS_EARLY.file.c. In general, we try to build out of the OpenZFS tree
+# unaltered. There's a problem, though, that since we're building for a
+# standalone environment that's neither userland nor kernel, we sometimes need
+# special code and that's handled by the 'nested' includes where we either setup
+# something just-so before we include the include/XXX file, or if we need to
+# tweak something defined in that file.
+#
-ZFS_EARLY= -I${ZFSOSINC} \
+ZFS_EARLY= -I${ZFSSRC}/spl \
+ -I${ZFSOSINC} \
-I${ZFSOSINC}/spl \
-I${ZFSOSINC}/zfs
-.for i in ${ZFSSRC}
-CFLAGS.$i+= -include ${ZFSOSINC}/spl/sys/ccompile.h
+#
+# For all files, though, we prepend the sys/ccompile.h file to the build which
+# has a bunch of defines that are present in OpenSolaris / Illumos, but missing
+# from FreeBSD.
+#
+.for i in ${ZFS_SRC} ${ZSTD_SRC}
+CFLAGS.$i+= -include ${ZFSOSINC}/spl/sys/ccompile.h -Wformat -Wall -I${OZFS}/include \
+ -DNEED_SOLARIS_BOOLEAN
.endfor
+CFLAGS_EARLY.blake3.c+= ${ZFS_EARLY}
+CFLAGS_EARLY.blake3_generic.c+= ${ZFS_EARLY}
+CFLAGS_EARLY.blake3_impl_hack.c+= ${ZFS_EARLY}
CFLAGS_EARLY.list.c+= ${ZFS_EARLY}
-CFLAGS_EARLY.zstd_shim.c+= ${ZFS_EARLY}
+CFLAGS_EARLY.zfs_zstd.c+= ${ZFS_EARLY}
+CFLAGS_EARLY.nvlist.c+= ${ZFS_EARLY}
+CFLAGS_EARLY.zfs.c += ${ZFS_EARLY}
-# Can't use the early flags because there's two conflicting definitions of boolean_t in
-# the zfs code that need to be unified.
-CFLAGS.nvlist.c+= -I${ZFSOSINC}/spl
-CFLAGS.zfs.c+= -I${ZFSOSINC}/spl \
+#
+# zfs.c is special: we need to define HAS_ZSTD_ZFS to get zfssubr.c to initialize zstd
+# properly. We need to have the cddl boot compat directory in the include path for zfssubr.c
+# to be found, and we need a couple of other include paths for skein and lz4. Finally we
+# temporarily need LDRSRC to pick up part.h until libsa has a way to look into partitions
+# or enumerate them...
+#
+CFLAGS.zfs.c+= -DHAS_ZSTD_ZFS \
+ -I${SYSDIR}/cddl/boot/zfs \
+ -I${LDRSRC} \
+ -I${SYSDIR}/crypto/skein \
-I${SRCTOP}/sys/cddl/contrib/opensolaris/common/lz4
-CFLAGS.entropy_common.c= -U__BMI__
-CFLAGS.entropy_common.c+= ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
-CFLAGS.error_private.c= -U__BMI__
-CFLAGS.error_private.c+= ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
-CFLAGS.fse_compress.c= -U__BMI__
-CFLAGS.fse_compress.c+= ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
-CFLAGS.fse_decompress.c= -U__BMI__
-CFLAGS.fse_decompress.c+= ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
-CFLAGS.hist.c= -U__BMI__
-CFLAGS.hist.c+= ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
-CFLAGS.huf_compress.c= -U__BMI__
-CFLAGS.huf_compress.c+= ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
-CFLAGS.huf_decompress.c= -U__BMI__
-CFLAGS.huf_decompress.c+= ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
-CFLAGS.pool.c= -U__BMI__
-CFLAGS.pool.c+= ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
-CFLAGS.xxhash.c= -U__BMI__
-CFLAGS.xxhash.c+= ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
-CFLAGS.zstd_common.c= -U__BMI__
-CFLAGS.zstd_common.c+= ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
-CFLAGS.zstd_compress.c= -U__BMI__
-CFLAGS.zstd_compress.c+= ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
-CFLAGS.zstd_compress_literals.c= -U__BMI__
-CFLAGS.zstd_compress_literals.c+= ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
-CFLAGS.zstd_compress_sequences.c= -U__BMI__
-CFLAGS.zstd_compress_sequences.c+= ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
-CFLAGS.zstd_compress_superblock.c= -U__BMI__
-CFLAGS.zstd_compress_superblock.c+= ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
-CFLAGS.zstd_double_fast.c= -U__BMI__
-CFLAGS.zstd_double_fast.c+= ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
-CFLAGS.zstd_fast.c= -U__BMI__
-CFLAGS.zstd_fast.c+= ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
-CFLAGS.zstd_lazy.c= -U__BMI__
-CFLAGS.zstd_lazy.c+= ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
-CFLAGS.zstd_ldm.c= -U__BMI__
-CFLAGS.zstd_ldm.c+= ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
-CFLAGS.zstd_opt.c= -U__BMI__
-CFLAGS.zstd_opt.c+= ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
-CFLAGS.zstd_ddict.c= -U__BMI__
-CFLAGS.zstd_ddict.c+= ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
-CFLAGS.zstd_decompress.c= -U__BMI__
-CFLAGS.zstd_decompress.c+= ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
-CFLAGS.zstd_decompress_block.c= -U__BMI__
-CFLAGS.zstd_decompress_block.c+= ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
-CFLAGS.zstd_shim.c+= -DIN_BASE -DIN_LIBSA -I${OZFS}/include
+
+#
+# ZSTD coding style has some issues, so suppress clang's warnings. Also, zstd's
+# use of BMI instrucitons is broken in this environment, so avoid them.
+#
+.for i in ${ZSTD_SRC}
+CFLAGS.$i+= -U__BMI__ ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
+.endfor
+
+CFLAGS.zfs_zstd.c+= -DIN_BASE -DIN_LIBSA
# Do not unroll skein loops, reduce code size
CFLAGS.skein_block.c+= -DSKEIN_LOOP=111
-CFLAGS+= -I${SYSDIR}/contrib/openzfs/include
-CFLAGS+= -I${SYSDIR}/contrib/openzfs/include/os/freebsd/zfs
-CFLAGS.zfs.c+= -I${SYSDIR}/cddl/contrib/opensolaris/common/lz4
-
-CFLAGS+= -Wformat -Wall
+# To find blake3_impl.c in OpenZFS tree for our somehat ugly blake3_impl_hack.c
+# that's needed until the necessary tweaks can be upstreamed.
+CFLAGS.blake3_impl_hack.c+= -I${OZFS}/module/icp/algs/blake3
diff --git a/stand/libsa/zfs/blake3_impl_hack.c b/stand/libsa/zfs/blake3_impl_hack.c
new file mode 100644
index 000000000000..bc958b961a08
--- /dev/null
+++ b/stand/libsa/zfs/blake3_impl_hack.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2022, Netflix, Inc
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+/*
+ * Hack for aarch64... There's no way to tell it omit the SIMD
+ * versions, so we fake it here.
+ */
+#ifndef isspace
+static __inline int isspace(int c)
+{
+ return c == ' ' || (c >= 0x9 && c <= 0xd);
+}
+#endif
+
+#include "blake3_impl.c"
+
+static inline boolean_t blake3_is_not_supported(void)
+{
+ return (B_FALSE);
+}
+
+const blake3_ops_t blake3_sse2_impl = {
+ .is_supported = blake3_is_not_supported,
+ .degree = 4,
+ .name = "fakesse2"
+};
+
+const blake3_ops_t blake3_sse41_impl = {
+ .is_supported = blake3_is_not_supported,
+ .degree = 4,
+ .name = "fakesse41"
+};
diff --git a/stand/libsa/zfs/devicename_stubs.c b/stand/libsa/zfs/devicename_stubs.c
index 41bf907e0cf1..e58bc9c40e35 100644
--- a/stand/libsa/zfs/devicename_stubs.c
+++ b/stand/libsa/zfs/devicename_stubs.c
@@ -39,7 +39,7 @@ zfs_parsedev(struct zfs_devdesc *dev, const char *devspec, const char **path)
__attribute__((weak))
char *
-zfs_fmtdev(void *vdev)
+zfs_fmtdev(struct devdesc *vdev)
{
static char buf[128];
diff --git a/stand/libsa/zfs/libzfs.h b/stand/libsa/zfs/libzfs.h
index e8676c0d53b8..2f0dfd8afc86 100644
--- a/stand/libsa/zfs/libzfs.h
+++ b/stand/libsa/zfs/libzfs.h
@@ -50,7 +50,7 @@ struct zfs_devdesc {
int zfs_parsedev(struct zfs_devdesc *dev, const char *devspec,
const char **path);
-char *zfs_fmtdev(void *vdev);
+char *zfs_fmtdev(struct devdesc *);
int zfs_probe_dev(const char *devname, uint64_t *pool_guid);
int zfs_list(const char *name);
int zfs_get_bootonce(void *, const char *, char *, size_t);
diff --git a/stand/libsa/zfs/spl/sys/blake3.h b/stand/libsa/zfs/spl/sys/blake3.h
new file mode 100644
index 000000000000..aa2d3b7e55cc
--- /dev/null
+++ b/stand/libsa/zfs/spl/sys/blake3.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2022, Netflix, Inc
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+/*
+ * Gross and ugly hack to cope with upstream's sys/blake3.h not being standalone
+ * safe.
+ */
+#define _KERNEL
+
+#include_next <sys/blake3.h>
+
+#undef _KERNEL
diff --git a/stand/libsa/zfs/spl/sys/zfs_context.h b/stand/libsa/zfs/spl/sys/zfs_context.h
new file mode 100644
index 000000000000..48f164317611
--- /dev/null
+++ b/stand/libsa/zfs/spl/sys/zfs_context.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2022, Netflix, Inc
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+/* TODO: openzfs/include/sys/uio_impl.h must not be included in stand */
+#ifndef _SYS_UIO_IMPL_H
+#define _SYS_UIO_IMPL_H
+#endif
+
+/*
+ * sys/atomic.h must be included after sys/sysmacros.h. The latter includes
+ * machine/atomic.h, which interferes. Sadly, upstream includes them in the
+ * wrong order, so we include it here to fix that.
+ */
+#include <sys/sysmacros.h>
+
+#include_next <sys/zfs_context.h>
+
+#define ZFS_MODULE_PARAM_ARGS void
+
+/*
+ * Not sure why I need these, but including the canonical stand.h fails because
+ * the normal string.h doesn't like all the other shenanigans in this environment.
+ */
+void *memcpy(void *dst, const void *src, size_t len);
+void *memset(void *dest, int c, size_t len);
+void *memmem(const void *big, size_t big_len, const void *little,
+ size_t little_len);
diff --git a/stand/libsa/zfs/zfs.c b/stand/libsa/zfs/zfs.c
index 633ef3b18784..bee243352f78 100644
--- a/stand/libsa/zfs/zfs.c
+++ b/stand/libsa/zfs/zfs.c
@@ -108,7 +108,8 @@ struct zfs_be_entry {
static int
zfs_open(const char *upath, struct open_file *f)
{
- struct zfsmount *mount = (struct zfsmount *)f->f_devdata;
+ struct devdesc *dev = f->f_devdata;
+ struct zfsmount *mount = dev->d_opendata;
struct file *fp;
int rc;
@@ -149,7 +150,8 @@ zfs_close(struct open_file *f)
static int
zfs_read(struct open_file *f, void *start, size_t size, size_t *resid /* out */)
{
- const spa_t *spa = ((struct zfsmount *)f->f_devdata)->spa;
+ struct devdesc *dev = f->f_devdata;
+ const spa_t *spa = ((struct zfsmount *)dev->d_opendata)->spa;
struct file *fp = (struct file *)f->f_fsdata;
struct stat sb;
size_t n;
@@ -213,7 +215,8 @@ zfs_seek(struct open_file *f, off_t offset, int where)
static int
zfs_stat(struct open_file *f, struct stat *sb)
{
- const spa_t *spa = ((struct zfsmount *)f->f_devdata)->spa;
+ struct devdesc *dev = f->f_devdata;
+ const spa_t *spa = ((struct zfsmount *)dev->d_opendata)->spa;
struct file *fp = (struct file *)f->f_fsdata;
return (zfs_dnode_stat(spa, &fp->f_dnode, sb));
@@ -222,7 +225,8 @@ zfs_stat(struct open_file *f, struct stat *sb)
static int
zfs_readdir(struct open_file *f, struct dirent *d)
{
- const spa_t *spa = ((struct zfsmount *)f->f_devdata)->spa;
+ struct devdesc *dev = f->f_devdata;
+ const spa_t *spa = ((struct zfsmount *)dev->d_opendata)->spa;
struct file *fp = (struct file *)f->f_fsdata;
mzap_ent_phys_t mze;
struct stat sb;
@@ -1583,11 +1587,10 @@ zfs_dev_open(struct open_file *f, ...)
rv = 0;
/* This device is not set as currdev, mount us private copy. */
if (mount == NULL)
- rv = zfs_mount(zfs_fmtdev(dev), NULL, (void **)&mount);
+ rv = zfs_mount(devformat(&dev->dd), NULL, (void **)&mount);
if (rv == 0) {
- f->f_devdata = mount;
- free(dev);
+ dev->dd.d_opendata = mount;
}
return (rv);
}
@@ -1595,25 +1598,18 @@ zfs_dev_open(struct open_file *f, ...)
static int
zfs_dev_close(struct open_file *f)
{
+ struct devdesc *dev;
struct zfsmount *mnt, *mount;
- mnt = f->f_devdata;
+ dev = f->f_devdata;
+ mnt = dev->d_opendata;
STAILQ_FOREACH(mount, &zfsmount, next) {
if (mnt->spa->spa_guid == mount->spa->spa_guid)
break;
}
- /*
- * devclose() will free f->f_devdata, but since we do have
- * pointer to zfsmount structure in f->f_devdata, and
- * zfs_unmount() will also free the zfsmount structure,
- * we will get double free. To prevent double free,
- * we must set f_devdata to NULL there.
- */
- if (mount != NULL)
- f->f_devdata = NULL;
-
+ /* XXX */
return (0);
}
@@ -1633,7 +1629,8 @@ struct devsw zfs_dev = {
.dv_close = zfs_dev_close,
.dv_ioctl = noioctl,
.dv_print = zfs_dev_print,
- .dv_cleanup = NULL
+ .dv_cleanup = nullsys,
+ .dv_fmtdev = zfs_fmtdev,
};
int
@@ -1681,7 +1678,7 @@ zfs_parsedev(struct zfs_devdesc *dev, const char *devspec, const char **path)
}
char *
-zfs_fmtdev(void *vdev)
+zfs_fmtdev(struct devdesc *vdev)
{
static char rootname[ZFS_MAXNAMELEN];
static char buf[2 * ZFS_MAXNAMELEN + 8];
@@ -1689,7 +1686,7 @@ zfs_fmtdev(void *vdev)
spa_t *spa;
buf[0] = '\0';
- if (dev->dd.d_dev->dv_type != DEVT_ZFS)
+ if (vdev->d_dev->dv_type != DEVT_ZFS)
return (buf);
/* Do we have any pools? */
diff --git a/stand/libsa/zfs/zfsimpl.c b/stand/libsa/zfs/zfsimpl.c
index 865294dafed4..6b961f3110ae 100644
--- a/stand/libsa/zfs/zfsimpl.c
+++ b/stand/libsa/zfs/zfsimpl.c
@@ -140,6 +140,7 @@ static const char *features_for_read[] = {
"org.freebsd:zstd_compress",
"com.delphix:bookmark_written",
"com.delphix:head_errlog",
+ "org.openzfs:blake3",
NULL
};
diff --git a/stand/libsa/zfs/zstd_shim.c b/stand/libsa/zfs/zstd_shim.c
deleted file mode 100644
index b1ba4babcf36..000000000000
--- a/stand/libsa/zfs/zstd_shim.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*-
- * Copyright (c) 2020 M. Warner Losh <imp@FreeBSD.org>
- *
- * 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$");
-
-/*
- * Small amount of shim code needed to get zfs_zstd.c to compile. These items
- * here should all be defined in the SPL or as part of libsa somewhere, but
- * aren't for reasons that haven't been tracked down yet. Ideally, they would
- * all go away and we'd compile zfs_zstd.c directly. Based on an original by
- * Matt Macey, but only the #include remains untouched from that.
- */
-
-#define ZFS_MODULE_PARAM_ARGS void
-typedef int boolean_t; /* This one may be tough to get rid of */
-
-/* TODO: openzfs/include/sys/uio_impl.h must not be included */
-#ifndef _SYS_UIO_IMPL_H
-#define _SYS_UIO_IMPL_H
-#endif
-
-#include <contrib/openzfs/module/zstd/zfs_zstd.c>
diff --git a/stand/loader.mk b/stand/loader.mk
index aa88122cb7a1..9fa4c74e2501 100644
--- a/stand/loader.mk
+++ b/stand/loader.mk
@@ -6,6 +6,7 @@ CFLAGS+=-I${LDRSRC}
SRCS+= boot.c commands.c console.c devopen.c interp.c
SRCS+= interp_backslash.c interp_parse.c ls.c misc.c
+SRCS+= modinfo.c
SRCS+= module.c nvstore.c pnglite.c tslog.c
CFLAGS.module.c += -I$(SRCTOP)/sys/teken -I${SRCTOP}/contrib/pnglite
diff --git a/stand/lua/menu.lua b/stand/lua/menu.lua
index f1a4f07a8d73..400dbf3d469b 100644
--- a/stand/lua/menu.lua
+++ b/stand/lua/menu.lua
@@ -60,6 +60,10 @@ local function bootenvSet(env)
config.reload()
end
+local function multiUserPrompt()
+ return loader.getenv("loader_menu_multi_user_prompt") or "Multi user"
+end
+
-- Module exports
menu.handlers = {
-- Menu handlers take the current menu and selected entry as parameters,
@@ -263,11 +267,16 @@ menu.welcome = {
all_entries = {
multi_user = {
entry_type = core.MENU_ENTRY,
- name = color.highlight("B") .. "oot Multi user " ..
- color.highlight("[Enter]"),
+ name = function()
+ return color.highlight("B") .. "oot " ..
+ multiUserPrompt() .. " " ..
+ color.highlight("[Enter]")
+ end,
-- Not a standard menu entry function!
- alternate_name = color.highlight("B") ..
- "oot Multi user",
+ alternate_name = function()
+ return color.highlight("B") .. "oot " ..
+ multiUserPrompt()
+ end,
func = function()
core.setSingleUser(false)
core.boot()
diff --git a/stand/man/loader.efi.8 b/stand/man/loader.efi.8
index ca7480d5eba6..b15ae53f2f9d 100644
--- a/stand/man/loader.efi.8
+++ b/stand/man/loader.efi.8
@@ -1,8 +1,13 @@
.\"
.\" SPDX-License-Identifier: BSD-2-Clause-FreeBSD
.\"
-.\" Copyright (c) 2019 Netflix, Inc
+.\" Copyright (c) 2019-2022 Netflix, Inc
.\" Copyright (c) 2022 Mateusz Piotrowski <0mp@FreeBSD.org>
+.\" Copyright 2022 The FreeBSD Foundation, Inc.
+.\"
+.\" Part of this documentation was written by
+.\" Konstantin Belousov <kib@FreeBSD.org> under sponsorship
+.\" from the FreeBSD Foundation.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
@@ -27,7 +32,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd March 18, 2022
+.Dd September 4, 2022
.Dt LOADER.EFI 8
.Os
.Sh NAME
@@ -41,7 +46,277 @@ loads the kernel.
.Xr boot1.efi 8
is used to load
.Nm
-when it is placed within the system.
+when it is placed within a UFS or ZFS file system.
+Alternatively,
+.Nm
+is used directly when configured with
+.Xr efibootmgr 8 ,
+or when placed directly as the default boot program as described in
+.Xr uefi 8 .
+When a system is built using
+.Xr bsdinstall 8 ,
+.Nm
+will be used directly.
+.Ss Console Considerations
+The EFI BIOS provides a generic console.
+In
+.Nm
+this is selected by specifying
+.Dq efi
+using the
+.Dv console
+variable.
+.Nm
+examines the
+.Dv 8be4df61-93ca-11d2-aa0d-00e098032b8c-ConOut
+UEFI environment variable to guess what the
+.Dq efi
+console points to.
+.Nm
+will output its prompts and menus to all the places specified by ConOut.
+However, the
+.Fx
+kernel has a limitation when more than one console is present.
+The kernel outputs to all configured consoles.
+Only the primary console will get the log messages from the
+.Xr rc 8
+system, and prompts for things like
+.Xr geli 8
+passwords.
+If
+.Nm
+finds a video device first, then
+.Nm
+tells the kernel to use the video console as primary.
+Likewise, if a serial device is first in the
+.Dv ConOut
+list, the serial port will be the primary console.
+.Pp
+If there is no
+.Dv ConOut
+variable, both serial and video are attempted.
+.Nm
+uses the
+.Dq efi
+console for the video (which may or may not work) and
+.Dq comconsole
+for the serial on
+.Dv COM1
+at the default baud rate.
+The kernel will use a dual console, with the video console
+primary if a UEFI graphics device is detected, or the serial console
+as primary if not.
+.Pp
+On x86 platforms, if you wish to redirect the loader's output to a serial port
+when the EFI BIOS doesn't support it, or to a serial port that isn't the one the
+EFI BIOS redirects its output to, set
+.Dv console
+to
+.Dq comconsole .
+The default port is
+.Dv COM1
+with an I/O address of 0x3f8.
+.Dv comconsole_port
+is used to set this to a different port address.
+.Dv comconsole_speed
+is used to set the of the serial port (the default is 9600).
+If you have
+.Dv console
+set to
+.Dq efi,comconsole
+you will get output on both the EFI console and the serial port.
+If this causes a doubling of characters, set
+.Dv console
+to
+.Dq efi ,
+since your EFI BIOS is redirecting to the serial port already.
+.Pp
+If your EFI BIOS redirects the serial port, you may need to tell the kernel
+which address to use.
+EFI uses ACPI's UID to identify the serial port, but
+.Nm
+does not have an ACPI parser, so it cannot convert that to an I/O port.
+The
+.Fx
+kernel initializes its consoles before it can decode ACPI resources.
+The
+.Fx
+kernel will look at the
+.Dv hw.uart.console
+variable to set its serial console.
+Its format should be described in
+.Xr uart 4
+but is not.
+Set it to
+.Dq io:0x3f8,br:115200
+with the proper port address.
+PCI or memory mapped ports are beyond the scope of this man page.
+.Pp
+The serial ports are assigned as follows on IBM PC compatible systems:
+.Bl -column -offset indent ".Sy Windows Name" ".Sy I/O Port Address" ".Sy Typical FreeBSD device"
+.It Sy Windows Name Ta Sy I/O Port Address Ta Sy Typical FreeBSD device
+.It COM1 Ta 0x3f8 Ta Pa /dev/uart0
+.It COM2 Ta 0x2f8 Ta Pa /dev/uart1
+.It COM3 Ta 0x3e8 Ta Pa /dev/uart2
+.It COM4 Ta 0x2e8 Ta Pa /dev/uart3
+.El
+Though
+.Dv COM3
+and
+.Dv COM4
+can vary.
+.Pp
+.Ss Primary Console
+The primary console is set using the boot flags.
+These command line arguments set corresponding flags for the kernel.
+These flags can be controlled by setting loader environment variables
+to
+.Dq yes
+or
+.Dq no .
+Boot flags may be set on the command line to the boot command.
+Inside the kernel, the RB_ flags are used to control behavior, sometimes
+in architecturally specific ways and are included to aid in discovery
+of any behavior not covered in this document.
+.Bl -column -offset indent ".Sy boot flag" ".Sy loader variable" ".Sy Kernel RB_ flag"
+.It Sy boot flag Ta Sy loader variable Ta Sy Kernel RB_ flag
+.It Fl a Ta Dv boot_askme Ta Va RB_ASKNAME
+.It Fl c Ta Dv boot_cdrom Ta Va RB_CDROM
+.It Fl d Ta Dv boot_ddb Ta Va RB_KDB
+.It Fl r Ta Dv boot_dfltroot Ta Va RB_DFLTROOT
+.It Fl D Ta Dv boot_multiple Ta Va RB_MULTIPLE
+.It Fl m Ta Dv boot_mute Ta Va RB_MUTE
+.It Fl g Ta Dv boot_gdb Ta Va RB_GDB
+.It Fl h Ta Dv boot_serial Ta Va RB_SERIAL
+.It Fl p Ta Dv boot_pause Ta Va RB_PAUSE
+.It Fl P Ta Dv boot_probe Ta Va RB_PROBE
+.It Fl s Ta Dv boot_single Ta Va RB_SINGLE
+.It Fl v Ta Dv boot_verbose Ta Va RB_VERBOSE
+.El
+And the following flags determine the primary console:
+.Bl -column -offset indent ".Sy Flags" ".Sy Kernel Flags" ".Sy Kernel Consoles" ".Sy Primary Console"
+.It Sy Flags Ta Sy Kernel Flags Ta Sy Kernel Consoles Ta Sy Primary Console
+.It none Ta 0 Ta Video Ta Video
+.It Fl h Ta RB_SERIAL Ta Serial Ta Serial
+.It Fl D Ta RB_MULTIPLE Ta Serial, Video Ta Video
+.It Fl Dh Ta RB_SERIAL | RB_MULTIPLE Ta Serial, Video Ta Serial
+.El
+.Pp
+.Nm
+does not implement the probe
+.Fl P
+functionality where we use the video console if a keyboard is connected and a
+serial console otherwise.
+.Ss Staging Slop
+The kernel must parse the firmware memory map tables to know what memory
+it can use.
+Since it must allocate memory to do this,
+.Nm
+ensures there's extra memory available, called
+.Dq slop ,
+after everything it loads
+.Po
+the kernel, modules and metadata
+.Pc
+for the kernel to bootstrap the memory allocator.
+.Pp
+By default, amd64 reserves 8MB.
+The
+.Ic staging_slop
+command allows for tuning the slop size.
+It takes a single argument, the size of the slop in bytes.
+.Ss amd64 Nocopy
+.Nm
+will load the kernel into memory that is 2MB aligned below 4GB.
+It cannot load to a fixed address because the UEFI firmware may reserve
+arbitrary memory for its use at runtime.
+Prior to
+.Fx 13.1 ,
+kernels retained the old BIOS-boot protocol of loading at exactly 2MB.
+Such kernels must be copied from their loaded location to 2MB prior
+starting them up.
+The
+.Ic copy_staging
+command is used to enable this copying for older kernels.
+It takes a single argument
+which can be one of
+.Bl -tag -width disable
+.It Ar disable
+Force-disable copying staging area to
+.Ad 2M .
+.It Ar enable
+Force-enable copying staging area to
+.Ad 2M .
+.It Ar auto
+Selects the behaviour based on the kernel's capability of boostraping
+from non-2M physical base.
+The kernel reports this capability by exporting the symbol
+.Va kernphys .
+.El
+.Pp
+Arm64 loaders have operated in the
+.Sq nocopy
+mode from their inception, so there is no
+.Ic copy_staging
+command on that platform.
+Riscv, 32-bit arm and arm64 have always loaded at any
+.Ad 2MB
+aligned location, so do not provide
+.Ic copy_staging .
+.Pp
+.Bd -ragged -offset indent
+.Sy Note.
+BIOS loaders on i386 and amd64 put the staging area starting
+at the physical address
+.Ad 2M ,
+then enable paging with identical mapping for the low
+.Ad 1G .
+The initial port of
+.Nm
+followed the same scheme for handing control to the kernel,
+since it avoided modifications for the loader/kernel hand-off protocol,
+and for the kernel page table bootstrap.
+.Pp
+This approach is incompatible with the UEFI specification,
+and as a practical matter, caused troubles on many boards,
+because UEFI firmware is free to use any memory for its own needs.
+Applications like
+.Nm
+must only use memory explicitly allocated using boot interfaces.
+The original way also potentially destroyed UEFI runtime interfaces data.
+.Pp
+Eventually,
+.Nm
+and the kernel were improved to avoid this problem.
+.Ed
+.Ss amd64 Faults
+Because it executes in x86 protected mode, the amd64 version of
+.Nm
+is susceptible to CPU faults due to programmer mistakes and
+memory corruption.
+To make debugging such faults easier, amd64
+.Nm
+can provide detailed reporting of the CPU state at the time
+of the fault.
+.Pp
+The
+.Ic grab_faults
+command installs a handler for faults directly in the IDT,
+avoiding the use of the UEFI debugging interface
+.Fn EFI_DEBUG_SUPPORT_PROTOCOL.RegisterExceptionCallback .
+That interface is left available for advanced debuggers in
+the UEFI environment.
+The
+.Ic ungrab_faults
+command tries to deinstall the fault handler, returning TSS and IDT
+CPU tables to their pre-installation state.
+The
+.Ic fault
+command produces a fault in the
+.Nm
+environment for testing purposes, by executing the
+.Ic ud2
+processor instruction.
.Sh FILES
.Bl -tag -width "/boot/loader.efi"
.It Pa /boot/loader.efi
@@ -49,7 +324,7 @@ The location of the UEFI kernel loader within the system.
.El
.Ss EFI System Partition
.Nm
-is installed on ESP (EFI System Partition) in one of the following locations:
+is installed on the ESP (EFI System Partition) in one of the following locations:
.Bl -tag -width "efi/freebsd/loader.efi"
.It Pa efi/boot/bootXXX.efi
The default location for any EFI loader
@@ -68,10 +343,10 @@ EFI loader.
The default location for the ESP mount point is documented in
.Xr hier 7 .
.Sh EXAMPLES
-.Ss Updating loader.efi on ESP
+.Ss Updating loader.efi on the ESP
The following examples shows how to install a new
.Nm
-on ESP.
+on the ESP.
.Pp
First, find the partition of type
.Dq efi :
@@ -85,10 +360,10 @@ First, find the partition of type
1. Name: nvd0
.Ed
.Pp
-The name of ESP on this system is
+The name of the ESP on this system is
.Pa nvd0p1 .
.Pp
-Second, let's mount ESP, copy
+Second, let's mount the ESP, copy
.Nm
to the special location reserved for
.Fx
@@ -97,6 +372,18 @@ EFI loaders, and unmount once finished:
# mount_msdosfs /dev/nvd0p1 /boot/efi
# cp /boot/loader.efi /boot/efi/efi/freebsd/loader.efi
# umount /boot/efi
+.Ed
.Sh SEE ALSO
.Xr loader 8 ,
.Xr uefi 8
+.Sh BUGS
+Systems that do not have a
+.Dv ConOut
+variable set are not conformant with the standard, and likely have unexpected
+results.
+.Pp
+Non-x86 serial console handling is even more confusing and less well documented.
+.Pp
+Sometimes when the serial port speed isn't set, 9600 is used.
+Other times the result is typically 115200 since the speed remains unchanged
+from the default.
diff --git a/stand/powerpc/ofw/ldscript.powerpc b/stand/powerpc/ofw/ldscript.powerpc
index 5fa27eaf6a13..9202eff286b2 100644
--- a/stand/powerpc/ofw/ldscript.powerpc
+++ b/stand/powerpc/ofw/ldscript.powerpc
@@ -57,6 +57,7 @@ SECTIONS
.sbss2 : { *(.sbss2) }
/* Adjust the address for the data segment to the next page up. */
. = ((. + 0x1000) & ~(0x1000 - 1));
+ .data.rel.ro : { *(.data.rel.ro*) }
.data :
{
*(.data)
diff --git a/stand/powerpc/ofw/ldscript.powerpcle b/stand/powerpc/ofw/ldscript.powerpcle
index 813459b8c242..47fe96e0233f 100644
--- a/stand/powerpc/ofw/ldscript.powerpcle
+++ b/stand/powerpc/ofw/ldscript.powerpcle
@@ -57,6 +57,7 @@ SECTIONS
.sbss2 : { *(.sbss2) }
/* Adjust the address for the data segment to the next page up. */
. = ((. + 0x1000) & ~(0x1000 - 1));
+ .data.rel.ro : { *(.data.rel.ro*) }
.data :
{
*(.data)
diff --git a/stand/uboot/devicename.c b/stand/uboot/devicename.c
index b6b0e6e40639..b73a7694f14a 100644
--- a/stand/uboot/devicename.c
+++ b/stand/uboot/devicename.c
@@ -160,29 +160,6 @@ fail:
}
-char *
-uboot_fmtdev(void *vdev)
-{
- struct uboot_devdesc *dev = (struct uboot_devdesc *)vdev;
- static char buf[128];
-
- switch(dev->dd.d_dev->dv_type) {
- case DEVT_NONE:
- strcpy(buf, "(no device)");
- break;
-
- case DEVT_DISK:
-#ifdef LOADER_DISK_SUPPORT
- return (disk_fmtdev(vdev));
-#endif
-
- case DEVT_NET:
- sprintf(buf, "%s%d:", dev->dd.d_dev->dv_name, dev->dd.d_unit);
- break;
- }
- return(buf);
-}
-
/*
* Set currdev to suit the value being supplied in (value).
*/
diff --git a/stand/uboot/libuboot.h b/stand/uboot/libuboot.h
index 18a12c216d7e..b9039bcf7fdf 100644
--- a/stand/uboot/libuboot.h
+++ b/stand/uboot/libuboot.h
@@ -50,7 +50,6 @@ struct uboot_devdesc {
#endif
int uboot_getdev(void **vdev, const char *devspec, const char **path);
-char *uboot_fmtdev(void *vdev);
int uboot_setcurrdev(struct env_var *ev, int flags, const void *value);
extern int devs_no;
diff --git a/stand/uboot/main.c b/stand/uboot/main.c
index 85ddf5db1f90..573995663fe4 100644
--- a/stand/uboot/main.c
+++ b/stand/uboot/main.c
@@ -475,6 +475,13 @@ main(int argc, char **argv)
meminfo();
+ archsw.arch_loadaddr = uboot_loadaddr;
+ archsw.arch_getdev = uboot_getdev;
+ archsw.arch_copyin = uboot_copyin;
+ archsw.arch_copyout = uboot_copyout;
+ archsw.arch_readin = uboot_readin;
+ archsw.arch_autoload = uboot_autoload;
+
/* Set up currdev variable to have hooks in place. */
env_setenv("currdev", EV_VOLATILE, "", uboot_setcurrdev, env_nounset);
@@ -526,7 +533,7 @@ main(int argc, char **argv)
return (0xbadef1ce);
}
- ldev = uboot_fmtdev(&currdev);
+ ldev = devformat(&currdev.dd);
env_setenv("currdev", EV_VOLATILE, ldev, uboot_setcurrdev, env_nounset);
env_setenv("loaddev", EV_VOLATILE, ldev, env_noset, env_nounset);
printf("Booting from %s\n", ldev);
@@ -538,13 +545,6 @@ do_interact:
setenv("usefdt", "1", 1);
#endif
- archsw.arch_loadaddr = uboot_loadaddr;
- archsw.arch_getdev = uboot_getdev;
- archsw.arch_copyin = uboot_copyin;
- archsw.arch_copyout = uboot_copyout;
- archsw.arch_readin = uboot_readin;
- archsw.arch_autoload = uboot_autoload;
-
interact(); /* doesn't return */
return (0);
diff --git a/stand/uboot/uboot_disk.c b/stand/uboot/uboot_disk.c
index 70dcfdcc8863..2a41d1181992 100644
--- a/stand/uboot/uboot_disk.c
+++ b/stand/uboot/uboot_disk.c
@@ -81,15 +81,16 @@ static int stor_print(int);
static void stor_cleanup(void);
struct devsw uboot_storage = {
- "disk",
- DEVT_DISK,
- stor_init,
- stor_strategy,
- stor_open,
- stor_close,
- stor_ioctl,
- stor_print,
- stor_cleanup
+ .dv_name = "disk",
+ .dv_type = DEVT_DISK,
+ .dv_init = stor_init,
+ .dv_strategy = stor_strategy,
+ .dv_open = stor_open,
+ .dv_close = stor_close,
+ .dv_ioctl = stor_ioctl,
+ .dv_print = stor_print,
+ .dv_cleanup = stor_cleanup,
+ .dv_fmtdev = disk_fmtdev,
};
static int
diff --git a/stand/uboot/uboot_fdt.c b/stand/uboot/uboot_fdt.c
index 4b0a85e3aec0..697aa85ea01b 100644
--- a/stand/uboot/uboot_fdt.c
+++ b/stand/uboot/uboot_fdt.c
@@ -1,6 +1,5 @@
/*-
* Copyright (c) 2009-2010 The FreeBSD Foundation
- * All rights reserved.
*
* This software was developed by Semihalf under sponsorship from
* the FreeBSD Foundation.
diff --git a/stand/usb/storage/umass_loader.c b/stand/usb/storage/umass_loader.c
index 1c12f05c2769..cc1f6b68e275 100644
--- a/stand/usb/storage/umass_loader.c
+++ b/stand/usb/storage/umass_loader.c
@@ -61,6 +61,7 @@ struct devsw umass_disk = {
.dv_ioctl = umass_disk_ioctl,
.dv_print = umass_disk_print,
.dv_cleanup = umass_disk_cleanup,
+ .dv_fmtdev = disk_fmtdev,
};
static int
diff --git a/stand/userboot/userboot/bootinfo.c b/stand/userboot/userboot/bootinfo.c
index 43088e2a7c0e..d77b2f3e51c7 100644
--- a/stand/userboot/userboot/bootinfo.c
+++ b/stand/userboot/userboot/bootinfo.c
@@ -83,31 +83,3 @@ bi_setboothowto(int howto)
boot_howto_to_env(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.
- */
-vm_offset_t
-bi_copyenv(vm_offset_t addr)
-{
- struct env_var *ep;
-
- /* traverse the environment */
- for (ep = environ; ep != NULL; ep = ep->ev_next) {
- CALLBACK(copyin, ep->ev_name, addr, strlen(ep->ev_name));
- addr += strlen(ep->ev_name);
- CALLBACK(copyin, "=", addr, 1);
- addr++;
- if (ep->ev_value != NULL) {
- CALLBACK(copyin, ep->ev_value, addr, strlen(ep->ev_value));
- addr += strlen(ep->ev_value);
- }
- CALLBACK(copyin, "", addr, 1);
- addr++;
- }
- CALLBACK(copyin, "", addr, 1);
- addr++;
- return(addr);
-}
diff --git a/stand/userboot/userboot/bootinfo32.c b/stand/userboot/userboot/bootinfo32.c
index ecd4ccf2edd8..782628c4126c 100644
--- a/stand/userboot/userboot/bootinfo32.c
+++ b/stand/userboot/userboot/bootinfo32.c
@@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$");
#include <i386/include/bootinfo.h>
#include "bootstrap.h"
+#include "modinfo.h"
#include "libuserboot.h"
#ifdef LOADER_GELI_SUPPORT
@@ -43,90 +44,6 @@ __FBSDID("$FreeBSD$");
static struct bootinfo bi;
/*
- * 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) \
- CALLBACK(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) \
- CALLBACK(copyin, s, a, strlen(s) + 1); \
- a += roundup(strlen(s) + 1, sizeof(uint32_t));\
-}
-
-#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) \
- CALLBACK(copyin, &s, a, sizeof(s)); \
- a += roundup(sizeof(s), sizeof(uint32_t)); \
-}
-
-#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) \
- CALLBACK(copyin, mm->md_data, a, mm->md_size); \
- a += roundup(mm->md_size, sizeof(uint32_t));\
-}
-
-#define MOD_END(a, c) { \
- COPY32(MODINFO_END, a, c); \
- COPY32(0, a, c); \
-}
-
-static vm_offset_t
-bi_copymodules32(vm_offset_t addr)
-{
- struct preloaded_file *fp;
- struct file_metadata *md;
- int c;
-
- 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 field must come first */
- MOD_TYPE(addr, fp->f_type, c);
- if (fp->f_args)
- MOD_ARGS(addr, fp->f_args, c);
- MOD_ADDR(addr, fp->f_addr, c);
- MOD_SIZE(addr, fp->f_size, 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);
-}
-
-/*
* Load the information expected by an i386 kernel.
*
* - The 'boothowto' argument is constructed
@@ -139,7 +56,7 @@ int
bi_load32(char *args, int *howtop, int *bootdevp, vm_offset_t *bip, vm_offset_t *modulep, vm_offset_t *kernendp)
{
struct preloaded_file *xp, *kfp;
- struct i386_devdesc *rootdev;
+ struct devdesc *rootdev;
struct file_metadata *md;
vm_offset_t addr;
vm_offset_t kernend;
@@ -167,12 +84,12 @@ bi_load32(char *args, int *howtop, int *bootdevp, vm_offset_t *bip, vm_offset_t
}
/* Try reading the /etc/fstab file to select the root device */
- getrootmount(userboot_fmtdev((void *)rootdev));
+ getrootmount(devformat(rootdev));
bootdevnr = 0;
#if 0
if (bootdevnr == -1) {
- printf("root device %s invalid\n", i386_fmtdev(rootdev));
+ printf("root device %s invalid\n", devformat(rootdev));
return (EINVAL);
}
#endif
@@ -189,7 +106,7 @@ bi_load32(char *args, int *howtop, int *bootdevp, vm_offset_t *bip, vm_offset_t
/* copy our environment */
envp = addr;
- addr = bi_copyenv(addr);
+ addr = md_copyenv(addr);
/* pad to a page boundary */
addr = roundup(addr, PAGE_SIZE);
@@ -210,7 +127,7 @@ bi_load32(char *args, int *howtop, int *bootdevp, vm_offset_t *bip, vm_offset_t
/* Figure out the size and location of the metadata */
*modulep = addr;
- size = bi_copymodules32(0);
+ size = md_copymodules(0, false);
kernend = roundup(addr + size, PAGE_SIZE);
*kernendp = kernend;
@@ -219,7 +136,7 @@ bi_load32(char *args, int *howtop, int *bootdevp, vm_offset_t *bip, vm_offset_t
bcopy(&kernend, md->md_data, sizeof kernend);
/* copy module list and metadata */
- (void)bi_copymodules32(addr);
+ (void)md_copymodules(addr, false);
ssym = esym = 0;
md = file_findmetadata(kfp, MODINFOMD_SSYM);
@@ -235,13 +152,6 @@ bi_load32(char *args, int *howtop, int *bootdevp, vm_offset_t *bip, vm_offset_t
kernelname = getenv("kernelname");
userboot_getdev(NULL, kernelname, &kernelpath);
bi.bi_version = BOOTINFO_VERSION;
- bi.bi_kernelname = 0; /* XXX char * -> kernel name */
- bi.bi_nfs_diskless = 0; /* struct nfs_diskless * */
- bi.bi_n_bios_used = 0; /* XXX would have to hook biosdisk driver for these */
-#if 0
- for (i = 0; i < N_BIOS_GEOM; i++)
- bi.bi_bios_geom[i] = bd_getbigeom(i);
-#endif
bi.bi_size = sizeof(bi);
CALLBACK(getmem, &lowmem, &highmem);
bi.bi_memsizes_valid = 1;
diff --git a/stand/userboot/userboot/bootinfo64.c b/stand/userboot/userboot/bootinfo64.c
index 60887413e0ec..530ddaf768ed 100644
--- a/stand/userboot/userboot/bootinfo64.c
+++ b/stand/userboot/userboot/bootinfo64.c
@@ -37,96 +37,10 @@ __FBSDID("$FreeBSD$");
#include <machine/specialreg.h>
#include "bootstrap.h"
+#include "modinfo.h"
#include "libuserboot.h"
/*
- * 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) \
- CALLBACK(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) \
- CALLBACK(copyin, s, a, strlen(s) + 1); \
- a += roundup(strlen(s) + 1, sizeof(uint64_t));\
-}
-
-#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) \
- CALLBACK(copyin, &s, a, sizeof(s)); \
- a += roundup(sizeof(s), sizeof(uint64_t)); \
-}
-
-#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) \
- CALLBACK(copyin, mm->md_data, a, mm->md_size); \
- a += roundup(mm->md_size, sizeof(uint64_t));\
-}
-
-#define MOD_END(a, c) { \
- COPY32(MODINFO_END, a, c); \
- COPY32(0, a, c); \
-}
-
-static vm_offset_t
-bi_copymodules64(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 field 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;
- 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);
-}
-
-/*
* Check to see if this CPU supports long mode.
*/
static int
@@ -182,7 +96,7 @@ int
bi_load64(char *args, vm_offset_t *modulep, vm_offset_t *kernendp)
{
struct preloaded_file *xp, *kfp;
- struct userboot_devdesc *rootdev;
+ struct devdesc *rootdev;
struct file_metadata *md;
vm_offset_t addr;
uint64_t kernend;
@@ -211,7 +125,7 @@ bi_load64(char *args, vm_offset_t *modulep, vm_offset_t *kernendp)
}
/* Try reading the /etc/fstab file to select the root device */
- getrootmount(userboot_fmtdev((void *)rootdev));
+ getrootmount(devformat(rootdev));
/* find the last module in the chain */
addr = 0;
@@ -224,7 +138,7 @@ bi_load64(char *args, vm_offset_t *modulep, vm_offset_t *kernendp)
/* copy our environment */
envp = addr;
- addr = bi_copyenv(addr);
+ addr = md_copyenv(addr);
/* pad to a page boundary */
addr = roundup(addr, PAGE_SIZE);
@@ -242,7 +156,7 @@ bi_load64(char *args, vm_offset_t *modulep, vm_offset_t *kernendp)
/* Figure out the size and location of the metadata */
*modulep = addr;
- size = bi_copymodules64(0);
+ size = md_copymodules(0, true);
kernend = roundup(addr + size, PAGE_SIZE);
*kernendp = kernend;
@@ -251,7 +165,7 @@ bi_load64(char *args, vm_offset_t *modulep, vm_offset_t *kernendp)
bcopy(&kernend, md->md_data, sizeof kernend);
/* copy module list and metadata */
- (void)bi_copymodules64(addr);
+ (void)md_copymodules(addr, true);
return(0);
}
diff --git a/stand/userboot/userboot/devicename.c b/stand/userboot/userboot/devicename.c
index e770e6bf4bb1..45bf9bc6ebd8 100644
--- a/stand/userboot/userboot/devicename.c
+++ b/stand/userboot/userboot/devicename.c
@@ -176,40 +176,6 @@ fail:
}
-char *
-userboot_fmtdev(void *vdev)
-{
- struct devdesc *dev = (struct devdesc *)vdev;
- static char buf[128]; /* XXX device length constant? */
-
- switch(dev->d_dev->dv_type) {
- case DEVT_NONE:
- strcpy(buf, "(no device)");
- break;
-
- case DEVT_CD:
- sprintf(buf, "%s%d:", dev->d_dev->dv_name, dev->d_unit);
- break;
-
- case DEVT_DISK:
- return (disk_fmtdev(vdev));
-
- case DEVT_NET:
- sprintf(buf, "%s%d:", dev->d_dev->dv_name, dev->d_unit);
- break;
-
- case DEVT_ZFS:
-#if defined(USERBOOT_ZFS_SUPPORT)
- return (zfs_fmtdev(vdev));
-#else
- sprintf(buf, "%s%d:", dev->d_dev->dv_name, dev->d_unit);
-#endif
- break;
- }
- return (buf);
-}
-
-
/*
* Set currdev to suit the value being supplied in (value)
*/
diff --git a/stand/userboot/userboot/host.c b/stand/userboot/userboot/host.c
index 20952983e0d1..d7f01f45c0ab 100644
--- a/stand/userboot/userboot/host.c
+++ b/stand/userboot/userboot/host.c
@@ -155,14 +155,14 @@ host_dev_strategy(void *devdata, int rw, daddr_t dblk, size_t size,
}
struct fs_ops host_fsops = {
- "host",
- host_open,
- host_close,
- host_read,
- null_write,
- host_seek,
- host_stat,
- host_readdir
+ .fs_name = "host",
+ .fo_open = host_open,
+ .fo_close = host_close,
+ .fo_read = host_read,
+ .fo_write = null_write,
+ .fo_seek = host_seek,
+ .fo_stat = host_stat,
+ .fo_readdir = host_readdir,
};
struct devsw host_dev = {
@@ -174,5 +174,5 @@ struct devsw host_dev = {
.dv_close = host_dev_close,
.dv_ioctl = noioctl,
.dv_print = host_dev_print,
- .dv_cleanup = NULL
+ .dv_cleanup = nullsys,
};
diff --git a/stand/userboot/userboot/libuserboot.h b/stand/userboot/userboot/libuserboot.h
index 75732c6c0e38..6d7dc0c3ff40 100644
--- a/stand/userboot/userboot/libuserboot.h
+++ b/stand/userboot/userboot/libuserboot.h
@@ -57,12 +57,10 @@ extern ssize_t userboot_copyin(const void *, vm_offset_t, size_t);
extern ssize_t userboot_copyout(vm_offset_t, void *, size_t);
extern ssize_t userboot_readin(readin_handle_t, vm_offset_t, size_t);
extern int userboot_getdev(void **, const char *, const char **);
-char *userboot_fmtdev(void *vdev);
int userboot_setcurrdev(struct env_var *ev, int flags, const void *value);
int bi_getboothowto(char *kargs);
void bi_setboothowto(int howto);
-vm_offset_t bi_copyenv(vm_offset_t addr);
int bi_load32(char *args, int *howtop, int *bootdevp, vm_offset_t *bip,
vm_offset_t *modulep, vm_offset_t *kernend);
int bi_load64(char *args, vm_offset_t *modulep, vm_offset_t *kernend);
diff --git a/stand/userboot/userboot/main.c b/stand/userboot/userboot/main.c
index 07630945cf80..9ede0cd360e9 100644
--- a/stand/userboot/userboot/main.c
+++ b/stand/userboot/userboot/main.c
@@ -260,7 +260,7 @@ extract_currdev(void)
bzero(&zdev, sizeof(zdev));
zdev.dd.d_dev = &zfs_dev;
- init_zfs_boot_options(zfs_fmtdev(&zdev));
+ init_zfs_boot_options(devformat(&zdev.dd));
dd = &zdev.dd;
} else
#endif
@@ -285,7 +285,7 @@ extract_currdev(void)
dd = &dev.dd;
}
- set_currdev(userboot_fmtdev(dd));
+ set_currdev(devformat(dd));
#if defined(USERBOOT_ZFS_SUPPORT)
if (userboot_zfs_found) {
diff --git a/stand/userboot/userboot/userboot_disk.c b/stand/userboot/userboot/userboot_disk.c
index caaa3373812b..d5b0f36e5e50 100644
--- a/stand/userboot/userboot/userboot_disk.c
+++ b/stand/userboot/userboot/userboot_disk.c
@@ -63,15 +63,16 @@ static int userdisk_ioctl(struct open_file *f, u_long cmd, void *data);
static int userdisk_print(int verbose);
struct devsw userboot_disk = {
- "disk",
- DEVT_DISK,
- userdisk_init,
- userdisk_strategy,
- userdisk_open,
- userdisk_close,
- userdisk_ioctl,
- userdisk_print,
- userdisk_cleanup
+ .dv_name = "disk",
+ .dv_type = DEVT_DISK,
+ .dv_init = userdisk_init,
+ .dv_strategy = userdisk_strategy,
+ .dv_open = userdisk_open,
+ .dv_close = userdisk_close,
+ .dv_ioctl = userdisk_ioctl,
+ .dv_print = userdisk_print,
+ .dv_cleanup = userdisk_cleanup,
+ .dv_fmtdev = disk_fmtdev,
};
/*