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 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 28 /* 29 * Wrapper function to implement reboot w/ arguments on x86 30 * platforms. Extract reboot arguments and place them in 31 * in a transient entry in /[stub]boot/grub/menu.lst 32 * All other commands are passed through. 33 */ 34 35 #include "lint.h" 36 #include <fcntl.h> 37 #include <ctype.h> 38 #include <stdio.h> 39 #include <stdlib.h> 40 #include <sys/types.h> 41 #include <sys/stat.h> 42 #include <sys/uadmin.h> 43 #include <unistd.h> 44 #include <strings.h> 45 #include <pthread.h> 46 #include <zone.h> 47 #include <libscf.h> 48 49 static int 50 legal_arg(char *bargs) 51 { 52 int i; 53 54 for (i = 0; i < BOOTARGS_MAX; i++, bargs++) { 55 if (*bargs == 0 && i > 0) 56 return (i); 57 if (!isprint(*bargs)) 58 break; 59 } 60 return (-1); 61 } 62 63 static char quote[] = "\'"; 64 65 int 66 uadmin(int cmd, int fcn, uintptr_t mdep) 67 { 68 extern int __uadmin(int cmd, int fcn, uintptr_t mdep); 69 char *bargs, cmdbuf[256]; 70 struct stat sbuf; 71 char *altroot; 72 scf_simple_prop_t *prop = NULL; 73 uint8_t *ret_val = NULL; 74 boolean_t update_flag = B_FALSE; 75 char *fmri = "svc:/system/boot-config:default"; 76 77 bargs = (char *)mdep; 78 79 if (geteuid() == 0 && getzoneid() == GLOBAL_ZONEID && 80 (cmd == A_SHUTDOWN || cmd == A_REBOOT)) { 81 int off = 0; 82 83 switch (fcn) { 84 case AD_IBOOT: 85 case AD_SBOOT: 86 case AD_SIBOOT: 87 /* 88 * These functions fabricate appropriate bootargs. 89 * If bootargs are passed in, map these functions 90 * to AD_BOOT. 91 */ 92 if (bargs == 0) { 93 switch (fcn) { 94 case AD_IBOOT: 95 bargs = "-a"; 96 break; 97 case AD_SBOOT: 98 bargs = "-s"; 99 break; 100 case AD_SIBOOT: 101 bargs = "-sa"; 102 break; 103 } 104 } 105 /*FALLTHROUGH*/ 106 case AD_BOOT: 107 case AD_FASTREBOOT: 108 if (bargs == 0) 109 break; /* no args */ 110 if (legal_arg(bargs) < 0) 111 break; /* bad args */ 112 113 /* avoid cancellation in system() */ 114 (void) pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, 115 NULL); 116 117 /* check for /stubboot */ 118 if (stat("/stubboot/boot/grub/menu.lst", &sbuf) == 0) { 119 altroot = "-R /stubboot "; 120 } else { 121 altroot = ""; 122 } 123 124 if (fcn == AD_FASTREBOOT) { 125 char *newarg, *head; 126 char bargs_scratch[BOOTARGS_MAX]; 127 128 bzero(bargs_scratch, BOOTARGS_MAX); 129 130 bcopy(bargs, bargs_scratch, strlen(bargs)); 131 head = bargs_scratch; 132 newarg = strtok(bargs_scratch, " "); 133 134 if (newarg == NULL || newarg[0] == '-') 135 break; 136 137 /* First argument is rootdir */ 138 if (strncmp(&newarg[strlen(newarg)-4], 139 "unix", 4) != 0) { 140 newarg = strtok(NULL, " "); 141 off = newarg - head; 142 } 143 144 /* 145 * If we are using alternate root via 146 * mountpoint or a different BE, don't 147 * bother to update the temp menu entry. 148 */ 149 if (off > 0) 150 break; 151 } 152 153 /* are we rebooting to a GRUB menu entry? */ 154 if (isdigit(bargs[0])) { 155 int entry = strtol(bargs, NULL, 10); 156 (void) snprintf(cmdbuf, sizeof (cmdbuf), 157 "/sbin/bootadm set-menu %sdefault=%d", 158 altroot, entry); 159 } else { 160 (void) snprintf(cmdbuf, sizeof (cmdbuf), 161 "/sbin/bootadm -m update_temp %s" 162 "-o %s%s%s", altroot, quote, 163 &bargs[off], quote); 164 } 165 (void) system(cmdbuf); 166 } 167 168 prop = scf_simple_prop_get(NULL, fmri, "config", 169 "uadmin_boot_archive_sync"); 170 if (prop) { 171 if ((ret_val = scf_simple_prop_next_boolean(prop)) != 172 NULL) 173 update_flag = (*ret_val == 0) ? B_FALSE : 174 B_TRUE; 175 scf_simple_prop_free(prop); 176 } 177 if (update_flag == B_TRUE) 178 (void) system("/sbin/bootadm update-archive"); 179 } 180 181 return (__uadmin(cmd, fcn, mdep)); 182 } 183