1/* $NetBSD: hp700.c,v 1.4 2008/04/28 20:24:16 martin 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: hp700.c,v 1.4 2008/04/28 20:24:16 martin 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 HP700_LABELOFFSET 512 62#define HP700_LABELSIZE 404 /* reserve 16 partitions */ 63#define HP700_BOOT_BLOCK_SIZE 8192 64 65static int hp700_clearboot(ib_params *); 66static int hp700_setboot(ib_params *); 67 68struct ib_mach ib_mach_hp700 = 69 { "hp700", hp700_setboot, hp700_clearboot, no_editboot, 0}; 70 71static int 72hp700_clearboot(ib_params *params) 73{ 74 char bb[HP700_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, HP700_LABELOFFSET); 96 eol = HP700_LABELOFFSET + HP700_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 != HP700_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 122static int 123hp700_setboot(ib_params *params) 124{ 125 struct stat bootstrapsb; 126 char bb[HP700_BOOT_BLOCK_SIZE]; 127 struct { 128 char l_off[HP700_LABELOFFSET]; 129 struct disklabel l; 130 char l_pad[HP700_BOOT_BLOCK_SIZE 131 - HP700_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, HP700_BOOT_BLOCK_SIZE, 0); 147 if (rv == -1) { 148 warn("Reading `%s'", params->filesystem); 149 goto done; 150 } else if (rv != HP700_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 hp700 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[HP700_LABELOFFSET], &label.l, HP700_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, HP700_BOOT_BLOCK_SIZE, 0); 210 if (rv == -1) { 211 warn("Writing `%s'", params->filesystem); 212 goto done; 213 } else if (rv != HP700_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