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 }