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