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