1 /* $NetBSD: bsddisklabel.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 /* bsddisklabel.c -- generate standard BSD disklabel */ 36 /* Included by appropriate arch/XXXX/md.c */ 37 38 #include <sys/param.h> 39 #include <sys/sysctl.h> 40 #include <sys/exec.h> 41 #include <sys/utsname.h> 42 #include <sys/types.h> 43 #include <sys/stat.h> 44 #include <machine/cpu.h> 45 #include <stdio.h> 46 #include <stddef.h> 47 #include <util.h> 48 #include <dirent.h> 49 #include "defs.h" 50 #include "md.h" 51 #include "endian.h" 52 #include "msg_defs.h" 53 #include "menu_defs.h" 54 55 /* For the current state of this file blame abs@NetBSD.org */ 56 /* Even though he wasn't the last to hack it, but he did admit doing so :-) */ 57 58 #define PART_ANY -1 59 #define PART_EXTRA -2 60 #define PART_TMP_RAMDISK -3 61 62 /* Defaults for things that might be defined in md.h */ 63 #ifndef PART_ROOT 64 #define PART_ROOT PART_A 65 #endif 66 #ifndef PART_SWAP 67 #define PART_SWAP PART_B 68 #endif 69 #ifndef PART_USR 70 #define PART_USR PART_ANY 71 #endif 72 73 #ifndef DEFVARSIZE 74 #define DEFVARSIZE 32 75 #endif 76 #ifndef DEFROOTSIZE 77 #define DEFROOTSIZE 32 78 #endif 79 #ifndef DEFUSRSIZE 80 #define DEFUSRSIZE 128 81 #endif 82 #ifndef DEFSWAPSIZE 83 #define DEFSWAPSIZE 128 84 #endif 85 86 int 87 save_ptn(int ptn, daddr_t start, daddr_t size, int fstype, const char *mountpt) 88 { 89 static int maxptn; 90 partinfo *p; 91 int pp; 92 char *buf; 93 94 if (maxptn == 0) 95 maxptn = getmaxpartitions(); 96 97 if (ptn < 0 || pm->bsdlabel[ptn].pi_fstype != FS_UNUSED) { 98 ptn = getrawpartition() + 1; 99 #ifdef PART_FIRST_FREE 100 if (ptn < PART_FIRST_FREE) 101 ptn = PART_FIRST_FREE; 102 #endif 103 for (;; ptn++) { 104 if (ptn >= maxptn) 105 return -1; 106 if (ptn == PART_USR) 107 continue; 108 if (pm->bsdlabel[ptn].pi_fstype == FS_UNUSED) 109 break; 110 } 111 } 112 113 if (fstype == FS_UNUSED) 114 return ptn; 115 116 p = pm->bsdlabel + ptn; 117 p->pi_offset = start; 118 p->pi_size = size; 119 set_ptype(p, fstype, mountpt ? PIF_NEWFS : 0); 120 121 /* Hack because we does not have something like FS_LVMPV */ 122 p->lvmpv = 0; 123 if (mountpt != NULL && strcmp(mountpt, "lvm") == 0) 124 p->lvmpv = 1; 125 else if (mountpt != NULL) { 126 for (pp = 0; pp < maxptn; pp++) { 127 if (strcmp(pm->bsdlabel[pp].pi_mount, mountpt) == 0) 128 pm->bsdlabel[pp].pi_flags &= ~PIF_MOUNT; 129 } 130 if (mountpt[0] != '/') 131 asprintf(&buf, "/%s", mountpt); 132 else 133 asprintf(&buf, "%s", mountpt); 134 strlcpy(p->pi_mount, buf, sizeof p->pi_mount); 135 p->pi_flags |= PIF_MOUNT; 136 /* Default to UFS2. */ 137 if (p->pi_fstype == FS_BSDFFS) { 138 #ifdef DEFAULT_UFS2 139 #ifndef HAVE_UFS2_BOOT 140 if (strcmp(mountpt, "/") != 0) 141 #endif 142 p->pi_flags |= PIF_FFSv2; 143 #endif 144 } 145 free(buf); 146 } 147 148 return ptn; 149 } 150 151 void 152 set_ptn_titles(menudesc *m, int opt, void *arg) 153 { 154 struct ptn_info *pi = arg; 155 struct ptn_size *p; 156 int sm = MEG / pm->sectorsize; 157 daddr_t size; 158 char inc_free[12]; 159 160 p = &pi->ptn_sizes[opt]; 161 if (p->mount[0] == 0) { 162 wprintw(m->mw, "%s", msg_string(MSG_add_another_ptn)); 163 return; 164 } 165 size = p->size; 166 if (p == pi->pool_part) 167 snprintf(inc_free, sizeof inc_free, "(%" PRIi64 ")", 168 (size + pi->free_space) / sm); 169 else 170 inc_free[0] = 0; 171 wprintw(m->mw, "%6" PRIi64 "%8s%10" PRIi64 "%10" PRIi64 " %c %s", 172 size / sm, inc_free, size / pm->dlcylsize, size, 173 p == pi->pool_part ? '+' : ' ', p->mount); 174 } 175 176 void 177 set_ptn_menu(struct ptn_info *pi) 178 { 179 struct ptn_size *p; 180 menu_ent *m; 181 182 for (m = pi->ptn_menus, p = pi->ptn_sizes;; m++, p++) { 183 m->opt_name = NULL; 184 m->opt_menu = OPT_NOMENU; 185 m->opt_flags = 0; 186 m->opt_action = set_ptn_size; 187 if (p->mount[0] == 0) 188 break; 189 } 190 if (pi->free_parts != 0) 191 m++; 192 m->opt_name = MSG_askunits; 193 m->opt_menu = MENU_sizechoice; 194 m->opt_flags = OPT_SUB; 195 m->opt_action = NULL; 196 m++; 197 198 if (pi->free_space >= 0) 199 snprintf(pi->exit_msg, sizeof pi->exit_msg, 200 msg_string(MSG_fssizesok), 201 (int)(pi->free_space / sizemult), multname, pi->free_parts); 202 else 203 snprintf(pi->exit_msg, sizeof pi->exit_msg, 204 msg_string(MSG_fssizesbad), 205 (int)(-pi->free_space / sizemult), multname, (uint) -pi->free_space); 206 207 set_menu_numopts(pi->menu_no, m - pi->ptn_menus); 208 } 209 210 int 211 set_ptn_size(menudesc *m, void *arg) 212 { 213 struct ptn_info *pi = arg; 214 struct ptn_size *p; 215 char answer[10]; 216 char dflt[10]; 217 char *cp; 218 daddr_t size, old_size; 219 int mult; 220 221 p = pi->ptn_sizes + m->cursel; 222 223 if (pi->free_parts == 0 && p->size == 0) 224 /* Don't allow 'free_parts' to go negative */ 225 return 0; 226 227 if (p->mount[0] == 0) { 228 msg_prompt_win(partman_go?MSG_askfsmountadv:MSG_askfsmount, 229 -1, 18, 0, 0, NULL, p->mount, sizeof p->mount); 230 if (p->mount[0] == 0) 231 return 0; 232 } 233 234 size = p->size; 235 old_size = size; 236 if (size == 0) 237 size = p->dflt_size; 238 size /= sizemult; 239 snprintf(dflt, sizeof dflt, "%" PRIi64 "%s", 240 size, p == pi->pool_part ? "+" : ""); 241 242 for (;;) { 243 mult = sizemult; 244 msg_prompt_win(MSG_askfssize, -1, 18, 0, 0, 245 dflt, answer, sizeof answer, 246 p->mount, multname); 247 /* Some special cases when /usr is first given a size */ 248 if (old_size == 0 && !strcmp(p->mount, "/usr")) { 249 /* Remove space for /usr from / */ 250 if (!pi->ptn_sizes[0].changed) { 251 pi->ptn_sizes[0].size -= p->dflt_size; 252 pi->free_space += p->dflt_size; 253 pi->ptn_sizes[0].changed = 1; 254 } 255 /* hack to add free space to default sized /usr */ 256 if (!strcmp(answer, dflt)) { 257 size = p->dflt_size; 258 pi->pool_part = p; 259 goto adjust_free; 260 } 261 } 262 size = strtoul(answer, &cp, 0); 263 switch (*cp++) { 264 default: 265 continue; 266 case 's': 267 mult = 1; 268 break; 269 case 'c': 270 mult = pm->dlcylsize; 271 break; 272 case 'm': 273 case 'M': 274 mult = MEG / pm->sectorsize; 275 break; 276 case 'g': 277 case 'G': 278 mult = 1024 * MEG / pm->sectorsize; 279 break; 280 case '+': 281 cp--; 282 if (cp != answer) 283 break; 284 mult = 1; 285 size = old_size; 286 break; 287 case 0: 288 cp--; 289 break; 290 } 291 if (*cp == 0 || *cp == '+') 292 break; 293 } 294 295 size = NUMSEC(size, mult, pm->dlcylsize); 296 if (p->ptn_id == PART_TMP_RAMDISK) { 297 p->size = size; 298 return 0; 299 } 300 if (p == pi->pool_part) 301 pi->pool_part = NULL; 302 if (*cp == '+' && p->limit == 0) { 303 pi->pool_part = p; 304 if (size == 0) 305 size = pm->dlcylsize; 306 } 307 if (p->limit != 0 && size > p->limit) 308 size = p->limit; 309 adjust_free: 310 if (size != old_size) 311 p->changed = 1; 312 pi->free_space += old_size - size; 313 p->size = size; 314 if (size == 0) { 315 if (old_size != 0) 316 pi->free_parts++; 317 if (p->ptn_id == PART_EXTRA) 318 memmove(p, p + 1, 319 (char *)&pi->ptn_sizes[MAXPARTITIONS] 320 - (char *)p); 321 } else { 322 int f = pi->free_space; 323 if (old_size == 0) 324 pi->free_parts--; 325 if (f < mult && -f < mult) { 326 /* 327 * Round size to end of available space, 328 * but keep cylinder alignment 329 */ 330 if (f < 0) 331 f = -roundup(-f, pm->dlcylsize); 332 else 333 f = rounddown(f, pm->dlcylsize); 334 size += f; 335 if (size != 0) { 336 pi->free_space -= f; 337 p->size += f; 338 } 339 } 340 } 341 342 set_ptn_menu(pi); 343 344 return 0; 345 } 346 347 /* Menu to change sizes of /, /usr, /home and etc. partitions */ 348 void 349 get_ptn_sizes(daddr_t part_start, daddr_t sectors, int no_swap) 350 { 351 int i; 352 int maxpart = getmaxpartitions(); 353 int sm; /* sectors in 1MB */ 354 struct ptn_size *p; 355 daddr_t size; 356 static int swap_created = 0, root_created = 0; 357 358 if (pm->pi.menu_no < 0) 359 pm->pi = (struct ptn_info) { -1, { 360 #define PI_ROOT 0 361 { PART_ROOT, { '/', '\0' }, 362 DEFROOTSIZE, DEFROOTSIZE , 0, 0}, 363 #define PI_SWAP 1 364 { PART_SWAP, { 's', 'w', 'a', 'p', '\0' }, 365 DEFSWAPSIZE, DEFSWAPSIZE, 0, 0 }, 366 { PART_TMP_RAMDISK, 367 #ifdef HAVE_TMPFS 368 { '/', 't', 'm', 'p', ' ', '(', 't', 'm', 'p', 'f', 's', ')', '\0' }, 369 #else 370 { '/', 't', 'm', 'p', ' ', '(', 'm', 'f', 's', ')', '\0' }, 371 #endif 372 64, 0, 0, 0 }, 373 #define PI_USR 3 374 { PART_USR, { '/', 'u', 's', 'r', '\0' }, DEFUSRSIZE, 375 0, 0, 0 }, 376 { PART_ANY, { '/', 'v', 'a', 'r', '\0' }, DEFVARSIZE, 377 0, 0, 0 }, 378 { PART_ANY, { '/', 'h', 'o', 'm', 'e', '\0' }, 0, 379 0, 0, 0 }, 380 }, { 381 { NULL, OPT_NOMENU, 0, set_ptn_size }, 382 { MSG_askunits, MENU_sizechoice, OPT_SUB, NULL }, 383 }, 0, 0, NULL, { 0 } }; 384 385 if (maxpart > MAXPARTITIONS) 386 maxpart = MAXPARTITIONS; /* sanity */ 387 388 msg_display(MSG_ptnsizes); 389 msg_table_add(MSG_ptnheaders); 390 391 if (pm->pi.menu_no < 0) { 392 /* If there is a swap partition elsewhere, don't add one here.*/ 393 if (no_swap || (swap_created && partman_go)) { 394 pm->pi.ptn_sizes[PI_SWAP].size = 0; 395 } else { 396 #if DEFSWAPSIZE == -1 397 /* Dynamic swap size. */ 398 pm->pi.ptn_sizes[PI_SWAP].dflt_size = get_ramsize(); 399 pm->pi.ptn_sizes[PI_SWAP].size = 400 pm->pi.ptn_sizes[PI_SWAP].dflt_size; 401 #endif 402 } 403 404 /* If installing X increase default size of /usr */ 405 if (set_X11_selected()) 406 pm->pi.ptn_sizes[PI_USR].dflt_size += XNEEDMB; 407 408 /* Start of planning to give free space to / */ 409 pm->pi.pool_part = &pm->pi.ptn_sizes[PI_ROOT]; 410 /* Make size of root include default size of /usr */ 411 pm->pi.ptn_sizes[PI_ROOT].size += pm->pi.ptn_sizes[PI_USR].dflt_size; 412 413 sm = MEG / pm->sectorsize; 414 415 if (root_limit != 0) { 416 /* Bah - bios can not read all the disk, limit root */ 417 pm->pi.ptn_sizes[PI_ROOT].limit = root_limit - part_start; 418 /* Allocate a /usr partition if bios can't read 419 * everything except swap. 420 */ 421 if (pm->pi.ptn_sizes[PI_ROOT].limit 422 < sectors - pm->pi.ptn_sizes[PI_SWAP].size * sm) { 423 /* Root won't be able to access all the space */ 424 /* Claw back space for /usr */ 425 pm->pi.ptn_sizes[PI_USR].size = 426 pm->pi.ptn_sizes[PI_USR].dflt_size; 427 pm->pi.ptn_sizes[PI_ROOT].size -= 428 pm->pi.ptn_sizes[PI_USR].dflt_size; 429 pm->pi.ptn_sizes[PI_ROOT].changed = 1; 430 /* Give free space to /usr */ 431 pm->pi.pool_part = &pm->pi.ptn_sizes[PI_USR]; 432 } 433 } 434 435 /* Change preset sizes from MB to sectors */ 436 pm->pi.free_space = sectors; 437 for (p = pm->pi.ptn_sizes; p->mount[0]; p++) { 438 p->size = NUMSEC(p->size, sm, pm->dlcylsize); 439 p->dflt_size = NUMSEC(p->dflt_size, sm, pm->dlcylsize); 440 pm->pi.free_space -= p->size; 441 } 442 443 /* Steal space from swap to make things fit.. */ 444 if (pm->pi.free_space < 0) { 445 i = roundup(-pm->pi.free_space, pm->dlcylsize); 446 if (i > pm->pi.ptn_sizes[PI_SWAP].size) 447 i = pm->pi.ptn_sizes[PI_SWAP].size; 448 pm->pi.ptn_sizes[PI_SWAP].size -= i; 449 pm->pi.free_space += i; 450 } 451 452 /* Add space for 2 system dumps to / (traditional) */ 453 i = get_ramsize() * sm; 454 i = roundup(i, pm->dlcylsize); 455 if (pm->pi.free_space > i * 2) 456 i *= 2; 457 if (pm->pi.free_space > i) { 458 pm->pi.ptn_sizes[PI_ROOT].size += i; 459 pm->pi.free_space -= i; 460 } 461 462 if (root_created && partman_go) { 463 pm->pi.ptn_sizes[PI_ROOT].size = 0; 464 pm->pi.pool_part = 0; 465 } 466 467 /* Ensure all of / is readable by the system boot code */ 468 i = pm->pi.ptn_sizes[PI_ROOT].limit; 469 if (i != 0 && (i -= pm->pi.ptn_sizes[PI_ROOT].size) < 0) { 470 pm->pi.ptn_sizes[PI_ROOT].size += i; 471 pm->pi.free_space -= i; 472 } 473 474 /* Count free partition slots */ 475 pm->pi.free_parts = 0; 476 for (i = 0; i < maxpart; i++) { 477 if (pm->bsdlabel[i].pi_size == 0) 478 pm->pi.free_parts++; 479 } 480 for (i = 0; i < MAXPARTITIONS; i++) { 481 p = &pm->pi.ptn_sizes[i]; 482 if (i != 0 && p->ptn_id == 0) 483 p->ptn_id = PART_EXTRA; 484 if (p->size != 0) 485 pm->pi.free_parts--; 486 } 487 488 pm->pi.menu_no = new_menu(0, pm->pi.ptn_menus, nelem(pm->pi.ptn_menus), 489 3, -1, 12, 70, 490 MC_ALWAYS_SCROLL | MC_NOBOX | MC_NOCLEAR, 491 NULL, set_ptn_titles, NULL, 492 "help", pm->pi.exit_msg); 493 494 if (pm->pi.menu_no < 0) 495 return; 496 } 497 498 do { 499 set_ptn_menu(&pm->pi); 500 pm->current_cylsize = pm->dlcylsize; 501 process_menu(pm->pi.menu_no, &pm->pi); 502 } while (pm->pi.free_space < 0 || pm->pi.free_parts < 0); 503 504 /* Give any cylinder fragment to last partition */ 505 if (pm->pi.pool_part != NULL || pm->pi.free_space < pm->dlcylsize) { 506 for (p = pm->pi.ptn_sizes + nelem(pm->pi.ptn_sizes) - 1; ;p--) { 507 if (p->size == 0) { 508 if (p == pm->pi.ptn_sizes) 509 break; 510 continue; 511 } 512 if (p->ptn_id == PART_TMP_RAMDISK) 513 continue; 514 p->size += pm->pi.free_space % pm->dlcylsize; 515 pm->pi.free_space -= pm->pi.free_space % pm->dlcylsize; 516 break; 517 } 518 } 519 520 for (p = pm->pi.ptn_sizes; p->mount[0]; p++, part_start += size) { 521 size = p->size; 522 if (p == pm->pi.pool_part) { 523 size += rounddown(pm->pi.free_space, pm->dlcylsize); 524 if (p->limit != 0 && size > p->limit) 525 size = p->limit; 526 } 527 i = p->ptn_id; 528 if (i == PART_TMP_RAMDISK) { 529 tmp_ramdisk_size = size; 530 size = 0; 531 continue; 532 } 533 if (size == 0) 534 continue; 535 if (i == PART_ROOT && size > 0) 536 root_created = 1; 537 if (i == PART_SWAP) { 538 if (size > 0) 539 swap_created = 1; 540 save_ptn(i, part_start, size, FS_SWAP, NULL); 541 continue; 542 } 543 if (!strcmp(p->mount, "raid")) { 544 save_ptn(i, part_start, size, FS_RAID, NULL); 545 continue; 546 } else if (!strcmp(p->mount, "cgd")) { 547 save_ptn(i, part_start, size, FS_CGD, NULL); 548 continue; 549 } 550 save_ptn(i, part_start, size, FS_BSDFFS, p->mount); 551 } 552 } 553 554 /* 555 * md back-end code for menu-driven BSD disklabel editor. 556 */ 557 int 558 make_bsd_partitions(void) 559 { 560 int i; 561 int part; 562 int maxpart = getmaxpartitions(); 563 daddr_t partstart; 564 int part_raw, part_bsd; 565 daddr_t ptend; 566 int no_swap = 0, valid_part = -1; 567 partinfo *p, savedlabel[MAXPARTITIONS]; 568 569 memcpy(&savedlabel, &pm->bsdlabel, sizeof savedlabel); 570 571 /* 572 * Initialize global variables that track space used on this disk. 573 * Standard 4.4BSD 8-partition labels always cover whole disk. 574 */ 575 if (pm->ptsize == 0) 576 pm->ptsize = pm->dlsize - pm->ptstart; 577 if (pm->dlsize == 0) 578 pm->dlsize = pm->ptstart + pm->ptsize; 579 if (logfp) fprintf(logfp, "dlsize=%" PRId64 " ptsize=%" PRId64 580 " ptstart=%" PRId64 "\n", 581 pm->dlsize, pm->ptsize, pm->ptstart); 582 583 partstart = pm->ptstart; 584 ptend = pm->ptstart + pm->ptsize; 585 586 /* Ask for layout type -- standard or special */ 587 if (partman_go == 0) { 588 msg_display(MSG_layout, 589 (int) (pm->ptsize / (MEG / pm->sectorsize)), 590 DEFROOTSIZE + DEFSWAPSIZE + DEFUSRSIZE, 591 DEFROOTSIZE + DEFSWAPSIZE + DEFUSRSIZE + XNEEDMB); 592 process_menu(MENU_layout, NULL); 593 } 594 595 /* Set so we use the 'real' geometry for rounding, input in MB */ 596 pm->current_cylsize = pm->dlcylsize; 597 set_sizemultname_meg(); 598 599 /* Build standard partitions */ 600 memset(&pm->bsdlabel, 0, sizeof pm->bsdlabel); 601 602 /* Set initial partition types to unused */ 603 for (part = 0 ; part < maxpart ; ++part) 604 pm->bsdlabel[part].pi_fstype = FS_UNUSED; 605 606 /* Whole disk partition */ 607 part_raw = getrawpartition(); 608 if (part_raw == -1) 609 part_raw = PART_C; /* for sanity... */ 610 pm->bsdlabel[part_raw].pi_offset = 0; 611 pm->bsdlabel[part_raw].pi_size = pm->dlsize; 612 613 if (part_raw == PART_D) { 614 /* Probably a system that expects an i386 style mbr */ 615 part_bsd = PART_C; 616 pm->bsdlabel[PART_C].pi_offset = pm->ptstart; 617 pm->bsdlabel[PART_C].pi_size = pm->ptsize; 618 } else { 619 part_bsd = part_raw; 620 } 621 622 #if defined(PART_BOOT) && defined(BOOT_SIZE) 623 i = BOOT_SIZE; 624 if (i >= 1024) { 625 /* Treat big numbers as a byte count */ 626 i = (i + pm->dlcylsize * pm->sectorsize - 1) / (pm->dlcylsize * pm->sectorsize); 627 i *= pm->dlcylsize; 628 } 629 #if defined(PART_BOOT_FFS) 630 pm->bsdlabel[PART_BOOT].pi_fstype = FS_BSDFFS; 631 pm->bsdlabel[PART_BOOT].pi_flags = PIF_NEWFS; 632 #else 633 pm->bsdlabel[PART_BOOT].pi_fstype = FS_BOOT; 634 #endif 635 pm->bsdlabel[PART_BOOT].pi_size = i; 636 #ifdef BOOT_HIGH 637 pm->bsdlabel[PART_BOOT].pi_offset = ptend - i; 638 ptend -= i; 639 #else 640 pm->bsdlabel[PART_BOOT].pi_offset = pm->ptstart; 641 partstart += i; 642 #endif 643 #elif defined(PART_BOOT) 644 if (pm->bootsize != 0) { 645 #if defined(PART_BOOT_MSDOS) 646 pm->bsdlabel[PART_BOOT].pi_fstype = FS_MSDOS; 647 #else 648 pm->bsdlabel[PART_BOOT].pi_fstype = FS_BOOT; 649 #endif 650 pm->bsdlabel[PART_BOOT].pi_size = pm->bootsize; 651 pm->bsdlabel[PART_BOOT].pi_offset = pm->bootstart; 652 #if defined(PART_BOOT_PI_FLAGS) 653 pm->bsdlabel[PART_BOOT].pi_flags |= PART_BOOT_PI_FLAGS; 654 #endif 655 #if defined(PART_BOOT_PI_MOUNT) 656 strlcpy(pm->bsdlabel[PART_BOOT].pi_mount, PART_BOOT_PI_MOUNT, 657 sizeof pm->bsdlabel[PART_BOOT].pi_mount); 658 #endif 659 } 660 #endif /* PART_BOOT w/o BOOT_SIZE */ 661 662 #if defined(PART_SYSVBFS) && defined(SYSVBFS_SIZE) 663 pm->bsdlabel[PART_SYSVBFS].pi_offset = partstart; 664 pm->bsdlabel[PART_SYSVBFS].pi_fstype = FS_SYSVBFS; 665 pm->bsdlabel[PART_SYSVBFS].pi_size = SYSVBFS_SIZE; 666 pm->bsdlabel[PART_SYSVBFS].pi_flags |= PIF_NEWFS | PIF_MOUNT; 667 strlcpy(pm->bsdlabel[PART_SYSVBFS].pi_mount, "/stand", 668 sizeof pm->bsdlabel[PART_SYSVBFS].pi_mount); 669 partstart += SYSVBFS_SIZE; 670 #endif 671 672 #ifdef PART_REST 673 pm->bsdlabel[PART_REST].pi_offset = 0; 674 pm->bsdlabel[PART_REST].pi_size = pm->ptstart; 675 #endif 676 677 if (layoutkind == LY_USEEXIST) { 678 /* 679 * If 'pm->oldlabel' is a default label created by the kernel it 680 * will have exactly one valid partition besides raw_part 681 * which covers the whole disk - but might lie outside the 682 * mbr partition we (by now) have offset by a few sectors. 683 * Check for this and and fix ut up. 684 */ 685 valid_part = -1; 686 for (i = 0; i < maxpart; i++) { 687 if (i == part_raw) 688 continue; 689 if (pm->oldlabel[i].pi_size > 0 && PI_ISBSDFS(&pm->oldlabel[i])) { 690 if (valid_part >= 0) { 691 /* nope, not the default case */ 692 valid_part = -1; 693 break; 694 } 695 valid_part = i; 696 } 697 } 698 if (valid_part >= 0 && pm->oldlabel[valid_part].pi_offset < pm->ptstart) { 699 pm->oldlabel[valid_part].pi_offset = pm->ptstart; 700 pm->oldlabel[valid_part].pi_size -= pm->ptstart; 701 } 702 } 703 704 /* 705 * Save any partitions that are outside the area we are 706 * going to use. 707 * In particular this saves details of the other MBR 708 * partitions on a multiboot i386 system. 709 */ 710 for (i = maxpart; i--;) { 711 if (pm->bsdlabel[i].pi_size != 0) 712 /* Don't overwrite special partitions */ 713 continue; 714 p = &pm->oldlabel[i]; 715 if (p->pi_fstype == FS_UNUSED || p->pi_size == 0) 716 continue; 717 if (layoutkind == LY_USEEXIST) { 718 if (PI_ISBSDFS(p)) { 719 p->pi_flags |= PIF_MOUNT; 720 if (layoutkind == LY_USEEXIST && i == valid_part) { 721 int fstype = p->pi_fstype; 722 p->pi_fstype = 0; 723 strcpy(p->pi_mount, "/"); 724 set_ptype(p, fstype, PIF_NEWFS); 725 } 726 } 727 } else { 728 if (p->pi_offset < pm->ptstart + pm->ptsize && 729 p->pi_offset + p->pi_size > pm->ptstart) 730 /* Not outside area we are allocating */ 731 continue; 732 if (p->pi_fstype == FS_SWAP) 733 no_swap = 1; 734 } 735 pm->bsdlabel[i] = pm->oldlabel[i]; 736 } 737 738 if (layoutkind == LY_SETNEW) 739 get_ptn_sizes(partstart, ptend - partstart, no_swap); 740 741 else if (layoutkind == LY_NEWRAID) { 742 set_ptype(&(pm->bsdlabel[PART_E]), FS_RAID, 0); 743 pm->bsdlabel[PART_E].pi_size = pm->ptsize; 744 } 745 else if (layoutkind == LY_NEWCGD) { 746 set_ptype(&(pm->bsdlabel[PART_E]), FS_CGD, 0); 747 pm->bsdlabel[PART_E].pi_size = pm->ptsize; 748 } 749 else if (layoutkind == LY_NEWLVM) { 750 set_ptype(&(pm->bsdlabel[PART_E]), FS_BSDFFS, 0); 751 pm->bsdlabel[PART_E].pi_size = pm->ptsize; 752 pm->bsdlabel[PART_E].lvmpv = 1; 753 } 754 755 /* 756 * OK, we have a partition table. Give the user the chance to 757 * edit it and verify it's OK, or abort altogether. 758 */ 759 do { 760 if (edit_and_check_label(pm->bsdlabel, maxpart, part_raw, part_bsd) == 0) { 761 msg_display(MSG_abort); 762 memcpy(&pm->bsdlabel, &savedlabel, sizeof pm->bsdlabel); 763 return 0; 764 } 765 } while (partman_go == 0 && check_partitions() == 0); 766 767 /* Disk name */ 768 if (!partman_go) 769 msg_prompt(MSG_packname, pm->bsddiskname, pm->bsddiskname, 770 sizeof pm->bsddiskname); 771 772 /* save label to disk for MI code to update. */ 773 if (! partman_go) 774 (void) savenewlabel(pm->bsdlabel, maxpart); 775 776 /* Everything looks OK. */ 777 return (1); 778 } 779 780 /* 781 * check that there is at least a / somewhere. 782 */ 783 int 784 check_partitions(void) 785 { 786 #ifdef HAVE_BOOTXX_xFS 787 int rv = 1; 788 char *bootxx; 789 #endif 790 #ifndef HAVE_UFS2_BOOT 791 int fstype; 792 #endif 793 794 #ifdef HAVE_BOOTXX_xFS 795 /* check if we have boot code for the root partition type */ 796 bootxx = bootxx_name(); 797 if (bootxx != NULL) { 798 rv = access(bootxx, R_OK); 799 free(bootxx); 800 } else 801 rv = -1; 802 if (rv != 0) { 803 process_menu(MENU_ok, deconst(MSG_No_Bootcode)); 804 return 0; 805 } 806 #endif 807 #ifndef HAVE_UFS2_BOOT 808 fstype = pm->bsdlabel[pm->rootpart].pi_fstype; 809 if (fstype == FS_BSDFFS && 810 (pm->bsdlabel[pm->rootpart].pi_flags & PIF_FFSv2) != 0) { 811 process_menu(MENU_ok, deconst(MSG_cannot_ufs2_root)); 812 return 0; 813 } 814 #endif 815 816 return md_check_partitions(); 817 } 818