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 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 /* 416 * Copy it into the clean buffer. 417 */ 418 (void) strcpy(cleantoken, ptr); 419 /* 420 * Strip off trailing white-space. 421 */ 422 for (ptr = cleantoken + strlen(cleantoken) - 1; 423 isspace(*ptr) && (ptr >= cleantoken); ptr--) { 424 *ptr = '\0'; 425 } 426 } 427 428 static int32_t 429 sup_setpart(struct extvtoc *vt) 430 { 431 TOKEN token, cleaned, ident; 432 int32_t i, index, status; 433 uint64_t val1, val2; 434 ushort_t vtoc_tag = 0xFFFF; 435 ushort_t vtoc_flag = 0xFFFF; 436 437 /* 438 * Pull in some grammar. 439 */ 440 441 status = sup_gettoken(token); 442 443 if (status != SUP_COLON) { 444 (void) fprintf(stderr, 445 gettext("Expecting ':', found '%s'"), token); 446 (void) fprintf(stderr, 447 gettext("Line no %d\n"), data_lineno); 448 return (-1); 449 } 450 451 for (;;) { 452 status = sup_gettoken(token); 453 if (status != SUP_STRING) { 454 (void) fprintf(stderr, 455 gettext("Expecting string, found '%s'"), token); 456 (void) fprintf(stderr, 457 gettext("Line no %d\n"), data_lineno); 458 return (-1); 459 } 460 clean_token(ident, token); 461 /* 462 * Here's the index of the partition we're dealing with 463 */ 464 index = (int32_t)my_atoll(ident); 465 if ((index < 0) || (index >= NDKMAP)) { 466 (void) fprintf(stderr, 467 gettext("Unknown partition %d"), index); 468 (void) fprintf(stderr, 469 gettext("Line no %d\n"), data_lineno); 470 return (-1); 471 } 472 /* 473 * Check for floppy and PCMCIA_MEM cards. 474 * for floppy, the partition no. can be 0 1 2. 475 * for PCMCIA, the partition no. can be 2 476 */ 477 if (med_info.sm_media_type == SM_FLOPPY) { 478 if ((index < 0) || (index > 2)) { 479 (void) fprintf(stderr, gettext( 480 "Floppy can have partitions 0 1 and 2\n")); 481 return (-1); 482 } 483 } 484 if (med_info.sm_media_type == SM_PCMCIA_MEM) { 485 if (index != 2) { 486 (void) fprintf(stderr, gettext( 487 "PCMCIA Memory cards can have partition 2 only.\n")); 488 return (-1); 489 } 490 } 491 492 DPRINTF1("\n Partition %d: ", index); 493 494 status = sup_gettoken(token); 495 if (status != SUP_EQL) { 496 (void) fprintf(stderr, 497 gettext("Expecting '=', found '%s'"), token); 498 (void) fprintf(stderr, 499 gettext("Line no %d\n"), data_lineno); 500 return (-1); 501 502 } 503 504 505 status = sup_gettoken(token); 506 /* 507 * If we hit a key character, it's an error. 508 */ 509 if (status != SUP_STRING) { 510 (void) fprintf(stderr, 511 gettext("Expecting value, found '%s'"), token); 512 (void) fprintf(stderr, 513 gettext("Line no %d\n"), data_lineno); 514 return (-1); 515 } 516 clean_token(cleaned, token); 517 /* 518 * <tag> may be one of: boot, root, swap, etc. 519 * <flag> consists of two characters: 520 * W (writable) or R (read-only) 521 * M (mountable) or U (unmountable) 522 * 523 * Start with the defaults assigned above: 524 */ 525 526 /* 527 * All other attributes have a pair of numeric values. 528 * Convert the first value to a number. This value 529 * is the starting cylinder number of the partition. 530 */ 531 532 /* Check for valid partition, e.g. > 8 or 16 */ 533 val1 = str2sector(cleaned); 534 if (val1 == -1) { 535 (void) fprintf(stderr, 536 gettext("Invalid partition beggining %s \n"), 537 cleaned); 538 (void) fprintf(stderr, 539 gettext("Line no %d\n"), data_lineno); 540 } 541 542 DPRINTF1(" begins %s", cleaned); 543 /* 544 * Pull in some grammar. 545 */ 546 status = sup_gettoken(token); 547 if (status != SUP_COMMA) { 548 (void) fprintf(stderr, 549 gettext("Expecting ', ', found '%s'"), token); 550 (void) fprintf(stderr, 551 gettext("Line no %d\n"), data_lineno); 552 return (-1); 553 } 554 /* 555 * Pull in the second value. 556 */ 557 status = sup_gettoken(token); 558 if (status != SUP_STRING) { 559 (void) fprintf(stderr, 560 gettext("Expecting value, found '%s'"), token); 561 (void) fprintf(stderr, 562 gettext("Line no %d\n"), data_lineno); 563 return (-1); 564 } 565 clean_token(cleaned, token); 566 567 val2 = str2sector(cleaned); 568 if (val2 == -1) { 569 (void) fprintf(stderr, 570 gettext("Invalid partition size %s \n"), 571 cleaned); 572 (void) fprintf(stderr, 573 gettext("Line no %d\n"), data_lineno); 574 } 575 DPRINTF1(" ends %s ", cleaned); 576 577 /* 578 * Pull in some grammar. 579 */ 580 status = sup_gettoken(token); 581 582 if (status == SUP_COMMA) { 583 /* tags and flags */ 584 status = sup_gettoken(token); 585 if (status != SUP_STRING) { 586 (void) fprintf(stderr, 587 gettext("Expecting value, found '%s'"), 588 token); 589 (void) fprintf(stderr, 590 gettext("Line no %d\n"), data_lineno); 591 return (-1); 592 } 593 clean_token(cleaned, token); 594 if (find_value(pflag_choices, cleaned, &i) == 1) { 595 /* 596 * Found valid tag. Use it and advance parser 597 */ 598 DPRINTF1(" flag = %s", cleaned); 599 vtoc_flag = (ushort_t)i; 600 status = sup_gettoken(token); 601 } else if (find_value(ptag_choices, cleaned, &i) == 1) { 602 DPRINTF1(" tag = %s", cleaned); 603 vtoc_tag = (ushort_t)i; 604 status = sup_gettoken(token); 605 if (status == SUP_COMMA) { 606 (void) fprintf(stderr, 607 gettext("Expecting : got %s\n"), 608 token); 609 (void) fprintf(stderr, 610 gettext("Line no %d\n"), 611 data_lineno); 612 return (-1); 613 } 614 } else { 615 (void) fprintf(stderr, 616 gettext("Invalid flag or tag\n")); 617 (void) fprintf(stderr, 618 gettext("Line no %d\n"), data_lineno); 619 return (-1); 620 } 621 622 623 if (status == SUP_COMMA) { 624 /* Can be tag only */ 625 626 status = sup_gettoken(token); 627 if (status != SUP_STRING) { 628 (void) fprintf(stderr, 629 gettext("Expecting value" 630 ", found '%s'"), 631 token); 632 (void) fprintf(stderr, 633 gettext("Line no %d\n"), 634 data_lineno); 635 return (-1); 636 } 637 638 clean_token(cleaned, token); 639 if (find_value(ptag_choices, 640 cleaned, &i) == 1) { 641 DPRINTF1(" tag = %s", cleaned); 642 vtoc_tag = (ushort_t)i; 643 } 644 status = sup_gettoken(token); 645 } 646 } 647 648 /* 649 * Fill in the appropriate map entry with the values. 650 */ 651 vt->v_part[index].p_start = val1; 652 vt->v_part[index].p_size = val2; 653 if (vtoc_tag != 0xFFFF) { 654 vt->v_part[index].p_tag = vtoc_tag; 655 vtoc_tag = 0xFFFF; 656 } 657 if (vtoc_flag != 0xFFFF) { 658 vt->v_part[index].p_flag = vtoc_flag; 659 vtoc_flag = 0xFFFF; 660 } 661 if (status == SUP_EOF) { 662 DPRINTF("\nEnd of file\n"); 663 break; 664 } 665 if (status != SUP_COLON) { 666 (void) fprintf(stderr, 667 gettext("Expecting ':', found '%s'"), token); 668 (void) fprintf(stderr, 669 gettext("Line no %d\n"), data_lineno); 670 return (-1); 671 } 672 673 } 674 return (0); 675 } 676 677 static int32_t 678 find_value(slist_t *slist, char *match_str, int32_t *match_value) 679 { 680 int32_t i; 681 int32_t nmatches; 682 int32_t length; 683 int32_t match_length; 684 685 nmatches = 0; 686 length = 0; 687 688 match_length = strlen(match_str); 689 690 for (; slist->str != NULL; slist++) { 691 /* 692 * See how many characters of the token match 693 */ 694 i = strcnt(match_str, slist->str); 695 /* 696 * If it's not the whole token, then it's not a match. 697 */ 698 if (i < match_length) { 699 continue; 700 } 701 /* 702 * If it ties with another input, remember that. 703 */ 704 if (i == length) 705 nmatches++; 706 /* 707 * If it matches the most so far, record that. 708 */ 709 if (i > length) { 710 *match_value = slist->value; 711 nmatches = 1; 712 length = i; 713 } 714 } 715 716 return (nmatches); 717 } 718 719 static int32_t 720 strcnt(char *s1, char *s2) 721 { 722 int32_t i = 0; 723 724 while ((*s1 != '\0') && (*s1++ == *s2++)) 725 i++; 726 return (i); 727 } 728 729 static uint64_t 730 str2sector(char *str) 731 { 732 int32_t mul_factor = 1; 733 char *s1, *s2, *base; 734 uint64_t num_sectors; 735 uint64_t size; 736 737 base = s2 = (char *)malloc(strlen(str) + 1); 738 if (s2 == NULL) { 739 PERROR("Malloc failed"); 740 return (-1); 741 } 742 *s2 = '\0'; 743 744 745 746 s1 = str; 747 while (*s1) { 748 if ((*s1 != 'x') && ((*s1 < 'A') || (*s1 > 'F')) && 749 ((*s1 < 'a') || (*s1 > 'f')) && ((*s1 < '0') || 750 (*s1 > '9'))) { 751 if (*s1 == 'G') { 752 mul_factor = 1024*1024*1024; 753 s1++; 754 } else if (*s1 == 'M') { 755 mul_factor = 1024*1024; 756 s1++; 757 } else if (*s1 == 'K') { 758 mul_factor = 1024; 759 s1++; 760 } 761 if ((*s1 != 'B') || (*(++s1) != '\0')) { 762 (void) fprintf(stderr, 763 gettext("Extra chars at the end\n")); 764 free(base); 765 return (-1); 766 } 767 break; 768 } else { 769 *s2++ = *s1++; 770 *s2 = '\0'; 771 } 772 } 773 *s2 = '\0'; 774 775 size = my_atoll(base); 776 if ((!mul_factor) || (size == -1)) { 777 free(base); 778 return (-1); 779 } 780 num_sectors = size * (uint64_t)mul_factor /512; 781 782 free(base); 783 return (num_sectors); 784 } 785 786 787 int32_t 788 valid_slice_file(smedia_handle_t handle, int32_t fd, char *file_name, 789 struct extvtoc *vt) 790 { 791 struct stat status; 792 int32_t ret_val; 793 if (stat(file_name, &status)) { 794 PERROR(file_name); 795 return (-1); 796 } 797 (void) memset(vt, 0, sizeof (*vt)); 798 /* Set default tag and flag */ 799 #ifdef sparc 800 vt->v_part[0].p_tag = V_ROOT; 801 vt->v_part[1].p_tag = V_SWAP; 802 vt->v_part[2].p_tag = V_BACKUP; 803 vt->v_part[6].p_tag = V_USR; 804 805 vt->v_part[1].p_flag = V_UNMNT; /* Unmountable */ 806 vt->v_part[2].p_flag = V_UNMNT; /* Unmountable */ 807 #endif 808 809 ret_val = sup_prxfile(file_name, vt); 810 if (ret_val < 0) 811 return (-1); 812 813 #ifdef DEBUG 814 { 815 int32_t i; 816 for (i = 0; i < 8; i++) { 817 DPRINTF1("\npart %d\n", i); 818 DPRINTF1("\t start %llu", vt->v_part[i].p_start); 819 DPRINTF1("\t size %llu ", vt->v_part[i].p_size); 820 DPRINTF1("\t tag %d", vt->v_part[i].p_tag); 821 DPRINTF1("\t flag %d", vt->v_part[i].p_flag); 822 } 823 } 824 #endif /* DEBUG */ 825 if (check_vtoc_sanity(handle, fd, vt) < 0) { 826 return (-1); 827 } 828 #ifdef DEBUG 829 { 830 int32_t i; 831 for (i = 0; i < 8; i++) { 832 DPRINTF1("\npart %d\n", i); 833 DPRINTF1("\t start %llu", vt->v_part[i].p_start); 834 DPRINTF1("\t size %llu ", vt->v_part[i].p_size); 835 DPRINTF1("\t tag %d", vt->v_part[i].p_tag); 836 DPRINTF1("\t flag %d", vt->v_part[i].p_flag); 837 } 838 } 839 #endif /* DEBUG */ 840 return (0); 841 } 842 843 #define SWAP(a, b) {diskaddr_t tmp; tmp = (a); (a) = (b); (b) = tmp; } 844 845 /* 846 * On x86 Solaris, the partitioning is done in two levels, fdisk and Solaris 847 * VTOC. Where as, on sparc solaris, it is only VTOC. On floppy and PCMCIA 848 * also it is assumed to be only VTOC, no fdisk. 849 * 850 * On sparc, the back up slice can cover the whole medium. But on x86 851 * (SCSI/ATAPI disks), the backup slice can cover the solaris partition 852 * in fdisk table. 853 * Following table describes how is it handled 854 * SPARC: 855 * SCSI/ATAPI, floppy, pcmcia : don't check for fdisk. 856 * DKIOCGGEOM is sufficient. 857 * x86 : floppy, pcmcia : Don't check for fdisk. DKIOCGGEOM is sufficient. 858 * SCSI/ATAPI : Check for fdisk. 859 * if not present, assume that the solaris 860 * partition covers 100% of the medium 861 * (minus one cylinder). 862 * 863 * if present : 864 * check for active solaris partition. 865 * if not found, take the first solaris 866 * partition. 867 * If there are no solaris partitions, its an error, stop. 868 */ 869 870 static int32_t 871 check_vtoc_sanity(smedia_handle_t handle, int32_t fd, struct extvtoc *vt) 872 { 873 874 int32_t i, j; 875 struct dk_geom dkg; 876 int32_t num_backup = 0; 877 diskaddr_t backup_size = 0; 878 struct part_struct { 879 diskaddr_t start; 880 diskaddr_t end; 881 int32_t num; 882 } part[NDKMAP]; 883 diskaddr_t min_val; 884 int32_t min_slice, num_slices; 885 diskaddr_t media_size; 886 uint32_t cyl_size; 887 int sparc_style = 0; /* sparc_style handling ? */ 888 struct fdisk_info fdisk; 889 int sol_part; 890 int total_parts = 0; 891 892 #ifdef sparc 893 sparc_style = 1; 894 #endif /* sparc */ 895 896 if ((med_info.sm_media_type == SM_FLOPPY) || 897 (med_info.sm_media_type == SM_PCMCIA_MEM) || 898 (med_info.sm_media_type == SM_PCMCIA_ATA) || 899 (med_info.sm_media_type == SM_SCSI_FLOPPY)) { 900 sparc_style = 1; 901 } 902 903 if (sparc_style) { 904 DPRINTF("sparc style true\n"); 905 if (ioctl(fd, DKIOCGGEOM, &dkg) < 0) { 906 PERROR("DKIOCGGEOM Failed"); 907 return (-1); 908 } 909 media_size = (diskaddr_t)dkg.dkg_ncyl * dkg.dkg_nhead * 910 dkg.dkg_nsect; 911 cyl_size = dkg.dkg_nhead * dkg.dkg_nsect; 912 } 913 914 if (!sparc_style) { 915 /* 916 * Try to get the fdisk information if available. 917 */ 918 if (get_fdisk(handle, fd, 0, &fdisk) >= 0) { 919 /* fdisk table on disk */ 920 sol_part = 0xFF; 921 for (i = 0; i < FD_NUMPART; i++) { 922 if (fdisk.part[i].systid == SUNIXOS || 923 fdisk.part[i].systid == SUNIXOS2) { 924 if (sol_part == 0xFF) 925 sol_part = i; 926 total_parts++; 927 if (fdisk.part[i].bootid == ACTIVE) 928 sol_part = i; 929 } 930 } 931 if (sol_part == 0xFF) { 932 /* No Solaris partition */ 933 934 (void) fprintf(stderr, gettext("No FDISK \ 935 Solaris partition found!\n")); 936 return (-1); 937 } 938 if (total_parts > 1) 939 (void) fprintf(stderr, gettext("Multiple FDISK \ 940 Solaris partitions found.\n")); 941 media_size = (diskaddr_t)fdisk.part[sol_part].numsect; 942 943 DPRINTF1("sol_part %d\n", sol_part); 944 DPRINTF1("media_size %llu\n", media_size); 945 } else { 946 DPRINTF("Didn't get fdisk\n"); 947 /* 948 * No fdisk partition available. Assume a 100% Solaris. 949 * partition. 950 * Try getting disk geometry. 951 */ 952 if (ioctl(fd, DKIOCGGEOM, &dkg) < 0) 953 if (ioctl(fd, DKIOCG_PHYGEOM, &dkg) < 0) { 954 DPRINTF("DKIOCG_PHYGEOM ioctl failed"); 955 return (-1); 956 } 957 /* On x86 platform 1 cylinder is used for fdisk table */ 958 dkg.dkg_ncyl = dkg.dkg_ncyl - 1; 959 media_size = (diskaddr_t)dkg.dkg_ncyl * dkg.dkg_nhead * 960 dkg.dkg_nsect; 961 } 962 } 963 964 #ifdef DEBUG 965 DPRINTF1("Ncyl %d\n", dkg.dkg_ncyl); 966 DPRINTF1("nhead %d\n", dkg.dkg_nhead); 967 DPRINTF1("nsect %d\n", dkg.dkg_nsect); 968 #endif /* DEBUG */ 969 970 if (media_size == 0) { 971 media_size = (uint32_t)med_info.sm_capacity; 972 } 973 974 (void) memset(&part, 0, sizeof (part)); 975 for (i = 0, j = 0; i < NDKMAP; i++) { 976 if (vt->v_part[i].p_tag == V_BACKUP) { 977 if (vt->v_part[i].p_start != 0) { 978 (void) fprintf(stderr, 979 gettext( 980 "Backup slice should start at sector 0\n")); 981 return (-1); 982 } 983 backup_size = vt->v_part[i].p_size; 984 num_backup++; 985 continue; 986 } 987 if (vt->v_part[i].p_size) { 988 989 if (sparc_style) { 990 if (vt->v_part[i].p_start % cyl_size) { 991 (void) fprintf(stderr, 992 gettext( 993 "Slice %d does not start on cylinder boundary\n"), i); 994 (void) fprintf(stderr, 995 gettext( 996 "Cylinder size %d 512 byte sectors\n"), cyl_size); 997 return (-1); 998 } 999 } 1000 part[j].start = vt->v_part[i].p_start; 1001 part[j].end = vt->v_part[i].p_start + 1002 vt->v_part[i].p_size -1; 1003 part[j].num = i; 1004 j++; 1005 } 1006 } 1007 if (num_backup > 1) { 1008 (void) fprintf(stderr, 1009 gettext("Maximum one backup slice is allowed\n")); 1010 (void) smedia_release_handle(handle); 1011 (void) close(fd); 1012 exit(1); 1013 } 1014 num_slices = j; 1015 1016 for (i = 0; i < num_slices; i++) { 1017 min_val = part[i].start; 1018 min_slice = i; 1019 for (j = i+1; j < num_slices; j++) { 1020 if (part[j].start < min_val) { 1021 min_val = part[j].start; 1022 min_slice = j; 1023 } 1024 } 1025 if (min_slice != i) { 1026 SWAP(part[i].start, part[min_slice].start) 1027 SWAP(part[i].end, part[min_slice].end) 1028 SWAP(part[i].num, part[min_slice].num) 1029 } 1030 } 1031 1032 #ifdef DEBUG 1033 for (i = 0; i < num_slices; i++) { 1034 DPRINTF4("\n %d (%d) : %llu, %llu", i, part[i].num, 1035 part[i].start, part[i].end); 1036 } 1037 #endif /* DEBUG */ 1038 1039 if (backup_size > media_size) { 1040 if (sparc_style) { 1041 (void) fprintf(stderr, 1042 gettext( 1043 "Backup slice extends beyond size of media\n")); 1044 (void) fprintf(stderr, 1045 gettext("media size : %llu sectors \n"), 1046 media_size); 1047 } else { 1048 1049 (void) fprintf(stderr, 1050 gettext("Backup slice extends beyond size of FDISK \ 1051 Solaris partition\n")); 1052 (void) fprintf(stderr, 1053 gettext( 1054 "FDISK Solaris partition size : %llu sectors \n"), 1055 media_size); 1056 } 1057 return (-1); 1058 } 1059 1060 /* 1061 * If we have only backup slice return success here. 1062 */ 1063 if (num_slices == 0) 1064 return (0); 1065 1066 if (backup_size) { 1067 if (part[num_slices - 1].end > backup_size) { 1068 (void) fprintf(stderr, 1069 gettext("Slice %d extends beyond backup slice.\n"), 1070 part[num_slices -1].num); 1071 return (-1); 1072 } 1073 } else { 1074 if (part[num_slices - 1].end > media_size) { 1075 if (sparc_style) { 1076 (void) fprintf(stderr, 1077 gettext( 1078 "Slice %d extends beyond media size\n"), 1079 part[num_slices -1].num); 1080 (void) fprintf(stderr, 1081 gettext("media size : %llu sectors \n"), 1082 media_size); 1083 } else { 1084 (void) fprintf(stderr, 1085 gettext("Slice %d extends beyond FDISK" 1086 " Solaris partition size\n"), 1087 part[num_slices -1].num); 1088 (void) fprintf(stderr, gettext( 1089 "FDISK Solaris partition size : %llu " 1090 "sectors \n"), media_size); 1091 } 1092 return (-1); 1093 } 1094 } 1095 1096 1097 1098 for (i = 0; i < num_slices; i++) { 1099 if (i == 0) 1100 continue; 1101 if (part[i].start <= part[i-1].end) { 1102 (void) fprintf(stderr, 1103 gettext("Overlap between slices %d and %d\n"), 1104 part[i-1].num, part[i].num); 1105 (void) smedia_release_handle(handle); 1106 (void) close(fd); 1107 exit(1); 1108 } 1109 } 1110 1111 return (0); 1112 } 1113 1114 1115 static int32_t 1116 get_fdisk(smedia_handle_t handle, int32_t fd, int32_t offset, 1117 struct fdisk_info *fdisk) 1118 { 1119 struct mboot *boot_sec; 1120 struct ipart *part; 1121 char *buf; 1122 int32_t i, ret; 1123 int save_errno; 1124 1125 /* Read the master boot program */ 1126 1127 buf = (char *)malloc(med_info.sm_blocksize); 1128 if (buf == NULL) { 1129 PERROR("malloc failed"); 1130 exit(1); 1131 } 1132 errno = 0; 1133 ret = ioctl(fd, DKIOCGMBOOT, buf); 1134 if (ret < 0) { 1135 if (errno != ENOTTY) { 1136 PERROR("DKIOCGMBOOT ioctl failed"); 1137 return (-1); 1138 } 1139 1140 /* Turn on privileges. */ 1141 (void) __priv_bracket(PRIV_ON); 1142 1143 ret = smedia_raw_read(handle, 1144 (diskaddr_t)offset/med_info.sm_blocksize, 1145 buf, med_info.sm_blocksize); 1146 1147 /* Turn off privileges. */ 1148 (void) __priv_bracket(PRIV_OFF); 1149 1150 save_errno = errno; 1151 errno = save_errno; 1152 if (ret != med_info.sm_blocksize) { 1153 if (errno == ENOTSUP) { 1154 errno = 0; 1155 if (lseek(fd, offset, SEEK_SET)) { 1156 PERROR("Seek failed:"); 1157 free(buf); 1158 return (-1); 1159 } 1160 1161 /* Turn on privileges. */ 1162 (void) __priv_bracket(PRIV_ON); 1163 1164 ret = read(fd, buf, sizeof (struct mboot)); 1165 1166 /* Turn off privileges. */ 1167 (void) __priv_bracket(PRIV_OFF); 1168 1169 if (ret != sizeof (struct mboot)) { 1170 PERROR("Could not read " 1171 "master boot record"); 1172 free(buf); 1173 return (-1); 1174 } 1175 } else { 1176 PERROR("Could not read master boot record"); 1177 free(buf); 1178 return (-1); 1179 } 1180 } 1181 } 1182 /* LINTED pointer cast may result in improper alignment */ 1183 boot_sec = (struct mboot *)buf; 1184 1185 /* Is this really a master boot record? */ 1186 if (les(boot_sec->signature) != MBB_MAGIC) { 1187 DPRINTF("fdisk: Invalid master boot file \n"); 1188 DPRINTF2("Bad magic number: is %x, should be %x.\n", 1189 les(boot_sec->signature), MBB_MAGIC); 1190 free(buf); 1191 return (-1); 1192 } 1193 1194 for (i = 0; i < FD_NUMPART; i++) { 1195 DPRINTF1("part %d\n", i); 1196 /* LINTED pointer cast may result in improper alignment */ 1197 part = (struct ipart *)&boot_sec->parts[i * 1198 sizeof (struct ipart)]; 1199 fdisk->part[i].bootid = part->bootid; 1200 if (part->bootid && (part->bootid != ACTIVE)) { 1201 /* Hmmm...not a valid fdisk! */ 1202 return (-1); 1203 } 1204 fdisk->part[i].systid = part->systid; 1205 1206 /* To avoid the misalign access in sparc */ 1207 1208 fdisk->part[i].relsect = lel(GET_32(&(part->relsect))); 1209 fdisk->part[i].numsect = lel(GET_32(&(part->numsect))); 1210 1211 DPRINTF1("\tboot id 0x%x\n", part->bootid); 1212 DPRINTF1("\tsystem id 0x%x\n", part->systid); 1213 DPRINTF1("\trel sector 0x%x\n", fdisk->part[i].relsect); 1214 DPRINTF1("\tnum sector 0x%x\n", fdisk->part[i].numsect); 1215 } 1216 free(buf); 1217 return (0); 1218 } 1219 1220 1221 /* 1222 * write_default_label(int32_t fd) 1223 * fd = file descriptor for the device. 1224 * 1225 * For sparc solaris 1226 * Create a vtoc partition with 1227 * slice 0 = slice 2 = medium capacity. 1228 * The cyl, head, sect (CHS) values are computed as done in sd 1229 * capacity <= 1GB, 1230 * nhead = 64, nsect = 32 1231 * capacity > 1gb, 1232 * nhead = 255, nsect = 63 1233 * 1234 * For x86 solaris 1235 * Create a fdisk partition, 1236 * partition 0 covers the full medium, the partition 1237 * type is set to Solaris. 1238 * Then create solaris vtoc. The algorithm is same as sparc solaris. 1239 * But the capacity is reduced by 1 cyl, to leave space for fdisk table. 1240 */ 1241 1242 #ifdef sparc 1243 /*ARGSUSED*/ 1244 void 1245 write_default_label(smedia_handle_t handle, int32_t fd) 1246 { 1247 1248 struct extvtoc v_toc; 1249 uint32_t nhead, numcyl, nsect; 1250 diskaddr_t capacity; 1251 int32_t ret; 1252 char asciilabel[LEN_DKL_ASCII]; 1253 char asciilabel2[LEN_DKL_ASCII] = "DEFAULT\0"; 1254 uint32_t acyl = 2; 1255 1256 1257 DPRINTF("Writing default vtoc\n"); 1258 (void) memset(&v_toc, 0, sizeof (v_toc)); 1259 1260 1261 v_toc.v_nparts = V_NUMPAR; 1262 v_toc.v_sanity = VTOC_SANE; 1263 v_toc.v_version = V_VERSION; 1264 v_toc.v_sectorsz = DEV_BSIZE; 1265 1266 /* 1267 * For the head, cyl and number of sector per track, 1268 * if the capacity <= 1GB, head = 64, sect = 32. 1269 * else head = 255, sect 63 1270 * NOTE: the capacity should be equal to C*H*S values. 1271 * This will cause some truncation of size due to 1272 * round off errors. 1273 */ 1274 if ((uint32_t)med_info.sm_capacity <= 0x200000) { 1275 nhead = 64; 1276 nsect = 32; 1277 } else { 1278 nhead = 255; 1279 nsect = 63; 1280 } 1281 1282 numcyl = (uint32_t)med_info.sm_capacity / (nhead * nsect); 1283 capacity = (diskaddr_t)nhead * nsect * numcyl; 1284 1285 v_toc.v_part[0].p_start = 0; 1286 v_toc.v_part[0].p_size = capacity; 1287 v_toc.v_part[0].p_tag = V_ROOT; 1288 v_toc.v_part[0].p_flag = 0; /* Mountable */ 1289 1290 v_toc.v_part[2].p_start = 0; 1291 v_toc.v_part[2].p_size = capacity; 1292 v_toc.v_part[2].p_tag = V_BACKUP; 1293 v_toc.v_part[2].p_flag = V_UNMNT; 1294 1295 /* Create asciilabel for compatibility with format utility */ 1296 (void) snprintf(asciilabel, sizeof (asciilabel), 1297 "%s cyl %d alt %d hd %d sec %d", 1298 asciilabel2, numcyl, acyl, nhead, nsect); 1299 (void) memcpy(v_toc.v_asciilabel, asciilabel, 1300 LEN_DKL_ASCII); 1301 1302 errno = 0; 1303 1304 /* Turn on privileges. */ 1305 (void) __priv_bracket(PRIV_ON); 1306 1307 ret = write_extvtoc(fd, &v_toc); 1308 1309 /* Turn off privileges. */ 1310 (void) __priv_bracket(PRIV_OFF); 1311 1312 if (ret < 0) { 1313 PERROR("write VTOC failed"); 1314 DPRINTF1("Errno = %d\n", errno); 1315 } 1316 } 1317 1318 #else /* !sparc */ 1319 #ifdef i386 1320 1321 void 1322 write_default_label(smedia_handle_t handle, int32_t fd) 1323 { 1324 1325 int32_t i, ret; 1326 struct dk_geom dkg; 1327 struct extvtoc v_toc; 1328 int tmp_fd; 1329 char *fdisk_buf; 1330 struct mboot boot_code; /* Buffer for master boot record */ 1331 struct ipart parts[FD_NUMPART]; 1332 uint32_t numcyl, nhead, nsect; 1333 uint32_t unixend; 1334 uint32_t blocksize; 1335 diskaddr_t capacity; 1336 int save_errno; 1337 size_t bytes_written; 1338 char asciilabel[LEN_DKL_ASCII]; 1339 char asciilabel2[LEN_DKL_ASCII] = "DEFAULT\0"; 1340 uint32_t acyl = 2; 1341 1342 DPRINTF("Writing default fdisk table and vtoc\n"); 1343 (void) memset(&v_toc, 0, sizeof (v_toc)); 1344 /* 1345 * Try getting disk geometry. 1346 */ 1347 if (ioctl(fd, DKIOCGGEOM, &dkg) < 0) 1348 if (ioctl(fd, DKIOCG_PHYGEOM, &dkg) < 0) { 1349 1350 DPRINTF("DKIOCG_PHYGEOM ioctl failed"); 1351 return; 1352 } 1353 1354 tmp_fd = open("/boot/pmbr", O_RDONLY); 1355 if (tmp_fd <= 0) { 1356 return; 1357 } 1358 1359 if (read(tmp_fd, &boot_code, sizeof (struct mboot)) 1360 != sizeof (struct mboot)) { 1361 (void) close(tmp_fd); 1362 return; 1363 } 1364 1365 blocksize = med_info.sm_blocksize; 1366 fdisk_buf = (char *)malloc(blocksize); 1367 if (fdisk_buf == NULL) { 1368 DPRINTF("malloc for fdisk_buf failed\n"); 1369 return; 1370 } 1371 1372 (void) memset(&parts, 0, sizeof (parts)); 1373 1374 for (i = 0; i < FD_NUMPART; i++) { 1375 parts[i].systid = UNUSED; 1376 parts[i].numsect = lel(UNUSED); 1377 parts[i].relsect = lel(UNUSED); 1378 parts[i].bootid = 0; 1379 } 1380 1381 numcyl = dkg.dkg_ncyl; 1382 nhead = dkg.dkg_nhead; 1383 nsect = dkg.dkg_nsect; 1384 1385 parts[0].bootid = ACTIVE; 1386 parts[0].begsect = 1; 1387 1388 unixend = numcyl; 1389 1390 parts[0].relsect = lel(nhead * nsect); 1391 parts[0].numsect = lel(((diskaddr_t)numcyl * nhead * nsect)); 1392 parts[0].systid = SUNIXOS2; /* Solaris */ 1393 parts[0].beghead = 0; 1394 parts[0].begcyl = 1; 1395 parts[0].endhead = nhead - 1; 1396 parts[0].endsect = (nsect & 0x3f) | 1397 (char)((unixend >> 2) & 0x00c0); 1398 parts[0].endcyl = (char)(unixend & 0x00ff); 1399 1400 (void) memcpy(&(boot_code.parts), parts, sizeof (parts)); 1401 (void) memcpy(fdisk_buf, &boot_code, sizeof (boot_code)); 1402 1403 /* Turn on privileges. */ 1404 (void) __priv_bracket(PRIV_ON); 1405 1406 ret = ioctl(fd, DKIOCSMBOOT, fdisk_buf); 1407 1408 /* Turn off privileges. */ 1409 (void) __priv_bracket(PRIV_OFF); 1410 1411 if (ret == -1) { 1412 if (errno != ENOTTY) { 1413 PERROR("DKIOCSMBOOT ioctl Failed"); 1414 return; 1415 } 1416 1417 /* Turn on privileges. */ 1418 (void) __priv_bracket(PRIV_ON); 1419 1420 bytes_written = smedia_raw_write(handle, (diskaddr_t)0, 1421 fdisk_buf, blocksize); 1422 1423 /* Turn off privileges. */ 1424 (void) __priv_bracket(PRIV_OFF); 1425 1426 save_errno = errno; 1427 errno = save_errno; 1428 if (bytes_written != blocksize) { 1429 if (errno == ENOTSUP) { 1430 1431 /* Turn on privileges. */ 1432 (void) __priv_bracket(PRIV_ON); 1433 1434 ret = write(fd, fdisk_buf, blocksize); 1435 1436 /* Turn off privileges. */ 1437 (void) __priv_bracket(PRIV_OFF); 1438 1439 if (ret != blocksize) { 1440 return; 1441 } 1442 } else { 1443 return; 1444 } 1445 } 1446 } 1447 capacity = (diskaddr_t)(numcyl - 1) * nhead * nsect; 1448 1449 v_toc.v_nparts = V_NUMPAR; 1450 v_toc.v_sanity = VTOC_SANE; 1451 v_toc.v_version = V_VERSION; 1452 v_toc.v_sectorsz = DEV_BSIZE; 1453 1454 v_toc.v_part[0].p_start = 0; 1455 v_toc.v_part[0].p_size = capacity; 1456 v_toc.v_part[0].p_tag = V_ROOT; 1457 v_toc.v_part[0].p_flag = 0; /* Mountable */ 1458 1459 v_toc.v_part[2].p_start = 0; 1460 v_toc.v_part[2].p_size = capacity; 1461 v_toc.v_part[2].p_tag = V_BACKUP; 1462 v_toc.v_part[2].p_flag = V_UNMNT; 1463 1464 /* Create asciilabel for compatibility with format utility */ 1465 (void) snprintf(asciilabel, sizeof (asciilabel), 1466 "%s cyl %d alt %d hd %d sec %d", 1467 asciilabel2, numcyl, acyl, nhead, nsect); 1468 (void) memcpy(v_toc.v_asciilabel, asciilabel, 1469 LEN_DKL_ASCII); 1470 1471 errno = 0; 1472 1473 1474 /* Turn on privileges. */ 1475 (void) __priv_bracket(PRIV_ON); 1476 1477 ret = write_extvtoc(fd, &v_toc); 1478 1479 /* Turn off privileges. */ 1480 (void) __priv_bracket(PRIV_OFF); 1481 1482 if (ret < 0) { 1483 PERROR("write VTOC failed"); 1484 DPRINTF1("Errno = %d\n", errno); 1485 } 1486 } 1487 1488 #else /* !i386 */ 1489 1490 #error One of sparc or i386 must be defined! 1491 1492 #endif /* i386 */ 1493 #endif /* sparc */ 1494 1495 /* 1496 * void overwrite_metadata(int32_t fd, smedia_handle_t handle) 1497 * 1498 * purpose : quick format does not erase the data on Iomega 1499 * zip/jaz media. So, the meta data on the disk should be erased. 1500 * 1501 * If there is a valid fdisk table, 1502 * erase first 64K of each partition. 1503 * If there is a valid vtoc, 1504 * erase first 64k of each slice. 1505 * Then erase the 0th sector (the home for vtoc and fdisk) of the disk. 1506 * Note that teh vtoc on x86 resides in one of the fdisk partition. 1507 * So delay the erasing of the solaris partition until the vtoc is read. 1508 */ 1509 1510 void 1511 overwrite_metadata(int32_t fd, smedia_handle_t handle) 1512 { 1513 1514 struct fdisk_info fdisk; 1515 diskaddr_t sol_offset = 0; 1516 int i, ret; 1517 struct extvtoc t_vtoc; 1518 #ifdef i386 1519 diskaddr_t sol_size = 0; 1520 int32_t active = 0; 1521 #endif /* i386 */ 1522 1523 /* Get fdisk info. */ 1524 if (get_fdisk(handle, fd, 0, &fdisk) >= 0) { 1525 /* Got a valid fdisk */ 1526 for (i = 0; i < FD_NUMPART; i++) { 1527 1528 if (fdisk.part[i].numsect == 0) 1529 continue; 1530 if ((fdisk.part[i].systid == UNUSED) || 1531 (fdisk.part[i].systid == 0)) 1532 continue; 1533 #ifdef i386 1534 if (fdisk.part[i].systid == SUNIXOS || 1535 fdisk.part[i].systid == SUNIXOS2) { 1536 if (!sol_offset) { 1537 sol_offset = fdisk.part[i].relsect; 1538 sol_size = fdisk.part[i].numsect; 1539 if (fdisk.part[i].bootid == ACTIVE) 1540 active = 1; 1541 continue; 1542 } else if ((fdisk.part[i].bootid == ACTIVE) && 1543 (!active)) { 1544 erase(handle, sol_offset, sol_size); 1545 sol_offset = fdisk.part[i].relsect; 1546 sol_size = fdisk.part[i].numsect; 1547 active = 1; 1548 continue; 1549 } 1550 } 1551 #endif /* i386 */ 1552 erase(handle, (diskaddr_t)fdisk.part[i].relsect, 1553 (diskaddr_t)fdisk.part[i].numsect); 1554 } 1555 } 1556 1557 (void) memset(&t_vtoc, 0, sizeof (t_vtoc)); 1558 1559 if (sol_offset) { 1560 /* fdisk x86 Solaris partition */ 1561 /* VTOC location in solaris partition is DK_LABEL_LOC */ 1562 1563 /* Turn on privileges. */ 1564 (void) __priv_bracket(PRIV_ON); 1565 1566 ret = read_extvtoc(fd, &t_vtoc); 1567 1568 /* Turn off privileges. */ 1569 (void) __priv_bracket(PRIV_OFF); 1570 1571 if (ret < 0) { 1572 /* No valid vtoc, erase fdisk table. */ 1573 erase(handle, (diskaddr_t)0, (diskaddr_t)1); 1574 return; 1575 } 1576 } else { 1577 /* Sparc Solaris or x86 solaris with faked fdisk */ 1578 1579 /* Turn on privileges */ 1580 (void) __priv_bracket(PRIV_ON); 1581 1582 ret = read_extvtoc(fd, &t_vtoc); 1583 1584 /* Turn off privileges. */ 1585 (void) __priv_bracket(PRIV_OFF); 1586 1587 if (ret < 0) { 1588 /* No valid vtoc, erase from 0th sector */ 1589 erase(handle, (diskaddr_t)0, 1590 (uint32_t)med_info.sm_capacity); 1591 return; 1592 } 1593 } 1594 1595 for (i = 0; i < V_NUMPAR; i++) { 1596 if (t_vtoc.v_part[i].p_size != 0) { 1597 erase(handle, sol_offset + t_vtoc.v_part[i].p_start, 1598 t_vtoc.v_part[i].p_size); 1599 /* 1600 * To make the udfs not recognise the partition we will 1601 * erase sectors 256, (p_size-256) and psize. 1602 */ 1603 erase(handle, 1604 sol_offset + t_vtoc.v_part[i].p_start + 256, 1605 (diskaddr_t)1); 1606 erase(handle, 1607 (sol_offset + t_vtoc.v_part[i].p_start + 1608 t_vtoc.v_part[i].p_size - 256), 1609 (diskaddr_t)1); 1610 erase(handle, 1611 (sol_offset + t_vtoc.v_part[i].p_start + 1612 t_vtoc.v_part[i].p_size - 1), 1613 (diskaddr_t)1); 1614 } 1615 } 1616 1617 /* 1618 * If x86 fdisk solaris partition, erase the vtoc also. 1619 * for sparc, the erasing 0the sector erases vtoc. 1620 */ 1621 if (sol_offset) { 1622 erase(handle, sol_offset, (diskaddr_t)DK_LABEL_LOC + 2); 1623 } 1624 1625 /* 1626 * erase the 0th sector, it is not guaranteed to be 1627 * erased in the above sequence. 1628 */ 1629 1630 erase(handle, (diskaddr_t)0, (diskaddr_t)1); 1631 } 1632 1633 /* 1634 * void erase(smedia_handle_t handle, uint32_t offset, uint32_t size) 1635 * 1636 * Initialize the media with '0' from offset 'offset' upto 'size' 1637 * or 128 blocks(64k), whichever is smaller. 1638 */ 1639 1640 static void 1641 erase(smedia_handle_t handle, diskaddr_t offset, diskaddr_t size) 1642 { 1643 char *buf; 1644 diskaddr_t nblocks = size; 1645 int32_t ret; 1646 1647 1648 nblocks = (nblocks < 128) ? nblocks : 128; 1649 buf = (char *)malloc(nblocks * med_info.sm_blocksize); 1650 if (buf == NULL) { 1651 PERROR("malloc failed"); 1652 return; 1653 } 1654 (void) memset(buf, 0, (size_t)nblocks * med_info.sm_blocksize); 1655 1656 /* Turn on privileges. */ 1657 (void) __priv_bracket(PRIV_ON); 1658 1659 ret = smedia_raw_write(handle, offset, buf, 1660 (size_t)nblocks * med_info.sm_blocksize); 1661 1662 /* Turn off privileges. */ 1663 (void) __priv_bracket(PRIV_OFF); 1664 1665 if (ret != (nblocks * med_info.sm_blocksize)) 1666 PERROR("error in writing\n"); 1667 1668 free(buf); 1669 1670 } 1671