7297dc4441
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.
160 lines
4.9 KiB
C
160 lines
4.9 KiB
C
/*-
|
|
* Copyright (c) 2012 Andriy Gapon <avg@FreeBSD.org>
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms are freely
|
|
* permitted provided that the above copyright notice and this
|
|
* paragraph and the following disclaimer are duplicated in all
|
|
* such forms.
|
|
*
|
|
* This software is provided "AS IS" and without any express or
|
|
* implied warranties, including, without limitation, the implied
|
|
* warranties of merchantability and fitness for a particular
|
|
* purpose.
|
|
*
|
|
* $FreeBSD$
|
|
*/
|
|
|
|
#ifndef _BOOT_I386_ARGS_H_
|
|
#define _BOOT_I386_ARGS_H_
|
|
|
|
#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) */
|
|
#define BA_BOOTINFO 20 /* offsetof(struct bootargs, bootinfo) */
|
|
#define BI_SIZE 48 /* offsetof(struct bootinfo, bi_size) */
|
|
|
|
/*
|
|
* We reserve some space above BTX allocated stack for the arguments
|
|
* and certain data that could hang off them. Currently only struct bootinfo
|
|
* is supported in that category. The bootinfo is placed at the top
|
|
* of the arguments area and the actual arguments are placed at ARGOFF offset
|
|
* from the top and grow towards the top. Hopefully we have enough space
|
|
* for bootinfo and the arguments to not run into each other.
|
|
* Arguments area below ARGOFF is reserved for future use.
|
|
*/
|
|
#define ARGSPACE 0x1000 /* total size of the BTX args area */
|
|
#define ARGOFF 0x800 /* actual args offset within the args area */
|
|
#define ARGADJ (ARGSPACE - ARGOFF)
|
|
|
|
#ifndef __ASSEMBLER__
|
|
|
|
/*
|
|
* This struct describes the contents of the stack on entry to btxldr.S. This
|
|
* is the data that follows the return address, so it begins at 4(%esp). On
|
|
* the sending side, this data is passed as individual args to __exec(). On the
|
|
* receiving side, code in btxldr.S copies the data from the entry stack to a
|
|
* known fixed location in the new address space. Then, btxcsu.S sets the
|
|
* global variable __args to point to that known fixed location before calling
|
|
* main(), which casts __args to a struct bootargs pointer to access the data.
|
|
* The btxldr.S code is aware of KARGS_FLAGS_EXTARG, and if it's set, the extra
|
|
* args data is copied along with the other bootargs from the entry stack to the
|
|
* fixed location in the new address space.
|
|
*
|
|
* The bootinfo field is actually a pointer to a bootinfo struct that has been
|
|
* converted to uint32_t using VTOP(). On the receiving side it must be
|
|
* converted back to a pointer using PTOV(). Code in btxldr.S is aware of this
|
|
* field and if it's non-NULL it copies the data it points to into another known
|
|
* fixed location, and adjusts the bootinfo field to point to that new location.
|
|
*/
|
|
struct bootargs
|
|
{
|
|
uint32_t howto;
|
|
uint32_t bootdev;
|
|
uint32_t bootflags;
|
|
union {
|
|
struct {
|
|
uint32_t pxeinfo;
|
|
uint32_t reserved;
|
|
};
|
|
uint64_t zfspool;
|
|
};
|
|
uint32_t bootinfo;
|
|
|
|
/*
|
|
* If KARGS_FLAGS_EXTARG is set in bootflags, then the above fields
|
|
* are followed by a uint32_t field that specifies a size of the
|
|
* extended arguments (including the size field).
|
|
*/
|
|
};
|
|
|
|
#ifdef LOADER_GELI_SUPPORT
|
|
#include <crypto/intake.h>
|
|
#include "geliboot.h"
|
|
#endif
|
|
|
|
/*
|
|
* geli_boot_data is embedded in geli_boot_args (passed from gptboot to loader)
|
|
* and in zfs_boot_args (passed from zfsboot and gptzfsboot to loader).
|
|
*/
|
|
struct geli_boot_data
|
|
{
|
|
union {
|
|
char gelipw[256];
|
|
struct {
|
|
char notapw; /*
|
|
* single null byte to stop keybuf
|
|
* being interpreted as a password
|
|
*/
|
|
uint32_t keybuf_sentinel;
|
|
#ifdef LOADER_GELI_SUPPORT
|
|
struct keybuf *keybuf;
|
|
#else
|
|
void *keybuf;
|
|
#endif
|
|
};
|
|
};
|
|
};
|
|
|
|
#ifdef LOADER_GELI_SUPPORT
|
|
|
|
static inline void
|
|
export_geli_boot_data(struct geli_boot_data *gbdata)
|
|
{
|
|
|
|
gbdata->notapw = '\0';
|
|
gbdata->keybuf_sentinel = KEYBUF_SENTINEL;
|
|
gbdata->keybuf = malloc(sizeof(struct keybuf) +
|
|
(GELI_MAX_KEYS * sizeof(struct keybuf_ent)));
|
|
geli_export_key_buffer(gbdata->keybuf);
|
|
}
|
|
|
|
static inline void
|
|
import_geli_boot_data(struct geli_boot_data *gbdata)
|
|
{
|
|
|
|
if (gbdata->gelipw[0] != '\0') {
|
|
setenv("kern.geom.eli.passphrase", gbdata->gelipw, 1);
|
|
explicit_bzero(gbdata->gelipw, sizeof(gbdata->gelipw));
|
|
} else if (gbdata->keybuf_sentinel == KEYBUF_SENTINEL) {
|
|
geli_import_key_buffer(gbdata->keybuf);
|
|
}
|
|
}
|
|
#endif /* LOADER_GELI_SUPPORT */
|
|
|
|
struct geli_boot_args
|
|
{
|
|
uint32_t size;
|
|
struct geli_boot_data gelidata;
|
|
};
|
|
|
|
struct zfs_boot_args
|
|
{
|
|
uint32_t size;
|
|
uint32_t reserved;
|
|
uint64_t pool;
|
|
uint64_t root;
|
|
uint64_t primary_pool;
|
|
uint64_t primary_vdev;
|
|
struct geli_boot_data gelidata;
|
|
};
|
|
|
|
#endif /*__ASSEMBLER__*/
|
|
|
|
#endif /* !_BOOT_I386_ARGS_H_ */
|