summaryrefslogtreecommitdiff
path: root/usr/src/cmd/luxadm/setboot.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd/luxadm/setboot.c')
-rw-r--r--usr/src/cmd/luxadm/setboot.c257
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);
+}