1*e7cbe64fSgw25295 /* 2*e7cbe64fSgw25295 * CDDL HEADER START 3*e7cbe64fSgw25295 * 4*e7cbe64fSgw25295 * The contents of this file are subject to the terms of the 5*e7cbe64fSgw25295 * Common Development and Distribution License (the "License"). 6*e7cbe64fSgw25295 * You may not use this file except in compliance with the License. 7*e7cbe64fSgw25295 * 8*e7cbe64fSgw25295 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*e7cbe64fSgw25295 * or http://www.opensolaris.org/os/licensing. 10*e7cbe64fSgw25295 * See the License for the specific language governing permissions 11*e7cbe64fSgw25295 * and limitations under the License. 12*e7cbe64fSgw25295 * 13*e7cbe64fSgw25295 * When distributing Covered Code, include this CDDL HEADER in each 14*e7cbe64fSgw25295 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*e7cbe64fSgw25295 * If applicable, add the following below this CDDL HEADER, with the 16*e7cbe64fSgw25295 * fields enclosed by brackets "[]" replaced with your own identifying 17*e7cbe64fSgw25295 * information: Portions Copyright [yyyy] [name of copyright owner] 18*e7cbe64fSgw25295 * 19*e7cbe64fSgw25295 * CDDL HEADER END 20*e7cbe64fSgw25295 */ 21*e7cbe64fSgw25295 /* 22*e7cbe64fSgw25295 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23*e7cbe64fSgw25295 * Use is subject to license terms. 24*e7cbe64fSgw25295 */ 25*e7cbe64fSgw25295 #pragma ident "%Z%%M% %I% %E% SMI" 26*e7cbe64fSgw25295 27*e7cbe64fSgw25295 #include <sys/promif.h> 28*e7cbe64fSgw25295 #include <sys/salib.h> 29*e7cbe64fSgw25295 30*e7cbe64fSgw25295 #define MAX_CMDLINE 1600 /* from GRUB source */ 31*e7cbe64fSgw25295 32*e7cbe64fSgw25295 char **titles; 33*e7cbe64fSgw25295 char **datasets; 34*e7cbe64fSgw25295 35*e7cbe64fSgw25295 int menu_entry_count; 36*e7cbe64fSgw25295 int menu_table_size; 37*e7cbe64fSgw25295 38*e7cbe64fSgw25295 int in_menu_entry; 39*e7cbe64fSgw25295 40*e7cbe64fSgw25295 #define ENTRY_ALLOC_COUNT 10 41*e7cbe64fSgw25295 42*e7cbe64fSgw25295 extern void set_default_fs(char *fsw_name); 43*e7cbe64fSgw25295 extern int mountroot(char *str); 44*e7cbe64fSgw25295 45*e7cbe64fSgw25295 void 46*e7cbe64fSgw25295 init_table(void) 47*e7cbe64fSgw25295 { 48*e7cbe64fSgw25295 49*e7cbe64fSgw25295 menu_entry_count = 0; 50*e7cbe64fSgw25295 titles = (char **)calloc(ENTRY_ALLOC_COUNT, sizeof (char *)); 51*e7cbe64fSgw25295 datasets = (char **)calloc(ENTRY_ALLOC_COUNT, sizeof (char *)); 52*e7cbe64fSgw25295 if (titles == NULL || datasets == NULL) 53*e7cbe64fSgw25295 prom_panic("out of mem"); 54*e7cbe64fSgw25295 menu_table_size = ENTRY_ALLOC_COUNT; 55*e7cbe64fSgw25295 in_menu_entry = 0; 56*e7cbe64fSgw25295 } 57*e7cbe64fSgw25295 58*e7cbe64fSgw25295 void 59*e7cbe64fSgw25295 add_title_entry(char *title_str) 60*e7cbe64fSgw25295 { 61*e7cbe64fSgw25295 62*e7cbe64fSgw25295 /* skip leading white space */ 63*e7cbe64fSgw25295 while (isspace(*title_str)) 64*e7cbe64fSgw25295 title_str++; 65*e7cbe64fSgw25295 66*e7cbe64fSgw25295 if (menu_entry_count == menu_table_size) { 67*e7cbe64fSgw25295 printf("Reallocating at count %d\n", menu_table_size); 68*e7cbe64fSgw25295 titles = (char **)realloc(titles, 69*e7cbe64fSgw25295 ENTRY_ALLOC_COUNT * sizeof (char *)); 70*e7cbe64fSgw25295 datasets = (char **)realloc(datasets, 71*e7cbe64fSgw25295 ENTRY_ALLOC_COUNT * sizeof (char *)); 72*e7cbe64fSgw25295 if (titles == NULL || datasets == NULL) 73*e7cbe64fSgw25295 prom_panic("out of mem"); 74*e7cbe64fSgw25295 menu_table_size += ENTRY_ALLOC_COUNT; 75*e7cbe64fSgw25295 } 76*e7cbe64fSgw25295 77*e7cbe64fSgw25295 if (in_menu_entry) 78*e7cbe64fSgw25295 free(titles[menu_entry_count]); 79*e7cbe64fSgw25295 if ((titles[menu_entry_count] = strdup(title_str)) == NULL) 80*e7cbe64fSgw25295 prom_panic("out of mem"); 81*e7cbe64fSgw25295 in_menu_entry = 1; 82*e7cbe64fSgw25295 } 83*e7cbe64fSgw25295 84*e7cbe64fSgw25295 void 85*e7cbe64fSgw25295 add_dataset_entry(char *dataset_str) 86*e7cbe64fSgw25295 { 87*e7cbe64fSgw25295 char *cp; 88*e7cbe64fSgw25295 89*e7cbe64fSgw25295 /* skip leading white space */ 90*e7cbe64fSgw25295 while (isspace(*dataset_str)) 91*e7cbe64fSgw25295 dataset_str++; 92*e7cbe64fSgw25295 93*e7cbe64fSgw25295 /* if there is still any white space in the line, it's invalid */ 94*e7cbe64fSgw25295 for (cp = dataset_str; *cp; cp++) 95*e7cbe64fSgw25295 if (isspace(*cp)) 96*e7cbe64fSgw25295 break; 97*e7cbe64fSgw25295 if (*cp) 98*e7cbe64fSgw25295 return; /* dataset name was invalid */ 99*e7cbe64fSgw25295 100*e7cbe64fSgw25295 if (!in_menu_entry) 101*e7cbe64fSgw25295 return; /* dataset line was not preceded by a title */ 102*e7cbe64fSgw25295 103*e7cbe64fSgw25295 if ((datasets[menu_entry_count] = strdup(dataset_str)) == NULL) 104*e7cbe64fSgw25295 prom_panic("out of mem"); 105*e7cbe64fSgw25295 menu_entry_count++; 106*e7cbe64fSgw25295 in_menu_entry = 0; 107*e7cbe64fSgw25295 } 108*e7cbe64fSgw25295 109*e7cbe64fSgw25295 110*e7cbe64fSgw25295 char * 111*e7cbe64fSgw25295 trim_white_space(char *cp) 112*e7cbe64fSgw25295 { 113*e7cbe64fSgw25295 char *ep; 114*e7cbe64fSgw25295 115*e7cbe64fSgw25295 /* skip leading white space */ 116*e7cbe64fSgw25295 while (isspace(*cp)) 117*e7cbe64fSgw25295 cp++; 118*e7cbe64fSgw25295 119*e7cbe64fSgw25295 /* 120*e7cbe64fSgw25295 * if the string contained nothing but white space, return a 121*e7cbe64fSgw25295 * null string. 122*e7cbe64fSgw25295 */ 123*e7cbe64fSgw25295 if (*cp == '\0') 124*e7cbe64fSgw25295 return (cp); 125*e7cbe64fSgw25295 126*e7cbe64fSgw25295 /* truncate trailing white space */ 127*e7cbe64fSgw25295 for (ep = cp + strlen(cp) - 1; isspace(*ep); ep--) 128*e7cbe64fSgw25295 ; 129*e7cbe64fSgw25295 ep++; 130*e7cbe64fSgw25295 *ep = '\0'; 131*e7cbe64fSgw25295 return (cp); 132*e7cbe64fSgw25295 } 133*e7cbe64fSgw25295 134*e7cbe64fSgw25295 char *cons_gets(char *, int); 135*e7cbe64fSgw25295 136*e7cbe64fSgw25295 void 137*e7cbe64fSgw25295 main(void *cif) 138*e7cbe64fSgw25295 { 139*e7cbe64fSgw25295 char linebuf[MAX_CMDLINE]; 140*e7cbe64fSgw25295 FILE *file; 141*e7cbe64fSgw25295 char *cp, *ep; 142*e7cbe64fSgw25295 int n; 143*e7cbe64fSgw25295 unsigned long choice; 144*e7cbe64fSgw25295 145*e7cbe64fSgw25295 prom_init("bootlst", cif); 146*e7cbe64fSgw25295 set_default_fs("promfs"); 147*e7cbe64fSgw25295 if (mountroot("bootfs") != 0) 148*e7cbe64fSgw25295 prom_panic("can't mount root"); 149*e7cbe64fSgw25295 150*e7cbe64fSgw25295 if ((file = fopen("/boot/menu.lst", "r")) == NULL) 151*e7cbe64fSgw25295 prom_panic("can't open menu.lst"); 152*e7cbe64fSgw25295 init_table(); 153*e7cbe64fSgw25295 154*e7cbe64fSgw25295 while (fgets(linebuf, MAX_CMDLINE, file)) { 155*e7cbe64fSgw25295 cp = trim_white_space(linebuf); 156*e7cbe64fSgw25295 157*e7cbe64fSgw25295 /* skip comments and blank lines */ 158*e7cbe64fSgw25295 if (*cp == '#' || *cp == '\0') 159*e7cbe64fSgw25295 continue; 160*e7cbe64fSgw25295 161*e7cbe64fSgw25295 /* find end of first keyword on line */ 162*e7cbe64fSgw25295 for (ep = cp; !isspace(*ep) && *ep; ep++) 163*e7cbe64fSgw25295 ; 164*e7cbe64fSgw25295 165*e7cbe64fSgw25295 /* if at the end of the line, the line had no arguments */ 166*e7cbe64fSgw25295 if (*ep == '\0') 167*e7cbe64fSgw25295 continue; 168*e7cbe64fSgw25295 169*e7cbe64fSgw25295 *ep = '\0'; 170*e7cbe64fSgw25295 171*e7cbe64fSgw25295 if (strcmp(cp, "title") == 0) { 172*e7cbe64fSgw25295 add_title_entry(ep + 1); 173*e7cbe64fSgw25295 continue; 174*e7cbe64fSgw25295 } 175*e7cbe64fSgw25295 176*e7cbe64fSgw25295 if (strcmp(cp, "bootfs") == 0) { 177*e7cbe64fSgw25295 add_dataset_entry(ep + 1); 178*e7cbe64fSgw25295 continue; 179*e7cbe64fSgw25295 } 180*e7cbe64fSgw25295 } 181*e7cbe64fSgw25295 182*e7cbe64fSgw25295 if (menu_entry_count == 0) 183*e7cbe64fSgw25295 prom_panic("no menu entries found"); 184*e7cbe64fSgw25295 185*e7cbe64fSgw25295 for (n = 0; n < menu_entry_count; n++) { 186*e7cbe64fSgw25295 printf("%d %s\n", n + 1, titles[n]); 187*e7cbe64fSgw25295 } 188*e7cbe64fSgw25295 189*e7cbe64fSgw25295 printf("Select environment to boot: [ 1 - %d ]: ", menu_entry_count); 190*e7cbe64fSgw25295 191*e7cbe64fSgw25295 while (cons_gets(linebuf, MAX_CMDLINE)) { 192*e7cbe64fSgw25295 /* cut off leading and trailing white space */ 193*e7cbe64fSgw25295 cp = trim_white_space(linebuf); 194*e7cbe64fSgw25295 choice = strtoul(cp, NULL, 0); 195*e7cbe64fSgw25295 196*e7cbe64fSgw25295 /* 197*e7cbe64fSgw25295 * If the input is totally invalid, the return value of 198*e7cbe64fSgw25295 * strtoul() will be 0 or ULONG_MAX. Either way, it's 199*e7cbe64fSgw25295 * of the acceptable range. 200*e7cbe64fSgw25295 */ 201*e7cbe64fSgw25295 if (choice == 0 || choice > menu_entry_count) { 202*e7cbe64fSgw25295 printf("Invalid entry.\n"); 203*e7cbe64fSgw25295 continue; 204*e7cbe64fSgw25295 } 205*e7cbe64fSgw25295 /* XXX here is the result */ 206*e7cbe64fSgw25295 printf("\nTo boot the selected entry, invoke:\n"); 207*e7cbe64fSgw25295 printf("boot [<root-device>] -Z %s\n\n", datasets[choice - 1]); 208*e7cbe64fSgw25295 prom_exit_to_mon(); 209*e7cbe64fSgw25295 } 210*e7cbe64fSgw25295 } 211