diff options
Diffstat (limited to 'usr/src/cmd/luxadm/setboot.c')
-rw-r--r-- | usr/src/cmd/luxadm/setboot.c | 257 |
1 files changed, 257 insertions, 0 deletions
diff --git a/usr/src/cmd/luxadm/setboot.c b/usr/src/cmd/luxadm/setboot.c new file mode 100644 index 0000000000..909d312111 --- /dev/null +++ b/usr/src/cmd/luxadm/setboot.c @@ -0,0 +1,257 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * I18N message number ranges + * This file: 6000 - 6499 + * Shared common messages: 1 - 1999 + */ + + + +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <fcntl.h> +#include <errno.h> +#include <sys/param.h> +#include <sys/mnttab.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/openpromio.h> + + +/* + * For i18n + */ +#include <stgcom.h> + + +/* + * 128 is the size of the largest (currently) property name + * 8192 - MAXPROPSIZE - sizeof (int) is the size of the largest + * (currently) property value, viz. nvramrc. + * the sizeof(uint_t) is from struct openpromio + */ +#define MAXPROPSIZE 128 +#define MAXVALSIZE (8192 - MAXPROPSIZE - sizeof (uint_t)) + +#define BOOTDEV_PROP_NAME "boot-device" + +static int getbootdevname(char *, char *); +static int setprom(unsigned, unsigned, char *); +extern int devfs_dev_to_prom_name(char *, char *); + +/* + * Call getbootdevname() to get the absolute pathname of boot device + * and call setprom() to set the boot-device variable. + */ +int +setboot(unsigned int yes, unsigned int verbose, char *fname) +{ + char bdev[MAXPATHLEN]; + + if (!getbootdevname(fname, bdev)) { + (void) fprintf(stderr, MSGSTR(6000, + "Cannot determine device name for %s\n"), + fname); + return (errno); + } + + return (setprom(yes, verbose, bdev)); +} + +/* + * Read the mnttab and resolve the special device of the fs we are + * interested in, into an absolute pathname + */ +static int +getbootdevname(char *bootfs, char *bdev) +{ + FILE *f; + char *fname; + char *devname; + struct mnttab m; + struct stat sbuf; + int mountpt = 0; + int found = 0; + + devname = bootfs; + + if (stat(bootfs, &sbuf) < 0) { + perror(MSGSTR(6001, "stat")); + return (0); + } + + switch (sbuf.st_mode & S_IFMT) { + case S_IFBLK: + break; + default: + mountpt = 1; + break; + } + + if (mountpt) { + fname = MNTTAB; + f = fopen(fname, "r"); + if (f == NULL) { + perror(fname); + return (0); + } + + while (getmntent(f, &m) == 0) { + if (strcmp(m.mnt_mountp, bootfs)) + continue; + else { + found = 1; + break; + } + } + + (void) fclose(f); + + if (!found) { + return (0); + } + devname = m.mnt_special; + } + + if (devfs_dev_to_prom_name(devname, bdev) != 0) { + perror(devname); + return (0); + } + + return (1); +} + +/* + * setprom() - use /dev/openprom to read the "boot_device" variable and set + * it to the new value. + */ +static int +setprom(unsigned yes, unsigned verbose, char *bdev) +{ + struct openpromio *pio; + int fd; + char save_bootdev[MAXVALSIZE]; + + if ((fd = open("/dev/openprom", O_RDWR)) < 0) { + perror(MSGSTR(6002, "Could not open openprom dev")); + return (errno); + } + + pio = (struct openpromio *)malloc(sizeof (struct openpromio) + + MAXVALSIZE + MAXPROPSIZE); + + if (pio == (struct openpromio *)NULL) { + perror(MSGSTR(6003, " Error: Unable to allocate memory.")); + return (errno); + } + + pio->oprom_size = MAXVALSIZE; + (void) strcpy(pio->oprom_array, BOOTDEV_PROP_NAME); + + if (ioctl(fd, OPROMGETOPT, pio) < 0) { + perror(MSGSTR(6004, "openprom getopt ioctl")); + return (errno); + } + + /* + * save the existing boot-device, so we can use it if setting + * to new value fails. + */ + (void) strcpy(save_bootdev, pio->oprom_array); + + if (verbose) { + (void) fprintf(stdout, + MSGSTR(6005, + "Current boot-device = %s\n"), pio->oprom_array); + (void) fprintf(stdout, MSGSTR(6006, + "New boot-device = %s\n"), bdev); + } + + if (!yes) { + (void) fprintf(stdout, MSGSTR(6007, + "Do you want to change boot-device " + "to the new setting? (y/n) ")); + switch (getchar()) { + case 'Y': + case 'y': + break; + default: + return (0); + } + } + + /* set the new value for boot-device */ + + pio->oprom_size = (int)strlen(BOOTDEV_PROP_NAME) + 1 + + (int)strlen(bdev); + + (void) strcpy(pio->oprom_array, BOOTDEV_PROP_NAME); + (void) strcpy(pio->oprom_array + (int)strlen(BOOTDEV_PROP_NAME) + 1, + bdev); + + if (ioctl(fd, OPROMSETOPT, pio) < 0) { + perror(MSGSTR(6008, "openprom setopt ioctl")); + return (errno); + } + + /* read back the value that was set */ + + pio->oprom_size = MAXVALSIZE; + (void) strcpy(pio->oprom_array, BOOTDEV_PROP_NAME); + + if (ioctl(fd, OPROMGETOPT, pio) < 0) { + perror(MSGSTR(6009, "openprom getopt ioctl")); + return (errno); + } + + if (strcmp(bdev, pio->oprom_array)) { + + /* could not set the new device name, set the old one back */ + + perror(MSGSTR(6010, + "Could not set boot-device, reverting to old value")); + pio->oprom_size = (int)strlen(BOOTDEV_PROP_NAME) + 1 + + (int)strlen(save_bootdev); + + (void) strcpy(pio->oprom_array, BOOTDEV_PROP_NAME); + (void) strcpy(pio->oprom_array + + (int)strlen(BOOTDEV_PROP_NAME) + 1, + save_bootdev); + + if (ioctl(fd, OPROMSETOPT, pio) < 0) { + perror(MSGSTR(6011, "openprom setopt ioctl")); + return (errno); + } + + } + + (void) close(fd); + + return (0); +} |