bootadm_upgrade.c revision 5648:161f8007cab9
1251875Speter/* 2251875Speter * CDDL HEADER START 3251875Speter * 4251875Speter * The contents of this file are subject to the terms of the 5251875Speter * Common Development and Distribution License (the "License"). 6251875Speter * You may not use this file except in compliance with the License. 7251875Speter * 8251875Speter * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9251875Speter * or http://www.opensolaris.org/os/licensing. 10251875Speter * See the License for the specific language governing permissions 11251875Speter * and limitations under the License. 12251875Speter * 13251875Speter * When distributing Covered Code, include this CDDL HEADER in each 14251875Speter * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15251875Speter * If applicable, add the following below this CDDL HEADER, with the 16251875Speter * fields enclosed by brackets "[]" replaced with your own identifying 17251875Speter * information: Portions Copyright [yyyy] [name of copyright owner] 18251875Speter * 19251875Speter * CDDL HEADER END 20251875Speter */ 21251875Speter/* 22251875Speter * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23251875Speter * Use is subject to license terms. 24251875Speter */ 25251875Speter 26251875Speter#pragma ident "%Z%%M% %I% %E% SMI" 27251875Speter 28251875Speter#include <stdio.h> 29251875Speter#include <errno.h> 30251875Speter#include <stdlib.h> 31251875Speter#include <string.h> 32251875Speter#include <unistd.h> 33251875Speter#include <sys/types.h> 34251875Speter#include <sys/stat.h> 35251875Speter#include <limits.h> 36251875Speter#include <fcntl.h> 37251875Speter#include <strings.h> 38251875Speter 39251875Speter#include <sys/mman.h> 40251875Speter#include <sys/elf.h> 41251875Speter#include <sys/multiboot.h> 42251875Speter 43251875Speter#include "message.h" 44251875Speter#include "bootadm.h" 45251875Speter 46251875Speterdirect_or_multi_t bam_direct = BAM_DIRECT_NOT_SET; 47251875Speterhv_t bam_is_hv = BAM_HV_UNKNOWN; 48251875Speter 49251875Spetererror_t 50251875Speterdboot_or_multiboot(const char *root) 51251875Speter{ 52251875Speter char fname[PATH_MAX]; 53251875Speter char *image; 54251875Speter uchar_t *ident; 55251875Speter int fd, m; 56251875Speter multiboot_header_t *mbh; 57251875Speter struct stat sb; 58251875Speter 59251875Speter if (!is_grub(root)) { 60251875Speter /* there is no non dboot sparc new-boot */ 61251875Speter bam_direct = BAM_DIRECT_DBOOT; 62251875Speter return (BAM_SUCCESS); 63251875Speter } 64251875Speter 65251875Speter (void) snprintf(fname, PATH_MAX, "%s/%s", root, 66251875Speter "platform/i86pc/kernel/unix"); 67251875Speter fd = open(fname, O_RDONLY); 68251875Speter if (fd < 0) { 69251875Speter bam_error(OPEN_FAIL, fname, strerror(errno)); 70251875Speter return (BAM_ERROR); 71251875Speter } 72251875Speter 73251875Speter /* 74251875Speter * mmap the first 8K 75251875Speter */ 76251875Speter image = mmap(NULL, 8192, PROT_READ, MAP_SHARED, fd, 0); 77251875Speter if (image == MAP_FAILED) { 78251875Speter bam_error(MMAP_FAIL, fname, strerror(errno)); 79251875Speter return (BAM_ERROR); 80251875Speter } 81251875Speter 82251875Speter ident = (uchar_t *)image; 83251875Speter if (ident[EI_MAG0] != ELFMAG0 || ident[EI_MAG1] != ELFMAG1 || 84251875Speter ident[EI_MAG2] != ELFMAG2 || ident[EI_MAG3] != ELFMAG3) { 85251875Speter bam_error(NOT_ELF_FILE, fname); 86251875Speter return (BAM_ERROR); 87251875Speter } 88251875Speter if (ident[EI_CLASS] != ELFCLASS32) { 89251875Speter bam_error(WRONG_ELF_CLASS, fname, ident[EI_CLASS]); 90251875Speter return (BAM_ERROR); 91251875Speter } 92251875Speter 93251875Speter /* 94251875Speter * The GRUB multiboot header must be 32-bit aligned and completely 95251875Speter * contained in the 1st 8K of the file. If the unix binary has 96251875Speter * a multiboot header, then it is a 'dboot' kernel. Otherwise, 97251875Speter * this kernel must be booted via multiboot -- we call this a 98251875Speter * 'multiboot' kernel. 99251875Speter */ 100251875Speter bam_direct = BAM_DIRECT_MULTIBOOT; 101251875Speter for (m = 0; m < 8192 - sizeof (multiboot_header_t); m += 4) { 102251875Speter mbh = (void *)(image + m); 103251875Speter if (mbh->magic == MB_HEADER_MAGIC) { 104251875Speter bam_direct = BAM_DIRECT_DBOOT; 105251875Speter break; 106251875Speter } 107251875Speter } 108251875Speter (void) munmap(image, 8192); 109251875Speter (void) close(fd); 110251875Speter 111251875Speter if (bam_direct == BAM_DIRECT_DBOOT) { 112251875Speter (void) snprintf(fname, PATH_MAX, "%s/%s", root, XEN_32); 113251875Speter if (stat(fname, &sb) == 0) { 114251875Speter bam_is_hv = BAM_HV_PRESENT; 115251875Speter } else { 116251875Speter bam_is_hv = BAM_HV_NO; 117251875Speter } 118251875Speter } 119251875Speter 120251875Speter return (BAM_SUCCESS); 121251875Speter} 122251875Speter 123251875Speter#define INST_RELEASE "var/sadm/system/admin/INST_RELEASE" 124251875Speter 125251875Speter/* 126251875Speter * Return true if root has been bfu'ed. bfu will blow away 127251875Speter * var/sadm/system/admin/INST_RELEASE, so if it's still there, we can 128251875Speter * assume the system has not been bfu'ed. 129251875Speter */ 130251875Speterstatic int 131251875Speteris_bfu_system(const char *root) 132251875Speter{ 133251875Speter static int is_bfu = -1; 134251875Speter char path[PATH_MAX]; 135251875Speter struct stat sb; 136251875Speter 137251875Speter if (is_bfu != -1) 138251875Speter return (is_bfu); 139251875Speter 140251875Speter (void) snprintf(path, sizeof (path), "%s/%s", root, INST_RELEASE); 141251875Speter if (stat(path, &sb) != 0) { 142251875Speter is_bfu = 1; 143251875Speter } else { 144251875Speter is_bfu = 0; 145251875Speter } 146251875Speter return (is_bfu); 147251875Speter} 148251875Speter 149251875Speter#define MENU_URL(root) (is_bfu_system(root) ? \ 150251875Speter "http://www.sun.com/msg/SUNOS-8000-CF" : \ 151251875Speter "http://www.sun.com/msg/SUNOS-8000-AK") 152251875Speter 153251875Speter/* 154251875Speter * Simply allocate a new line and copy in cmd + sep + arg 155251875Speter */ 156251875Spetervoid 157251875Speterupdate_line(line_t *linep) 158251875Speter{ 159251875Speter size_t size; 160251875Speter 161251875Speter free(linep->line); 162251875Speter size = strlen(linep->cmd) + strlen(linep->sep) + strlen(linep->arg) + 1; 163251875Speter linep->line = s_calloc(1, size); 164251875Speter (void) snprintf(linep->line, size, "%s%s%s", linep->cmd, linep->sep, 165251875Speter linep->arg); 166251875Speter} 167251875Speter 168251875Speter/* 169251875Speter * The parse_kernel_line function examines a menu.lst kernel line. For 170251875Speter * multiboot, this is: 171251875Speter * 172251875Speter * kernel <multiboot path> <flags1> <kernel path> <flags2> 173251875Speter * 174251875Speter * <multiboot path> is either /platform/i86pc/multiboot or /boot/multiboot 175251875Speter * 176251875Speter * <kernel path> may be missing, or may be any full or relative path to unix. 177251875Speter * We check for it by looking for a word ending in "/unix". If it ends 178251875Speter * in "kernel/unix", we upgrade it to a 32-bit entry. If it ends in 179251875Speter * "kernel/amd64/unix", we upgrade it to the default entry. Otherwise, 180251875Speter * it's a custom kernel, and we skip it. 181251875Speter * 182251875Speter * <flags*> are anything that doesn't fit either of the above - these will be 183251875Speter * copied over. 184251875Speter * 185251875Speter * For direct boot, the defaults are 186251875Speter * 187251875Speter * kernel$ <kernel path> <flags> 188251875Speter * 189251875Speter * <kernel path> is one of: 190251875Speter * /platform/i86pc/kernel/$ISADIR/unix 191251875Speter * /platform/i86pc/kernel/unix 192251875Speter * /platform/i86pc/kernel/amd64/unix 193251875Speter * /boot/platform/i86pc/kernel/unix 194251875Speter * 195251875Speter * If <kernel path> is any of the last three, the command may also be "kernel". 196251875Speter * 197251875Speter * <flags> is anything that isn't <kernel path>. 198251875Speter * 199251875Speter * This function is only called if it applies to our target boot environment. 200251875Speter * If we can't make any sense of the kernel line, an error is printed and 201251875Speter * BAM_ERROR is returned. 202251875Speter * 203251875Speter * The desired install type is given in the global variable bam_direct. 204251875Speter * If the kernel line is of a different install type, we change it to the 205251875Speter * preferred type. If the kernel line is already of the correct install 206251875Speter * type, we do nothing. Either way, BAM_SUCCESS is returned. 207251875Speter * 208251875Speter * For safety, we do one more check: if the kernel path starts with /boot, 209251875Speter * we verify that the new kernel exists before changing it. This is mainly 210251875Speter * done for bfu, as it may cause the failsafe archives to be a different 211251875Speter * boot architecture from the newly bfu'ed system. 212251875Speter */ 213251875Speterstatic error_t 214251875Speterparse_kernel_line(line_t *linep, const char *root, uint8_t *flags) 215251875Speter{ 216251875Speter char path[PATH_MAX]; 217251875Speter int len, left, total_len; 218251875Speter struct stat sb; 219251875Speter char *new_ptr, *new_arg, *old_ptr; 220251875Speter menu_cmd_t which; 221251875Speter 222251875Speter /* Used when changing a multiboot line to dboot */ 223251875Speter char *unix_ptr, *flags1_ptr, *flags2_ptr; 224251875Speter 225251875Speter /* 226251875Speter * Note that BAM_ENTRY_DBOOT refers to the entry we're looking at, not 227251875Speter * necessarily the system type. 228251875Speter */ 229251875Speter if (strncmp(linep->arg, DIRECT_BOOT_32, 230251875Speter sizeof (DIRECT_BOOT_32) - 1) == 0) { 231251875Speter *flags |= BAM_ENTRY_DBOOT | BAM_ENTRY_32BIT; 232251875Speter } else if ((strncmp(linep->arg, DIRECT_BOOT_KERNEL, 233251875Speter sizeof (DIRECT_BOOT_KERNEL) - 1) == 0) || 234251875Speter (strncmp(linep->arg, DIRECT_BOOT_64, 235251875Speter sizeof (DIRECT_BOOT_64) - 1) == 0) || 236251875Speter (strncmp(linep->arg, DIRECT_BOOT_FAILSAFE_KERNEL, 237251875Speter sizeof (DIRECT_BOOT_FAILSAFE_KERNEL) - 1) == 0)) { 238251875Speter *flags |= BAM_ENTRY_DBOOT; 239251875Speter } else if ((strncmp(linep->arg, MULTI_BOOT, 240251875Speter sizeof (MULTI_BOOT) - 1) == 0) || 241251875Speter (strncmp(linep->arg, MULTI_BOOT_FAILSAFE, 242251875Speter sizeof (MULTI_BOOT_FAILSAFE) - 1) == 0)) { 243251875Speter *flags &= ~BAM_ENTRY_DBOOT; 244251875Speter } else { 245251875Speter bam_error(NO_KERNEL_MATCH, linep->lineNum, MENU_URL(root)); 246251875Speter return (BAM_ERROR); 247251875Speter } 248251875Speter 249251875Speter if (((*flags & BAM_ENTRY_DBOOT) && (bam_direct == BAM_DIRECT_DBOOT)) || 250251875Speter (((*flags & BAM_ENTRY_DBOOT) == 0) && 251251875Speter (bam_direct == BAM_DIRECT_MULTIBOOT))) { 252 253 /* No action needed */ 254 return (BAM_SUCCESS); 255 } 256 257 if (*flags & BAM_ENTRY_MINIROOT) { 258 /* 259 * We're changing boot architectures - make sure 260 * the multiboot failsafe still exists. 261 */ 262 (void) snprintf(path, PATH_MAX, "%s%s", root, 263 (*flags & BAM_ENTRY_DBOOT) ? MULTI_BOOT_FAILSAFE : 264 DIRECT_BOOT_FAILSAFE_KERNEL); 265 if (stat(path, &sb) != 0) { 266 if (bam_verbose) { 267 bam_error(FAILSAFE_MISSING, linep->lineNum); 268 } 269 return (BAM_SUCCESS); 270 } 271 } 272 273 /* 274 * Make sure we have the correct cmd - either kernel or kernel$ 275 * The failsafe entry should always be KERNEL_CMD. 276 */ 277 which = ((bam_direct == BAM_DIRECT_MULTIBOOT) || 278 (*flags & BAM_ENTRY_MINIROOT)) ? KERNEL_CMD : KERNEL_DOLLAR_CMD; 279 free(linep->cmd); 280 len = strlen(menu_cmds[which]) + 1; 281 linep->cmd = s_calloc(1, len); 282 (void) strncpy(linep->cmd, menu_cmds[which], len); 283 284 /* 285 * Since all arguments are copied, the new arg string should be close 286 * in size to the old one. Just add 32 to cover the difference in 287 * the boot path. 288 */ 289 total_len = strlen(linep->arg) + 32; 290 new_arg = s_calloc(1, total_len); 291 old_ptr = strchr(linep->arg, ' '); 292 if (old_ptr != NULL) 293 old_ptr++; 294 295 /* 296 * Transitioning from dboot to multiboot is pretty simple. We 297 * copy in multiboot and any args. 298 */ 299 if (bam_direct == BAM_DIRECT_MULTIBOOT) { 300 if (old_ptr == NULL) { 301 (void) snprintf(new_arg, total_len, "%s", 302 (*flags & BAM_ENTRY_MINIROOT) ? 303 MULTI_BOOT_FAILSAFE : MULTI_BOOT); 304 } else { 305 (void) snprintf(new_arg, total_len, "%s %s", 306 (*flags & BAM_ENTRY_MINIROOT) ? 307 MULTI_BOOT_FAILSAFE : MULTI_BOOT, old_ptr); 308 } 309 goto done; 310 } 311 312 /* 313 * Transitioning from multiboot to directboot is a bit more 314 * complicated, since we may have two sets of arguments to 315 * copy and a unix path to parse. 316 * 317 * First, figure out if there's a unix path. 318 */ 319 if ((old_ptr != NULL) && 320 ((unix_ptr = strstr(old_ptr, "/unix")) != NULL)) { 321 /* See if there's anything past unix */ 322 flags2_ptr = unix_ptr + sizeof ("/unix"); 323 if (*flags2_ptr == '\0') { 324 flags2_ptr = NULL; 325 } 326 327 while ((unix_ptr > old_ptr) && (*unix_ptr != ' ')) 328 unix_ptr--; 329 330 if (unix_ptr == old_ptr) { 331 flags1_ptr = NULL; 332 } else { 333 flags1_ptr = old_ptr; 334 } 335 336 if (strstr(unix_ptr, "kernel/unix") != NULL) { 337 *flags |= BAM_ENTRY_32BIT; 338 } else if ((strstr(unix_ptr, "kernel/amd64/unix") == NULL) && 339 (!bam_force)) { 340 /* 341 * If the above strstr returns NULL, but bam_force is 342 * set, we'll be upgrading an Install kernel. The 343 * result probably won't be what was intended, but we'll 344 * try it anyways. 345 */ 346 return (BAM_SKIP); 347 } 348 } else if (old_ptr != NULL) { 349 flags1_ptr = old_ptr; 350 unix_ptr = flags1_ptr + strlen(old_ptr); 351 flags2_ptr = NULL; 352 } else { 353 unix_ptr = flags1_ptr = flags2_ptr = NULL; 354 } 355 356 if (*flags & BAM_ENTRY_MINIROOT) { 357 (void) snprintf(new_arg, total_len, "%s", 358 DIRECT_BOOT_FAILSAFE_KERNEL); 359 } else if (*flags & BAM_ENTRY_32BIT) { 360 (void) snprintf(new_arg, total_len, "%s", DIRECT_BOOT_32); 361 } else { 362 (void) snprintf(new_arg, total_len, "%s", DIRECT_BOOT_KERNEL); 363 } 364 365 /* 366 * We now want to copy flags1_ptr through unix_ptr, and 367 * flags2_ptr through the end of the string 368 */ 369 if (flags1_ptr != NULL) { 370 len = strlcat(new_arg, " ", total_len); 371 left = total_len - len; 372 new_ptr = new_arg + len; 373 374 if ((unix_ptr - flags1_ptr) < left) 375 left = (unix_ptr - flags1_ptr) + 1; 376 (void) strlcpy(new_ptr, flags1_ptr, left); 377 } 378 if (flags2_ptr != NULL) { 379 (void) strlcat(new_arg, " ", total_len); 380 (void) strlcat(new_arg, flags2_ptr, total_len); 381 } 382 383done: 384 free(linep->arg); 385 linep->arg = new_arg; 386 update_line(linep); 387 return (BAM_SUCCESS); 388} 389 390/* 391 * Similar to above, except this time we're looking at a module line, 392 * which is quite a bit simpler. 393 * 394 * Under multiboot, the archive line is: 395 * 396 * module /platform/i86pc/boot_archive 397 * 398 * Under directboot, the archive line is: 399 * 400 * module$ /platform/i86pc/$ISADIR/boot_archive 401 * 402 * which may be specified exactly as either of: 403 * 404 * module /platform/i86pc/boot_archive 405 * module /platform/i86pc/amd64/boot_archive 406 * 407 * For either dboot or multiboot, the failsafe is: 408 * 409 * module /boot/x86.miniroot-safe 410 */ 411static error_t 412parse_module_line(line_t *linep, const char *root, uint8_t flags) 413{ 414 int len; 415 menu_cmd_t which; 416 char *new; 417 418 /* 419 * If necessary, BAM_ENTRY_MINIROOT was already set in flags 420 * in upgrade_menu(). We re-check BAM_ENTRY_DBOOT here in here 421 * in case the kernel and module lines differ. 422 */ 423 if ((strcmp(linep->arg, DIRECT_BOOT_ARCHIVE) == 0) || 424 (strcmp(linep->arg, DIRECT_BOOT_ARCHIVE_64) == 0)) { 425 flags |= BAM_ENTRY_DBOOT; 426 } else if ((strcmp(linep->arg, MULTI_BOOT_ARCHIVE) == 0) || 427 (strcmp(linep->arg, MINIROOT) == 0)) { 428 flags &= ~BAM_ENTRY_DBOOT; 429 } else { 430 bam_error(NO_MODULE_MATCH, linep->lineNum, MENU_URL(root)); 431 return (BAM_ERROR); 432 } 433 434 if (((flags & BAM_ENTRY_DBOOT) && (bam_direct == BAM_DIRECT_DBOOT)) || 435 (((flags & BAM_ENTRY_DBOOT) == 0) && 436 (bam_direct == BAM_DIRECT_MULTIBOOT)) || 437 ((flags & BAM_ENTRY_MINIROOT) && 438 (strcmp(linep->cmd, menu_cmds[MODULE_CMD]) == 0))) { 439 440 /* No action needed */ 441 return (BAM_SUCCESS); 442 } 443 444 /* 445 * Make sure we have the correct cmd - either module or module$ 446 * The failsafe entry should always be MODULE_CMD. 447 */ 448 which = ((bam_direct == BAM_DIRECT_MULTIBOOT) || 449 (flags & BAM_ENTRY_MINIROOT)) ? MODULE_CMD : MODULE_DOLLAR_CMD; 450 free(linep->cmd); 451 len = strlen(menu_cmds[which]) + 1; 452 linep->cmd = s_calloc(1, len); 453 (void) strncpy(linep->cmd, menu_cmds[which], len); 454 455 if (flags & BAM_ENTRY_MINIROOT) { 456 new = MINIROOT; 457 } else if ((bam_direct == BAM_DIRECT_DBOOT) && 458 ((flags & BAM_ENTRY_32BIT) == 0)) { 459 new = DIRECT_BOOT_ARCHIVE; 460 } else { 461 new = MULTI_BOOT_ARCHIVE; 462 } 463 464 free(linep->arg); 465 len = strlen(new) + 1; 466 linep->arg = s_calloc(1, len); 467 (void) strncpy(linep->arg, new, len); 468 update_line(linep); 469 470 return (BAM_SUCCESS); 471} 472 473/*ARGSUSED*/ 474error_t 475upgrade_menu(menu_t *mp, char *root, char *opt) 476{ 477 entry_t *cur_entry; 478 line_t *cur_line; 479 int i, skipit, num_entries, found_hv; 480 int *hand_entries = NULL; 481 boolean_t found_kernel = B_FALSE; 482 error_t rv; 483 char *rootdev, *grubdisk = NULL; 484 485 skipit = num_entries = found_hv = 0; 486 487 rootdev = get_special(root); 488 if (rootdev) { 489 grubdisk = os_to_grubdisk(rootdev, strlen(root) == 1); 490 free(rootdev); 491 rootdev = NULL; 492 } 493 494 /* Loop through all OS entries in the menu.lst file */ 495 for (cur_entry = mp->entries; cur_entry != NULL; 496 cur_entry = cur_entry->next, skipit = 0) { 497 498 if ((cur_entry->flags & BAM_ENTRY_CHAINLOADER) || 499 ((cur_entry->flags & BAM_ENTRY_MINIROOT) && !bam_force)) 500 continue; 501 502 /* 503 * We only change entries added by bootadm and live upgrade, 504 * and warn on the rest, unless the -f flag was passed. 505 */ 506 if ((!(cur_entry->flags & (BAM_ENTRY_BOOTADM|BAM_ENTRY_LU))) && 507 !bam_force) { 508 if (num_entries == 0) { 509 hand_entries = s_calloc(1, sizeof (int)); 510 } else { 511 hand_entries = s_realloc(hand_entries, 512 (num_entries + 1) * sizeof (int)); 513 } 514 hand_entries[num_entries++] = cur_entry->entryNum; 515 continue; 516 } 517 518 if (cur_entry->flags & BAM_ENTRY_HV) { 519 found_hv = 1; 520 continue; 521 } 522 523 /* 524 * We make two loops through the lines. First, we check if 525 * there is a root entry, and if so, whether we should be 526 * checking this entry. 527 */ 528 if ((grubdisk != NULL) && (cur_entry->flags & BAM_ENTRY_ROOT)) { 529 for (cur_line = cur_entry->start; cur_line != NULL; 530 cur_line = cur_line->next) { 531 if ((cur_line->cmd == NULL) || 532 (cur_line->arg == NULL)) 533 continue; 534 535 if (strcmp(cur_line->cmd, 536 menu_cmds[ROOT_CMD]) == 0) { 537 if (strcmp(cur_line->arg, 538 grubdisk) != 0) { 539 /* A different slice */ 540 skipit = 1; 541 } 542 break; 543 } 544 if (cur_line == cur_entry->end) 545 break; 546 } 547 } 548 if (skipit) 549 continue; 550 551 for (cur_line = cur_entry->start; cur_line != NULL; 552 cur_line = cur_line->next) { 553 554 /* 555 * We only compare for the length of KERNEL_CMD, 556 * so that KERNEL_DOLLAR_CMD will also match. 557 */ 558 if (strncmp(cur_line->cmd, menu_cmds[KERNEL_CMD], 559 strlen(menu_cmds[KERNEL_CMD])) == 0) { 560 rv = parse_kernel_line(cur_line, root, 561 &(cur_entry->flags)); 562 if (rv == BAM_SKIP) { 563 break; 564 } else if (rv != BAM_SUCCESS) { 565 return (rv); 566 } 567 found_kernel = B_TRUE; 568 } else if (strncmp(cur_line->cmd, 569 menu_cmds[MODULE_CMD], 570 strlen(menu_cmds[MODULE_CMD])) == 0) { 571 rv = parse_module_line(cur_line, root, 572 cur_entry->flags); 573 if (rv != BAM_SUCCESS) { 574 return (rv); 575 } 576 } 577 if (cur_line == cur_entry->end) 578 break; 579 } 580 } 581 582 /* 583 * If we're upgrading to a virtualized kernel and there are no 584 * hv entries in menu.lst, we need to add one. 585 */ 586 if ((bam_is_hv == BAM_HV_PRESENT) && (found_hv == 0)) { 587 (void) add_boot_entry(mp, NEW_HV_ENTRY, grubdisk, 588 XEN_MENU, KERNEL_MODULE_LINE, DIRECT_BOOT_ARCHIVE); 589 } 590 591 /* 592 * We only want to output one error, to avoid confusing a user. We 593 * rank "No kernels changed" as a higher priority than "will not 594 * update hand-added entries", since the former implies the latter. 595 */ 596 if (found_kernel == B_FALSE) { 597 bam_error(NO_KERNELS_FOUND, MENU_URL(root)); 598 return (BAM_ERROR); 599 } else if (num_entries > 0) { 600 bam_error(HAND_ADDED_ENTRY, MENU_URL(root)); 601 bam_print_stderr("Entry Number%s: ", (num_entries > 1) ? 602 "s" : ""); 603 for (i = 0; i < num_entries; i++) { 604 bam_print_stderr("%d ", hand_entries[i]); 605 } 606 bam_print_stderr("\n"); 607 } 608 return (BAM_WRITE); 609} 610