1 /* $NetBSD: md.c,v 1.2 2014/08/03 16:09:39 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 if (get_ramsize() <= 32) 251 set_swap(pm->diskdev, pm->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 */ 260 int 261 md_post_newfs(void) 262 { 263 if (!nobootfs) { 264 msg_display(msg_string(MSG_copybootloader), pm->diskdev); 265 cp_to_target("/usr/mdec/boot", PART_BOOT_FAT12_PI_MOUNT); 266 } 267 268 return 0; 269 } 270 271 int 272 md_post_extract(void) 273 { 274 return 0; 275 } 276 277 void 278 md_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 287 int 288 md_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(pm->diskdev, NULL); 296 297 read_mbr(pm->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 */ 320 int 321 md_update(void) 322 { 323 md_post_newfs(); 324 return 1; 325 } 326 327 int 328 md_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 pm->bootstart = part->mbrp_start; 339 pm->bootsize = part->mbrp_size; 340 break; 341 } 342 } 343 } 344 if (pm->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 (pm->bootstart == 0 || pm->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 363 int 364 md_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 = pm->dlsize - (bsec + FAT12_BOOT_SIZE / 512); 387 part[1].mbrp_start = bsec + FAT12_BOOT_SIZE / 512; 388 part[1].mbrp_flag = 0; 389 390 pm->ptstart = part[1].mbrp_start; 391 pm->ptsize = part[1].mbrp_size; 392 pm->bootstart = part[0].mbrp_start; 393 pm->bootsize = part[0].mbrp_size; 394 return 1; 395 } 396 397 int 398 md_pre_mount() 399 { 400 return 0; 401 } 402