bootadm.c revision 9632cfad671ee03057c5878b18702ea3b53be47d
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * CDDL HEADER START
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The contents of this file are subject to the terms of the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Common Development and Distribution License (the "License").
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * You may not use this file except in compliance with the License.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * See the License for the specific language governing permissions
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * and limitations under the License.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * When distributing Covered Code, include this CDDL HEADER in each
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * If applicable, add the following below this CDDL HEADER, with the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * fields enclosed by brackets "[]" replaced with your own identifying
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * information: Portions Copyright [yyyy] [name of copyright owner]
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * CDDL HEADER END
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Use is subject to license terms.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#pragma ident "%Z%%M% %I% %E% SMI"
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * bootadm(1M) is a new utility for managing bootability of
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Solaris *Newboot* environments. It has two primary tasks:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * - Allow end users to manage bootability of Newboot Solaris instances
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * - Provide services to other subsystems in Solaris (primarily Install)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/* Headers */
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as#endif /* TEXT_DOMAIN */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/* Type definitions */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/* Primary subcmds */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwtypedef enum {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/* GRUB menu per-line classification */
dc20a3024900c47dd2ee44b9707e6df38f7d62a5astypedef enum {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/* struct for menu.lst contents */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwtypedef struct line {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int entryNum; /* menu boot entry #. ENTRY_INIT if not applicable */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwtypedef struct entry {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwtypedef struct {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwtypedef enum {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwtypedef enum {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw BAM_ERROR = -1, /* Must be negative. add_boot_entry() depends on it */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwtypedef struct {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/* lock related */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#define LOCK_FILE_PERMS (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#define CREATE_RAMDISK "/boot/solaris/bin/create_ramdisk"
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#define CREATE_DISKMAP "/boot/solaris/bin/create_diskmap"
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#define LU_ACTIVATE_FILE "/etc/lu/DelayUpdate/activate.sh"
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Default file attributes
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Menu related
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * menu_cmd_t and menu_cmds must be kept in sync
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwtypedef enum {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic char *menu_cmds[] = {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * archive related
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwtypedef struct {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#define ETC_FILE_LIST "etc/boot/solaris/filelist.ramdisk"
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#define FILE_STAT_TMP "boot/solaris/filestat.ramdisk.tmp"
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#define DIR_PERMS (S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#define BAM_HDR "---------- ADDED BY BOOTADM - DO NOT EDIT ----------"
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#define BAM_FTR "---------------------END BOOTADM--------------------"
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/* Globals */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic char *prog;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic char *bam_root;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic char *bam_subcmd;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic char *bam_opt;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic char **bam_argv;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/* function prototypes */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic error_t bam_menu(char *subcmd, char *opt, int argc, char *argv[]);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic void bam_lock(void);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic void bam_unlock(void);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int exec_cmd(char *cmdline, char *output, int64_t osize);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic error_t list_entry(menu_t *mp, char *menu_path, char *opt);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic error_t delete_all_entries(menu_t *mp, char *menu_path, char *opt);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic error_t update_entry(menu_t *mp, char *root, char *opt);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic error_t update_temp(menu_t *mp, char *root, char *opt);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic error_t read_list(char *root, filelist_t *flistp);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic error_t set_global(menu_t *mp, char *globalcmd, int val);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic error_t set_option(menu_t *mp, char *globalcmd, char *opt);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int is_readonly(char *);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int is_amd64(void);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#if defined(__sparc)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic void sparc_abort(void);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/* Menu related sub commands */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw "delete_all_entries", OPT_ABSENT, delete_all_entries, 0, /* PVT */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw "update_temp", OPT_OPTIONAL, update_temp, 0, /* reboot */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/* Archive related sub commands */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic struct {
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) {
return (BAM_ERROR);
usage();
return (BAM_ERROR);
} else if (largc != 0) {
usage();
return (BAM_ERROR);
return (ret);
static error_t
char *subcmd,
char *opt)
return (BAM_ERROR);
#if defined(__sparc)
return (BAM_SUCCESS);
sparc_abort();
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_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) {
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_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;
out:
update_fdisk();
return (ret);
static entry_t *
return (ent);
return (ent);
if (ent)
str++;
str++;
str++;
str++;
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);
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);
"/platform/i86pc/boot_archive");
return (BAM_ERROR);
return (BAM_WRITE);
static error_t
return (BAM_ERROR);
if (found) {
return (BAM_WRITE);
static error_t
char *val;
return (BAM_ERROR);
return (BAM_ERROR);
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);
char *ptr;
return (NULL);
return (ptr);
is_amd64(void)
return (amd64);
amd64 = 0;
return (amd64);