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