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.
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.
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]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
36 #include <sys/types.h>
37 #include <sys/param.h>
38 #include <sys/mntent.h>
39 #include <sys/uadmin.h>
40 #include <sys/dktp/fdisk.h>
42 #include <libdevinfo.h>
43 #include "libgrubmgmt.h"
44 #include "libgrub_errno.h"
47 * Macros for processing the GRUB menu.
49 #define GRUB_MENU "/boot/grub/menu.lst"
50 #define BOOTSIGN_DIR "/boot/grub/bootsign"
51 #define BOOTSIGN_LEN (2 * MAXNAMELEN)
52 #define ZFS_BOOT_VAR "$ZFS-BOOTFS" /* ZFS boot option */
53 #define ISADIR_VAR "$ISADIR" /* ISADIR option */
55 #define PRTNUM_INVALID -1 /* Partition number invlaid */
56 #define SLCNUM_INVALID -1 /* Slice number invalid */
58 #define SLCNUM_FIRST 'a'
59 #define SLCNUM_WHOLE_DISK 'q'
61 #define IS_SLCNUM_VALID(x) ((x) >= SLCNUM_FIRST && (x) < SLCNUM_WHOLE_DISK)
62 #define IS_PRTNUM_VALID(x) ((uint_t)(x) < FD_NUMPART + MAX_EXT_PARTS)
64 #define GRBM_VALID_FLAG ((uint_t)1 << 31)
65 #define GRBM_MAXLINE 8192
66 #define IS_ENTRY_VALID(ent) ((ent) && ((ent)->ge_flags & GRBM_VALID_FLAG))
67 #define IS_BARG_VALID(barg) ((barg)->gb_flags & GRBM_VALID_FLAG)
68 #define IS_ENTRY_BARG_VALID(ent) \
69 (IS_ENTRY_VALID(ent) && IS_BARG_VALID(&(ent)->ge_barg))
70 #define IS_LINE2BIG(buf, bfsz, len) \
71 ((len = strlen(buf)) == (bfsz) - 1 && (buf)[len - 1] != '\n')
72 #define IS_STR_NULL(x) ((x) == NULL ? "NULL" : (x))
73 #define GRUB_ENTRY_IS_XVM(fbarg) \
74 (strstr(fbarg.gba_kernel, "xen.gz") != NULL)
77 #define menu_cmd(cmd, num, flags, parsef) num,
78 #define menu_cmd_end(num) num
79 #include "libgrub_cmd.def"
82 typedef struct _grub_fs
{
84 di_devlink_handle_t gf_dvlh
;
85 libzfs_handle_t
*gf_lzfh
;
89 typedef struct _grub_cmd_desc
{
104 typedef struct _grub_root
{
105 char gr_fstyp
[MNTMAXSTR
];
106 char gr_physpath
[MAXPATHLEN
];
107 grub_fsdesc_t gr_fs
[GRBM_FS_MAX
];
111 * Data struct for the boot argument constructed from a GRUB menu entry
113 typedef struct _grub_barg
{
114 grub_entry_t
*gb_entry
;
115 grub_line_t
*gb_errline
;
116 int gb_walkret
; /* set to 0 when match found */
121 char gb_bootsign
[BOOTSIGN_LEN
];
122 char gb_kernel
[BOOTARGS_MAX
];
123 char gb_module
[BOOTARGS_MAX
];
127 /* GRUB menu per-line classification */
129 GRUB_LINE_INVALID
= 0,
138 * Data structures for menu.lst contents
141 grub_line_t
*gl_next
;
142 grub_line_t
*gl_prev
;
143 int gl_line_num
; /* Line number in menu.lst */
144 int gl_entry_num
; /* menu boot entry #. */
145 /* GRUB_ENTRY_DEFAULT if none */
147 uint_t gl_cmdtp
; /* recognized command type */
155 grub_menu_t
*ge_menu
; /* grub_menu_t it belongs to */
156 grub_entry_t
*ge_next
;
157 grub_entry_t
*ge_prev
;
158 grub_line_t
*ge_start
;
162 uint_t ge_emask
; /* invalid lines mask */
167 grub_line_t
*gm_start
;
169 grub_line_t
*gm_curdefault
; /* line containing default */
170 grub_entry_t
*gm_ent_start
; /* os entries */
171 grub_entry_t
*gm_ent_end
;
172 grub_entry_t
*gm_ent_default
; /* default entry */
173 uint_t gm_line_num
; /* number of lines processed */
174 uint_t gm_entry_num
; /* number of entries processed */
175 char gm_path
[MAXPATHLEN
];
180 /* File system helper functions */
181 int grub_current_root(grub_fs_t
*, grub_root_t
*);
182 grub_fsdesc_t
*grub_get_rootfsd(const grub_root_t
*);
183 int grub_fsd_mount_tmp(grub_fsdesc_t
*, const char *);
184 void grub_fsd_umount_tmp(grub_fsdesc_t
*);
185 int grub_fsd_get_mountp(grub_fsdesc_t
*fsd
, char *fstyp
);
186 int grub_find_bootsign(grub_barg_t
*barg
);
189 /* GRUB menu parse functions */
190 int skip_line(const grub_line_t
*lp
, grub_barg_t
*barg
);
191 int error_line(const grub_line_t
*lp
, grub_barg_t
*barg
);
192 int kernel(const grub_line_t
*lp
, grub_barg_t
*barg
);
193 int module(const grub_line_t
*lp
, grub_barg_t
*barg
);
194 int dollar_kernel(const grub_line_t
*lp
, grub_barg_t
*barg
);
195 int dollar_module(const grub_line_t
*lp
, grub_barg_t
*barg
);
196 int findroot(const grub_line_t
*lp
, grub_barg_t
*barg
);
197 int bootfs(const grub_line_t
*lp
, grub_barg_t
*barg
);
198 size_t clean_path(char *path
);
201 /* GRUB entry functions */
202 int grub_entry_construct_barg(grub_entry_t
*ent
);
203 const char *grub_entry_get_fstyp(const grub_entry_t
*ent
);
204 const char *grub_entry_get_kernel(const grub_entry_t
*ent
);
205 const char *grub_entry_get_module(const grub_entry_t
*ent
);
206 const grub_fsdesc_t
*grub_entry_get_rootfs(const grub_entry_t
*ent
);
207 size_t grub_entry_get_cmdline(grub_entry_t
*ent
, char *cmdline
, size_t size
);
210 * GRUB menu parse/access funcions.
212 * Callers must call grub_menu_init() to to obtain a handle to the menu before
213 * calling any of the other functions, and call grub_menu_fini() to close.
216 * Reads and parses GRUB menu file into a grub_menu_t data structure.
217 * If grub_menu_path file path is NULL, will use 'currently active'
220 * Frees all resources allocated by grub_menu_init().
222 * grub_menu_get_entry:
223 * Returns a particular entry from the menu.
224 * grub_menu_next_entry:
225 * grub_menu_prev_entry:
226 * Returns next or previous entry in the menu.
227 * If current entry is NULL, return first or last entry.
229 * grub_menu_next_line:
230 * grub_menu_prev_line:
231 * Returns next/prev (to the current) line in the menu.
232 * If current line is NULL, returns first or last line.
233 * grub_menu_get_line:
234 * Returns the specified line in the menu (line counter starts from one).
236 int grub_menu_init(const char *grub_menu_path
, grub_menu_t
**menup
);
237 void grub_menu_fini(grub_menu_t
*);
238 grub_entry_t
*grub_menu_get_entry(const grub_menu_t
*menu
, int num
);
239 grub_entry_t
*grub_menu_next_entry(const grub_menu_t
*menu
,
240 const grub_entry_t
*current
);
241 grub_entry_t
*grub_menu_prev_entry(const grub_menu_t
*menu
,
242 const grub_entry_t
*current
);
243 grub_line_t
*grub_menu_next_line(const grub_menu_t
*menu
,
244 const grub_line_t
*current
);
245 grub_line_t
*grub_menu_prev_line(const grub_menu_t
*menu
,
246 const grub_line_t
*current
);
252 #endif /* _GRBMIMPL_H */