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