bootadm.c revision 98892a3058bed9457ab6a22659dcccecfaf05d2a
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Madden * CDDL HEADER START
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Madden * The contents of this file are subject to the terms of the
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Madden * Common Development and Distribution License (the "License").
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Madden * You may not use this file except in compliance with the License.
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Madden * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Madden * See the License for the specific language governing permissions
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Madden * and limitations under the License.
c49a898cb851f8fef7d7a6a9501c66b8f03ae05cPhill Cunnington * When distributing Covered Code, include this CDDL HEADER in each
c49a898cb851f8fef7d7a6a9501c66b8f03ae05cPhill Cunnington * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Madden * If applicable, add the following below this CDDL HEADER, with the
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Madden * fields enclosed by brackets "[]" replaced with your own identifying
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Madden * information: Portions Copyright [yyyy] [name of copyright owner]
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Madden * CDDL HEADER END
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Madden * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Madden * Use is subject to license terms.
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Madden#pragma ident "%Z%%M% %I% %E% SMI"
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Madden * bootadm(1M) is a new utility for managing bootability of
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Madden * Solaris *Newboot* environments. It has two primary tasks:
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Madden * - Allow end users to manage bootability of Newboot Solaris instances
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Madden * - Provide services to other subsystems in Solaris (primarily Install)
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Madden/* Headers */
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Madden#endif /* TEXT_DOMAIN */
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Madden/* Type definitions */
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Madden/* Primary subcmds */
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Maddentypedef enum {
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Maddentypedef enum {
c49a898cb851f8fef7d7a6a9501c66b8f03ae05cPhill Cunnington OPT_OPTIONAL /* option may or may not be present */
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Maddentypedef struct {
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Madden int unpriv; /* is this an unprivileged command */
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Madden#define ENTRY_INIT -1 /* entryNum initial value */
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Madden#define ALL_ENTRIES -2 /* selects all boot entries */
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Madden/* lock related */
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Madden#define LOCK_FILE_PERMS (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Madden#define CREATE_RAMDISK "/boot/solaris/bin/create_ramdisk"
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Madden#define CREATE_DISKMAP "/boot/solaris/bin/create_diskmap"
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Madden#define GRUBDISK_MAP "/var/run/solaris_grubdisk.map"
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Madden#define GRUB_backup_menu "/etc/lu/GRUB_backup_menu"
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Madden#define LU_ACTIVATE_FILE "/etc/lu/DelayUpdate/activate.sh"
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Madden#define GRUB_fdisk_target "/etc/lu/GRUB_fdisk_target"
* consolidation. It is set by pdo.c when a patch with SUNW_PATCH_SAFEMODE
char *menu_cmds[] = {
} filelist_t;
int bam_verbose;
int bam_force;
static char *prog;
static char *bam_root;
static int bam_rootlen;
static int bam_root_readonly;
static int bam_alt_root;
static char *bam_subcmd;
static char *bam_opt;
static int bam_debug;
static char **bam_argv;
static int bam_argc;
static int bam_check;
static int bam_smf_check;
static int bam_update_all;
static void bam_lock(void);
static void bam_unlock(void);
static int is_readonly(char *);
static int is_amd64(void);
#if defined(__sparc)
static void sparc_abort(void);
int need_update;
} walk_arg;
struct safefile {
char *name;
usage(void)
prog);
#ifndef __sparc
prog++;
#if defined(__sparc)
sparc_abort();
switch (bam_cmd) {
case BAM_MENU:
case BAM_ARCHIVE:
usage();
bam_unlock();
#if defined(__sparc)
sparc_abort(void)
static struct cmd_map {
char *bam_cmdname;
int bam_cmd;
char *bam_subcmd;
} cmd_map[] = {
cmp++;
usage();
argc--;
argv++;
int c, error;
extern char *optarg;
opterr = 0;
error = 0;
if (bam_cmd) {
if (bam_debug) {
if (bam_force) {
if (bam_cmd) {
if (bam_check) {
if (bam_opt) {
if (bam_verbose) {
if (bam_root) {
if (!bam_cmd) {
usage();
bam_exit(0);
if (error) {
usage();
if (bam_check)
static error_t
char *subcmd,
char *opt,
return (BAM_ERROR);
usage();
return (BAM_ERROR);
return (BAM_ERROR);
return (BAM_ERROR);
bam_lock();
if (opt)
return (BAM_ERROR);
return (BAM_SUCCESS);
char *mntpt;
*mnted = 0;
if (physlice)
if (logslice)
if (fs_type)
return (NULL);
return (NULL);
return (NULL);
if (physlice) {
if (logslice) {
if (fs_type) {
goto error;
if (mntpt) {
return (mntpt);
goto error;
goto error;
return (mntpt);
if (physlice) {
if (logslice) {
if (fs_type) {
return (NULL);
int mnted,
char *mntpt,
char *physlice,
char *logslice,
char *fs_type)
if (mnted) {
mntpt);
if (physlice)
if (logslice)
if (fs_type)
use_stubboot(void)
int mnted;
return (NULL);
return (NULL);
mnted = 0;
if (mnted)
return (STUBBOOT);
STUBBOOT);
return (NULL);
return (STUBBOOT);
if (mnted) {
static error_t
return (BAM_ERROR);
mnted = 0;
if (bam_alt_root) {
} else if (bam_alt_root) {
return (BAM_ERROR);
usage();
return (BAM_ERROR);
} else if (largc != 0) {
usage();
return (BAM_ERROR);
return (ret);
return (ret);
static error_t
char *subcmd,
char *opt)
return (BAM_ERROR);
#if defined(__sparc)
return (BAM_SUCCESS);
sparc_abort();
return (ret);
return (BAM_ERROR);
bam_update_all = 0;
return (ret);
bam_unlock();
bam_lock(void)
if (bam_lock_fd < 0) {
pid = 0;
bam_unlock(void)
if (bam_lock_fd < 0) {
static error_t
return (BAM_ERROR);
return (BAM_SUCCESS);
static error_t
int ret;
return (BAM_ERROR);
return (BAM_SUCCESS);
if (bam_verbose)
if (bam_verbose)
return (BAM_ERROR);
return (BAM_ERROR);
return (BAM_ERROR);
return (BAM_ERROR);
return (BAM_ERROR);
return (BAM_ERROR);
return (BAM_ERROR);
if (ret != 0) {
return (BAM_ERROR);
return (BAM_SUCCESS);
const char *file,
int flags,
int error;
if (error)
* If we are invoked as part of system/filesyste/boot-archive, then
if (bam_smf_check) {
sizeof (struct safefile));
sizeof (struct safefile));
if (bam_verbose)
if (bam_smf_check) {
if (bam_verbose)
if (bam_smf_check)
if (bam_force) {
static error_t
if (bam_debug)
return (BAM_ERROR);
return (BAM_ERROR);
return (BAM_SUCCESS);
static error_t
int rval;
return (rval);
return (BAM_ERROR);
return (BAM_SUCCESS);
char *ostat;
if (bam_verbose)
if (error) {
char *file;
if (bam_smf_check)
if (bam_verbose)
create_newstat(void)
int error;
if (error) {
* For example: etc/rtc_config on a x86 diskless system
if (bam_verbose)
char *nstat;
sz = 0;
NV_ENCODE_XDR, 0);
if (error) {
clear_walk_args(void)
int need_update;
if (bam_smf_check) {
return (BAM_ERROR);
if (!bam_check)
static error_t
return (BAM_ERROR);
return (BAM_ERROR);
return (BAM_ERROR);
return (BAM_ERROR);
return (BAM_SUCCESS);
int found;
char *cp;
found = 0;
if (!found) {
if (bam_verbose)
if (bam_verbose)
if (bam_verbose)
if (bam_verbose)
if (bam_verbose)
static error_t
return (BAM_SUCCESS);
return (BAM_SUCCESS);
if (bam_verbose)
return (BAM_SUCCESS);
if (bam_verbose)
return (BAM_SUCCESS);
if (bam_check) {
return (ret);
update_fdisk(void)
restore_grub_slice(void)
mnted = 0;
static error_t
return (BAM_ERROR);
goto out;
goto out;
goto out;
out:
update_fdisk();
return (ret);
static entry_t *
return (ent);
return (ent);
if (ent)
static int in_liveupgrade = 0;
str++;
in_liveupgrade = 0;
str++;
str++;
str++;
if (in_liveupgrade) {
int lineNum;
int entryNum;
int old_default_value;
static menu_t *
return (mp);
return (mp);
static error_t
char *eq;
char *opt_dup;
int entryNum;
if (entry)
if (title)
return (BAM_ERROR);
return (BAM_ERROR);
return (BAM_ERROR);
return (BAM_SUCCESS);
static error_t
int found;
return (BAM_ERROR);
return (BAM_ERROR);
found = 0;
if (!found) {
return (BAM_ERROR);
return (BAM_SUCCESS);
char *title,
char *root,
char *kernel,
char *module)
return (BAM_ERROR);
return (BAM_ERROR);
if (root) {
return (entryNum);
static error_t
int deleted;
while (ent) {
if (ent)
return (BAM_ERROR);
return (BAM_SUCCESS);
static error_t
return (BAM_SUCCESS);
return (BAM_ERROR);
return (BAM_WRITE);
static FILE *
return (fp);
if (!is_pcfs)
if (!is_pcfs)
return (partno);
for (i = 0; i < FD_NUMPART; i++) {
partno = i;
partno = i;
return (partno);
char *slice;
char *grubhd;
int fdiskpart;
int found = 0;
return (NULL);
if (slice)
if (grubhd)
if (slice)
if (found == 0) {
if (bam_verbose)
return (NULL);
if (slice) {
if (!on_bootdev)
return (grubdisk);
return (NULL);
if (cp)
return (NULL);
char *grubdisk;
return (NULL);
return (grubdisk);
int ret;
if (bootp)
return (ret);
static entry_t *
if (title) {
if (root_opt == 0) {
*entry_num = i;
return (ent);
int i, change_kernel = 0;
root_opt, &i);
if (change_kernel) {
kernel);
module);
static error_t
int entry;
return (BAM_ERROR);
return (BAM_ERROR);
return (BAM_ERROR);
return (BAM_WRITE);
read_grub_root(void)
char *rootstr;
return (NULL);
return (NULL);
return (NULL);
return (NULL);
return (rootstr);
if (lp)
int entry;
char *str;
static error_t
int entry;
0, &entry);
return (BAM_SUCCESS);
return (BAM_WRITE);
if (rootdev) {
return (BAM_ERROR);
!= BAM_SUCCESS)
return (BAM_ERROR);
BUFSIZ);
return (BAM_ERROR);
BUFSIZ);
BUFSIZ);
return (BAM_ERROR);
BUFSIZ);
return (BAM_ERROR);
NULL);
return (BAM_ERROR);
return (BAM_WRITE);
static error_t
return (BAM_ERROR);
if (found) {
return (BAM_WRITE);
int new_path_len;
return (new_path);
return (new_path);
return (new_path);
return (NULL);
char *new_archive;
static error_t
char old_space;
return (BAM_ERROR);
return (BAM_ERROR);
&entryNum);
return (BAM_ERROR);
old_args++;
return (BAM_SUCCESS);
return (BAM_SUCCESS);
return (BAM_SUCCESS);
goto done;
goto done;
return (BAM_ERROR);
free_new_path = 0;
if (rootdev) {
goto done;
goto done;
old_args);
done:
if (free_new_path)
return (rv);
static error_t
char *val;
return (BAM_ERROR);
return (BAM_ERROR);
return (rv);
static error_t
char *arg;
if (!quiet)
return (BAM_ERROR);
done = 0;
if (!quiet)
return (ret);
static error_t
while (start) {
while (ent) {
int ret;
void (*disp)(int);
errno = 0;
if (buf) {
return (buf);
void *ptr;
return (ptr);
return (ptr);
char *ptr;
return (NULL);
return (ptr);
is_amd64(void)
return (amd64);
amd64 = 0;
return (amd64);