|
|
1.1 ! root 1: /* ! 2: * Code extracted from ! 3: * linux/kernel/hd.c ! 4: * ! 5: * Copyright (C) 1991, 1992 Linus Torvalds ! 6: * ! 7: * ! 8: * Thanks to Branko Lankester, [email protected], who found a bug ! 9: * in the early extended-partition checks and added DM partitions ! 10: * ! 11: * Support for DiskManager v6.0x added by Mark Lord ([email protected]) ! 12: * with information provided by OnTrack. This now works for linux fdisk ! 13: * and LILO, as well as loadlin and bootln. Note that disks other than ! 14: * /dev/hda *must* have a "DOS" type 0x51 partition in the first slot (hda1). ! 15: * ! 16: * More flexible handling of extended partitions - aeb, 950831 ! 17: * ! 18: * Check partition table on IDE disks for common CHS translations ! 19: */ ! 20: ! 21: #include <linux/config.h> ! 22: #include <linux/fs.h> ! 23: #include <linux/genhd.h> ! 24: #include <linux/kernel.h> ! 25: #include <linux/major.h> ! 26: #include <linux/string.h> ! 27: ! 28: #include <asm/system.h> ! 29: ! 30: #ifdef __alpha__ ! 31: /* ! 32: * On the Alpha, we get unaligned access exceptions on ! 33: * p->nr_sects and p->start_sect, when the partition table ! 34: * is not on a 4-byte boundary, which is frequently the case. ! 35: * This code uses unaligned load instructions to prevent ! 36: * such exceptions. ! 37: */ ! 38: #include <asm/unaligned.h> ! 39: #define NR_SECTS(p) ldl_u(&p->nr_sects) ! 40: #define START_SECT(p) ldl_u(&p->start_sect) ! 41: #else /* __alpha__ */ ! 42: #define NR_SECTS(p) p->nr_sects ! 43: #define START_SECT(p) p->start_sect ! 44: #endif /* __alpha__ */ ! 45: ! 46: #ifdef MACH ! 47: #include <i386/ipl.h> ! 48: #endif ! 49: ! 50: struct gendisk *gendisk_head = NULL; ! 51: ! 52: static int current_minor = 0; ! 53: extern int *blk_size[]; ! 54: extern void rd_load(void); ! 55: ! 56: extern int chr_dev_init(void); ! 57: extern int blk_dev_init(void); ! 58: extern int scsi_dev_init(void); ! 59: extern int net_dev_init(void); ! 60: ! 61: static void print_minor_name (struct gendisk *hd, int minor) ! 62: { ! 63: unsigned int unit = minor >> hd->minor_shift; ! 64: unsigned int part = minor & ((1 << hd->minor_shift) - 1); ! 65: ! 66: #ifdef CONFIG_BLK_DEV_IDE ! 67: /* ! 68: * IDE devices use multiple major numbers, but the drives ! 69: * are named as: {hda,hdb}, {hdc,hdd}, {hde,hdf}, {hdg,hdh}.. ! 70: * This requires some creative handling here to find the ! 71: * correct name to use, with some help from ide.c ! 72: */ ! 73: if (!strcmp(hd->major_name,"ide")) { ! 74: char name[16]; /* more than large enough */ ! 75: strcpy(name, hd->real_devices); /* courtesy ide.c */ ! 76: name[strlen(name)-1] += unit; ! 77: printk(" %s", name); ! 78: } else ! 79: #endif ! 80: printk(" %s%c", hd->major_name, 'a' + unit); ! 81: if (part) ! 82: printk("%d", part); ! 83: else ! 84: printk(":"); ! 85: } ! 86: ! 87: static void add_partition (struct gendisk *hd, int minor, int start, int size) ! 88: { ! 89: hd->part[minor].start_sect = start; ! 90: hd->part[minor].nr_sects = size; ! 91: /* print_minor_name(hd, minor);*/ ! 92: } ! 93: ! 94: static inline int is_extended_partition(struct partition *p) ! 95: { ! 96: return (p->sys_ind == DOS_EXTENDED_PARTITION || ! 97: p->sys_ind == LINUX_EXTENDED_PARTITION); ! 98: } ! 99: ! 100: #ifdef CONFIG_MSDOS_PARTITION ! 101: /* ! 102: * Create devices for each logical partition in an extended partition. ! 103: * The logical partitions form a linked list, with each entry being ! 104: * a partition table with two entries. The first entry ! 105: * is the real data partition (with a start relative to the partition ! 106: * table start). The second is a pointer to the next logical partition ! 107: * (with a start relative to the entire extended partition). ! 108: * We do not create a Linux partition for the partition tables, but ! 109: * only for the actual data partitions. ! 110: */ ! 111: ! 112: static void extended_partition(struct gendisk *hd, kdev_t dev) ! 113: { ! 114: struct buffer_head *bh; ! 115: struct partition *p; ! 116: unsigned long first_sector, first_size, this_sector, this_size; ! 117: int mask = (1 << hd->minor_shift) - 1; ! 118: int i; ! 119: ! 120: first_sector = hd->part[MINOR(dev)].start_sect; ! 121: first_size = hd->part[MINOR(dev)].nr_sects; ! 122: this_sector = first_sector; ! 123: ! 124: while (1) { ! 125: if ((current_minor & mask) == 0) ! 126: return; ! 127: if (!(bh = bread(dev,0,1024))) ! 128: return; ! 129: /* ! 130: * This block is from a device that we're about to stomp on. ! 131: * So make sure nobody thinks this block is usable. ! 132: */ ! 133: bh->b_state = 0; ! 134: ! 135: if (*(unsigned short *) (bh->b_data+510) != 0xAA55) ! 136: goto done; ! 137: ! 138: p = (struct partition *) (0x1BE + bh->b_data); ! 139: ! 140: this_size = hd->part[MINOR(dev)].nr_sects; ! 141: ! 142: /* ! 143: * Usually, the first entry is the real data partition, ! 144: * the 2nd entry is the next extended partition, or empty, ! 145: * and the 3rd and 4th entries are unused. ! 146: * However, DRDOS sometimes has the extended partition as ! 147: * the first entry (when the data partition is empty), ! 148: * and OS/2 seems to use all four entries. ! 149: */ ! 150: ! 151: /* ! 152: * First process the data partition(s) ! 153: */ ! 154: for (i=0; i<4; i++, p++) { ! 155: if (!NR_SECTS(p) || is_extended_partition(p)) ! 156: continue; ! 157: ! 158: /* Check the 3rd and 4th entries - ! 159: these sometimes contain random garbage */ ! 160: if (i >= 2 ! 161: && START_SECT(p) + NR_SECTS(p) > this_size ! 162: && (this_sector + START_SECT(p) < first_sector || ! 163: this_sector + START_SECT(p) + NR_SECTS(p) > ! 164: first_sector + first_size)) ! 165: continue; ! 166: ! 167: add_partition(hd, current_minor, this_sector+START_SECT(p), NR_SECTS(p)); ! 168: current_minor++; ! 169: if ((current_minor & mask) == 0) ! 170: goto done; ! 171: } ! 172: /* ! 173: * Next, process the (first) extended partition, if present. ! 174: * (So far, there seems to be no reason to make ! 175: * extended_partition() recursive and allow a tree ! 176: * of extended partitions.) ! 177: * It should be a link to the next logical partition. ! 178: * Create a minor for this just long enough to get the next ! 179: * partition table. The minor will be reused for the next ! 180: * data partition. ! 181: */ ! 182: p -= 4; ! 183: for (i=0; i<4; i++, p++) ! 184: if(NR_SECTS(p) && is_extended_partition(p)) ! 185: break; ! 186: if (i == 4) ! 187: goto done; /* nothing left to do */ ! 188: ! 189: hd->part[current_minor].nr_sects = NR_SECTS(p); ! 190: hd->part[current_minor].start_sect = first_sector + START_SECT(p); ! 191: this_sector = first_sector + START_SECT(p); ! 192: dev = MKDEV(hd->major, current_minor); ! 193: brelse(bh); ! 194: } ! 195: done: ! 196: brelse(bh); ! 197: } ! 198: ! 199: static int msdos_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector) ! 200: { ! 201: int i, minor = current_minor; ! 202: struct buffer_head *bh; ! 203: struct partition *p; ! 204: unsigned char *data; ! 205: int mask = (1 << hd->minor_shift) - 1; ! 206: #ifdef CONFIG_BLK_DEV_IDE ! 207: int tested_for_xlate = 0; ! 208: ! 209: read_mbr: ! 210: #endif ! 211: if (!(bh = bread(dev,0,1024))) { ! 212: printk(" unable to read partition table\n"); ! 213: return -1; ! 214: } ! 215: data = bh->b_data; ! 216: /* In some cases we modify the geometry */ ! 217: /* of the drive (below), so ensure that */ ! 218: /* nobody else tries to re-use this data. */ ! 219: bh->b_state = 0; ! 220: #ifdef CONFIG_BLK_DEV_IDE ! 221: check_table: ! 222: #endif ! 223: if (*(unsigned short *) (0x1fe + data) != 0xAA55) { ! 224: brelse(bh); ! 225: return 0; ! 226: } ! 227: p = (struct partition *) (0x1be + data); ! 228: ! 229: #ifdef CONFIG_BLK_DEV_IDE ! 230: if (!tested_for_xlate++) { /* Do this only once per disk */ ! 231: /* ! 232: * Look for various forms of IDE disk geometry translation ! 233: */ ! 234: extern int ide_xlate_1024(kdev_t, int, const char *); ! 235: unsigned int sig = *(unsigned short *)(data + 2); ! 236: if (p->sys_ind == EZD_PARTITION) { ! 237: /* ! 238: * The remainder of the disk must be accessed using ! 239: * a translated geometry that reduces the number of ! 240: * apparent cylinders to less than 1024 if possible. ! 241: * ! 242: * ide_xlate_1024() will take care of the necessary ! 243: * adjustments to fool fdisk/LILO and partition check. ! 244: */ ! 245: if (ide_xlate_1024(dev, -1, " [EZD]")) { ! 246: data += 512; ! 247: goto check_table; ! 248: } ! 249: } else if (p->sys_ind == DM6_PARTITION) { ! 250: ! 251: /* ! 252: * Everything on the disk is offset by 63 sectors, ! 253: * including a "new" MBR with its own partition table, ! 254: * and the remainder of the disk must be accessed using ! 255: * a translated geometry that reduces the number of ! 256: * apparent cylinders to less than 1024 if possible. ! 257: * ! 258: * ide_xlate_1024() will take care of the necessary ! 259: * adjustments to fool fdisk/LILO and partition check. ! 260: */ ! 261: if (ide_xlate_1024(dev, 1, " [DM6:DDO]")) { ! 262: brelse(bh); ! 263: goto read_mbr; /* start over with new MBR */ ! 264: } ! 265: } else if (sig <= 0x1ae && *(unsigned short *)(data + sig) == 0x55AA ! 266: && (1 & *(unsigned char *)(data + sig + 2)) ) ! 267: { ! 268: /* ! 269: * DM6 signature in MBR, courtesy of OnTrack ! 270: */ ! 271: (void) ide_xlate_1024 (dev, 0, " [DM6:MBR]"); ! 272: } else if (p->sys_ind == DM6_AUX1PARTITION || p->sys_ind == DM6_AUX3PARTITION) { ! 273: /* ! 274: * DM6 on other than the first (boot) drive ! 275: */ ! 276: (void) ide_xlate_1024(dev, 0, " [DM6:AUX]"); ! 277: } else { ! 278: /* ! 279: * Examine the partition table for common translations. ! 280: * This is necessary for drives for situations where ! 281: * the translated geometry is unavailable from the BIOS. ! 282: */ ! 283: for (i = 0; i < 4 ; i++) { ! 284: struct partition *q = &p[i]; ! 285: if (NR_SECTS(q) && q->sector == 1 && q->end_sector == 63) { ! 286: unsigned int heads = q->end_head + 1; ! 287: if (heads == 32 || heads == 64 || heads == 128) { ! 288: ! 289: (void) ide_xlate_1024(dev, heads, " [PTBL]"); ! 290: break; ! 291: } ! 292: } ! 293: } ! 294: } ! 295: } ! 296: #endif /* CONFIG_BLK_DEV_IDE */ ! 297: ! 298: current_minor += 4; /* first "extra" minor (for extended partitions) */ ! 299: for (i=1 ; i<=4 ; minor++,i++,p++) { ! 300: if (!NR_SECTS(p)) ! 301: continue; ! 302: add_partition(hd, minor, first_sector+START_SECT(p), NR_SECTS(p)); ! 303: if (is_extended_partition(p)) { ! 304: /* printk(" <");*/ ! 305: /* ! 306: * If we are rereading the partition table, we need ! 307: * to set the size of the partition so that we will ! 308: * be able to bread the block containing the extended ! 309: * partition info. ! 310: */ ! 311: hd->sizes[minor] = hd->part[minor].nr_sects ! 312: >> (BLOCK_SIZE_BITS - 9); ! 313: extended_partition(hd, MKDEV(hd->major, minor)); ! 314: /* printk(" >");*/ ! 315: /* prevent someone doing mkfs or mkswap on an ! 316: extended partition, but leave room for LILO */ ! 317: if (hd->part[minor].nr_sects > 2) ! 318: hd->part[minor].nr_sects = 2; ! 319: } ! 320: } ! 321: /* ! 322: * Check for old-style Disk Manager partition table ! 323: */ ! 324: if (*(unsigned short *) (data+0xfc) == 0x55AA) { ! 325: p = (struct partition *) (0x1be + data); ! 326: for (i = 4 ; i < 16 ; i++, current_minor++) { ! 327: p--; ! 328: if ((current_minor & mask) == 0) ! 329: break; ! 330: if (!(START_SECT(p) && NR_SECTS(p))) ! 331: continue; ! 332: add_partition(hd, current_minor, START_SECT(p), NR_SECTS(p)); ! 333: } ! 334: } ! 335: /* printk("\n");*/ ! 336: brelse(bh); ! 337: return 1; ! 338: } ! 339: ! 340: #endif /* CONFIG_MSDOS_PARTITION */ ! 341: ! 342: #ifdef CONFIG_OSF_PARTITION ! 343: ! 344: static int osf_partition(struct gendisk *hd, unsigned int dev, unsigned long first_sector) ! 345: { ! 346: int i; ! 347: int mask = (1 << hd->minor_shift) - 1; ! 348: struct buffer_head *bh; ! 349: struct disklabel { ! 350: u32 d_magic; ! 351: u16 d_type,d_subtype; ! 352: u8 d_typename[16]; ! 353: u8 d_packname[16]; ! 354: u32 d_secsize; ! 355: u32 d_nsectors; ! 356: u32 d_ntracks; ! 357: u32 d_ncylinders; ! 358: u32 d_secpercyl; ! 359: u32 d_secprtunit; ! 360: u16 d_sparespertrack; ! 361: u16 d_sparespercyl; ! 362: u32 d_acylinders; ! 363: u16 d_rpm, d_interleave, d_trackskew, d_cylskew; ! 364: u32 d_headswitch, d_trkseek, d_flags; ! 365: u32 d_drivedata[5]; ! 366: u32 d_spare[5]; ! 367: u32 d_magic2; ! 368: u16 d_checksum; ! 369: u16 d_npartitions; ! 370: u32 d_bbsize, d_sbsize; ! 371: struct d_partition { ! 372: u32 p_size; ! 373: u32 p_offset; ! 374: u32 p_fsize; ! 375: u8 p_fstype; ! 376: u8 p_frag; ! 377: u16 p_cpg; ! 378: } d_partitions[8]; ! 379: } * label; ! 380: struct d_partition * partition; ! 381: #define DISKLABELMAGIC (0x82564557UL) ! 382: ! 383: if (!(bh = bread(dev,0,1024))) { ! 384: printk("unable to read partition table\n"); ! 385: return -1; ! 386: } ! 387: label = (struct disklabel *) (bh->b_data+64); ! 388: partition = label->d_partitions; ! 389: if (label->d_magic != DISKLABELMAGIC) { ! 390: printk("magic: %08x\n", label->d_magic); ! 391: brelse(bh); ! 392: return 0; ! 393: } ! 394: if (label->d_magic2 != DISKLABELMAGIC) { ! 395: printk("magic2: %08x\n", label->d_magic2); ! 396: brelse(bh); ! 397: return 0; ! 398: } ! 399: for (i = 0 ; i < label->d_npartitions; i++, partition++) { ! 400: if ((current_minor & mask) == 0) ! 401: break; ! 402: if (partition->p_size) ! 403: add_partition(hd, current_minor, ! 404: first_sector+partition->p_offset, ! 405: partition->p_size); ! 406: current_minor++; ! 407: } ! 408: /* printk("\n");*/ ! 409: brelse(bh); ! 410: return 1; ! 411: } ! 412: ! 413: #endif /* CONFIG_OSF_PARTITION */ ! 414: ! 415: #ifdef CONFIG_SUN_PARTITION ! 416: ! 417: static int sun_partition(struct gendisk *hd, unsigned int dev, unsigned long first_sector) ! 418: { ! 419: int i, csum; ! 420: unsigned short *ush; ! 421: struct buffer_head *bh; ! 422: struct sun_disklabel { ! 423: unsigned char info[128]; /* Informative text string */ ! 424: unsigned char spare[292]; /* Boot information etc. */ ! 425: unsigned short rspeed; /* Disk rotational speed */ ! 426: unsigned short pcylcount; /* Physical cylinder count */ ! 427: unsigned short sparecyl; /* extra sects per cylinder */ ! 428: unsigned char spare2[4]; /* More magic... */ ! 429: unsigned short ilfact; /* Interleave factor */ ! 430: unsigned short ncyl; /* Data cylinder count */ ! 431: unsigned short nacyl; /* Alt. cylinder count */ ! 432: unsigned short ntrks; /* Tracks per cylinder */ ! 433: unsigned short nsect; /* Sectors per track */ ! 434: unsigned char spare3[4]; /* Even more magic... */ ! 435: struct sun_partition { ! 436: unsigned long start_cylinder; ! 437: unsigned long num_sectors; ! 438: } partitions[8]; ! 439: unsigned short magic; /* Magic number */ ! 440: unsigned short csum; /* Label xor'd checksum */ ! 441: } * label; ! 442: struct sun_partition *p; ! 443: unsigned long spc; ! 444: #define SUN_LABEL_MAGIC 0xDABE ! 445: ! 446: if(!(bh = bread(dev, 0, 1024))) { ! 447: printk("Dev %d: unable to read partition table\n", dev); ! 448: return -1; ! 449: } ! 450: label = (struct sun_disklabel *) bh->b_data; ! 451: p = label->partitions; ! 452: if(label->magic != SUN_LABEL_MAGIC) { ! 453: printk("Dev %d Sun disklabel: bad magic %08x\n", dev, label->magic); ! 454: brelse(bh); ! 455: return 0; ! 456: } ! 457: /* Look at the checksum */ ! 458: ush = ((unsigned short *) (label+1)) - 1; ! 459: for(csum = 0; ush >= ((unsigned short *) label);) ! 460: csum ^= *ush--; ! 461: if(csum) { ! 462: printk("Dev %d Sun disklabel: Csum bad, label corrupted\n", dev); ! 463: brelse(bh); ! 464: return 0; ! 465: } ! 466: /* All Sun disks have 8 partition entries */ ! 467: spc = (label->ntrks * label->nsect); ! 468: for(i=0; i < 8; i++, p++) { ! 469: unsigned long st_sector; ! 470: ! 471: /* We register all partitions, even if zero size, so that ! 472: * the minor numbers end up ok as per SunOS interpretation. ! 473: */ ! 474: st_sector = first_sector + (p->start_cylinder * spc); ! 475: add_partition(hd, current_minor, st_sector, p->num_sectors); ! 476: current_minor++; ! 477: } ! 478: /* printk("\n");*/ ! 479: brelse(bh); ! 480: return 1; ! 481: } ! 482: ! 483: #endif /* CONFIG_SUN_PARTITION */ ! 484: ! 485: static void check_partition(struct gendisk *hd, kdev_t dev) ! 486: { ! 487: static int first_time = 1; ! 488: unsigned long first_sector; ! 489: ! 490: /* if (first_time) ! 491: printk("Partition check:\n");*/ ! 492: first_time = 0; ! 493: first_sector = hd->part[MINOR(dev)].start_sect; ! 494: ! 495: /* ! 496: * This is a kludge to allow the partition check to be ! 497: * skipped for specific drives (e.g. IDE cd-rom drives) ! 498: */ ! 499: if ((int)first_sector == -1) { ! 500: hd->part[MINOR(dev)].start_sect = 0; ! 501: return; ! 502: } ! 503: ! 504: /* printk(" "); ! 505: print_minor_name(hd, MINOR(dev));*/ ! 506: #ifdef CONFIG_MSDOS_PARTITION ! 507: if (msdos_partition(hd, dev, first_sector)) ! 508: return; ! 509: #endif ! 510: #ifdef CONFIG_OSF_PARTITION ! 511: if (osf_partition(hd, dev, first_sector)) ! 512: return; ! 513: #endif ! 514: #ifdef CONFIG_SUN_PARTITION ! 515: if(sun_partition(hd, dev, first_sector)) ! 516: return; ! 517: #endif ! 518: printk(" unknown partition table\n"); ! 519: } ! 520: ! 521: /* This function is used to re-read partition tables for removable disks. ! 522: Much of the cleanup from the old partition tables should have already been ! 523: done */ ! 524: ! 525: /* This function will re-read the partition tables for a given device, ! 526: and set things back up again. There are some important caveats, ! 527: however. You must ensure that no one is using the device, and no one ! 528: can start using the device while this function is being executed. */ ! 529: ! 530: void resetup_one_dev(struct gendisk *dev, int drive) ! 531: { ! 532: int i; ! 533: int first_minor = drive << dev->minor_shift; ! 534: int end_minor = first_minor + dev->max_p; ! 535: ! 536: blk_size[dev->major] = NULL; ! 537: current_minor = 1 + first_minor; ! 538: check_partition(dev, MKDEV(dev->major, first_minor)); ! 539: ! 540: /* ! 541: * We need to set the sizes array before we will be able to access ! 542: * any of the partitions on this device. ! 543: */ ! 544: if (dev->sizes != NULL) { /* optional safeguard in ll_rw_blk.c */ ! 545: for (i = first_minor; i < end_minor; i++) ! 546: dev->sizes[i] = dev->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9); ! 547: blk_size[dev->major] = dev->sizes; ! 548: } ! 549: } ! 550: ! 551: static void setup_dev(struct gendisk *dev) ! 552: { ! 553: int i, drive; ! 554: int end_minor = dev->max_nr * dev->max_p; ! 555: ! 556: blk_size[dev->major] = NULL; ! 557: for (i = 0 ; i < end_minor; i++) { ! 558: dev->part[i].start_sect = 0; ! 559: dev->part[i].nr_sects = 0; ! 560: } ! 561: dev->init(dev); ! 562: for (drive = 0 ; drive < dev->nr_real ; drive++) { ! 563: int first_minor = drive << dev->minor_shift; ! 564: current_minor = 1 + first_minor; ! 565: check_partition(dev, MKDEV(dev->major, first_minor)); ! 566: } ! 567: if (dev->sizes != NULL) { /* optional safeguard in ll_rw_blk.c */ ! 568: for (i = 0; i < end_minor; i++) ! 569: dev->sizes[i] = dev->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9); ! 570: blk_size[dev->major] = dev->sizes; ! 571: } ! 572: } ! 573: ! 574: void device_setup(void) ! 575: { ! 576: extern void console_map_init(void); ! 577: struct gendisk *p; ! 578: int nr=0; ! 579: #ifdef MACH ! 580: extern int linux_intr_pri; ! 581: ! 582: linux_intr_pri = SPL5; ! 583: #endif ! 584: ! 585: #ifndef MACH ! 586: chr_dev_init(); ! 587: #endif ! 588: blk_dev_init(); ! 589: sti(); ! 590: #ifdef CONFIG_SCSI ! 591: scsi_dev_init(); ! 592: #endif ! 593: #ifdef CONFIG_INET ! 594: #ifdef MACH ! 595: linux_intr_pri = SPL6; ! 596: #endif ! 597: net_dev_init(); ! 598: #endif ! 599: #ifndef MACH ! 600: console_map_init(); ! 601: #endif ! 602: ! 603: for (p = gendisk_head ; p ; p=p->next) { ! 604: setup_dev(p); ! 605: nr += p->nr_real; ! 606: } ! 607: #ifdef CONFIG_BLK_DEV_RAM ! 608: rd_load(); ! 609: #endif ! 610: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.