|
|
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, ! 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: #ifdef CONFIG_BLK_DEV_INITRD ! 28: #include <linux/blk.h> ! 29: #endif ! 30: ! 31: #include <asm/system.h> ! 32: ! 33: /* ! 34: * Many architectures don't like unaligned accesses, which is ! 35: * frequently the case with the nr_sects and start_sect partition ! 36: * table entries. ! 37: */ ! 38: #include <asm/unaligned.h> ! 39: ! 40: #ifdef MACH ! 41: #include <machine/spl.h> ! 42: #endif ! 43: ! 44: #define SYS_IND(p) get_unaligned(&p->sys_ind) ! 45: #define NR_SECTS(p) get_unaligned(&p->nr_sects) ! 46: #define START_SECT(p) get_unaligned(&p->start_sect) ! 47: ! 48: ! 49: struct gendisk *gendisk_head = NULL; ! 50: ! 51: static int current_minor = 0; ! 52: extern int *blk_size[]; ! 53: extern void rd_load(void); ! 54: extern void initrd_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: /* ! 62: * disk_name() is used by genhd.c and md.c. ! 63: * It formats the devicename of the indicated disk ! 64: * into the supplied buffer, and returns a pointer ! 65: * to that same buffer (for convenience). ! 66: */ ! 67: char *disk_name (struct gendisk *hd, int minor, char *buf) ! 68: { ! 69: unsigned int part; ! 70: const char *maj = hd->major_name; ! 71: #ifdef MACH ! 72: char unit = (minor >> hd->minor_shift) + '0'; ! 73: #else ! 74: char unit = (minor >> hd->minor_shift) + 'a'; ! 75: #endif ! 76: ! 77: #ifdef CONFIG_BLK_DEV_IDE ! 78: /* ! 79: * IDE devices use multiple major numbers, but the drives ! 80: * are named as: {hda,hdb}, {hdc,hdd}, {hde,hdf}, {hdg,hdh}.. ! 81: * This requires special handling here. ! 82: */ ! 83: switch (hd->major) { ! 84: case IDE3_MAJOR: ! 85: unit += 2; ! 86: case IDE2_MAJOR: ! 87: unit += 2; ! 88: case IDE1_MAJOR: ! 89: unit += 2; ! 90: case IDE0_MAJOR: ! 91: maj = "hd"; ! 92: } ! 93: #endif ! 94: part = minor & ((1 << hd->minor_shift) - 1); ! 95: if (part) ! 96: #ifdef MACH ! 97: sprintf(buf, "%s%cs%d", maj, unit, part); ! 98: #else ! 99: sprintf(buf, "%s%c%d", maj, unit, part); ! 100: #endif ! 101: else ! 102: sprintf(buf, "%s%c", maj, unit); ! 103: return buf; ! 104: } ! 105: ! 106: static void add_partition (struct gendisk *hd, int minor, int start, int size) ! 107: { ! 108: char buf[8]; ! 109: hd->part[minor].start_sect = start; ! 110: hd->part[minor].nr_sects = size; ! 111: printk(" %s", disk_name(hd, minor, buf)); ! 112: } ! 113: ! 114: #ifdef MACH ! 115: static int mach_minor; ! 116: static void ! 117: add_bsd_partition (struct gendisk *hd, int minor, int slice, ! 118: int start, int size) ! 119: { ! 120: char buf[16]; ! 121: hd->part[minor].start_sect = start; ! 122: hd->part[minor].nr_sects = size; ! 123: printk (" %s%c", disk_name (hd, mach_minor, buf), slice); ! 124: } ! 125: #endif ! 126: ! 127: static inline int is_extended_partition(struct partition *p) ! 128: { ! 129: return (SYS_IND(p) == DOS_EXTENDED_PARTITION || ! 130: SYS_IND(p) == WIN98_EXTENDED_PARTITION || ! 131: SYS_IND(p) == LINUX_EXTENDED_PARTITION); ! 132: } ! 133: ! 134: #ifdef CONFIG_MSDOS_PARTITION ! 135: /* ! 136: * Create devices for each logical partition in an extended partition. ! 137: * The logical partitions form a linked list, with each entry being ! 138: * a partition table with two entries. The first entry ! 139: * is the real data partition (with a start relative to the partition ! 140: * table start). The second is a pointer to the next logical partition ! 141: * (with a start relative to the entire extended partition). ! 142: * We do not create a Linux partition for the partition tables, but ! 143: * only for the actual data partitions. ! 144: */ ! 145: ! 146: static void extended_partition(struct gendisk *hd, kdev_t dev) ! 147: { ! 148: struct buffer_head *bh; ! 149: struct partition *p; ! 150: unsigned long first_sector, first_size, this_sector, this_size; ! 151: int mask = (1 << hd->minor_shift) - 1; ! 152: int i; ! 153: ! 154: first_sector = hd->part[MINOR(dev)].start_sect; ! 155: first_size = hd->part[MINOR(dev)].nr_sects; ! 156: this_sector = first_sector; ! 157: ! 158: while (1) { ! 159: if ((current_minor & mask) == 0) ! 160: return; ! 161: if (!(bh = bread(dev,0,1024))) ! 162: return; ! 163: /* ! 164: * This block is from a device that we're about to stomp on. ! 165: * So make sure nobody thinks this block is usable. ! 166: */ ! 167: bh->b_state = 0; ! 168: ! 169: if (*(unsigned short *) (bh->b_data+510) != 0xAA55) ! 170: goto done; ! 171: ! 172: p = (struct partition *) (0x1BE + bh->b_data); ! 173: ! 174: this_size = hd->part[MINOR(dev)].nr_sects; ! 175: ! 176: /* ! 177: * Usually, the first entry is the real data partition, ! 178: * the 2nd entry is the next extended partition, or empty, ! 179: * and the 3rd and 4th entries are unused. ! 180: * However, DRDOS sometimes has the extended partition as ! 181: * the first entry (when the data partition is empty), ! 182: * and OS/2 seems to use all four entries. ! 183: */ ! 184: ! 185: /* ! 186: * First process the data partition(s) ! 187: */ ! 188: for (i=0; i<4; i++, p++) { ! 189: if (!NR_SECTS(p) || is_extended_partition(p)) ! 190: continue; ! 191: ! 192: /* Check the 3rd and 4th entries - ! 193: these sometimes contain random garbage */ ! 194: if (i >= 2 ! 195: && START_SECT(p) + NR_SECTS(p) > this_size ! 196: && (this_sector + START_SECT(p) < first_sector || ! 197: this_sector + START_SECT(p) + NR_SECTS(p) > ! 198: first_sector + first_size)) ! 199: continue; ! 200: ! 201: add_partition(hd, current_minor, this_sector+START_SECT(p), NR_SECTS(p)); ! 202: current_minor++; ! 203: if ((current_minor & mask) == 0) ! 204: goto done; ! 205: } ! 206: /* ! 207: * Next, process the (first) extended partition, if present. ! 208: * (So far, there seems to be no reason to make ! 209: * extended_partition() recursive and allow a tree ! 210: * of extended partitions.) ! 211: * It should be a link to the next logical partition. ! 212: * Create a minor for this just long enough to get the next ! 213: * partition table. The minor will be reused for the next ! 214: * data partition. ! 215: */ ! 216: p -= 4; ! 217: for (i=0; i<4; i++, p++) ! 218: if(NR_SECTS(p) && is_extended_partition(p)) ! 219: break; ! 220: if (i == 4) ! 221: goto done; /* nothing left to do */ ! 222: ! 223: hd->part[current_minor].nr_sects = NR_SECTS(p); ! 224: hd->part[current_minor].start_sect = first_sector + START_SECT(p); ! 225: this_sector = first_sector + START_SECT(p); ! 226: dev = MKDEV(hd->major, current_minor); ! 227: brelse(bh); ! 228: } ! 229: done: ! 230: brelse(bh); ! 231: } ! 232: ! 233: #ifdef CONFIG_BSD_DISKLABEL ! 234: /* ! 235: * Create devices for BSD partitions listed in a disklabel, under a ! 236: * dos-like partition. See extended_partition() for more information. ! 237: */ ! 238: static void bsd_disklabel_partition(struct gendisk *hd, kdev_t dev) ! 239: { ! 240: struct buffer_head *bh; ! 241: struct bsd_disklabel *l; ! 242: struct bsd_partition *p; ! 243: int mask = (1 << hd->minor_shift) - 1; ! 244: ! 245: if (!(bh = bread(dev,0,1024))) ! 246: return; ! 247: bh->b_state = 0; ! 248: l = (struct bsd_disklabel *) (bh->b_data+512); ! 249: if (l->d_magic != BSD_DISKMAGIC) { ! 250: brelse(bh); ! 251: return; ! 252: } ! 253: ! 254: p = &l->d_partitions[0]; ! 255: while (p - &l->d_partitions[0] <= BSD_MAXPARTITIONS) { ! 256: if ((current_minor & mask) >= (4 + hd->max_p)) ! 257: break; ! 258: ! 259: if (p->p_fstype != BSD_FS_UNUSED) { ! 260: #ifdef MACH ! 261: add_bsd_partition (hd, current_minor, ! 262: p - &l->d_partitions[0] + 'a', ! 263: p->p_offset, p->p_size); ! 264: #else ! 265: add_partition(hd, current_minor, p->p_offset, p->p_size); ! 266: #endif ! 267: current_minor++; ! 268: } ! 269: p++; ! 270: } ! 271: brelse(bh); ! 272: ! 273: } ! 274: #endif ! 275: ! 276: static int msdos_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector) ! 277: { ! 278: int i, minor = current_minor; ! 279: struct buffer_head *bh; ! 280: struct partition *p; ! 281: unsigned char *data; ! 282: int mask = (1 << hd->minor_shift) - 1; ! 283: #ifdef CONFIG_BLK_DEV_IDE ! 284: int tested_for_xlate = 0; ! 285: ! 286: read_mbr: ! 287: #endif ! 288: if (!(bh = bread(dev,0,1024))) { ! 289: printk(" unable to read partition table\n"); ! 290: return -1; ! 291: } ! 292: data = bh->b_data; ! 293: /* In some cases we modify the geometry */ ! 294: /* of the drive (below), so ensure that */ ! 295: /* nobody else tries to re-use this data. */ ! 296: bh->b_state = 0; ! 297: #ifdef CONFIG_BLK_DEV_IDE ! 298: check_table: ! 299: #endif ! 300: if (*(unsigned short *) (0x1fe + data) != 0xAA55) { ! 301: brelse(bh); ! 302: return 0; ! 303: } ! 304: p = (struct partition *) (0x1be + data); ! 305: ! 306: #ifdef CONFIG_BLK_DEV_IDE ! 307: if (!tested_for_xlate++) { /* Do this only once per disk */ ! 308: /* ! 309: * Look for various forms of IDE disk geometry translation ! 310: */ ! 311: extern int ide_xlate_1024(kdev_t, int, const char *); ! 312: unsigned int sig = *(unsigned short *)(data + 2); ! 313: if (SYS_IND(p) == EZD_PARTITION) { ! 314: /* ! 315: * The remainder of the disk must be accessed using ! 316: * a translated geometry that reduces the number of ! 317: * apparent cylinders to less than 1024 if possible. ! 318: * ! 319: * ide_xlate_1024() will take care of the necessary ! 320: * adjustments to fool fdisk/LILO and partition check. ! 321: */ ! 322: if (ide_xlate_1024(dev, -1, " [EZD]")) { ! 323: data += 512; ! 324: goto check_table; ! 325: } ! 326: } else if (SYS_IND(p) == DM6_PARTITION) { ! 327: ! 328: /* ! 329: * Everything on the disk is offset by 63 sectors, ! 330: * including a "new" MBR with its own partition table, ! 331: * and the remainder of the disk must be accessed using ! 332: * a translated geometry that reduces the number of ! 333: * apparent cylinders to less than 1024 if possible. ! 334: * ! 335: * ide_xlate_1024() will take care of the necessary ! 336: * adjustments to fool fdisk/LILO and partition check. ! 337: */ ! 338: if (ide_xlate_1024(dev, 1, " [DM6:DDO]")) { ! 339: brelse(bh); ! 340: goto read_mbr; /* start over with new MBR */ ! 341: } ! 342: } else if (sig <= 0x1ae && *(unsigned short *)(data + sig) == 0x55AA ! 343: && (1 & *(unsigned char *)(data + sig + 2)) ) ! 344: { ! 345: /* ! 346: * DM6 signature in MBR, courtesy of OnTrack ! 347: */ ! 348: (void) ide_xlate_1024 (dev, 0, " [DM6:MBR]"); ! 349: } else if (SYS_IND(p) == DM6_AUX1PARTITION || SYS_IND(p) == DM6_AUX3PARTITION) { ! 350: /* ! 351: * DM6 on other than the first (boot) drive ! 352: */ ! 353: (void) ide_xlate_1024(dev, 0, " [DM6:AUX]"); ! 354: } else { ! 355: /* ! 356: * Examine the partition table for common translations. ! 357: * This is necessary for drives for situations where ! 358: * the translated geometry is unavailable from the BIOS. ! 359: */ ! 360: for (i = 0; i < 4 ; i++) { ! 361: struct partition *q = &p[i]; ! 362: if (NR_SECTS(q) ! 363: && (q->sector & 63) == 1 ! 364: && (q->end_sector & 63) == 63) { ! 365: unsigned int heads = q->end_head + 1; ! 366: if (heads == 32 || heads == 64 || heads == 128 || heads == 255) { ! 367: ! 368: (void) ide_xlate_1024(dev, heads, " [PTBL]"); ! 369: break; ! 370: } ! 371: } ! 372: } ! 373: } ! 374: } ! 375: #endif /* CONFIG_BLK_DEV_IDE */ ! 376: ! 377: current_minor += 4; /* first "extra" minor (for extended partitions) */ ! 378: for (i=1 ; i<=4 ; minor++,i++,p++) { ! 379: if (!NR_SECTS(p)) ! 380: continue; ! 381: add_partition(hd, minor, first_sector+START_SECT(p), NR_SECTS(p)); ! 382: if (is_extended_partition(p)) { ! 383: printk(" <"); ! 384: /* ! 385: * If we are rereading the partition table, we need ! 386: * to set the size of the partition so that we will ! 387: * be able to bread the block containing the extended ! 388: * partition info. ! 389: */ ! 390: hd->sizes[minor] = hd->part[minor].nr_sects ! 391: >> (BLOCK_SIZE_BITS - 9); ! 392: extended_partition(hd, MKDEV(hd->major, minor)); ! 393: printk(" >"); ! 394: /* prevent someone doing mkfs or mkswap on an ! 395: extended partition, but leave room for LILO */ ! 396: if (hd->part[minor].nr_sects > 2) ! 397: hd->part[minor].nr_sects = 2; ! 398: } ! 399: #ifdef CONFIG_BSD_DISKLABEL ! 400: if (SYS_IND(p) == BSD_PARTITION) { ! 401: printk(" <"); ! 402: #ifdef MACH ! 403: mach_minor = minor; ! 404: #endif ! 405: bsd_disklabel_partition(hd, MKDEV(hd->major, minor)); ! 406: printk(" >"); ! 407: } ! 408: #endif ! 409: } ! 410: /* ! 411: * Check for old-style Disk Manager partition table ! 412: */ ! 413: if (*(unsigned short *) (data+0xfc) == 0x55AA) { ! 414: p = (struct partition *) (0x1be + data); ! 415: for (i = 4 ; i < 16 ; i++, current_minor++) { ! 416: p--; ! 417: if ((current_minor & mask) == 0) ! 418: break; ! 419: if (!(START_SECT(p) && NR_SECTS(p))) ! 420: continue; ! 421: add_partition(hd, current_minor, START_SECT(p), NR_SECTS(p)); ! 422: } ! 423: } ! 424: printk("\n"); ! 425: brelse(bh); ! 426: return 1; ! 427: } ! 428: ! 429: #endif /* CONFIG_MSDOS_PARTITION */ ! 430: ! 431: #ifdef CONFIG_OSF_PARTITION ! 432: ! 433: static int osf_partition(struct gendisk *hd, unsigned int dev, unsigned long first_sector) ! 434: { ! 435: int i; ! 436: int mask = (1 << hd->minor_shift) - 1; ! 437: struct buffer_head *bh; ! 438: struct disklabel { ! 439: u32 d_magic; ! 440: u16 d_type,d_subtype; ! 441: u8 d_typename[16]; ! 442: u8 d_packname[16]; ! 443: u32 d_secsize; ! 444: u32 d_nsectors; ! 445: u32 d_ntracks; ! 446: u32 d_ncylinders; ! 447: u32 d_secpercyl; ! 448: u32 d_secprtunit; ! 449: u16 d_sparespertrack; ! 450: u16 d_sparespercyl; ! 451: u32 d_acylinders; ! 452: u16 d_rpm, d_interleave, d_trackskew, d_cylskew; ! 453: u32 d_headswitch, d_trkseek, d_flags; ! 454: u32 d_drivedata[5]; ! 455: u32 d_spare[5]; ! 456: u32 d_magic2; ! 457: u16 d_checksum; ! 458: u16 d_npartitions; ! 459: u32 d_bbsize, d_sbsize; ! 460: struct d_partition { ! 461: u32 p_size; ! 462: u32 p_offset; ! 463: u32 p_fsize; ! 464: u8 p_fstype; ! 465: u8 p_frag; ! 466: u16 p_cpg; ! 467: } d_partitions[8]; ! 468: } * label; ! 469: struct d_partition * partition; ! 470: #define DISKLABELMAGIC (0x82564557UL) ! 471: ! 472: if (!(bh = bread(dev,0,1024))) { ! 473: printk("unable to read partition table\n"); ! 474: return -1; ! 475: } ! 476: label = (struct disklabel *) (bh->b_data+64); ! 477: partition = label->d_partitions; ! 478: if (label->d_magic != DISKLABELMAGIC) { ! 479: printk("magic: %08x\n", label->d_magic); ! 480: brelse(bh); ! 481: return 0; ! 482: } ! 483: if (label->d_magic2 != DISKLABELMAGIC) { ! 484: printk("magic2: %08x\n", label->d_magic2); ! 485: brelse(bh); ! 486: return 0; ! 487: } ! 488: for (i = 0 ; i < label->d_npartitions; i++, partition++) { ! 489: if ((current_minor & mask) == 0) ! 490: break; ! 491: if (partition->p_size) ! 492: add_partition(hd, current_minor, ! 493: first_sector+partition->p_offset, ! 494: partition->p_size); ! 495: current_minor++; ! 496: } ! 497: printk("\n"); ! 498: brelse(bh); ! 499: return 1; ! 500: } ! 501: ! 502: #endif /* CONFIG_OSF_PARTITION */ ! 503: ! 504: #ifdef CONFIG_SUN_PARTITION ! 505: ! 506: static int sun_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector) ! 507: { ! 508: int i, csum; ! 509: unsigned short *ush; ! 510: struct buffer_head *bh; ! 511: struct sun_disklabel { ! 512: unsigned char info[128]; /* Informative text string */ ! 513: unsigned char spare[292]; /* Boot information etc. */ ! 514: unsigned short rspeed; /* Disk rotational speed */ ! 515: unsigned short pcylcount; /* Physical cylinder count */ ! 516: unsigned short sparecyl; /* extra sects per cylinder */ ! 517: unsigned char spare2[4]; /* More magic... */ ! 518: unsigned short ilfact; /* Interleave factor */ ! 519: unsigned short ncyl; /* Data cylinder count */ ! 520: unsigned short nacyl; /* Alt. cylinder count */ ! 521: unsigned short ntrks; /* Tracks per cylinder */ ! 522: unsigned short nsect; /* Sectors per track */ ! 523: unsigned char spare3[4]; /* Even more magic... */ ! 524: struct sun_partition { ! 525: __u32 start_cylinder; ! 526: __u32 num_sectors; ! 527: } partitions[8]; ! 528: unsigned short magic; /* Magic number */ ! 529: unsigned short csum; /* Label xor'd checksum */ ! 530: } * label; ! 531: struct sun_partition *p; ! 532: int other_endian; ! 533: unsigned long spc; ! 534: #define SUN_LABEL_MAGIC 0xDABE ! 535: #define SUN_LABEL_MAGIC_SWAPPED 0xBEDA ! 536: /* No need to optimize these macros since they are called only when reading ! 537: * the partition table. This occurs only at each disk change. */ ! 538: #define SWAP16(x) (other_endian ? (((__u16)(x) & 0xFF) << 8) \ ! 539: | (((__u16)(x) & 0xFF00) >> 8) \ ! 540: : (__u16)(x)) ! 541: #define SWAP32(x) (other_endian ? (((__u32)(x) & 0xFF) << 24) \ ! 542: | (((__u32)(x) & 0xFF00) << 8) \ ! 543: | (((__u32)(x) & 0xFF0000) >> 8) \ ! 544: | (((__u32)(x) & 0xFF000000) >> 24) \ ! 545: : (__u32)(x)) ! 546: ! 547: if(!(bh = bread(dev, 0, 1024))) { ! 548: printk("Dev %s: unable to read partition table\n", ! 549: kdevname(dev)); ! 550: return -1; ! 551: } ! 552: label = (struct sun_disklabel *) bh->b_data; ! 553: p = label->partitions; ! 554: if (label->magic != SUN_LABEL_MAGIC && label->magic != SUN_LABEL_MAGIC_SWAPPED) { ! 555: printk("Dev %s Sun disklabel: bad magic %04x\n", ! 556: kdevname(dev), label->magic); ! 557: brelse(bh); ! 558: return 0; ! 559: } ! 560: other_endian = (label->magic == SUN_LABEL_MAGIC_SWAPPED); ! 561: /* Look at the checksum */ ! 562: ush = ((unsigned short *) (label+1)) - 1; ! 563: for(csum = 0; ush >= ((unsigned short *) label);) ! 564: csum ^= *ush--; ! 565: if(csum) { ! 566: printk("Dev %s Sun disklabel: Csum bad, label corrupted\n", ! 567: kdevname(dev)); ! 568: brelse(bh); ! 569: return 0; ! 570: } ! 571: /* All Sun disks have 8 partition entries */ ! 572: spc = SWAP16(label->ntrks) * SWAP16(label->nsect); ! 573: for(i=0; i < 8; i++, p++) { ! 574: unsigned long st_sector; ! 575: ! 576: /* We register all partitions, even if zero size, so that ! 577: * the minor numbers end up ok as per SunOS interpretation. ! 578: */ ! 579: st_sector = first_sector + SWAP32(p->start_cylinder) * spc; ! 580: add_partition(hd, current_minor, st_sector, SWAP32(p->num_sectors)); ! 581: current_minor++; ! 582: } ! 583: printk("\n"); ! 584: brelse(bh); ! 585: return 1; ! 586: #undef SWAP16 ! 587: #undef SWAP32 ! 588: } ! 589: ! 590: #endif /* CONFIG_SUN_PARTITION */ ! 591: ! 592: #ifdef CONFIG_AMIGA_PARTITION ! 593: #include <asm/byteorder.h> ! 594: #include <linux/affs_hardblocks.h> ! 595: ! 596: static __inline__ __u32 ! 597: checksum_block(__u32 *m, int size) ! 598: { ! 599: __u32 sum = 0; ! 600: ! 601: while (size--) ! 602: sum += htonl(*m++); ! 603: return sum; ! 604: } ! 605: ! 606: static int ! 607: amiga_partition(struct gendisk *hd, unsigned int dev, unsigned long first_sector) ! 608: { ! 609: struct buffer_head *bh; ! 610: struct RigidDiskBlock *rdb; ! 611: struct PartitionBlock *pb; ! 612: int start_sect; ! 613: int nr_sects; ! 614: int blk; ! 615: int part, res; ! 616: ! 617: set_blocksize(dev,512); ! 618: res = 0; ! 619: ! 620: for (blk = 0; blk < RDB_ALLOCATION_LIMIT; blk++) { ! 621: if(!(bh = bread(dev,blk,512))) { ! 622: printk("Dev %d: unable to read RDB block %d\n",dev,blk); ! 623: goto rdb_done; ! 624: } ! 625: if (*(__u32 *)bh->b_data == htonl(IDNAME_RIGIDDISK)) { ! 626: rdb = (struct RigidDiskBlock *)bh->b_data; ! 627: if (checksum_block((__u32 *)bh->b_data,htonl(rdb->rdb_SummedLongs) & 0x7F)) { ! 628: printk("Dev %d: RDB in block %d has bad checksum\n",dev,blk); ! 629: brelse(bh); ! 630: continue; ! 631: } ! 632: printk(" RDSK"); ! 633: blk = htonl(rdb->rdb_PartitionList); ! 634: brelse(bh); ! 635: for (part = 1; blk > 0 && part <= 16; part++) { ! 636: if (!(bh = bread(dev,blk,512))) { ! 637: printk("Dev %d: unable to read partition block %d\n", ! 638: dev,blk); ! 639: goto rdb_done; ! 640: } ! 641: pb = (struct PartitionBlock *)bh->b_data; ! 642: blk = htonl(pb->pb_Next); ! 643: if (pb->pb_ID == htonl(IDNAME_PARTITION) && checksum_block( ! 644: (__u32 *)pb,htonl(pb->pb_SummedLongs) & 0x7F) == 0 ) { ! 645: ! 646: /* Tell Kernel about it */ ! 647: ! 648: if (!(nr_sects = (htonl(pb->pb_Environment[10]) + 1 - ! 649: htonl(pb->pb_Environment[9])) * ! 650: htonl(pb->pb_Environment[3]) * ! 651: htonl(pb->pb_Environment[5]))) { ! 652: continue; ! 653: } ! 654: start_sect = htonl(pb->pb_Environment[9]) * ! 655: htonl(pb->pb_Environment[3]) * ! 656: htonl(pb->pb_Environment[5]); ! 657: add_partition(hd,current_minor,start_sect,nr_sects); ! 658: current_minor++; ! 659: res = 1; ! 660: } ! 661: brelse(bh); ! 662: } ! 663: printk("\n"); ! 664: break; ! 665: } ! 666: } ! 667: ! 668: rdb_done: ! 669: set_blocksize(dev,BLOCK_SIZE); ! 670: return res; ! 671: } ! 672: #endif /* CONFIG_AMIGA_PARTITION */ ! 673: ! 674: static void check_partition(struct gendisk *hd, kdev_t dev) ! 675: { ! 676: static int first_time = 1; ! 677: unsigned long first_sector; ! 678: char buf[8]; ! 679: ! 680: if (first_time) ! 681: printk("Partition check:\n"); ! 682: first_time = 0; ! 683: first_sector = hd->part[MINOR(dev)].start_sect; ! 684: ! 685: /* ! 686: * This is a kludge to allow the partition check to be ! 687: * skipped for specific drives (e.g. IDE cd-rom drives) ! 688: */ ! 689: if ((int)first_sector == -1) { ! 690: hd->part[MINOR(dev)].start_sect = 0; ! 691: return; ! 692: } ! 693: ! 694: printk(" %s:", disk_name(hd, MINOR(dev), buf)); ! 695: #ifdef CONFIG_MSDOS_PARTITION ! 696: if (msdos_partition(hd, dev, first_sector)) ! 697: return; ! 698: #endif ! 699: #ifdef CONFIG_OSF_PARTITION ! 700: if (osf_partition(hd, dev, first_sector)) ! 701: return; ! 702: #endif ! 703: #ifdef CONFIG_SUN_PARTITION ! 704: if(sun_partition(hd, dev, first_sector)) ! 705: return; ! 706: #endif ! 707: #ifdef CONFIG_AMIGA_PARTITION ! 708: if(amiga_partition(hd, dev, first_sector)) ! 709: return; ! 710: #endif ! 711: printk(" unknown partition table\n"); ! 712: } ! 713: ! 714: /* This function is used to re-read partition tables for removable disks. ! 715: Much of the cleanup from the old partition tables should have already been ! 716: done */ ! 717: ! 718: /* This function will re-read the partition tables for a given device, ! 719: and set things back up again. There are some important caveats, ! 720: however. You must ensure that no one is using the device, and no one ! 721: can start using the device while this function is being executed. */ ! 722: ! 723: void resetup_one_dev(struct gendisk *dev, int drive) ! 724: { ! 725: int i; ! 726: int first_minor = drive << dev->minor_shift; ! 727: int end_minor = first_minor + dev->max_p; ! 728: ! 729: blk_size[dev->major] = NULL; ! 730: current_minor = 1 + first_minor; ! 731: check_partition(dev, MKDEV(dev->major, first_minor)); ! 732: ! 733: /* ! 734: * We need to set the sizes array before we will be able to access ! 735: * any of the partitions on this device. ! 736: */ ! 737: if (dev->sizes != NULL) { /* optional safeguard in ll_rw_blk.c */ ! 738: for (i = first_minor; i < end_minor; i++) ! 739: dev->sizes[i] = dev->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9); ! 740: blk_size[dev->major] = dev->sizes; ! 741: } ! 742: } ! 743: ! 744: static void setup_dev(struct gendisk *dev) ! 745: { ! 746: int i, drive; ! 747: int end_minor = dev->max_nr * dev->max_p; ! 748: ! 749: blk_size[dev->major] = NULL; ! 750: for (i = 0 ; i < end_minor; i++) { ! 751: dev->part[i].start_sect = 0; ! 752: dev->part[i].nr_sects = 0; ! 753: } ! 754: dev->init(dev); ! 755: for (drive = 0 ; drive < dev->nr_real ; drive++) { ! 756: int first_minor = drive << dev->minor_shift; ! 757: current_minor = 1 + first_minor; ! 758: check_partition(dev, MKDEV(dev->major, first_minor)); ! 759: } ! 760: if (dev->sizes != NULL) { /* optional safeguard in ll_rw_blk.c */ ! 761: for (i = 0; i < end_minor; i++) ! 762: dev->sizes[i] = dev->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9); ! 763: blk_size[dev->major] = dev->sizes; ! 764: } ! 765: } ! 766: ! 767: void device_setup(void) ! 768: { ! 769: extern void console_map_init(void); ! 770: struct gendisk *p; ! 771: int nr=0; ! 772: #ifdef MACH ! 773: extern int linux_intr_pri; ! 774: ! 775: linux_intr_pri = SPL5; ! 776: #endif ! 777: ! 778: #ifndef MACH ! 779: chr_dev_init(); ! 780: #endif ! 781: blk_dev_init(); ! 782: sti(); ! 783: #ifdef CONFIG_SCSI ! 784: scsi_dev_init(); ! 785: #endif ! 786: #ifdef CONFIG_INET ! 787: #ifdef MACH ! 788: linux_intr_pri = SPL6; ! 789: #endif ! 790: net_dev_init(); ! 791: #endif ! 792: #ifndef MACH ! 793: console_map_init(); ! 794: #endif ! 795: ! 796: for (p = gendisk_head ; p ; p=p->next) { ! 797: setup_dev(p); ! 798: nr += p->nr_real; ! 799: } ! 800: #ifdef CONFIG_BLK_DEV_RAM ! 801: #ifdef CONFIG_BLK_DEV_INITRD ! 802: if (initrd_start && mount_initrd) initrd_load(); ! 803: else ! 804: #endif ! 805: rd_load(); ! 806: #endif ! 807: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.