svn commit: r341473 - in head/stand/i386: common gptboot loader
Ian Lepore
ian at FreeBSD.org
Tue Dec 4 16:43:51 UTC 2018
Author: ian
Date: Tue Dec 4 16:43:50 2018
New Revision: 341473
URL: https://svnweb.freebsd.org/changeset/base/341473
Log:
Fix args cross-threading between gptboot(8) and loader(8) with zfs support.
When loader(8) is built with zfs support enabled, it assumes that any extarg
data present is a zfs_boot_args struct, but if the first-stage loader was
gptboot(8) the extarg data is actually a geli_boot_args struct. Luckily,
zfsboot(8) and gptzfsboot(8) have always passed KARGS_FLAGS_ZFS along with
KARGS_FLAGS_EXTARG, so we can use KARGS_FLAGS_ZFS to decide whether the
extarg data is a zfs_boot_args struct.
To avoid similar problems in the future, gptboot(8) now passes a new
KARGS_FLAGS_GELI to indicate that extarg data is geli_boot_args. In
loader(8), if the neither KARGS_FLAGS_ZFS nor KARGS_FLAGS_GELI is set but
extarg data is present (which will be the case for gptboot compiled before
this change), we now check for the known size of the geli_boot_args struct
passed by the older versions of gptboot as a way of confirming what type of
extarg data is present.
In a semi-related tidying up, since loader's main() has already decided
what type of extarg data is present and set the global 'zargs' var
accordingly, don't repeat the check in extract_currdev, just check whether
zargs is NULL or not.
X-MFC after: a few days, along with prior related changes.
Modified:
head/stand/i386/common/bootargs.h
head/stand/i386/gptboot/gptboot.c
head/stand/i386/loader/main.c
Modified: head/stand/i386/common/bootargs.h
==============================================================================
--- head/stand/i386/common/bootargs.h Tue Dec 4 16:12:43 2018 (r341472)
+++ head/stand/i386/common/bootargs.h Tue Dec 4 16:43:50 2018 (r341473)
@@ -18,10 +18,11 @@
#ifndef _BOOT_I386_ARGS_H_
#define _BOOT_I386_ARGS_H_
-#define KARGS_FLAGS_CD 0x1
-#define KARGS_FLAGS_PXE 0x2
-#define KARGS_FLAGS_ZFS 0x4
-#define KARGS_FLAGS_EXTARG 0x8 /* variably sized extended argument */
+#define KARGS_FLAGS_CD 0x0001 /* .bootdev is a bios CD dev */
+#define KARGS_FLAGS_PXE 0x0002 /* .pxeinfo is valid */
+#define KARGS_FLAGS_ZFS 0x0004 /* .zfspool is valid, EXTARG is zfs_boot_args */
+#define KARGS_FLAGS_EXTARG 0x0008 /* variably sized extended argument */
+#define KARGS_FLAGS_GELI 0x0010 /* EXTARG is geli_boot_args */
#define BOOTARGS_SIZE 24 /* sizeof(struct bootargs) */
#define BA_BOOTFLAGS 8 /* offsetof(struct bootargs, bootflags) */
Modified: head/stand/i386/gptboot/gptboot.c
==============================================================================
--- head/stand/i386/gptboot/gptboot.c Tue Dec 4 16:12:43 2018 (r341472)
+++ head/stand/i386/gptboot/gptboot.c Tue Dec 4 16:43:50 2018 (r341473)
@@ -490,7 +490,7 @@ load(void)
__exec((caddr_t)addr, RB_BOOTINFO | (opts & RBX_MASK),
MAKEBOOTDEV(dev_maj[gdsk.dsk.type], gdsk.dsk.part + 1, gdsk.dsk.unit, 0xff),
#ifdef LOADER_GELI_SUPPORT
- KARGS_FLAGS_EXTARG, 0, 0, VTOP(&bootinfo), geliargs
+ KARGS_FLAGS_GELI | KARGS_FLAGS_EXTARG, 0, 0, VTOP(&bootinfo), geliargs
#else
0, 0, 0, VTOP(&bootinfo)
#endif
Modified: head/stand/i386/loader/main.c
==============================================================================
--- head/stand/i386/loader/main.c Tue Dec 4 16:12:43 2018 (r341472)
+++ head/stand/i386/loader/main.c Tue Dec 4 16:43:50 2018 (r341473)
@@ -73,6 +73,7 @@ void exit(int code);
#ifdef LOADER_GELI_SUPPORT
#include "geliboot.h"
struct geli_boot_args *gargs;
+struct geli_boot_data *gbdata;
#endif
#ifdef LOADER_ZFS_SUPPORT
struct zfs_boot_args *zargs;
@@ -169,24 +170,46 @@ main(void)
#ifdef LOADER_ZFS_SUPPORT
archsw.arch_zfs_probe = i386_zfs_probe;
-#ifdef LOADER_GELI_SUPPORT
- if ((kargs->bootflags & KARGS_FLAGS_EXTARG) != 0) {
+ /*
+ * zfsboot and gptzfsboot have always passed KARGS_FLAGS_ZFS, so if that is
+ * set along with KARGS_FLAGS_EXTARG we know we can interpret the extarg
+ * data as a struct zfs_boot_args.
+ */
+#define KARGS_EXTARGS_ZFS (KARGS_FLAGS_EXTARG | KARGS_FLAGS_ZFS)
+
+ if ((kargs->bootflags & KARGS_EXTARGS_ZFS) == KARGS_EXTARGS_ZFS) {
zargs = (struct zfs_boot_args *)(kargs + 1);
- if (zargs->size > offsetof(struct zfs_boot_args, gelidata)) {
- import_geli_boot_data(&zargs->gelidata);
- }
}
-#endif /* LOADER_GELI_SUPPORT */
-#else /* !LOADER_ZFS_SUPPORT */
+#endif /* LOADER_ZFS_SUPPORT */
+
#ifdef LOADER_GELI_SUPPORT
- if ((kargs->bootflags & KARGS_FLAGS_EXTARG) != 0) {
+ /*
+ * If we decided earlier that we have zfs_boot_args extarg data, and it is
+ * big enough to contain the embedded geli data (the early zfs_boot_args
+ * structs weren't), then init the gbdata pointer accordingly. If there is
+ * extarg data which isn't zfs_boot_args data, determine whether it is
+ * geli_boot_args data. Recent versions of gptboot set KARGS_FLAGS_GELI to
+ * indicate that. Earlier versions didn't, but we presume that's what we
+ * have if the extarg size exactly matches the size of the geli_boot_args
+ * struct during that pre-flag era.
+ */
+#define LEGACY_GELI_ARGS_SIZE 260 /* This can never change */
+
+ if (zargs != NULL) {
+ if (zargs->size > offsetof(struct zfs_boot_args, gelidata)) {
+ gbdata = &zargs->gelidata;
+ }
+ } else if ((kargs->bootflags & KARGS_FLAGS_EXTARG) != 0) {
gargs = (struct geli_boot_args *)(kargs + 1);
- if (gargs->size >= offsetof(struct geli_boot_args, gelidata)) {
- import_geli_boot_data(&gargs->gelidata);
+ if ((kargs->bootflags & KARGS_FLAGS_GELI) ||
+ gargs->size == LEGACY_GELI_ARGS_SIZE) {
+ gbdata = &gargs->gelidata;
}
}
+
+ if (gbdata != NULL)
+ import_geli_boot_data(gbdata);
#endif /* LOADER_GELI_SUPPORT */
-#endif /* LOADER_ZFS_SUPPORT */
/*
* March through the device switch probing for things.
@@ -258,11 +281,7 @@ extract_currdev(void)
}
#ifdef LOADER_ZFS_SUPPORT
} else if ((kargs->bootflags & KARGS_FLAGS_ZFS) != 0) {
- zargs = NULL;
- /* check for new style extended argument */
- if ((kargs->bootflags & KARGS_FLAGS_EXTARG) != 0)
- zargs = (struct zfs_boot_args *)(kargs + 1);
-
+ /* zargs was set in main() if we have new style extended argument */
if (zargs != NULL &&
zargs->size >= offsetof(struct zfs_boot_args, primary_pool)) {
/* sufficient data is provided */
More information about the svn-src-all
mailing list