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 30 extern "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 72 enum { 73 #define menu_cmd(cmd, num, flags, parsef) num, 74 #define menu_cmd_end(num) num 75 #include "libgrub_cmd.def" 76 }; 77 78 typedef 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 85 typedef 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 92 enum { 93 GRBM_UFS = 0, 94 GRBM_ZFS_TOPFS = 0, 95 GRBM_FS_TOP = 0, 96 GRBM_ZFS_BOOTFS, 97 GRBM_FS_MAX 98 }; 99 100 typedef 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 */ 109 typedef 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 */ 124 enum { 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 */ 136 struct 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 150 struct 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 162 struct 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 */ 177 int grub_current_root(grub_fs_t *, grub_root_t *); 178 grub_fsdesc_t *grub_get_rootfsd(const grub_root_t *); 179 int grub_fsd_mount_tmp(grub_fsdesc_t *, const char *); 180 void grub_fsd_umount_tmp(grub_fsdesc_t *); 181 int grub_fsd_get_mountp(grub_fsdesc_t *fsd, char *fstyp); 182 int grub_find_bootsign(grub_barg_t *barg); 183 184 185 /* GRUB menu parse functions */ 186 int skip_line(const grub_line_t *lp, grub_barg_t *barg); 187 int error_line(const grub_line_t *lp, grub_barg_t *barg); 188 int kernel(const grub_line_t *lp, grub_barg_t *barg); 189 int module(const grub_line_t *lp, grub_barg_t *barg); 190 int dollar_kernel(const grub_line_t *lp, grub_barg_t *barg); 191 int dollar_module(const grub_line_t *lp, grub_barg_t *barg); 192 int findroot(const grub_line_t *lp, grub_barg_t *barg); 193 int bootfs(const grub_line_t *lp, grub_barg_t *barg); 194 size_t clean_path(char *path); 195 196 197 /* GRUB entry functions */ 198 int grub_entry_construct_barg(grub_entry_t *ent); 199 const char *grub_entry_get_fstyp(const grub_entry_t *ent); 200 const char *grub_entry_get_kernel(const grub_entry_t *ent); 201 const char *grub_entry_get_module(const grub_entry_t *ent); 202 const grub_fsdesc_t *grub_entry_get_rootfs(const grub_entry_t *ent); 203 size_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 */ 232 int grub_menu_init(const char *grub_menu_path, grub_menu_t **menup); 233 void grub_menu_fini(grub_menu_t *); 234 grub_entry_t *grub_menu_get_entry(const grub_menu_t *menu, int num); 235 grub_entry_t *grub_menu_next_entry(const grub_menu_t *menu, 236 const grub_entry_t *current); 237 grub_entry_t *grub_menu_prev_entry(const grub_menu_t *menu, 238 const grub_entry_t *current); 239 grub_line_t *grub_menu_next_line(const grub_menu_t *menu, 240 const grub_line_t *current); 241 grub_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