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]
22 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
31 #include <sys/multiboot.h>
32 #include <sys/sysmacros.h>
34 #include "bblk_einfo.h"
35 #include "boot_utils.h"
36 #include "mboot_extra.h"
39 * Common functions to deal with the fake-multiboot encapsulation of the
40 * bootblock and the location of the extra information area.
43 /* mboot checksum routine. */
45 compute_checksum(char *data
, uint32_t size
)
51 ck_ptr
= (uint32_t *)data
;
52 for (i
= 0; i
< size
; i
+= sizeof (uint32_t))
58 /* Given a buffer, look for a multiboot header within it. */
60 find_multiboot(char *buffer
, uint32_t buf_size
, uint32_t *mboot_off
)
62 multiboot_header_t
*mboot
;
68 iter
= (uint32_t *)buffer
;
70 /* multiboot header has to be within the first 32K. */
71 boundary
= MBOOT_SCAN_SIZE
;
72 if (boundary
> buf_size
)
75 boundary
= boundary
- sizeof (multiboot_header_t
);
77 for (i
= 0; i
< boundary
; i
+= 4, iter
++) {
79 mboot
= (multiboot_header_t
*)iter
;
80 if (mboot
->magic
!= MB_HEADER_MAGIC
)
83 /* Found magic signature -- check checksum. */
84 cksum
= -(mboot
->flags
+ mboot
->magic
);
85 if (mboot
->checksum
!= cksum
) {
86 BOOT_DEBUG("multiboot magic found at %p, but checksum "
87 "mismatches (is %x, should be %x)\n", mboot
,
88 mboot
->checksum
, cksum
);
91 if (!(mboot
->flags
& BB_MBOOT_AOUT_FLAG
)) {
92 BOOT_DEBUG("multiboot structure found, but no "
93 "AOUT kludge specified, skipping.\n");
96 /* proper multiboot structure found. */
107 * Given a pointer to the extra information area (a sequence of bb_header_ext_t
108 * + payload chunks), find the extended information structure.
111 find_einfo(char *extra
, uint32_t size
)
113 bb_header_ext_t
*ext_header
;
117 assert(extra
!= NULL
);
119 ext_header
= (bb_header_ext_t
*)extra
;
120 if (ext_header
->size
> size
) {
121 BOOT_DEBUG("Unable to find extended versioning information, "
122 "data size too big\n");
126 cksum
= compute_checksum(extra
+ sizeof (bb_header_ext_t
),
128 BOOT_DEBUG("Extended information header checksum is %x\n", cksum
);
130 if (cksum
!= ext_header
->checksum
) {
131 BOOT_DEBUG("Unable to find extended versioning information, "
132 "data looks corrupted\n");
137 * Currently we only have one extra header so it must be encapsulating
138 * the extended information structure.
140 einfo
= (bblk_einfo_t
*)(extra
+ sizeof (bb_header_ext_t
));
141 if (memcmp(einfo
->magic
, EINFO_MAGIC
, EINFO_MAGIC_SIZE
) != 0) {
142 BOOT_DEBUG("Unable to read stage2 extended versioning "
143 "information, wrong magic identifier\n");
144 BOOT_DEBUG("Found %s, expected %s\n", einfo
->magic
,
153 * Given a pointer to the extra area, add the extended information structure
154 * encapsulated by a bb_header_ext_t structure.
157 add_einfo(char *extra
, char *updt_str
, bblk_hs_t
*hs
, uint32_t avail_space
)
159 bb_header_ext_t
*ext_hdr
;
164 assert(extra
!= NULL
);
166 if (updt_str
== NULL
) {
167 BOOT_DEBUG("WARNING: no update string passed to "
168 "add_stage2_einfo()\n");
172 /* Reserve space for the extra header. */
173 ext_hdr
= (bb_header_ext_t
*)extra
;
174 dest
= (unsigned char *)extra
+ sizeof (*ext_hdr
);
175 /* Place the extended information structure. */
176 ret
= prepare_and_write_einfo(dest
, updt_str
, hs
, avail_space
,
179 (void) fprintf(stderr
, gettext("Unable to write the extended "
180 "versioning information\n"));
184 /* Fill the extended information associated header. */
185 ext_hdr
->size
= P2ROUNDUP(used_space
, 8);
186 ext_hdr
->checksum
= compute_checksum((char *)dest
, ext_hdr
->size
);