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