1*753a6d45SSherry Moore /* 2*753a6d45SSherry Moore * CDDL HEADER START 3*753a6d45SSherry Moore * 4*753a6d45SSherry Moore * The contents of this file are subject to the terms of the 5*753a6d45SSherry Moore * Common Development and Distribution License (the "License"). 6*753a6d45SSherry Moore * You may not use this file except in compliance with the License. 7*753a6d45SSherry Moore * 8*753a6d45SSherry Moore * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*753a6d45SSherry Moore * or http://www.opensolaris.org/os/licensing. 10*753a6d45SSherry Moore * See the License for the specific language governing permissions 11*753a6d45SSherry Moore * and limitations under the License. 12*753a6d45SSherry Moore * 13*753a6d45SSherry Moore * When distributing Covered Code, include this CDDL HEADER in each 14*753a6d45SSherry Moore * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*753a6d45SSherry Moore * If applicable, add the following below this CDDL HEADER, with the 16*753a6d45SSherry Moore * fields enclosed by brackets "[]" replaced with your own identifying 17*753a6d45SSherry Moore * information: Portions Copyright [yyyy] [name of copyright owner] 18*753a6d45SSherry Moore * 19*753a6d45SSherry Moore * CDDL HEADER END 20*753a6d45SSherry Moore */ 21*753a6d45SSherry Moore /* 22*753a6d45SSherry Moore * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23*753a6d45SSherry Moore * Use is subject to license terms. 24*753a6d45SSherry Moore */ 25*753a6d45SSherry Moore 26*753a6d45SSherry Moore /* 27*753a6d45SSherry Moore * This file contains all the functions that get/set fields 28*753a6d45SSherry Moore * in a GRUB menu entry. 29*753a6d45SSherry Moore */ 30*753a6d45SSherry Moore #include <stdio.h> 31*753a6d45SSherry Moore #include <errno.h> 32*753a6d45SSherry Moore #include <stdlib.h> 33*753a6d45SSherry Moore #include <strings.h> 34*753a6d45SSherry Moore #include <unistd.h> 35*753a6d45SSherry Moore #include <sys/types.h> 36*753a6d45SSherry Moore #include <assert.h> 37*753a6d45SSherry Moore #include <ctype.h> 38*753a6d45SSherry Moore 39*753a6d45SSherry Moore #include "libgrub_cmd.def" 40*753a6d45SSherry Moore #include "libgrub_impl.h" 41*753a6d45SSherry Moore 42*753a6d45SSherry Moore typedef int (*barg_parsef_t)(const grub_line_t *, grub_barg_t *); 43*753a6d45SSherry Moore static const barg_parsef_t barg_parse[] = { 44*753a6d45SSherry Moore #define menu_cmd(cmd, num, flag, parsef) parsef, 45*753a6d45SSherry Moore #include "libgrub_cmd.def" 46*753a6d45SSherry Moore }; 47*753a6d45SSherry Moore 48*753a6d45SSherry Moore /* 49*753a6d45SSherry Moore * Remove extra '/', stops at first isspace character. 50*753a6d45SSherry Moore * Return new string length. 51*753a6d45SSherry Moore */ 52*753a6d45SSherry Moore size_t 53*753a6d45SSherry Moore clean_path(char *path) 54*753a6d45SSherry Moore { 55*753a6d45SSherry Moore int i, c; 56*753a6d45SSherry Moore size_t k, n; 57*753a6d45SSherry Moore 58*753a6d45SSherry Moore n = strlen(path) + 1; 59*753a6d45SSherry Moore 60*753a6d45SSherry Moore for (i = 0; (c = path[i]) != 0 && !isspace(c); i++) { 61*753a6d45SSherry Moore if (c == '/' && (k = strspn(path + i, "/") - 1) != 0) { 62*753a6d45SSherry Moore /* bcopy should deal with overlapping buffers */ 63*753a6d45SSherry Moore n -= k; 64*753a6d45SSherry Moore bcopy(path + i + k, path + i, n - i); 65*753a6d45SSherry Moore } 66*753a6d45SSherry Moore } 67*753a6d45SSherry Moore return (n - 1); 68*753a6d45SSherry Moore } 69*753a6d45SSherry Moore 70*753a6d45SSherry Moore /* 71*753a6d45SSherry Moore * Construct boot command line from the ge_barg field 72*753a6d45SSherry Moore */ 73*753a6d45SSherry Moore static size_t 74*753a6d45SSherry Moore barg_cmdline(const grub_barg_t *barg, char *cmd, size_t size) 75*753a6d45SSherry Moore { 76*753a6d45SSherry Moore size_t n; 77*753a6d45SSherry Moore const grub_fsdesc_t *fsd; 78*753a6d45SSherry Moore 79*753a6d45SSherry Moore if (!IS_BARG_VALID(barg) || 80*753a6d45SSherry Moore (fsd = grub_get_rootfsd(&barg->gb_root)) == NULL) 81*753a6d45SSherry Moore return ((size_t)-1); 82*753a6d45SSherry Moore 83*753a6d45SSherry Moore /* if disk/top dataset is mounted, use mount point */ 84*753a6d45SSherry Moore if (fsd->gfs_mountp[0] != 0) { 85*753a6d45SSherry Moore if ((n = snprintf(cmd, size, "%s%s", fsd->gfs_mountp, 86*753a6d45SSherry Moore barg->gb_kernel)) >= size) 87*753a6d45SSherry Moore return (n); 88*753a6d45SSherry Moore return (clean_path(cmd)); 89*753a6d45SSherry Moore } else 90*753a6d45SSherry Moore return (snprintf(cmd, size, "%s %s", fsd->gfs_dev, 91*753a6d45SSherry Moore barg->gb_kernel)); 92*753a6d45SSherry Moore } 93*753a6d45SSherry Moore 94*753a6d45SSherry Moore 95*753a6d45SSherry Moore /* 96*753a6d45SSherry Moore * Construct ge_barg field based on the other fields of the entry. 97*753a6d45SSherry Moore * Return 0 on success, errno on failure. 98*753a6d45SSherry Moore */ 99*753a6d45SSherry Moore int 100*753a6d45SSherry Moore grub_entry_construct_barg(grub_entry_t *ent) 101*753a6d45SSherry Moore { 102*753a6d45SSherry Moore int ret = 0; 103*753a6d45SSherry Moore grub_barg_t *barg; 104*753a6d45SSherry Moore grub_line_t *lp, *lend; 105*753a6d45SSherry Moore grub_menu_t *mp; 106*753a6d45SSherry Moore 107*753a6d45SSherry Moore assert(ent); 108*753a6d45SSherry Moore 109*753a6d45SSherry Moore barg = &ent->ge_barg; 110*753a6d45SSherry Moore mp = ent->ge_menu; 111*753a6d45SSherry Moore 112*753a6d45SSherry Moore assert(barg); 113*753a6d45SSherry Moore assert(mp); 114*753a6d45SSherry Moore 115*753a6d45SSherry Moore (void) memset(barg, 0, sizeof (*barg)); 116*753a6d45SSherry Moore barg->gb_entry = ent; 117*753a6d45SSherry Moore (void) bcopy(&mp->gm_root, &barg->gb_root, sizeof (barg->gb_root)); 118*753a6d45SSherry Moore 119*753a6d45SSherry Moore lend = ent->ge_end->gl_next; 120*753a6d45SSherry Moore for (lp = ent->ge_start; lp != lend; lp = lp->gl_next) { 121*753a6d45SSherry Moore if (lp->gl_cmdtp >= GRBM_CMD_NUM) 122*753a6d45SSherry Moore ret = EG_INVALIDCMD; 123*753a6d45SSherry Moore else 124*753a6d45SSherry Moore ret = barg_parse[lp->gl_cmdtp](lp, barg); 125*753a6d45SSherry Moore 126*753a6d45SSherry Moore if (ret != 0) 127*753a6d45SSherry Moore break; 128*753a6d45SSherry Moore } 129*753a6d45SSherry Moore 130*753a6d45SSherry Moore barg->gb_errline = lp; 131*753a6d45SSherry Moore if (ret == 0) { 132*753a6d45SSherry Moore /* at least kernel and module should be defined */ 133*753a6d45SSherry Moore if (barg->gb_kernel[0] != 0 && barg->gb_module[0] != 0) 134*753a6d45SSherry Moore barg->gb_flags |= GRBM_VALID_FLAG; 135*753a6d45SSherry Moore } 136*753a6d45SSherry Moore 137*753a6d45SSherry Moore return (ret); 138*753a6d45SSherry Moore } 139*753a6d45SSherry Moore 140*753a6d45SSherry Moore const char * 141*753a6d45SSherry Moore grub_entry_get_fstyp(const grub_entry_t *ent) 142*753a6d45SSherry Moore { 143*753a6d45SSherry Moore if (IS_ENTRY_BARG_VALID(ent)) 144*753a6d45SSherry Moore return (ent->ge_barg.gb_root.gr_fstyp); 145*753a6d45SSherry Moore else 146*753a6d45SSherry Moore return (NULL); 147*753a6d45SSherry Moore } 148*753a6d45SSherry Moore 149*753a6d45SSherry Moore const char * 150*753a6d45SSherry Moore grub_entry_get_kernel(const grub_entry_t *ent) 151*753a6d45SSherry Moore { 152*753a6d45SSherry Moore if (IS_ENTRY_BARG_VALID(ent)) 153*753a6d45SSherry Moore return (ent->ge_barg.gb_kernel); 154*753a6d45SSherry Moore else 155*753a6d45SSherry Moore return (NULL); 156*753a6d45SSherry Moore } 157*753a6d45SSherry Moore 158*753a6d45SSherry Moore const char * 159*753a6d45SSherry Moore grub_entry_get_module(const grub_entry_t *ent) 160*753a6d45SSherry Moore { 161*753a6d45SSherry Moore if (IS_ENTRY_BARG_VALID(ent)) 162*753a6d45SSherry Moore return (ent->ge_barg.gb_module); 163*753a6d45SSherry Moore else 164*753a6d45SSherry Moore return (NULL); 165*753a6d45SSherry Moore } 166*753a6d45SSherry Moore 167*753a6d45SSherry Moore const char * 168*753a6d45SSherry Moore grub_entry_get_error_desc(const grub_entry_t *ent) 169*753a6d45SSherry Moore { 170*753a6d45SSherry Moore assert(ent != NULL); 171*753a6d45SSherry Moore return ("Not implemented"); 172*753a6d45SSherry Moore } 173*753a6d45SSherry Moore 174*753a6d45SSherry Moore const grub_fsdesc_t * 175*753a6d45SSherry Moore grub_entry_get_rootfs(const grub_entry_t *ent) 176*753a6d45SSherry Moore { 177*753a6d45SSherry Moore if (IS_ENTRY_BARG_VALID(ent)) 178*753a6d45SSherry Moore return (grub_get_rootfsd(&ent->ge_barg.gb_root)); 179*753a6d45SSherry Moore else 180*753a6d45SSherry Moore return (NULL); 181*753a6d45SSherry Moore } 182*753a6d45SSherry Moore 183*753a6d45SSherry Moore size_t 184*753a6d45SSherry Moore grub_entry_get_cmdline(grub_entry_t *ent, char *cmdline, size_t size) 185*753a6d45SSherry Moore { 186*753a6d45SSherry Moore if (IS_ENTRY_VALID(ent) && (grub_entry_construct_barg(ent) == 0)) 187*753a6d45SSherry Moore return (barg_cmdline(&ent->ge_barg, cmdline, size)); 188*753a6d45SSherry Moore else 189*753a6d45SSherry Moore return ((size_t)-1); 190*753a6d45SSherry Moore 191*753a6d45SSherry Moore } 192