1 /* $NetBSD: md.c,v 1.2 2014/08/03 16:09:38 martin Exp $ */ 2 3 /* 4 * Copyright 1997 Piermont Information Systems Inc. 5 * All rights reserved. 6 * 7 * Based on code written by Philip A. Nelson for Piermont Information 8 * Systems Inc. 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 * 3. The name of Piermont Information Systems Inc. may not be used to endorse 19 * or promote products derived from this software without specific prior 20 * written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS'' 23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE 26 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 32 * THE POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35 /* md.c -- arm32 machine specific routines - also used by acorn26 */ 36 37 #include <stdio.h> 38 #include <curses.h> 39 #include <unistd.h> 40 #include <fcntl.h> 41 #include <util.h> 42 #include <sys/types.h> 43 #include <sys/disklabel.h> 44 #include <sys/disklabel_acorn.h> 45 #include <sys/ioctl.h> 46 #include <sys/param.h> 47 48 #include "defs.h" 49 #include "md.h" 50 #include "msg_defs.h" 51 #include "menu_defs.h" 52 53 static int filecore_checksum(u_char *); 54 55 void 56 md_init(void) 57 { 58 } 59 60 void 61 md_init_set_status(int flags) 62 { 63 (void)flags; 64 } 65 66 int 67 md_get_info(void) 68 { 69 struct disklabel disklabel; 70 int fd; 71 char dev_name[100]; 72 static unsigned char bb[DEV_BSIZE]; 73 struct filecore_bootblock *fcbb = (struct filecore_bootblock *)bb; 74 int offset = 0; 75 76 if (strncmp(pm->diskdev, "wd", 2) == 0) 77 pm->disktype = "ST506"; 78 else 79 pm->disktype = "SCSI"; 80 81 snprintf(dev_name, 100, "/dev/r%s%c", pm->diskdev, 'a' + getrawpartition()); 82 83 fd = open(dev_name, O_RDONLY, 0); 84 if (fd < 0) { 85 endwin(); 86 fprintf(stderr, "Can't open %s\n", dev_name); 87 exit(1); 88 } 89 if (ioctl(fd, DIOCGDINFO, &disklabel) == -1) { 90 endwin(); 91 fprintf(stderr, "Can't read disklabel on %s.\n", dev_name); 92 close(fd); 93 exit(1); 94 } 95 96 if (lseek(fd, (off_t)FILECORE_BOOT_SECTOR * DEV_BSIZE, SEEK_SET) < 0 97 || read(fd, bb, sizeof(bb)) - sizeof(bb) != 0) { 98 endwin(); 99 fprintf(stderr, "%s", msg_string(MSG_badreadbb)); 100 close(fd); 101 exit(1); 102 } 103 104 /* Check if table is valid. */ 105 if (filecore_checksum(bb) == fcbb->checksum) { 106 /* 107 * Check for NetBSD/arm32 (RiscBSD) partition marker. 108 * If found the NetBSD disklabel location is easy. 109 */ 110 111 offset = (fcbb->partition_cyl_low + 112 (fcbb->partition_cyl_high << 8)) * 113 fcbb->heads * fcbb->secspertrack; 114 115 if (fcbb->partition_type == PARTITION_FORMAT_RISCBSD) 116 ; 117 else if (fcbb->partition_type == PARTITION_FORMAT_RISCIX) { 118 /* 119 * Ok we need to read the RISCiX partition table and 120 * search for a partition named RiscBSD, NetBSD or 121 * Empty: 122 */ 123 124 struct riscix_partition_table *riscix_part = 125 (struct riscix_partition_table *)bb; 126 struct riscix_partition *part; 127 int loop; 128 129 if (lseek(fd, (off_t)offset * DEV_BSIZE, SEEK_SET) < 0 130 || read(fd, bb, sizeof(bb)) - sizeof(bb) != 0) { 131 endwin(); 132 fprintf(stderr, "%s", 133 msg_string(MSG_badreadriscix)); 134 close(fd); 135 exit(1); 136 } 137 138 /* Break out as soon as we find a suitable partition */ 139 for (loop = 0; loop < NRISCIX_PARTITIONS; ++loop) { 140 part = &riscix_part->partitions[loop]; 141 if (strcmp((char *)part->rp_name, "RiscBSD") == 0 142 || strcmp((char *)part->rp_name, "NetBSD") == 0 143 || strcmp((char *)part->rp_name, "Empty:") == 0) { 144 offset = part->rp_start; 145 break; 146 } 147 } 148 if (loop == NRISCIX_PARTITIONS) { 149 /* 150 * Valid filecore boot block, RISCiX partition 151 * table but no NetBSD partition. We should 152 * leave this disc alone. 153 */ 154 endwin(); 155 fprintf(stderr, "%s", 156 msg_string(MSG_notnetbsdriscix)); 157 close(fd); 158 exit(1); 159 } 160 } else { 161 /* 162 * Valid filecore boot block and no non-ADFS partition. 163 * This means that the whole disc is allocated for ADFS 164 * so do not trash ! If the user really wants to put a 165 * NetBSD disklabel on the disc then they should remove 166 * the filecore boot block first with dd. 167 */ 168 endwin(); 169 fprintf(stderr, "%s", msg_string(MSG_notnetbsd)); 170 close(fd); 171 exit(1); 172 } 173 } 174 close(fd); 175 176 pm->dlcyl = disklabel.d_ncylinders; 177 pm->dlhead = disklabel.d_ntracks; 178 pm->dlsec = disklabel.d_nsectors; 179 pm->sectorsize = disklabel.d_secsize; 180 pm->dlcylsize = disklabel.d_secpercyl; 181 182 /* 183 * Compute whole disk size. Take max of (pm->dlcyl*pm->dlhead*pm->dlsec) 184 * and secperunit, just in case the disk is already labelled. 185 * (If our new label's RAW_PART size ends up smaller than the 186 * in-core RAW_PART size value, updating the label will fail.) 187 */ 188 pm->dlsize = pm->dlcyl*pm->dlhead*pm->dlsec; 189 if (disklabel.d_secperunit > pm->dlsize) 190 pm->dlsize = disklabel.d_secperunit; 191 192 pm->ptstart = offset; 193 /* endwin(); 194 printf("pm->dlcyl=%d\n", pm->dlcyl); 195 printf("pm->dlhead=%d\n", pm->dlhead); 196 printf("pm->dlsec=%d\n", pm->dlsec); 197 printf("secsz=%d\n", pm->sectorsize); 198 printf("cylsz=%d\n", pm->dlcylsize); 199 printf("dlsz=%d\n", pm->dlsize); 200 printf("pstart=%d\n", pm->ptstart); 201 printf("pstart=%d\n", partsize); 202 printf("secpun=%d\n", disklabel.d_secperunit); 203 backtowin();*/ 204 205 return 1; 206 } 207 208 /* 209 * md back-end code for menu-driven BSD disklabel editor. 210 */ 211 int 212 md_make_bsd_partitions(void) 213 { 214 return make_bsd_partitions(); 215 } 216 217 /* 218 * any additional partition validation 219 */ 220 int 221 md_check_partitions(void) 222 { 223 return 1; 224 } 225 226 /* 227 * hook called before writing new disklabel. 228 */ 229 int 230 md_pre_disklabel(void) 231 { 232 return 0; 233 } 234 235 /* 236 * hook called after writing disklabel to new target disk. 237 */ 238 int 239 md_post_disklabel(void) 240 { 241 return 0; 242 } 243 244 /* 245 * hook called after upgrade() or install() has finished setting 246 * up the target disk but immediately before the user is given the 247 * ``disks are now set up'' message. 248 */ 249 int 250 md_post_newfs(void) 251 { 252 return 0; 253 } 254 255 int 256 md_post_extract(void) 257 { 258 return 0; 259 } 260 261 void 262 md_cleanup_install(void) 263 { 264 #ifndef DEBUG 265 enable_rc_conf(); 266 #endif 267 } 268 269 int 270 md_pre_update(void) 271 { 272 return 1; 273 } 274 275 /* Upgrade support */ 276 int 277 md_update(void) 278 { 279 md_post_newfs(); 280 return 1; 281 } 282 283 /* 284 * static int filecore_checksum(u_char *bootblock) 285 * 286 * Calculates the filecore boot block checksum. This is used to validate 287 * a filecore boot block on the disk. If a boot block is validated then 288 * it is used to locate the partition table. If the boot block is not 289 * validated, it is assumed that the whole disk is NetBSD. 290 * 291 * The basic algorithm is: 292 * 293 * for (each byte in block, excluding checksum) { 294 * sum += byte; 295 * if (sum > 255) 296 * sum -= 255; 297 * } 298 * 299 * That's equivalent to summing all of the bytes in the block 300 * (excluding the checksum byte, of course), then calculating the 301 * checksum as "cksum = sum - ((sum - 1) / 255) * 255)". That 302 * expression may or may not yield a faster checksum function, 303 * but it's easier to reason about. 304 * 305 * Note that if you have a block filled with bytes of a single 306 * value "X" (regardless of that value!) and calculate the cksum 307 * of the block (excluding the checksum byte), you will _always_ 308 * end up with a checksum of X. (Do the math; that can be derived 309 * from the checksum calculation function!) That means that 310 * blocks which contain bytes which all have the same value will 311 * always checksum properly. That's a _very_ unlikely occurence 312 * (probably impossible, actually) for a valid filecore boot block, 313 * so we treat such blocks as invalid. 314 */ 315 316 static int 317 filecore_checksum(u_char *bootblock) 318 { 319 u_char byte0, accum_diff; 320 u_int sum; 321 int i; 322 323 sum = 0; 324 accum_diff = 0; 325 byte0 = bootblock[0]; 326 327 /* 328 * Sum the contents of the block, keeping track of whether 329 * or not all bytes are the same. If 'accum_diff' ends up 330 * being zero, all of the bytes are, in fact, the same. 331 */ 332 for (i = 0; i < 511; ++i) { 333 sum += bootblock[i]; 334 accum_diff |= bootblock[i] ^ byte0; 335 } 336 337 /* 338 * Check to see if the checksum byte is the same as the 339 * rest of the bytes, too. (Note that if all of the bytes 340 * are the same except the checksum, a checksum compare 341 * won't succeed, but that's not our problem.) 342 */ 343 accum_diff |= bootblock[i] ^ byte0; 344 345 /* All bytes in block are the same; call it invalid. */ 346 if (accum_diff == 0) 347 return (-1); 348 349 return (sum - ((sum - 1) / 255) * 255); 350 } 351 352 int 353 md_pre_mount() 354 { 355 return 0; 356 } 357