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