xref: /onnv-gate/usr/src/cmd/boot/common/mboot_extra.c (revision 12947:f5f96e09bf49)
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