Unleashed v1.4
[unleashed.git] / usr / src / cmd / boot / bootadm / bootadm_upgrade.c
blobdffcd3a3b09480ec8c78a4ae6fbc94d9ed96ad3e
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 * Copyright 2017 Toomas Soome <tsoome@me.com>
27 #include <stdio.h>
28 #include <errno.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <unistd.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <limits.h>
35 #include <fcntl.h>
36 #include <strings.h>
38 #include <sys/mman.h>
39 #include <sys/elf.h>
40 #include <sys/multiboot.h>
42 #include "bootadm.h"
44 direct_or_multi_t bam_direct = BAM_DIRECT_NOT_SET;
45 hv_t bam_is_hv = BAM_HV_UNKNOWN;
46 findroot_t bam_is_findroot = BAM_FINDROOT_PRESENT;
48 error_t
49 get_boot_cap(const char *osroot)
51 char fname[PATH_MAX];
52 char *image;
53 uchar_t *ident;
54 uchar_t class;
55 int fd;
56 int m;
57 multiboot_header_t *mbh;
58 struct stat sb;
59 int error;
60 const char *fcn = "get_boot_cap()";
63 * The install media can support both 64 and 32 bit boot
64 * by using boot archive as ramdisk image. However, to save
65 * the memory, the ramdisk may only have either 32 or 64
66 * bit kernel files. To avoid error message about missing unix,
67 * we should try both variants here and only complain if neither
68 * is found. Since the 64-bit systems are more common, we start
69 * from amd64.
71 class = ELFCLASS64;
72 (void) snprintf(fname, PATH_MAX, "%s/%s", osroot,
73 "platform/kernel/unix");
74 fd = open(fname, O_RDONLY);
76 error = errno;
77 INJECT_ERROR1("GET_CAP_UNIX_OPEN", fd = -1);
78 if (fd < 0) {
79 bam_error(_("failed to open file: %s: %s\n"), fname,
80 strerror(error));
81 return (BAM_ERROR);
85 * Verify that this is a sane unix at least 8192 bytes in length
87 if (fstat(fd, &sb) == -1 || sb.st_size < 8192) {
88 (void) close(fd);
89 bam_error(_("invalid or corrupted binary: %s\n"), fname);
90 return (BAM_ERROR);
94 * mmap the first 8K
96 image = mmap(NULL, 8192, PROT_READ, MAP_SHARED, fd, 0);
97 error = errno;
98 INJECT_ERROR1("GET_CAP_MMAP", image = MAP_FAILED);
99 if (image == MAP_FAILED) {
100 bam_error(_("failed to mmap file: %s: %s\n"), fname,
101 strerror(error));
102 return (BAM_ERROR);
105 ident = (uchar_t *)image;
106 if (ident[EI_MAG0] != ELFMAG0 || ident[EI_MAG1] != ELFMAG1 ||
107 ident[EI_MAG2] != ELFMAG2 || ident[EI_MAG3] != ELFMAG3) {
108 bam_error(_("%s is not an ELF file.\n"), fname);
109 return (BAM_ERROR);
111 if (ident[EI_CLASS] != class) {
112 bam_error(_("%s is wrong ELF class 0x%x\n"), fname,
113 ident[EI_CLASS]);
114 return (BAM_ERROR);
118 * The GRUB multiboot header must be 32-bit aligned and completely
119 * contained in the 1st 8K of the file. If the unix binary has
120 * a multiboot header, then it is a 'dboot' kernel. Otherwise,
121 * this kernel must be booted via multiboot -- we call this a
122 * 'multiboot' kernel.
124 bam_direct = BAM_DIRECT_MULTIBOOT;
125 for (m = 0; m < 8192 - sizeof (multiboot_header_t); m += 4) {
126 mbh = (void *)(image + m);
127 if (mbh->magic == MB_HEADER_MAGIC) {
128 BAM_DPRINTF(("%s: is DBOOT unix\n", fcn));
129 bam_direct = BAM_DIRECT_DBOOT;
130 break;
133 (void) munmap(image, 8192);
134 (void) close(fd);
136 INJECT_ERROR1("GET_CAP_MULTIBOOT", bam_direct = BAM_DIRECT_MULTIBOOT);
137 if (bam_direct == BAM_DIRECT_DBOOT) {
138 if (bam_is_hv == BAM_HV_PRESENT) {
139 BAM_DPRINTF(("%s: is xVM system\n", fcn));
140 } else {
141 BAM_DPRINTF(("%s: is *NOT* xVM system\n", fcn));
143 } else {
144 BAM_DPRINTF(("%s: is MULTIBOOT unix\n", fcn));
147 BAM_DPRINTF(("%s: returning SUCCESS\n", fcn));
148 return (BAM_SUCCESS);