1 /*-
2 * Copyright (c) 2012 Andriy Gapon <avg@FreeBSD.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms are freely
6 * permitted provided that the above copyright notice and this
7 * paragraph and the following disclaimer are duplicated in all
8 * such forms.
9 *
10 * This software is provided "AS IS" and without any express or
11 * implied warranties, including, without limitation, the implied
12 * warranties of merchantability and fitness for a particular
13 * purpose.
14 */
15
16 #ifndef _BOOT_I386_ARGS_H_
17 #define _BOOT_I386_ARGS_H_
18
19 #define KARGS_FLAGS_CD 0x0001 /* .bootdev is a bios CD dev */
20 #define KARGS_FLAGS_PXE 0x0002 /* .pxeinfo is valid */
21 #define KARGS_FLAGS_ZFS 0x0004 /* .zfspool is valid, EXTARG is zfs_boot_args */
22 #define KARGS_FLAGS_EXTARG 0x0008 /* variably sized extended argument */
23 #define KARGS_FLAGS_GELI 0x0010 /* EXTARG is geli_boot_args */
24
25 #define BOOTARGS_SIZE 24 /* sizeof(struct bootargs) */
26 #define BA_BOOTFLAGS 8 /* offsetof(struct bootargs, bootflags) */
27 #define BA_BOOTINFO 20 /* offsetof(struct bootargs, bootinfo) */
28 #define BI_SIZE 48 /* offsetof(struct bootinfo, bi_size) */
29
30 /*
31 * We reserve some space above BTX allocated stack for the arguments
32 * and certain data that could hang off them. Currently only struct bootinfo
33 * is supported in that category. The bootinfo is placed at the top
34 * of the arguments area and the actual arguments are placed at ARGOFF offset
35 * from the top and grow towards the top. Hopefully we have enough space
36 * for bootinfo and the arguments to not run into each other.
37 * Arguments area below ARGOFF is reserved for future use.
38 */
39 #define ARGSPACE 0x1000 /* total size of the BTX args area */
40 #define ARGOFF 0x800 /* actual args offset within the args area */
41 #define ARGADJ (ARGSPACE - ARGOFF)
42
43 #ifndef __ASSEMBLER__
44
45 /*
46 * This struct describes the contents of the stack on entry to btxldr.S. This
47 * is the data that follows the return address, so it begins at 4(%esp). On
48 * the sending side, this data is passed as individual args to __exec(). On the
49 * receiving side, code in btxldr.S copies the data from the entry stack to a
50 * known fixed location in the new address space. Then, btxcsu.S sets the
51 * global variable __args to point to that known fixed location before calling
52 * main(), which casts __args to a struct bootargs pointer to access the data.
53 * The btxldr.S code is aware of KARGS_FLAGS_EXTARG, and if it's set, the extra
54 * args data is copied along with the other bootargs from the entry stack to the
55 * fixed location in the new address space.
56 *
57 * The bootinfo field is actually a pointer to a bootinfo struct that has been
58 * converted to uint32_t using VTOP(). On the receiving side it must be
59 * converted back to a pointer using PTOV(). Code in btxldr.S is aware of this
60 * field and if it's non-NULL it copies the data it points to into another known
61 * fixed location, and adjusts the bootinfo field to point to that new location.
62 */
63 struct bootargs
64 {
65 uint32_t howto;
66 uint32_t bootdev;
67 uint32_t bootflags;
68 union {
69 struct {
70 uint32_t pxeinfo;
71 uint32_t reserved;
72 };
73 uint64_t zfspool;
74 };
75 uint32_t bootinfo;
76
77 /*
78 * If KARGS_FLAGS_EXTARG is set in bootflags, then the above fields
79 * are followed by a uint32_t field that specifies a size of the
80 * extended arguments (including the size field).
81 */
82 };
83
84 #ifdef LOADER_GELI_SUPPORT
85 #include <crypto/intake.h>
86 #include "geliboot.h"
87 #endif
88
89 /*
90 * geli_boot_data is embedded in geli_boot_args (passed from gptboot to loader)
91 * and in zfs_boot_args (passed from zfsboot and gptzfsboot to loader).
92 */
93 struct geli_boot_data
94 {
95 union {
96 char gelipw[256];
97 struct {
98 char notapw; /*
99 * single null byte to stop keybuf
100 * being interpreted as a password
101 */
102 uint32_t keybuf_sentinel;
103 #ifdef LOADER_GELI_SUPPORT
104 struct keybuf *keybuf;
105 #else
106 void *keybuf;
107 #endif
108 };
109 };
110 };
111
112 #ifdef LOADER_GELI_SUPPORT
113
114 static inline void
export_geli_boot_data(struct geli_boot_data * gbdata)115 export_geli_boot_data(struct geli_boot_data *gbdata)
116 {
117
118 gbdata->notapw = '\0';
119 gbdata->keybuf_sentinel = KEYBUF_SENTINEL;
120 gbdata->keybuf = malloc(sizeof(struct keybuf) +
121 (GELI_MAX_KEYS * sizeof(struct keybuf_ent)));
122 geli_export_key_buffer(gbdata->keybuf);
123 }
124
125 static inline void
import_geli_boot_data(struct geli_boot_data * gbdata)126 import_geli_boot_data(struct geli_boot_data *gbdata)
127 {
128
129 if (gbdata->gelipw[0] != '\0') {
130 setenv("kern.geom.eli.passphrase", gbdata->gelipw, 1);
131 explicit_bzero(gbdata->gelipw, sizeof(gbdata->gelipw));
132 } else if (gbdata->keybuf_sentinel == KEYBUF_SENTINEL) {
133 geli_import_key_buffer(gbdata->keybuf);
134 }
135 }
136 #endif /* LOADER_GELI_SUPPORT */
137
138 struct geli_boot_args
139 {
140 uint32_t size;
141 struct geli_boot_data gelidata;
142 };
143
144 struct zfs_boot_args
145 {
146 uint32_t size;
147 uint32_t reserved;
148 uint64_t pool;
149 uint64_t root;
150 uint64_t primary_pool;
151 uint64_t primary_vdev;
152 struct geli_boot_data gelidata;
153 };
154
155 #endif /*__ASSEMBLER__*/
156
157 #endif /* !_BOOT_I386_ARGS_H_ */
158