1 /* $NetBSD: bsddisklabel.c,v 1.4 2018/06/03 13:16:30 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 if (pm && pm->no_part) 570 return 1; 571 572 memcpy(&savedlabel, &pm->bsdlabel, sizeof savedlabel); 573 574 /* 575 * Initialize global variables that track space used on this disk. 576 * Standard 4.4BSD 8-partition labels always cover whole disk. 577 */ 578 if (pm->ptsize == 0) 579 pm->ptsize = pm->dlsize - pm->ptstart; 580 if (pm->dlsize == 0) 581 pm->dlsize = pm->ptstart + pm->ptsize; 582 if (logfp) fprintf(logfp, "dlsize=%" PRId64 " ptsize=%" PRId64 583 " ptstart=%" PRId64 "\n", 584 pm->dlsize, pm->ptsize, pm->ptstart); 585 586 partstart = pm->ptstart; 587 ptend = pm->ptstart + pm->ptsize; 588 589 /* Ask for layout type -- standard or special */ 590 if (partman_go == 0) { 591 msg_display(MSG_layout, 592 (int) (pm->ptsize / (MEG / pm->sectorsize)), 593 DEFROOTSIZE + DEFSWAPSIZE + DEFUSRSIZE, 594 DEFROOTSIZE + DEFSWAPSIZE + DEFUSRSIZE + XNEEDMB); 595 process_menu(MENU_layout, NULL); 596 } 597 598 /* Set so we use the 'real' geometry for rounding, input in MB */ 599 pm->current_cylsize = pm->dlcylsize; 600 set_sizemultname_meg(); 601 602 /* Build standard partitions */ 603 memset(&pm->bsdlabel, 0, sizeof pm->bsdlabel); 604 605 /* Set initial partition types to unused */ 606 for (part = 0 ; part < maxpart ; ++part) 607 pm->bsdlabel[part].pi_fstype = FS_UNUSED; 608 609 /* Whole disk partition */ 610 part_raw = getrawpartition(); 611 if (part_raw == -1) 612 part_raw = PART_C; /* for sanity... */ 613 pm->bsdlabel[part_raw].pi_offset = 0; 614 pm->bsdlabel[part_raw].pi_size = pm->dlsize; 615 616 if (part_raw == PART_D) { 617 /* Probably a system that expects an i386 style mbr */ 618 part_bsd = PART_C; 619 pm->bsdlabel[PART_C].pi_offset = pm->ptstart; 620 pm->bsdlabel[PART_C].pi_size = pm->ptsize; 621 } else { 622 part_bsd = part_raw; 623 } 624 625 #if defined(PART_BOOT) && defined(BOOT_SIZE) 626 i = BOOT_SIZE; 627 if (i >= 1024) { 628 /* Treat big numbers as a byte count */ 629 i = (i + pm->dlcylsize * pm->sectorsize - 1) / (pm->dlcylsize * pm->sectorsize); 630 i *= pm->dlcylsize; 631 } 632 #if defined(PART_BOOT_FFS) 633 pm->bsdlabel[PART_BOOT].pi_fstype = FS_BSDFFS; 634 pm->bsdlabel[PART_BOOT].pi_flags = PIF_NEWFS; 635 #else 636 pm->bsdlabel[PART_BOOT].pi_fstype = FS_BOOT; 637 #endif 638 pm->bsdlabel[PART_BOOT].pi_size = i; 639 #ifdef BOOT_HIGH 640 pm->bsdlabel[PART_BOOT].pi_offset = ptend - i; 641 ptend -= i; 642 #else 643 pm->bsdlabel[PART_BOOT].pi_offset = pm->ptstart; 644 partstart += i; 645 #endif 646 #elif defined(PART_BOOT) 647 if (pm->bootsize != 0) { 648 #if defined(PART_BOOT_MSDOS) 649 pm->bsdlabel[PART_BOOT].pi_fstype = FS_MSDOS; 650 #else 651 pm->bsdlabel[PART_BOOT].pi_fstype = FS_BOOT; 652 #endif 653 pm->bsdlabel[PART_BOOT].pi_size = pm->bootsize; 654 pm->bsdlabel[PART_BOOT].pi_offset = pm->bootstart; 655 #if defined(PART_BOOT_PI_FLAGS) 656 pm->bsdlabel[PART_BOOT].pi_flags |= PART_BOOT_PI_FLAGS; 657 #endif 658 #if defined(PART_BOOT_PI_MOUNT) 659 strlcpy(pm->bsdlabel[PART_BOOT].pi_mount, PART_BOOT_PI_MOUNT, 660 sizeof pm->bsdlabel[PART_BOOT].pi_mount); 661 #endif 662 } 663 #endif /* PART_BOOT w/o BOOT_SIZE */ 664 665 #if defined(PART_SYSVBFS) && defined(SYSVBFS_SIZE) 666 pm->bsdlabel[PART_SYSVBFS].pi_offset = partstart; 667 pm->bsdlabel[PART_SYSVBFS].pi_fstype = FS_SYSVBFS; 668 pm->bsdlabel[PART_SYSVBFS].pi_size = SYSVBFS_SIZE; 669 pm->bsdlabel[PART_SYSVBFS].pi_flags |= PIF_NEWFS | PIF_MOUNT; 670 strlcpy(pm->bsdlabel[PART_SYSVBFS].pi_mount, "/stand", 671 sizeof pm->bsdlabel[PART_SYSVBFS].pi_mount); 672 partstart += SYSVBFS_SIZE; 673 #endif 674 675 #ifdef PART_REST 676 pm->bsdlabel[PART_REST].pi_offset = 0; 677 pm->bsdlabel[PART_REST].pi_size = pm->ptstart; 678 #endif 679 680 if (layoutkind == LY_USEEXIST) { 681 /* 682 * If 'pm->oldlabel' is a default label created by the kernel it 683 * will have exactly one valid partition besides raw_part 684 * which covers the whole disk - but might lie outside the 685 * mbr partition we (by now) have offset by a few sectors. 686 * Check for this and and fix ut up. 687 */ 688 valid_part = -1; 689 for (i = 0; i < maxpart; i++) { 690 if (i == part_raw) 691 continue; 692 if (pm->oldlabel[i].pi_size > 0 && PI_ISBSDFS(&pm->oldlabel[i])) { 693 if (valid_part >= 0) { 694 /* nope, not the default case */ 695 valid_part = -1; 696 break; 697 } 698 valid_part = i; 699 } 700 } 701 if (valid_part >= 0 && pm->oldlabel[valid_part].pi_offset < pm->ptstart) { 702 pm->oldlabel[valid_part].pi_offset = pm->ptstart; 703 pm->oldlabel[valid_part].pi_size -= pm->ptstart; 704 } 705 } 706 707 /* 708 * Save any partitions that are outside the area we are 709 * going to use. 710 * In particular this saves details of the other MBR 711 * partitions on a multiboot i386 system. 712 */ 713 for (i = maxpart; i--;) { 714 if (pm->bsdlabel[i].pi_size != 0) 715 /* Don't overwrite special partitions */ 716 continue; 717 p = &pm->oldlabel[i]; 718 if (p->pi_fstype == FS_UNUSED || p->pi_size == 0) 719 continue; 720 if (layoutkind == LY_USEEXIST) { 721 if (PI_ISBSDFS(p)) { 722 p->pi_flags |= PIF_MOUNT; 723 if (layoutkind == LY_USEEXIST && i == valid_part) { 724 int fstype = p->pi_fstype; 725 p->pi_fstype = 0; 726 strcpy(p->pi_mount, "/"); 727 set_ptype(p, fstype, PIF_NEWFS); 728 } 729 } 730 } else { 731 if (p->pi_offset < pm->ptstart + pm->ptsize && 732 p->pi_offset + p->pi_size > pm->ptstart) 733 /* Not outside area we are allocating */ 734 continue; 735 if (p->pi_fstype == FS_SWAP) 736 no_swap = 1; 737 } 738 pm->bsdlabel[i] = pm->oldlabel[i]; 739 } 740 741 if (layoutkind == LY_SETNEW) 742 get_ptn_sizes(partstart, ptend - partstart, no_swap); 743 744 else if (layoutkind == LY_NEWRAID) { 745 set_ptype(&(pm->bsdlabel[PART_E]), FS_RAID, 0); 746 pm->bsdlabel[PART_E].pi_size = pm->ptsize; 747 } 748 else if (layoutkind == LY_NEWCGD) { 749 set_ptype(&(pm->bsdlabel[PART_E]), FS_CGD, 0); 750 pm->bsdlabel[PART_E].pi_size = pm->ptsize; 751 } 752 else if (layoutkind == LY_NEWLVM) { 753 set_ptype(&(pm->bsdlabel[PART_E]), FS_BSDFFS, 0); 754 pm->bsdlabel[PART_E].pi_size = pm->ptsize; 755 pm->bsdlabel[PART_E].lvmpv = 1; 756 } 757 758 /* 759 * OK, we have a partition table. Give the user the chance to 760 * edit it and verify it's OK, or abort altogether. 761 */ 762 do { 763 if (edit_and_check_label(pm->bsdlabel, maxpart, part_raw, part_bsd) == 0) { 764 msg_display(MSG_abort); 765 memcpy(&pm->bsdlabel, &savedlabel, sizeof pm->bsdlabel); 766 return 0; 767 } 768 } while (partman_go == 0 && check_partitions() == 0); 769 770 /* Disk name */ 771 if (!partman_go) 772 msg_prompt(MSG_packname, pm->bsddiskname, pm->bsddiskname, 773 sizeof pm->bsddiskname); 774 775 /* save label to disk for MI code to update. */ 776 if (! partman_go) 777 (void) savenewlabel(pm->bsdlabel, maxpart); 778 779 /* Everything looks OK. */ 780 return (1); 781 } 782 783 /* 784 * check that there is at least a / somewhere. 785 */ 786 int 787 check_partitions(void) 788 { 789 #ifdef HAVE_BOOTXX_xFS 790 int rv = 1; 791 char *bootxx; 792 #endif 793 #ifndef HAVE_UFS2_BOOT 794 int fstype; 795 #endif 796 797 #ifdef HAVE_BOOTXX_xFS 798 /* check if we have boot code for the root partition type */ 799 bootxx = bootxx_name(); 800 if (bootxx != NULL) { 801 rv = access(bootxx, R_OK); 802 free(bootxx); 803 } else 804 rv = -1; 805 if (rv != 0) { 806 process_menu(MENU_ok, __UNCONST(MSG_No_Bootcode)); 807 return 0; 808 } 809 #endif 810 #ifndef HAVE_UFS2_BOOT 811 fstype = pm->bsdlabel[pm->rootpart].pi_fstype; 812 if (fstype == FS_BSDFFS && 813 (pm->bsdlabel[pm->rootpart].pi_flags & PIF_FFSv2) != 0) { 814 process_menu(MENU_ok, __UNCONST(MSG_cannot_ufs2_root)); 815 return 0; 816 } 817 #endif 818 819 return md_check_partitions(); 820 } 821