|
|
1.1 root 1: /*
2: * Copyright (c) 1996 The University of Utah and
3: * the Computer Systems Laboratory at the University of Utah (CSL).
4: * All rights reserved.
5: *
6: * Permission to use, copy, modify and distribute this software is hereby
7: * granted provided that (1) source code retains these copyright, permission,
8: * and disclaimer notices, and (2) redistributions including binaries
9: * reproduce the notices in supporting documentation, and (3) all advertising
10: * materials mentioning features or use of this software display the following
11: * acknowledgement: ``This product includes software developed by the
12: * Computer Systems Laboratory at the University of Utah.''
13: *
14: * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
15: * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
16: * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
17: *
18: * CSL requests users of this software to return to [email protected] any
19: * improvements that they make and grant CSL redistribution rights.
20: *
21: * Author: Kevin T. Van Maren, University of Utah CSL
22: */
23:
24: /*
25: * Mach Operating System
26: * Copyright (c) 1991,1990 Carnegie Mellon University
27: * All Rights Reserved.
28: *
29: * Permission to use, copy, modify and distribute this software and its
30: * documentation is hereby granted, provided that both the copyright
31: * notice and this permission notice appear in all copies of the
32: * software, derivative works or modified versions, and any portions
33: * thereof, and that both notices appear in supporting documentation.
34: *
35: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
36: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
37: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
38: *
39: * Carnegie Mellon requests users of this software to return to
40: *
41: * Software Distribution Coordinator or [email protected]
42: * School of Computer Science
43: * Carnegie Mellon University
44: * Pittsburgh PA 15213-3890
45: *
46: * any improvements or extensions that they make and grant Carnegie Mellon
47: * the rights to redistribute these changes.
48: */
49:
50: /*
51: * Copyright (c) 1994 Shantanu Goel
52: * All Rights Reserved.
53: *
54: * Permission to use, copy, modify and distribute this software and its
55: * documentation is hereby granted, provided that both the copyright
56: * notice and this permission notice appear in all copies of the
57: * software, derivative works or modified versions, and any portions
58: * thereof, and that both notices appear in supporting documentation.
59: *
60: * THE AUTHOR ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
61: * CONDITION. THE AUTHOR DISCLAIMS ANY LIABILITY OF ANY KIND FOR
62: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
63: *
64: */
65:
66: /* This file contains the partition code that is used by the Mach
67: * device drivers (ide & scsi). */
68:
69: #include <scsi/compat_30.h>
70: #include <sys/types.h>
71:
72: #include <scsi/rz_labels.h>
73: #include <i386at/disk.h> /* combine & rename these... */
74:
75: #define SECTOR_SIZE 512 /* BAD!!! */
76:
77: #define DSLICE(dev) ((dev >> 4) & 0x3f)
78: #define DPART(dev) (dev & 0xf)
79:
80: /* note: 0 will supress ALL output;
81: 1 is 'normal' output; 2 is verbose; 3 is Very verbose */
82: #define PARTITION_DEBUG 1
83:
84: #define min(x,y) (x<y?x:y)
85:
86: /*
87: * Label that is filled in with extra info
88: */
89: struct disklabel default_label =
90: {
91: DISKMAGIC, DTYPE_SCSI, 0,
92: "SCSI", "",
93: DEV_BSIZE, 1, 1, 1, 1, 1, 0, 0, 0,
94: 3600, 1, 1, 1, 0, 0, 0,
95: {0,}, {0,},
96: DISKMAGIC, 0,
97: 8, 8192, 8192,
98: {{ -1, 0, 1024, FS_BSDFFS, 8, 3 },
99: { -1, 0, 1024, FS_BSDFFS, 8, 3 },
100: { -1, 0, 1024, FS_BSDFFS, 8, 3 },
101: { -1, 0, 1024, FS_BSDFFS, 8, 3 },
102: { -1, 0, 1024, FS_BSDFFS, 8, 3 },
103: { -1, 0, 1024, FS_BSDFFS, 8, 3 },
104: { -1, 0, 1024, FS_BSDFFS, 8, 3 },
105: { -1, 0, 1024, FS_BSDFFS, 8, 3 }}
106: };
107:
108:
109:
110: /* the device driver calls this just to save some info it got from the HW */
111: /* This is a bad holdover from the disklabel days, and needs to go */
112: fudge_bsd_label(struct disklabel *label, int type, int total_secs, int heads, int sectors, int sectorsize, int n)
113: {
114: *label=default_label;
115:
116: label->d_ncylinders = total_secs/(heads*sectors);
117: label->d_ntracks = heads;
118: label->d_nsectors = sectors;
119:
120: label->d_secpercyl = heads*sectors;
121: label->d_secperunit = total_secs;
122:
123: /* this is never used, but ... */
124: label->d_partitions[MAXPARTITIONS].p_offset = 0;
125: label->d_partitions[MAXPARTITIONS].p_size = total_secs;
126:
127: /* ??
128: */
129: label->d_secsize = sectorsize;
130: label->d_type = type;
131: label->d_subtype = 0xa; /* ??? */
132:
133: label->d_npartitions = n; /* up to 'c' */
134: label->d_checksum = 0;
135:
136: /* should do a checksum on it now */
137: }
138:
139:
140:
141: /* This is placed here to
142: a. provide comparability with existing servers
143: b. allow the use of FreeBSD-style slices to access ANY disk partition
144: c. provide an easy migration path to lites-based partition code
145: by only passing the drive name to get the entire disk (sd0).
146:
147: This will be called by every routine that needs to access partition info
148: based on a device number. It is slower than the old method of indexing
149: into a disklabel, but is more flexible, and reasonably fast in the (future)
150: case where Lites will access the whole disk. An array of disklabels
151: could have been used, but this is more compact and general. The underlying
152: structure does not limit it to 2-levels, but keeping the kernel interface
153: simple does. */
154:
155:
156: /* this code and data structure based on conversation with Bryan Ford */
157: /* Note: this is called ON EVERY read or write. It makes sense to
158: optimize this for the common case. Hopefully the common case
159: will become the '0,0' case, as partitioning is moved out of the
160: kernel. (Downside is kernel can't protect filesystems from each other).
161: It is slower than indexing into a 1-D array, but not much. */
162:
163: struct diskpart *lookup_part(struct diskpart *array, int dev_number)
164: {
165: /* Note: 10 bit encoding to get partitions 0-15 (0,a-h typically), and slices
166: * 0-63
167: */
168:
169: int slice = DSLICE(dev_number);
170: int part = DPART(dev_number);
171: struct diskpart *s;
172:
173: if (slice == 0) /* compatability slice */
174: {
175: if (part == 0) /* whole disk */
176: return &array[0];
177:
178: if (array[0].type == DISKPART_DOS)
179: {
180: int i;
181: for (i = 0; i < array[0].nsubs; i++)
182: {
183: s = &array[0].subs[i];
184: if ( s->type == DISKPART_BSD
185: || s->type == DISKPART_VTOC)
186: {
187: if (part > s->nsubs)
188: return 0;
189: return (&s->subs[part-1]);
190: }
191: }
192: }
193:
194: if (part > array[0].nsubs)
195: return 0;
196: return(&array[0].subs[part-1]);
197: }
198: else
199: {
200: if ( array[0].type != DISKPART_DOS
201: || slice > array[0].nsubs)
202: return 0;
203:
204: s = &array[0].subs[slice-1];
205:
206: if (part == 0) /* whole slice */
207: return (s);
208: if (part > s->nsubs)
209: return 0;
210:
211: return (&s->subs[part-1]);
212: }
213: }
214:
215:
216:
217:
218: static inline void fill_array(struct diskpart *array, int start, int size,
219: struct diskpart *subs, int nsubs, short type, short fsys)
220: {
221: array->start=start;
222: array->size=size;
223: array->subs=subs;
224: array->nsubs=nsubs;
225: array->type=type;
226: array->fsys=fsys;
227: #if (PARTITION_DEBUG > 2)
228: printf("fill: type %d:%d, start %d, size %d, %d parts\n",type,fsys,
229: start,size,nsubs);
230: #endif
231: }
232:
233:
234:
235:
236: void print_array(struct diskpart *array, int level)
237: {
238: int i,j;
239: struct diskpart *subs;
240:
241: #if (PARTITION_DEBUG)
242: subs=array[0].subs;
243:
244: for (i=0;i<array[0].nsubs;i++) {
245: for (j=0;j<level;j++)
246: printf(" ");
247: printf("%c: %d, %d, %d, %d (%d subparts)\n",'a'+i,
248: subs[i].start, subs[i].size, subs[i].fsys,
249: subs[i].type, subs[i].nsubs);
250: if (subs[i].nsubs>0)
251: print_array(&subs[i], level+1);
252: }
253: #endif
254: }
255:
256:
257:
258: /* individual routines to find the drive labels.
259: There needs to be a function for every different method for partitioning
260: much of the following code is derived from the SCSI/IDE drivers */
261:
262: int get_dos(struct diskpart *array, char *buff, int start,
263: void *driver_info, int (*bottom_read_fun)(),
264: char *name, int max_part)
265: {
266:
267: bios_label_t *mp;
268: struct bios_partition_info *pp;
269:
270: int count, i, j;
271: int pstart, psize;
272: int ext=-1, mystart=start, mybase;
273: int first=1;
274:
275: /* note: start is added, although a start != 0 is meaningless
276: to DOS and anything else... */
277:
278: /* check the boot sector for a partition table. */
279: (*bottom_read_fun)(driver_info, start, buff); /* always in sector 0 */
280:
281: /*
282: * Check for valid partition table.
283: */
284: mp = (bios_label_t *)&buff[BIOS_LABEL_BYTE_OFFSET];
285: if (mp->magic != BIOS_LABEL_MAGIC) {
286: #if (PARTITION_DEBUG>1)
287: printf("%s invalid partition table\n", name);
288: #endif
289: return(0); /* didn't add any partitions */
290: }
291: #if (PARTITION_DEBUG>1)
292: printf("DOS partition table found\n");
293: #endif
294:
295: count=min(4,max_part); /* always 4 (primary) partitions */
296: #if (PARTITION_DEBUG)
297: if (count<4) printf("More partitions than space!\n");
298: #endif
299:
300:
301: /* fill the next 4 entries in the array */
302: for (i=0, pp=(struct bios_partition_info *)mp->partitions;
303: i<count; i++,pp++) {
304:
305: fill_array(&array[i], pp->offset, pp->n_sectors, NULL, 0,
306: DISKPART_NONE, pp->systid);
307: if ((pp->systid == DOS_EXTENDED) &&(ext<0)) {
308: mystart+=pp->offset;
309: ext=i;
310: }
311: }
312:
313: /* if there is an extended partition, find all the logical partitions */
314: /* note: logical start at '5' (extended is one of the numbered 1-4) */
315:
316: /* logical partitions 'should' be nested inside the primary, but
317: then it would be impossible to NAME a disklabel inside a logical
318: partition, which would be nice to do */
319: #if (PARTITION_DEBUG>1)
320: if (ext>=0)
321: printf("extended partition found: %d\n",ext);
322: #endif 0
323:
324: while (ext>=0) {
325: pp = &(((struct bios_partition_info *)mp->partitions)[ext]);
326:
327: /* read the EXTENDED partition table */
328: if (first) {
329: mybase=mystart;
330: first=0;
331: } else {
332: mybase=mystart+pp->offset;
333: }
334:
335: (*bottom_read_fun)(driver_info, mybase, buff);
336:
337: if (mp->magic != BIOS_LABEL_MAGIC) {
338: #if (PARTITION_DEBUG>1)
339: printf("%s invalid expanded magic\n", name);
340: #endif
341: return(count);/*don't add any more partitions*/
342: }
343:
344: /* just in case more than one partition is there...*/
345: /* search the EXTENDED partition table */
346: ext=-1;
347: for (j=0,pp=(struct bios_partition_info *)mp->partitions;
348: j<4; j++,pp++) {
349:
350: if (pp->systid && (pp->systid!=DOS_EXTENDED)) {
351: if (count<max_part) {
352: fill_array(&array[count],
353: mybase +pp->offset,
354: pp->n_sectors, NULL, 0, DISKPART_NONE,
355: pp->systid);
356: count++; }
357: else {
358: #if (PARTITION_DEBUG)
359: printf("More partitions than space!\n");
360: #endif
361: return(count);
362: }
363: } else if ((ext<0) &&(pp->systid==DOS_EXTENDED)) {
364: ext=j;
365: /* recursivly search the chain here */
366: }
367: }
368: }
369: #if (PARTITION_DEBUG>1)
370: printf("%d dos partitions\n",count);
371: #endif 0
372: return(count); /* number dos partitions found */
373:
374: }
375:
376:
377:
378: /* this should work on the bare drive, or in a dos partition */
379: int get_disklabel(struct diskpart *array, char *buff, int start,
380: void *driver_info, int (*bottom_read_fun)(),
381: char *name, int max_part)
382: {
383: struct disklabel *dlp;
384: int mybase = start + (512 * LBLLOC)/SECTOR_SIZE, i;
385: int count;
386:
387: (*bottom_read_fun)(driver_info, mybase, buff);
388:
389: dlp = (struct disklabel *)buff;
390: if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) {
391: #if (PARTITION_DEBUG>1)
392: printf("%s no BSD label found\n",name);
393: #endif
394: return(0); /* no partitions added */
395: }
396: #if (PARTITION_DEBUG>1)
397: printf(" BSD LABEL\n");
398: #endif 0
399: /* note: BSD disklabel offsets are from start of DRIVE -- uuggh */
400:
401: count=min(8,max_part); /* always 8 in a disklabel */
402: #if (PARTITION_DEBUG)
403: if (count<8) printf("More partitions than space!\n");
404: #endif
405: /* COPY into the array */
406: for (i=0;i<count;i++)
407: fill_array(&array[i], /* mybase + */
408: dlp->d_partitions[i].p_offset,
409: dlp->d_partitions[i].p_size,
410: NULL, 0, DISKPART_NONE, dlp->d_partitions[i].p_fstype);
411:
412: /* note: p_fstype is not the same set as the DOS types */
413:
414: return(count); /* 'always' 8 partitions in disklabel -- if space */
415:
416: /* UNREACHED CODE FOLLOWS: (alternative method in scsi) */
417: #if 0
418: (*bottom_read_fun)(driver_info, (start)+LABELSECTOR, buff);
419:
420: register int j;
421: boolean_t found;
422:
423: for (j = LABELOFFSET, found = FALSE;
424: j < (SECTOR_SIZE-sizeof(struct disklabel));
425: j += sizeof(int)) {
426: search = (struct disklabel *)&buff[j];
427: if (search->d_magic == DISKMAGIC &&
428: search->d_magic2 == DISKMAGIC) {
429: found = TRUE;
430: break;
431: }
432: }
433: if (found) {
434: #if (PARTITION_DEBUG>1)
435: printf("Label found in LABELSECTOR\n");
436: #endif
437: } else {
438: search = 0;
439: }
440:
441:
442: #endif 0
443:
444: }
445:
446:
447: /* NOT TESTED! */
448: /* VTOC in sector 29 */
449: int get_vtoc(struct diskpart *array, char *buff, int start,
450: void *driver_info, int (*bottom_read_fun)(),
451: char *name, int max_part)
452: {
453: struct evtoc *evp;
454: int n,i;
455: struct disklabel lpl;
456: struct disklabel *lp = &lpl;
457:
458: #if (PARTITION_DEBUG)
459: printf("Read VTOC.\n");
460: #endif
461: (*bottom_read_fun)(driver_info, start +PDLOCATION, buff);
462: evp = (struct evtoc *)buff;
463: if (evp->sanity != VTOC_SANE) {
464: #if (PARTITION_DEBUG)
465: printf("%s evtoc corrupt or not found\n", name);
466: #endif
467: return(0);
468: }
469: n = min(evp->nparts,max_part); /* no longer DISKLABEL limitations... */
470: #if 0
471: n = (evp->nparts > MAXPARTITIONS) ? MAXPARTITIONS : evp->nparts;
472: #endif 0
473:
474: for (i = 0; i < n; i++)
475: fill_array(&array[i], /* mybase + */
476: evp->part[i].p_start,
477: evp->part[i].p_size,
478: NULL, 0, DISKPART_NONE, FS_BSDFFS);
479:
480: return(n); /* (evp->nparts) */
481: }
482:
483:
484: /* NOT TESTED! */
485: int get_omron(struct diskpart *array, char *buff, int start,
486: void *driver_info, int (*bottom_read_fun)(),
487: char *name, int max_part)
488: {
489:
490: struct disklabel *label;
491:
492: /* here look for an Omron label */
493: register omron_label_t *part;
494: int i;
495:
496: #if (PARTITION_DEBUG)
497: printf("Looking for Omron label...\n");
498: #endif
499:
500: (*bottom_read_fun)(driver_info, start+
501: OMRON_LABEL_BYTE_OFFSET/SECTOR_SIZE, buff);
502:
503: part = (omron_label_t*)&buff[OMRON_LABEL_BYTE_OFFSET%SECTOR_SIZE];
504: if (part->magic == OMRON_LABEL_MAGIC) {
505: #if (PARTITION_DEBUG)
506: printf("{Using OMRON label}");
507: #endif
508: for (i = 0; i < 8; i++) {
509: label->d_partitions[i].p_size = part->partitions[i].n_sectors;
510: label->d_partitions[i].p_offset = part->partitions[i].offset;
511: }
512: bcopy(part->packname, label->d_packname, 16);
513: label->d_ncylinders = part->ncyl;
514: label->d_acylinders = part->acyl;
515: label->d_ntracks = part->nhead;
516: label->d_nsectors = part->nsect;
517: /* Many disks have this wrong, therefore.. */
518: #if 0
519: label->d_secperunit = part->maxblk;
520: #else
521: label->d_secperunit = label->d_ncylinders * label->d_ntracks *
522: label->d_nsectors;
523: #endif 0
524:
525: return(8);
526: }
527: #if (PARTITION_DEBUG)
528: printf("No Omron label found.\n");
529: #endif
530: return(0);
531: }
532:
533:
534: /* NOT TESTED! */
535: int get_dec(struct diskpart *array, char *buff, int start,
536: void *driver_info, int (*bottom_read_fun)(),
537: char *name, int max_part)
538: {
539: struct disklabel *label;
540:
541: /* here look for a DEC label */
542: register dec_label_t *part;
543: int i;
544:
545: #if (PARTITION_DEBUG)
546: printf("Checking for dec_label...\n");
547: #endif
548:
549: (*bottom_read_fun)(driver_info, start +
550: DEC_LABEL_BYTE_OFFSET/SECTOR_SIZE, buff);
551:
552: if (part->magic == DEC_LABEL_MAGIC) {
553: #if (PARTITION_DEBUG)
554: printf("{Using DEC label}");
555: #endif
556: for (i = 0; i < 8; i++) {
557: label->d_partitions[i].p_size = part->partitions[i].n_sectors;
558: label->d_partitions[i].p_offset = part->partitions[i].offset;
559: }
560: return(8);
561: }
562: #if (PARTITION_DEBUG)
563: printf("No dec label found.\n");
564: #endif
565:
566: return(0);
567: }
568:
569:
570:
571:
572: /* array is a pointer to an array of partition_info structures */
573: /* array_size is the number of pre-allocated entries there are */
574: int get_only_partition(void *driver_info, int (*bottom_read_fun)(),
575: struct diskpart *array, int array_size,
576: int disk_size, char *drive_name)
577: {
578: char buff[SECTOR_SIZE];
579: int i,n,cnt;
580: int arrsize;
581: struct diskpart *res;
582:
583: /* first fill in the entire disk stuff */
584: /* or should the calling routine do that already? */
585:
586: fill_array(array, 0, disk_size, NULL, 0, -1, -1);
587:
588: /* while the structure does not preclude additional nestings,
589: additional ones make no sense currently, so they are not
590: checked (Mach can't handle them anyway). It might be nice
591: if for all partitions found, all types of sub-partitions
592: were looked for (unnecessary). This will be done when this
593: is moved out of ther kernel, and there is some way to name them */
594:
595: arrsize = array_size -1; /* 1 for whole disk */
596:
597: /* search for dos partition table */
598: /* find all the partitions (including logical) */
599: n=get_dos(&array[1], buff, 0,
600: driver_info, (bottom_read_fun), drive_name,
601: arrsize);
602:
603: if (n>0) {
604: fill_array(array, 0, disk_size, &array[1], n,
605: DISKPART_DOS, 256+DISKPART_DOS);
606: arrsize-=n;
607:
608:
609: /* search each one for a BSD disklabel (iff BSDOS) */
610: /* note: searchine extended and logical partitions */
611: for (i=0;i<n;i++)
612: if (array[i+1].fsys==BSDOS) {
613: #if (PARTITION_DEBUG)
614: printf("BSD OS slice: %d\n",i+1);
615: #endif
616: cnt=get_disklabel(&array[n+1], buff,
617: array[i+1].start,
618: driver_info, (bottom_read_fun),
619: drive_name,arrsize);
620:
621: if (cnt>0) {
622: arrsize-=cnt;
623: fill_array(&array[i+1],array[i+1].start,
624: array[i+1].size, &array[n+1],
625: cnt, DISKPART_BSD,
626: array[i+1].fsys);
627: }
628: n+=cnt;
629: }
630:
631: /* search for VTOC -- in a DOS partition as well */
632: for (i=0;i<n;i++)
633: if (array[i+1].fsys==UNIXOS) {
634: #if (PARTITION_DEBUG)
635: printf("UNIXOS (vtoc) partition\n");
636: #endif
637: cnt=get_vtoc(&array[n+1], buff,
638: array[i+1].start,
639: driver_info, (bottom_read_fun),
640: drive_name,arrsize);
641:
642: if (cnt>0) {
643: arrsize-=cnt;
644: fill_array(&array[i+1],array[i+1].start,
645: array[i+1].size, &array[n+1],
646: cnt, DISKPART_VTOC,
647: array[i+1].fsys);
648: }
649: n+=cnt;
650: }
651: }
652:
653: /* search for only disklabel */
654: if (n==0) {
655: fill_array(array, 0, disk_size, &array[1], n, DISKPART_BSD,
656: 256+DISKPART_BSD);
657: n=get_disklabel(&array[1], buff, 0, driver_info,
658: (bottom_read_fun), drive_name,arrsize);
659: }
660:
661: /* search for only VTOC -- NOT TESTED! */
662: if (n==0) {
663: fill_array(array, 0, disk_size, &array[1], n, DISKPART_VTOC,
664: 256+DISKPART_VTOC);
665: n=get_vtoc(&array[1], buff, 0, driver_info, (bottom_read_fun),
666: drive_name,arrsize);
667: }
668: #if 0
669: /* search for only omron -- NOT TESTED! */
670: if (n==0) {
671: fill_array(array, 0, disk_size, &array[1], n, DISKPART_OMRON,
672: 256+DISKPART_OMRON);
673: n=get_omron(&array[1], buff, 0,driver_info, (bottom_read_fun),
674: drive_name,arrsize);
675: }
676:
677: /* search for only dec -- NOT TESTED! */
678: if (n==0) {
679: fill_array(array, 0, disk_size, &array[1], n, DISKPART_DEC,
680: 256+DISKPART_DEC);
681: n=get_dec(&array[1], buff, 0, driver_info, (bottom_read_fun),
682: drive_name,arrsize);
683: }
684: #endif 0
685:
686: #if (PARTITION_DEBUG) /* print out what we found */
687: print_array(array,0);
688: #endif
689:
690: }
691:
692:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.