summaryrefslogtreecommitdiff
path: root/usr/src/cmd
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd')
-rw-r--r--usr/src/cmd/Makefile.check1
-rw-r--r--usr/src/cmd/halt/Makefile44
-rw-r--r--usr/src/cmd/halt/halt.c244
-rw-r--r--usr/src/cmd/halt/smf/Makefile40
-rw-r--r--usr/src/cmd/halt/smf/boot-config.xml179
-rwxr-xr-xusr/src/cmd/halt/smf/svc-boot-config40
-rw-r--r--usr/src/cmd/initpkg/umountall.sh1
-rw-r--r--usr/src/cmd/svc/startd/Makefile5
-rw-r--r--usr/src/cmd/svc/startd/graph.c55
-rw-r--r--usr/src/cmd/uadmin/Makefile7
-rw-r--r--usr/src/cmd/uadmin/uadmin.c30
11 files changed, 537 insertions, 109 deletions
diff --git a/usr/src/cmd/Makefile.check b/usr/src/cmd/Makefile.check
index 608a0467cd..3a63d88d33 100644
--- a/usr/src/cmd/Makefile.check
+++ b/usr/src/cmd/Makefile.check
@@ -107,6 +107,7 @@ MANIFEST_SUBDIRS= \
gss/gssd \
hal/addons/network-devices \
hal/hald/solaris \
+ halt/smf \
hostid/smf \
idmap/idmapd \
ipf/svc \
diff --git a/usr/src/cmd/halt/Makefile b/usr/src/cmd/halt/Makefile
index 135e8fee26..bc622af56c 100644
--- a/usr/src/cmd/halt/Makefile
+++ b/usr/src/cmd/halt/Makefile
@@ -19,31 +19,50 @@
# CDDL HEADER END
#
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
PROG = halt
-ROOTLINKS = $(ROOTUSRSBIN)/poweroff $(ROOTUSRSBIN)/reboot
-ROOTSYMLINKS= $(ROOTETC)/halt $(ROOTETC)/reboot
-
-lint := LINTFLAGS = -u
include ../Makefile.cmd
+#
+# Currently Fast Reboot is only supported on x86.
+#
+sparc_SUBDIRS =
+i386_SUBDIRS = smf
+SUBDIRS = $($(MACH)_SUBDIRS)
+
+ROOTLINKS = $(ROOTUSRSBIN)/poweroff $(ROOTUSRSBIN)/reboot
+ROOTSYMLINKS= $(ROOTETC)/halt $(ROOTETC)/reboot
+
FILEMODE = 0755
GROUP = bin
.KEEP_STATE:
-all: $(PROG)
-
CPPFLAGS += -I../../lib/libzpool/common
+CPPFLAGS += -I../../lib/libscf/inc
CPPFLAGS += -I../../uts/common/fs/zfs
LDLIBS += -lbsm -lscf -lzfs -lgen
+LDLIBS_i386 += -lgrubmgmt
+LDLIBS += $(LDLIBS_$(MACH))
+
+CLOBBERFILES += $(ROOTLINKS) $(ROOTSYMLINKS)
+
+all := TARGET = all
+install := TARGET = install
+clean := TARGET = clean
+clobber := TARGET = clobber
+lint := TARGET = lint
+lint := LINTFLAGS = -u
+
+
+all: $(PROG)
-install: all $(ROOTUSRSBINPROG) $(ROOTLINKS) $(ROOTSYMLINKS)
+install: all $(ROOTUSRSBINPROG) $(ROOTLINKS) $(ROOTSYMLINKS) $(SUBDIRS)
$(ROOTLINKS): $(ROOTUSRSBINPROG)
$(RM) $@
@@ -53,8 +72,17 @@ $(ROOTSYMLINKS):
$(RM) $@
$(SYMLINK) ../usr/sbin/$(PROG) $@
+$(SUBDIRS): FRC
+ @cd $@; pwd; $(MAKE) $(TARGET)
+
clean:
+clobber: $(SUBDIRS)
+
lint: lint_PROG
+check: $(CHKMANIFEST)
+
+FRC:
+
include ../Makefile.targ
diff --git a/usr/src/cmd/halt/halt.c b/usr/src/cmd/halt/halt.c
index bafce88e5b..51dfea7ddb 100644
--- a/usr/src/cmd/halt/halt.c
+++ b/usr/src/cmd/halt/halt.c
@@ -24,7 +24,7 @@
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
-/* All Rights Reserved */
+/* All Rights Reserved */
/*
* University Copyright- Copyright (c) 1982, 1986, 1988
@@ -60,6 +60,7 @@
#include <fcntl.h>
#include <libgen.h>
#include <libscf.h>
+#include <libscf_priv.h>
#include <limits.h>
#include <locale.h>
#include <libintl.h>
@@ -79,6 +80,9 @@
#include <spawn.h>
#include <libzfs.h>
+#if defined(__i386)
+#include <libgrubmgmt.h>
+#endif
#if !defined(TEXT_DOMAIN)
#define TEXT_DOMAIN "SYS_TEST"
@@ -118,12 +122,21 @@ static ctid_t startdct = -1;
#define LUUMOUNT_PROG "/usr/sbin/luumount"
#define LUMOUNT_PROG "/usr/sbin/lumount"
+#define BOOTADM_PROG "/sbin/bootadm"
/*
* The length of FASTBOOT_MOUNTPOINT must be less than MAXPATHLEN.
*/
#define FASTBOOT_MOUNTPOINT "/tmp/.fastboot.root"
+/*
+ * Fast Reboot related variables
+ */
static char fastboot_mounted[MAXPATHLEN];
+#if defined(__i386)
+static grub_boot_args_t fbarg;
+static grub_boot_args_t *fbarg_used;
+static int fbarg_entnum = GRUB_ENTRY_DEFAULT;
+#endif /* __i386 */
static int validate_ufs_disk(char *, char *);
static int validate_zfs_pool(char *, char *);
@@ -542,29 +555,30 @@ validate_disk(char *arg, char *mountpoint)
{
static char root_dev_path[] = "/dev/dsk";
char kernpath[MAXPATHLEN];
- struct stat buf;
struct stat64 statbuf;
int rc = 0;
if (strlen(arg) > MAXPATHLEN) {
(void) fprintf(stderr,
- gettext("%s: argument is too long\n"), cmdname);
+ gettext("%s: Argument is too long\n"), cmdname);
return (-1);
}
bcopy(FASTBOOT_MOUNTPOINT, mountpoint, sizeof (FASTBOOT_MOUNTPOINT));
- /*
- * Do a force umount just in case some other filesystem has
- * been mounted there.
- */
- (void) umount2(mountpoint, MS_FORCE);
+ if (strstr(arg, mountpoint) == NULL) {
+ /*
+ * Do a force umount just in case some other filesystem has
+ * been mounted there.
+ */
+ (void) umount2(mountpoint, MS_FORCE);
+ }
/* Create the directory if it doesn't already exist */
- if (lstat(mountpoint, &buf) != 0) {
+ if (lstat64(mountpoint, &statbuf) != 0) {
if (mkdirp(mountpoint, 0755) != 0) {
(void) fprintf(stderr,
- gettext("failed to create mountpoint %s\n"),
+ gettext("Failed to create mountpoint %s\n"),
mountpoint);
return (-1);
}
@@ -608,7 +622,7 @@ validate_ufs_disk(char *arg, char *mountpoint)
mntopts, sizeof (mntopts)) != 0) {
perror(cmdname);
(void) fprintf(stderr,
- gettext("%s: failed to mount %s\n"), cmdname, arg);
+ gettext("%s: Failed to mount %s\n"), cmdname, arg);
return (-1);
}
@@ -623,7 +637,7 @@ validate_zfs_pool(char *arg, char *mountpoint)
int rc = 0;
if ((g_zfs = libzfs_init()) == NULL) {
- (void) fprintf(stderr, gettext("internal error: failed to "
+ (void) fprintf(stderr, gettext("Internal error: failed to "
"initialize ZFS library\n"));
return (-1);
}
@@ -634,11 +648,11 @@ validate_zfs_pool(char *arg, char *mountpoint)
return (-1);
/* perform the mount */
- if (mount(zfs_get_name(zhp), mountpoint, MS_DATA|MS_OPTIONSTR,
+ if (mount(zfs_get_name(zhp), mountpoint, MS_DATA|MS_OPTIONSTR|MS_RDONLY,
MNTTYPE_ZFS, NULL, 0, mntopts, sizeof (mntopts)) != 0) {
perror(cmdname);
(void) fprintf(stderr,
- gettext("%s: failed to mount %s\n"), cmdname, arg);
+ gettext("%s: Failed to mount %s\n"), cmdname, arg);
rc = -1;
}
@@ -665,12 +679,13 @@ get_zfs_bootfs_arg(const char *arg, const char ** fpth, int *is_zfs,
FILE *mtabp = NULL;
struct mnttab mnt;
char *poolname = NULL;
- char physpath[MAXNAMELEN];
+ char physpath[MAXPATHLEN];
char mntsp[ZPOOL_MAXNAMELEN];
char bootfs[ZPOOL_MAXNAMELEN];
int rc = 0;
size_t mntlen = 0;
size_t msz;
+ static char fmt[] = "-B zfs-bootfs=%s,bootpath=\"%s\"";
*fpth = arg;
*is_zfs = 0;
@@ -705,7 +720,7 @@ get_zfs_bootfs_arg(const char *arg, const char ** fpth, int *is_zfs,
/* Try to open the dataset */
if ((zhp = zfs_open(g_zfs, mntsp,
ZFS_TYPE_FILESYSTEM | ZFS_TYPE_DATASET)) == NULL) {
- (void) fprintf(stderr, gettext("cannot open %s\n"), mntsp);
+ (void) fprintf(stderr, gettext("Cannot open %s\n"), mntsp);
rc = -1;
goto validate_zfs_err_out;
}
@@ -718,27 +733,29 @@ get_zfs_bootfs_arg(const char *arg, const char ** fpth, int *is_zfs,
}
if ((zpoolp = zpool_open(g_zfs, poolname)) == NULL) {
- (void) fprintf(stderr, gettext("cannot open %s\n"), poolname);
+ (void) fprintf(stderr, gettext("Cannot open %s\n"), poolname);
rc = -1;
goto validate_zfs_err_out;
}
- if (zpool_get_physpath(zpoolp, physpath) != 0) {
- (void) fprintf(stderr, gettext("cannot find phys_path\n"));
+ if (zpool_get_physpath(zpoolp, physpath, sizeof (physpath)) != 0) {
+ (void) fprintf(stderr, gettext("Cannot find phys_path\n"));
rc = -1;
goto validate_zfs_err_out;
}
- if (zpool_set_prop(zpoolp, "bootfs", bootfs) != 0) {
- (void) fprintf(stderr, gettext("cannot set bootfs to %s\n"),
- bootfs);
- rc = -1;
- goto validate_zfs_err_out;
+ /*
+ * For the mirror physpath would contain the list of all
+ * bootable devices, pick up the first one.
+ */
+ (void) strtok(physpath, " ");
+ if (snprintf(bootfs_arg, BOOTARGS_MAX, fmt, bootfs, physpath) >=
+ BOOTARGS_MAX) {
+ rc = E2BIG;
+ (void) fprintf(stderr,
+ gettext("Boot arguments are too long\n"));
}
- (void) snprintf(bootfs_arg, BOOTARGS_MAX,
- "-B zfs-bootfs=%s,bootpath=\"%s\"", bootfs, physpath);
-
validate_zfs_err_out:
if (zhp != NULL)
zfs_close(zhp);
@@ -768,7 +785,7 @@ validate_unix(char *arg, int *mplen, int *is_zfs, char *bootfs_arg,
if ((sz = resolvepath(arg, physpath, sizeof (physpath) - 1)) ==
(size_t)-1) {
(void) fprintf(stderr,
- gettext("cannot resolve path for %s: %s\n"),
+ gettext("Cannot resolve path for %s: %s\n"),
arg, strerror(errno));
return (-1);
}
@@ -776,13 +793,13 @@ validate_unix(char *arg, int *mplen, int *is_zfs, char *bootfs_arg,
if (strlen(arg) > MAXPATHLEN) {
(void) fprintf(stderr,
- gettext("%s: new kernel name is too long\n"), cmdname);
+ gettext("%s: New kernel name is too long\n"), cmdname);
return (-1);
}
if (strncmp(basename(arg), "unix", 4) != 0) {
(void) fprintf(stderr,
- gettext("%s: %s: kernel name must be unix\n"),
+ gettext("%s: %s: Kernel name must be unix\n"),
cmdname, arg);
return (-1);
}
@@ -798,7 +815,7 @@ validate_unix(char *arg, int *mplen, int *is_zfs, char *bootfs_arg,
*failsafe = 0;
else {
(void) fprintf(stderr,
- gettext("%s: %s: no /boot/platform or /platform in"
+ gettext("%s: %s: No /boot/platform or /platform in"
" file name\n"), cmdname, arg);
goto err_out;
}
@@ -813,18 +830,16 @@ validate_unix(char *arg, int *mplen, int *is_zfs, char *bootfs_arg,
class = ident[EI_CLASS];
if ((class != ELFCLASS32 && class != ELFCLASS64) ||
- ident[EI_MAG0] != ELFMAG0 || ident[EI_MAG1] != ELFMAG1 ||
- ident[EI_MAG2] != ELFMAG2 || ident[EI_MAG3] != ELFMAG3) {
+ memcmp(&ident[EI_MAG0], ELFMAG, 4) != 0) {
(void) fprintf(stderr,
- gettext("%s: %s: not a valid ELF file\n"),
- cmdname, arg);
+ gettext("%s: %s: Not a valid ELF file\n"), cmdname, arg);
goto err_out;
}
format = ident[EI_DATA];
if (format != CUR_ELFDATA) {
- (void) fprintf(stderr, gettext("%s: %s: invalid data format\n"),
+ (void) fprintf(stderr, gettext("%s: %s: Invalid data format\n"),
cmdname, arg);
goto err_out;
}
@@ -839,28 +854,6 @@ err_out:
return (-1);
}
-#ifndef __i386
-/* ARGSUSED */
-#endif /* __i386 */
-static int
-is_fastboot_default(uid_t uid)
-{
-#if defined(__i386)
- int ret;
- struct stat st;
- static const char fastboot_default[] = "/etc/fastreboot";
-
- ret = (lstat(fastboot_default, &st) == 0 &&
- S_ISREG(st.st_mode) &&
- (st.st_mode & S_IRUSR) != 0 &&
- uid == st.st_uid);
-
- return (ret);
-#else
- return (0);
-#endif /* __i386 */
-}
-
static int
halt_exec(const char *path, ...)
{
@@ -891,7 +884,7 @@ halt_exec(const char *path, ...)
va_end(vp);
(void) execve(path, (char * const *)argv, NULL);
- (void) fprintf(stderr, gettext("cannot execute %s: %s\n"),
+ (void) fprintf(stderr, gettext("Cannot execute %s: %s\n"),
path, strerror(errno));
exit(-1);
} else {
@@ -918,7 +911,7 @@ fastboot_bename(const char *bename, char *mountpoint, size_t mpsz)
if ((rc = halt_exec(LUMOUNT_PROG, "-n", bename, FASTBOOT_MOUNTPOINT,
NULL)) != 0)
- (void) fprintf(stderr, gettext("%s: cannot mount BE %s\n"),
+ (void) fprintf(stderr, gettext("%s: Cannot mount BE %s\n"),
cmdname, bename);
else
(void) strlcpy(mountpoint, FASTBOOT_MOUNTPOINT, mpsz);
@@ -928,11 +921,12 @@ fastboot_bename(const char *bename, char *mountpoint, size_t mpsz)
/*
* Returns 0 on successful parsing of the arguments;
- * retuens non-zero on failure.
+ * returns EINVAL on parsing failures that should abort the reboot attempt;
+ * returns other error code to fall back to regular reboot.
*/
static int
-parse_fastboot_args(char *bootargs_buf, int *is_dryrun, const char *bename,
- int *failsafe)
+parse_fastboot_args(char *bootargs_buf, size_t buf_size,
+ int *is_dryrun, const char *bename, int *failsafe)
{
char mountpoint[MAXPATHLEN];
char bootargs_saved[BOOTARGS_MAX];
@@ -965,11 +959,6 @@ parse_fastboot_args(char *bootargs_buf, int *is_dryrun, const char *bename,
bzero(&bootargs_scratch[buflen], sizeof (bootargs_scratch) - buflen);
head = &bootargs_scratch[0];
- /* Zero out the boot argument buffer as we will reconstruct it */
- bzero(bootargs_buf, BOOTARGS_MAX);
- bzero(bootfs_arg, BOOTARGS_MAX);
- bzero(unixfile, sizeof (unixfile));
-
/* Get the first argument */
newarg = strtok(bootargs_scratch, " ");
@@ -988,22 +977,72 @@ parse_fastboot_args(char *bootargs_buf, int *is_dryrun, const char *bename,
*/
if (uadmin(A_SHUTDOWN, AD_FASTREBOOT_DRYRUN,
(uintptr_t)bootargs_saved) != 0) {
- (void) fprintf(stderr, gettext("%s: not all drivers "
- "have implemented quiesce(9E)\n"), cmdname);
+ (void) fprintf(stderr, gettext("%s: Not all drivers "
+ "have implemented quiesce(9E)\n"
+ "\tPlease see /var/adm/messages for drivers that haven't\n"
+ "\timplemented quiesce(9E).\n"), cmdname);
} else if (*is_dryrun) {
- (void) fprintf(stderr, gettext("%s: all drivers have "
+ (void) fprintf(stderr, gettext("%s: All drivers have "
"implemented quiesce(9E)\n"), cmdname);
}
- /*
- * Return if it is a true dry run.
- */
+ /* Return if it is a true dry run. */
if (*is_dryrun)
return (rc);
+#if defined(__i386)
+ /* Read boot args from GRUB menu */
+ if ((bootargs_buf[0] == 0 || isdigit(bootargs_buf[0])) &&
+ bename == NULL) {
+ /*
+ * If no boot arguments are given, or a GRUB menu entry
+ * number is provided, process the GRUB menu.
+ */
+ int entnum;
+ if (bootargs_buf[0] == 0)
+ entnum = GRUB_ENTRY_DEFAULT;
+ else {
+ errno = 0;
+ entnum = strtoul(bootargs_buf, NULL, 10);
+ rc = errno;
+ }
+
+ if (rc == 0 && (rc = grub_get_boot_args(&fbarg, NULL,
+ entnum)) == 0) {
+ if (strlcpy(bootargs_buf, fbarg.gba_bootargs,
+ buf_size) >= buf_size) {
+ grub_cleanup_boot_args(&fbarg);
+ bcopy(bootargs_saved, bootargs_buf, buf_size);
+ rc = E2BIG;
+ }
+ }
+ /* Failed to read GRUB menu, fall back to normal reboot */
+ if (rc != 0) {
+ (void) fprintf(stderr,
+ gettext("%s: Failed to process GRUB menu "
+ "entry for fast reboot.\n\t%s\n"),
+ cmdname, grub_strerror(rc));
+ (void) fprintf(stderr,
+ gettext("%s: Falling back to regular reboot.\n"),
+ cmdname);
+ return (-1);
+ }
+ /* No need to process further */
+ fbarg_used = &fbarg;
+ fbarg_entnum = entnum;
+ return (0);
+ }
+#endif /* __i386 */
+
+ /* Zero out the boot argument buffer as we will reconstruct it */
+ bzero(bootargs_buf, buf_size);
+ bzero(bootfs_arg, sizeof (bootfs_arg));
+ bzero(unixfile, sizeof (unixfile));
+
if (bename && (rc = fastboot_bename(bename, mountpoint,
sizeof (mountpoint))) != 0)
- return (rc);
+ return (EINVAL);
+
/*
* If BE is not specified, look for disk argument to construct
@@ -1070,7 +1109,7 @@ parse_fastboot_args(char *bootargs_buf, int *is_dryrun, const char *bename,
"/platform/i86pc/kernel/unix");
} else {
(void) fprintf(stderr,
- gettext("%s: unknown architecture"), cmdname);
+ gettext("%s: Unknown architecture"), cmdname);
return (EINVAL);
}
}
@@ -1163,9 +1202,9 @@ main(int argc, char *argv[])
{
char *ttyn = ttyname(STDERR_FILENO);
- uid_t euid;
int qflag = 0, needlog = 1, nosync = 0;
int fast_reboot = 0;
+ int prom_reboot = 0;
uintptr_t mdep = NULL;
int cmd, fcn, c, aval, r;
const char *usage;
@@ -1198,8 +1237,8 @@ main(int argc, char *argv[])
} else if (strcmp(cmdname, "reboot") == 0) {
(void) audit_reboot_setup();
#if defined(__i386)
- optstring = "dlnqfe:";
- usage = gettext("usage: %s [ -dlnqfe: ] [ boot args ]\n");
+ optstring = "dlnqpfe:";
+ usage = gettext("usage: %s [ -dlnq(p|fe:) ] [ boot args ]\n");
#else
optstring = "dlnq";
usage = gettext("usage: %s [ -dlnq ] [ boot args ]\n");
@@ -1237,6 +1276,9 @@ main(int argc, char *argv[])
ttyn = NULL;
break;
#if defined(__i386)
+ case 'p':
+ prom_reboot = 1;
+ break;
case 'f':
fast_reboot = 1;
break;
@@ -1280,17 +1322,25 @@ main(int argc, char *argv[])
bzero(bootargs_buf, sizeof (bootargs_buf));
}
- if ((euid = geteuid()) != 0) {
+ if (geteuid() != 0) {
(void) fprintf(stderr,
gettext("%s: permission denied\n"), cmdname);
goto fail;
}
+ if (fast_reboot && prom_reboot) {
+ (void) fprintf(stderr,
+ gettext("%s: -p and -f are mutually exclusive\n"),
+ cmdname);
+ return (EINVAL);
+ }
+
/*
- * Check whether fast reboot is the default operating mode
+ * Check whether fast reboot is the default operating mode
*/
- if (fcn == AD_BOOT && !fast_reboot)
- fast_reboot = is_fastboot_default(euid);
+ if (fcn == AD_BOOT && !fast_reboot && !prom_reboot &&
+ zoneid == GLOBAL_ZONEID)
+ fast_reboot = scf_is_fastboot_default();
if (bename && !fast_reboot) {
(void) fprintf(stderr, gettext("%s: -e only valid with -f\n"),
@@ -1298,7 +1348,6 @@ main(int argc, char *argv[])
return (EINVAL);
}
-
/*
* If fast reboot, do some sanity check on the argument
*/
@@ -1308,25 +1357,28 @@ main(int argc, char *argv[])
if (zoneid != GLOBAL_ZONEID) {
(void) fprintf(stderr,
- gettext("%s: fast reboot only valid from global"
+ gettext("%s: Fast reboot only valid from global"
" zone\n"), cmdname);
return (EINVAL);
}
- rc = parse_fastboot_args(bootargs_buf, &is_dryrun,
- bename, &failsafe);
+ rc = parse_fastboot_args(bootargs_buf, sizeof (bootargs_buf),
+ &is_dryrun, bename, &failsafe);
/*
* If dry run, or if arguments are invalid, return.
*/
if (is_dryrun)
return (rc);
- else if (rc != 0)
+ else if (rc == EINVAL)
goto fail;
+ else if (rc != 0)
+ fast_reboot = 0;
/*
* For all the other errors, we continue on in case user
- * user want to force fast reboot.
+ * user want to force fast reboot, or fall back to regular
+ * reboot.
*/
if (strlen(bootargs_buf) != 0)
mdep = (uintptr_t)bootargs_buf;
@@ -1395,8 +1447,16 @@ main(int argc, char *argv[])
need_check_zones = halt_zones();
}
- /* if we're dumping, do the archive update here and don't defer it */
+#if defined(__i386)
+ /* set new default entry in the GRUB entry */
+ if (fbarg_entnum != GRUB_ENTRY_DEFAULT) {
+ char buf[32];
+ (void) snprintf(buf, sizeof (buf), "default=%u", fbarg_entnum);
+ (void) halt_exec(BOOTADM_PROG, "set-menu", buf, NULL);
+ }
+#endif /* __i386 */
+ /* if we're dumping, do the archive update here and don't defer it */
if (cmd == A_DUMP && zoneid == GLOBAL_ZONEID && !nosync)
do_archives_update(fast_reboot);
@@ -1539,6 +1599,10 @@ fail:
} else if (strlen(fastboot_mounted) != 0) {
(void) umount(fastboot_mounted);
+#if defined(__i386)
+ } else if (fbarg_used != NULL) {
+ grub_cleanup_boot_args(fbarg_used);
+#endif /* __i386 */
}
}
diff --git a/usr/src/cmd/halt/smf/Makefile b/usr/src/cmd/halt/smf/Makefile
new file mode 100644
index 0000000000..c150613e8e
--- /dev/null
+++ b/usr/src/cmd/halt/smf/Makefile
@@ -0,0 +1,40 @@
+#
+# 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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+include ../../Makefile.cmd
+
+MANIFEST= boot-config.xml
+SVCMETHOD= svc-boot-config
+
+ROOTMANIFESTDIR = $(ROOTSVCSYSTEM)
+
+all clean clobber lint:
+
+install: all $(ROOTMANIFEST) $(ROOTSVCMETHOD)
+
+check: $(CHKMANIFEST)
+
+include ../../Makefile.targ
diff --git a/usr/src/cmd/halt/smf/boot-config.xml b/usr/src/cmd/halt/smf/boot-config.xml
new file mode 100644
index 0000000000..45dccefd57
--- /dev/null
+++ b/usr/src/cmd/halt/smf/boot-config.xml
@@ -0,0 +1,179 @@
+<?xml version="1.0"?>
+<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
+<!--
+ Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ Use is subject to license terms.
+
+ 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
+
+ NOTE: This service manifest is not editable; its contents will
+ be overwritten by package or patch operations, including
+ operating system upgrade. Make customizations in a different
+ file.
+-->
+
+<service_bundle type='manifest' name='SUNWcsr:boot-config'>
+
+<service
+ name='system/boot-config'
+ type='service'
+ version='1'>
+
+ <single_instance />
+
+ <dependency
+ name='manifest_import'
+ grouping='optional_all'
+ restart_on='none'
+ type='service'>
+ <service_fmri value='svc:/system/manifest-import:default' />
+ </dependency>
+
+ <!-- The boot-config service is made to depend on milestone
+ multi-user to minimize the chance for panic reboot loop. -->
+ <dependency
+ name='boot_multi-user'
+ grouping='optional_all'
+ restart_on='none'
+ type='service'>
+ <service_fmri value='svc:/milestone/multi-user' />
+ </dependency>
+
+ <instance name='default' enabled = 'true'>
+
+ <exec_method
+ type='method'
+ name='start'
+ exec='/lib/svc/method/svc-boot-config'
+ timeout_seconds='60' />
+
+ <exec_method
+ type='method'
+ name='stop'
+ exec=':true'
+ timeout_seconds='60' />
+
+ <exec_method
+ type='method'
+ name='refresh'
+ exec='/lib/svc/method/svc-boot-config'
+ timeout_seconds='60' />
+
+ <property_group name='startd' type='framework'>
+ <propval name='duration' type='astring'
+ value='transient' />
+ </property_group>
+
+ <property_group name='general' type='framework'>
+ <propval name='action_authorization' type='astring'
+ value='solaris.system.shutdown' />
+ <propval name='value_authorization' type='astring'
+ value='solaris.system.shutdown' />
+ </property_group>
+
+ <property_group name='config' type='application'>
+ <stability value='Stable' />
+ <propval name='fastreboot_default' type='boolean'
+ value='true' />
+ <propval name='fastreboot_onpanic' type='boolean'
+ value='true' />
+ <propval name='value_authorization' type='astring'
+ value='solaris.system.shutdown' />
+ </property_group>
+
+ <property_group name='fastreboot_blacklist' type='application'>
+ <stability value='Unstable' />
+ <property name='platforms' type='astring'>
+ <astring_list>
+ <value_node value='VirtualBox' />
+ <value_node value='VMware Virtual Platform' />
+ <value_node value='MCP55' />
+ </astring_list>
+ </property>
+ </property_group>
+ </instance>
+
+ <stability value='Stable' />
+
+ <template>
+ <common_name>
+ <loctext xml:lang='C'>
+ Boot Configuration Management
+ </loctext>
+ </common_name>
+ <description>
+ <loctext xml:lang='C'>
+Apply the configuration defined in this service by uploading the configuration to the kernel.
+ </loctext>
+ </description>
+ <documentation>
+ <manpage title='reboot' section='1M'
+ manpath='/usr/share/man' />
+ <manpage title='init' section='1M'
+ manpath='/usr/share/man' />
+ <manpage title='uadmin' section='2'
+ manpath='/usr/share/man' />
+ <manpage title='quiesce' section='9E'
+ manpath='/usr/share/man' />
+ </documentation>
+ <pg_pattern name='config' type='application'
+ required='true'>
+ <common_name>
+ <loctext xml:lang='C'>
+ Boot Configuration Parameters
+ </loctext>
+ </common_name>
+ <description>
+ <loctext xml:lang='C'>
+Parameters for controlling the reboot behavior.
+ </loctext>
+ </description>
+ <prop_pattern name='fastreboot_default' type='boolean'
+ required='true'>
+ <common_name>
+ <loctext xml:lang='C'>
+ Fast Reboot by Default
+ </loctext>
+ </common_name>
+ <description>
+ <loctext xml:lang='C'>
+When set to true, reboot(1M) and init(1M) 6 will call uadmin(2) with AD_FASTREOOT, which will bypass firmware.
+ </loctext>
+ </description>
+ </prop_pattern>
+ <prop_pattern name='fastreboot_onpanic' type='boolean'
+ required='true'>
+ <common_name>
+ <loctext xml:lang='C'>
+ Fast Reboot on Panic
+ </loctext>
+ </common_name>
+ <description>
+ <loctext xml:lang='C'>
+When set to true, the system will fast reboot on panic.
+ </loctext>
+ </description>
+ </prop_pattern>
+ </pg_pattern>
+
+ </template>
+</service>
+
+</service_bundle>
diff --git a/usr/src/cmd/halt/smf/svc-boot-config b/usr/src/cmd/halt/smf/svc-boot-config
new file mode 100755
index 0000000000..e54214d754
--- /dev/null
+++ b/usr/src/cmd/halt/smf/svc-boot-config
@@ -0,0 +1,40 @@
+#!/sbin/sh
+#
+# 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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# Start and refresh method script for the boot-config service.
+#
+
+. /lib/svc/share/smf_include.sh
+
+#
+# This service is only valid in the global zone.
+#
+smf_is_globalzone || exit $SMF_EXIT_OK
+
+#
+# uadmin A_CONFIG AD_UPDATE_BOOT_CONFIG
+#
+/usr/sbin/uadmin 23 1
+exit $SMF_EXIT_OK
diff --git a/usr/src/cmd/initpkg/umountall.sh b/usr/src/cmd/initpkg/umountall.sh
index e589feebb9..e3e93ff98a 100644
--- a/usr/src/cmd/initpkg/umountall.sh
+++ b/usr/src/cmd/initpkg/umountall.sh
@@ -253,6 +253,7 @@ doumounts () {
/system/contract | \
/system/object | \
/tmp | \
+ /tmp/.libgrubmgmt* | \
/usr | \
/var | \
/var/adm | \
diff --git a/usr/src/cmd/svc/startd/Makefile b/usr/src/cmd/svc/startd/Makefile
index f5b20e6e81..582cf512c1 100644
--- a/usr/src/cmd/svc/startd/Makefile
+++ b/usr/src/cmd/svc/startd/Makefile
@@ -19,7 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
@@ -75,6 +75,9 @@ LDLIBS += \
-lumem \
-luutil
+LDLIBS_i386 += -lgrubmgmt
+LDLIBS += $(LDLIBS_$(MACH))
+
FILEMODE = 0555
OWNER = root
GROUP = sys
diff --git a/usr/src/cmd/svc/startd/graph.c b/usr/src/cmd/svc/startd/graph.c
index 455b14ab0c..40c5619fb4 100644
--- a/usr/src/cmd/svc/startd/graph.c
+++ b/usr/src/cmd/svc/startd/graph.c
@@ -126,6 +126,9 @@
#include <sys/statvfs.h>
#include <sys/uadmin.h>
#include <zone.h>
+#if defined(__i386)
+#include <libgrubmgmt.h>
+#endif /* __i386 */
#include "startd.h"
#include "protocol.h"
@@ -3479,20 +3482,54 @@ kill_user_procs(void)
static void
do_uadmin(void)
{
+ const char * const resetting = "/etc/svc/volatile/resetting";
int fd;
struct statvfs vfs;
time_t now;
struct tm nowtm;
char down_buf[256], time_buf[256];
+ uintptr_t mdep;
+#if defined(__i386)
+ grub_boot_args_t fbarg;
+#endif /* __i386 */
- const char * const resetting = "/etc/svc/volatile/resetting";
-
+ mdep = NULL;
fd = creat(resetting, 0777);
if (fd >= 0)
startd_close(fd);
else
uu_warn("Could not create \"%s\"", resetting);
+ /*
+ * Right now, fast reboot is supported only on i386.
+ * scf_is_fastboot_default() should take care of it.
+ * If somehow we got there on unsupported platform -
+ * print warning and fall back to regular reboot.
+ */
+ if (halting == AD_FASTREBOOT) {
+#if defined(__i386)
+ int rc;
+
+ if ((rc = grub_get_boot_args(&fbarg, NULL,
+ GRUB_ENTRY_DEFAULT)) == 0) {
+ mdep = (uintptr_t)&fbarg.gba_bootargs;
+ } else {
+ /*
+ * Failed to read GRUB menu, fall back to normal reboot
+ */
+ halting = AD_BOOT;
+ uu_warn("Failed to process GRUB menu entry "
+ "for fast reboot.\n\t%s\n"
+ "Falling back to regular reboot.\n",
+ grub_strerror(rc));
+ }
+#else /* __i386 */
+ halting = AD_BOOT;
+ uu_warn("Fast reboot configured, but not supported by "
+ "this ISA\n");
+#endif /* __i386 */
+ }
+
/* Kill dhcpagent if we're not using nfs for root */
if ((statvfs("/", &vfs) == 0) &&
(strncmp(vfs.f_basetype, "nfs", sizeof ("nfs") - 1) != 0))
@@ -3578,9 +3615,15 @@ do_uadmin(void)
}
(void) printf("%s%s\n", down_buf, time_buf);
- (void) uadmin(A_SHUTDOWN, halting, NULL);
+ (void) uadmin(A_SHUTDOWN, halting, mdep);
uu_warn("uadmin() failed");
+#if defined(__i386)
+ /* uadmin fail, cleanup grub_boot_args */
+ if (halting == AD_FASTREBOOT)
+ grub_cleanup_boot_args(&fbarg);
+#endif /* __i386 */
+
if (remove(resetting) != 0 && errno != ENOENT)
uu_warn("Could not remove \"%s\"", resetting);
}
@@ -5066,8 +5109,10 @@ dgraph_set_runlevel(scf_propertygroup_t *pg, scf_property_t *prop)
case '6':
halting_time = time(NULL);
fork_rc_script(rl, stop, B_TRUE);
- halting = AD_BOOT;
- goto uadmin;
+ if (scf_is_fastboot_default() && getzoneid() == GLOBAL_ZONEID)
+ halting = AD_FASTREBOOT;
+ else
+ halting = AD_BOOT;
uadmin:
uu_warn("The system is coming down. Please wait.\n");
diff --git a/usr/src/cmd/uadmin/Makefile b/usr/src/cmd/uadmin/Makefile
index d4a3c9b7b2..aad6970d8c 100644
--- a/usr/src/cmd/uadmin/Makefile
+++ b/usr/src/cmd/uadmin/Makefile
@@ -19,11 +19,9 @@
# CDDL HEADER END
#
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-# ident "%Z%%M% %I% %E% SMI"
-#
PROG= uadmin
ROOTFS_PROG= $(PROG)
@@ -32,7 +30,10 @@ include ../Makefile.cmd
OWNER = root
GROUP = sys
+
+i386_LDLIBS += -lscf
LDLIBS += -lbsm
+LDLIBS += $($(MACH)_LDLIBS)
LINTFLAGS = -ux
.KEEP_STATE:
diff --git a/usr/src/cmd/uadmin/uadmin.c b/usr/src/cmd/uadmin/uadmin.c
index 73d1014afb..8959e9c84b 100644
--- a/usr/src/cmd/uadmin/uadmin.c
+++ b/usr/src/cmd/uadmin/uadmin.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -36,6 +36,9 @@
#include <strings.h>
#include <signal.h>
#include <unistd.h>
+#ifdef __i386
+#include <libscf_priv.h>
+#endif /* __i386 */
#include <bsm/adt.h>
#include <bsm/adt_event.h>
@@ -64,6 +67,10 @@ main(int argc, char *argv[])
adt_event_data_t *event = NULL; /* event to be generated */
au_event_t event_id;
enum adt_uadmin_fcn fcn_id;
+#ifdef __i386
+ uint8_t boot_config = 0;
+#endif /* __i386 */
+
if (argc < 3 || argc > 4) {
(void) fprintf(stderr, Usage, argv[0]);
@@ -111,6 +118,9 @@ main(int argc, char *argv[])
case A_FTRACE:
event_id = ADT_uadmin_ftrace;
break;
+ case A_CONFIG:
+ event_id = ADT_uadmin_config;
+ break;
case A_SWAPCTL:
event_id = ADT_uadmin_swapctl;
break;
@@ -148,7 +158,7 @@ main(int argc, char *argv[])
#ifdef __i386
fcn_id = ADT_UADMIN_FCN_AD_FASTREBOOT;
mdep = NULL; /* Ignore all arguments */
-#else
+#else /* __i386 */
fcn = AD_BOOT;
fcn_id = ADT_UADMIN_FCN_AD_BOOT;
#endif /* __i386 */
@@ -196,6 +206,16 @@ main(int argc, char *argv[])
fcn_id = ADT_UADMIN_FCN_AD_FTRACE_STOP;
break;
}
+#ifdef __i386
+ } else if (cmd == A_CONFIG) {
+ switch (fcn) {
+ case AD_UPDATE_BOOT_CONFIG:
+ fcn_id = ADT_UADMIN_FCN_AD_UPDATE_BOOT_CONFIG;
+ scf_get_boot_config(&boot_config);
+ mdep = (uintptr_t)(&boot_config);
+ break;
+ }
+#endif /* __i386 */
}
if (geteuid() == 0) {
@@ -222,6 +242,11 @@ main(int argc, char *argv[])
break;
case A_FTRACE:
event->adt_uadmin_ftrace.fcn = fcn_id;
+ event->adt_uadmin_ftrace.mdep = (char *)mdep;
+ break;
+ case A_CONFIG:
+ event->adt_uadmin_config.fcn = fcn_id;
+ event->adt_uadmin_config.mdep = (char *)mdep;
break;
case A_SWAPCTL:
event->adt_uadmin_swapctl.fcn = fcn_id;
@@ -302,6 +327,7 @@ closeout_audit(int cmd, int fcn)
case A_REMOUNT:
case A_SWAPCTL:
case A_FTRACE:
+ case A_CONFIG:
/* No system discontinuity, don't turn off auditd */
return (0);
case A_FREEZE: