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