xref: /netbsd-src/usr.sbin/installboot/arch/hppa.c (revision e5c09b191b3a14e8b4648a699077b773caf1ed9b)
1*e5c09b19Sthorpej /*	$NetBSD: hppa.c,v 1.2 2019/05/07 04:35:31 thorpej Exp $	*/
26d3ceb1dSskrll 
36d3ceb1dSskrll /*-
46d3ceb1dSskrll  * Copyright (c) 2002 The NetBSD Foundation, Inc.
56d3ceb1dSskrll  * All rights reserved.
66d3ceb1dSskrll  *
76d3ceb1dSskrll  * This code is derived from software contributed to The NetBSD Foundation
86d3ceb1dSskrll  * by Luke Mewburn of Wasabi Systems.
96d3ceb1dSskrll  *
106d3ceb1dSskrll  * Redistribution and use in source and binary forms, with or without
116d3ceb1dSskrll  * modification, are permitted provided that the following conditions
126d3ceb1dSskrll  * are met:
136d3ceb1dSskrll  * 1. Redistributions of source code must retain the above copyright
146d3ceb1dSskrll  *    notice, this list of conditions and the following disclaimer.
156d3ceb1dSskrll  * 2. Redistributions in binary form must reproduce the above copyright
166d3ceb1dSskrll  *    notice, this list of conditions and the following disclaimer in the
176d3ceb1dSskrll  *    documentation and/or other materials provided with the distribution.
186d3ceb1dSskrll  *
196d3ceb1dSskrll  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
206d3ceb1dSskrll  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
216d3ceb1dSskrll  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
226d3ceb1dSskrll  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
236d3ceb1dSskrll  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
246d3ceb1dSskrll  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
256d3ceb1dSskrll  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
266d3ceb1dSskrll  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
276d3ceb1dSskrll  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
286d3ceb1dSskrll  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
296d3ceb1dSskrll  * POSSIBILITY OF SUCH DAMAGE.
306d3ceb1dSskrll  */
316d3ceb1dSskrll 
326d3ceb1dSskrll #if HAVE_NBTOOL_CONFIG_H
336d3ceb1dSskrll #include "nbtool_config.h"
346d3ceb1dSskrll #endif
356d3ceb1dSskrll 
366d3ceb1dSskrll #include <sys/cdefs.h>
376d3ceb1dSskrll #if !defined(__lint)
38*e5c09b19Sthorpej __RCSID("$NetBSD: hppa.c,v 1.2 2019/05/07 04:35:31 thorpej Exp $");
396d3ceb1dSskrll #endif	/* !__lint */
406d3ceb1dSskrll 
416d3ceb1dSskrll /* We need the target disklabel.h, not the hosts one..... */
426d3ceb1dSskrll #ifdef HAVE_NBTOOL_CONFIG_H
436d3ceb1dSskrll #include "nbtool_config.h"
446d3ceb1dSskrll #include <nbinclude/sys/disklabel.h>
456d3ceb1dSskrll #else
466d3ceb1dSskrll #include <sys/disklabel.h>
476d3ceb1dSskrll #endif
486d3ceb1dSskrll #include <sys/param.h>
496d3ceb1dSskrll #include <sys/stat.h>
506d3ceb1dSskrll 
516d3ceb1dSskrll #include <assert.h>
526d3ceb1dSskrll #include <err.h>
536d3ceb1dSskrll #include <stddef.h>
546d3ceb1dSskrll #include <stdio.h>
556d3ceb1dSskrll #include <stdlib.h>
566d3ceb1dSskrll #include <string.h>
576d3ceb1dSskrll #include <unistd.h>
586d3ceb1dSskrll 
596d3ceb1dSskrll #include "installboot.h"
606d3ceb1dSskrll 
616d3ceb1dSskrll #define HPPA_LABELOFFSET	512
626d3ceb1dSskrll #define HPPA_LABELSIZE		404 /* reserve 16 partitions */
636d3ceb1dSskrll #define	HPPA_BOOT_BLOCK_SIZE	8192
646d3ceb1dSskrll 
656d3ceb1dSskrll static int hppa_clearboot(ib_params *);
666d3ceb1dSskrll static int hppa_setboot(ib_params *);
676d3ceb1dSskrll 
68*e5c09b19Sthorpej struct ib_mach ib_mach_hppa = {
69*e5c09b19Sthorpej 	.name		=	"hppa",
70*e5c09b19Sthorpej 	.setboot	=	hppa_setboot,
71*e5c09b19Sthorpej 	.clearboot	=	hppa_clearboot,
72*e5c09b19Sthorpej 	.editboot	=	no_editboot,
73*e5c09b19Sthorpej };
746d3ceb1dSskrll 
756d3ceb1dSskrll static int
hppa_clearboot(ib_params * params)766d3ceb1dSskrll hppa_clearboot(ib_params *params)
776d3ceb1dSskrll {
786d3ceb1dSskrll 	char		bb[HPPA_BOOT_BLOCK_SIZE];
796d3ceb1dSskrll 	int		retval, eol;
806d3ceb1dSskrll 	ssize_t		rv;
816d3ceb1dSskrll 
826d3ceb1dSskrll 	assert(params != NULL);
836d3ceb1dSskrll 	assert(params->fsfd != -1);
846d3ceb1dSskrll 	assert(params->filesystem != NULL);
856d3ceb1dSskrll 
866d3ceb1dSskrll 	retval = 0;
876d3ceb1dSskrll 
886d3ceb1dSskrll 	/* read disklabel on the target disk */
896d3ceb1dSskrll 	rv = pread(params->fsfd, bb, sizeof bb, 0);
906d3ceb1dSskrll 	if (rv == -1) {
916d3ceb1dSskrll 		warn("Reading `%s'", params->filesystem);
926d3ceb1dSskrll 		goto done;
936d3ceb1dSskrll 	} else if (rv != sizeof bb) {
946d3ceb1dSskrll 		warnx("Reading `%s': short read", params->filesystem);
956d3ceb1dSskrll 		goto done;
966d3ceb1dSskrll 	}
976d3ceb1dSskrll 
986d3ceb1dSskrll 	/* clear header */
996d3ceb1dSskrll 	memset(bb, 0, HPPA_LABELOFFSET);
1006d3ceb1dSskrll 	eol = HPPA_LABELOFFSET + HPPA_LABELSIZE;
1016d3ceb1dSskrll 	memset(&bb[eol], 0, sizeof bb - eol);
1026d3ceb1dSskrll 
1036d3ceb1dSskrll 	if (params->flags & IB_VERBOSE) {
1046d3ceb1dSskrll 		printf("%slearing bootstrap\n",
1056d3ceb1dSskrll 		    (params->flags & IB_NOWRITE) ? "Not c" : "C");
1066d3ceb1dSskrll 	}
1076d3ceb1dSskrll 	if (params->flags & IB_NOWRITE) {
1086d3ceb1dSskrll 		retval = 1;
1096d3ceb1dSskrll 		goto done;
1106d3ceb1dSskrll 	}
1116d3ceb1dSskrll 
1126d3ceb1dSskrll 	rv = pwrite(params->fsfd, bb, sizeof bb, 0);
1136d3ceb1dSskrll 	if (rv == -1) {
1146d3ceb1dSskrll 		warn("Writing `%s'", params->filesystem);
1156d3ceb1dSskrll 		goto done;
1166d3ceb1dSskrll 	} else if (rv != HPPA_BOOT_BLOCK_SIZE) {
1176d3ceb1dSskrll 		warnx("Writing `%s': short write", params->filesystem);
1186d3ceb1dSskrll 		goto done;
1196d3ceb1dSskrll 	} else
1206d3ceb1dSskrll 		retval = 1;
1216d3ceb1dSskrll 
1226d3ceb1dSskrll  done:
1236d3ceb1dSskrll 	return (retval);
1246d3ceb1dSskrll }
1256d3ceb1dSskrll 
1266d3ceb1dSskrll static int
hppa_setboot(ib_params * params)1276d3ceb1dSskrll hppa_setboot(ib_params *params)
1286d3ceb1dSskrll {
1296d3ceb1dSskrll 	struct stat	bootstrapsb;
1306d3ceb1dSskrll 	char		bb[HPPA_BOOT_BLOCK_SIZE];
1316d3ceb1dSskrll 	struct {
1326d3ceb1dSskrll 		char	l_off[HPPA_LABELOFFSET];
1336d3ceb1dSskrll 		struct disklabel l;
1346d3ceb1dSskrll 		char	l_pad[HPPA_BOOT_BLOCK_SIZE
1356d3ceb1dSskrll 			    - HPPA_LABELOFFSET - sizeof(struct disklabel)];
1366d3ceb1dSskrll 	} label;
1376d3ceb1dSskrll 	unsigned int	secsize, npart;
1386d3ceb1dSskrll 	int		retval;
1396d3ceb1dSskrll 	ssize_t		rv;
1406d3ceb1dSskrll 
1416d3ceb1dSskrll 	assert(params != NULL);
1426d3ceb1dSskrll 	assert(params->fsfd != -1);
1436d3ceb1dSskrll 	assert(params->filesystem != NULL);
1446d3ceb1dSskrll 	assert(params->s1fd != -1);
1456d3ceb1dSskrll 	assert(params->stage1 != NULL);
1466d3ceb1dSskrll 
1476d3ceb1dSskrll 	retval = 0;
1486d3ceb1dSskrll 
1496d3ceb1dSskrll 	/* read disklabel on the target disk */
1506d3ceb1dSskrll 	rv = pread(params->fsfd, &label, HPPA_BOOT_BLOCK_SIZE, 0);
1516d3ceb1dSskrll 	if (rv == -1) {
1526d3ceb1dSskrll 		warn("Reading `%s'", params->filesystem);
1536d3ceb1dSskrll 		goto done;
1546d3ceb1dSskrll 	} else if (rv != HPPA_BOOT_BLOCK_SIZE) {
1556d3ceb1dSskrll 		warnx("Reading `%s': short read", params->filesystem);
1566d3ceb1dSskrll 		goto done;
1576d3ceb1dSskrll 	}
1586d3ceb1dSskrll 
1596d3ceb1dSskrll 	if (fstat(params->s1fd, &bootstrapsb) == -1) {
1606d3ceb1dSskrll 		warn("Examining `%s'", params->stage1);
1616d3ceb1dSskrll 		goto done;
1626d3ceb1dSskrll 	}
1636d3ceb1dSskrll 	if (!S_ISREG(bootstrapsb.st_mode)) {
1646d3ceb1dSskrll 		warnx("`%s' must be a regular file", params->stage1);
1656d3ceb1dSskrll 		goto done;
1666d3ceb1dSskrll 	}
1676d3ceb1dSskrll 
1686d3ceb1dSskrll 	/* check if valid disklabel exists */
1696d3ceb1dSskrll 	secsize = be32toh(label.l.d_secsize);
1706d3ceb1dSskrll 	npart = be16toh(label.l.d_npartitions);
1716d3ceb1dSskrll 	if (label.l.d_magic != htobe32(DISKMAGIC) ||
1726d3ceb1dSskrll 	    label.l.d_magic2 != htobe32(DISKMAGIC) ||
1736d3ceb1dSskrll 	    secsize == 0 || secsize & (secsize - 1) ||
1746d3ceb1dSskrll 	    npart > MAXMAXPARTITIONS) {
1756d3ceb1dSskrll 		warnx("No disklabel in `%s'", params->filesystem);
1766d3ceb1dSskrll 
1776d3ceb1dSskrll 	/* then check if boot partition exists */
1786d3ceb1dSskrll 	} else if (npart < 1 || label.l.d_partitions[0].p_size == 0) {
1796d3ceb1dSskrll 		warnx("Partition `a' doesn't exist in %s", params->filesystem);
1806d3ceb1dSskrll 
1816d3ceb1dSskrll 	/* check if the boot partition is below 2GB */
1826d3ceb1dSskrll 	} else if (be32toh(label.l.d_partitions[0].p_offset) +
1836d3ceb1dSskrll 	    be32toh(label.l.d_partitions[0].p_size) >
1846d3ceb1dSskrll 	    ((unsigned)2*1024*1024*1024) / secsize) {
1856d3ceb1dSskrll 		warnx("Partition `a' of `%s' exceeds 2GB boundary.",
1866d3ceb1dSskrll 		    params->filesystem);
1876d3ceb1dSskrll 		warnx("It won't boot since hppa PDC can handle only 2GB.");
1886d3ceb1dSskrll 		goto done;
1896d3ceb1dSskrll 	}
1906d3ceb1dSskrll 
1916d3ceb1dSskrll 	/* read boot loader */
1926d3ceb1dSskrll 	memset(&bb, 0, sizeof bb);
1936d3ceb1dSskrll 	rv = read(params->s1fd, &bb, sizeof bb);
1946d3ceb1dSskrll 	if (rv == -1) {
1956d3ceb1dSskrll 		warn("Reading `%s'", params->stage1);
1966d3ceb1dSskrll 		goto done;
1976d3ceb1dSskrll 	}
1986d3ceb1dSskrll 	/* then, overwrite disklabel */
1996d3ceb1dSskrll 	memcpy(&bb[HPPA_LABELOFFSET], &label.l, HPPA_LABELSIZE);
2006d3ceb1dSskrll 
2016d3ceb1dSskrll 	if (params->flags & IB_VERBOSE) {
2026d3ceb1dSskrll 		printf("Bootstrap start sector: %#x\n", 0);
2036d3ceb1dSskrll 		printf("Bootstrap byte count:   %#zx\n", rv);
2046d3ceb1dSskrll 		printf("%sriting bootstrap\n",
2056d3ceb1dSskrll 		    (params->flags & IB_NOWRITE) ? "Not w" : "W");
2066d3ceb1dSskrll 	}
2076d3ceb1dSskrll 	if (params->flags & IB_NOWRITE) {
2086d3ceb1dSskrll 		retval = 1;
2096d3ceb1dSskrll 		goto done;
2106d3ceb1dSskrll 	}
2116d3ceb1dSskrll 
2126d3ceb1dSskrll 	/* write boot loader and disklabel into the target disk */
2136d3ceb1dSskrll 	rv = pwrite(params->fsfd, &bb, HPPA_BOOT_BLOCK_SIZE, 0);
2146d3ceb1dSskrll 	if (rv == -1) {
2156d3ceb1dSskrll 		warn("Writing `%s'", params->filesystem);
2166d3ceb1dSskrll 		goto done;
2176d3ceb1dSskrll 	} else if (rv != HPPA_BOOT_BLOCK_SIZE) {
2186d3ceb1dSskrll 		warnx("Writing `%s': short write", params->filesystem);
2196d3ceb1dSskrll 		goto done;
2206d3ceb1dSskrll 	} else
2216d3ceb1dSskrll 		retval = 1;
2226d3ceb1dSskrll 
2236d3ceb1dSskrll  done:
2246d3ceb1dSskrll 	return (retval);
2256d3ceb1dSskrll }
226