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 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * rmf_slice.c : 28 * This file contains the functions for parsing a slice file 29 * for rmformat. 30 */ 31 32 #include <sys/types.h> 33 #include <ctype.h> 34 #include <sys/vtoc.h> 35 #include <stdlib.h> 36 #include <unistd.h> 37 #include <string.h> 38 #include <fcntl.h> 39 #include <errno.h> 40 #include <memory.h> 41 #include <dirent.h> 42 #include <sys/fcntl.h> 43 #include <sys/param.h> 44 #include <sys/stat.h> 45 #include <stdio.h> 46 #include <sys/dkio.h> 47 #include <priv_utils.h> 48 #include "rmformat.h" 49 50 extern void my_perror(char *err_string); 51 52 static int32_t last_token_type = 0; 53 #define spc() (last_token_type) 54 55 56 /* 57 * This global is used to store the current line # in the 58 * data file. It must be global because the I/O routines 59 * are allowed to side effect it to keep track of backslashed 60 * newlines. 61 */ 62 63 static int32_t data_lineno; /* current line # in data file */ 64 65 #define CHG_MODE_UNDEFINED (-1) /* undefined value */ 66 #define CHG_MODE_SET 0 /* set bits by or'ing */ 67 #define CHG_MODE_CLR 1 /* clr bits by and'ing */ 68 #define CHG_MODE_ABS 2 /* set absolute value */ 69 70 71 #define TOKEN_SIZE 36 /* max length of a token */ 72 typedef char TOKEN[TOKEN_SIZE+1]; /* token type */ 73 #define DATA_INPUT 0 /* 2 modes of input */ 74 #define CMD_INPUT 1 75 #define WILD_STRING "$" /* wildcard character */ 76 #define COMMENT_CHAR '#' /* comment character */ 77 78 /* 79 * List of strings with arbitrary matching values 80 */ 81 typedef struct slist { 82 char *str; 83 char *help; 84 int32_t value; 85 } slist_t; 86 87 static slist_t ptag_choices[] = { 88 { "unassigned", "", V_UNASSIGNED }, 89 { "boot", "", V_BOOT }, 90 { "root", "", V_ROOT }, 91 { "swap", "", V_SWAP }, 92 { "usr", "", V_USR }, 93 { "backup", "", V_BACKUP }, 94 { "stand", "", V_STAND }, 95 { "var", "", V_VAR }, 96 { "home", "", V_HOME }, 97 { "alternates", "", V_ALTSCTR }, 98 { NULL } 99 }; 100 101 102 /* 103 * Choices for the p_flag vtoc field 104 */ 105 static slist_t pflag_choices[] = { 106 { "wm", "read-write, mountable", 0 }, 107 { "wu", "read-write, unmountable", V_UNMNT }, 108 { "rm", "read-only, mountable", V_RONLY }, 109 { "ru", "read-only, unmountable", V_RONLY|V_UNMNT }, 110 { NULL } 111 }; 112 113 /* 114 * The definitions are the token types that the data file parser recognizes. 115 */ 116 #define SUP_EOF -1 /* eof token */ 117 #define SUP_STRING 0 /* string token */ 118 #define SUP_EQL 1 /* equals token */ 119 #define SUP_COMMA 2 /* comma token */ 120 #define SUP_COLON 3 /* colon token */ 121 #define SUP_EOL 4 /* newline token */ 122 #define SUP_OR 5 /* vertical bar */ 123 #define SUP_AND 6 /* ampersand */ 124 #define SUP_TILDE 7 /* tilde */ 125 126 127 /* 128 * Prototypes for ANSI C compilers 129 */ 130 static int32_t sup_prxfile(char *file_name, struct extvtoc *vt); 131 static int32_t sup_setpart(struct extvtoc *vt); 132 static void sup_pushchar(int32_t c); 133 static void clean_token(char *cleantoken, char *token); 134 static void clean_token(char *cleantoken, char *token); 135 static int32_t sup_inputchar(); 136 static int32_t sup_gettoken(char *buf); 137 static int32_t sup_get_token(char *buf); 138 static int32_t find_value(slist_t *slist, char *str, int32_t *value); 139 static int32_t check_vtoc_sanity(smedia_handle_t, int32_t fd, 140 struct extvtoc *vt); 141 static uint64_t str2sector(char *str); 142 static int32_t strcnt(char *s1, char *s2); 143 static int32_t get_fdisk(smedia_handle_t, int32_t fd, int32_t offset, 144 struct fdisk_info *fdisk); 145 static void erase(smedia_handle_t handle, diskaddr_t offset, diskaddr_t size); 146 147 extern char *myname; 148 extern uint64_t my_atoll(char *ptr); 149 extern smmedium_prop_t med_info; 150 151 static FILE *data_file; 152 153 static int32_t 154 sup_prxfile(char *file_name, struct extvtoc *vt) 155 { 156 int32_t status, ret_val; 157 TOKEN token; 158 TOKEN cleaned; 159 160 /* 161 * Open the data file. Return 0 if unable to do so. 162 */ 163 data_file = fopen(file_name, "r"); 164 if (data_file == NULL) { 165 PERROR("Open failed"); 166 return (-1); 167 } 168 /* 169 * Step through the data file a meta-line at a time. There are 170 * typically several backslashed newlines in each meta-line, 171 * so data_lineno will be getting side effected along the way. 172 */ 173 data_lineno = 1; 174 for (;;) { 175 176 /* 177 * Get the keyword. 178 */ 179 status = sup_gettoken(token); 180 /* 181 * If we hit the end of the data file, we're done. 182 */ 183 if (status == SUP_EOF) 184 break; 185 /* 186 * If the line starts with some key character, it's an error. 187 */ 188 if (status != SUP_STRING) { 189 (void) fprintf(stderr, 190 gettext("Expecting keyword, found '%s'"), 191 token); 192 (void) fprintf(stderr, 193 gettext("Line no %d\n"), data_lineno); 194 continue; 195 } 196 /* 197 * Clean up the token and see which keyword it is. Call 198 * the appropriate routine to process the rest of the line. 199 */ 200 clean_token(cleaned, token); 201 if (strcmp(cleaned, "slices") == 0) { 202 ret_val = sup_setpart(vt); 203 (void) fclose(data_file); 204 return (ret_val); 205 } else { 206 (void) fprintf(stderr, gettext("Unknown keyword '%s'"), 207 cleaned); 208 (void) fprintf(stderr, 209 gettext("Line no %d\n"), data_lineno); 210 (void) fclose(data_file); 211 return (-1); 212 } 213 } 214 /* 215 * Close the data file. 216 */ 217 (void) fclose(data_file); 218 219 (void) fprintf(stderr, 220 gettext("Unexpected end of file (line no %d)\n"), data_lineno); 221 return (-1); 222 } 223 224 static int32_t 225 sup_gettoken(char *buf) 226 { 227 /* 228 * Skip end of lines and blank lines. 229 */ 230 while ((last_token_type = sup_get_token(buf)) == SUP_EOL) 231 ; 232 return (last_token_type); 233 } 234 235 static int32_t 236 sup_get_token(char *buf) 237 { 238 char *ptr = buf; 239 int32_t c, quoted = 0; 240 241 /* 242 * Was an end of file detected last try? 243 */ 244 245 if (feof(data_file)) { 246 return (SUP_EOF); 247 } 248 249 /* 250 * Zero out the returned token buffer 251 */ 252 253 bzero(buf, TOKEN_SIZE + 1); 254 255 /* 256 * Strip off leading white-space. 257 */ 258 while (isspace(c = sup_inputchar())) 259 ; 260 261 /* 262 * Only white spaces and then end of file? 263 */ 264 265 if (feof(data_file)) { 266 return (SUP_EOF); 267 } 268 269 /* 270 * Read in characters until we hit unquoted white-space. 271 */ 272 for (; !isspace(c) || quoted; c = sup_inputchar()) { 273 274 /* 275 * If we hit eof, check if we have anything in buffer. 276 * if we have, return STRING, next time we will return EOF 277 * else, return EOF here...should not happen. 278 */ 279 if (feof(data_file)) { 280 if (ptr - buf > 0) { 281 return (SUP_STRING); 282 } else { 283 return (SUP_EOF); 284 } 285 } 286 287 /* 288 * If we hit a double quote, change the state of quoting. 289 */ 290 if (c == '"') { 291 quoted = !quoted; 292 continue; 293 } 294 /* 295 * If we hit a newline, that delimits a token. 296 */ 297 if (c == '\n') 298 break; 299 /* 300 * If we hit any nonquoted special delimiters, that delimits 301 * a token. 302 */ 303 if (!quoted && (c == '=' || c == ',' || c == ':' || 304 c == '#' || c == '|' || c == '&' || c == '~')) 305 break; 306 /* 307 * Store the character if there's room left. 308 */ 309 if (ptr - buf < TOKEN_SIZE) 310 *ptr++ = (char)c; 311 } 312 /* 313 * If we stored characters in the buffer, then we inputted a string. 314 * Push the delimiter back into the pipe and return the string. 315 */ 316 if (ptr - buf > 0) { 317 sup_pushchar(c); 318 return (SUP_STRING); 319 } 320 /* 321 * We didn't input a string, so we must have inputted a known delimiter. 322 * store the delimiter in the buffer, so it will get returned. 323 */ 324 buf[0] = c; 325 /* 326 * Switch on the delimiter. Return the appropriate value for each one. 327 */ 328 switch (c) { 329 case '=': 330 return (SUP_EQL); 331 case ':': 332 return (SUP_COLON); 333 case ',': 334 return (SUP_COMMA); 335 case '\n': 336 return (SUP_EOL); 337 case '|': 338 return (SUP_OR); 339 case '&': 340 return (SUP_AND); 341 case '~': 342 return (SUP_TILDE); 343 case '#': 344 /* 345 * For comments, we flush out the rest of the line and return 346 * an eol. 347 */ 348 while ((c = sup_inputchar()) != '\n' && !feof(data_file)) 349 ; 350 if (feof(data_file)) 351 return (SUP_EOF); 352 else 353 return (SUP_EOL); 354 /* 355 * Shouldn't ever get here. 356 */ 357 default: 358 return (SUP_STRING); 359 } 360 } 361 static int32_t 362 sup_inputchar() 363 { 364 int32_t c; 365 366 /* 367 * Input the character. 368 */ 369 c = getc(data_file); 370 /* 371 * If it's not a backslash, return it. 372 */ 373 374 /* 375 * It was a backslash. Get the next character. 376 */ 377 378 if (c == '\\') 379 c = getc(data_file); 380 381 /* 382 * If it was a newline, update the line counter and get the next 383 * character. 384 */ 385 if (c == '\n') { 386 data_lineno++; 387 } 388 /* 389 * Return the character. 390 */ 391 return (c); 392 } 393 394 static void 395 sup_pushchar(int32_t c) 396 { 397 398 (void) ungetc(c, data_file); 399 if (c == '\n') 400 data_lineno--; 401 } 402 403 static void 404 clean_token(char *cleantoken, char *token) 405 { 406 char *ptr; 407 408 /* 409 * Strip off leading white-space. 410 */ 411 for (ptr = token; isspace(*ptr) && (ptr <= 412 (token + strlen(token) - 1)); ptr++); 413 414 /* 415 * Copy it into the clean buffer. 416 */ 417 (void) strcpy(cleantoken, ptr); 418 /* 419 * Strip off trailing white-space. 420 */ 421 for (ptr = cleantoken + strlen(cleantoken) - 1; 422 isspace(*ptr) && (ptr >= cleantoken); ptr--) { 423 *ptr = '\0'; 424 } 425 } 426 427 static int32_t 428 sup_setpart(struct extvtoc *vt) 429 { 430 TOKEN token, cleaned, ident; 431 int32_t i, index, status; 432 uint64_t val1, val2; 433 ushort_t vtoc_tag = 0xFFFF; 434 ushort_t vtoc_flag = 0xFFFF; 435 436 /* 437 * Pull in some grammar. 438 */ 439 440 status = sup_gettoken(token); 441 442 if (status != SUP_COLON) { 443 (void) fprintf(stderr, 444 gettext("Expecting ':', found '%s'"), token); 445 (void) fprintf(stderr, 446 gettext("Line no %d\n"), data_lineno); 447 return (-1); 448 } 449 450 for (;;) { 451 status = sup_gettoken(token); 452 if (status != SUP_STRING) { 453 (void) fprintf(stderr, 454 gettext("Expecting string, found '%s'"), token); 455 (void) fprintf(stderr, 456 gettext("Line no %d\n"), data_lineno); 457 return (-1); 458 } 459 clean_token(ident, token); 460 /* 461 * Also make sure it is within the legal range of letters. 462 */ 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 '%s'"), 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( 632 "Expecting value, 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; 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( 1088 "Slice %d extends beyond FDISK 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 master boot record"); 1173 free(buf); 1174 return (-1); 1175 } 1176 } else { 1177 PERROR("Could not read master boot record"); 1178 free(buf); 1179 return (-1); 1180 } 1181 } 1182 } 1183 /* LINTED pointer cast may result in improper alignment */ 1184 boot_sec = (struct mboot *)buf; 1185 1186 /* Is this really a master boot record? */ 1187 if (les(boot_sec->signature) != MBB_MAGIC) { 1188 DPRINTF("fdisk: Invalid master boot file \n"); 1189 DPRINTF2("Bad magic number: is %x, should be %x.\n", 1190 les(boot_sec->signature), MBB_MAGIC); 1191 free(buf); 1192 return (-1); 1193 } 1194 1195 for (i = 0; i < FD_NUMPART; i++) { 1196 DPRINTF1("part %d\n", i); 1197 /* LINTED pointer cast may result in improper alignment */ 1198 part = (struct ipart *)&boot_sec->parts[i * 1199 sizeof (struct ipart)]; 1200 fdisk->part[i].bootid = part->bootid; 1201 if (part->bootid && (part->bootid != ACTIVE)) { 1202 /* Hmmm...not a valid fdisk! */ 1203 return (-1); 1204 } 1205 fdisk->part[i].systid = part->systid; 1206 1207 /* To avoid the misalign access in sparc */ 1208 1209 fdisk->part[i].relsect = lel(GET_32(&(part->relsect))); 1210 fdisk->part[i].numsect = lel(GET_32(&(part->numsect))); 1211 1212 DPRINTF1("\tboot id 0x%x\n", part->bootid); 1213 DPRINTF1("\tsystem id 0x%x\n", part->systid); 1214 DPRINTF1("\trel sector 0x%x\n", fdisk->part[i].relsect); 1215 DPRINTF1("\tnum sector 0x%x\n", fdisk->part[i].numsect); 1216 } 1217 free(buf); 1218 return (0); 1219 } 1220 1221 1222 /* 1223 * wrrite_defualt_label(int32_t fd) 1224 * fd = file descriptor for the device. 1225 * 1226 * For sparc solaris 1227 * Create a vtoc partition with 1228 * slice 0 = slice 2 = medium capacity. 1229 * The cyl, head, sect (CHS) values are computed as done in sd 1230 * capacity <= 1GB, 1231 * nhead = 64, nsect = 32 1232 * capacity > 1gb, 1233 * nhead = 255, nsect = 63 1234 * 1235 * For x86 solaris 1236 * Create a fdisk partition, 1237 * partition 0 covers the full medium, the partition 1238 * type is set to Solaris. 1239 * Then create solaris vtoc. The algorithm is same as sparc solaris. 1240 * But the capacity is reduced by 1 cyl, to leave space for fdisk table. 1241 */ 1242 1243 #ifdef sparc 1244 /*ARGSUSED*/ 1245 void 1246 write_default_label(smedia_handle_t handle, int32_t fd) 1247 { 1248 1249 struct extvtoc v_toc; 1250 uint32_t nhead, numcyl, nsect; 1251 diskaddr_t capacity; 1252 int32_t ret; 1253 char asciilabel[LEN_DKL_ASCII]; 1254 char asciilabel2[LEN_DKL_ASCII] = "DEFAULT\0"; 1255 uint32_t acyl = 2; 1256 1257 1258 DPRINTF("Writing default vtoc\n"); 1259 (void) memset(&v_toc, 0, sizeof (v_toc)); 1260 1261 1262 v_toc.v_nparts = V_NUMPAR; 1263 v_toc.v_sanity = VTOC_SANE; 1264 v_toc.v_version = V_VERSION; 1265 v_toc.v_sectorsz = DEV_BSIZE; 1266 1267 /* 1268 * For the head, cyl and number of sector per track, 1269 * if the capacity <= 1GB, head = 64, sect = 32. 1270 * else head = 255, sect 63 1271 * NOTE: the capacity should be equal to C*H*S values. 1272 * This will cause some truncation of size due to 1273 * round off errors. 1274 */ 1275 if ((uint32_t)med_info.sm_capacity <= 0x200000) { 1276 nhead = 64; 1277 nsect = 32; 1278 } else { 1279 nhead = 255; 1280 nsect = 63; 1281 } 1282 1283 numcyl = (uint32_t)med_info.sm_capacity / (nhead * nsect); 1284 capacity = (diskaddr_t)nhead * nsect * numcyl; 1285 1286 v_toc.v_part[0].p_start = 0; 1287 v_toc.v_part[0].p_size = capacity; 1288 v_toc.v_part[0].p_tag = V_ROOT; 1289 v_toc.v_part[0].p_flag = 0; /* Mountable */ 1290 1291 v_toc.v_part[2].p_start = 0; 1292 v_toc.v_part[2].p_size = capacity; 1293 v_toc.v_part[2].p_tag = V_BACKUP; 1294 v_toc.v_part[2].p_flag = V_UNMNT; 1295 1296 /* Create asciilabel for compatibility with format utility */ 1297 (void) snprintf(asciilabel, sizeof (asciilabel), 1298 "%s cyl %d alt %d hd %d sec %d", 1299 asciilabel2, numcyl, acyl, nhead, nsect); 1300 (void) memcpy(v_toc.v_asciilabel, asciilabel, 1301 LEN_DKL_ASCII); 1302 1303 errno = 0; 1304 1305 /* Turn on privileges. */ 1306 (void) __priv_bracket(PRIV_ON); 1307 1308 ret = write_extvtoc(fd, &v_toc); 1309 1310 /* Turn off privileges. */ 1311 (void) __priv_bracket(PRIV_OFF); 1312 1313 if (ret < 0) { 1314 PERROR("write VTOC failed"); 1315 DPRINTF1("Errno = %d\n", errno); 1316 } 1317 } 1318 1319 #else /* !sparc */ 1320 #ifdef i386 1321 1322 void 1323 write_default_label(smedia_handle_t handle, int32_t fd) 1324 { 1325 1326 int32_t i, ret; 1327 struct dk_geom dkg; 1328 struct extvtoc v_toc; 1329 int tmp_fd; 1330 char *fdisk_buf; 1331 struct mboot boot_code; /* Buffer for master boot record */ 1332 struct ipart parts[FD_NUMPART]; 1333 uint32_t numcyl, nhead, nsect; 1334 uint32_t unixend; 1335 uint32_t blocksize; 1336 diskaddr_t capacity; 1337 int save_errno; 1338 size_t bytes_written; 1339 char asciilabel[LEN_DKL_ASCII]; 1340 char asciilabel2[LEN_DKL_ASCII] = "DEFAULT\0"; 1341 uint32_t acyl = 2; 1342 1343 DPRINTF("Writing default fdisk table and vtoc\n"); 1344 (void) memset(&v_toc, 0, sizeof (v_toc)); 1345 /* 1346 * Try getting disk geometry. 1347 */ 1348 if (ioctl(fd, DKIOCGGEOM, &dkg) < 0) 1349 if (ioctl(fd, DKIOCG_PHYGEOM, &dkg) < 0) { 1350 1351 DPRINTF("DKIOCG_PHYGEOM ioctl failed"); 1352 return; 1353 } 1354 1355 tmp_fd = open("/usr/lib/fs/ufs/mboot", O_RDONLY); 1356 if (tmp_fd <= 0) { 1357 return; 1358 } 1359 1360 if (read(tmp_fd, &boot_code, sizeof (struct mboot)) 1361 != sizeof (struct mboot)) { 1362 (void) close(tmp_fd); 1363 return; 1364 } 1365 1366 blocksize = med_info.sm_blocksize; 1367 fdisk_buf = (char *)malloc(blocksize); 1368 if (fdisk_buf == NULL) { 1369 DPRINTF("malloc for fdisk_buf failed\n"); 1370 return; 1371 } 1372 1373 (void) memset(&parts, 0, sizeof (parts)); 1374 1375 for (i = 0; i < FD_NUMPART; i++) { 1376 parts[i].systid = UNUSED; 1377 parts[i].numsect = lel(UNUSED); 1378 parts[i].relsect = lel(UNUSED); 1379 parts[i].bootid = 0; 1380 } 1381 1382 numcyl = dkg.dkg_ncyl; 1383 nhead = dkg.dkg_nhead; 1384 nsect = dkg.dkg_nsect; 1385 1386 parts[0].bootid = ACTIVE; 1387 parts[0].begsect = 1; 1388 1389 unixend = numcyl; 1390 1391 parts[0].relsect = lel(nhead * nsect); 1392 parts[0].numsect = lel(((diskaddr_t)numcyl * nhead * nsect)); 1393 parts[0].systid = SUNIXOS2; /* Solaris */ 1394 parts[0].beghead = 0; 1395 parts[0].begcyl = 1; 1396 parts[0].endhead = nhead - 1; 1397 parts[0].endsect = (nsect & 0x3f) | 1398 (char)((unixend >> 2) & 0x00c0); 1399 parts[0].endcyl = (char)(unixend & 0x00ff); 1400 1401 (void) memcpy(&(boot_code.parts), parts, sizeof (parts)); 1402 (void) memcpy(fdisk_buf, &boot_code, sizeof (boot_code)); 1403 1404 /* Turn on privileges. */ 1405 (void) __priv_bracket(PRIV_ON); 1406 1407 ret = ioctl(fd, DKIOCSMBOOT, fdisk_buf); 1408 1409 /* Turn off privileges. */ 1410 (void) __priv_bracket(PRIV_OFF); 1411 1412 if (ret == -1) { 1413 if (errno != ENOTTY) { 1414 PERROR("DKIOCSMBOOT ioctl Failed"); 1415 return; 1416 } 1417 1418 /* Turn on privileges. */ 1419 (void) __priv_bracket(PRIV_ON); 1420 1421 bytes_written = smedia_raw_write(handle, (diskaddr_t)0, 1422 fdisk_buf, blocksize); 1423 1424 /* Turn off privileges. */ 1425 (void) __priv_bracket(PRIV_OFF); 1426 1427 save_errno = errno; 1428 errno = save_errno; 1429 if (bytes_written != blocksize) { 1430 if (errno == ENOTSUP) { 1431 1432 /* Turn on privileges. */ 1433 (void) __priv_bracket(PRIV_ON); 1434 1435 ret = write(fd, fdisk_buf, blocksize); 1436 1437 /* Turn off privileges. */ 1438 (void) __priv_bracket(PRIV_OFF); 1439 1440 if (ret != blocksize) { 1441 return; 1442 } 1443 } else { 1444 return; 1445 } 1446 } 1447 } 1448 capacity = (diskaddr_t)(numcyl - 1) * nhead * nsect; 1449 1450 v_toc.v_nparts = V_NUMPAR; 1451 v_toc.v_sanity = VTOC_SANE; 1452 v_toc.v_version = V_VERSION; 1453 v_toc.v_sectorsz = DEV_BSIZE; 1454 1455 v_toc.v_part[0].p_start = 0; 1456 v_toc.v_part[0].p_size = capacity; 1457 v_toc.v_part[0].p_tag = V_ROOT; 1458 v_toc.v_part[0].p_flag = 0; /* Mountable */ 1459 1460 v_toc.v_part[2].p_start = 0; 1461 v_toc.v_part[2].p_size = capacity; 1462 v_toc.v_part[2].p_tag = V_BACKUP; 1463 v_toc.v_part[2].p_flag = V_UNMNT; 1464 1465 /* Create asciilabel for compatibility with format utility */ 1466 (void) snprintf(asciilabel, sizeof (asciilabel), 1467 "%s cyl %d alt %d hd %d sec %d", 1468 asciilabel2, numcyl, acyl, nhead, nsect); 1469 (void) memcpy(v_toc.v_asciilabel, asciilabel, 1470 LEN_DKL_ASCII); 1471 1472 errno = 0; 1473 1474 1475 /* Turn on privileges. */ 1476 (void) __priv_bracket(PRIV_ON); 1477 1478 ret = write_extvtoc(fd, &v_toc); 1479 1480 /* Turn off privileges. */ 1481 (void) __priv_bracket(PRIV_OFF); 1482 1483 if (ret < 0) { 1484 PERROR("write VTOC failed"); 1485 DPRINTF1("Errno = %d\n", errno); 1486 } 1487 } 1488 1489 #else /* !i386 */ 1490 1491 #error One of sparc or i386 must be defined! 1492 1493 #endif /* i386 */ 1494 #endif /* sparc */ 1495 1496 /* 1497 * void overwrite_metadata(int32_t fd, smedia_handle_t handle) 1498 * 1499 * purpose : quick format does not erase the data on Iomega 1500 * zip/jaz media. So, the meta data on the disk should be erased. 1501 * 1502 * If there is a valid fdisk table, 1503 * erase first 64K of each partition. 1504 * If there is a valid vtoc, 1505 * erase first 64k of each slice. 1506 * Then erase the 0th sector (the home for vtoc and fdisk) of the disk. 1507 * Note that teh vtoc on x86 resides in one of the fdisk partition. 1508 * So delay the erasing of the solaris partition until the vtoc is read. 1509 */ 1510 1511 void 1512 overwrite_metadata(int32_t fd, smedia_handle_t handle) 1513 { 1514 1515 struct fdisk_info fdisk; 1516 diskaddr_t sol_offset = 0; 1517 int i, ret; 1518 struct extvtoc t_vtoc; 1519 #ifdef i386 1520 diskaddr_t sol_size = 0; 1521 int32_t active = 0; 1522 #endif /* i386 */ 1523 1524 /* Get fdisk info. */ 1525 if (get_fdisk(handle, fd, 0, &fdisk) >= 0) { 1526 /* Got a valid fdisk */ 1527 for (i = 0; i < FD_NUMPART; i++) { 1528 1529 if (fdisk.part[i].numsect == 0) 1530 continue; 1531 if ((fdisk.part[i].systid == UNUSED) || 1532 (fdisk.part[i].systid == 0)) 1533 continue; 1534 #ifdef i386 1535 if (fdisk.part[i].systid == SUNIXOS || 1536 fdisk.part[i].systid == SUNIXOS2) { 1537 if (!sol_offset) { 1538 sol_offset = fdisk.part[i].relsect; 1539 sol_size = fdisk.part[i].numsect; 1540 if (fdisk.part[i].bootid == ACTIVE) 1541 active = 1; 1542 continue; 1543 } else if ((fdisk.part[i].bootid == ACTIVE) && 1544 (!active)) { 1545 erase(handle, sol_offset, sol_size); 1546 sol_offset = fdisk.part[i].relsect; 1547 sol_size = fdisk.part[i].numsect; 1548 active = 1; 1549 continue; 1550 } 1551 } 1552 #endif /* i386 */ 1553 erase(handle, (diskaddr_t)fdisk.part[i].relsect, 1554 (diskaddr_t)fdisk.part[i].numsect); 1555 } 1556 } 1557 1558 (void) memset(&t_vtoc, 0, sizeof (t_vtoc)); 1559 1560 if (sol_offset) { 1561 /* fdisk x86 Solaris partition */ 1562 /* VTOC location in solaris partition is DK_LABEL_LOC */ 1563 1564 /* Turn on privileges. */ 1565 (void) __priv_bracket(PRIV_ON); 1566 1567 ret = read_extvtoc(fd, &t_vtoc); 1568 1569 /* Turn off privileges. */ 1570 (void) __priv_bracket(PRIV_OFF); 1571 1572 if (ret < 0) { 1573 /* No valid vtoc, erase fdisk table. */ 1574 erase(handle, (diskaddr_t)0, (diskaddr_t)1); 1575 return; 1576 } 1577 } else { 1578 /* Sparc Solaris or x86 solaris with faked fdisk */ 1579 1580 /* Turn on privileges */ 1581 (void) __priv_bracket(PRIV_ON); 1582 1583 ret = read_extvtoc(fd, &t_vtoc); 1584 1585 /* Turn off privileges. */ 1586 (void) __priv_bracket(PRIV_OFF); 1587 1588 if (ret < 0) { 1589 /* No valid vtoc, erase from 0th sector */ 1590 erase(handle, (diskaddr_t)0, 1591 (uint32_t)med_info.sm_capacity); 1592 return; 1593 } 1594 } 1595 1596 for (i = 0; i < V_NUMPAR; i++) { 1597 if (t_vtoc.v_part[i].p_size != 0) { 1598 erase(handle, sol_offset + t_vtoc.v_part[i].p_start, 1599 t_vtoc.v_part[i].p_size); 1600 /* 1601 * To make the udfs not recognise the partition we will 1602 * erase sectors 256, (p_size-256) and psize. 1603 */ 1604 erase(handle, 1605 sol_offset + t_vtoc.v_part[i].p_start + 256, 1606 (diskaddr_t)1); 1607 erase(handle, 1608 (sol_offset + t_vtoc.v_part[i].p_start + 1609 t_vtoc.v_part[i].p_size - 256), 1610 (diskaddr_t)1); 1611 erase(handle, 1612 (sol_offset + t_vtoc.v_part[i].p_start + 1613 t_vtoc.v_part[i].p_size - 1), 1614 (diskaddr_t)1); 1615 } 1616 } 1617 1618 /* 1619 * If x86 fdisk solaris partition, erase the vtoc also. 1620 * for sparc, the erasing 0the sector erases vtoc. 1621 */ 1622 if (sol_offset) { 1623 erase(handle, sol_offset, (diskaddr_t)DK_LABEL_LOC + 2); 1624 } 1625 1626 /* 1627 * erase the 0th sector, it is not guaranteed to be 1628 * erased in the above sequence. 1629 */ 1630 1631 erase(handle, (diskaddr_t)0, (diskaddr_t)1); 1632 } 1633 1634 /* 1635 * void erase(smedia_handle_t handle, uint32_t offset, uint32_t size) 1636 * 1637 * Initialize the media with '0' from offset 'offset' upto 'size' 1638 * or 128 blocks(64k), whichever is smaller. 1639 */ 1640 1641 static void 1642 erase(smedia_handle_t handle, diskaddr_t offset, diskaddr_t size) 1643 { 1644 char *buf; 1645 diskaddr_t nblocks = size; 1646 int32_t ret; 1647 1648 1649 nblocks = (nblocks < 128) ? nblocks : 128; 1650 buf = (char *)malloc(nblocks * med_info.sm_blocksize); 1651 if (buf == NULL) { 1652 PERROR("malloc failed"); 1653 return; 1654 } 1655 (void) memset(buf, 0, (size_t)nblocks * med_info.sm_blocksize); 1656 1657 /* Turn on privileges. */ 1658 (void) __priv_bracket(PRIV_ON); 1659 1660 ret = smedia_raw_write(handle, offset, buf, 1661 (size_t)nblocks * med_info.sm_blocksize); 1662 1663 /* Turn off privileges. */ 1664 (void) __priv_bracket(PRIV_OFF); 1665 1666 if (ret != (nblocks * med_info.sm_blocksize)) 1667 PERROR("error in writing\n"); 1668 1669 free(buf); 1670 1671 } 1672