1f64ca102SToomas Soome /* 2f64ca102SToomas Soome * CDDL HEADER START 3f64ca102SToomas Soome * 4f64ca102SToomas Soome * The contents of this file are subject to the terms of the 5f64ca102SToomas Soome * Common Development and Distribution License (the "License"). 6f64ca102SToomas Soome * You may not use this file except in compliance with the License. 7f64ca102SToomas Soome * 8f64ca102SToomas Soome * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9f64ca102SToomas Soome * or http://www.opensolaris.org/os/licensing. 10f64ca102SToomas Soome * See the License for the specific language governing permissions 11f64ca102SToomas Soome * and limitations under the License. 12f64ca102SToomas Soome * 13f64ca102SToomas Soome * When distributing Covered Code, include this CDDL HEADER in each 14f64ca102SToomas Soome * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15f64ca102SToomas Soome * If applicable, add the following below this CDDL HEADER, with the 16f64ca102SToomas Soome * fields enclosed by brackets "[]" replaced with your own identifying 17f64ca102SToomas Soome * information: Portions Copyright [yyyy] [name of copyright owner] 18f64ca102SToomas Soome * 19f64ca102SToomas Soome * CDDL HEADER END 20f64ca102SToomas Soome */ 21f64ca102SToomas Soome /* 22f64ca102SToomas Soome * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 23f64ca102SToomas Soome * Copyright 2012 Milan Jurik. All rights reserved. 24f64ca102SToomas Soome */ 25f64ca102SToomas Soome 26f64ca102SToomas Soome /* 27f64ca102SToomas Soome * Copyright 2015 Nexenta Systems, Inc. All rights reserved. 28f64ca102SToomas Soome * Copyright 2016 Toomas Soome <tsoome@me.com> 29*71668a2fSAndy Fiddaman * Copyright 2018 OmniOS Community Edition (OmniOSce) Association. 30f64ca102SToomas Soome */ 31f64ca102SToomas Soome 32f64ca102SToomas Soome /* 33f64ca102SToomas Soome * Loader menu management. 34f64ca102SToomas Soome */ 35f64ca102SToomas Soome 36f64ca102SToomas Soome #include <stdio.h> 37f64ca102SToomas Soome #include <stdlib.h> 38f64ca102SToomas Soome #include <string.h> 39f64ca102SToomas Soome #include <wchar.h> 40f64ca102SToomas Soome #include <errno.h> 41f64ca102SToomas Soome #include <limits.h> 42f64ca102SToomas Soome #include <alloca.h> 43f64ca102SToomas Soome #include <unistd.h> 44f64ca102SToomas Soome #include <sys/types.h> 45f64ca102SToomas Soome #include <sys/stat.h> 46f64ca102SToomas Soome #include <sys/queue.h> 47f64ca102SToomas Soome #include <libbe.h> 48f64ca102SToomas Soome #include <ficl.h> 49f64ca102SToomas Soome #include <ficlplatform/emu.h> 50353ca6f2SToomas Soome #include <ofmt.h> 51f64ca102SToomas Soome 52f64ca102SToomas Soome #include "bootadm.h" 53f64ca102SToomas Soome 54f64ca102SToomas Soome extern int bam_rootlen; 55f64ca102SToomas Soome extern int bam_alt_root; 56f64ca102SToomas Soome extern char *rootbuf; 57f64ca102SToomas Soome extern char *bam_root; 58f64ca102SToomas Soome 59f64ca102SToomas Soome #define BOOT_DIR "/boot" 60f64ca102SToomas Soome #define CONF_DIR BOOT_DIR "/conf.d" 61f64ca102SToomas Soome #define MENU BOOT_DIR "/menu.lst" 62f64ca102SToomas Soome #define TRANSIENT BOOT_DIR "/transient.conf" 63f64ca102SToomas Soome #define XEN_CONFIG CONF_DIR "/xen" 64f64ca102SToomas Soome 65353ca6f2SToomas Soome typedef struct menu_entry { 66353ca6f2SToomas Soome int me_idx; 67353ca6f2SToomas Soome boolean_t me_active; 68353ca6f2SToomas Soome char *me_title; 69353ca6f2SToomas Soome char *me_type; 70353ca6f2SToomas Soome char *me_bootfs; 71353ca6f2SToomas Soome STAILQ_ENTRY(menu_entry) me_next; 72353ca6f2SToomas Soome } menu_entry_t; 73f64ca102SToomas Soome STAILQ_HEAD(menu_lst, menu_entry); 74f64ca102SToomas Soome 75f64ca102SToomas Soome static error_t set_option(struct menu_lst *, char *, char *); 76f64ca102SToomas Soome static error_t list_entry(struct menu_lst *, char *, char *); 77f64ca102SToomas Soome static error_t update_entry(struct menu_lst *, char *, char *); 78f64ca102SToomas Soome static error_t update_temp(struct menu_lst *, char *, char *); 79f64ca102SToomas Soome static error_t list_setting(struct menu_lst *menu, char *, char *); 80f64ca102SToomas Soome static error_t disable_hyper(struct menu_lst *, char *, char *); 81f64ca102SToomas Soome static error_t enable_hyper(struct menu_lst *, char *, char *); 82f64ca102SToomas Soome 83f64ca102SToomas Soome /* Menu related sub commands */ 84f64ca102SToomas Soome static subcmd_defn_t menu_subcmds[] = { 85f64ca102SToomas Soome "set_option", OPT_ABSENT, set_option, 0, /* PUB */ 86f64ca102SToomas Soome "list_entry", OPT_OPTIONAL, list_entry, 1, /* PUB */ 87f64ca102SToomas Soome "update_entry", OPT_REQ, update_entry, 0, /* menu */ 88f64ca102SToomas Soome "update_temp", OPT_OPTIONAL, update_temp, 0, /* reboot */ 89f64ca102SToomas Soome "list_setting", OPT_OPTIONAL, list_setting, 1, /* menu */ 90f64ca102SToomas Soome "disable_hypervisor", OPT_ABSENT, disable_hyper, 0, /* menu */ 91f64ca102SToomas Soome "enable_hypervisor", OPT_ABSENT, enable_hyper, 0, /* menu */ 92f64ca102SToomas Soome NULL, 0, NULL, 0 /* must be last */ 93f64ca102SToomas Soome }; 94f64ca102SToomas Soome 95353ca6f2SToomas Soome #define NUM_COLS (5) 96f64ca102SToomas Soome 97353ca6f2SToomas Soome static boolean_t 98353ca6f2SToomas Soome print_menu_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize) 99f64ca102SToomas Soome { 100353ca6f2SToomas Soome menu_entry_t *entry = ofarg->ofmt_cbarg; 101f64ca102SToomas Soome 102353ca6f2SToomas Soome switch (ofarg->ofmt_id) { 103353ca6f2SToomas Soome case 0: 104353ca6f2SToomas Soome (void) snprintf(buf, bufsize, "%d", entry->me_idx); 105353ca6f2SToomas Soome break; 106353ca6f2SToomas Soome case 1: 107353ca6f2SToomas Soome (void) snprintf(buf, bufsize, "%s", entry->me_title); 108353ca6f2SToomas Soome break; 109353ca6f2SToomas Soome case 2: 110353ca6f2SToomas Soome (void) snprintf(buf, bufsize, "%s", entry->me_bootfs); 111353ca6f2SToomas Soome break; 112353ca6f2SToomas Soome case 3: 113353ca6f2SToomas Soome (void) snprintf(buf, bufsize, "%s", entry->me_type); 114353ca6f2SToomas Soome break; 115353ca6f2SToomas Soome case 4: 116353ca6f2SToomas Soome if (entry->me_active == B_TRUE) 117353ca6f2SToomas Soome (void) snprintf(buf, bufsize, " *"); 118353ca6f2SToomas Soome else 119353ca6f2SToomas Soome (void) snprintf(buf, bufsize, " -"); 120353ca6f2SToomas Soome break; 121353ca6f2SToomas Soome default: 122353ca6f2SToomas Soome return (B_FALSE); 123f64ca102SToomas Soome } 124353ca6f2SToomas Soome return (B_TRUE); 125f64ca102SToomas Soome } 126f64ca102SToomas Soome 127f64ca102SToomas Soome static void 128353ca6f2SToomas Soome init_hdr_cols(ofmt_field_t *hdr) 129f64ca102SToomas Soome { 130353ca6f2SToomas Soome uint_t i; 131f64ca102SToomas Soome 132f64ca102SToomas Soome for (i = 0; i < NUM_COLS; i++) { 133353ca6f2SToomas Soome char *name = NULL; 134353ca6f2SToomas Soome 135353ca6f2SToomas Soome switch (i) { 136353ca6f2SToomas Soome case 0: 137353ca6f2SToomas Soome name = _("INDEX"); 138353ca6f2SToomas Soome break; 139353ca6f2SToomas Soome case 1: 140353ca6f2SToomas Soome name = _("NAME"); 141353ca6f2SToomas Soome break; 142353ca6f2SToomas Soome case 2: 143353ca6f2SToomas Soome name = _("DEVICE"); 144353ca6f2SToomas Soome break; 145353ca6f2SToomas Soome case 3: 146353ca6f2SToomas Soome name = _("TYPE"); 147353ca6f2SToomas Soome break; 148353ca6f2SToomas Soome case 4: 149353ca6f2SToomas Soome name = _("DEFAULT"); 150353ca6f2SToomas Soome break; 151353ca6f2SToomas Soome } 152353ca6f2SToomas Soome 153353ca6f2SToomas Soome hdr[i].of_name = name; 154353ca6f2SToomas Soome hdr[i].of_id = i; 155353ca6f2SToomas Soome hdr[i].of_cb = print_menu_cb; 156f64ca102SToomas Soome 157f64ca102SToomas Soome if (name != NULL) { 158f64ca102SToomas Soome wchar_t wname[128]; 159f64ca102SToomas Soome size_t sz = mbstowcs(wname, name, sizeof (wname) / 160f64ca102SToomas Soome sizeof (wchar_t)); 161f64ca102SToomas Soome if (sz > 0) { 162f64ca102SToomas Soome int wcsw = wcswidth(wname, sz); 163f64ca102SToomas Soome if (wcsw > 0) 164353ca6f2SToomas Soome hdr[i].of_width = wcsw; 165f64ca102SToomas Soome else 166353ca6f2SToomas Soome hdr[i].of_width = sz; 167f64ca102SToomas Soome } else { 168353ca6f2SToomas Soome hdr[i].of_width = strlen(name); 169f64ca102SToomas Soome } 170f64ca102SToomas Soome } 171f64ca102SToomas Soome } 172f64ca102SToomas Soome } 173f64ca102SToomas Soome 174f64ca102SToomas Soome static void 175353ca6f2SToomas Soome menu_update_widths(ofmt_field_t *hdr, struct menu_lst *menu) 176f64ca102SToomas Soome { 177f64ca102SToomas Soome size_t len[NUM_COLS]; 178353ca6f2SToomas Soome menu_entry_t *entry; 179f64ca102SToomas Soome int i; 180f64ca102SToomas Soome 181f64ca102SToomas Soome for (i = 0; i < NUM_COLS; i++) 182353ca6f2SToomas Soome len[i] = hdr[i].of_width + 1; 183f64ca102SToomas Soome 184353ca6f2SToomas Soome STAILQ_FOREACH(entry, menu, me_next) { 185353ca6f2SToomas Soome size_t entry_len; 186353ca6f2SToomas Soome 187353ca6f2SToomas Soome entry_len = strlen(entry->me_title) + 1; 188353ca6f2SToomas Soome if (entry_len > len[1]) 189353ca6f2SToomas Soome len[1] = entry_len; 190353ca6f2SToomas Soome 191353ca6f2SToomas Soome entry_len = strlen(entry->me_bootfs) + 1; 192353ca6f2SToomas Soome if (entry_len > len[2]) 193353ca6f2SToomas Soome len[2] = entry_len; 194353ca6f2SToomas Soome 195353ca6f2SToomas Soome entry_len = strlen(entry->me_type) + 1; 196353ca6f2SToomas Soome if (entry_len > len[3]) 197353ca6f2SToomas Soome len[3] = entry_len; 198f64ca102SToomas Soome } 199f64ca102SToomas Soome 200f64ca102SToomas Soome for (i = 0; i < NUM_COLS; i++) 201353ca6f2SToomas Soome hdr[i].of_width = len[i]; 202f64ca102SToomas Soome } 203f64ca102SToomas Soome 204353ca6f2SToomas Soome static ofmt_field_t * 205353ca6f2SToomas Soome init_menu_template(struct menu_lst *menu) 206f64ca102SToomas Soome { 207353ca6f2SToomas Soome ofmt_field_t *temp; 208f64ca102SToomas Soome 209353ca6f2SToomas Soome if ((temp = calloc(NUM_COLS + 1, sizeof (ofmt_field_t))) == NULL) 210353ca6f2SToomas Soome return (temp); 211f64ca102SToomas Soome 212353ca6f2SToomas Soome init_hdr_cols(temp); 213353ca6f2SToomas Soome menu_update_widths(temp, menu); 214353ca6f2SToomas Soome return (temp); 215f64ca102SToomas Soome } 216f64ca102SToomas Soome 217f64ca102SToomas Soome static void 218f64ca102SToomas Soome print_nodes(boolean_t parsable, struct menu_lst *menu) 219f64ca102SToomas Soome { 220353ca6f2SToomas Soome ofmt_status_t oferr; 221353ca6f2SToomas Soome ofmt_handle_t ofmt; 222353ca6f2SToomas Soome uint_t ofmtflags = 0; 223353ca6f2SToomas Soome ofmt_field_t *menu_template; 224353ca6f2SToomas Soome menu_entry_t *entry; 225f64ca102SToomas Soome 226353ca6f2SToomas Soome if (parsable == B_TRUE) 227353ca6f2SToomas Soome ofmtflags = OFMT_PARSABLE; 228353ca6f2SToomas Soome 229353ca6f2SToomas Soome menu_template = init_menu_template(menu); 230353ca6f2SToomas Soome oferr = ofmt_open(NULL, menu_template, ofmtflags, 0, &ofmt); 231353ca6f2SToomas Soome 232353ca6f2SToomas Soome if (oferr != OFMT_SUCCESS) { 233353ca6f2SToomas Soome char buf[OFMT_BUFSIZE]; 234353ca6f2SToomas Soome 235353ca6f2SToomas Soome (void) ofmt_strerror(ofmt, oferr, buf, sizeof (buf)); 236353ca6f2SToomas Soome (void) printf("bootadm: %s\n", buf); 237353ca6f2SToomas Soome free(menu_template); 238353ca6f2SToomas Soome return; 239f64ca102SToomas Soome } 240f64ca102SToomas Soome 241353ca6f2SToomas Soome STAILQ_FOREACH(entry, menu, me_next) 242353ca6f2SToomas Soome ofmt_print(ofmt, entry); 243353ca6f2SToomas Soome 244353ca6f2SToomas Soome ofmt_close(ofmt); 245353ca6f2SToomas Soome free(menu_template); 246353ca6f2SToomas Soome } 247353ca6f2SToomas Soome 248353ca6f2SToomas Soome /* 249353ca6f2SToomas Soome * Get the be_active_on_boot for bootfs. 250353ca6f2SToomas Soome */ 251353ca6f2SToomas Soome static boolean_t 252353ca6f2SToomas Soome menu_active_on_boot(be_node_list_t *be_nodes, const char *bootfs) 253353ca6f2SToomas Soome { 254353ca6f2SToomas Soome be_node_list_t *be_node; 255353ca6f2SToomas Soome boolean_t rv = B_FALSE; 256353ca6f2SToomas Soome 257353ca6f2SToomas Soome for (be_node = be_nodes; be_node != NULL; 258353ca6f2SToomas Soome be_node = be_node->be_next_node) { 259353ca6f2SToomas Soome if (strcmp(be_node->be_root_ds, bootfs) == 0) { 260353ca6f2SToomas Soome rv = be_node->be_active_on_boot; 261353ca6f2SToomas Soome break; 262353ca6f2SToomas Soome } 263353ca6f2SToomas Soome } 264353ca6f2SToomas Soome 265353ca6f2SToomas Soome return (rv); 266f64ca102SToomas Soome } 267f64ca102SToomas Soome 268f64ca102SToomas Soome error_t 269f64ca102SToomas Soome menu_read(struct menu_lst *menu, char *menu_path) 270f64ca102SToomas Soome { 271f64ca102SToomas Soome FILE *fp; 272353ca6f2SToomas Soome be_node_list_t *be_nodes; 273353ca6f2SToomas Soome menu_entry_t *mp; 274f64ca102SToomas Soome char buf[PATH_MAX]; 275f64ca102SToomas Soome char *title; 276f64ca102SToomas Soome char *bootfs; 277353ca6f2SToomas Soome char *type; 278353ca6f2SToomas Soome char *key, *value; 279f64ca102SToomas Soome int i = 0; 280f64ca102SToomas Soome int ret = BAM_SUCCESS; 281f64ca102SToomas Soome 282f64ca102SToomas Soome fp = fopen(menu_path, "r"); 283f64ca102SToomas Soome if (fp == NULL) 284f64ca102SToomas Soome return (BAM_ERROR); 285f64ca102SToomas Soome 286*71668a2fSAndy Fiddaman if (be_list(NULL, &be_nodes, BE_LIST_DEFAULT) != BE_SUCCESS) 287353ca6f2SToomas Soome be_nodes = NULL; 288353ca6f2SToomas Soome 289f64ca102SToomas Soome /* 290f64ca102SToomas Soome * menu.lst entry is on two lines, one for title, one for bootfs 291f64ca102SToomas Soome * so we process both lines in succession. 292f64ca102SToomas Soome */ 293353ca6f2SToomas Soome title = NULL; 294353ca6f2SToomas Soome type = NULL; 295353ca6f2SToomas Soome bootfs = NULL; 296f64ca102SToomas Soome do { 297f64ca102SToomas Soome if (fgets(buf, PATH_MAX, fp) == NULL) { 298f64ca102SToomas Soome if (!feof(fp)) 299f64ca102SToomas Soome ret = BAM_ERROR; 300353ca6f2SToomas Soome goto done; 301f64ca102SToomas Soome } 302353ca6f2SToomas Soome key = strtok(buf, " \n"); 303353ca6f2SToomas Soome if (strcmp(key, "title") != 0) { 304353ca6f2SToomas Soome ret = BAM_ERROR; 305353ca6f2SToomas Soome goto done; 306f64ca102SToomas Soome } 307353ca6f2SToomas Soome value = strtok(NULL, " \n"); 308353ca6f2SToomas Soome if ((title = strdup(value)) == NULL) { 309353ca6f2SToomas Soome ret = BAM_ERROR; 310353ca6f2SToomas Soome goto done; 311f64ca102SToomas Soome } 312f64ca102SToomas Soome 313f64ca102SToomas Soome if (fgets(buf, PATH_MAX, fp) == NULL) { 314353ca6f2SToomas Soome ret = BAM_ERROR; 315353ca6f2SToomas Soome goto done; 316f64ca102SToomas Soome } 317f64ca102SToomas Soome 318353ca6f2SToomas Soome key = strtok(buf, " \n"); 319353ca6f2SToomas Soome if ((type = strdup(key)) == NULL) { 320353ca6f2SToomas Soome ret = BAM_ERROR; 321353ca6f2SToomas Soome goto done; 322353ca6f2SToomas Soome } 323353ca6f2SToomas Soome value = strtok(NULL, " \n"); 324353ca6f2SToomas Soome if ((bootfs = strdup(value)) == NULL) { 325353ca6f2SToomas Soome ret = BAM_ERROR; 326353ca6f2SToomas Soome goto done; 327353ca6f2SToomas Soome } 328353ca6f2SToomas Soome if ((mp = malloc(sizeof (menu_entry_t))) == NULL) { 329353ca6f2SToomas Soome ret = BAM_ERROR; 330353ca6f2SToomas Soome goto done; 331353ca6f2SToomas Soome } 332353ca6f2SToomas Soome mp->me_idx = i++; 333353ca6f2SToomas Soome mp->me_title = title; 334353ca6f2SToomas Soome mp->me_type = type; 335353ca6f2SToomas Soome mp->me_bootfs = bootfs; 336353ca6f2SToomas Soome mp->me_active = menu_active_on_boot(be_nodes, bootfs); 337353ca6f2SToomas Soome STAILQ_INSERT_TAIL(menu, mp, me_next); 338f64ca102SToomas Soome 339353ca6f2SToomas Soome title = NULL; 340353ca6f2SToomas Soome type = NULL; 341353ca6f2SToomas Soome bootfs = NULL; 342f64ca102SToomas Soome } while (feof(fp) == 0); 343f64ca102SToomas Soome 344353ca6f2SToomas Soome done: 345353ca6f2SToomas Soome free(title); 346353ca6f2SToomas Soome free(type); 347353ca6f2SToomas Soome free(bootfs); 348f64ca102SToomas Soome (void) fclose(fp); 349353ca6f2SToomas Soome be_free_list(be_nodes); 350f64ca102SToomas Soome return (ret); 351f64ca102SToomas Soome } 352f64ca102SToomas Soome 353f64ca102SToomas Soome void 354f64ca102SToomas Soome menu_free(struct menu_lst *menu) 355f64ca102SToomas Soome { 356353ca6f2SToomas Soome menu_entry_t *entry; 357353ca6f2SToomas Soome STAILQ_FOREACH(entry, menu, me_next) { 358353ca6f2SToomas Soome STAILQ_REMOVE_HEAD(menu, me_next); 359353ca6f2SToomas Soome free(entry->me_title); 360353ca6f2SToomas Soome free(entry->me_type); 361353ca6f2SToomas Soome free(entry->me_bootfs); 362f64ca102SToomas Soome free(entry); 363f64ca102SToomas Soome } 364f64ca102SToomas Soome } 365f64ca102SToomas Soome 366f64ca102SToomas Soome error_t 367f64ca102SToomas Soome bam_loader_menu(char *subcmd, char *opt, int largc, char *largv[]) 368f64ca102SToomas Soome { 369f64ca102SToomas Soome error_t ret; 370f64ca102SToomas Soome char menu_path[PATH_MAX]; 371f64ca102SToomas Soome char clean_menu_root[PATH_MAX]; 372f64ca102SToomas Soome char menu_root[PATH_MAX]; 373f64ca102SToomas Soome struct stat sb; 374f64ca102SToomas Soome error_t (*f)(struct menu_lst *, char *, char *); 375f64ca102SToomas Soome char *special; 376f64ca102SToomas Soome char *pool = NULL; 377f64ca102SToomas Soome zfs_mnted_t zmnted; 378f64ca102SToomas Soome char *zmntpt; 379f64ca102SToomas Soome char *osdev; 380f64ca102SToomas Soome char *osroot; 381f64ca102SToomas Soome const char *fcn = "bam_loader_menu()"; 382f64ca102SToomas Soome struct menu_lst menu = {0}; 383f64ca102SToomas Soome 384f64ca102SToomas Soome STAILQ_INIT(&menu); 385f64ca102SToomas Soome 386f64ca102SToomas Soome /* 387f64ca102SToomas Soome * Check arguments 388f64ca102SToomas Soome */ 389f64ca102SToomas Soome ret = check_subcmd_and_options(subcmd, opt, menu_subcmds, &f); 390f64ca102SToomas Soome if (ret == BAM_ERROR) { 391f64ca102SToomas Soome return (BAM_ERROR); 392f64ca102SToomas Soome } 393f64ca102SToomas Soome 394f64ca102SToomas Soome assert(bam_root); 395f64ca102SToomas Soome 396f64ca102SToomas Soome (void) strlcpy(menu_root, bam_root, sizeof (menu_root)); 397f64ca102SToomas Soome osdev = osroot = NULL; 398f64ca102SToomas Soome 399f64ca102SToomas Soome if (strcmp(subcmd, "update_entry") == 0) { 400f64ca102SToomas Soome assert(opt); 401f64ca102SToomas Soome 402f64ca102SToomas Soome osdev = strtok(opt, ","); 403f64ca102SToomas Soome assert(osdev); 404f64ca102SToomas Soome osroot = strtok(NULL, ","); 405f64ca102SToomas Soome if (osroot) { 406f64ca102SToomas Soome /* fixup bam_root so that it points at osroot */ 407f64ca102SToomas Soome if (realpath(osroot, rootbuf) == NULL) { 408f64ca102SToomas Soome bam_error(_("cannot resolve path %s: %s\n"), 409f64ca102SToomas Soome osroot, strerror(errno)); 410f64ca102SToomas Soome return (BAM_ERROR); 411f64ca102SToomas Soome } 412f64ca102SToomas Soome bam_alt_root = 1; 413f64ca102SToomas Soome bam_root = rootbuf; 414f64ca102SToomas Soome bam_rootlen = strlen(rootbuf); 415f64ca102SToomas Soome } 416f64ca102SToomas Soome } 417f64ca102SToomas Soome 418f64ca102SToomas Soome if (stat(menu_root, &sb) == -1) { 419f64ca102SToomas Soome bam_error(_("cannot find menu\n")); 420f64ca102SToomas Soome return (BAM_ERROR); 421f64ca102SToomas Soome } 422f64ca102SToomas Soome 423f64ca102SToomas Soome if (!is_zfs(menu_root)) { 424f64ca102SToomas Soome bam_error(_("only ZFS root is supported\n")); 425f64ca102SToomas Soome return (BAM_ERROR); 426f64ca102SToomas Soome } 427f64ca102SToomas Soome 428f64ca102SToomas Soome assert(strcmp(menu_root, bam_root) == 0); 429f64ca102SToomas Soome special = get_special(menu_root); 430f64ca102SToomas Soome INJECT_ERROR1("Z_MENU_GET_SPECIAL", special = NULL); 431f64ca102SToomas Soome if (special == NULL) { 432f64ca102SToomas Soome bam_error(_("cant find special file for mount-point %s\n"), 433f64ca102SToomas Soome menu_root); 434f64ca102SToomas Soome return (BAM_ERROR); 435f64ca102SToomas Soome } 436f64ca102SToomas Soome pool = strtok(special, "/"); 437f64ca102SToomas Soome INJECT_ERROR1("Z_MENU_GET_POOL", pool = NULL); 438f64ca102SToomas Soome if (pool == NULL) { 439f64ca102SToomas Soome free(special); 440f64ca102SToomas Soome bam_error(_("cant find pool for mount-point %s\n"), menu_root); 441f64ca102SToomas Soome return (BAM_ERROR); 442f64ca102SToomas Soome } 443f64ca102SToomas Soome BAM_DPRINTF(("%s: derived pool=%s from special\n", fcn, pool)); 444f64ca102SToomas Soome 445f64ca102SToomas Soome zmntpt = mount_top_dataset(pool, &zmnted); 446f64ca102SToomas Soome INJECT_ERROR1("Z_MENU_MOUNT_TOP_DATASET", zmntpt = NULL); 447f64ca102SToomas Soome if (zmntpt == NULL) { 448f64ca102SToomas Soome bam_error(_("cannot mount pool dataset for pool: %s\n"), pool); 449f64ca102SToomas Soome free(special); 450f64ca102SToomas Soome return (BAM_ERROR); 451f64ca102SToomas Soome } 452f64ca102SToomas Soome BAM_DPRINTF(("%s: top dataset mountpoint=%s\n", fcn, zmntpt)); 453f64ca102SToomas Soome 454f64ca102SToomas Soome (void) strlcpy(menu_root, zmntpt, sizeof (menu_root)); 455f64ca102SToomas Soome BAM_DPRINTF(("%s: zfs menu_root=%s\n", fcn, menu_root)); 456f64ca102SToomas Soome 457f64ca102SToomas Soome elide_trailing_slash(menu_root, clean_menu_root, 458f64ca102SToomas Soome sizeof (clean_menu_root)); 459f64ca102SToomas Soome 460f64ca102SToomas Soome BAM_DPRINTF(("%s: cleaned menu root is <%s>\n", fcn, clean_menu_root)); 461f64ca102SToomas Soome 462f64ca102SToomas Soome (void) strlcpy(menu_path, clean_menu_root, sizeof (menu_path)); 463f64ca102SToomas Soome (void) strlcat(menu_path, MENU, sizeof (menu_path)); 464f64ca102SToomas Soome 465f64ca102SToomas Soome BAM_DPRINTF(("%s: menu path is: %s\n", fcn, menu_path)); 466f64ca102SToomas Soome 467f64ca102SToomas Soome /* 468f64ca102SToomas Soome * update_entry is special case, its used by installer 469f64ca102SToomas Soome * and needs to create menu.lst file for loader 470f64ca102SToomas Soome */ 471f64ca102SToomas Soome if (menu_read(&menu, menu_path) == BAM_ERROR && 472f64ca102SToomas Soome strcmp(subcmd, "update_entry") != 0) { 473f64ca102SToomas Soome bam_error(_("cannot find menu file: %s\n"), menu_path); 474f64ca102SToomas Soome if (special != NULL) 475f64ca102SToomas Soome free(special); 476f64ca102SToomas Soome return (BAM_ERROR); 477f64ca102SToomas Soome } 478f64ca102SToomas Soome 479f64ca102SToomas Soome /* 480f64ca102SToomas Soome * If listing the menu, display the menu location 481f64ca102SToomas Soome */ 482f64ca102SToomas Soome if (strcmp(subcmd, "list_entry") == 0) 483f64ca102SToomas Soome bam_print(_("the location for the active menu is: %s\n"), 484f64ca102SToomas Soome menu_path); 485f64ca102SToomas Soome 486f64ca102SToomas Soome /* 487f64ca102SToomas Soome * We already checked the following case in 488f64ca102SToomas Soome * check_subcmd_and_suboptions() above. Complete the 489f64ca102SToomas Soome * final step now. 490f64ca102SToomas Soome */ 491f64ca102SToomas Soome if (strcmp(subcmd, "set_option") == 0) { 492f64ca102SToomas Soome assert(largc == 1 && largv[0] && largv[1] == NULL); 493f64ca102SToomas Soome opt = largv[0]; 494f64ca102SToomas Soome } else if ((strcmp(subcmd, "enable_hypervisor") != 0) && 495f64ca102SToomas Soome (strcmp(subcmd, "list_setting") != 0)) { 496f64ca102SToomas Soome assert(largc == 0 && largv == NULL); 497f64ca102SToomas Soome } 498f64ca102SToomas Soome 499f64ca102SToomas Soome /* 500f64ca102SToomas Soome * Once the sub-cmd handler has run 501f64ca102SToomas Soome * only the line field is guaranteed to have valid values 502f64ca102SToomas Soome */ 503f64ca102SToomas Soome if (strcmp(subcmd, "update_entry") == 0) { 504f64ca102SToomas Soome ret = f(&menu, menu_root, osdev); 505f64ca102SToomas Soome } else if (strcmp(subcmd, "upgrade") == 0) { 506f64ca102SToomas Soome ret = f(&menu, bam_root, menu_root); 507f64ca102SToomas Soome } else if (strcmp(subcmd, "list_entry") == 0) { 508f64ca102SToomas Soome ret = f(&menu, menu_path, opt); 509f64ca102SToomas Soome } else if (strcmp(subcmd, "list_setting") == 0) { 510f64ca102SToomas Soome ret = f(&menu, ((largc > 0) ? largv[0] : ""), 511f64ca102SToomas Soome ((largc > 1) ? largv[1] : "")); 512f64ca102SToomas Soome } else if (strcmp(subcmd, "disable_hypervisor") == 0) { 513f64ca102SToomas Soome if (is_sparc()) { 514f64ca102SToomas Soome bam_error(_("%s operation unsupported on SPARC " 515f64ca102SToomas Soome "machines\n"), subcmd); 516f64ca102SToomas Soome ret = BAM_ERROR; 517f64ca102SToomas Soome } else { 518f64ca102SToomas Soome ret = f(&menu, bam_root, NULL); 519f64ca102SToomas Soome } 520f64ca102SToomas Soome } else if (strcmp(subcmd, "enable_hypervisor") == 0) { 521f64ca102SToomas Soome if (is_sparc()) { 522f64ca102SToomas Soome bam_error(_("%s operation unsupported on SPARC " 523f64ca102SToomas Soome "machines\n"), subcmd); 524f64ca102SToomas Soome ret = BAM_ERROR; 525f64ca102SToomas Soome } else { 526f64ca102SToomas Soome char *extra_args = NULL; 527f64ca102SToomas Soome 528f64ca102SToomas Soome /* 529f64ca102SToomas Soome * Compress all arguments passed in the largv[] array 530f64ca102SToomas Soome * into one string that can then be appended to the 531f64ca102SToomas Soome * end of the kernel$ string the routine to enable the 532f64ca102SToomas Soome * hypervisor will build. 533f64ca102SToomas Soome * 534f64ca102SToomas Soome * This allows the caller to supply arbitrary unparsed 535f64ca102SToomas Soome * arguments, such as dom0 memory settings or APIC 536f64ca102SToomas Soome * options. 537f64ca102SToomas Soome * 538f64ca102SToomas Soome * This concatenation will be done without ANY syntax 539f64ca102SToomas Soome * checking whatsoever, so it's the responsibility of 540f64ca102SToomas Soome * the caller to make sure the arguments are valid and 541f64ca102SToomas Soome * do not duplicate arguments the conversion routines 542f64ca102SToomas Soome * may create. 543f64ca102SToomas Soome */ 544f64ca102SToomas Soome if (largc > 0) { 545f64ca102SToomas Soome int extra_len, i; 546f64ca102SToomas Soome 547f64ca102SToomas Soome for (extra_len = 0, i = 0; i < largc; i++) 548f64ca102SToomas Soome extra_len += strlen(largv[i]); 549f64ca102SToomas Soome 550f64ca102SToomas Soome /* 551f64ca102SToomas Soome * Allocate space for argument strings, 552f64ca102SToomas Soome * intervening spaces and terminating NULL. 553f64ca102SToomas Soome */ 554f64ca102SToomas Soome extra_args = alloca(extra_len + largc); 555f64ca102SToomas Soome 556f64ca102SToomas Soome (void) strcpy(extra_args, largv[0]); 557f64ca102SToomas Soome 558f64ca102SToomas Soome for (i = 1; i < largc; i++) { 559f64ca102SToomas Soome (void) strcat(extra_args, " "); 560f64ca102SToomas Soome (void) strcat(extra_args, largv[i]); 561f64ca102SToomas Soome } 562f64ca102SToomas Soome } 563f64ca102SToomas Soome 564f64ca102SToomas Soome ret = f(&menu, bam_root, extra_args); 565f64ca102SToomas Soome } 566f64ca102SToomas Soome } else 567f64ca102SToomas Soome ret = f(&menu, NULL, opt); 568f64ca102SToomas Soome 569f64ca102SToomas Soome if (ret == BAM_WRITE) { 570f64ca102SToomas Soome BAM_DPRINTF(("%s: writing menu to clean-menu-root: <%s>\n", 571f64ca102SToomas Soome fcn, clean_menu_root)); 572f64ca102SToomas Soome /* ret = menu_write(clean_menu_root, menu); */ 573f64ca102SToomas Soome } 574f64ca102SToomas Soome 575f64ca102SToomas Soome INJECT_ERROR1("POOL_SET", pool = "/pooldata"); 576f64ca102SToomas Soome assert((is_zfs(menu_root)) ^ (pool == NULL)); 577f64ca102SToomas Soome if (pool) { 578f64ca102SToomas Soome (void) umount_top_dataset(pool, zmnted, zmntpt); 579f64ca102SToomas Soome free(special); 580f64ca102SToomas Soome } 581f64ca102SToomas Soome 582f64ca102SToomas Soome menu_free(&menu); 583f64ca102SToomas Soome return (ret); 584f64ca102SToomas Soome } 585f64ca102SToomas Soome 586f64ca102SToomas Soome /* 587f64ca102SToomas Soome * To suppress output from ficl. We do not want to see messages 588f64ca102SToomas Soome * from interpreting loader config. 589f64ca102SToomas Soome */ 590f64ca102SToomas Soome 591f64ca102SToomas Soome /*ARGSUSED*/ 592f64ca102SToomas Soome static void 593f64ca102SToomas Soome ficlTextOutSilent(ficlCallback *cb, char *text) 594f64ca102SToomas Soome { 595f64ca102SToomas Soome } 596f64ca102SToomas Soome 597f64ca102SToomas Soome /*ARGSUSED*/ 598f64ca102SToomas Soome static error_t 599f64ca102SToomas Soome set_option(struct menu_lst *menu, char *dummy, char *opt) 600f64ca102SToomas Soome { 601f64ca102SToomas Soome char path[PATH_MAX]; 602f64ca102SToomas Soome char *val; 603f64ca102SToomas Soome char *rest; 604f64ca102SToomas Soome int optval; 605353ca6f2SToomas Soome menu_entry_t *entry; 606f64ca102SToomas Soome nvlist_t *be_attrs; 607f64ca102SToomas Soome FILE *fp; 608f64ca102SToomas Soome int rv, ret = BAM_SUCCESS; 609f64ca102SToomas Soome 610f64ca102SToomas Soome assert(menu); 611f64ca102SToomas Soome assert(opt); 612f64ca102SToomas Soome assert(dummy == NULL); 613f64ca102SToomas Soome 614f64ca102SToomas Soome val = strchr(opt, '='); 615f64ca102SToomas Soome if (val != NULL) { 616f64ca102SToomas Soome *val++ = '\0'; 617f64ca102SToomas Soome } 618f64ca102SToomas Soome 619f64ca102SToomas Soome if (strcmp(opt, "default") == 0) { 620f64ca102SToomas Soome errno = 0; 621f64ca102SToomas Soome optval = strtol(val, &rest, 10); 622f64ca102SToomas Soome if (errno != 0 || *rest != '\0') { 623f64ca102SToomas Soome bam_error(_("invalid boot entry number: %s\n"), val); 624f64ca102SToomas Soome return (BAM_ERROR); 625f64ca102SToomas Soome } 626353ca6f2SToomas Soome STAILQ_FOREACH(entry, menu, me_next) { 627353ca6f2SToomas Soome if (entry->me_idx == optval) 628f64ca102SToomas Soome break; 629f64ca102SToomas Soome } 630f64ca102SToomas Soome if (entry == NULL) { 631f64ca102SToomas Soome bam_error(_("invalid boot entry number: %s\n"), val); 632f64ca102SToomas Soome return (BAM_ERROR); 633f64ca102SToomas Soome } 634f64ca102SToomas Soome if (nvlist_alloc(&be_attrs, NV_UNIQUE_NAME, 0) != 0) { 635f64ca102SToomas Soome bam_error(_("out of memory\n")); 636f64ca102SToomas Soome return (BAM_ERROR); 637f64ca102SToomas Soome } 638f64ca102SToomas Soome if (nvlist_add_string(be_attrs, BE_ATTR_ORIG_BE_NAME, 639353ca6f2SToomas Soome entry->me_title) != 0) { 640f64ca102SToomas Soome bam_error(_("out of memory\n")); 641f64ca102SToomas Soome nvlist_free(be_attrs); 642f64ca102SToomas Soome return (BAM_ERROR); 643f64ca102SToomas Soome } 644f64ca102SToomas Soome ret = be_activate(be_attrs); 645f64ca102SToomas Soome nvlist_free(be_attrs); 646f64ca102SToomas Soome if (ret != 0) 647f64ca102SToomas Soome ret = BAM_ERROR; 648f64ca102SToomas Soome return (ret); 649f64ca102SToomas Soome } else if (strcmp(opt, "timeout") == 0) { 650f64ca102SToomas Soome errno = 0; 651f64ca102SToomas Soome optval = strtol(val, &rest, 10); 652f64ca102SToomas Soome if (errno != 0 || *rest != '\0') { 653f64ca102SToomas Soome bam_error(_("invalid timeout: %s\n"), val); 654f64ca102SToomas Soome return (BAM_ERROR); 655f64ca102SToomas Soome } 656f64ca102SToomas Soome 657f64ca102SToomas Soome (void) snprintf(path, PATH_MAX, "%s" CONF_DIR "/timeout", 658f64ca102SToomas Soome bam_root); 659f64ca102SToomas Soome 660f64ca102SToomas Soome fp = fopen(path, "w"); 661f64ca102SToomas Soome if (fp == NULL) { 662f64ca102SToomas Soome bam_error(_("failed to open file: %s: %s\n"), 663f64ca102SToomas Soome path, strerror(errno)); 664f64ca102SToomas Soome return (BAM_ERROR); 665f64ca102SToomas Soome } 666f64ca102SToomas Soome /* 667f64ca102SToomas Soome * timeout=-1 is to disable auto boot in illumos, but 668f64ca102SToomas Soome * loader needs "NO" to disable auto boot. 669f64ca102SToomas Soome */ 670f64ca102SToomas Soome if (optval == -1) 671f64ca102SToomas Soome rv = fprintf(fp, "autoboot_delay=\"NO\"\n"); 672f64ca102SToomas Soome else 673f64ca102SToomas Soome rv = fprintf(fp, "autoboot_delay=\"%d\"\n", optval); 674f64ca102SToomas Soome 675f64ca102SToomas Soome if (rv < 0) { 676f64ca102SToomas Soome bam_error(_("write to file failed: %s: %s\n"), 677f64ca102SToomas Soome path, strerror(errno)); 678f64ca102SToomas Soome (void) fclose(fp); 679f64ca102SToomas Soome ret = BAM_ERROR; 680f64ca102SToomas Soome } else 681f64ca102SToomas Soome rv = fclose(fp); 682f64ca102SToomas Soome 683f64ca102SToomas Soome if (rv < 0) { 684f64ca102SToomas Soome bam_error(_("failed to close file: %s: %s\n"), 685f64ca102SToomas Soome path, strerror(errno)); 686f64ca102SToomas Soome ret = BAM_ERROR; 687f64ca102SToomas Soome } 688f64ca102SToomas Soome if (ret == BAM_ERROR) 689f64ca102SToomas Soome (void) unlink(path); 690f64ca102SToomas Soome 691f64ca102SToomas Soome return (BAM_SUCCESS); 692f64ca102SToomas Soome } 693f64ca102SToomas Soome 694f64ca102SToomas Soome bam_error(_("invalid option: %s\n"), opt); 695f64ca102SToomas Soome return (BAM_ERROR); 696f64ca102SToomas Soome } 697f64ca102SToomas Soome 698f64ca102SToomas Soome static int 699353ca6f2SToomas Soome bam_mount_be(menu_entry_t *entry, char **dir) 700f64ca102SToomas Soome { 701f64ca102SToomas Soome nvlist_t *be_attrs = NULL; 702f64ca102SToomas Soome const char *tmpdir = getenv("TMPDIR"); 703f64ca102SToomas Soome const char *tmpname = "bam.XXXXXX"; 704f64ca102SToomas Soome be_node_list_t *be_node, *be_nodes = NULL; 705f64ca102SToomas Soome int ret; 706f64ca102SToomas Soome 707f64ca102SToomas Soome *dir = NULL; 708f64ca102SToomas Soome if (tmpdir == NULL) 709f64ca102SToomas Soome tmpdir = "/tmp"; 710f64ca102SToomas Soome 711f64ca102SToomas Soome ret = asprintf(dir, "%s/%s", tmpdir, tmpname); 712f64ca102SToomas Soome if (ret < 0) { 713f64ca102SToomas Soome return (BE_ERR_NOMEM); 714f64ca102SToomas Soome } 715f64ca102SToomas Soome *dir = mkdtemp(*dir); 716f64ca102SToomas Soome 717f64ca102SToomas Soome if (nvlist_alloc(&be_attrs, NV_UNIQUE_NAME, 0) != 0) { 718f64ca102SToomas Soome ret = BE_ERR_NOMEM; 719f64ca102SToomas Soome goto out; 720f64ca102SToomas Soome } 721f64ca102SToomas Soome 722*71668a2fSAndy Fiddaman ret = be_list(NULL, &be_nodes, BE_LIST_DEFAULT); 723f64ca102SToomas Soome if (ret != BE_SUCCESS) { 724f64ca102SToomas Soome goto out; 725f64ca102SToomas Soome } 726f64ca102SToomas Soome 727f64ca102SToomas Soome for (be_node = be_nodes; be_node; 728f64ca102SToomas Soome be_node = be_node->be_next_node) 729353ca6f2SToomas Soome if (strcmp(be_node->be_root_ds, entry->me_bootfs) == 0) 730f64ca102SToomas Soome break; 731f64ca102SToomas Soome 732f64ca102SToomas Soome if (nvlist_add_string(be_attrs, BE_ATTR_ORIG_BE_NAME, 733f64ca102SToomas Soome be_node->be_node_name) != 0) { 734f64ca102SToomas Soome ret = BE_ERR_NOMEM; 735f64ca102SToomas Soome goto out; 736f64ca102SToomas Soome } 737f64ca102SToomas Soome 738f64ca102SToomas Soome if (nvlist_add_string(be_attrs, BE_ATTR_MOUNTPOINT, *dir) != 0) { 739f64ca102SToomas Soome ret = BE_ERR_NOMEM; 740f64ca102SToomas Soome goto out; 741f64ca102SToomas Soome } 742f64ca102SToomas Soome 743f64ca102SToomas Soome ret = be_mount(be_attrs); 744f64ca102SToomas Soome if (ret == BE_ERR_MOUNTED) { 745f64ca102SToomas Soome /* 746f64ca102SToomas Soome * if BE is mounted, dir does not point to correct directory 747f64ca102SToomas Soome */ 748f64ca102SToomas Soome (void) rmdir(*dir); 749f64ca102SToomas Soome free(*dir); 750f64ca102SToomas Soome *dir = NULL; 751f64ca102SToomas Soome } 752f64ca102SToomas Soome out: 753f64ca102SToomas Soome if (be_nodes != NULL) 754f64ca102SToomas Soome be_free_list(be_nodes); 755f64ca102SToomas Soome nvlist_free(be_attrs); 756f64ca102SToomas Soome return (ret); 757f64ca102SToomas Soome } 758f64ca102SToomas Soome 759f64ca102SToomas Soome static int 760f64ca102SToomas Soome bam_umount_be(char *dir) 761f64ca102SToomas Soome { 762f64ca102SToomas Soome nvlist_t *be_attrs; 763f64ca102SToomas Soome int ret; 764f64ca102SToomas Soome 765f64ca102SToomas Soome if (dir == NULL) /* nothing to do */ 766f64ca102SToomas Soome return (BE_SUCCESS); 767f64ca102SToomas Soome 768f64ca102SToomas Soome if (nvlist_alloc(&be_attrs, NV_UNIQUE_NAME, 0) != 0) 769f64ca102SToomas Soome return (BE_ERR_NOMEM); 770f64ca102SToomas Soome 771f64ca102SToomas Soome if (nvlist_add_string(be_attrs, BE_ATTR_ORIG_BE_NAME, dir) != 0) { 772f64ca102SToomas Soome ret = BE_ERR_NOMEM; 773f64ca102SToomas Soome goto out; 774f64ca102SToomas Soome } 775f64ca102SToomas Soome 776f64ca102SToomas Soome ret = be_unmount(be_attrs); 777f64ca102SToomas Soome out: 778f64ca102SToomas Soome nvlist_free(be_attrs); 779f64ca102SToomas Soome return (ret); 780f64ca102SToomas Soome } 781f64ca102SToomas Soome 782f64ca102SToomas Soome /* 783f64ca102SToomas Soome * display details of menu entry or single property 784f64ca102SToomas Soome */ 785f64ca102SToomas Soome static error_t 786353ca6f2SToomas Soome list_menu_entry(menu_entry_t *entry, char *setting) 787f64ca102SToomas Soome { 788f64ca102SToomas Soome int ret = BAM_SUCCESS; 789f64ca102SToomas Soome char *ptr, *dir; 790f64ca102SToomas Soome char buf[MAX_INPUT]; 791f64ca102SToomas Soome ficlVm *vm; 792f64ca102SToomas Soome int mounted; 793f64ca102SToomas Soome 794353ca6f2SToomas Soome if (strcmp(entry->me_type, "bootfs") != 0 || 795353ca6f2SToomas Soome strchr(entry->me_bootfs, ':') != NULL) { 796353ca6f2SToomas Soome (void) printf("\nTitle: %s\n", entry->me_title); 797353ca6f2SToomas Soome (void) printf("Type: %s\n", entry->me_type); 798353ca6f2SToomas Soome (void) printf("Device: %s\n", entry->me_bootfs); 799353ca6f2SToomas Soome return (ret); 800353ca6f2SToomas Soome } 801353ca6f2SToomas Soome 802f64ca102SToomas Soome mounted = bam_mount_be(entry, &dir); 803f64ca102SToomas Soome if (mounted != BE_SUCCESS && mounted != BE_ERR_MOUNTED) { 804f64ca102SToomas Soome if (dir != NULL) { 805f64ca102SToomas Soome (void) rmdir(dir); 806f64ca102SToomas Soome free(dir); 807f64ca102SToomas Soome } 808353ca6f2SToomas Soome bam_error(_("%s is not mounted\n"), entry->me_title); 809f64ca102SToomas Soome return (BAM_ERROR); 810f64ca102SToomas Soome } 811f64ca102SToomas Soome 812f64ca102SToomas Soome vm = bf_init("", ficlTextOutSilent); 813f64ca102SToomas Soome if (vm == NULL) { 814f64ca102SToomas Soome bam_error(_("error setting up forth interpreter\n")); 815f64ca102SToomas Soome ret = BAM_ERROR; 816f64ca102SToomas Soome goto done; 817f64ca102SToomas Soome } 818f64ca102SToomas Soome 819f64ca102SToomas Soome /* should only get FICL_VM_STATUS_OUT_OF_TEXT */ 820f64ca102SToomas Soome (void) snprintf(buf, MAX_INPUT, "set currdev=zfs:%s:", 821353ca6f2SToomas Soome entry->me_bootfs); 822f64ca102SToomas Soome ret = ficlVmEvaluate(vm, buf); 823f64ca102SToomas Soome if (ret != FICL_VM_STATUS_OUT_OF_TEXT) { 824f64ca102SToomas Soome bam_error(_("error interpreting boot config\n")); 825f64ca102SToomas Soome ret = BAM_ERROR; 826f64ca102SToomas Soome goto done; 827f64ca102SToomas Soome } 828f64ca102SToomas Soome (void) snprintf(buf, MAX_INPUT, "include /boot/forth/loader.4th"); 829f64ca102SToomas Soome ret = ficlVmEvaluate(vm, buf); 830f64ca102SToomas Soome if (ret != FICL_VM_STATUS_OUT_OF_TEXT) { 831f64ca102SToomas Soome bam_error(_("error interpreting boot config\n")); 832f64ca102SToomas Soome ret = BAM_ERROR; 833f64ca102SToomas Soome goto done; 834f64ca102SToomas Soome } 835f64ca102SToomas Soome (void) snprintf(buf, MAX_INPUT, "start"); 836f64ca102SToomas Soome ret = ficlVmEvaluate(vm, buf); 837f64ca102SToomas Soome if (ret != FICL_VM_STATUS_OUT_OF_TEXT) { 838f64ca102SToomas Soome bam_error(_("error interpreting boot config\n")); 839f64ca102SToomas Soome ret = BAM_ERROR; 840f64ca102SToomas Soome goto done; 841f64ca102SToomas Soome } 842f64ca102SToomas Soome (void) snprintf(buf, MAX_INPUT, "boot"); 843f64ca102SToomas Soome ret = ficlVmEvaluate(vm, buf); 844f64ca102SToomas Soome if (ret != FICL_VM_STATUS_OUT_OF_TEXT) { 845f64ca102SToomas Soome bam_error(_("error interpreting boot config\n")); 846f64ca102SToomas Soome ret = BAM_ERROR; 847f64ca102SToomas Soome goto done; 848f64ca102SToomas Soome } 849f64ca102SToomas Soome 850f64ca102SToomas Soome ret = BAM_SUCCESS; 851f64ca102SToomas Soome if (*setting == '\0') 852353ca6f2SToomas Soome (void) printf("\nTitle: %s\n", entry->me_title); 853f64ca102SToomas Soome else if (strcasecmp(setting, "title") == 0) { 854353ca6f2SToomas Soome (void) printf("%s\n", entry->me_title); 855f64ca102SToomas Soome goto done; 856f64ca102SToomas Soome } 857f64ca102SToomas Soome 858f64ca102SToomas Soome ptr = getenv("autoboot_delay"); 859f64ca102SToomas Soome if (ptr != NULL) { 860f64ca102SToomas Soome char *timeout = "-1"; 861f64ca102SToomas Soome 862f64ca102SToomas Soome if (strcasecmp(ptr, "NO") != 0) 863f64ca102SToomas Soome timeout = ptr; 864f64ca102SToomas Soome 865f64ca102SToomas Soome if (*setting == '\0') 866f64ca102SToomas Soome (void) printf("Timeout: %s\n", timeout); 867f64ca102SToomas Soome else if (strcasecmp(setting, "timeout") == 0) { 868f64ca102SToomas Soome (void) printf("%s\n", timeout); 869f64ca102SToomas Soome goto done; 870f64ca102SToomas Soome } 871f64ca102SToomas Soome 872f64ca102SToomas Soome } 873f64ca102SToomas Soome ptr = getenv("console"); 874f64ca102SToomas Soome if (ptr != NULL) { 875f64ca102SToomas Soome if (*setting == '\0') 876f64ca102SToomas Soome (void) printf("Console: %s\n", ptr); 877f64ca102SToomas Soome else if (strcasecmp(setting, "console") == 0) { 878f64ca102SToomas Soome (void) printf("%s\n", ptr); 879f64ca102SToomas Soome goto done; 880f64ca102SToomas Soome } 881f64ca102SToomas Soome } 882f64ca102SToomas Soome 883f64ca102SToomas Soome if (*setting == '\0') 884353ca6f2SToomas Soome (void) printf("Bootfs: %s\n", entry->me_bootfs); 885f64ca102SToomas Soome else if (strcasecmp(setting, "bootfs") == 0) { 886353ca6f2SToomas Soome (void) printf("%s\n", entry->me_bootfs); 887f64ca102SToomas Soome goto done; 888f64ca102SToomas Soome } 889f64ca102SToomas Soome 890f64ca102SToomas Soome ptr = getenv("xen_kernel"); 891f64ca102SToomas Soome if (ptr != NULL) { 892f64ca102SToomas Soome if (*setting == '\0') { 893f64ca102SToomas Soome (void) printf("Xen kernel: %s\n", ptr); 894f64ca102SToomas Soome } else if (strcasecmp(setting, "xen_kernel") == 0) { 895f64ca102SToomas Soome (void) printf("%s\n", ptr); 896f64ca102SToomas Soome goto done; 897f64ca102SToomas Soome } 898f64ca102SToomas Soome 899f64ca102SToomas Soome if (*setting == '\0') { 900f64ca102SToomas Soome (void) printf("Xen args: \"%s\"\n", 901f64ca102SToomas Soome getenv("xen_cmdline")); 902f64ca102SToomas Soome } else if (strcasecmp(setting, "xen_cmdline") == 0) { 903f64ca102SToomas Soome (void) printf("%s\n", getenv("xen_cmdline")); 904f64ca102SToomas Soome goto done; 905f64ca102SToomas Soome } 906f64ca102SToomas Soome 907f64ca102SToomas Soome if (*setting == '\0') { 908f64ca102SToomas Soome (void) printf("Kernel: %s\n", 909f64ca102SToomas Soome getenv("bootfile")); 910f64ca102SToomas Soome } if (strcasecmp(setting, "kernel") == 0) { 911f64ca102SToomas Soome (void) printf("%s\n", getenv("bootfile")); 912f64ca102SToomas Soome goto done; 913f64ca102SToomas Soome } 914f64ca102SToomas Soome } else { 915f64ca102SToomas Soome ptr = getenv("kernelname"); 916f64ca102SToomas Soome if (ptr != NULL) { 917f64ca102SToomas Soome if (*setting == '\0') { 918f64ca102SToomas Soome (void) printf("Kernel: %s\n", ptr); 919f64ca102SToomas Soome } else if (strcasecmp(setting, "kernel") == 0) { 920f64ca102SToomas Soome (void) printf("%s\n", ptr); 921f64ca102SToomas Soome goto done; 922f64ca102SToomas Soome } 923f64ca102SToomas Soome } 924f64ca102SToomas Soome } 925f64ca102SToomas Soome 926f64ca102SToomas Soome ptr = getenv("boot-args"); 927f64ca102SToomas Soome if (ptr != NULL) { 928f64ca102SToomas Soome if (*setting == '\0') { 929f64ca102SToomas Soome (void) printf("Boot-args: \"%s\"\n", ptr); 930f64ca102SToomas Soome } else if (strcasecmp(setting, "boot-args") == 0) { 931f64ca102SToomas Soome (void) printf("%s\n", ptr); 932f64ca102SToomas Soome goto done; 933f64ca102SToomas Soome } 934f64ca102SToomas Soome } 935f64ca102SToomas Soome 936f64ca102SToomas Soome if (*setting == '\0' || strcasecmp(setting, "modules") == 0) { 937f64ca102SToomas Soome (void) printf("\nModules:\n"); 938f64ca102SToomas Soome ficlVmSetTextOut(vm, ficlCallbackDefaultTextOut); 939f64ca102SToomas Soome (void) snprintf(buf, MAX_INPUT, "show-module-options"); 940f64ca102SToomas Soome ret = ficlVmEvaluate(vm, buf); 941f64ca102SToomas Soome if (ret != FICL_VM_STATUS_OUT_OF_TEXT) { 942f64ca102SToomas Soome bam_error(_("error interpreting boot config\n")); 943f64ca102SToomas Soome ret = BAM_ERROR; 944f64ca102SToomas Soome goto done; 945f64ca102SToomas Soome } 946f64ca102SToomas Soome ret = BAM_SUCCESS; 947f64ca102SToomas Soome goto done; 948f64ca102SToomas Soome } 949f64ca102SToomas Soome 950f64ca102SToomas Soome /* if we got here with setting string, its unknown property */ 951f64ca102SToomas Soome if (*setting != '\0') { 952f64ca102SToomas Soome bam_error(_("unknown property: %s\n"), setting); 953f64ca102SToomas Soome ret = BAM_ERROR; 954f64ca102SToomas Soome } else 955f64ca102SToomas Soome ret = BAM_SUCCESS; 956f64ca102SToomas Soome done: 957f64ca102SToomas Soome bf_fini(); 958f64ca102SToomas Soome if (mounted != BE_ERR_MOUNTED) { 959f64ca102SToomas Soome (void) bam_umount_be(dir); 960f64ca102SToomas Soome } 961f64ca102SToomas Soome 962f64ca102SToomas Soome if (dir != NULL) { 963f64ca102SToomas Soome (void) rmdir(dir); 964f64ca102SToomas Soome free(dir); 965f64ca102SToomas Soome } 966f64ca102SToomas Soome 967f64ca102SToomas Soome return (ret); 968f64ca102SToomas Soome } 969f64ca102SToomas Soome 970f64ca102SToomas Soome /*ARGSUSED*/ 971f64ca102SToomas Soome static error_t 972f64ca102SToomas Soome list_entry(struct menu_lst *menu, char *menu_root, char *opt) 973f64ca102SToomas Soome { 974f64ca102SToomas Soome error_t ret = BAM_SUCCESS; 975353ca6f2SToomas Soome menu_entry_t *entry; 976f64ca102SToomas Soome char *ptr, *title = NULL; 977f64ca102SToomas Soome int i, e = -1; 978f64ca102SToomas Soome 979f64ca102SToomas Soome if (opt == NULL) { 980f64ca102SToomas Soome print_nodes(B_FALSE, menu); 981f64ca102SToomas Soome return (ret); 982f64ca102SToomas Soome } 983f64ca102SToomas Soome 984f64ca102SToomas Soome if ((ptr = strchr(opt, '=')) == NULL) { 985f64ca102SToomas Soome bam_error(_("invalid option: %s\n"), opt); 986f64ca102SToomas Soome return (BAM_ERROR); 987f64ca102SToomas Soome } 988f64ca102SToomas Soome 989f64ca102SToomas Soome i = ptr - opt; 990f64ca102SToomas Soome if (strncmp(opt, "entry", i) == 0) { 991f64ca102SToomas Soome e = atoi(ptr+1); 992f64ca102SToomas Soome } else if (strncmp(opt, "title", i) == 0) { 993f64ca102SToomas Soome title = ptr+1; 994f64ca102SToomas Soome } else { 995f64ca102SToomas Soome bam_error(_("invalid option: %s\n"), opt); 996f64ca102SToomas Soome return (BAM_ERROR); 997f64ca102SToomas Soome } 998f64ca102SToomas Soome 999353ca6f2SToomas Soome STAILQ_FOREACH(entry, menu, me_next) { 1000f64ca102SToomas Soome if (title != NULL) { 1001353ca6f2SToomas Soome if (strcmp(title, entry->me_title) == 0) 1002f64ca102SToomas Soome break; 1003353ca6f2SToomas Soome } else if (entry->me_idx == e) 1004f64ca102SToomas Soome break; 1005f64ca102SToomas Soome } 1006f64ca102SToomas Soome 1007f64ca102SToomas Soome if (entry == NULL) { 1008f64ca102SToomas Soome bam_error(_("no matching entry found\n")); 1009f64ca102SToomas Soome return (BAM_ERROR); 1010f64ca102SToomas Soome } 1011f64ca102SToomas Soome 1012f64ca102SToomas Soome return (list_menu_entry(entry, "")); 1013f64ca102SToomas Soome } 1014f64ca102SToomas Soome 1015f64ca102SToomas Soome /* 1016f64ca102SToomas Soome * For now this is just stub entry to support grub interface, the 1017f64ca102SToomas Soome * known consumer is installer ict.py code, calling as: 1018f64ca102SToomas Soome * bootadm update-menu -R /a -Z -o rdisk 1019f64ca102SToomas Soome * Later this can be converted to do something useful. 1020f64ca102SToomas Soome */ 1021f64ca102SToomas Soome /*ARGSUSED*/ 1022f64ca102SToomas Soome static error_t 1023f64ca102SToomas Soome update_entry(struct menu_lst *menu, char *menu_root, char *osdev) 1024f64ca102SToomas Soome { 1025f64ca102SToomas Soome char path[PATH_MAX]; 1026f64ca102SToomas Soome char *pool = menu_root + 1; 1027f64ca102SToomas Soome be_node_list_t *be_nodes, *be_node; 1028f64ca102SToomas Soome int rv; 1029f64ca102SToomas Soome FILE *fp; 1030f64ca102SToomas Soome 1031f64ca102SToomas Soome (void) snprintf(path, PATH_MAX, "%s%s", menu_root, MENU); 1032*71668a2fSAndy Fiddaman rv = be_list(NULL, &be_nodes, BE_LIST_DEFAULT); 1033f64ca102SToomas Soome 1034f64ca102SToomas Soome if (rv != BE_SUCCESS) 1035f64ca102SToomas Soome return (BAM_ERROR); 1036f64ca102SToomas Soome 1037f64ca102SToomas Soome fp = fopen(path, "w"); 1038f64ca102SToomas Soome if (fp == NULL) { 1039f64ca102SToomas Soome be_free_list(be_nodes); 1040f64ca102SToomas Soome return (BAM_ERROR); 1041f64ca102SToomas Soome } 1042f64ca102SToomas Soome 1043f64ca102SToomas Soome for (be_node = be_nodes; be_node; be_node = be_node->be_next_node) { 1044f64ca102SToomas Soome if (strcmp(be_node->be_rpool, pool) == 0) { 1045f64ca102SToomas Soome (void) fprintf(fp, "title %s\n", be_node->be_node_name); 1046f64ca102SToomas Soome (void) fprintf(fp, "bootfs %s\n", be_node->be_root_ds); 1047f64ca102SToomas Soome } 1048f64ca102SToomas Soome } 1049f64ca102SToomas Soome 1050f64ca102SToomas Soome be_free_list(be_nodes); 1051f64ca102SToomas Soome (void) fclose(fp); 1052f64ca102SToomas Soome return (BAM_SUCCESS); 1053f64ca102SToomas Soome } 1054f64ca102SToomas Soome 1055f64ca102SToomas Soome /*ARGSUSED*/ 1056f64ca102SToomas Soome static error_t 1057f64ca102SToomas Soome update_temp(struct menu_lst *menu, char *dummy, char *opt) 1058f64ca102SToomas Soome { 1059f64ca102SToomas Soome error_t ret = BAM_ERROR; 1060f64ca102SToomas Soome char path[PATH_MAX]; 1061f64ca102SToomas Soome char buf[MAX_INPUT]; 1062f64ca102SToomas Soome struct mnttab mpref = { 0 }; 1063f64ca102SToomas Soome struct mnttab mp = { 0 }; 1064f64ca102SToomas Soome ficlVm *vm; 1065f64ca102SToomas Soome char *env, *o; 1066f64ca102SToomas Soome FILE *fp; 1067f64ca102SToomas Soome 1068f64ca102SToomas Soome (void) snprintf(path, PATH_MAX, "%s" TRANSIENT, bam_root); 1069f64ca102SToomas Soome /* 1070f64ca102SToomas Soome * if opt == NULL, remove transient config 1071f64ca102SToomas Soome */ 1072f64ca102SToomas Soome if (opt == NULL) { 1073f64ca102SToomas Soome (void) unlink(path); 1074f64ca102SToomas Soome return (BAM_SUCCESS); 1075f64ca102SToomas Soome } 1076f64ca102SToomas Soome 1077f64ca102SToomas Soome fp = fopen(MNTTAB, "r"); 1078f64ca102SToomas Soome if (fp == NULL) 1079f64ca102SToomas Soome return (BAM_ERROR); 1080f64ca102SToomas Soome 1081f64ca102SToomas Soome mpref.mnt_mountp = "/"; 1082f64ca102SToomas Soome if (getmntany(fp, &mp, &mpref) != 0) { 1083f64ca102SToomas Soome (void) fclose(fp); 1084f64ca102SToomas Soome return (BAM_ERROR); 1085f64ca102SToomas Soome } 1086f64ca102SToomas Soome (void) fclose(fp); 1087f64ca102SToomas Soome 1088f64ca102SToomas Soome vm = bf_init("", ficlTextOutSilent); 1089f64ca102SToomas Soome if (vm == NULL) { 1090f64ca102SToomas Soome bam_error(_("Error setting up forth interpreter\n")); 1091f64ca102SToomas Soome return (ret); 1092f64ca102SToomas Soome } 1093f64ca102SToomas Soome 1094f64ca102SToomas Soome /* 1095f64ca102SToomas Soome * need to check current boot config, so fire up the ficl 1096f64ca102SToomas Soome * if its xen setup, we add option to boot-args list, not replacing it. 1097f64ca102SToomas Soome */ 1098f64ca102SToomas Soome (void) snprintf(buf, MAX_INPUT, "set currdev=zfs:%s:", mp.mnt_special); 1099f64ca102SToomas Soome ret = ficlVmEvaluate(vm, buf); 1100f64ca102SToomas Soome if (ret != FICL_VM_STATUS_OUT_OF_TEXT) { 1101f64ca102SToomas Soome bam_error(_("Error interpreting boot config\n")); 1102f64ca102SToomas Soome bf_fini(); 1103f64ca102SToomas Soome return (BAM_ERROR); 1104f64ca102SToomas Soome } 1105f64ca102SToomas Soome (void) snprintf(buf, MAX_INPUT, "include /boot/forth/loader.4th"); 1106f64ca102SToomas Soome ret = ficlVmEvaluate(vm, buf); 1107f64ca102SToomas Soome if (ret != FICL_VM_STATUS_OUT_OF_TEXT) { 1108f64ca102SToomas Soome bam_error(_("Error interpreting boot config\n")); 1109f64ca102SToomas Soome bf_fini(); 1110f64ca102SToomas Soome return (BAM_ERROR); 1111f64ca102SToomas Soome } 1112f64ca102SToomas Soome (void) snprintf(buf, MAX_INPUT, "start"); 1113f64ca102SToomas Soome ret = ficlVmEvaluate(vm, buf); 1114f64ca102SToomas Soome if (ret != FICL_VM_STATUS_OUT_OF_TEXT) { 1115f64ca102SToomas Soome bam_error(_("Error interpreting boot config\n")); 1116f64ca102SToomas Soome bf_fini(); 1117f64ca102SToomas Soome return (BAM_ERROR); 1118f64ca102SToomas Soome } 1119f64ca102SToomas Soome (void) snprintf(buf, MAX_INPUT, "boot"); 1120f64ca102SToomas Soome ret = ficlVmEvaluate(vm, buf); 1121f64ca102SToomas Soome if (ret != FICL_VM_STATUS_OUT_OF_TEXT) { 1122f64ca102SToomas Soome bam_error(_("Error interpreting boot config\n")); 1123f64ca102SToomas Soome bf_fini(); 1124f64ca102SToomas Soome return (BAM_ERROR); 1125f64ca102SToomas Soome } 1126f64ca102SToomas Soome bf_fini(); 1127f64ca102SToomas Soome 1128f64ca102SToomas Soome if (opt[0] == '-') { 1129f64ca102SToomas Soome env = getenv("xen_kernel"); 1130f64ca102SToomas Soome fp = fopen(path, "w"); 1131f64ca102SToomas Soome if (fp == NULL) 1132f64ca102SToomas Soome return (BAM_ERROR); 1133f64ca102SToomas Soome 1134f64ca102SToomas Soome if (env != NULL) { 1135f64ca102SToomas Soome env = getenv("boot-args"); 1136f64ca102SToomas Soome (void) fprintf(fp, "boot-args=\"%s %s\"\n", env, opt); 1137f64ca102SToomas Soome } else 1138f64ca102SToomas Soome (void) fprintf(fp, "boot-args=\"%s\"\n", opt); 1139f64ca102SToomas Soome (void) fclose(fp); 1140f64ca102SToomas Soome return (BAM_SUCCESS); 1141f64ca102SToomas Soome } 1142f64ca102SToomas Soome 1143f64ca102SToomas Soome /* 1144f64ca102SToomas Soome * it should be the case with "kernel args" 1145f64ca102SToomas Soome * so, we split the opt at first space 1146f64ca102SToomas Soome * and store bootfile= and boot-args= 1147f64ca102SToomas Soome */ 1148f64ca102SToomas Soome env = getenv("xen_kernel"); 1149f64ca102SToomas Soome 1150f64ca102SToomas Soome o = strchr(opt, ' '); 1151f64ca102SToomas Soome if (o == NULL) { 1152f64ca102SToomas Soome fp = fopen(path, "w"); 1153f64ca102SToomas Soome if (fp == NULL) 1154f64ca102SToomas Soome return (BAM_ERROR); 1155f64ca102SToomas Soome (void) fprintf(fp, "bootfile=\"%s\"\n", opt); 1156f64ca102SToomas Soome (void) fclose(fp); 1157f64ca102SToomas Soome return (BAM_SUCCESS); 1158f64ca102SToomas Soome } 1159f64ca102SToomas Soome *o++ = '\0'; 1160f64ca102SToomas Soome fp = fopen(path, "w"); 1161f64ca102SToomas Soome if (fp == NULL) 1162f64ca102SToomas Soome return (BAM_ERROR); 1163f64ca102SToomas Soome (void) fprintf(fp, "bootfile=\"%s\"\n", opt); 1164f64ca102SToomas Soome 1165f64ca102SToomas Soome if (env != NULL) { 1166f64ca102SToomas Soome env = getenv("boot-args"); 1167f64ca102SToomas Soome (void) fprintf(fp, "boot-args=\"%s %s\"\n", env, opt); 1168f64ca102SToomas Soome } else 1169f64ca102SToomas Soome (void) fprintf(fp, "boot-args=\"%s\"\n", o); 1170f64ca102SToomas Soome 1171f64ca102SToomas Soome (void) fflush(fp); 1172f64ca102SToomas Soome (void) fclose(fp); 1173f64ca102SToomas Soome return (ret); 1174f64ca102SToomas Soome } 1175f64ca102SToomas Soome 1176f64ca102SToomas Soome static error_t 1177f64ca102SToomas Soome list_setting(struct menu_lst *menu, char *which, char *setting) 1178f64ca102SToomas Soome { 1179f64ca102SToomas Soome int entry = -1; 1180353ca6f2SToomas Soome menu_entry_t *m; 1181f64ca102SToomas Soome be_node_list_t *be_nodes, *be_node = NULL; 1182f64ca102SToomas Soome int ret; 1183f64ca102SToomas Soome 1184f64ca102SToomas Soome assert(which); 1185f64ca102SToomas Soome assert(setting); 1186f64ca102SToomas Soome 1187f64ca102SToomas Soome /* 1188f64ca102SToomas Soome * which can be: 1189f64ca102SToomas Soome * "" - list default entry 1190f64ca102SToomas Soome * number - use for entry number 1191f64ca102SToomas Soome * property name 1192f64ca102SToomas Soome */ 1193f64ca102SToomas Soome if (*which != '\0') { 1194f64ca102SToomas Soome if (isdigit(*which)) { 1195f64ca102SToomas Soome char *rest; 1196f64ca102SToomas Soome errno = 0; 1197f64ca102SToomas Soome entry = strtol(which, &rest, 10); 1198f64ca102SToomas Soome if (errno != 0 || *rest != '\0') { 1199f64ca102SToomas Soome bam_error(_("invalid boot entry number: %s\n"), 1200f64ca102SToomas Soome which); 1201f64ca102SToomas Soome return (BAM_ERROR); 1202f64ca102SToomas Soome } 1203f64ca102SToomas Soome } else 1204f64ca102SToomas Soome setting = which; 1205f64ca102SToomas Soome } 1206f64ca102SToomas Soome 1207f64ca102SToomas Soome /* find default entry */ 1208f64ca102SToomas Soome if (entry == -1) { 1209*71668a2fSAndy Fiddaman ret = be_list(NULL, &be_nodes, BE_LIST_DEFAULT); 1210f64ca102SToomas Soome if (ret != BE_SUCCESS) { 1211f64ca102SToomas Soome bam_error(_("No BE's found\n")); 1212f64ca102SToomas Soome return (BAM_ERROR); 1213f64ca102SToomas Soome } 1214353ca6f2SToomas Soome STAILQ_FOREACH(m, menu, me_next) { 1215f64ca102SToomas Soome entry++; 1216f64ca102SToomas Soome for (be_node = be_nodes; be_node; 1217353ca6f2SToomas Soome be_node = be_node->be_next_node) { 1218353ca6f2SToomas Soome if (strcmp(be_node->be_root_ds, 1219353ca6f2SToomas Soome m->me_bootfs) == 0) 1220f64ca102SToomas Soome break; 1221353ca6f2SToomas Soome } 1222353ca6f2SToomas Soome if (be_node != NULL && 1223353ca6f2SToomas Soome be_node->be_active_on_boot == B_TRUE) 1224f64ca102SToomas Soome break; /* found active node */ 1225f64ca102SToomas Soome } 1226f64ca102SToomas Soome be_free_list(be_nodes); 1227f64ca102SToomas Soome if (be_node == NULL) { 1228f64ca102SToomas Soome bam_error(_("None of BE nodes is marked active\n")); 1229f64ca102SToomas Soome return (BAM_ERROR); 1230f64ca102SToomas Soome } 1231f64ca102SToomas Soome } else { 1232353ca6f2SToomas Soome STAILQ_FOREACH(m, menu, me_next) 1233353ca6f2SToomas Soome if (m->me_idx == entry) 1234f64ca102SToomas Soome break; 1235f64ca102SToomas Soome 1236f64ca102SToomas Soome if (m == NULL) { 1237f64ca102SToomas Soome bam_error(_("no matching entry found\n")); 1238f64ca102SToomas Soome return (BAM_ERROR); 1239f64ca102SToomas Soome } 1240f64ca102SToomas Soome } 1241f64ca102SToomas Soome 1242f64ca102SToomas Soome return (list_menu_entry(m, setting)); 1243f64ca102SToomas Soome } 1244f64ca102SToomas Soome 1245f64ca102SToomas Soome /*ARGSUSED*/ 1246f64ca102SToomas Soome static error_t 1247f64ca102SToomas Soome disable_hyper(struct menu_lst *menu, char *osroot, char *opt) 1248f64ca102SToomas Soome { 1249f64ca102SToomas Soome char path[PATH_MAX]; 1250f64ca102SToomas Soome 1251f64ca102SToomas Soome (void) snprintf(path, PATH_MAX, "%s" XEN_CONFIG, bam_root); 1252f64ca102SToomas Soome (void) unlink(path); 1253f64ca102SToomas Soome return (BAM_SUCCESS); 1254f64ca102SToomas Soome } 1255f64ca102SToomas Soome 1256f64ca102SToomas Soome /*ARGSUSED*/ 1257f64ca102SToomas Soome static error_t 1258f64ca102SToomas Soome enable_hyper(struct menu_lst *menu, char *osroot, char *opt) 1259f64ca102SToomas Soome { 1260f64ca102SToomas Soome ficlVm *vm; 1261f64ca102SToomas Soome char path[PATH_MAX]; 1262f64ca102SToomas Soome char buf[MAX_INPUT]; 1263f64ca102SToomas Soome char *env; 1264f64ca102SToomas Soome FILE *fp; 1265f64ca102SToomas Soome struct mnttab mpref = { 0 }; 1266f64ca102SToomas Soome struct mnttab mp = { 0 }; 1267f64ca102SToomas Soome int ret; 1268f64ca102SToomas Soome 1269f64ca102SToomas Soome fp = fopen(MNTTAB, "r"); 1270f64ca102SToomas Soome if (fp == NULL) 1271f64ca102SToomas Soome return (BAM_ERROR); 1272f64ca102SToomas Soome 1273f64ca102SToomas Soome mpref.mnt_mountp = "/"; 1274f64ca102SToomas Soome if (getmntany(fp, &mp, &mpref) != 0) { 1275f64ca102SToomas Soome (void) fclose(fp); 1276f64ca102SToomas Soome return (BAM_ERROR); 1277f64ca102SToomas Soome } 1278f64ca102SToomas Soome (void) fclose(fp); 1279f64ca102SToomas Soome 1280f64ca102SToomas Soome vm = bf_init("", ficlTextOutSilent); 1281f64ca102SToomas Soome if (vm == NULL) { 1282f64ca102SToomas Soome bam_error(_("Error setting up forth interpreter\n")); 1283f64ca102SToomas Soome return (BAM_ERROR); 1284f64ca102SToomas Soome } 1285f64ca102SToomas Soome 1286f64ca102SToomas Soome /* 1287f64ca102SToomas Soome * need to check current boot config, so fire up the ficl 1288f64ca102SToomas Soome * if its xen setup, we add option to boot-args list, not replacing it. 1289f64ca102SToomas Soome */ 1290f64ca102SToomas Soome (void) snprintf(buf, MAX_INPUT, "set currdev=zfs:%s:", mp.mnt_special); 1291f64ca102SToomas Soome ret = ficlVmEvaluate(vm, buf); 1292f64ca102SToomas Soome if (ret != FICL_VM_STATUS_OUT_OF_TEXT) { 1293f64ca102SToomas Soome bam_error(_("Error interpreting boot config\n")); 1294f64ca102SToomas Soome bf_fini(); 1295f64ca102SToomas Soome return (BAM_ERROR); 1296f64ca102SToomas Soome } 1297f64ca102SToomas Soome (void) snprintf(buf, MAX_INPUT, "include /boot/forth/loader.4th"); 1298f64ca102SToomas Soome ret = ficlVmEvaluate(vm, buf); 1299f64ca102SToomas Soome if (ret != FICL_VM_STATUS_OUT_OF_TEXT) { 1300f64ca102SToomas Soome bam_error(_("Error interpreting boot config\n")); 1301f64ca102SToomas Soome bf_fini(); 1302f64ca102SToomas Soome return (BAM_ERROR); 1303f64ca102SToomas Soome } 1304f64ca102SToomas Soome (void) snprintf(buf, MAX_INPUT, "start"); 1305f64ca102SToomas Soome ret = ficlVmEvaluate(vm, buf); 1306f64ca102SToomas Soome if (ret != FICL_VM_STATUS_OUT_OF_TEXT) { 1307f64ca102SToomas Soome bam_error(_("Error interpreting boot config\n")); 1308f64ca102SToomas Soome bf_fini(); 1309f64ca102SToomas Soome return (BAM_ERROR); 1310f64ca102SToomas Soome } 1311f64ca102SToomas Soome (void) snprintf(buf, MAX_INPUT, "boot"); 1312f64ca102SToomas Soome ret = ficlVmEvaluate(vm, buf); 1313f64ca102SToomas Soome if (ret != FICL_VM_STATUS_OUT_OF_TEXT) { 1314f64ca102SToomas Soome bam_error(_("Error interpreting boot config\n")); 1315f64ca102SToomas Soome bf_fini(); 1316f64ca102SToomas Soome return (BAM_ERROR); 1317f64ca102SToomas Soome } 1318f64ca102SToomas Soome bf_fini(); 1319f64ca102SToomas Soome 1320f64ca102SToomas Soome (void) mkdir(CONF_DIR, 0755); 1321f64ca102SToomas Soome (void) snprintf(path, PATH_MAX, "%s" XEN_CONFIG, bam_root); 1322f64ca102SToomas Soome fp = fopen(path, "w"); 1323f64ca102SToomas Soome if (fp == NULL) { 1324f64ca102SToomas Soome return (BAM_ERROR); /* error, cant write config */ 1325f64ca102SToomas Soome } 1326f64ca102SToomas Soome 1327f64ca102SToomas Soome errno = 0; 1328f64ca102SToomas Soome /* 1329f64ca102SToomas Soome * on write error, remove file to ensure we have bootable config. 1330f64ca102SToomas Soome * note we dont mind if config exists, it will get updated 1331f64ca102SToomas Soome */ 1332f64ca102SToomas Soome (void) fprintf(fp, "xen_kernel=\"/boot/${ISADIR}/xen\"\n"); 1333f64ca102SToomas Soome if (errno != 0) 1334f64ca102SToomas Soome goto error; 1335f64ca102SToomas Soome 1336f64ca102SToomas Soome /* 1337f64ca102SToomas Soome * really simple and stupid console conversion. 1338f64ca102SToomas Soome * it really has to be gone, it belongs to milestone/xvm properties. 1339f64ca102SToomas Soome */ 1340f64ca102SToomas Soome env = getenv("console"); 1341f64ca102SToomas Soome if (env != NULL) { 1342f64ca102SToomas Soome if (strcmp(env, "ttya") == 0) 1343f64ca102SToomas Soome (void) fprintf(fp, "xen_cmdline=\"console=com1 %s\"\n", 1344f64ca102SToomas Soome opt); 1345f64ca102SToomas Soome else if (strcmp(env, "ttyb") == 0) 1346f64ca102SToomas Soome (void) fprintf(fp, "xen_cmdline=\"console=com2 %s\"\n", 1347f64ca102SToomas Soome opt); 1348f64ca102SToomas Soome else 1349f64ca102SToomas Soome (void) fprintf(fp, "xen_cmdline=\"console=vga %s\"\n", 1350f64ca102SToomas Soome opt); 1351f64ca102SToomas Soome } else 1352f64ca102SToomas Soome (void) fprintf(fp, "xen_cmdline=\"%s\"\n", opt); 1353f64ca102SToomas Soome if (errno != 0) 1354f64ca102SToomas Soome goto error; 1355f64ca102SToomas Soome 1356f64ca102SToomas Soome (void) fprintf(fp, 1357f64ca102SToomas Soome "bootfile=\"/platform/i86xpv/kernel/${ISADIR}/unix\"\n"); 1358f64ca102SToomas Soome if (errno != 0) 1359f64ca102SToomas Soome goto error; 1360f64ca102SToomas Soome 1361f64ca102SToomas Soome (void) fprintf(fp, 1362f64ca102SToomas Soome "boot-args=\"/platform/i86xpv/kernel/${ISADIR}/unix\"\n"); 1363f64ca102SToomas Soome if (errno != 0) 1364f64ca102SToomas Soome goto error; 1365f64ca102SToomas Soome 1366f64ca102SToomas Soome (void) fclose(fp); 1367f64ca102SToomas Soome if (errno != 0) { 1368f64ca102SToomas Soome (void) unlink(path); 1369f64ca102SToomas Soome return (BAM_ERROR); 1370f64ca102SToomas Soome } 1371f64ca102SToomas Soome return (BAM_SUCCESS); 1372f64ca102SToomas Soome error: 1373f64ca102SToomas Soome (void) fclose(fp); 1374f64ca102SToomas Soome (void) unlink(path); 1375f64ca102SToomas Soome return (BAM_ERROR); 1376f64ca102SToomas Soome } 1377