1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
|
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
#ifndef _GRBMIMPL_H
#define _GRBMIMPL_H
#ifdef __cplusplus
extern "C" {
#endif
#include <sys/types.h>
#include <sys/param.h>
#include <sys/mntent.h>
#include <sys/uadmin.h>
#include <sys/dktp/fdisk.h>
#include <libzfs.h>
#include <libdevinfo.h>
#include "libgrubmgmt.h"
#include "libgrub_errno.h"
/*
* Macros for processing the GRUB menu.
*/
#define GRUB_MENU "/boot/grub/menu.lst"
#define BOOTSIGN_DIR "/boot/grub/bootsign"
#define BOOTSIGN_LEN (2 * MAXNAMELEN)
#define ZFS_BOOT_VAR "$ZFS-BOOTFS" /* ZFS boot option */
#define ISADIR_VAR "$ISADIR" /* ISADIR option */
#define PRTNUM_INVALID -1 /* Partition number invlaid */
#define SLCNUM_INVALID -1 /* Slice number invalid */
#define SLCNUM_FIRST 'a'
#define SLCNUM_WHOLE_DISK 'q'
#define IS_SLCNUM_VALID(x) ((x) >= SLCNUM_FIRST && (x) < SLCNUM_WHOLE_DISK)
#define IS_PRTNUM_VALID(x) ((uint_t)(x) < FD_NUMPART + MAX_EXT_PARTS)
#define GRBM_VALID_FLAG ((uint_t)1 << 31)
#define GRBM_MAXLINE 8192
#define IS_ENTRY_VALID(ent) ((ent) && ((ent)->ge_flags & GRBM_VALID_FLAG))
#define IS_BARG_VALID(barg) ((barg)->gb_flags & GRBM_VALID_FLAG)
#define IS_ENTRY_BARG_VALID(ent) \
(IS_ENTRY_VALID(ent) && IS_BARG_VALID(&(ent)->ge_barg))
#define IS_LINE2BIG(buf, bfsz, len) \
((len = strlen(buf)) == (bfsz) - 1 && (buf)[len - 1] != '\n')
#define IS_STR_NULL(x) ((x) == NULL ? "NULL" : (x))
#define GRUB_ENTRY_IS_XVM(fbarg) \
(strstr(fbarg.gba_kernel, "xen.gz") != NULL)
enum {
#define menu_cmd(cmd, num, flags, parsef) num,
#define menu_cmd_end(num) num
#include "libgrub_cmd.def"
};
typedef struct _grub_fs {
di_node_t gf_diroot;
di_devlink_handle_t gf_dvlh;
libzfs_handle_t *gf_lzfh;
} grub_fs_t;
typedef struct _grub_cmd_desc {
const char *gcd_cmd;
uint_t gcd_num;
int gcd_flags;
} grub_cmd_desc_t;
enum {
GRBM_UFS = 0,
GRBM_ZFS_TOPFS = 0,
GRBM_FS_TOP = 0,
GRBM_ZFS_BOOTFS,
GRBM_FS_MAX
};
typedef struct _grub_root {
char gr_fstyp[MNTMAXSTR];
char gr_physpath[MAXPATHLEN];
grub_fsdesc_t gr_fs[GRBM_FS_MAX];
} grub_root_t;
/*
* Data struct for the boot argument constructed from a GRUB menu entry
*/
typedef struct _grub_barg {
grub_entry_t *gb_entry;
grub_line_t *gb_errline;
int gb_walkret; /* set to 0 when match found */
uint_t gb_flags;
uint_t gb_prtnum;
uint_t gb_slcnum;
grub_root_t gb_root;
char gb_bootsign[BOOTSIGN_LEN];
char gb_kernel[BOOTARGS_MAX];
char gb_module[BOOTARGS_MAX];
} grub_barg_t;
/* GRUB menu per-line classification */
enum {
GRUB_LINE_INVALID = 0,
GRUB_LINE_EMPTY,
GRUB_LINE_COMMENT,
GRUB_LINE_GLOBAL,
GRUB_LINE_ENTRY,
GRUB_LINE_TITLE
};
/*
* Data structures for menu.lst contents
*/
struct grub_line {
grub_line_t *gl_next;
grub_line_t *gl_prev;
int gl_line_num; /* Line number in menu.lst */
int gl_entry_num; /* menu boot entry #. */
/* GRUB_ENTRY_DEFAULT if none */
int gl_flags;
uint_t gl_cmdtp; /* recognized command type */
char *gl_cmd;
char *gl_sep;
char *gl_arg;
char *gl_line;
};
struct grub_entry {
grub_menu_t *ge_menu; /* grub_menu_t it belongs to */
grub_entry_t *ge_next;
grub_entry_t *ge_prev;
grub_line_t *ge_start;
grub_line_t *ge_end;
int ge_entry_num;
uint_t ge_flags;
uint_t ge_emask; /* invalid lines mask */
grub_barg_t ge_barg;
};
struct grub_menu {
grub_line_t *gm_start;
grub_line_t *gm_end;
grub_line_t *gm_curdefault; /* line containing default */
grub_entry_t *gm_ent_start; /* os entries */
grub_entry_t *gm_ent_end;
grub_entry_t *gm_ent_default; /* default entry */
uint_t gm_line_num; /* number of lines processed */
uint_t gm_entry_num; /* number of entries processed */
char gm_path[MAXPATHLEN];
grub_fs_t gm_fs;
grub_root_t gm_root;
};
/* File system helper functions */
int grub_current_root(grub_fs_t *, grub_root_t *);
grub_fsdesc_t *grub_get_rootfsd(const grub_root_t *);
int grub_fsd_mount_tmp(grub_fsdesc_t *, const char *);
void grub_fsd_umount_tmp(grub_fsdesc_t *);
int grub_fsd_get_mountp(grub_fsdesc_t *fsd, char *fstyp);
int grub_find_bootsign(grub_barg_t *barg);
/* GRUB menu parse functions */
int skip_line(const grub_line_t *lp, grub_barg_t *barg);
int error_line(const grub_line_t *lp, grub_barg_t *barg);
int kernel(const grub_line_t *lp, grub_barg_t *barg);
int module(const grub_line_t *lp, grub_barg_t *barg);
int dollar_kernel(const grub_line_t *lp, grub_barg_t *barg);
int dollar_module(const grub_line_t *lp, grub_barg_t *barg);
int findroot(const grub_line_t *lp, grub_barg_t *barg);
int bootfs(const grub_line_t *lp, grub_barg_t *barg);
size_t clean_path(char *path);
/* GRUB entry functions */
int grub_entry_construct_barg(grub_entry_t *ent);
const char *grub_entry_get_fstyp(const grub_entry_t *ent);
const char *grub_entry_get_kernel(const grub_entry_t *ent);
const char *grub_entry_get_module(const grub_entry_t *ent);
const grub_fsdesc_t *grub_entry_get_rootfs(const grub_entry_t *ent);
size_t grub_entry_get_cmdline(grub_entry_t *ent, char *cmdline, size_t size);
/*
* GRUB menu parse/access funcions.
*
* Callers must call grub_menu_init() to to obtain a handle to the menu before
* calling any of the other functions, and call grub_menu_fini() to close.
*
* grub_menu_init:
* Reads and parses GRUB menu file into a grub_menu_t data structure.
* If grub_menu_path file path is NULL, will use 'currently active'
* GRUB menu file.
* grub_menu_fini:
* Frees all resources allocated by grub_menu_init().
*
* grub_menu_get_entry:
* Returns a particular entry from the menu.
* grub_menu_next_entry:
* grub_menu_prev_entry:
* Returns next or previous entry in the menu.
* If current entry is NULL, return first or last entry.
*
* grub_menu_next_line:
* grub_menu_prev_line:
* Returns next/prev (to the current) line in the menu.
* If current line is NULL, returns first or last line.
* grub_menu_get_line:
* Returns the specified line in the menu (line counter starts from one).
*/
int grub_menu_init(const char *grub_menu_path, grub_menu_t **menup);
void grub_menu_fini(grub_menu_t *);
grub_entry_t *grub_menu_get_entry(const grub_menu_t *menu, int num);
grub_entry_t *grub_menu_next_entry(const grub_menu_t *menu,
const grub_entry_t *current);
grub_entry_t *grub_menu_prev_entry(const grub_menu_t *menu,
const grub_entry_t *current);
grub_line_t *grub_menu_next_line(const grub_menu_t *menu,
const grub_line_t *current);
grub_line_t *grub_menu_prev_line(const grub_menu_t *menu,
const grub_line_t *current);
#ifdef __cplusplus
}
#endif
#endif /* _GRBMIMPL_H */
|