1*12947SEnrico.Perla@Sun.COM /*
2*12947SEnrico.Perla@Sun.COM * CDDL HEADER START
3*12947SEnrico.Perla@Sun.COM *
4*12947SEnrico.Perla@Sun.COM * The contents of this file are subject to the terms of the
5*12947SEnrico.Perla@Sun.COM * Common Development and Distribution License (the "License").
6*12947SEnrico.Perla@Sun.COM * You may not use this file except in compliance with the License.
7*12947SEnrico.Perla@Sun.COM *
8*12947SEnrico.Perla@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*12947SEnrico.Perla@Sun.COM * or http://www.opensolaris.org/os/licensing.
10*12947SEnrico.Perla@Sun.COM * See the License for the specific language governing permissions
11*12947SEnrico.Perla@Sun.COM * and limitations under the License.
12*12947SEnrico.Perla@Sun.COM *
13*12947SEnrico.Perla@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
14*12947SEnrico.Perla@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*12947SEnrico.Perla@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
16*12947SEnrico.Perla@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
17*12947SEnrico.Perla@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
18*12947SEnrico.Perla@Sun.COM *
19*12947SEnrico.Perla@Sun.COM * CDDL HEADER END
20*12947SEnrico.Perla@Sun.COM */
21*12947SEnrico.Perla@Sun.COM /*
22*12947SEnrico.Perla@Sun.COM * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
23*12947SEnrico.Perla@Sun.COM */
24*12947SEnrico.Perla@Sun.COM
25*12947SEnrico.Perla@Sun.COM #include <stdio.h>
26*12947SEnrico.Perla@Sun.COM #include <errno.h>
27*12947SEnrico.Perla@Sun.COM #include <assert.h>
28*12947SEnrico.Perla@Sun.COM #include <unistd.h>
29*12947SEnrico.Perla@Sun.COM #include <libintl.h>
30*12947SEnrico.Perla@Sun.COM #include <sys/multiboot.h>
31*12947SEnrico.Perla@Sun.COM #include <sys/sysmacros.h>
32*12947SEnrico.Perla@Sun.COM
33*12947SEnrico.Perla@Sun.COM #include "bblk_einfo.h"
34*12947SEnrico.Perla@Sun.COM #include "boot_utils.h"
35*12947SEnrico.Perla@Sun.COM #include "mboot_extra.h"
36*12947SEnrico.Perla@Sun.COM
37*12947SEnrico.Perla@Sun.COM /*
38*12947SEnrico.Perla@Sun.COM * Common functions to deal with the fake-multiboot encapsulation of the
39*12947SEnrico.Perla@Sun.COM * bootblock and the location of the extra information area.
40*12947SEnrico.Perla@Sun.COM */
41*12947SEnrico.Perla@Sun.COM
42*12947SEnrico.Perla@Sun.COM /* mboot checksum routine. */
43*12947SEnrico.Perla@Sun.COM uint32_t
compute_checksum(char * data,uint32_t size)44*12947SEnrico.Perla@Sun.COM compute_checksum(char *data, uint32_t size)
45*12947SEnrico.Perla@Sun.COM {
46*12947SEnrico.Perla@Sun.COM uint32_t *ck_ptr;
47*12947SEnrico.Perla@Sun.COM uint32_t cksum = 0;
48*12947SEnrico.Perla@Sun.COM int i;
49*12947SEnrico.Perla@Sun.COM
50*12947SEnrico.Perla@Sun.COM ck_ptr = (uint32_t *)data;
51*12947SEnrico.Perla@Sun.COM for (i = 0; i < size; i += sizeof (uint32_t))
52*12947SEnrico.Perla@Sun.COM cksum += *ck_ptr++;
53*12947SEnrico.Perla@Sun.COM
54*12947SEnrico.Perla@Sun.COM return (-cksum);
55*12947SEnrico.Perla@Sun.COM }
56*12947SEnrico.Perla@Sun.COM
57*12947SEnrico.Perla@Sun.COM /* Given a buffer, look for a multiboot header within it. */
58*12947SEnrico.Perla@Sun.COM int
find_multiboot(char * buffer,uint32_t buf_size,uint32_t * mboot_off)59*12947SEnrico.Perla@Sun.COM find_multiboot(char *buffer, uint32_t buf_size, uint32_t *mboot_off)
60*12947SEnrico.Perla@Sun.COM {
61*12947SEnrico.Perla@Sun.COM multiboot_header_t *mboot;
62*12947SEnrico.Perla@Sun.COM uint32_t *iter;
63*12947SEnrico.Perla@Sun.COM uint32_t cksum;
64*12947SEnrico.Perla@Sun.COM uint32_t boundary;
65*12947SEnrico.Perla@Sun.COM int i = 0;
66*12947SEnrico.Perla@Sun.COM
67*12947SEnrico.Perla@Sun.COM iter = (uint32_t *)buffer;
68*12947SEnrico.Perla@Sun.COM *mboot_off = 0;
69*12947SEnrico.Perla@Sun.COM /* multiboot header has to be within the first 32K. */
70*12947SEnrico.Perla@Sun.COM boundary = MBOOT_SCAN_SIZE;
71*12947SEnrico.Perla@Sun.COM if (boundary > buf_size)
72*12947SEnrico.Perla@Sun.COM boundary = buf_size;
73*12947SEnrico.Perla@Sun.COM
74*12947SEnrico.Perla@Sun.COM boundary = boundary - sizeof (multiboot_header_t);
75*12947SEnrico.Perla@Sun.COM
76*12947SEnrico.Perla@Sun.COM for (i = 0; i < boundary; i += 4, iter++) {
77*12947SEnrico.Perla@Sun.COM
78*12947SEnrico.Perla@Sun.COM mboot = (multiboot_header_t *)iter;
79*12947SEnrico.Perla@Sun.COM if (mboot->magic != MB_HEADER_MAGIC)
80*12947SEnrico.Perla@Sun.COM continue;
81*12947SEnrico.Perla@Sun.COM
82*12947SEnrico.Perla@Sun.COM /* Found magic signature -- check checksum. */
83*12947SEnrico.Perla@Sun.COM cksum = -(mboot->flags + mboot->magic);
84*12947SEnrico.Perla@Sun.COM if (mboot->checksum != cksum) {
85*12947SEnrico.Perla@Sun.COM BOOT_DEBUG("multiboot magic found at %p, but checksum "
86*12947SEnrico.Perla@Sun.COM "mismatches (is %x, should be %x)\n", mboot,
87*12947SEnrico.Perla@Sun.COM mboot->checksum, cksum);
88*12947SEnrico.Perla@Sun.COM continue;
89*12947SEnrico.Perla@Sun.COM } else {
90*12947SEnrico.Perla@Sun.COM if (!(mboot->flags & BB_MBOOT_AOUT_FLAG)) {
91*12947SEnrico.Perla@Sun.COM BOOT_DEBUG("multiboot structure found, but no "
92*12947SEnrico.Perla@Sun.COM "AOUT kludge specified, skipping.\n");
93*12947SEnrico.Perla@Sun.COM continue;
94*12947SEnrico.Perla@Sun.COM } else {
95*12947SEnrico.Perla@Sun.COM /* proper multiboot structure found. */
96*12947SEnrico.Perla@Sun.COM *mboot_off = i;
97*12947SEnrico.Perla@Sun.COM return (BC_SUCCESS);
98*12947SEnrico.Perla@Sun.COM }
99*12947SEnrico.Perla@Sun.COM }
100*12947SEnrico.Perla@Sun.COM }
101*12947SEnrico.Perla@Sun.COM
102*12947SEnrico.Perla@Sun.COM return (BC_ERROR);
103*12947SEnrico.Perla@Sun.COM }
104*12947SEnrico.Perla@Sun.COM
105*12947SEnrico.Perla@Sun.COM /*
106*12947SEnrico.Perla@Sun.COM * Given a pointer to the extra information area (a sequence of bb_header_ext_t
107*12947SEnrico.Perla@Sun.COM * + payload chunks), find the extended information structure.
108*12947SEnrico.Perla@Sun.COM */
109*12947SEnrico.Perla@Sun.COM bblk_einfo_t *
find_einfo(char * extra)110*12947SEnrico.Perla@Sun.COM find_einfo(char *extra)
111*12947SEnrico.Perla@Sun.COM {
112*12947SEnrico.Perla@Sun.COM bb_header_ext_t *ext_header;
113*12947SEnrico.Perla@Sun.COM bblk_einfo_t *einfo;
114*12947SEnrico.Perla@Sun.COM uint32_t cksum;
115*12947SEnrico.Perla@Sun.COM
116*12947SEnrico.Perla@Sun.COM assert(extra != NULL);
117*12947SEnrico.Perla@Sun.COM
118*12947SEnrico.Perla@Sun.COM ext_header = (bb_header_ext_t *)extra;
119*12947SEnrico.Perla@Sun.COM cksum = compute_checksum(extra + sizeof (bb_header_ext_t),
120*12947SEnrico.Perla@Sun.COM ext_header->size);
121*12947SEnrico.Perla@Sun.COM BOOT_DEBUG("Extended information header checksum is %x\n", cksum);
122*12947SEnrico.Perla@Sun.COM
123*12947SEnrico.Perla@Sun.COM if (cksum != ext_header->checksum) {
124*12947SEnrico.Perla@Sun.COM BOOT_DEBUG("Unable to find extended versioning information, "
125*12947SEnrico.Perla@Sun.COM "data looks corrupted\n");
126*12947SEnrico.Perla@Sun.COM return (NULL);
127*12947SEnrico.Perla@Sun.COM }
128*12947SEnrico.Perla@Sun.COM
129*12947SEnrico.Perla@Sun.COM /*
130*12947SEnrico.Perla@Sun.COM * Currently we only have one extra header so it must be encapsulating
131*12947SEnrico.Perla@Sun.COM * the extended information structure.
132*12947SEnrico.Perla@Sun.COM */
133*12947SEnrico.Perla@Sun.COM einfo = (bblk_einfo_t *)(extra + sizeof (bb_header_ext_t));
134*12947SEnrico.Perla@Sun.COM if (memcmp(einfo->magic, EINFO_MAGIC, EINFO_MAGIC_SIZE) != 0) {
135*12947SEnrico.Perla@Sun.COM BOOT_DEBUG("Unable to read stage2 extended versioning "
136*12947SEnrico.Perla@Sun.COM "information, wrong magic identifier\n");
137*12947SEnrico.Perla@Sun.COM BOOT_DEBUG("Found %s, expected %s\n", einfo->magic,
138*12947SEnrico.Perla@Sun.COM EINFO_MAGIC);
139*12947SEnrico.Perla@Sun.COM return (NULL);
140*12947SEnrico.Perla@Sun.COM }
141*12947SEnrico.Perla@Sun.COM
142*12947SEnrico.Perla@Sun.COM return (einfo);
143*12947SEnrico.Perla@Sun.COM }
144*12947SEnrico.Perla@Sun.COM
145*12947SEnrico.Perla@Sun.COM /*
146*12947SEnrico.Perla@Sun.COM * Given a pointer to the extra area, add the extended information structure
147*12947SEnrico.Perla@Sun.COM * encapsulated by a bb_header_ext_t structure.
148*12947SEnrico.Perla@Sun.COM */
149*12947SEnrico.Perla@Sun.COM void
add_einfo(char * extra,char * updt_str,bblk_hs_t * hs,uint32_t avail_space)150*12947SEnrico.Perla@Sun.COM add_einfo(char *extra, char *updt_str, bblk_hs_t *hs, uint32_t avail_space)
151*12947SEnrico.Perla@Sun.COM {
152*12947SEnrico.Perla@Sun.COM bb_header_ext_t *ext_hdr;
153*12947SEnrico.Perla@Sun.COM uint32_t used_space;
154*12947SEnrico.Perla@Sun.COM unsigned char *dest;
155*12947SEnrico.Perla@Sun.COM int ret;
156*12947SEnrico.Perla@Sun.COM
157*12947SEnrico.Perla@Sun.COM assert(extra != NULL);
158*12947SEnrico.Perla@Sun.COM
159*12947SEnrico.Perla@Sun.COM if (updt_str == NULL) {
160*12947SEnrico.Perla@Sun.COM BOOT_DEBUG("WARNING: no update string passed to "
161*12947SEnrico.Perla@Sun.COM "add_stage2_einfo()\n");
162*12947SEnrico.Perla@Sun.COM return;
163*12947SEnrico.Perla@Sun.COM }
164*12947SEnrico.Perla@Sun.COM
165*12947SEnrico.Perla@Sun.COM /* Reserve space for the extra header. */
166*12947SEnrico.Perla@Sun.COM ext_hdr = (bb_header_ext_t *)extra;
167*12947SEnrico.Perla@Sun.COM dest = (unsigned char *)extra + sizeof (*ext_hdr);
168*12947SEnrico.Perla@Sun.COM /* Place the extended information structure. */
169*12947SEnrico.Perla@Sun.COM ret = prepare_and_write_einfo(dest, updt_str, hs, avail_space,
170*12947SEnrico.Perla@Sun.COM &used_space);
171*12947SEnrico.Perla@Sun.COM if (ret != 0) {
172*12947SEnrico.Perla@Sun.COM (void) fprintf(stderr, gettext("Unable to write the extended "
173*12947SEnrico.Perla@Sun.COM "versioning information\n"));
174*12947SEnrico.Perla@Sun.COM return;
175*12947SEnrico.Perla@Sun.COM }
176*12947SEnrico.Perla@Sun.COM
177*12947SEnrico.Perla@Sun.COM /* Fill the extended information associated header. */
178*12947SEnrico.Perla@Sun.COM ext_hdr->size = P2ROUNDUP(used_space, 8);
179*12947SEnrico.Perla@Sun.COM ext_hdr->checksum = compute_checksum((char *)dest, ext_hdr->size);
180*12947SEnrico.Perla@Sun.COM }
181