1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 * 21 * 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 * 25 * Copyright 2014 Andrew Stormont. 26 */ 27 28 /* 29 * rmf_slice.c : 30 * This file contains the functions for parsing a slice file 31 * for rmformat. 32 */ 33 34 #include <sys/types.h> 35 #include <ctype.h> 36 #include <sys/vtoc.h> 37 #include <stdlib.h> 38 #include <unistd.h> 39 #include <string.h> 40 #include <fcntl.h> 41 #include <errno.h> 42 #include <memory.h> 43 #include <dirent.h> 44 #include <sys/fcntl.h> 45 #include <sys/param.h> 46 #include <sys/stat.h> 47 #include <stdio.h> 48 #include <sys/dkio.h> 49 #include <priv_utils.h> 50 #include "rmformat.h" 51 52 extern void my_perror(char *err_string); 53 54 static int32_t last_token_type = 0; 55 #define spc() (last_token_type) 56 57 58 /* 59 * This global is used to store the current line # in the 60 * data file. It must be global because the I/O routines 61 * are allowed to side effect it to keep track of backslashed 62 * newlines. 63 */ 64 65 static int32_t data_lineno; /* current line # in data file */ 66 67 #define CHG_MODE_UNDEFINED (-1) /* undefined value */ 68 #define CHG_MODE_SET 0 /* set bits by or'ing */ 69 #define CHG_MODE_CLR 1 /* clr bits by and'ing */ 70 #define CHG_MODE_ABS 2 /* set absolute value */ 71 72 73 #define TOKEN_SIZE 36 /* max length of a token */ 74 typedef char TOKEN[TOKEN_SIZE+1]; /* token type */ 75 #define DATA_INPUT 0 /* 2 modes of input */ 76 #define CMD_INPUT 1 77 #define WILD_STRING "$" /* wildcard character */ 78 #define COMMENT_CHAR '#' /* comment character */ 79 80 /* 81 * List of strings with arbitrary matching values 82 */ 83 typedef struct slist { 84 char *str; 85 char *help; 86 int32_t value; 87 } slist_t; 88 89 static slist_t ptag_choices[] = { 90 { "unassigned", "", V_UNASSIGNED }, 91 { "boot", "", V_BOOT }, 92 { "root", "", V_ROOT }, 93 { "swap", "", V_SWAP }, 94 { "usr", "", V_USR }, 95 { "backup", "", V_BACKUP }, 96 { "stand", "", V_STAND }, 97 { "var", "", V_VAR }, 98 { "home", "", V_HOME }, 99 { "alternates", "", V_ALTSCTR }, 100 { NULL } 101 }; 102 103 104 /* 105 * Choices for the p_flag vtoc field 106 */ 107 static slist_t pflag_choices[] = { 108 { "wm", "read-write, mountable", 0 }, 109 { "wu", "read-write, unmountable", V_UNMNT }, 110 { "rm", "read-only, mountable", V_RONLY }, 111 { "ru", "read-only, unmountable", V_RONLY|V_UNMNT }, 112 { NULL } 113 }; 114 115 /* 116 * The definitions are the token types that the data file parser recognizes. 117 */ 118 #define SUP_EOF -1 /* eof token */ 119 #define SUP_STRING 0 /* string token */ 120 #define SUP_EQL 1 /* equals token */ 121 #define SUP_COMMA 2 /* comma token */ 122 #define SUP_COLON 3 /* colon token */ 123 #define SUP_EOL 4 /* newline token */ 124 #define SUP_OR 5 /* vertical bar */ 125 #define SUP_AND 6 /* ampersand */ 126 #define SUP_TILDE 7 /* tilde */ 127 128 129 /* 130 * Prototypes for ANSI C compilers 131 */ 132 static int32_t sup_prxfile(char *file_name, struct extvtoc *vt); 133 static int32_t sup_setpart(struct extvtoc *vt); 134 static void sup_pushchar(int32_t c); 135 static void clean_token(char *cleantoken, char *token); 136 static void clean_token(char *cleantoken, char *token); 137 static int32_t sup_inputchar(); 138 static int32_t sup_gettoken(char *buf); 139 static int32_t sup_get_token(char *buf); 140 static int32_t find_value(slist_t *slist, char *str, int32_t *value); 141 static int32_t check_vtoc_sanity(smedia_handle_t, int32_t fd, 142 struct extvtoc *vt); 143 static uint64_t str2sector(char *str); 144 static int32_t strcnt(char *s1, char *s2); 145 static int32_t get_fdisk(smedia_handle_t, int32_t fd, int32_t offset, 146 struct fdisk_info *fdisk); 147 static void erase(smedia_handle_t handle, diskaddr_t offset, diskaddr_t size); 148 149 extern char *myname; 150 extern uint64_t my_atoll(char *ptr); 151 extern smmedium_prop_t med_info; 152 153 static FILE *data_file; 154 155 static int32_t 156 sup_prxfile(char *file_name, struct extvtoc *vt) 157 { 158 int32_t status, ret_val; 159 TOKEN token; 160 TOKEN cleaned; 161 162 /* 163 * Open the data file. Return 0 if unable to do so. 164 */ 165 data_file = fopen(file_name, "r"); 166 if (data_file == NULL) { 167 PERROR("Open failed"); 168 return (-1); 169 } 170 /* 171 * Step through the data file a meta-line at a time. There are 172 * typically several backslashed newlines in each meta-line, 173 * so data_lineno will be getting side effected along the way. 174 */ 175 data_lineno = 1; 176 for (;;) { 177 178 /* 179 * Get the keyword. 180 */ 181 status = sup_gettoken(token); 182 /* 183 * If we hit the end of the data file, we're done. 184 */ 185 if (status == SUP_EOF) 186 break; 187 /* 188 * If the line starts with some key character, it's an error. 189 */ 190 if (status != SUP_STRING) { 191 (void) fprintf(stderr, 192 gettext("Expecting keyword, found '%s'"), 193 token); 194 (void) fprintf(stderr, 195 gettext("Line no %d\n"), data_lineno); 196 continue; 197 } 198 /* 199 * Clean up the token and see which keyword it is. Call 200 * the appropriate routine to process the rest of the line. 201 */ 202 clean_token(cleaned, token); 203 if (strcmp(cleaned, "slices") == 0) { 204 ret_val = sup_setpart(vt); 205 (void) fclose(data_file); 206 return (ret_val); 207 } else { 208 (void) fprintf(stderr, gettext("Unknown keyword '%s'"), 209 cleaned); 210 (void) fprintf(stderr, 211 gettext("Line no %d\n"), data_lineno); 212 (void) fclose(data_file); 213 return (-1); 214 } 215 } 216 /* 217 * Close the data file. 218 */ 219 (void) fclose(data_file); 220 221 (void) fprintf(stderr, 222 gettext("Unexpected end of file (line no %d)\n"), data_lineno); 223 return (-1); 224 } 225 226 static int32_t 227 sup_gettoken(char *buf) 228 { 229 /* 230 * Skip end of lines and blank lines. 231 */ 232 while ((last_token_type = sup_get_token(buf)) == SUP_EOL) 233 ; 234 return (last_token_type); 235 } 236 237 static int32_t 238 sup_get_token(char *buf) 239 { 240 char *ptr = buf; 241 int32_t c, quoted = 0; 242 243 /* 244 * Was an end of file detected last try? 245 */ 246 247 if (feof(data_file)) { 248 return (SUP_EOF); 249 } 250 251 /* 252 * Zero out the returned token buffer 253 */ 254 255 bzero(buf, TOKEN_SIZE + 1); 256 257 /* 258 * Strip off leading white-space. 259 */ 260 while (isspace(c = sup_inputchar())) 261 ; 262 263 /* 264 * Only white spaces and then end of file? 265 */ 266 267 if (feof(data_file)) { 268 return (SUP_EOF); 269 } 270 271 /* 272 * Read in characters until we hit unquoted white-space. 273 */ 274 for (; !isspace(c) || quoted; c = sup_inputchar()) { 275 276 /* 277 * If we hit eof, check if we have anything in buffer. 278 * if we have, return STRING, next time we will return EOF 279 * else, return EOF here...should not happen. 280 */ 281 if (feof(data_file)) { 282 if (ptr - buf > 0) { 283 return (SUP_STRING); 284 } else { 285 return (SUP_EOF); 286 } 287 } 288 289 /* 290 * If we hit a double quote, change the state of quoting. 291 */ 292 if (c == '"') { 293 quoted = !quoted; 294 continue; 295 } 296 /* 297 * If we hit a newline, that delimits a token. 298 */ 299 if (c == '\n') 300 break; 301 /* 302 * If we hit any nonquoted special delimiters, that delimits 303 * a token. 304 */ 305 if (!quoted && (c == '=' || c == ',' || c == ':' || 306 c == '#' || c == '|' || c == '&' || c == '~')) 307 break; 308 /* 309 * Store the character if there's room left. 310 */ 311 if (ptr - buf < TOKEN_SIZE) 312 *ptr++ = (char)c; 313 } 314 /* 315 * If we stored characters in the buffer, then we inputted a string. 316 * Push the delimiter back into the pipe and return the string. 317 */ 318 if (ptr - buf > 0) { 319 sup_pushchar(c); 320 return (SUP_STRING); 321 } 322 /* 323 * We didn't input a string, so we must have inputted a known delimiter. 324 * store the delimiter in the buffer, so it will get returned. 325 */ 326 buf[0] = c; 327 /* 328 * Switch on the delimiter. Return the appropriate value for each one. 329 */ 330 switch (c) { 331 case '=': 332 return (SUP_EQL); 333 case ':': 334 return (SUP_COLON); 335 case ',': 336 return (SUP_COMMA); 337 case '\n': 338 return (SUP_EOL); 339 case '|': 340 return (SUP_OR); 341 case '&': 342 return (SUP_AND); 343 case '~': 344 return (SUP_TILDE); 345 case '#': 346 /* 347 * For comments, we flush out the rest of the line and return 348 * an eol. 349 */ 350 while ((c = sup_inputchar()) != '\n' && !feof(data_file)) 351 ; 352 if (feof(data_file)) 353 return (SUP_EOF); 354 else 355 return (SUP_EOL); 356 /* 357 * Shouldn't ever get here. 358 */ 359 default: 360 return (SUP_STRING); 361 } 362 } 363 static int32_t 364 sup_inputchar() 365 { 366 int32_t c; 367 368 /* 369 * Input the character. 370 */ 371 c = getc(data_file); 372 /* 373 * If it's not a backslash, return it. 374 */ 375 376 /* 377 * It was a backslash. Get the next character. 378 */ 379 380 if (c == '\\') 381 c = getc(data_file); 382 383 /* 384 * If it was a newline, update the line counter and get the next 385 * character. 386 */ 387 if (c == '\n') { 388 data_lineno++; 389 } 390 /* 391 * Return the character. 392 */ 393 return (c); 394 } 395 396 static void 397 sup_pushchar(int32_t c) 398 { 399 400 (void) ungetc(c, data_file); 401 if (c == '\n') 402 data_lineno--; 403 } 404 405 static void 406 clean_token(char *cleantoken, char *token) 407 { 408 char *ptr; 409 410 /* 411 * Strip off leading white-space. 412 */ 413 for (ptr = token; isspace(*ptr) && (ptr <= 414 (token + strlen(token) - 1)); ptr++) 415 ; 416 417 /* 418 * Copy it into the clean buffer. 419 */ 420 (void) strcpy(cleantoken, ptr); 421 /* 422 * Strip off trailing white-space. 423 */ 424 for (ptr = cleantoken + strlen(cleantoken) - 1; 425 isspace(*ptr) && (ptr >= cleantoken); ptr--) { 426 *ptr = '\0'; 427 } 428 } 429 430 static int32_t 431 sup_setpart(struct extvtoc *vt) 432 { 433 TOKEN token, cleaned, ident; 434 int32_t i, index, status; 435 uint64_t val1, val2; 436 ushort_t vtoc_tag = 0xFFFF; 437 ushort_t vtoc_flag = 0xFFFF; 438 439 /* 440 * Pull in some grammar. 441 */ 442 443 status = sup_gettoken(token); 444 445 if (status != SUP_COLON) { 446 (void) fprintf(stderr, 447 gettext("Expecting ':', found '%s'"), token); 448 (void) fprintf(stderr, 449 gettext("Line no %d\n"), data_lineno); 450 return (-1); 451 } 452 453 for (;;) { 454 status = sup_gettoken(token); 455 if (status != SUP_STRING) { 456 (void) fprintf(stderr, 457 gettext("Expecting string, found '%s'"), token); 458 (void) fprintf(stderr, 459 gettext("Line no %d\n"), data_lineno); 460 return (-1); 461 } 462 clean_token(ident, token); 463 /* 464 * Here's the index of the partition we're dealing with 465 */ 466 index = (int32_t)my_atoll(ident); 467 if ((index < 0) || (index >= NDKMAP)) { 468 (void) fprintf(stderr, 469 gettext("Unknown partition %d"), index); 470 (void) fprintf(stderr, 471 gettext("Line no %d\n"), data_lineno); 472 return (-1); 473 } 474 /* 475 * Check for floppy and PCMCIA_MEM cards. 476 * for floppy, the partition no. can be 0 1 2. 477 * for PCMCIA, the partition no. can be 2 478 */ 479 if (med_info.sm_media_type == SM_FLOPPY) { 480 if ((index < 0) || (index > 2)) { 481 (void) fprintf(stderr, gettext( 482 "Floppy can have partitions 0 1 and 2\n")); 483 return (-1); 484 } 485 } 486 if (med_info.sm_media_type == SM_PCMCIA_MEM) { 487 if (index != 2) { 488 (void) fprintf(stderr, gettext( 489 "PCMCIA Memory cards can have partition 2 only.\n")); 490 return (-1); 491 } 492 } 493 494 DPRINTF1("\n Partition %d: ", index); 495 496 status = sup_gettoken(token); 497 if (status != SUP_EQL) { 498 (void) fprintf(stderr, 499 gettext("Expecting '=', found '%s'"), token); 500 (void) fprintf(stderr, 501 gettext("Line no %d\n"), data_lineno); 502 return (-1); 503 504 } 505 506 507 status = sup_gettoken(token); 508 /* 509 * If we hit a key character, it's an error. 510 */ 511 if (status != SUP_STRING) { 512 (void) fprintf(stderr, 513 gettext("Expecting value, found '%s'"), token); 514 (void) fprintf(stderr, 515 gettext("Line no %d\n"), data_lineno); 516 return (-1); 517 } 518 clean_token(cleaned, token); 519 /* 520 * <tag> may be one of: boot, root, swap, etc. 521 * <flag> consists of two characters: 522 * W (writable) or R (read-only) 523 * M (mountable) or U (unmountable) 524 * 525 * Start with the defaults assigned above: 526 */ 527 528 /* 529 * All other attributes have a pair of numeric values. 530 * Convert the first value to a number. This value 531 * is the starting cylinder number of the partition. 532 */ 533 534 /* Check for valid partition, e.g. > 8 or 16 */ 535 val1 = str2sector(cleaned); 536 if (val1 == -1) { 537 (void) fprintf(stderr, 538 gettext("Invalid partition beggining %s \n"), 539 cleaned); 540 (void) fprintf(stderr, 541 gettext("Line no %d\n"), data_lineno); 542 } 543 544 DPRINTF1(" begins %s", cleaned); 545 /* 546 * Pull in some grammar. 547 */ 548 status = sup_gettoken(token); 549 if (status != SUP_COMMA) { 550 (void) fprintf(stderr, 551 gettext("Expecting ', ', found '%s'"), token); 552 (void) fprintf(stderr, 553 gettext("Line no %d\n"), data_lineno); 554 return (-1); 555 } 556 /* 557 * Pull in the second value. 558 */ 559 status = sup_gettoken(token); 560 if (status != SUP_STRING) { 561 (void) fprintf(stderr, 562 gettext("Expecting value, found '%s'"), token); 563 (void) fprintf(stderr, 564 gettext("Line no %d\n"), data_lineno); 565 return (-1); 566 } 567 clean_token(cleaned, token); 568 569 val2 = str2sector(cleaned); 570 if (val2 == -1) { 571 (void) fprintf(stderr, 572 gettext("Invalid partition size %s \n"), 573 cleaned); 574 (void) fprintf(stderr, 575 gettext("Line no %d\n"), data_lineno); 576 } 577 DPRINTF1(" ends %s ", cleaned); 578 579 /* 580 * Pull in some grammar. 581 */ 582 status = sup_gettoken(token); 583 584 if (status == SUP_COMMA) { 585 /* tags and flags */ 586 status = sup_gettoken(token); 587 if (status != SUP_STRING) { 588 (void) fprintf(stderr, 589 gettext("Expecting value, found '%s'"), 590 token); 591 (void) fprintf(stderr, 592 gettext("Line no %d\n"), data_lineno); 593 return (-1); 594 } 595 clean_token(cleaned, token); 596 if (find_value(pflag_choices, cleaned, &i) == 1) { 597 /* 598 * Found valid tag. Use it and advance parser 599 */ 600 DPRINTF1(" flag = %s", cleaned); 601 vtoc_flag = (ushort_t)i; 602 status = sup_gettoken(token); 603 } else if (find_value(ptag_choices, cleaned, &i) == 1) { 604 DPRINTF1(" tag = %s", cleaned); 605 vtoc_tag = (ushort_t)i; 606 status = sup_gettoken(token); 607 if (status == SUP_COMMA) { 608 (void) fprintf(stderr, 609 gettext("Expecting : got %s\n"), 610 token); 611 (void) fprintf(stderr, 612 gettext("Line no %d\n"), 613 data_lineno); 614 return (-1); 615 } 616 } else { 617 (void) fprintf(stderr, 618 gettext("Invalid flag or tag\n")); 619 (void) fprintf(stderr, 620 gettext("Line no %d\n"), data_lineno); 621 return (-1); 622 } 623 624 625 if (status == SUP_COMMA) { 626 /* Can be tag only */ 627 628 status = sup_gettoken(token); 629 if (status != SUP_STRING) { 630 (void) fprintf(stderr, 631 gettext("Expecting value" 632 ", found '%s'"), 633 token); 634 (void) fprintf(stderr, 635 gettext("Line no %d\n"), 636 data_lineno); 637 return (-1); 638 } 639 640 clean_token(cleaned, token); 641 if (find_value(ptag_choices, 642 cleaned, &i) == 1) { 643 DPRINTF1(" tag = %s", cleaned); 644 vtoc_tag = (ushort_t)i; 645 } 646 status = sup_gettoken(token); 647 } 648 } 649 650 /* 651 * Fill in the appropriate map entry with the values. 652 */ 653 vt->v_part[index].p_start = val1; 654 vt->v_part[index].p_size = val2; 655 if (vtoc_tag != 0xFFFF) { 656 vt->v_part[index].p_tag = vtoc_tag; 657 vtoc_tag = 0xFFFF; 658 } 659 if (vtoc_flag != 0xFFFF) { 660 vt->v_part[index].p_flag = vtoc_flag; 661 vtoc_flag = 0xFFFF; 662 } 663 if (status == SUP_EOF) { 664 DPRINTF("\nEnd of file\n"); 665 break; 666 } 667 if (status != SUP_COLON) { 668 (void) fprintf(stderr, 669 gettext("Expecting ':', found '%s'"), token); 670 (void) fprintf(stderr, 671 gettext("Line no %d\n"), data_lineno); 672 return (-1); 673 } 674 675 } 676 return (0); 677 } 678 679 static int32_t 680 find_value(slist_t *slist, char *match_str, int32_t *match_value) 681 { 682 int32_t i; 683 int32_t nmatches; 684 int32_t length; 685 int32_t match_length; 686 687 nmatches = 0; 688 length = 0; 689 690 match_length = strlen(match_str); 691 692 for (; slist->str != NULL; slist++) { 693 /* 694 * See how many characters of the token match 695 */ 696 i = strcnt(match_str, slist->str); 697 /* 698 * If it's not the whole token, then it's not a match. 699 */ 700 if (i < match_length) { 701 continue; 702 } 703 /* 704 * If it ties with another input, remember that. 705 */ 706 if (i == length) 707 nmatches++; 708 /* 709 * If it matches the most so far, record that. 710 */ 711 if (i > length) { 712 *match_value = slist->value; 713 nmatches = 1; 714 length = i; 715 } 716 } 717 718 return (nmatches); 719 } 720 721 static int32_t 722 strcnt(char *s1, char *s2) 723 { 724 int32_t i = 0; 725 726 while ((*s1 != '\0') && (*s1++ == *s2++)) 727 i++; 728 return (i); 729 } 730 731 static uint64_t 732 str2sector(char *str) 733 { 734 int32_t mul_factor = 1; 735 char *s1, *s2, *base; 736 uint64_t num_sectors; 737 uint64_t size; 738 739 base = s2 = (char *)malloc(strlen(str) + 1); 740 if (s2 == NULL) { 741 PERROR("Malloc failed"); 742 return (-1); 743 } 744 *s2 = '\0'; 745 746 747 748 s1 = str; 749 while (*s1) { 750 if ((*s1 != 'x') && ((*s1 < 'A') || (*s1 > 'F')) && 751 ((*s1 < 'a') || (*s1 > 'f')) && ((*s1 < '0') || 752 (*s1 > '9'))) { 753 if (*s1 == 'G') { 754 mul_factor = 1024*1024*1024; 755 s1++; 756 } else if (*s1 == 'M') { 757 mul_factor = 1024*1024; 758 s1++; 759 } else if (*s1 == 'K') { 760 mul_factor = 1024; 761 s1++; 762 } 763 if ((*s1 != 'B') || (*(++s1) != NULL)) { 764 (void) fprintf(stderr, 765 gettext("Extra chars at the end\n")); 766 free(base); 767 return (-1); 768 } 769 break; 770 } else { 771 *s2++ = *s1++; 772 *s2 = '\0'; 773 } 774 } 775 *s2 = NULL; 776 777 size = my_atoll(base); 778 if ((!mul_factor) || (size == -1)) { 779 free(base); 780 return (-1); 781 } 782 num_sectors = size * (uint64_t)mul_factor /512; 783 784 free(base); 785 return (num_sectors); 786 } 787 788 789 int32_t 790 valid_slice_file(smedia_handle_t handle, int32_t fd, char *file_name, 791 struct extvtoc *vt) 792 { 793 struct stat status; 794 int32_t ret_val; 795 if (stat(file_name, &status)) { 796 PERROR(file_name); 797 return (-1); 798 } 799 (void) memset(vt, 0, sizeof (*vt)); 800 /* Set default tag and flag */ 801 #ifdef sparc 802 vt->v_part[0].p_tag = V_ROOT; 803 vt->v_part[1].p_tag = V_SWAP; 804 vt->v_part[2].p_tag = V_BACKUP; 805 vt->v_part[6].p_tag = V_USR; 806 807 vt->v_part[1].p_flag = V_UNMNT; /* Unmountable */ 808 vt->v_part[2].p_flag = V_UNMNT; /* Unmountable */ 809 #endif 810 811 ret_val = sup_prxfile(file_name, vt); 812 if (ret_val < 0) 813 return (-1); 814 815 #ifdef DEBUG 816 { 817 int32_t i; 818 for (i = 0; i < 8; i++) { 819 DPRINTF1("\npart %d\n", i); 820 DPRINTF1("\t start %llu", vt->v_part[i].p_start); 821 DPRINTF1("\t size %llu ", vt->v_part[i].p_size); 822 DPRINTF1("\t tag %d", vt->v_part[i].p_tag); 823 DPRINTF1("\t flag %d", vt->v_part[i].p_flag); 824 } 825 } 826 #endif /* DEBUG */ 827 if (check_vtoc_sanity(handle, fd, vt) < 0) { 828 return (-1); 829 } 830 #ifdef DEBUG 831 { 832 int32_t i; 833 for (i = 0; i < 8; i++) { 834 DPRINTF1("\npart %d\n", i); 835 DPRINTF1("\t start %llu", vt->v_part[i].p_start); 836 DPRINTF1("\t size %llu ", vt->v_part[i].p_size); 837 DPRINTF1("\t tag %d", vt->v_part[i].p_tag); 838 DPRINTF1("\t flag %d", vt->v_part[i].p_flag); 839 } 840 } 841 #endif /* DEBUG */ 842 return (0); 843 } 844 845 #define SWAP(a, b) {diskaddr_t tmp; tmp = (a); (a) = (b); (b) = tmp; } 846 847 /* 848 * On x86 Solaris, the partitioning is done in two levels, fdisk and Solaris 849 * VTOC. Where as, on sparc solaris, it is only VTOC. On floppy and PCMCIA 850 * also it is assumed to be only VTOC, no fdisk. 851 * 852 * On sparc, the back up slice can cover the whole medium. But on x86 853 * (SCSI/ATAPI disks), the backup slice can cover the solaris partition 854 * in fdisk table. 855 * Following table describes how is it handled 856 * SPARC: 857 * SCSI/ATAPI, floppy, pcmcia : don't check for fdisk. 858 * DKIOCGGEOM is sufficient. 859 * x86 : floppy, pcmcia : Don't check for fdisk. DKIOCGGEOM is sufficient. 860 * SCSI/ATAPI : Check for fdisk. 861 * if not present, assume that the solaris 862 * partition covers 100% of the medium 863 * (minus one cylinder). 864 * 865 * if present : 866 * check for active solaris partition. 867 * if not found, take the first solaris 868 * partition. 869 * If there are no solaris partitions, its an error, stop. 870 */ 871 872 static int32_t 873 check_vtoc_sanity(smedia_handle_t handle, int32_t fd, struct extvtoc *vt) 874 { 875 876 int32_t i, j; 877 struct dk_geom dkg; 878 int32_t num_backup = 0; 879 diskaddr_t backup_size = 0; 880 struct part_struct { 881 diskaddr_t start; 882 diskaddr_t end; 883 int32_t num; 884 } part[NDKMAP]; 885 diskaddr_t min_val; 886 int32_t min_slice, num_slices; 887 diskaddr_t media_size; 888 uint32_t cyl_size = 0; 889 int sparc_style = 0; /* sparc_style handling ? */ 890 struct fdisk_info fdisk; 891 int sol_part; 892 int total_parts = 0; 893 894 #ifdef sparc 895 sparc_style = 1; 896 #endif /* sparc */ 897 898 if ((med_info.sm_media_type == SM_FLOPPY) || 899 (med_info.sm_media_type == SM_PCMCIA_MEM) || 900 (med_info.sm_media_type == SM_PCMCIA_ATA) || 901 (med_info.sm_media_type == SM_SCSI_FLOPPY)) { 902 sparc_style = 1; 903 } 904 905 if (sparc_style) { 906 DPRINTF("sparc style true\n"); 907 if (ioctl(fd, DKIOCGGEOM, &dkg) < 0) { 908 PERROR("DKIOCGGEOM Failed"); 909 return (-1); 910 } 911 media_size = (diskaddr_t)dkg.dkg_ncyl * dkg.dkg_nhead * 912 dkg.dkg_nsect; 913 cyl_size = dkg.dkg_nhead * dkg.dkg_nsect; 914 } 915 916 if (!sparc_style) { 917 /* 918 * Try to get the fdisk information if available. 919 */ 920 if (get_fdisk(handle, fd, 0, &fdisk) >= 0) { 921 /* fdisk table on disk */ 922 sol_part = 0xFF; 923 for (i = 0; i < FD_NUMPART; i++) { 924 if (fdisk.part[i].systid == SUNIXOS || 925 fdisk.part[i].systid == SUNIXOS2) { 926 if (sol_part == 0xFF) 927 sol_part = i; 928 total_parts++; 929 if (fdisk.part[i].bootid == ACTIVE) 930 sol_part = i; 931 } 932 } 933 if (sol_part == 0xFF) { 934 /* No Solaris partition */ 935 936 (void) fprintf(stderr, gettext("No FDISK \ 937 Solaris partition found!\n")); 938 return (-1); 939 } 940 if (total_parts > 1) 941 (void) fprintf(stderr, gettext("Multiple FDISK \ 942 Solaris partitions found.\n")); 943 media_size = (diskaddr_t)fdisk.part[sol_part].numsect; 944 945 DPRINTF1("sol_part %d\n", sol_part); 946 DPRINTF1("media_size %llu\n", media_size); 947 } else { 948 DPRINTF("Didn't get fdisk\n"); 949 /* 950 * No fdisk partition available. Assume a 100% Solaris. 951 * partition. 952 * Try getting disk geometry. 953 */ 954 if (ioctl(fd, DKIOCGGEOM, &dkg) < 0) 955 if (ioctl(fd, DKIOCG_PHYGEOM, &dkg) < 0) { 956 DPRINTF("DKIOCG_PHYGEOM ioctl failed"); 957 return (-1); 958 } 959 /* On x86 platform 1 cylinder is used for fdisk table */ 960 dkg.dkg_ncyl = dkg.dkg_ncyl - 1; 961 media_size = (diskaddr_t)dkg.dkg_ncyl * dkg.dkg_nhead * 962 dkg.dkg_nsect; 963 } 964 } 965 966 #ifdef DEBUG 967 DPRINTF1("Ncyl %d\n", dkg.dkg_ncyl); 968 DPRINTF1("nhead %d\n", dkg.dkg_nhead); 969 DPRINTF1("nsect %d\n", dkg.dkg_nsect); 970 #endif /* DEBUG */ 971 972 if (media_size == 0) { 973 media_size = (uint32_t)med_info.sm_capacity; 974 } 975 976 (void) memset(&part, 0, sizeof (part)); 977 for (i = 0, j = 0; i < NDKMAP; i++) { 978 if (vt->v_part[i].p_tag == V_BACKUP) { 979 if (vt->v_part[i].p_start != 0) { 980 (void) fprintf(stderr, 981 gettext( 982 "Backup slice should start at sector 0\n")); 983 return (-1); 984 } 985 backup_size = vt->v_part[i].p_size; 986 num_backup++; 987 continue; 988 } 989 if (vt->v_part[i].p_size) { 990 991 if (sparc_style) { 992 if (vt->v_part[i].p_start % cyl_size) { 993 (void) fprintf(stderr, 994 gettext( 995 "Slice %d does not start on cylinder boundary\n"), i); 996 (void) fprintf(stderr, 997 gettext( 998 "Cylinder size %d 512 byte sectors\n"), cyl_size); 999 return (-1); 1000 } 1001 } 1002 part[j].start = vt->v_part[i].p_start; 1003 part[j].end = vt->v_part[i].p_start + 1004 vt->v_part[i].p_size -1; 1005 part[j].num = i; 1006 j++; 1007 } 1008 } 1009 if (num_backup > 1) { 1010 (void) fprintf(stderr, 1011 gettext("Maximum one backup slice is allowed\n")); 1012 (void) smedia_release_handle(handle); 1013 (void) close(fd); 1014 exit(1); 1015 } 1016 num_slices = j; 1017 1018 for (i = 0; i < num_slices; i++) { 1019 min_val = part[i].start; 1020 min_slice = i; 1021 for (j = i+1; j < num_slices; j++) { 1022 if (part[j].start < min_val) { 1023 min_val = part[j].start; 1024 min_slice = j; 1025 } 1026 } 1027 if (min_slice != i) { 1028 SWAP(part[i].start, part[min_slice].start) 1029 SWAP(part[i].end, part[min_slice].end) 1030 SWAP(part[i].num, part[min_slice].num) 1031 } 1032 } 1033 1034 #ifdef DEBUG 1035 for (i = 0; i < num_slices; i++) { 1036 DPRINTF4("\n %d (%d) : %llu, %llu", i, part[i].num, 1037 part[i].start, part[i].end); 1038 } 1039 #endif /* DEBUG */ 1040 1041 if (backup_size > media_size) { 1042 if (sparc_style) { 1043 (void) fprintf(stderr, 1044 gettext( 1045 "Backup slice extends beyond size of media\n")); 1046 (void) fprintf(stderr, 1047 gettext("media size : %llu sectors \n"), 1048 media_size); 1049 } else { 1050 1051 (void) fprintf(stderr, 1052 gettext("Backup slice extends beyond size of FDISK \ 1053 Solaris partition\n")); 1054 (void) fprintf(stderr, 1055 gettext( 1056 "FDISK Solaris partition size : %llu sectors \n"), 1057 media_size); 1058 } 1059 return (-1); 1060 } 1061 1062 /* 1063 * If we have only backup slice return success here. 1064 */ 1065 if (num_slices == 0) 1066 return (0); 1067 1068 if (backup_size) { 1069 if (part[num_slices - 1].end > backup_size) { 1070 (void) fprintf(stderr, 1071 gettext("Slice %d extends beyond backup slice.\n"), 1072 part[num_slices -1].num); 1073 return (-1); 1074 } 1075 } else { 1076 if (part[num_slices - 1].end > media_size) { 1077 if (sparc_style) { 1078 (void) fprintf(stderr, 1079 gettext( 1080 "Slice %d extends beyond media size\n"), 1081 part[num_slices -1].num); 1082 (void) fprintf(stderr, 1083 gettext("media size : %llu sectors \n"), 1084 media_size); 1085 } else { 1086 (void) fprintf(stderr, 1087 gettext("Slice %d extends beyond FDISK" 1088 " Solaris partition size\n"), 1089 part[num_slices -1].num); 1090 (void) fprintf(stderr, gettext( 1091 "FDISK Solaris partition size : %llu " 1092 "sectors \n"), media_size); 1093 } 1094 return (-1); 1095 } 1096 } 1097 1098 1099 1100 for (i = 0; i < num_slices; i++) { 1101 if (i == 0) 1102 continue; 1103 if (part[i].start <= part[i-1].end) { 1104 (void) fprintf(stderr, 1105 gettext("Overlap between slices %d and %d\n"), 1106 part[i-1].num, part[i].num); 1107 (void) smedia_release_handle(handle); 1108 (void) close(fd); 1109 exit(1); 1110 } 1111 } 1112 1113 return (0); 1114 } 1115 1116 1117 static int32_t 1118 get_fdisk(smedia_handle_t handle, int32_t fd, int32_t offset, 1119 struct fdisk_info *fdisk) 1120 { 1121 struct mboot *boot_sec; 1122 struct ipart *part; 1123 char *buf; 1124 int32_t i, ret; 1125 int save_errno; 1126 1127 /* Read the master boot program */ 1128 1129 buf = (char *)malloc(med_info.sm_blocksize); 1130 if (buf == NULL) { 1131 PERROR("malloc failed"); 1132 exit(1); 1133 } 1134 errno = 0; 1135 ret = ioctl(fd, DKIOCGMBOOT, buf); 1136 if (ret < 0) { 1137 if (errno != ENOTTY) { 1138 PERROR("DKIOCGMBOOT ioctl failed"); 1139 return (-1); 1140 } 1141 1142 /* Turn on privileges. */ 1143 (void) __priv_bracket(PRIV_ON); 1144 1145 ret = smedia_raw_read(handle, 1146 (diskaddr_t)offset/med_info.sm_blocksize, 1147 buf, med_info.sm_blocksize); 1148 1149 /* Turn off privileges. */ 1150 (void) __priv_bracket(PRIV_OFF); 1151 1152 save_errno = errno; 1153 errno = save_errno; 1154 if (ret != med_info.sm_blocksize) { 1155 if (errno == ENOTSUP) { 1156 errno = 0; 1157 if (lseek(fd, offset, SEEK_SET)) { 1158 PERROR("Seek failed:"); 1159 free(buf); 1160 return (-1); 1161 } 1162 1163 /* Turn on privileges. */ 1164 (void) __priv_bracket(PRIV_ON); 1165 1166 ret = read(fd, buf, sizeof (struct mboot)); 1167 1168 /* Turn off privileges. */ 1169 (void) __priv_bracket(PRIV_OFF); 1170 1171 if (ret != sizeof (struct mboot)) { 1172 PERROR("Could not read " 1173 "master boot record"); 1174 free(buf); 1175 return (-1); 1176 } 1177 } else { 1178 PERROR("Could not read master boot record"); 1179 free(buf); 1180 return (-1); 1181 } 1182 } 1183 } 1184 /* LINTED pointer cast may result in improper alignment */ 1185 boot_sec = (struct mboot *)buf; 1186 1187 /* Is this really a master boot record? */ 1188 if (les(boot_sec->signature) != MBB_MAGIC) { 1189 DPRINTF("fdisk: Invalid master boot file \n"); 1190 DPRINTF2("Bad magic number: is %x, should be %x.\n", 1191 les(boot_sec->signature), MBB_MAGIC); 1192 free(buf); 1193 return (-1); 1194 } 1195 1196 for (i = 0; i < FD_NUMPART; i++) { 1197 DPRINTF1("part %d\n", i); 1198 /* LINTED pointer cast may result in improper alignment */ 1199 part = (struct ipart *)&boot_sec->parts[i * 1200 sizeof (struct ipart)]; 1201 fdisk->part[i].bootid = part->bootid; 1202 if (part->bootid && (part->bootid != ACTIVE)) { 1203 /* Hmmm...not a valid fdisk! */ 1204 return (-1); 1205 } 1206 fdisk->part[i].systid = part->systid; 1207 1208 /* To avoid the misalign access in sparc */ 1209 1210 fdisk->part[i].relsect = lel(GET_32(&(part->relsect))); 1211 fdisk->part[i].numsect = lel(GET_32(&(part->numsect))); 1212 1213 DPRINTF1("\tboot id 0x%x\n", part->bootid); 1214 DPRINTF1("\tsystem id 0x%x\n", part->systid); 1215 DPRINTF1("\trel sector 0x%x\n", fdisk->part[i].relsect); 1216 DPRINTF1("\tnum sector 0x%x\n", fdisk->part[i].numsect); 1217 } 1218 free(buf); 1219 return (0); 1220 } 1221 1222 1223 /* 1224 * wrrite_defualt_label(int32_t fd) 1225 * fd = file descriptor for the device. 1226 * 1227 * For sparc solaris 1228 * Create a vtoc partition with 1229 * slice 0 = slice 2 = medium capacity. 1230 * The cyl, head, sect (CHS) values are computed as done in sd 1231 * capacity <= 1GB, 1232 * nhead = 64, nsect = 32 1233 * capacity > 1gb, 1234 * nhead = 255, nsect = 63 1235 * 1236 * For x86 solaris 1237 * Create a fdisk partition, 1238 * partition 0 covers the full medium, the partition 1239 * type is set to Solaris. 1240 * Then create solaris vtoc. The algorithm is same as sparc solaris. 1241 * But the capacity is reduced by 1 cyl, to leave space for fdisk table. 1242 */ 1243 1244 #ifdef sparc 1245 /*ARGSUSED*/ 1246 void 1247 write_default_label(smedia_handle_t handle, int32_t fd) 1248 { 1249 1250 struct extvtoc v_toc; 1251 uint32_t nhead, numcyl, nsect; 1252 diskaddr_t capacity; 1253 int32_t ret; 1254 char asciilabel[LEN_DKL_ASCII]; 1255 char asciilabel2[LEN_DKL_ASCII] = "DEFAULT\0"; 1256 uint32_t acyl = 2; 1257 1258 1259 DPRINTF("Writing default vtoc\n"); 1260 (void) memset(&v_toc, 0, sizeof (v_toc)); 1261 1262 1263 v_toc.v_nparts = V_NUMPAR; 1264 v_toc.v_sanity = VTOC_SANE; 1265 v_toc.v_version = V_VERSION; 1266 v_toc.v_sectorsz = DEV_BSIZE; 1267 1268 /* 1269 * For the head, cyl and number of sector per track, 1270 * if the capacity <= 1GB, head = 64, sect = 32. 1271 * else head = 255, sect 63 1272 * NOTE: the capacity should be equal to C*H*S values. 1273 * This will cause some truncation of size due to 1274 * round off errors. 1275 */ 1276 if ((uint32_t)med_info.sm_capacity <= 0x200000) { 1277 nhead = 64; 1278 nsect = 32; 1279 } else { 1280 nhead = 255; 1281 nsect = 63; 1282 } 1283 1284 numcyl = (uint32_t)med_info.sm_capacity / (nhead * nsect); 1285 capacity = (diskaddr_t)nhead * nsect * numcyl; 1286 1287 v_toc.v_part[0].p_start = 0; 1288 v_toc.v_part[0].p_size = capacity; 1289 v_toc.v_part[0].p_tag = V_ROOT; 1290 v_toc.v_part[0].p_flag = 0; /* Mountable */ 1291 1292 v_toc.v_part[2].p_start = 0; 1293 v_toc.v_part[2].p_size = capacity; 1294 v_toc.v_part[2].p_tag = V_BACKUP; 1295 v_toc.v_part[2].p_flag = V_UNMNT; 1296 1297 /* Create asciilabel for compatibility with format utility */ 1298 (void) snprintf(asciilabel, sizeof (asciilabel), 1299 "%s cyl %d alt %d hd %d sec %d", 1300 asciilabel2, numcyl, acyl, nhead, nsect); 1301 (void) memcpy(v_toc.v_asciilabel, asciilabel, 1302 LEN_DKL_ASCII); 1303 1304 errno = 0; 1305 1306 /* Turn on privileges. */ 1307 (void) __priv_bracket(PRIV_ON); 1308 1309 ret = write_extvtoc(fd, &v_toc); 1310 1311 /* Turn off privileges. */ 1312 (void) __priv_bracket(PRIV_OFF); 1313 1314 if (ret < 0) { 1315 PERROR("write VTOC failed"); 1316 DPRINTF1("Errno = %d\n", errno); 1317 } 1318 } 1319 1320 #else /* !sparc */ 1321 #ifdef i386 1322 1323 void 1324 write_default_label(smedia_handle_t handle, int32_t fd) 1325 { 1326 1327 int32_t i, ret; 1328 struct dk_geom dkg; 1329 struct extvtoc v_toc; 1330 int tmp_fd; 1331 char *fdisk_buf; 1332 struct mboot boot_code; /* Buffer for master boot record */ 1333 struct ipart parts[FD_NUMPART]; 1334 uint32_t numcyl, nhead, nsect; 1335 uint32_t unixend; 1336 uint32_t blocksize; 1337 diskaddr_t capacity; 1338 int save_errno; 1339 size_t bytes_written; 1340 char asciilabel[LEN_DKL_ASCII]; 1341 char asciilabel2[LEN_DKL_ASCII] = "DEFAULT\0"; 1342 uint32_t acyl = 2; 1343 1344 DPRINTF("Writing default fdisk table and vtoc\n"); 1345 (void) memset(&v_toc, 0, sizeof (v_toc)); 1346 /* 1347 * Try getting disk geometry. 1348 */ 1349 if (ioctl(fd, DKIOCGGEOM, &dkg) < 0) 1350 if (ioctl(fd, DKIOCG_PHYGEOM, &dkg) < 0) { 1351 1352 DPRINTF("DKIOCG_PHYGEOM ioctl failed"); 1353 return; 1354 } 1355 1356 tmp_fd = open("/usr/lib/fs/ufs/mboot", O_RDONLY); 1357 if (tmp_fd <= 0) { 1358 return; 1359 } 1360 1361 if (read(tmp_fd, &boot_code, sizeof (struct mboot)) 1362 != sizeof (struct mboot)) { 1363 (void) close(tmp_fd); 1364 return; 1365 } 1366 1367 blocksize = med_info.sm_blocksize; 1368 fdisk_buf = (char *)malloc(blocksize); 1369 if (fdisk_buf == NULL) { 1370 DPRINTF("malloc for fdisk_buf failed\n"); 1371 return; 1372 } 1373 1374 (void) memset(&parts, 0, sizeof (parts)); 1375 1376 for (i = 0; i < FD_NUMPART; i++) { 1377 parts[i].systid = UNUSED; 1378 parts[i].numsect = lel(UNUSED); 1379 parts[i].relsect = lel(UNUSED); 1380 parts[i].bootid = 0; 1381 } 1382 1383 numcyl = dkg.dkg_ncyl; 1384 nhead = dkg.dkg_nhead; 1385 nsect = dkg.dkg_nsect; 1386 1387 parts[0].bootid = ACTIVE; 1388 parts[0].begsect = 1; 1389 1390 unixend = numcyl; 1391 1392 parts[0].relsect = lel(nhead * nsect); 1393 parts[0].numsect = lel(((diskaddr_t)numcyl * nhead * nsect)); 1394 parts[0].systid = SUNIXOS2; /* Solaris */ 1395 parts[0].beghead = 0; 1396 parts[0].begcyl = 1; 1397 parts[0].endhead = nhead - 1; 1398 parts[0].endsect = (nsect & 0x3f) | 1399 (char)((unixend >> 2) & 0x00c0); 1400 parts[0].endcyl = (char)(unixend & 0x00ff); 1401 1402 (void) memcpy(&(boot_code.parts), parts, sizeof (parts)); 1403 (void) memcpy(fdisk_buf, &boot_code, sizeof (boot_code)); 1404 1405 /* Turn on privileges. */ 1406 (void) __priv_bracket(PRIV_ON); 1407 1408 ret = ioctl(fd, DKIOCSMBOOT, fdisk_buf); 1409 1410 /* Turn off privileges. */ 1411 (void) __priv_bracket(PRIV_OFF); 1412 1413 if (ret == -1) { 1414 if (errno != ENOTTY) { 1415 PERROR("DKIOCSMBOOT ioctl Failed"); 1416 return; 1417 } 1418 1419 /* Turn on privileges. */ 1420 (void) __priv_bracket(PRIV_ON); 1421 1422 bytes_written = smedia_raw_write(handle, (diskaddr_t)0, 1423 fdisk_buf, blocksize); 1424 1425 /* Turn off privileges. */ 1426 (void) __priv_bracket(PRIV_OFF); 1427 1428 save_errno = errno; 1429 errno = save_errno; 1430 if (bytes_written != blocksize) { 1431 if (errno == ENOTSUP) { 1432 1433 /* Turn on privileges. */ 1434 (void) __priv_bracket(PRIV_ON); 1435 1436 ret = write(fd, fdisk_buf, blocksize); 1437 1438 /* Turn off privileges. */ 1439 (void) __priv_bracket(PRIV_OFF); 1440 1441 if (ret != blocksize) { 1442 return; 1443 } 1444 } else { 1445 return; 1446 } 1447 } 1448 } 1449 capacity = (diskaddr_t)(numcyl - 1) * nhead * nsect; 1450 1451 v_toc.v_nparts = V_NUMPAR; 1452 v_toc.v_sanity = VTOC_SANE; 1453 v_toc.v_version = V_VERSION; 1454 v_toc.v_sectorsz = DEV_BSIZE; 1455 1456 v_toc.v_part[0].p_start = 0; 1457 v_toc.v_part[0].p_size = capacity; 1458 v_toc.v_part[0].p_tag = V_ROOT; 1459 v_toc.v_part[0].p_flag = 0; /* Mountable */ 1460 1461 v_toc.v_part[2].p_start = 0; 1462 v_toc.v_part[2].p_size = capacity; 1463 v_toc.v_part[2].p_tag = V_BACKUP; 1464 v_toc.v_part[2].p_flag = V_UNMNT; 1465 1466 /* Create asciilabel for compatibility with format utility */ 1467 (void) snprintf(asciilabel, sizeof (asciilabel), 1468 "%s cyl %d alt %d hd %d sec %d", 1469 asciilabel2, numcyl, acyl, nhead, nsect); 1470 (void) memcpy(v_toc.v_asciilabel, asciilabel, 1471 LEN_DKL_ASCII); 1472 1473 errno = 0; 1474 1475 1476 /* Turn on privileges. */ 1477 (void) __priv_bracket(PRIV_ON); 1478 1479 ret = write_extvtoc(fd, &v_toc); 1480 1481 /* Turn off privileges. */ 1482 (void) __priv_bracket(PRIV_OFF); 1483 1484 if (ret < 0) { 1485 PERROR("write VTOC failed"); 1486 DPRINTF1("Errno = %d\n", errno); 1487 } 1488 } 1489 1490 #else /* !i386 */ 1491 1492 #error One of sparc or i386 must be defined! 1493 1494 #endif /* i386 */ 1495 #endif /* sparc */ 1496 1497 /* 1498 * void overwrite_metadata(int32_t fd, smedia_handle_t handle) 1499 * 1500 * purpose : quick format does not erase the data on Iomega 1501 * zip/jaz media. So, the meta data on the disk should be erased. 1502 * 1503 * If there is a valid fdisk table, 1504 * erase first 64K of each partition. 1505 * If there is a valid vtoc, 1506 * erase first 64k of each slice. 1507 * Then erase the 0th sector (the home for vtoc and fdisk) of the disk. 1508 * Note that teh vtoc on x86 resides in one of the fdisk partition. 1509 * So delay the erasing of the solaris partition until the vtoc is read. 1510 */ 1511 1512 void 1513 overwrite_metadata(int32_t fd, smedia_handle_t handle) 1514 { 1515 1516 struct fdisk_info fdisk; 1517 diskaddr_t sol_offset = 0; 1518 int i, ret; 1519 struct extvtoc t_vtoc; 1520 #ifdef i386 1521 diskaddr_t sol_size = 0; 1522 int32_t active = 0; 1523 #endif /* i386 */ 1524 1525 /* Get fdisk info. */ 1526 if (get_fdisk(handle, fd, 0, &fdisk) >= 0) { 1527 /* Got a valid fdisk */ 1528 for (i = 0; i < FD_NUMPART; i++) { 1529 1530 if (fdisk.part[i].numsect == 0) 1531 continue; 1532 if ((fdisk.part[i].systid == UNUSED) || 1533 (fdisk.part[i].systid == 0)) 1534 continue; 1535 #ifdef i386 1536 if (fdisk.part[i].systid == SUNIXOS || 1537 fdisk.part[i].systid == SUNIXOS2) { 1538 if (!sol_offset) { 1539 sol_offset = fdisk.part[i].relsect; 1540 sol_size = fdisk.part[i].numsect; 1541 if (fdisk.part[i].bootid == ACTIVE) 1542 active = 1; 1543 continue; 1544 } else if ((fdisk.part[i].bootid == ACTIVE) && 1545 (!active)) { 1546 erase(handle, sol_offset, sol_size); 1547 sol_offset = fdisk.part[i].relsect; 1548 sol_size = fdisk.part[i].numsect; 1549 active = 1; 1550 continue; 1551 } 1552 } 1553 #endif /* i386 */ 1554 erase(handle, (diskaddr_t)fdisk.part[i].relsect, 1555 (diskaddr_t)fdisk.part[i].numsect); 1556 } 1557 } 1558 1559 (void) memset(&t_vtoc, 0, sizeof (t_vtoc)); 1560 1561 if (sol_offset) { 1562 /* fdisk x86 Solaris partition */ 1563 /* VTOC location in solaris partition is DK_LABEL_LOC */ 1564 1565 /* Turn on privileges. */ 1566 (void) __priv_bracket(PRIV_ON); 1567 1568 ret = read_extvtoc(fd, &t_vtoc); 1569 1570 /* Turn off privileges. */ 1571 (void) __priv_bracket(PRIV_OFF); 1572 1573 if (ret < 0) { 1574 /* No valid vtoc, erase fdisk table. */ 1575 erase(handle, (diskaddr_t)0, (diskaddr_t)1); 1576 return; 1577 } 1578 } else { 1579 /* Sparc Solaris or x86 solaris with faked fdisk */ 1580 1581 /* Turn on privileges */ 1582 (void) __priv_bracket(PRIV_ON); 1583 1584 ret = read_extvtoc(fd, &t_vtoc); 1585 1586 /* Turn off privileges. */ 1587 (void) __priv_bracket(PRIV_OFF); 1588 1589 if (ret < 0) { 1590 /* No valid vtoc, erase from 0th sector */ 1591 erase(handle, (diskaddr_t)0, 1592 (uint32_t)med_info.sm_capacity); 1593 return; 1594 } 1595 } 1596 1597 for (i = 0; i < V_NUMPAR; i++) { 1598 if (t_vtoc.v_part[i].p_size != 0) { 1599 erase(handle, sol_offset + t_vtoc.v_part[i].p_start, 1600 t_vtoc.v_part[i].p_size); 1601 /* 1602 * To make the udfs not recognise the partition we will 1603 * erase sectors 256, (p_size-256) and psize. 1604 */ 1605 erase(handle, 1606 sol_offset + t_vtoc.v_part[i].p_start + 256, 1607 (diskaddr_t)1); 1608 erase(handle, 1609 (sol_offset + t_vtoc.v_part[i].p_start + 1610 t_vtoc.v_part[i].p_size - 256), 1611 (diskaddr_t)1); 1612 erase(handle, 1613 (sol_offset + t_vtoc.v_part[i].p_start + 1614 t_vtoc.v_part[i].p_size - 1), 1615 (diskaddr_t)1); 1616 } 1617 } 1618 1619 /* 1620 * If x86 fdisk solaris partition, erase the vtoc also. 1621 * for sparc, the erasing 0the sector erases vtoc. 1622 */ 1623 if (sol_offset) { 1624 erase(handle, sol_offset, (diskaddr_t)DK_LABEL_LOC + 2); 1625 } 1626 1627 /* 1628 * erase the 0th sector, it is not guaranteed to be 1629 * erased in the above sequence. 1630 */ 1631 1632 erase(handle, (diskaddr_t)0, (diskaddr_t)1); 1633 } 1634 1635 /* 1636 * void erase(smedia_handle_t handle, uint32_t offset, uint32_t size) 1637 * 1638 * Initialize the media with '0' from offset 'offset' upto 'size' 1639 * or 128 blocks(64k), whichever is smaller. 1640 */ 1641 1642 static void 1643 erase(smedia_handle_t handle, diskaddr_t offset, diskaddr_t size) 1644 { 1645 char *buf; 1646 diskaddr_t nblocks = size; 1647 int32_t ret; 1648 1649 1650 nblocks = (nblocks < 128) ? nblocks : 128; 1651 buf = (char *)malloc(nblocks * med_info.sm_blocksize); 1652 if (buf == NULL) { 1653 PERROR("malloc failed"); 1654 return; 1655 } 1656 (void) memset(buf, 0, (size_t)nblocks * med_info.sm_blocksize); 1657 1658 /* Turn on privileges. */ 1659 (void) __priv_bracket(PRIV_ON); 1660 1661 ret = smedia_raw_write(handle, offset, buf, 1662 (size_t)nblocks * med_info.sm_blocksize); 1663 1664 /* Turn off privileges. */ 1665 (void) __priv_bracket(PRIV_OFF); 1666 1667 if (ret != (nblocks * med_info.sm_blocksize)) 1668 PERROR("error in writing\n"); 1669 1670 free(buf); 1671 1672 }