summaryrefslogtreecommitdiff
path: root/usr/src/lib/libgrubmgmt/common/libgrub_impl.h
blob: 5d973b20d296d93d2cafd2c27aa6313e5d722ec3 (plain)
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 */