bootadm.c revision 40541d5d290c13c7837bf676a9b7d6302a2acbb5
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * CDDL HEADER START
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * The contents of this file are subject to the terms of the
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * Common Development and Distribution License, Version 1.0 only
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * (the "License"). You may not use this file except in compliance
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * with the License.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * See the License for the specific language governing permissions
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * and limitations under the License.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * When distributing Covered Code, include this CDDL HEADER in each
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * If applicable, add the following below this CDDL HEADER, with the
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * fields enclosed by brackets "[]" replaced with your own identifying
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * information: Portions Copyright [yyyy] [name of copyright owner]
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * CDDL HEADER END
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * Use is subject to license terms.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk#pragma ident "%Z%%M% %I% %E% SMI"
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * bootadm(1M) is a new utility for managing bootability of
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * Solaris *Newboot* environments. It has two primary tasks:
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * - Allow end users to manage bootability of Newboot Solaris instances
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * - Provide services to other subsystems in Solaris (primarily Install)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk/* Headers */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk#endif /* TEXT_DOMAIN */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk/* Type definitions */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk/* Primary subcmds */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenktypedef enum {
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk/* GRUB menu per-line classification */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenktypedef enum {
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk/* struct for menu.lst contents */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenktypedef struct line {
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk int entryNum; /* menu boot entry #. ENTRY_INIT if not applicable */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenktypedef struct {
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenktypedef enum {
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk OPT_OPTIONAL /* option may or may not be present */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenktypedef enum {
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk BAM_ERROR = -1, /* Must be negative. add_boot_entry() depends on it */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenktypedef struct {
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk#define ENTRY_INIT -1 /* entryNum initial value */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk#define ALL_ENTRIES -2 /* selects all boot entries */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk#define BOOT_ARCHIVE "/platform/i86pc/boot_archive"
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk/* lock related */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk#define LOCK_FILE_PERMS (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk#define CREATE_RAMDISK "/boot/solaris/bin/create_ramdisk"
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk#define CREATE_DISKMAP "/boot/solaris/bin/create_diskmap"
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk#define GRUBDISK_MAP "/var/run/solaris_grubdisk.map"
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk#define GRUB_backup_menu "/etc/lu/GRUB_backup_menu"
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk#define LU_ACTIVATE_FILE "/etc/lu/DelayUpdate/activate.sh"
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * Default file attributes
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk#define DEFAULT_DEV_MODE 0644 /* default permissions */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * Menu related
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * menu_cmd_t and menu_cmds must be kept in sync
DEFAULT_CMD = 0,
} menu_cmd_t;
static char *menu_cmds[] = {
} filelist_t;
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_force;
static int bam_verbose;
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;
usage(void)
prog);
#ifndef __sparc
prog++;
if (geteuid() != 0) {
bam_lock();
#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);
return (BAM_ERROR);
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
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_check) {
return (ret);
restore_grub_slice(void)
mnted = 0;
static error_t
return (BAM_ERROR);
goto out;
out:
return (ret);
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);
return (BAM_ERROR);
return (BAM_ERROR);
return (BAM_ERROR);
return (BAM_ERROR);
return (BAM_ERROR);
return (BAM_ERROR);
return (BAM_ERROR);
return (BAM_ERROR);
return (entryNum);
static error_t
int bootadm_entry = 0;
int deleted;
deleted = 0;
if (!bootadm_entry) {
bootadm_entry = 0;
return (BAM_ERROR);
return (BAM_SUCCESS);
static error_t
return (BAM_SUCCESS);
return (BAM_ERROR);
return (BAM_ERROR);
return (BAM_ERROR);
return (BAM_WRITE);
static error_t
return (BAM_SUCCESS);
return (BAM_ERROR);
return (BAM_WRITE);
static FILE *
open_diskmap(void)
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);
if (cp)
return (cp);
return (NULL);
char *grubdisk;
return (NULL);
return (grubdisk);
int ret;
if (bootp)
return (ret);
static error_t
int entry;
return (BAM_ERROR);
return (BAM_ERROR);
bootadm_entry = 0;
bootadm_entry = 0;
"/platform/i86pc/boot_archive");
"/boot/x86.miniroot-safe");
return (BAM_ERROR);
return (BAM_WRITE);
read_grub_root(void)
char *rootstr;
return (NULL);
return (NULL);
return (NULL);
return (NULL);
return (rootstr);
static error_t
int entry;
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) {
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);