xref: /illumos-gate/usr/src/cmd/luxadm/setboot.c (revision fcf3ce441efd61da9bb2884968af01cb7c1452cc)
1*fcf3ce44SJohn Forte /*
2*fcf3ce44SJohn Forte  * CDDL HEADER START
3*fcf3ce44SJohn Forte  *
4*fcf3ce44SJohn Forte  * The contents of this file are subject to the terms of the
5*fcf3ce44SJohn Forte  * Common Development and Distribution License (the "License").
6*fcf3ce44SJohn Forte  * You may not use this file except in compliance with the License.
7*fcf3ce44SJohn Forte  *
8*fcf3ce44SJohn Forte  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*fcf3ce44SJohn Forte  * or http://www.opensolaris.org/os/licensing.
10*fcf3ce44SJohn Forte  * See the License for the specific language governing permissions
11*fcf3ce44SJohn Forte  * and limitations under the License.
12*fcf3ce44SJohn Forte  *
13*fcf3ce44SJohn Forte  * When distributing Covered Code, include this CDDL HEADER in each
14*fcf3ce44SJohn Forte  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*fcf3ce44SJohn Forte  * If applicable, add the following below this CDDL HEADER, with the
16*fcf3ce44SJohn Forte  * fields enclosed by brackets "[]" replaced with your own identifying
17*fcf3ce44SJohn Forte  * information: Portions Copyright [yyyy] [name of copyright owner]
18*fcf3ce44SJohn Forte  *
19*fcf3ce44SJohn Forte  * CDDL HEADER END
20*fcf3ce44SJohn Forte  */
21*fcf3ce44SJohn Forte /*
22*fcf3ce44SJohn Forte  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23*fcf3ce44SJohn Forte  * Use is subject to license terms.
24*fcf3ce44SJohn Forte  */
25*fcf3ce44SJohn Forte 
26*fcf3ce44SJohn Forte /*
27*fcf3ce44SJohn Forte  * I18N message number ranges
28*fcf3ce44SJohn Forte  *  This file: 6000 - 6499
29*fcf3ce44SJohn Forte  *  Shared common messages: 1 - 1999
30*fcf3ce44SJohn Forte  */
31*fcf3ce44SJohn Forte 
32*fcf3ce44SJohn Forte 
33*fcf3ce44SJohn Forte 
34*fcf3ce44SJohn Forte #include <stdio.h>
35*fcf3ce44SJohn Forte #include <unistd.h>
36*fcf3ce44SJohn Forte #include <stdlib.h>
37*fcf3ce44SJohn Forte #include <string.h>
38*fcf3ce44SJohn Forte #include <fcntl.h>
39*fcf3ce44SJohn Forte #include <errno.h>
40*fcf3ce44SJohn Forte #include <sys/param.h>
41*fcf3ce44SJohn Forte #include <sys/mnttab.h>
42*fcf3ce44SJohn Forte #include <sys/types.h>
43*fcf3ce44SJohn Forte #include <sys/stat.h>
44*fcf3ce44SJohn Forte #include <sys/openpromio.h>
45*fcf3ce44SJohn Forte 
46*fcf3ce44SJohn Forte 
47*fcf3ce44SJohn Forte /*
48*fcf3ce44SJohn Forte  * For i18n
49*fcf3ce44SJohn Forte  */
50*fcf3ce44SJohn Forte #include <stgcom.h>
51*fcf3ce44SJohn Forte 
52*fcf3ce44SJohn Forte 
53*fcf3ce44SJohn Forte /*
54*fcf3ce44SJohn Forte  * 128 is the size of the largest (currently) property name
55*fcf3ce44SJohn Forte  * 8192 - MAXPROPSIZE - sizeof (int) is the size of the largest
56*fcf3ce44SJohn Forte  * (currently) property value, viz. nvramrc.
57*fcf3ce44SJohn Forte  * the sizeof(uint_t) is from struct openpromio
58*fcf3ce44SJohn Forte  */
59*fcf3ce44SJohn Forte #define	MAXPROPSIZE		128
60*fcf3ce44SJohn Forte #define	MAXVALSIZE		(8192 - MAXPROPSIZE - sizeof (uint_t))
61*fcf3ce44SJohn Forte 
62*fcf3ce44SJohn Forte #define	BOOTDEV_PROP_NAME	"boot-device"
63*fcf3ce44SJohn Forte 
64*fcf3ce44SJohn Forte static int getbootdevname(char *, char *);
65*fcf3ce44SJohn Forte static int setprom(unsigned, unsigned, char *);
66*fcf3ce44SJohn Forte extern int devfs_dev_to_prom_name(char *, char *);
67*fcf3ce44SJohn Forte 
68*fcf3ce44SJohn Forte /*
69*fcf3ce44SJohn Forte  * Call getbootdevname() to get the absolute pathname of boot device
70*fcf3ce44SJohn Forte  * and call setprom() to set the boot-device variable.
71*fcf3ce44SJohn Forte  */
72*fcf3ce44SJohn Forte int
setboot(unsigned int yes,unsigned int verbose,char * fname)73*fcf3ce44SJohn Forte setboot(unsigned int yes, unsigned int verbose, char *fname)
74*fcf3ce44SJohn Forte {
75*fcf3ce44SJohn Forte 	char	bdev[MAXPATHLEN];
76*fcf3ce44SJohn Forte 
77*fcf3ce44SJohn Forte 	if (!getbootdevname(fname, bdev)) {
78*fcf3ce44SJohn Forte 		(void) fprintf(stderr, MSGSTR(6000,
79*fcf3ce44SJohn Forte 			"Cannot determine device name for %s\n"),
80*fcf3ce44SJohn Forte 			fname);
81*fcf3ce44SJohn Forte 		return (errno);
82*fcf3ce44SJohn Forte 	}
83*fcf3ce44SJohn Forte 
84*fcf3ce44SJohn Forte 	return (setprom(yes, verbose, bdev));
85*fcf3ce44SJohn Forte }
86*fcf3ce44SJohn Forte 
87*fcf3ce44SJohn Forte /*
88*fcf3ce44SJohn Forte  * Read the mnttab and resolve the special device of the fs we are
89*fcf3ce44SJohn Forte  * interested in, into an absolute pathname
90*fcf3ce44SJohn Forte  */
91*fcf3ce44SJohn Forte static int
getbootdevname(char * bootfs,char * bdev)92*fcf3ce44SJohn Forte getbootdevname(char *bootfs, char *bdev)
93*fcf3ce44SJohn Forte {
94*fcf3ce44SJohn Forte 	FILE *f;
95*fcf3ce44SJohn Forte 	char *fname;
96*fcf3ce44SJohn Forte 	char *devname;
97*fcf3ce44SJohn Forte 	struct mnttab m;
98*fcf3ce44SJohn Forte 	struct stat sbuf;
99*fcf3ce44SJohn Forte 	int mountpt = 0;
100*fcf3ce44SJohn Forte 	int found = 0;
101*fcf3ce44SJohn Forte 
102*fcf3ce44SJohn Forte 	devname = bootfs;
103*fcf3ce44SJohn Forte 
104*fcf3ce44SJohn Forte 	if (stat(bootfs, &sbuf) < 0) {
105*fcf3ce44SJohn Forte 		perror(MSGSTR(6001, "stat"));
106*fcf3ce44SJohn Forte 		return (0);
107*fcf3ce44SJohn Forte 	}
108*fcf3ce44SJohn Forte 
109*fcf3ce44SJohn Forte 	switch (sbuf.st_mode & S_IFMT) {
110*fcf3ce44SJohn Forte 		case S_IFBLK:
111*fcf3ce44SJohn Forte 			break;
112*fcf3ce44SJohn Forte 		default:
113*fcf3ce44SJohn Forte 			mountpt = 1;
114*fcf3ce44SJohn Forte 			break;
115*fcf3ce44SJohn Forte 	}
116*fcf3ce44SJohn Forte 
117*fcf3ce44SJohn Forte 	if (mountpt) {
118*fcf3ce44SJohn Forte 		fname = MNTTAB;
119*fcf3ce44SJohn Forte 		f = fopen(fname, "r");
120*fcf3ce44SJohn Forte 		if (f == NULL) {
121*fcf3ce44SJohn Forte 			perror(fname);
122*fcf3ce44SJohn Forte 			return (0);
123*fcf3ce44SJohn Forte 		}
124*fcf3ce44SJohn Forte 
125*fcf3ce44SJohn Forte 		while (getmntent(f, &m) == 0) {
126*fcf3ce44SJohn Forte 			if (strcmp(m.mnt_mountp, bootfs))
127*fcf3ce44SJohn Forte 				continue;
128*fcf3ce44SJohn Forte 			else {
129*fcf3ce44SJohn Forte 				found = 1;
130*fcf3ce44SJohn Forte 				break;
131*fcf3ce44SJohn Forte 			}
132*fcf3ce44SJohn Forte 		}
133*fcf3ce44SJohn Forte 
134*fcf3ce44SJohn Forte 		(void) fclose(f);
135*fcf3ce44SJohn Forte 
136*fcf3ce44SJohn Forte 		if (!found) {
137*fcf3ce44SJohn Forte 			return (0);
138*fcf3ce44SJohn Forte 		}
139*fcf3ce44SJohn Forte 		devname = m.mnt_special;
140*fcf3ce44SJohn Forte 	}
141*fcf3ce44SJohn Forte 
142*fcf3ce44SJohn Forte 	if (devfs_dev_to_prom_name(devname, bdev) != 0) {
143*fcf3ce44SJohn Forte 		perror(devname);
144*fcf3ce44SJohn Forte 		return (0);
145*fcf3ce44SJohn Forte 	}
146*fcf3ce44SJohn Forte 
147*fcf3ce44SJohn Forte 	return (1);
148*fcf3ce44SJohn Forte }
149*fcf3ce44SJohn Forte 
150*fcf3ce44SJohn Forte /*
151*fcf3ce44SJohn Forte  * setprom() - use /dev/openprom to read the "boot_device" variable and set
152*fcf3ce44SJohn Forte  * it to the new value.
153*fcf3ce44SJohn Forte  */
154*fcf3ce44SJohn Forte static int
setprom(unsigned yes,unsigned verbose,char * bdev)155*fcf3ce44SJohn Forte setprom(unsigned yes, unsigned verbose, char *bdev)
156*fcf3ce44SJohn Forte {
157*fcf3ce44SJohn Forte 	struct openpromio	*pio;
158*fcf3ce44SJohn Forte 	int			fd;
159*fcf3ce44SJohn Forte 	char			save_bootdev[MAXVALSIZE];
160*fcf3ce44SJohn Forte 
161*fcf3ce44SJohn Forte 	if ((fd = open("/dev/openprom", O_RDWR)) < 0) {
162*fcf3ce44SJohn Forte 		perror(MSGSTR(6002, "Could not open openprom dev"));
163*fcf3ce44SJohn Forte 		return (errno);
164*fcf3ce44SJohn Forte 	}
165*fcf3ce44SJohn Forte 
166*fcf3ce44SJohn Forte 	pio = (struct openpromio *)malloc(sizeof (struct openpromio) +
167*fcf3ce44SJohn Forte 					MAXVALSIZE + MAXPROPSIZE);
168*fcf3ce44SJohn Forte 
169*fcf3ce44SJohn Forte 	if (pio == (struct openpromio *)NULL) {
170*fcf3ce44SJohn Forte 		perror(MSGSTR(6003, " Error: Unable to allocate memory."));
171*fcf3ce44SJohn Forte 		return (errno);
172*fcf3ce44SJohn Forte 	}
173*fcf3ce44SJohn Forte 
174*fcf3ce44SJohn Forte 	pio->oprom_size = MAXVALSIZE;
175*fcf3ce44SJohn Forte 	(void) strcpy(pio->oprom_array, BOOTDEV_PROP_NAME);
176*fcf3ce44SJohn Forte 
177*fcf3ce44SJohn Forte 	if (ioctl(fd, OPROMGETOPT, pio) < 0) {
178*fcf3ce44SJohn Forte 		perror(MSGSTR(6004, "openprom getopt ioctl"));
179*fcf3ce44SJohn Forte 		return (errno);
180*fcf3ce44SJohn Forte 	}
181*fcf3ce44SJohn Forte 
182*fcf3ce44SJohn Forte 	/*
183*fcf3ce44SJohn Forte 	 * save the existing boot-device, so we can use it if setting
184*fcf3ce44SJohn Forte 	 * to new value fails.
185*fcf3ce44SJohn Forte 	 */
186*fcf3ce44SJohn Forte 	(void) strcpy(save_bootdev, pio->oprom_array);
187*fcf3ce44SJohn Forte 
188*fcf3ce44SJohn Forte 	if (verbose) {
189*fcf3ce44SJohn Forte 		(void) fprintf(stdout,
190*fcf3ce44SJohn Forte 			MSGSTR(6005,
191*fcf3ce44SJohn Forte 			"Current boot-device = %s\n"), pio->oprom_array);
192*fcf3ce44SJohn Forte 		(void) fprintf(stdout, MSGSTR(6006,
193*fcf3ce44SJohn Forte 			"New boot-device = %s\n"), bdev);
194*fcf3ce44SJohn Forte 	}
195*fcf3ce44SJohn Forte 
196*fcf3ce44SJohn Forte 	if (!yes) {
197*fcf3ce44SJohn Forte 		(void) fprintf(stdout, MSGSTR(6007,
198*fcf3ce44SJohn Forte 			"Do you want to change boot-device "
199*fcf3ce44SJohn Forte 			"to the new setting? (y/n) "));
200*fcf3ce44SJohn Forte 		switch (getchar()) {
201*fcf3ce44SJohn Forte 			case 'Y':
202*fcf3ce44SJohn Forte 			case 'y':
203*fcf3ce44SJohn Forte 				break;
204*fcf3ce44SJohn Forte 			default:
205*fcf3ce44SJohn Forte 				return (0);
206*fcf3ce44SJohn Forte 		}
207*fcf3ce44SJohn Forte 	}
208*fcf3ce44SJohn Forte 
209*fcf3ce44SJohn Forte 	/* set the new value for boot-device */
210*fcf3ce44SJohn Forte 
211*fcf3ce44SJohn Forte 	pio->oprom_size = (int)strlen(BOOTDEV_PROP_NAME) + 1 +
212*fcf3ce44SJohn Forte 				(int)strlen(bdev);
213*fcf3ce44SJohn Forte 
214*fcf3ce44SJohn Forte 	(void) strcpy(pio->oprom_array, BOOTDEV_PROP_NAME);
215*fcf3ce44SJohn Forte 	(void) strcpy(pio->oprom_array + (int)strlen(BOOTDEV_PROP_NAME) + 1,
216*fcf3ce44SJohn Forte 					bdev);
217*fcf3ce44SJohn Forte 
218*fcf3ce44SJohn Forte 	if (ioctl(fd, OPROMSETOPT, pio) < 0) {
219*fcf3ce44SJohn Forte 		perror(MSGSTR(6008, "openprom setopt ioctl"));
220*fcf3ce44SJohn Forte 		return (errno);
221*fcf3ce44SJohn Forte 	}
222*fcf3ce44SJohn Forte 
223*fcf3ce44SJohn Forte 	/* read back the value that was set */
224*fcf3ce44SJohn Forte 
225*fcf3ce44SJohn Forte 	pio->oprom_size = MAXVALSIZE;
226*fcf3ce44SJohn Forte 	(void) strcpy(pio->oprom_array, BOOTDEV_PROP_NAME);
227*fcf3ce44SJohn Forte 
228*fcf3ce44SJohn Forte 	if (ioctl(fd, OPROMGETOPT, pio) < 0) {
229*fcf3ce44SJohn Forte 		perror(MSGSTR(6009, "openprom getopt ioctl"));
230*fcf3ce44SJohn Forte 		return (errno);
231*fcf3ce44SJohn Forte 	}
232*fcf3ce44SJohn Forte 
233*fcf3ce44SJohn Forte 	if (strcmp(bdev, pio->oprom_array)) {
234*fcf3ce44SJohn Forte 
235*fcf3ce44SJohn Forte 		/* could not  set the new device name, set the old one back */
236*fcf3ce44SJohn Forte 
237*fcf3ce44SJohn Forte 		perror(MSGSTR(6010,
238*fcf3ce44SJohn Forte 			"Could not set boot-device, reverting to old value"));
239*fcf3ce44SJohn Forte 		pio->oprom_size = (int)strlen(BOOTDEV_PROP_NAME) + 1 +
240*fcf3ce44SJohn Forte 			(int)strlen(save_bootdev);
241*fcf3ce44SJohn Forte 
242*fcf3ce44SJohn Forte 		(void) strcpy(pio->oprom_array, BOOTDEV_PROP_NAME);
243*fcf3ce44SJohn Forte 			(void) strcpy(pio->oprom_array +
244*fcf3ce44SJohn Forte 				(int)strlen(BOOTDEV_PROP_NAME) + 1,
245*fcf3ce44SJohn Forte 				save_bootdev);
246*fcf3ce44SJohn Forte 
247*fcf3ce44SJohn Forte 		if (ioctl(fd, OPROMSETOPT, pio) < 0) {
248*fcf3ce44SJohn Forte 			perror(MSGSTR(6011, "openprom setopt ioctl"));
249*fcf3ce44SJohn Forte 			return (errno);
250*fcf3ce44SJohn Forte 		}
251*fcf3ce44SJohn Forte 
252*fcf3ce44SJohn Forte 	}
253*fcf3ce44SJohn Forte 
254*fcf3ce44SJohn Forte 	(void) close(fd);
255*fcf3ce44SJohn Forte 
256*fcf3ce44SJohn Forte 	return (0);
257*fcf3ce44SJohn Forte }
258