xref: /minix3/usr.sbin/installboot/arch/amiga.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc /*	$NetBSD: amiga.c,v 1.9 2015/06/05 05:02:48 mlelstv Exp $	*/
29f8e6353SEvgeniy Ivanov 
39f8e6353SEvgeniy Ivanov /*-
49f8e6353SEvgeniy Ivanov  * Copyright (c) 1999, 2002 The NetBSD Foundation, Inc.
59f8e6353SEvgeniy Ivanov  * All rights reserved.
69f8e6353SEvgeniy Ivanov  *
79f8e6353SEvgeniy Ivanov  * This code is derived from software contributed to The NetBSD Foundation
89f8e6353SEvgeniy Ivanov  * by Michael Hitch.
99f8e6353SEvgeniy Ivanov  *
109f8e6353SEvgeniy Ivanov  * This code is derived from software contributed to The NetBSD Foundation
119f8e6353SEvgeniy Ivanov  * by Luke Mewburn of Wasabi Systems.
129f8e6353SEvgeniy Ivanov  *
139f8e6353SEvgeniy Ivanov  * Redistribution and use in source and binary forms, with or without
149f8e6353SEvgeniy Ivanov  * modification, are permitted provided that the following conditions
159f8e6353SEvgeniy Ivanov  * are met:
169f8e6353SEvgeniy Ivanov  * 1. Redistributions of source code must retain the above copyright
179f8e6353SEvgeniy Ivanov  *    notice, this list of conditions and the following disclaimer.
189f8e6353SEvgeniy Ivanov  * 2. Redistributions in binary form must reproduce the above copyright
199f8e6353SEvgeniy Ivanov  *    notice, this list of conditions and the following disclaimer in the
209f8e6353SEvgeniy Ivanov  *    documentation and/or other materials provided with the distribution.
219f8e6353SEvgeniy Ivanov  *
229f8e6353SEvgeniy Ivanov  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
239f8e6353SEvgeniy Ivanov  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
249f8e6353SEvgeniy Ivanov  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
259f8e6353SEvgeniy Ivanov  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
269f8e6353SEvgeniy Ivanov  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
279f8e6353SEvgeniy Ivanov  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
289f8e6353SEvgeniy Ivanov  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
299f8e6353SEvgeniy Ivanov  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
309f8e6353SEvgeniy Ivanov  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
319f8e6353SEvgeniy Ivanov  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
329f8e6353SEvgeniy Ivanov  * POSSIBILITY OF SUCH DAMAGE.
339f8e6353SEvgeniy Ivanov  */
349f8e6353SEvgeniy Ivanov 
359f8e6353SEvgeniy Ivanov #if HAVE_NBTOOL_CONFIG_H
369f8e6353SEvgeniy Ivanov #include "nbtool_config.h"
379f8e6353SEvgeniy Ivanov #endif
389f8e6353SEvgeniy Ivanov 
399f8e6353SEvgeniy Ivanov #include <sys/cdefs.h>
409f8e6353SEvgeniy Ivanov #if !defined(__lint)
41*0a6a1f1dSLionel Sambuc __RCSID("$NetBSD: amiga.c,v 1.9 2015/06/05 05:02:48 mlelstv Exp $");
429f8e6353SEvgeniy Ivanov #endif	/* !__lint */
439f8e6353SEvgeniy Ivanov 
449f8e6353SEvgeniy Ivanov #include <sys/param.h>
459f8e6353SEvgeniy Ivanov #include <sys/stat.h>
469f8e6353SEvgeniy Ivanov 
479f8e6353SEvgeniy Ivanov #include <assert.h>
489f8e6353SEvgeniy Ivanov #include <err.h>
499f8e6353SEvgeniy Ivanov #include <stddef.h>
509f8e6353SEvgeniy Ivanov #include <stdio.h>
519f8e6353SEvgeniy Ivanov #include <stdlib.h>
529f8e6353SEvgeniy Ivanov #include <unistd.h>
539f8e6353SEvgeniy Ivanov #include <string.h>
549f8e6353SEvgeniy Ivanov 
559f8e6353SEvgeniy Ivanov #include "installboot.h"
569f8e6353SEvgeniy Ivanov 
579f8e6353SEvgeniy Ivanov /* XXX Must be kept in sync with bbstart.s! */
589f8e6353SEvgeniy Ivanov #define CMDLN_LOC 0x10
599f8e6353SEvgeniy Ivanov #define CMDLN_LEN 0x20
609f8e6353SEvgeniy Ivanov 
619f8e6353SEvgeniy Ivanov #define CHKSUMOFFS 1
629f8e6353SEvgeniy Ivanov 
639f8e6353SEvgeniy Ivanov u_int32_t chksum(u_int32_t *, int);
649f8e6353SEvgeniy Ivanov 
659f8e6353SEvgeniy Ivanov static int amiga_setboot(ib_params *);
669f8e6353SEvgeniy Ivanov 
679f8e6353SEvgeniy Ivanov struct ib_mach ib_mach_amiga =
689f8e6353SEvgeniy Ivanov 	{ "amiga", amiga_setboot, no_clearboot, no_editboot,
699f8e6353SEvgeniy Ivanov 		IB_STAGE1START | IB_STAGE2START | IB_COMMAND };
709f8e6353SEvgeniy Ivanov 
719f8e6353SEvgeniy Ivanov static int
amiga_setboot(ib_params * params)729f8e6353SEvgeniy Ivanov amiga_setboot(ib_params *params)
739f8e6353SEvgeniy Ivanov {
749f8e6353SEvgeniy Ivanov 	int retval;
759f8e6353SEvgeniy Ivanov 	ssize_t			rv;
769f8e6353SEvgeniy Ivanov 	char *dline;
779f8e6353SEvgeniy Ivanov 	int sumlen;
789f8e6353SEvgeniy Ivanov 	u_int32_t sum2, sum16;
799f8e6353SEvgeniy Ivanov 
809f8e6353SEvgeniy Ivanov 	struct stat		bootstrapsb;
819f8e6353SEvgeniy Ivanov 
829f8e6353SEvgeniy Ivanov 	u_int32_t block[128*16];
839f8e6353SEvgeniy Ivanov 
849f8e6353SEvgeniy Ivanov 	retval = 0;
859f8e6353SEvgeniy Ivanov 	if (fstat(params->s1fd, &bootstrapsb) == -1) {
869f8e6353SEvgeniy Ivanov 		warn("Examining `%s'", params->stage1);
879f8e6353SEvgeniy Ivanov 		goto done;
889f8e6353SEvgeniy Ivanov 	}
899f8e6353SEvgeniy Ivanov 	if (!S_ISREG(bootstrapsb.st_mode)) {
909f8e6353SEvgeniy Ivanov 		warnx("`%s' must be a regular file", params->stage1);
919f8e6353SEvgeniy Ivanov 		goto done;
929f8e6353SEvgeniy Ivanov 	}
939f8e6353SEvgeniy Ivanov 
949f8e6353SEvgeniy Ivanov 	rv = pread(params->s1fd, &block, sizeof(block), 0);
959f8e6353SEvgeniy Ivanov 	if (rv == -1) {
969f8e6353SEvgeniy Ivanov 		warn("Reading `%s'", params->stage1);
979f8e6353SEvgeniy Ivanov 		goto done;
989f8e6353SEvgeniy Ivanov 	} else if (rv != sizeof(block)) {
999f8e6353SEvgeniy Ivanov 		warnx("Reading `%s': short read", params->stage1);
1009f8e6353SEvgeniy Ivanov 		goto done;
1019f8e6353SEvgeniy Ivanov 	}
1029f8e6353SEvgeniy Ivanov 
1039f8e6353SEvgeniy Ivanov 	/* XXX the choices should not be hardcoded */
1049f8e6353SEvgeniy Ivanov 
1059f8e6353SEvgeniy Ivanov 	sum2  = chksum(block, 1024/4);
1069f8e6353SEvgeniy Ivanov 	sum16 = chksum(block, 8192/4);
1079f8e6353SEvgeniy Ivanov 
1089f8e6353SEvgeniy Ivanov 	if (sum16 == 0xffffffff) {
1099f8e6353SEvgeniy Ivanov 		sumlen = 8192/4;
1109f8e6353SEvgeniy Ivanov 	} else if (sum2 == 0xffffffff) {
1119f8e6353SEvgeniy Ivanov 		sumlen = 1024/4;
1129f8e6353SEvgeniy Ivanov 	} else {
1139f8e6353SEvgeniy Ivanov 		errx(1, "%s: wrong checksum", params->stage1);
1149f8e6353SEvgeniy Ivanov 		/* NOTREACHED */
1159f8e6353SEvgeniy Ivanov 	}
1169f8e6353SEvgeniy Ivanov 
1179f8e6353SEvgeniy Ivanov 	if (sum2 == sum16) {
1189f8e6353SEvgeniy Ivanov 		warnx("eek - both sums are the same");
1199f8e6353SEvgeniy Ivanov 	}
1209f8e6353SEvgeniy Ivanov 
1219f8e6353SEvgeniy Ivanov 	if (params->flags & IB_COMMAND) {
1229f8e6353SEvgeniy Ivanov 		dline = (char *)&(block[CMDLN_LOC/4]);
1239f8e6353SEvgeniy Ivanov 		/* XXX keep the default default line in sync with bbstart.s */
1249f8e6353SEvgeniy Ivanov 		if (strcmp(dline, "netbsd -ASn2") != 0) {
1259f8e6353SEvgeniy Ivanov 			errx(1, "Old bootblock version? Can't change command line.");
1269f8e6353SEvgeniy Ivanov 		}
1279f8e6353SEvgeniy Ivanov 		(void)strncpy(dline, params->command, CMDLN_LEN-1);
1289f8e6353SEvgeniy Ivanov 
129*0a6a1f1dSLionel Sambuc 		block[1] = htobe32(0);
130*0a6a1f1dSLionel Sambuc 		block[1] = htobe32(0xffffffff - chksum(block, sumlen));
1319f8e6353SEvgeniy Ivanov 	}
1329f8e6353SEvgeniy Ivanov 
1339f8e6353SEvgeniy Ivanov 	if (params->flags & IB_NOWRITE) {
1349f8e6353SEvgeniy Ivanov 		retval = 1;
1359f8e6353SEvgeniy Ivanov 		goto done;
1369f8e6353SEvgeniy Ivanov 	}
1379f8e6353SEvgeniy Ivanov 
1389f8e6353SEvgeniy Ivanov 	if (params->flags & IB_VERBOSE)
1399f8e6353SEvgeniy Ivanov 		printf("Writing boot block\n");
1409f8e6353SEvgeniy Ivanov 	rv = pwrite(params->fsfd, &block, sizeof(block), 0);
1419f8e6353SEvgeniy Ivanov 	if (rv == -1) {
1429f8e6353SEvgeniy Ivanov 		warn("Writing `%s'", params->filesystem);
1439f8e6353SEvgeniy Ivanov 		goto done;
1449f8e6353SEvgeniy Ivanov 	} else if (rv != sizeof(block)) {
1459f8e6353SEvgeniy Ivanov 		warnx("Writing `%s': short write", params->filesystem);
1469f8e6353SEvgeniy Ivanov 		goto done;
1479f8e6353SEvgeniy Ivanov 	} else {
1489f8e6353SEvgeniy Ivanov 		retval = 1;
1499f8e6353SEvgeniy Ivanov 	}
1509f8e6353SEvgeniy Ivanov 
1519f8e6353SEvgeniy Ivanov  done:
1529f8e6353SEvgeniy Ivanov 	return (retval);
1539f8e6353SEvgeniy Ivanov }
1549f8e6353SEvgeniy Ivanov 
1559f8e6353SEvgeniy Ivanov u_int32_t
chksum(block,size)1569f8e6353SEvgeniy Ivanov chksum(block, size)
1579f8e6353SEvgeniy Ivanov 	u_int32_t *block;
1589f8e6353SEvgeniy Ivanov 	int size;
1599f8e6353SEvgeniy Ivanov {
1609f8e6353SEvgeniy Ivanov 	u_int32_t sum, lastsum;
1619f8e6353SEvgeniy Ivanov 	int i;
1629f8e6353SEvgeniy Ivanov 
1639f8e6353SEvgeniy Ivanov 	sum = 0;
1649f8e6353SEvgeniy Ivanov 
1659f8e6353SEvgeniy Ivanov 	for (i=0; i<size; i++) {
1669f8e6353SEvgeniy Ivanov 		lastsum = sum;
167*0a6a1f1dSLionel Sambuc 		sum += be32toh(block[i]);
1689f8e6353SEvgeniy Ivanov 		if (sum < lastsum)
1699f8e6353SEvgeniy Ivanov 			++sum;
1709f8e6353SEvgeniy Ivanov 	}
1719f8e6353SEvgeniy Ivanov 
1729f8e6353SEvgeniy Ivanov 	return sum;
1739f8e6353SEvgeniy Ivanov }
174