1/* $NetBSD: md.c,v 1.35 2011/04/04 08:30:19 mbalmer 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 -- arc machine specific routines */ 36 37#include <sys/param.h> 38#include <sys/sysctl.h> 39#include <stdio.h> 40#include <util.h> 41#include <machine/cpu.h> 42 43#include "defs.h" 44#include "md.h" 45#include "msg_defs.h" 46#include "menu_defs.h" 47 48/* 49 * ARC BIOS reognizes only FAT, so we have to have a FAT partition 50 * to store our native bootloader. 51 */ 52static int nobootfs = 0; 53static int bootpart_fat12 = PART_BOOT_FAT12; 54 55void 56md_init(void) 57{ 58} 59 60void 61md_init_set_status(int flags) 62{ 63 (void)flags; 64} 65 66int 67md_get_info(void) 68{ 69 return set_bios_geom_with_mbr_guess(); 70} 71 72/* 73 * md back-end code for menu-driven BSD disklabel editor. 74 */ 75int 76md_make_bsd_partitions(void) 77{ 78 int i; 79 int part; 80 int maxpart = getmaxpartitions(); 81 int partstart; 82 int part_raw, part_bsd; 83 int ptend; 84 int no_swap = 0; 85 partinfo *p; 86 87 /* 88 * Initialize global variables that track space used on this disk. 89 * Standard 4.4BSD 8-partition labels always cover whole disk. 90 */ 91 if (ptsize == 0) 92 ptsize = dlsize - ptstart; 93 if (dlsize == 0) 94 dlsize = ptstart + ptsize; 95 96 partstart = ptstart; 97 ptend = ptstart + ptsize; 98 99 /* Ask for layout type -- standard or special */ 100 msg_display(MSG_layout, 101 ptsize / (MEG / sectorsize), 102 DEFROOTSIZE + DEFSWAPSIZE + DEFUSRSIZE, 103 DEFROOTSIZE + DEFSWAPSIZE + DEFUSRSIZE + XNEEDMB); 104 105 process_menu(MENU_layout, NULL); 106 107 /* Set so we use the 'real' geometry for rounding, input in MB */ 108 current_cylsize = dlcylsize; 109 set_sizemultname_meg(); 110 111 /* Build standard partitions */ 112 memset(&bsdlabel, 0, sizeof bsdlabel); 113 114 /* Set initial partition types to unused */ 115 for (part = 0 ; part < maxpart ; ++part) 116 bsdlabel[part].pi_fstype = FS_UNUSED; 117 118 /* Whole disk partition */ 119 part_raw = getrawpartition(); 120 if (part_raw == -1) 121 part_raw = PART_C; /* for sanity... */ 122 bsdlabel[part_raw].pi_offset = 0; 123 bsdlabel[part_raw].pi_size = dlsize; 124 125 if (part_raw == PART_D) { 126 /* Probably a system that expects an i386 style mbr */ 127 part_bsd = PART_C; 128 bsdlabel[PART_C].pi_offset = ptstart; 129 bsdlabel[PART_C].pi_size = ptsize; 130 } else { 131 part_bsd = part_raw; 132 } 133 134 if (bootsize != 0) { 135 bsdlabel[PART_BOOT_FAT12].pi_fstype = FS_MSDOS; 136 bsdlabel[PART_BOOT_FAT12].pi_size = bootsize; 137 bsdlabel[PART_BOOT_FAT12].pi_offset = bootstart; 138 bsdlabel[PART_BOOT_FAT12].pi_flags |= PART_BOOT_FAT12_PI_FLAGS; 139 strlcpy(bsdlabel[PART_BOOT_FAT12].pi_mount, 140 PART_BOOT_FAT12_PI_MOUNT, 141 sizeof bsdlabel[PART_BOOT_FAT12].pi_mount); 142 } 143 144#ifdef PART_REST 145 bsdlabel[PART_REST].pi_offset = 0; 146 bsdlabel[PART_REST].pi_size = ptstart; 147#endif 148 149 /* 150 * Save any partitions that are outside the area we are 151 * going to use. 152 * In particular this saves details of the other MBR 153 * partitions on a multiboot i386 system. 154 */ 155 for (i = maxpart; i--;) { 156 if (bsdlabel[i].pi_size != 0) 157 /* Don't overwrite special partitions */ 158 continue; 159 p = &oldlabel[i]; 160 if (p->pi_fstype == FS_UNUSED || p->pi_size == 0) 161 continue; 162 if (layoutkind == 4) { 163 if (PI_ISBSDFS(p)) 164 p->pi_flags |= PIF_MOUNT; 165 } else { 166 if (p->pi_offset < ptstart + ptsize && 167 p->pi_offset + p->pi_size > ptstart) 168 /* Not outside area we are allocating */ 169 continue; 170 if (p->pi_fstype == FS_SWAP) 171 no_swap = 1; 172 } 173 bsdlabel[i] = oldlabel[i]; 174 } 175 176 if (layoutkind == 4) { 177 /* XXX Check we have a sensible layout */ 178 ; 179 } else 180 get_ptn_sizes(partstart, ptend - partstart, no_swap); 181 182 /* 183 * OK, we have a partition table. Give the user the chance to 184 * edit it and verify it's OK, or abort altogether. 185 */ 186 edit_check: 187 if (edit_and_check_label(bsdlabel, maxpart, part_raw, part_bsd) == 0) { 188 msg_display(MSG_abort); 189 return 0; 190 } 191 if (md_check_partitions() == 0) 192 goto edit_check; 193 194 /* Disk name */ 195 msg_prompt(MSG_packname, bsddiskname, bsddiskname, sizeof bsddiskname); 196 197 /* save label to disk for MI code to update. */ 198 (void)savenewlabel(bsdlabel, maxpart); 199 200 /* Everything looks OK. */ 201 return 1; 202} 203 204/* 205 * any additional partition validation 206 */ 207int 208md_check_partitions(void) 209{ 210 int part; 211 212 /* we need to find a boot partition, otherwise we can't write our 213 * bootloader. We make the assumption that the user hasn't done 214 * something stupid, like move it away from the MBR partition. 215 */ 216 for (part = PART_A; part < MAXPARTITIONS; part++) 217 if (bsdlabel[part].pi_fstype == FS_MSDOS) { 218 bootpart_fat12 = part; 219 return 1; 220 } 221 222 msg_display(MSG_nobootpartdisklabel); 223 process_menu(MENU_ok, NULL); 224 return 0; 225} 226 227/* 228 * hook called before writing new disklabel. 229 */ 230int 231md_pre_disklabel(void) 232{ 233 msg_display(MSG_dofdisk); 234 235 /* write edited MBR onto disk. */ 236 if (write_mbr(diskdev, &mbr, 1) != 0) { 237 msg_display(MSG_wmbrfail); 238 process_menu(MENU_ok, NULL); 239 return 1; 240 } 241 return 0; 242} 243 244/* 245 * hook called after writing disklabel to new target disk. 246 */ 247int 248md_post_disklabel(void) 249{ 250 if (get_ramsize() <= 32) 251 set_swap(diskdev, bsdlabel); 252 return 0; 253} 254 255/* 256 * hook called after upgrade() or install() has finished setting 257 * up the target disk but immediately before the user is given the 258 * ``disks are now set up'' message. 259 */ 260int 261md_post_newfs(void) 262{ 263 if (!nobootfs) { 264 msg_display(msg_string(MSG_copybootloader), diskdev); 265 cp_to_target("/usr/mdec/boot", PART_BOOT_FAT12_PI_MOUNT); 266 } 267 268 return 0; 269} 270 271int 272md_post_extract(void) 273{ 274 return 0; 275} 276 277void 278md_cleanup_install(void) 279{ 280#ifndef DEBUG 281 enable_rc_conf(); 282#endif 283 msg_display(MSG_howtoboot); 284 process_menu(MENU_ok, NULL); 285} 286 287int 288md_pre_update(void) 289{ 290 struct mbr_partition *part; 291 mbr_info_t *ext; 292 int i; 293 294 if (get_ramsize() <= 32) 295 set_swap(diskdev, NULL); 296 297 read_mbr(diskdev, &mbr); 298 /* do a sanity check of the partition table */ 299 for (ext = &mbr; ext; ext = ext->extended) { 300 part = ext->mbr.mbr_parts; 301 for (i = 0; i < MBR_PART_COUNT; part++, i++) { 302 if (part->mbrp_type != MBR_PTYPE_FAT12) 303 continue; 304 if (part->mbrp_size < (MIN_FAT12_BOOT / 512)) { 305 msg_display(MSG_boottoosmall); 306 msg_display_add(MSG_nobootpart, 0); 307 process_menu(MENU_yesno, NULL); 308 if (!yesno) 309 return 0; 310 nobootfs = 1; 311 } 312 } 313 } 314 if (md_check_partitions() == 0) 315 nobootfs = 1; 316 return 1; 317} 318 319/* Upgrade support */ 320int 321md_update(void) 322{ 323 md_post_newfs(); 324 return 1; 325} 326 327int 328md_check_mbr(mbr_info_t *mbri) 329{ 330 mbr_info_t *ext; 331 struct mbr_partition *part; 332 int i; 333 334 for (ext = mbri; ext; ext = ext->extended) { 335 part = ext->mbr.mbr_parts; 336 for (i = 0; i < MBR_PART_COUNT; part++, i++) { 337 if (part->mbrp_type == MBR_PTYPE_FAT12) { 338 bootstart = part->mbrp_start; 339 bootsize = part->mbrp_size; 340 break; 341 } 342 } 343 } 344 if (bootsize < (MIN_FAT12_BOOT / 512)) { 345 msg_display(MSG_boottoosmall); 346 msg_display_add(MSG_reeditpart, 0); 347 process_menu(MENU_yesno, NULL); 348 if (!yesno) 349 return 0; 350 return 1; 351 } 352 if (bootstart == 0 || bootsize == 0) { 353 msg_display(MSG_nobootpart); 354 msg_display_add(MSG_reeditpart, 0); 355 process_menu(MENU_yesno, NULL); 356 if (!yesno) 357 return 0; 358 return 1; 359 } 360 return 2; 361} 362 363int 364md_mbr_use_wholedisk(mbr_info_t *mbri) 365{ 366 struct mbr_sector *mbrs = &mbri->mbr; 367 mbr_info_t *ext; 368 struct mbr_partition *part; 369 370 part = &mbrs->mbr_parts[0]; 371 /* Set the partition information for full disk usage. */ 372 while ((ext = mbri->extended)) { 373 mbri->extended = ext->extended; 374 free(ext); 375 } 376 memset(part, 0, MBR_PART_COUNT * sizeof *part); 377#ifdef BOOTSEL 378 memset(&mbri->mbrb, 0, sizeof mbri->mbrb); 379#endif 380 part[0].mbrp_type = MBR_PTYPE_FAT12; 381 part[0].mbrp_size = FAT12_BOOT_SIZE / 512; 382 part[0].mbrp_start = bsec; 383 part[0].mbrp_flag = MBR_PFLAG_ACTIVE; 384 385 part[1].mbrp_type = MBR_PTYPE_NETBSD; 386 part[1].mbrp_size = dlsize - (bsec + FAT12_BOOT_SIZE / 512); 387 part[1].mbrp_start = bsec + FAT12_BOOT_SIZE / 512; 388 part[1].mbrp_flag = 0; 389 390 ptstart = part[1].mbrp_start; 391 ptsize = part[1].mbrp_size; 392 bootstart = part[0].mbrp_start; 393 bootsize = part[0].mbrp_size; 394 return 1; 395} 396 397int 398md_pre_mount() 399{ 400 return 0; 401} 402