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 * Copyright 2013 Nexenta Systems, Inc. All rights reserved. 27 */ 28 29 #ifndef _GRBMIMPL_H 30 #define _GRBMIMPL_H 31 32 #ifdef __cplusplus 33 extern "C" { 34 #endif 35 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> 41 #include <libzfs.h> 42 #include <libdevinfo.h> 43 #include "libgrubmgmt.h" 44 #include "libgrub_errno.h" 45 46 /* 47 * Macros for processing the GRUB menu. 48 */ 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 */ 54 55 #define PRTNUM_INVALID -1 /* Partition number invlaid */ 56 #define SLCNUM_INVALID -1 /* Slice number invalid */ 57 58 #define SLCNUM_FIRST 'a' 59 #define SLCNUM_WHOLE_DISK 'q' 60 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) 63 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) 75 76 enum { 77 #define menu_cmd(cmd, num, flags, parsef) num, 78 #define menu_cmd_end(num) num 79 #include "libgrub_cmd.def" 80 }; 81 82 typedef struct _grub_fs { 83 di_node_t gf_diroot; 84 di_devlink_handle_t gf_dvlh; 85 libzfs_handle_t *gf_lzfh; 86 } grub_fs_t; 87 88 89 typedef struct _grub_cmd_desc { 90 const char *gcd_cmd; 91 uint_t gcd_num; 92 int gcd_flags; 93 } grub_cmd_desc_t; 94 95 96 enum { 97 GRBM_UFS = 0, 98 GRBM_ZFS_TOPFS = 0, 99 GRBM_FS_TOP = 0, 100 GRBM_ZFS_BOOTFS, 101 GRBM_FS_MAX 102 }; 103 104 typedef struct _grub_root { 105 char gr_fstyp[MNTMAXSTR]; 106 char gr_physpath[MAXPATHLEN]; 107 grub_fsdesc_t gr_fs[GRBM_FS_MAX]; 108 } grub_root_t; 109 110 /* 111 * Data struct for the boot argument constructed from a GRUB menu entry 112 */ 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 */ 117 uint_t gb_flags; 118 uint_t gb_prtnum; 119 uint_t gb_slcnum; 120 grub_root_t gb_root; 121 char gb_bootsign[BOOTSIGN_LEN]; 122 char gb_kernel[BOOTARGS_MAX]; 123 char gb_module[BOOTARGS_MAX]; 124 } grub_barg_t; 125 126 127 /* GRUB menu per-line classification */ 128 enum { 129 GRUB_LINE_INVALID = 0, 130 GRUB_LINE_EMPTY, 131 GRUB_LINE_COMMENT, 132 GRUB_LINE_GLOBAL, 133 GRUB_LINE_ENTRY, 134 GRUB_LINE_TITLE 135 }; 136 137 /* 138 * Data structures for menu.lst contents 139 */ 140 struct grub_line { 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 */ 146 int gl_flags; 147 uint_t gl_cmdtp; /* recognized command type */ 148 char *gl_cmd; 149 char *gl_sep; 150 char *gl_arg; 151 char *gl_line; 152 }; 153 154 struct grub_entry { 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; 159 grub_line_t *ge_end; 160 int ge_entry_num; 161 uint_t ge_flags; 162 uint_t ge_emask; /* invalid lines mask */ 163 grub_barg_t ge_barg; 164 }; 165 166 struct grub_menu { 167 grub_line_t *gm_start; 168 grub_line_t *gm_end; 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]; 176 grub_fs_t gm_fs; 177 grub_root_t gm_root; 178 }; 179 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); 187 188 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); 199 200 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); 208 209 /* 210 * GRUB menu parse/access funcions. 211 * 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. 214 * 215 * grub_menu_init: 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' 218 * GRUB menu file. 219 * grub_menu_fini: 220 * Frees all resources allocated by grub_menu_init(). 221 * 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. 228 * 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). 235 */ 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); 247 248 #ifdef __cplusplus 249 } 250 #endif 251 252 #endif /* _GRBMIMPL_H */ 253