xref: /titanic_50/usr/src/cmd/boot/common/bblk_einfo.c (revision 6a634c9dca3093f3922e4b7ab826d7bdf17bf78e)
1*af28f636SEnrico Perla - Sun Microsystems /*
2*af28f636SEnrico Perla - Sun Microsystems  * CDDL HEADER START
3*af28f636SEnrico Perla - Sun Microsystems  *
4*af28f636SEnrico Perla - Sun Microsystems  * The contents of this file are subject to the terms of the
5*af28f636SEnrico Perla - Sun Microsystems  * Common Development and Distribution License (the "License").
6*af28f636SEnrico Perla - Sun Microsystems  * You may not use this file except in compliance with the License.
7*af28f636SEnrico Perla - Sun Microsystems  *
8*af28f636SEnrico Perla - Sun Microsystems  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*af28f636SEnrico Perla - Sun Microsystems  * or http://www.opensolaris.org/os/licensing.
10*af28f636SEnrico Perla - Sun Microsystems  * See the License for the specific language governing permissions
11*af28f636SEnrico Perla - Sun Microsystems  * and limitations under the License.
12*af28f636SEnrico Perla - Sun Microsystems  *
13*af28f636SEnrico Perla - Sun Microsystems  * When distributing Covered Code, include this CDDL HEADER in each
14*af28f636SEnrico Perla - Sun Microsystems  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*af28f636SEnrico Perla - Sun Microsystems  * If applicable, add the following below this CDDL HEADER, with the
16*af28f636SEnrico Perla - Sun Microsystems  * fields enclosed by brackets "[]" replaced with your own identifying
17*af28f636SEnrico Perla - Sun Microsystems  * information: Portions Copyright [yyyy] [name of copyright owner]
18*af28f636SEnrico Perla - Sun Microsystems  *
19*af28f636SEnrico Perla - Sun Microsystems  * CDDL HEADER END
20*af28f636SEnrico Perla - Sun Microsystems  */
21*af28f636SEnrico Perla - Sun Microsystems /*
22*af28f636SEnrico Perla - Sun Microsystems  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
23*af28f636SEnrico Perla - Sun Microsystems  */
24*af28f636SEnrico Perla - Sun Microsystems 
25*af28f636SEnrico Perla - Sun Microsystems #include <stdio.h>
26*af28f636SEnrico Perla - Sun Microsystems #include <stdint.h>
27*af28f636SEnrico Perla - Sun Microsystems #include <stdlib.h>
28*af28f636SEnrico Perla - Sun Microsystems #include <string.h>
29*af28f636SEnrico Perla - Sun Microsystems #include <libintl.h>
30*af28f636SEnrico Perla - Sun Microsystems #include <unistd.h>
31*af28f636SEnrico Perla - Sun Microsystems #include <fcntl.h>
32*af28f636SEnrico Perla - Sun Microsystems #include <sys/types.h>
33*af28f636SEnrico Perla - Sun Microsystems #include <sys/stat.h>
34*af28f636SEnrico Perla - Sun Microsystems 
35*af28f636SEnrico Perla - Sun Microsystems #include "bblk_einfo.h"
36*af28f636SEnrico Perla - Sun Microsystems #include "boot_utils.h"
37*af28f636SEnrico Perla - Sun Microsystems 
38*af28f636SEnrico Perla - Sun Microsystems bblk_hash_t	bblk_no_hash = {BBLK_NO_HASH, 0, "(no hash)", NULL};
39*af28f636SEnrico Perla - Sun Microsystems bblk_hash_t	bblk_md5_hash = {BBLK_HASH_MD5, 0x10, "MD5", md5_calc};
40*af28f636SEnrico Perla - Sun Microsystems 
41*af28f636SEnrico Perla - Sun Microsystems bblk_hash_t	*bblk_hash_list[BBLK_HASH_TOT] = {
42*af28f636SEnrico Perla - Sun Microsystems 	&bblk_no_hash,
43*af28f636SEnrico Perla - Sun Microsystems 	&bblk_md5_hash
44*af28f636SEnrico Perla - Sun Microsystems };
45*af28f636SEnrico Perla - Sun Microsystems 
46*af28f636SEnrico Perla - Sun Microsystems /*
47*af28f636SEnrico Perla - Sun Microsystems  * einfo_compare_dotted_version()
48*af28f636SEnrico Perla - Sun Microsystems  * Compares two strings with an arbitrary long number of dot-separated numbers.
49*af28f636SEnrico Perla - Sun Microsystems  * Returns:	0  - if the version numbers are equal
50*af28f636SEnrico Perla - Sun Microsystems  *		1  - if str1 version number is more recent than str2
51*af28f636SEnrico Perla - Sun Microsystems  *		2  - if str2 version number is more recent than str1
52*af28f636SEnrico Perla - Sun Microsystems  *		-1 - if an error occurred
53*af28f636SEnrico Perla - Sun Microsystems  *
54*af28f636SEnrico Perla - Sun Microsystems  * Comparison is done field by field, by retrieving an unsigned integer value,
55*af28f636SEnrico Perla - Sun Microsystems  * (missing fields are assumed as 0, but explict zeroes take precedence) so:
56*af28f636SEnrico Perla - Sun Microsystems  *   4.1.2.11 > 4.1.2.2 > 4.1.2.0 > 4.1.2
57*af28f636SEnrico Perla - Sun Microsystems  *
58*af28f636SEnrico Perla - Sun Microsystems  * where ">" means "more recent than".
59*af28f636SEnrico Perla - Sun Microsystems  */
60*af28f636SEnrico Perla - Sun Microsystems static int
einfo_compare_dotted_version(const char * str1,const char * str2)61*af28f636SEnrico Perla - Sun Microsystems einfo_compare_dotted_version(const char *str1, const char *str2)
62*af28f636SEnrico Perla - Sun Microsystems {
63*af28f636SEnrico Perla - Sun Microsystems 	int		retval = 0;
64*af28f636SEnrico Perla - Sun Microsystems 	char		*verstr1, *verstr2, *freeptr1, *freeptr2;
65*af28f636SEnrico Perla - Sun Microsystems 	char		*parsep1, *parsep2;
66*af28f636SEnrico Perla - Sun Microsystems 	unsigned int	val_str1, val_str2;
67*af28f636SEnrico Perla - Sun Microsystems 
68*af28f636SEnrico Perla - Sun Microsystems 	freeptr1 = verstr1 = strdup(str1);
69*af28f636SEnrico Perla - Sun Microsystems 	freeptr2 = verstr2 = strdup(str2);
70*af28f636SEnrico Perla - Sun Microsystems 	if (verstr1 == NULL || verstr2 == NULL) {
71*af28f636SEnrico Perla - Sun Microsystems 		retval = -1;
72*af28f636SEnrico Perla - Sun Microsystems 		goto out;
73*af28f636SEnrico Perla - Sun Microsystems 	}
74*af28f636SEnrico Perla - Sun Microsystems 
75*af28f636SEnrico Perla - Sun Microsystems 	while (verstr1 != NULL && verstr2 != NULL) {
76*af28f636SEnrico Perla - Sun Microsystems 		parsep1 = strsep(&verstr1, ".");
77*af28f636SEnrico Perla - Sun Microsystems 		parsep2 = strsep(&verstr2, ".");
78*af28f636SEnrico Perla - Sun Microsystems 
79*af28f636SEnrico Perla - Sun Microsystems 		val_str1 = atoi(parsep1);
80*af28f636SEnrico Perla - Sun Microsystems 		val_str2 = atoi(parsep2);
81*af28f636SEnrico Perla - Sun Microsystems 
82*af28f636SEnrico Perla - Sun Microsystems 		if (val_str1 > val_str2) {
83*af28f636SEnrico Perla - Sun Microsystems 			retval = 1;
84*af28f636SEnrico Perla - Sun Microsystems 			goto out;
85*af28f636SEnrico Perla - Sun Microsystems 		}
86*af28f636SEnrico Perla - Sun Microsystems 
87*af28f636SEnrico Perla - Sun Microsystems 		if (val_str2 > val_str1) {
88*af28f636SEnrico Perla - Sun Microsystems 			retval = 2;
89*af28f636SEnrico Perla - Sun Microsystems 			goto out;
90*af28f636SEnrico Perla - Sun Microsystems 		}
91*af28f636SEnrico Perla - Sun Microsystems 	}
92*af28f636SEnrico Perla - Sun Microsystems 
93*af28f636SEnrico Perla - Sun Microsystems 	/* Common portion of the version string is equal. */
94*af28f636SEnrico Perla - Sun Microsystems 	if (verstr1 == NULL && verstr2 != NULL)
95*af28f636SEnrico Perla - Sun Microsystems 		retval = 2;
96*af28f636SEnrico Perla - Sun Microsystems 	if (verstr2 == NULL && verstr1 != NULL)
97*af28f636SEnrico Perla - Sun Microsystems 		retval = 1;
98*af28f636SEnrico Perla - Sun Microsystems 
99*af28f636SEnrico Perla - Sun Microsystems out:
100*af28f636SEnrico Perla - Sun Microsystems 	free(freeptr1);
101*af28f636SEnrico Perla - Sun Microsystems 	free(freeptr2);
102*af28f636SEnrico Perla - Sun Microsystems 	return (retval);
103*af28f636SEnrico Perla - Sun Microsystems }
104*af28f636SEnrico Perla - Sun Microsystems 
105*af28f636SEnrico Perla - Sun Microsystems /*
106*af28f636SEnrico Perla - Sun Microsystems  * einfo_compare_timestamps()
107*af28f636SEnrico Perla - Sun Microsystems  * Currently, timestamp is in %Y%m%dT%H%M%SZ format in UTC, which means that
108*af28f636SEnrico Perla - Sun Microsystems  * we can simply do a lexicographic comparison to know which one is the most
109*af28f636SEnrico Perla - Sun Microsystems  * recent.
110*af28f636SEnrico Perla - Sun Microsystems  *
111*af28f636SEnrico Perla - Sun Microsystems  * Returns:   0  - if timestamps coincide
112*af28f636SEnrico Perla - Sun Microsystems  *            1  - if the timestamp in str1 is more recent
113*af28f636SEnrico Perla - Sun Microsystems  *            2  - if the timestamp in str2 is more recent
114*af28f636SEnrico Perla - Sun Microsystems  */
115*af28f636SEnrico Perla - Sun Microsystems static int
einfo_compare_timestamps(const char * str1,const char * str2)116*af28f636SEnrico Perla - Sun Microsystems einfo_compare_timestamps(const char *str1, const char *str2)
117*af28f636SEnrico Perla - Sun Microsystems {
118*af28f636SEnrico Perla - Sun Microsystems 	int	retval;
119*af28f636SEnrico Perla - Sun Microsystems 
120*af28f636SEnrico Perla - Sun Microsystems 	retval = strcmp(str1, str2);
121*af28f636SEnrico Perla - Sun Microsystems 	if (retval > 0)
122*af28f636SEnrico Perla - Sun Microsystems 		retval = 1;
123*af28f636SEnrico Perla - Sun Microsystems 	if (retval < 0)
124*af28f636SEnrico Perla - Sun Microsystems 		retval = 2;
125*af28f636SEnrico Perla - Sun Microsystems 
126*af28f636SEnrico Perla - Sun Microsystems 	return (retval);
127*af28f636SEnrico Perla - Sun Microsystems }
128*af28f636SEnrico Perla - Sun Microsystems 
129*af28f636SEnrico Perla - Sun Microsystems /*
130*af28f636SEnrico Perla - Sun Microsystems  * einfo_compare_version()
131*af28f636SEnrico Perla - Sun Microsystems  * Given two extended versions, compare the two and returns which one is more
132*af28f636SEnrico Perla - Sun Microsystems  * "recent". Comparison is based on dotted version number fields and a
133*af28f636SEnrico Perla - Sun Microsystems  * timestamp.
134*af28f636SEnrico Perla - Sun Microsystems  *
135*af28f636SEnrico Perla - Sun Microsystems  * Returns:    -1   - on error
136*af28f636SEnrico Perla - Sun Microsystems  *              0   - if the two versions coincide
137*af28f636SEnrico Perla - Sun Microsystems  *              1   - if the version in str1 is more recent
138*af28f636SEnrico Perla - Sun Microsystems  *              2   - if the version in str2 is more recent
139*af28f636SEnrico Perla - Sun Microsystems  */
140*af28f636SEnrico Perla - Sun Microsystems static int
einfo_compare_version(const char * str1,const char * str2)141*af28f636SEnrico Perla - Sun Microsystems einfo_compare_version(const char *str1, const char *str2)
142*af28f636SEnrico Perla - Sun Microsystems {
143*af28f636SEnrico Perla - Sun Microsystems 	int	retval = 0;
144*af28f636SEnrico Perla - Sun Microsystems 	char	*verstr1, *verstr2, *freeptr1, *freeptr2;
145*af28f636SEnrico Perla - Sun Microsystems 	char	*parsep1, *parsep2;
146*af28f636SEnrico Perla - Sun Microsystems 
147*af28f636SEnrico Perla - Sun Microsystems 	freeptr1 = verstr1 = strdup(str1);
148*af28f636SEnrico Perla - Sun Microsystems 	freeptr2 = verstr2 = strdup(str2);
149*af28f636SEnrico Perla - Sun Microsystems 	if (verstr1 == NULL || verstr2 == NULL) {
150*af28f636SEnrico Perla - Sun Microsystems 		retval = -1;
151*af28f636SEnrico Perla - Sun Microsystems 		goto out;
152*af28f636SEnrico Perla - Sun Microsystems 	}
153*af28f636SEnrico Perla - Sun Microsystems 
154*af28f636SEnrico Perla - Sun Microsystems 	parsep1 = verstr1;
155*af28f636SEnrico Perla - Sun Microsystems 	parsep2 = verstr2;
156*af28f636SEnrico Perla - Sun Microsystems 
157*af28f636SEnrico Perla - Sun Microsystems 	while (parsep1 != NULL && parsep2 != NULL) {
158*af28f636SEnrico Perla - Sun Microsystems 		parsep1 = strsep(&verstr1, ",:-");
159*af28f636SEnrico Perla - Sun Microsystems 		parsep2 = strsep(&verstr2, ",:-");
160*af28f636SEnrico Perla - Sun Microsystems 
161*af28f636SEnrico Perla - Sun Microsystems 		/* verstr1 or verstr2 will be NULL before parsep1 or parsep2. */
162*af28f636SEnrico Perla - Sun Microsystems 		if (verstr1 == NULL || verstr2 == NULL) {
163*af28f636SEnrico Perla - Sun Microsystems 			retval = einfo_compare_timestamps(parsep1, parsep2);
164*af28f636SEnrico Perla - Sun Microsystems 			goto out;
165*af28f636SEnrico Perla - Sun Microsystems 		}
166*af28f636SEnrico Perla - Sun Microsystems 
167*af28f636SEnrico Perla - Sun Microsystems 		retval = einfo_compare_dotted_version(parsep1, parsep2);
168*af28f636SEnrico Perla - Sun Microsystems 		if (retval == 0)
169*af28f636SEnrico Perla - Sun Microsystems 			continue;
170*af28f636SEnrico Perla - Sun Microsystems 		else
171*af28f636SEnrico Perla - Sun Microsystems 			goto out;
172*af28f636SEnrico Perla - Sun Microsystems 	}
173*af28f636SEnrico Perla - Sun Microsystems out:
174*af28f636SEnrico Perla - Sun Microsystems 	free(freeptr1);
175*af28f636SEnrico Perla - Sun Microsystems 	free(freeptr2);
176*af28f636SEnrico Perla - Sun Microsystems 	return (retval);
177*af28f636SEnrico Perla - Sun Microsystems }
178*af28f636SEnrico Perla - Sun Microsystems 
179*af28f636SEnrico Perla - Sun Microsystems /*
180*af28f636SEnrico Perla - Sun Microsystems  * print_einfo()
181*af28f636SEnrico Perla - Sun Microsystems  *
182*af28f636SEnrico Perla - Sun Microsystems  * Print the extended information contained into the pointed structure.
183*af28f636SEnrico Perla - Sun Microsystems  * 'bufsize' specifies the real size of the structure, since str_off and
184*af28f636SEnrico Perla - Sun Microsystems  * hash_off need to point somewhere past the header.
185*af28f636SEnrico Perla - Sun Microsystems  */
186*af28f636SEnrico Perla - Sun Microsystems void
print_einfo(uint8_t flags,bblk_einfo_t * einfo,unsigned long bufsize)187*af28f636SEnrico Perla - Sun Microsystems print_einfo(uint8_t flags, bblk_einfo_t *einfo, unsigned long bufsize)
188*af28f636SEnrico Perla - Sun Microsystems {
189*af28f636SEnrico Perla - Sun Microsystems 	int		i = 0;
190*af28f636SEnrico Perla - Sun Microsystems 	char		*version;
191*af28f636SEnrico Perla - Sun Microsystems 	boolean_t	has_hash = B_FALSE;
192*af28f636SEnrico Perla - Sun Microsystems 	unsigned char	*hash;
193*af28f636SEnrico Perla - Sun Microsystems 
194*af28f636SEnrico Perla - Sun Microsystems 	if (einfo->str_off + einfo->str_size > bufsize) {
195*af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stdout, gettext("String offset %d is beyond the "
196*af28f636SEnrico Perla - Sun Microsystems 		    "buffer size\n"), einfo->str_off);
197*af28f636SEnrico Perla - Sun Microsystems 		return;
198*af28f636SEnrico Perla - Sun Microsystems 	}
199*af28f636SEnrico Perla - Sun Microsystems 
200*af28f636SEnrico Perla - Sun Microsystems 	version = (char *)einfo + einfo->str_off;
201*af28f636SEnrico Perla - Sun Microsystems 	if (einfo->hash_type != BBLK_NO_HASH &&
202*af28f636SEnrico Perla - Sun Microsystems 	    einfo->hash_type < BBLK_HASH_TOT) {
203*af28f636SEnrico Perla - Sun Microsystems 		if (einfo->hash_off + einfo->hash_size > bufsize) {
204*af28f636SEnrico Perla - Sun Microsystems 			(void) fprintf(stdout, gettext("Warning: hashing "
205*af28f636SEnrico Perla - Sun Microsystems 			    "present but hash offset %d is beyond the buffer "
206*af28f636SEnrico Perla - Sun Microsystems 			    "size\n"), einfo->hash_off);
207*af28f636SEnrico Perla - Sun Microsystems 			has_hash = B_FALSE;
208*af28f636SEnrico Perla - Sun Microsystems 		} else {
209*af28f636SEnrico Perla - Sun Microsystems 			hash = (unsigned char *)einfo + einfo->hash_off;
210*af28f636SEnrico Perla - Sun Microsystems 			has_hash = B_TRUE;
211*af28f636SEnrico Perla - Sun Microsystems 		}
212*af28f636SEnrico Perla - Sun Microsystems 	}
213*af28f636SEnrico Perla - Sun Microsystems 
214*af28f636SEnrico Perla - Sun Microsystems 	if (flags & EINFO_PRINT_HEADER) {
215*af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stdout, "Boot Block Extended Info Header:\n");
216*af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stdout, "\tmagic: ");
217*af28f636SEnrico Perla - Sun Microsystems 		for (i = 0; i < EINFO_MAGIC_SIZE; i++)
218*af28f636SEnrico Perla - Sun Microsystems 			(void) fprintf(stdout, "%c", einfo->magic[i]);
219*af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stdout, "\n");
220*af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stdout, "\tversion: %d\n", einfo->version);
221*af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stdout, "\tflags: %x\n", einfo->flags);
222*af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stdout, "\textended version string offset: %d\n",
223*af28f636SEnrico Perla - Sun Microsystems 		    einfo->str_off);
224*af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stdout, "\textended version string size: %d\n",
225*af28f636SEnrico Perla - Sun Microsystems 		    einfo->str_size);
226*af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stdout, "\thashing type: %d (%s)\n",
227*af28f636SEnrico Perla - Sun Microsystems 		    einfo->hash_type, has_hash ?
228*af28f636SEnrico Perla - Sun Microsystems 		    bblk_hash_list[einfo->hash_type]->name : "nil");
229*af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stdout, "\thash offset: %d\n", einfo->hash_off);
230*af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stdout, "\thash size: %d\n", einfo->hash_size);
231*af28f636SEnrico Perla - Sun Microsystems 	}
232*af28f636SEnrico Perla - Sun Microsystems 
233*af28f636SEnrico Perla - Sun Microsystems 	if (flags & EINFO_EASY_PARSE) {
234*af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stdout, "%s\n", version);
235*af28f636SEnrico Perla - Sun Microsystems 	} else {
236*af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stdout, "Extended version string: %s\n",
237*af28f636SEnrico Perla - Sun Microsystems 		    version);
238*af28f636SEnrico Perla - Sun Microsystems 		if (has_hash) {
239*af28f636SEnrico Perla - Sun Microsystems 			(void) fprintf(stdout, "%s hash: ",
240*af28f636SEnrico Perla - Sun Microsystems 			    bblk_hash_list[einfo->hash_type]->name);
241*af28f636SEnrico Perla - Sun Microsystems 		} else {
242*af28f636SEnrico Perla - Sun Microsystems 			(void) fprintf(stdout, "No hashing available\n");
243*af28f636SEnrico Perla - Sun Microsystems 		}
244*af28f636SEnrico Perla - Sun Microsystems 	}
245*af28f636SEnrico Perla - Sun Microsystems 
246*af28f636SEnrico Perla - Sun Microsystems 	if (has_hash) {
247*af28f636SEnrico Perla - Sun Microsystems 		for (i = 0; i < einfo->hash_size; i++) {
248*af28f636SEnrico Perla - Sun Microsystems 			(void) fprintf(stdout, "%02x", hash[i]);
249*af28f636SEnrico Perla - Sun Microsystems 		}
250*af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stdout, "\n");
251*af28f636SEnrico Perla - Sun Microsystems 	}
252*af28f636SEnrico Perla - Sun Microsystems }
253*af28f636SEnrico Perla - Sun Microsystems 
254*af28f636SEnrico Perla - Sun Microsystems static int
compute_hash(bblk_hs_t * hs,unsigned char * dest,bblk_hash_t * hash)255*af28f636SEnrico Perla - Sun Microsystems compute_hash(bblk_hs_t *hs, unsigned char *dest, bblk_hash_t *hash)
256*af28f636SEnrico Perla - Sun Microsystems {
257*af28f636SEnrico Perla - Sun Microsystems 	if (hs == NULL || dest == NULL || hash == NULL)
258*af28f636SEnrico Perla - Sun Microsystems 		return (-1);
259*af28f636SEnrico Perla - Sun Microsystems 
260*af28f636SEnrico Perla - Sun Microsystems 	hash->compute_hash(dest, hs->src_buf, hs->src_size);
261*af28f636SEnrico Perla - Sun Microsystems 	return (0);
262*af28f636SEnrico Perla - Sun Microsystems }
263*af28f636SEnrico Perla - Sun Microsystems 
264*af28f636SEnrico Perla - Sun Microsystems int
prepare_and_write_einfo(unsigned char * dest,char * infostr,bblk_hs_t * hs,uint32_t maxsize,uint32_t * used_space)265*af28f636SEnrico Perla - Sun Microsystems prepare_and_write_einfo(unsigned char *dest, char *infostr, bblk_hs_t *hs,
266*af28f636SEnrico Perla - Sun Microsystems     uint32_t maxsize, uint32_t *used_space)
267*af28f636SEnrico Perla - Sun Microsystems {
268*af28f636SEnrico Perla - Sun Microsystems 	uint16_t	hash_size;
269*af28f636SEnrico Perla - Sun Microsystems 	uint32_t	hash_off;
270*af28f636SEnrico Perla - Sun Microsystems 	unsigned char	*data;
271*af28f636SEnrico Perla - Sun Microsystems 	bblk_einfo_t	*einfo = (bblk_einfo_t *)dest;
272*af28f636SEnrico Perla - Sun Microsystems 	bblk_hash_t	*hashinfo = bblk_hash_list[BBLK_DEFAULT_HASH];
273*af28f636SEnrico Perla - Sun Microsystems 
274*af28f636SEnrico Perla - Sun Microsystems 	/*
275*af28f636SEnrico Perla - Sun Microsystems 	 * 'dest' might be both containing the buffer we want to hash and
276*af28f636SEnrico Perla - Sun Microsystems 	 * containing our einfo structure: delay any update of it after the
277*af28f636SEnrico Perla - Sun Microsystems 	 * hashing has been calculated.
278*af28f636SEnrico Perla - Sun Microsystems 	 */
279*af28f636SEnrico Perla - Sun Microsystems 	hash_size = hashinfo->size;
280*af28f636SEnrico Perla - Sun Microsystems 	hash_off = sizeof (bblk_einfo_t);
281*af28f636SEnrico Perla - Sun Microsystems 
282*af28f636SEnrico Perla - Sun Microsystems 	if (hash_off + hash_size > maxsize) {
283*af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("Unable to add extended info, "
284*af28f636SEnrico Perla - Sun Microsystems 		    "not enough space\n"));
285*af28f636SEnrico Perla - Sun Microsystems 		return (-1);
286*af28f636SEnrico Perla - Sun Microsystems 	}
287*af28f636SEnrico Perla - Sun Microsystems 
288*af28f636SEnrico Perla - Sun Microsystems 	data = dest + hash_off;
289*af28f636SEnrico Perla - Sun Microsystems 	if (compute_hash(hs, data, hashinfo) < 0) {
290*af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("%s hash operation failed\n"),
291*af28f636SEnrico Perla - Sun Microsystems 		    hashinfo->name);
292*af28f636SEnrico Perla - Sun Microsystems 		einfo->hash_type = bblk_no_hash.type;
293*af28f636SEnrico Perla - Sun Microsystems 		einfo->hash_size = bblk_no_hash.size;
294*af28f636SEnrico Perla - Sun Microsystems 	} else {
295*af28f636SEnrico Perla - Sun Microsystems 		einfo->hash_type = hashinfo->type;
296*af28f636SEnrico Perla - Sun Microsystems 		einfo->hash_size = hashinfo->size;
297*af28f636SEnrico Perla - Sun Microsystems 	}
298*af28f636SEnrico Perla - Sun Microsystems 
299*af28f636SEnrico Perla - Sun Microsystems 	(void) memcpy(einfo->magic, EINFO_MAGIC, EINFO_MAGIC_SIZE);
300*af28f636SEnrico Perla - Sun Microsystems 	einfo->version = BBLK_EINFO_VERSION;
301*af28f636SEnrico Perla - Sun Microsystems 	einfo->flags = 0;
302*af28f636SEnrico Perla - Sun Microsystems 	einfo->hash_off = hash_off;
303*af28f636SEnrico Perla - Sun Microsystems 	einfo->hash_size = hash_size;
304*af28f636SEnrico Perla - Sun Microsystems 	einfo->str_off = einfo->hash_off + einfo->hash_size + 1;
305*af28f636SEnrico Perla - Sun Microsystems 
306*af28f636SEnrico Perla - Sun Microsystems 	if (infostr == NULL) {
307*af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("Unable to add extended info, "
308*af28f636SEnrico Perla - Sun Microsystems 		    "string is empty\n"));
309*af28f636SEnrico Perla - Sun Microsystems 		return (-1);
310*af28f636SEnrico Perla - Sun Microsystems 	}
311*af28f636SEnrico Perla - Sun Microsystems 	einfo->str_size = strlen(infostr);
312*af28f636SEnrico Perla - Sun Microsystems 
313*af28f636SEnrico Perla - Sun Microsystems 	if (einfo->str_off + einfo->str_size > maxsize) {
314*af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("Unable to add extended info, "
315*af28f636SEnrico Perla - Sun Microsystems 		    "not enough space\n"));
316*af28f636SEnrico Perla - Sun Microsystems 		return (-1);
317*af28f636SEnrico Perla - Sun Microsystems 	}
318*af28f636SEnrico Perla - Sun Microsystems 
319*af28f636SEnrico Perla - Sun Microsystems 	data = dest + einfo->str_off;
320*af28f636SEnrico Perla - Sun Microsystems 	(void) memcpy(data, infostr, einfo->str_size);
321*af28f636SEnrico Perla - Sun Microsystems 	*used_space = einfo->str_off + einfo->str_size;
322*af28f636SEnrico Perla - Sun Microsystems 
323*af28f636SEnrico Perla - Sun Microsystems 	return (0);
324*af28f636SEnrico Perla - Sun Microsystems }
325*af28f636SEnrico Perla - Sun Microsystems 
326*af28f636SEnrico Perla - Sun Microsystems /*
327*af28f636SEnrico Perla - Sun Microsystems  * einfo_should_update()
328*af28f636SEnrico Perla - Sun Microsystems  * Given information on the boot block currently on disk (disk_einfo) and
329*af28f636SEnrico Perla - Sun Microsystems  * information on the supplied boot block (hs for hashing, verstr as the
330*af28f636SEnrico Perla - Sun Microsystems  * associated version string) decide if an update of the on-disk boot block
331*af28f636SEnrico Perla - Sun Microsystems  * is necessary or not.
332*af28f636SEnrico Perla - Sun Microsystems  */
333*af28f636SEnrico Perla - Sun Microsystems boolean_t
einfo_should_update(bblk_einfo_t * disk_einfo,bblk_hs_t * hs,char * verstr)334*af28f636SEnrico Perla - Sun Microsystems einfo_should_update(bblk_einfo_t *disk_einfo, bblk_hs_t *hs, char *verstr)
335*af28f636SEnrico Perla - Sun Microsystems {
336*af28f636SEnrico Perla - Sun Microsystems 	bblk_hash_t	*hashing;
337*af28f636SEnrico Perla - Sun Microsystems 	unsigned char	*disk_hash;
338*af28f636SEnrico Perla - Sun Microsystems 	unsigned char	*local_hash;
339*af28f636SEnrico Perla - Sun Microsystems 	char		*disk_version;
340*af28f636SEnrico Perla - Sun Microsystems 	int		retval;
341*af28f636SEnrico Perla - Sun Microsystems 
342*af28f636SEnrico Perla - Sun Microsystems 	if (disk_einfo == NULL)
343*af28f636SEnrico Perla - Sun Microsystems 		return (B_TRUE);
344*af28f636SEnrico Perla - Sun Microsystems 
345*af28f636SEnrico Perla - Sun Microsystems 	if (memcmp(disk_einfo->magic, EINFO_MAGIC, EINFO_MAGIC_SIZE) != 0)
346*af28f636SEnrico Perla - Sun Microsystems 		return (B_TRUE);
347*af28f636SEnrico Perla - Sun Microsystems 
348*af28f636SEnrico Perla - Sun Microsystems 	if (disk_einfo->version < BBLK_EINFO_VERSION)
349*af28f636SEnrico Perla - Sun Microsystems 		return (B_TRUE);
350*af28f636SEnrico Perla - Sun Microsystems 
351*af28f636SEnrico Perla - Sun Microsystems 	disk_version = einfo_get_string(disk_einfo);
352*af28f636SEnrico Perla - Sun Microsystems 	retval = einfo_compare_version(verstr, disk_version);
353*af28f636SEnrico Perla - Sun Microsystems 	/*
354*af28f636SEnrico Perla - Sun Microsystems 	 * If something goes wrong or if the on-disk version is more recent
355*af28f636SEnrico Perla - Sun Microsystems 	 * do not update the bootblock.
356*af28f636SEnrico Perla - Sun Microsystems 	 */
357*af28f636SEnrico Perla - Sun Microsystems 	if (retval == -1 || retval == 2)
358*af28f636SEnrico Perla - Sun Microsystems 		return (B_FALSE);
359*af28f636SEnrico Perla - Sun Microsystems 
360*af28f636SEnrico Perla - Sun Microsystems 	/*
361*af28f636SEnrico Perla - Sun Microsystems 	 * If we got here it means that the two version strings are either
362*af28f636SEnrico Perla - Sun Microsystems 	 * equal or the new bootblk binary is more recent. In order to save
363*af28f636SEnrico Perla - Sun Microsystems 	 * some needless writes let's use the hash to determine if an update
364*af28f636SEnrico Perla - Sun Microsystems 	 * is really necessary.
365*af28f636SEnrico Perla - Sun Microsystems 	 */
366*af28f636SEnrico Perla - Sun Microsystems 	if (disk_einfo->hash_type == bblk_no_hash.type)
367*af28f636SEnrico Perla - Sun Microsystems 		return (B_TRUE);
368*af28f636SEnrico Perla - Sun Microsystems 
369*af28f636SEnrico Perla - Sun Microsystems 	if (disk_einfo->hash_type >= BBLK_HASH_TOT)
370*af28f636SEnrico Perla - Sun Microsystems 		return (B_TRUE);
371*af28f636SEnrico Perla - Sun Microsystems 
372*af28f636SEnrico Perla - Sun Microsystems 	hashing = bblk_hash_list[disk_einfo->hash_type];
373*af28f636SEnrico Perla - Sun Microsystems 
374*af28f636SEnrico Perla - Sun Microsystems 	local_hash = malloc(hashing->size);
375*af28f636SEnrico Perla - Sun Microsystems 	if (local_hash == NULL)
376*af28f636SEnrico Perla - Sun Microsystems 		return (B_TRUE);
377*af28f636SEnrico Perla - Sun Microsystems 
378*af28f636SEnrico Perla - Sun Microsystems 	/*
379*af28f636SEnrico Perla - Sun Microsystems 	 * Failure in computing the hash may mean something wrong
380*af28f636SEnrico Perla - Sun Microsystems 	 * with the boot block file. Better be conservative here.
381*af28f636SEnrico Perla - Sun Microsystems 	 */
382*af28f636SEnrico Perla - Sun Microsystems 	if (compute_hash(hs, local_hash, hashing) < 0) {
383*af28f636SEnrico Perla - Sun Microsystems 		free(local_hash);
384*af28f636SEnrico Perla - Sun Microsystems 		return (B_FALSE);
385*af28f636SEnrico Perla - Sun Microsystems 	}
386*af28f636SEnrico Perla - Sun Microsystems 
387*af28f636SEnrico Perla - Sun Microsystems 	disk_hash = (unsigned char *)einfo_get_hash(disk_einfo);
388*af28f636SEnrico Perla - Sun Microsystems 
389*af28f636SEnrico Perla - Sun Microsystems 	if (memcmp(local_hash, disk_hash, disk_einfo->hash_size) == 0) {
390*af28f636SEnrico Perla - Sun Microsystems 		free(local_hash);
391*af28f636SEnrico Perla - Sun Microsystems 		return (B_FALSE);
392*af28f636SEnrico Perla - Sun Microsystems 	}
393*af28f636SEnrico Perla - Sun Microsystems 
394*af28f636SEnrico Perla - Sun Microsystems 	free(local_hash);
395*af28f636SEnrico Perla - Sun Microsystems 	return (B_TRUE);
396*af28f636SEnrico Perla - Sun Microsystems }
397*af28f636SEnrico Perla - Sun Microsystems 
398*af28f636SEnrico Perla - Sun Microsystems char *
einfo_get_string(bblk_einfo_t * einfo)399*af28f636SEnrico Perla - Sun Microsystems einfo_get_string(bblk_einfo_t *einfo)
400*af28f636SEnrico Perla - Sun Microsystems {
401*af28f636SEnrico Perla - Sun Microsystems 	if (einfo == NULL)
402*af28f636SEnrico Perla - Sun Microsystems 		return (NULL);
403*af28f636SEnrico Perla - Sun Microsystems 
404*af28f636SEnrico Perla - Sun Microsystems 	return ((char *)einfo + einfo->str_off);
405*af28f636SEnrico Perla - Sun Microsystems }
406*af28f636SEnrico Perla - Sun Microsystems 
407*af28f636SEnrico Perla - Sun Microsystems char *
einfo_get_hash(bblk_einfo_t * einfo)408*af28f636SEnrico Perla - Sun Microsystems einfo_get_hash(bblk_einfo_t *einfo)
409*af28f636SEnrico Perla - Sun Microsystems {
410*af28f636SEnrico Perla - Sun Microsystems 	if (einfo == NULL)
411*af28f636SEnrico Perla - Sun Microsystems 		return (NULL);
412*af28f636SEnrico Perla - Sun Microsystems 
413*af28f636SEnrico Perla - Sun Microsystems 	return ((char *)einfo + einfo->hash_off);
414*af28f636SEnrico Perla - Sun Microsystems }
415