1 /* $NetBSD: hppa.c,v 1.1 2014/02/24 07:23:44 skrll Exp $ */ 2 3 /*- 4 * Copyright (c) 2002 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Luke Mewburn of Wasabi Systems. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #if HAVE_NBTOOL_CONFIG_H 33 #include "nbtool_config.h" 34 #endif 35 36 #include <sys/cdefs.h> 37 #if !defined(__lint) 38 __RCSID("$NetBSD: hppa.c,v 1.1 2014/02/24 07:23:44 skrll Exp $"); 39 #endif /* !__lint */ 40 41 /* We need the target disklabel.h, not the hosts one..... */ 42 #ifdef HAVE_NBTOOL_CONFIG_H 43 #include "nbtool_config.h" 44 #include <nbinclude/sys/disklabel.h> 45 #else 46 #include <sys/disklabel.h> 47 #endif 48 #include <sys/param.h> 49 #include <sys/stat.h> 50 51 #include <assert.h> 52 #include <err.h> 53 #include <stddef.h> 54 #include <stdio.h> 55 #include <stdlib.h> 56 #include <string.h> 57 #include <unistd.h> 58 59 #include "installboot.h" 60 61 #define HPPA_LABELOFFSET 512 62 #define HPPA_LABELSIZE 404 /* reserve 16 partitions */ 63 #define HPPA_BOOT_BLOCK_SIZE 8192 64 65 static int hppa_clearboot(ib_params *); 66 static int hppa_setboot(ib_params *); 67 68 struct ib_mach ib_mach_hppa = 69 { "hppa", hppa_setboot, hppa_clearboot, no_editboot, 0}; 70 71 static int 72 hppa_clearboot(ib_params *params) 73 { 74 char bb[HPPA_BOOT_BLOCK_SIZE]; 75 int retval, eol; 76 ssize_t rv; 77 78 assert(params != NULL); 79 assert(params->fsfd != -1); 80 assert(params->filesystem != NULL); 81 82 retval = 0; 83 84 /* read disklabel on the target disk */ 85 rv = pread(params->fsfd, bb, sizeof bb, 0); 86 if (rv == -1) { 87 warn("Reading `%s'", params->filesystem); 88 goto done; 89 } else if (rv != sizeof bb) { 90 warnx("Reading `%s': short read", params->filesystem); 91 goto done; 92 } 93 94 /* clear header */ 95 memset(bb, 0, HPPA_LABELOFFSET); 96 eol = HPPA_LABELOFFSET + HPPA_LABELSIZE; 97 memset(&bb[eol], 0, sizeof bb - eol); 98 99 if (params->flags & IB_VERBOSE) { 100 printf("%slearing bootstrap\n", 101 (params->flags & IB_NOWRITE) ? "Not c" : "C"); 102 } 103 if (params->flags & IB_NOWRITE) { 104 retval = 1; 105 goto done; 106 } 107 108 rv = pwrite(params->fsfd, bb, sizeof bb, 0); 109 if (rv == -1) { 110 warn("Writing `%s'", params->filesystem); 111 goto done; 112 } else if (rv != HPPA_BOOT_BLOCK_SIZE) { 113 warnx("Writing `%s': short write", params->filesystem); 114 goto done; 115 } else 116 retval = 1; 117 118 done: 119 return (retval); 120 } 121 122 static int 123 hppa_setboot(ib_params *params) 124 { 125 struct stat bootstrapsb; 126 char bb[HPPA_BOOT_BLOCK_SIZE]; 127 struct { 128 char l_off[HPPA_LABELOFFSET]; 129 struct disklabel l; 130 char l_pad[HPPA_BOOT_BLOCK_SIZE 131 - HPPA_LABELOFFSET - sizeof(struct disklabel)]; 132 } label; 133 unsigned int secsize, npart; 134 int retval; 135 ssize_t rv; 136 137 assert(params != NULL); 138 assert(params->fsfd != -1); 139 assert(params->filesystem != NULL); 140 assert(params->s1fd != -1); 141 assert(params->stage1 != NULL); 142 143 retval = 0; 144 145 /* read disklabel on the target disk */ 146 rv = pread(params->fsfd, &label, HPPA_BOOT_BLOCK_SIZE, 0); 147 if (rv == -1) { 148 warn("Reading `%s'", params->filesystem); 149 goto done; 150 } else if (rv != HPPA_BOOT_BLOCK_SIZE) { 151 warnx("Reading `%s': short read", params->filesystem); 152 goto done; 153 } 154 155 if (fstat(params->s1fd, &bootstrapsb) == -1) { 156 warn("Examining `%s'", params->stage1); 157 goto done; 158 } 159 if (!S_ISREG(bootstrapsb.st_mode)) { 160 warnx("`%s' must be a regular file", params->stage1); 161 goto done; 162 } 163 164 /* check if valid disklabel exists */ 165 secsize = be32toh(label.l.d_secsize); 166 npart = be16toh(label.l.d_npartitions); 167 if (label.l.d_magic != htobe32(DISKMAGIC) || 168 label.l.d_magic2 != htobe32(DISKMAGIC) || 169 secsize == 0 || secsize & (secsize - 1) || 170 npart > MAXMAXPARTITIONS) { 171 warnx("No disklabel in `%s'", params->filesystem); 172 173 /* then check if boot partition exists */ 174 } else if (npart < 1 || label.l.d_partitions[0].p_size == 0) { 175 warnx("Partition `a' doesn't exist in %s", params->filesystem); 176 177 /* check if the boot partition is below 2GB */ 178 } else if (be32toh(label.l.d_partitions[0].p_offset) + 179 be32toh(label.l.d_partitions[0].p_size) > 180 ((unsigned)2*1024*1024*1024) / secsize) { 181 warnx("Partition `a' of `%s' exceeds 2GB boundary.", 182 params->filesystem); 183 warnx("It won't boot since hppa PDC can handle only 2GB."); 184 goto done; 185 } 186 187 /* read boot loader */ 188 memset(&bb, 0, sizeof bb); 189 rv = read(params->s1fd, &bb, sizeof bb); 190 if (rv == -1) { 191 warn("Reading `%s'", params->stage1); 192 goto done; 193 } 194 /* then, overwrite disklabel */ 195 memcpy(&bb[HPPA_LABELOFFSET], &label.l, HPPA_LABELSIZE); 196 197 if (params->flags & IB_VERBOSE) { 198 printf("Bootstrap start sector: %#x\n", 0); 199 printf("Bootstrap byte count: %#zx\n", rv); 200 printf("%sriting bootstrap\n", 201 (params->flags & IB_NOWRITE) ? "Not w" : "W"); 202 } 203 if (params->flags & IB_NOWRITE) { 204 retval = 1; 205 goto done; 206 } 207 208 /* write boot loader and disklabel into the target disk */ 209 rv = pwrite(params->fsfd, &bb, HPPA_BOOT_BLOCK_SIZE, 0); 210 if (rv == -1) { 211 warn("Writing `%s'", params->filesystem); 212 goto done; 213 } else if (rv != HPPA_BOOT_BLOCK_SIZE) { 214 warnx("Writing `%s': short write", params->filesystem); 215 goto done; 216 } else 217 retval = 1; 218 219 done: 220 return (retval); 221 } 222