1 /* $NetBSD: md.c,v 1.4 2015/05/10 10:14:02 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 -- 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 */ 52 static int nobootfs = 0; 53 static int bootpart_fat12 = PART_BOOT_FAT12; 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 return set_bios_geom_with_mbr_guess(); 70 } 71 72 /* 73 * md back-end code for menu-driven BSD disklabel editor. 74 */ 75 int 76 md_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 (pm->ptsize == 0) 92 pm->ptsize = pm->dlsize - pm->ptstart; 93 if (pm->dlsize == 0) 94 pm->dlsize = pm->ptstart + pm->ptsize; 95 96 partstart = pm->ptstart; 97 ptend = pm->ptstart + pm->ptsize; 98 99 /* Ask for layout type -- standard or special */ 100 msg_display(MSG_layout, 101 pm->ptsize / (MEG / pm->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 pm->current_cylsize = pm->dlcylsize; 109 set_sizemultname_meg(); 110 111 /* Build standard partitions */ 112 memset(&pm->bsdlabel, 0, sizeof pm->bsdlabel); 113 114 /* Set initial partition types to unused */ 115 for (part = 0 ; part < maxpart ; ++part) 116 pm->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 pm->bsdlabel[part_raw].pi_offset = 0; 123 pm->bsdlabel[part_raw].pi_size = pm->dlsize; 124 125 if (part_raw == PART_D) { 126 /* Probably a system that expects an i386 style mbr */ 127 part_bsd = PART_C; 128 pm->bsdlabel[PART_C].pi_offset = pm->ptstart; 129 pm->bsdlabel[PART_C].pi_size = pm->ptsize; 130 } else { 131 part_bsd = part_raw; 132 } 133 134 if (pm->bootsize != 0) { 135 pm->bsdlabel[PART_BOOT_FAT12].pi_fstype = FS_MSDOS; 136 pm->bsdlabel[PART_BOOT_FAT12].pi_size = pm->bootsize; 137 pm->bsdlabel[PART_BOOT_FAT12].pi_offset = pm->bootstart; 138 pm->bsdlabel[PART_BOOT_FAT12].pi_flags |= PART_BOOT_FAT12_PI_FLAGS; 139 strlcpy(pm->bsdlabel[PART_BOOT_FAT12].pi_mount, 140 PART_BOOT_FAT12_PI_MOUNT, 141 sizeof pm->bsdlabel[PART_BOOT_FAT12].pi_mount); 142 } 143 144 #ifdef PART_REST 145 pm->bsdlabel[PART_REST].pi_offset = 0; 146 pm->bsdlabel[PART_REST].pi_size = pm->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 (pm->bsdlabel[i].pi_size != 0) 157 /* Don't overwrite special partitions */ 158 continue; 159 p = &pm->oldlabel[i]; 160 if (p->pi_fstype == FS_UNUSED || p->pi_size == 0) 161 continue; 162 if (layoutkind == LY_USEEXIST) { 163 if (PI_ISBSDFS(p)) 164 p->pi_flags |= PIF_MOUNT; 165 } else { 166 if (p->pi_offset < pm->ptstart + pm->ptsize && 167 p->pi_offset + p->pi_size > pm->ptstart) 168 /* Not outside area we are allocating */ 169 continue; 170 if (p->pi_fstype == FS_SWAP) 171 no_swap = 1; 172 } 173 pm->bsdlabel[i] = pm->oldlabel[i]; 174 } 175 176 if (layoutkind == LY_USEEXIST) { 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(pm->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, pm->bsddiskname, pm->bsddiskname, sizeof pm->bsddiskname); 196 197 /* save label to disk for MI code to update. */ 198 (void)savenewlabel(pm->bsdlabel, maxpart); 199 200 /* Everything looks OK. */ 201 return 1; 202 } 203 204 /* 205 * any additional partition validation 206 */ 207 int 208 md_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 (pm->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 */ 230 int 231 md_pre_disklabel(void) 232 { 233 msg_display(MSG_dofdisk); 234 235 /* write edited MBR onto disk. */ 236 if (write_mbr(pm->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 */ 247 int 248 md_post_disklabel(void) 249 { 250 return 0; 251 } 252 253 /* 254 * hook called after upgrade() or install() has finished setting 255 * up the target disk but immediately before the user is given the 256 * ``disks are now set up'' message. 257 */ 258 int 259 md_post_newfs(void) 260 { 261 if (!nobootfs) { 262 msg_display(msg_string(MSG_copybootloader), pm->diskdev); 263 cp_to_target("/usr/mdec/boot", PART_BOOT_FAT12_PI_MOUNT); 264 } 265 266 return 0; 267 } 268 269 int 270 md_post_extract(void) 271 { 272 return 0; 273 } 274 275 void 276 md_cleanup_install(void) 277 { 278 #ifndef DEBUG 279 enable_rc_conf(); 280 #endif 281 msg_display(MSG_howtoboot); 282 process_menu(MENU_ok, NULL); 283 } 284 285 int 286 md_pre_update(void) 287 { 288 struct mbr_partition *part; 289 mbr_info_t *ext; 290 int i; 291 292 read_mbr(pm->diskdev, &mbr); 293 /* do a sanity check of the partition table */ 294 for (ext = &mbr; ext; ext = ext->extended) { 295 part = ext->mbr.mbr_parts; 296 for (i = 0; i < MBR_PART_COUNT; part++, i++) { 297 if (part->mbrp_type != MBR_PTYPE_FAT12) 298 continue; 299 if (part->mbrp_size < (MIN_FAT12_BOOT / 512)) { 300 msg_display(MSG_boottoosmall); 301 msg_display_add(MSG_nobootpart, 0); 302 if (!ask_yesno(NULL)) 303 return 0; 304 nobootfs = 1; 305 } 306 } 307 } 308 if (md_check_partitions() == 0) 309 nobootfs = 1; 310 return 1; 311 } 312 313 /* Upgrade support */ 314 int 315 md_update(void) 316 { 317 md_post_newfs(); 318 return 1; 319 } 320 321 int 322 md_check_mbr(mbr_info_t *mbri) 323 { 324 mbr_info_t *ext; 325 struct mbr_partition *part; 326 int i; 327 328 for (ext = mbri; ext; ext = ext->extended) { 329 part = ext->mbr.mbr_parts; 330 for (i = 0; i < MBR_PART_COUNT; part++, i++) { 331 if (part->mbrp_type == MBR_PTYPE_FAT12) { 332 pm->bootstart = part->mbrp_start; 333 pm->bootsize = part->mbrp_size; 334 break; 335 } 336 } 337 } 338 if (pm->bootsize < (MIN_FAT12_BOOT / 512)) { 339 msg_display(MSG_boottoosmall); 340 msg_display_add(MSG_reeditpart, 0); 341 if (!ask_yesno(NULL)) 342 return 0; 343 return 1; 344 } 345 if (pm->bootstart == 0 || pm->bootsize == 0) { 346 msg_display(MSG_nobootpart); 347 msg_display_add(MSG_reeditpart, 0); 348 if (!ask_yesno(NULL)) 349 return 0; 350 return 1; 351 } 352 return 2; 353 } 354 355 int 356 md_mbr_use_wholedisk(mbr_info_t *mbri) 357 { 358 struct mbr_sector *mbrs = &mbri->mbr; 359 mbr_info_t *ext; 360 struct mbr_partition *part; 361 362 part = &mbrs->mbr_parts[0]; 363 /* Set the partition information for full disk usage. */ 364 while ((ext = mbri->extended)) { 365 mbri->extended = ext->extended; 366 free(ext); 367 } 368 memset(part, 0, MBR_PART_COUNT * sizeof *part); 369 #ifdef BOOTSEL 370 memset(&mbri->mbrb, 0, sizeof mbri->mbrb); 371 #endif 372 part[0].mbrp_type = MBR_PTYPE_FAT12; 373 part[0].mbrp_size = FAT12_BOOT_SIZE / 512; 374 part[0].mbrp_start = bsec; 375 part[0].mbrp_flag = MBR_PFLAG_ACTIVE; 376 377 part[1].mbrp_type = MBR_PTYPE_NETBSD; 378 part[1].mbrp_size = pm->dlsize - (bsec + FAT12_BOOT_SIZE / 512); 379 part[1].mbrp_start = bsec + FAT12_BOOT_SIZE / 512; 380 part[1].mbrp_flag = 0; 381 382 pm->ptstart = part[1].mbrp_start; 383 pm->ptsize = part[1].mbrp_size; 384 pm->bootstart = part[0].mbrp_start; 385 pm->bootsize = part[0].mbrp_size; 386 return 1; 387 } 388 389 int 390 md_pre_mount() 391 { 392 return 0; 393 } 394