1 /*
2  *  fs/partitions/sgi.c
3  *
4  *  Code extracted from drivers/block/genhd.c
5  */
6 
7 #include <linux/fs.h>
8 #include <linux/genhd.h>
9 #include <linux/kernel.h>
10 #include <linux/major.h>
11 #include <linux/string.h>
12 #include <linux/blk.h>
13 
14 #include <asm/byteorder.h>
15 #include <asm/system.h>
16 
17 #include "check.h"
18 #include "sgi.h"
19 
sgi_partition(struct gendisk * hd,struct block_device * bdev,unsigned long first_sector,int current_minor)20 int sgi_partition(struct gendisk *hd, struct block_device *bdev, unsigned long first_sector, int current_minor)
21 {
22 	int i, csum, magic;
23 	unsigned int *ui, start, blocks, cs;
24 	Sector sect;
25 	kdev_t dev = to_kdev_t(bdev->bd_dev);
26 	struct sgi_disklabel {
27 		int magic_mushroom;         /* Big fat spliff... */
28 		short root_part_num;        /* Root partition number */
29 		short swap_part_num;        /* Swap partition number */
30 		char boot_file[16];         /* Name of boot file for ARCS */
31 		unsigned char _unused0[48]; /* Device parameter useless crapola.. */
32 		struct sgi_volume {
33 			char name[8];       /* Name of volume */
34 			int  block_num;     /* Logical block number */
35 			int  num_bytes;     /* How big, in bytes */
36 		} volume[15];
37 		struct sgi_partition {
38 			int num_blocks;     /* Size in logical blocks */
39 			int first_block;    /* First logical block */
40 			int type;           /* Type of this partition */
41 		} partitions[16];
42 		int csum;                   /* Disk label checksum */
43 		int _unused1;               /* Padding */
44 	} *label;
45 	struct sgi_partition *p;
46 
47 	label = (struct sgi_disklabel *) read_dev_sector(bdev, 0, &sect);
48 	if (!label)
49 		return -1;
50 	p = &label->partitions[0];
51 	magic = label->magic_mushroom;
52 	if(be32_to_cpu(magic) != SGI_LABEL_MAGIC) {
53 		/*printk("Dev %s SGI disklabel: bad magic %08x\n",
54 		       bdevname(dev), magic);*/
55 		put_dev_sector(sect);
56 		return 0;
57 	}
58 	ui = ((unsigned int *) (label + 1)) - 1;
59 	for(csum = 0; ui >= ((unsigned int *) label);) {
60 		cs = *ui--;
61 		csum += be32_to_cpu(cs);
62 	}
63 	if(csum) {
64 		printk(KERN_WARNING "Dev %s SGI disklabel: csum bad, label corrupted\n",
65 		       bdevname(dev));
66 		put_dev_sector(sect);
67 		return 0;
68 	}
69 	/* All SGI disk labels have 16 partitions, disks under Linux only
70 	 * have 15 minor's.  Luckily there are always a few zero length
71 	 * partitions which we don't care about so we never overflow the
72 	 * current_minor.
73 	 */
74 	for(i = 0; i < 16; i++, p++) {
75 		blocks = be32_to_cpu(p->num_blocks);
76 		start  = be32_to_cpu(p->first_block);
77 		if(!blocks)
78 			continue;
79 		add_gd_partition(hd, current_minor, start, blocks);
80 		current_minor++;
81 	}
82 	printk("\n");
83 	put_dev_sector(sect);
84 	return 1;
85 }
86