diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/partitions/ibm.c | 101 |
1 files changed, 71 insertions, 30 deletions
diff --git a/fs/partitions/ibm.c b/fs/partitions/ibm.c index 1e064c4a4f86..46297683cd34 100644 --- a/fs/partitions/ibm.c +++ b/fs/partitions/ibm.c | |||
@@ -21,20 +21,38 @@ | |||
21 | * compute the block number from a | 21 | * compute the block number from a |
22 | * cyl-cyl-head-head structure | 22 | * cyl-cyl-head-head structure |
23 | */ | 23 | */ |
24 | static inline int | 24 | static sector_t |
25 | cchh2blk (struct vtoc_cchh *ptr, struct hd_geometry *geo) { | 25 | cchh2blk (struct vtoc_cchh *ptr, struct hd_geometry *geo) { |
26 | return ptr->cc * geo->heads * geo->sectors + | 26 | |
27 | ptr->hh * geo->sectors; | 27 | sector_t cyl; |
28 | __u16 head; | ||
29 | |||
30 | /*decode cylinder and heads for large volumes */ | ||
31 | cyl = ptr->hh & 0xFFF0; | ||
32 | cyl <<= 12; | ||
33 | cyl |= ptr->cc; | ||
34 | head = ptr->hh & 0x000F; | ||
35 | return cyl * geo->heads * geo->sectors + | ||
36 | head * geo->sectors; | ||
28 | } | 37 | } |
29 | 38 | ||
30 | /* | 39 | /* |
31 | * compute the block number from a | 40 | * compute the block number from a |
32 | * cyl-cyl-head-head-block structure | 41 | * cyl-cyl-head-head-block structure |
33 | */ | 42 | */ |
34 | static inline int | 43 | static sector_t |
35 | cchhb2blk (struct vtoc_cchhb *ptr, struct hd_geometry *geo) { | 44 | cchhb2blk (struct vtoc_cchhb *ptr, struct hd_geometry *geo) { |
36 | return ptr->cc * geo->heads * geo->sectors + | 45 | |
37 | ptr->hh * geo->sectors + | 46 | sector_t cyl; |
47 | __u16 head; | ||
48 | |||
49 | /*decode cylinder and heads for large volumes */ | ||
50 | cyl = ptr->hh & 0xFFF0; | ||
51 | cyl <<= 12; | ||
52 | cyl |= ptr->cc; | ||
53 | head = ptr->hh & 0x000F; | ||
54 | return cyl * geo->heads * geo->sectors + | ||
55 | head * geo->sectors + | ||
38 | ptr->b; | 56 | ptr->b; |
39 | } | 57 | } |
40 | 58 | ||
@@ -43,14 +61,15 @@ cchhb2blk (struct vtoc_cchhb *ptr, struct hd_geometry *geo) { | |||
43 | int | 61 | int |
44 | ibm_partition(struct parsed_partitions *state, struct block_device *bdev) | 62 | ibm_partition(struct parsed_partitions *state, struct block_device *bdev) |
45 | { | 63 | { |
46 | int blocksize, offset, size,res; | 64 | int blocksize, res; |
47 | loff_t i_size; | 65 | loff_t i_size, offset, size, fmt_size; |
48 | dasd_information2_t *info; | 66 | dasd_information2_t *info; |
49 | struct hd_geometry *geo; | 67 | struct hd_geometry *geo; |
50 | char type[5] = {0,}; | 68 | char type[5] = {0,}; |
51 | char name[7] = {0,}; | 69 | char name[7] = {0,}; |
52 | union label_t { | 70 | union label_t { |
53 | struct vtoc_volume_label vol; | 71 | struct vtoc_volume_label_cdl vol; |
72 | struct vtoc_volume_label_ldl lnx; | ||
54 | struct vtoc_cms_label cms; | 73 | struct vtoc_cms_label cms; |
55 | } *label; | 74 | } *label; |
56 | unsigned char *data; | 75 | unsigned char *data; |
@@ -85,14 +104,16 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev) | |||
85 | if (data == NULL) | 104 | if (data == NULL) |
86 | goto out_readerr; | 105 | goto out_readerr; |
87 | 106 | ||
88 | strncpy (type, data, 4); | ||
89 | if ((!info->FBA_layout) && (!strcmp(info->type, "ECKD"))) | ||
90 | strncpy(name, data + 8, 6); | ||
91 | else | ||
92 | strncpy(name, data + 4, 6); | ||
93 | memcpy(label, data, sizeof(union label_t)); | 107 | memcpy(label, data, sizeof(union label_t)); |
94 | put_dev_sector(sect); | 108 | put_dev_sector(sect); |
95 | 109 | ||
110 | if ((!info->FBA_layout) && (!strcmp(info->type, "ECKD"))) { | ||
111 | strncpy(type, label->vol.vollbl, 4); | ||
112 | strncpy(name, label->vol.volid, 6); | ||
113 | } else { | ||
114 | strncpy(type, label->lnx.vollbl, 4); | ||
115 | strncpy(name, label->lnx.volid, 6); | ||
116 | } | ||
96 | EBCASC(type, 4); | 117 | EBCASC(type, 4); |
97 | EBCASC(name, 6); | 118 | EBCASC(name, 6); |
98 | 119 | ||
@@ -110,36 +131,54 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev) | |||
110 | /* | 131 | /* |
111 | * VM style CMS1 labeled disk | 132 | * VM style CMS1 labeled disk |
112 | */ | 133 | */ |
134 | blocksize = label->cms.block_size; | ||
113 | if (label->cms.disk_offset != 0) { | 135 | if (label->cms.disk_offset != 0) { |
114 | printk("CMS1/%8s(MDSK):", name); | 136 | printk("CMS1/%8s(MDSK):", name); |
115 | /* disk is reserved minidisk */ | 137 | /* disk is reserved minidisk */ |
116 | blocksize = label->cms.block_size; | ||
117 | offset = label->cms.disk_offset; | 138 | offset = label->cms.disk_offset; |
118 | size = (label->cms.block_count - 1) | 139 | size = (label->cms.block_count - 1) |
119 | * (blocksize >> 9); | 140 | * (blocksize >> 9); |
120 | } else { | 141 | } else { |
121 | printk("CMS1/%8s:", name); | 142 | printk("CMS1/%8s:", name); |
122 | offset = (info->label_block + 1); | 143 | offset = (info->label_block + 1); |
123 | size = i_size >> 9; | 144 | size = label->cms.block_count |
145 | * (blocksize >> 9); | ||
124 | } | 146 | } |
147 | put_partition(state, 1, offset*(blocksize >> 9), | ||
148 | size-offset*(blocksize >> 9)); | ||
125 | } else { | 149 | } else { |
126 | /* | 150 | if (strncmp(type, "LNX1", 4) == 0) { |
127 | * Old style LNX1 or unlabeled disk | 151 | printk("LNX1/%8s:", name); |
128 | */ | 152 | if (label->lnx.ldl_version == 0xf2) { |
129 | if (strncmp(type, "LNX1", 4) == 0) | 153 | fmt_size = label->lnx.formatted_blocks |
130 | printk ("LNX1/%8s:", name); | 154 | * (blocksize >> 9); |
131 | else | 155 | } else if (!strcmp(info->type, "ECKD")) { |
156 | /* formated w/o large volume support */ | ||
157 | fmt_size = geo->cylinders * geo->heads | ||
158 | * geo->sectors * (blocksize >> 9); | ||
159 | } else { | ||
160 | /* old label and no usable disk geometry | ||
161 | * (e.g. DIAG) */ | ||
162 | fmt_size = i_size >> 9; | ||
163 | } | ||
164 | size = i_size >> 9; | ||
165 | if (fmt_size < size) | ||
166 | size = fmt_size; | ||
167 | offset = (info->label_block + 1); | ||
168 | } else { | ||
169 | /* unlabeled disk */ | ||
132 | printk("(nonl)"); | 170 | printk("(nonl)"); |
133 | offset = (info->label_block + 1); | 171 | size = i_size >> 9; |
134 | size = i_size >> 9; | 172 | offset = (info->label_block + 1); |
135 | } | 173 | } |
136 | put_partition(state, 1, offset*(blocksize >> 9), | 174 | put_partition(state, 1, offset*(blocksize >> 9), |
137 | size-offset*(blocksize >> 9)); | 175 | size-offset*(blocksize >> 9)); |
176 | } | ||
138 | } else if (info->format == DASD_FORMAT_CDL) { | 177 | } else if (info->format == DASD_FORMAT_CDL) { |
139 | /* | 178 | /* |
140 | * New style CDL formatted disk | 179 | * New style CDL formatted disk |
141 | */ | 180 | */ |
142 | unsigned int blk; | 181 | sector_t blk; |
143 | int counter; | 182 | int counter; |
144 | 183 | ||
145 | /* | 184 | /* |
@@ -166,7 +205,8 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev) | |||
166 | /* skip FMT4 / FMT5 / FMT7 labels */ | 205 | /* skip FMT4 / FMT5 / FMT7 labels */ |
167 | if (f1.DS1FMTID == _ascebc['4'] | 206 | if (f1.DS1FMTID == _ascebc['4'] |
168 | || f1.DS1FMTID == _ascebc['5'] | 207 | || f1.DS1FMTID == _ascebc['5'] |
169 | || f1.DS1FMTID == _ascebc['7']) { | 208 | || f1.DS1FMTID == _ascebc['7'] |
209 | || f1.DS1FMTID == _ascebc['9']) { | ||
170 | blk++; | 210 | blk++; |
171 | data = read_dev_sector(bdev, blk * | 211 | data = read_dev_sector(bdev, blk * |
172 | (blocksize/512), | 212 | (blocksize/512), |
@@ -174,8 +214,9 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev) | |||
174 | continue; | 214 | continue; |
175 | } | 215 | } |
176 | 216 | ||
177 | /* only FMT1 valid at this point */ | 217 | /* only FMT1 and 8 labels valid at this point */ |
178 | if (f1.DS1FMTID != _ascebc['1']) | 218 | if (f1.DS1FMTID != _ascebc['1'] && |
219 | f1.DS1FMTID != _ascebc['8']) | ||
179 | break; | 220 | break; |
180 | 221 | ||
181 | /* OK, we got valid partition data */ | 222 | /* OK, we got valid partition data */ |