Annotation of /trunk/mkinitrd-magellan/busybox/util-linux/fdisk_sun.c
Parent Directory | Revision Log
Revision 532 -
(hide annotations)
(download)
Sat Sep 1 22:45:15 2007 UTC (16 years, 9 months ago) by niro
File MIME type: text/plain
File size: 20684 byte(s)
Sat Sep 1 22:45:15 2007 UTC (16 years, 9 months ago) by niro
File MIME type: text/plain
File size: 20684 byte(s)
-import if magellan mkinitrd; it is a fork of redhats mkinitrd-5.0.8 with all magellan patches and features; deprecates magellan-src/mkinitrd
1 | niro | 532 | #if ENABLE_FEATURE_SUN_LABEL |
2 | |||
3 | #define SUN_LABEL_MAGIC 0xDABE | ||
4 | #define SUN_LABEL_MAGIC_SWAPPED 0xBEDA | ||
5 | #define SUN_SSWAP16(x) (sun_other_endian ? fdisk_swap16(x) : (uint16_t)(x)) | ||
6 | #define SUN_SSWAP32(x) (sun_other_endian ? fdisk_swap32(x) : (uint32_t)(x)) | ||
7 | |||
8 | /* Copied from linux/major.h */ | ||
9 | #define FLOPPY_MAJOR 2 | ||
10 | |||
11 | #define SCSI_IOCTL_GET_IDLUN 0x5382 | ||
12 | |||
13 | /* | ||
14 | * fdisksunlabel.c | ||
15 | * | ||
16 | * I think this is mostly, or entirely, due to | ||
17 | * Jakub Jelinek (jj@sunsite.mff.cuni.cz), July 1996 | ||
18 | * | ||
19 | * Merged with fdisk for other architectures, aeb, June 1998. | ||
20 | * | ||
21 | * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br> | ||
22 | * Internationalization | ||
23 | */ | ||
24 | |||
25 | |||
26 | static int sun_other_endian; | ||
27 | static int scsi_disk; | ||
28 | static int floppy; | ||
29 | |||
30 | #ifndef IDE0_MAJOR | ||
31 | #define IDE0_MAJOR 3 | ||
32 | #endif | ||
33 | #ifndef IDE1_MAJOR | ||
34 | #define IDE1_MAJOR 22 | ||
35 | #endif | ||
36 | |||
37 | static void | ||
38 | guess_device_type(void) | ||
39 | { | ||
40 | struct stat bootstat; | ||
41 | |||
42 | if (fstat(fd, &bootstat) < 0) { | ||
43 | scsi_disk = 0; | ||
44 | floppy = 0; | ||
45 | } else if (S_ISBLK(bootstat.st_mode) | ||
46 | && (major(bootstat.st_rdev) == IDE0_MAJOR || | ||
47 | major(bootstat.st_rdev) == IDE1_MAJOR)) { | ||
48 | scsi_disk = 0; | ||
49 | floppy = 0; | ||
50 | } else if (S_ISBLK(bootstat.st_mode) | ||
51 | && major(bootstat.st_rdev) == FLOPPY_MAJOR) { | ||
52 | scsi_disk = 0; | ||
53 | floppy = 1; | ||
54 | } else { | ||
55 | scsi_disk = 1; | ||
56 | floppy = 0; | ||
57 | } | ||
58 | } | ||
59 | |||
60 | static const struct systypes sun_sys_types[] = { | ||
61 | { "\x00" "Empty" }, /* 0 */ | ||
62 | { "\x01" "Boot" }, /* 1 */ | ||
63 | { "\x02" "SunOS root" }, /* 2 */ | ||
64 | { "\x03" "SunOS swap" }, /* SUNOS_SWAP */ | ||
65 | { "\x04" "SunOS usr" }, /* 4 */ | ||
66 | { "\x05" "Whole disk" }, /* SUN_WHOLE_DISK */ | ||
67 | { "\x06" "SunOS stand" }, /* 6 */ | ||
68 | { "\x07" "SunOS var" }, /* 7 */ | ||
69 | { "\x08" "SunOS home" }, /* 8 */ | ||
70 | { "\x82" "Linux swap" }, /* LINUX_SWAP */ | ||
71 | { "\x83" "Linux native" }, /* LINUX_NATIVE */ | ||
72 | { "\x8e" "Linux LVM" }, /* 0x8e */ | ||
73 | /* New (2.2.x) raid partition with autodetect using persistent superblock */ | ||
74 | { "\xfd" "Linux raid autodetect" }, /* 0xfd */ | ||
75 | { NULL } | ||
76 | }; | ||
77 | |||
78 | |||
79 | static void | ||
80 | set_sun_partition(int i, uint start, uint stop, int sysid) | ||
81 | { | ||
82 | sunlabel->infos[i].id = sysid; | ||
83 | sunlabel->partitions[i].start_cylinder = | ||
84 | SUN_SSWAP32(start / (heads * sectors)); | ||
85 | sunlabel->partitions[i].num_sectors = | ||
86 | SUN_SSWAP32(stop - start); | ||
87 | set_changed(i); | ||
88 | } | ||
89 | |||
90 | static int | ||
91 | check_sun_label(void) | ||
92 | { | ||
93 | unsigned short *ush; | ||
94 | int csum; | ||
95 | |||
96 | if (sunlabel->magic != SUN_LABEL_MAGIC | ||
97 | && sunlabel->magic != SUN_LABEL_MAGIC_SWAPPED) { | ||
98 | current_label_type = label_dos; | ||
99 | sun_other_endian = 0; | ||
100 | return 0; | ||
101 | } | ||
102 | sun_other_endian = (sunlabel->magic == SUN_LABEL_MAGIC_SWAPPED); | ||
103 | ush = ((unsigned short *) (sunlabel + 1)) - 1; | ||
104 | for (csum = 0; ush >= (unsigned short *)sunlabel;) csum ^= *ush--; | ||
105 | if (csum) { | ||
106 | fprintf(stderr,_("Detected sun disklabel with wrong checksum.\n" | ||
107 | "Probably you'll have to set all the values,\n" | ||
108 | "e.g. heads, sectors, cylinders and partitions\n" | ||
109 | "or force a fresh label (s command in main menu)\n")); | ||
110 | } else { | ||
111 | heads = SUN_SSWAP16(sunlabel->ntrks); | ||
112 | cylinders = SUN_SSWAP16(sunlabel->ncyl); | ||
113 | sectors = SUN_SSWAP16(sunlabel->nsect); | ||
114 | } | ||
115 | update_units(); | ||
116 | current_label_type = label_sun; | ||
117 | partitions = 8; | ||
118 | return 1; | ||
119 | } | ||
120 | |||
121 | static const struct sun_predefined_drives { | ||
122 | const char *vendor; | ||
123 | const char *model; | ||
124 | unsigned short sparecyl; | ||
125 | unsigned short ncyl; | ||
126 | unsigned short nacyl; | ||
127 | unsigned short pcylcount; | ||
128 | unsigned short ntrks; | ||
129 | unsigned short nsect; | ||
130 | unsigned short rspeed; | ||
131 | } sun_drives[] = { | ||
132 | { "Quantum","ProDrive 80S",1,832,2,834,6,34,3662}, | ||
133 | { "Quantum","ProDrive 105S",1,974,2,1019,6,35,3662}, | ||
134 | { "CDC","Wren IV 94171-344",3,1545,2,1549,9,46,3600}, | ||
135 | { "IBM","DPES-31080",0,4901,2,4903,4,108,5400}, | ||
136 | { "IBM","DORS-32160",0,1015,2,1017,67,62,5400}, | ||
137 | { "IBM","DNES-318350",0,11199,2,11474,10,320,7200}, | ||
138 | { "SEAGATE","ST34371",0,3880,2,3882,16,135,7228}, | ||
139 | { "","SUN0104",1,974,2,1019,6,35,3662}, | ||
140 | { "","SUN0207",4,1254,2,1272,9,36,3600}, | ||
141 | { "","SUN0327",3,1545,2,1549,9,46,3600}, | ||
142 | { "","SUN0340",0,1538,2,1544,6,72,4200}, | ||
143 | { "","SUN0424",2,1151,2,2500,9,80,4400}, | ||
144 | { "","SUN0535",0,1866,2,2500,7,80,5400}, | ||
145 | { "","SUN0669",5,1614,2,1632,15,54,3600}, | ||
146 | { "","SUN1.0G",5,1703,2,1931,15,80,3597}, | ||
147 | { "","SUN1.05",0,2036,2,2038,14,72,5400}, | ||
148 | { "","SUN1.3G",6,1965,2,3500,17,80,5400}, | ||
149 | { "","SUN2.1G",0,2733,2,3500,19,80,5400}, | ||
150 | { "IOMEGA","Jaz",0,1019,2,1021,64,32,5394}, | ||
151 | }; | ||
152 | |||
153 | static const struct sun_predefined_drives * | ||
154 | sun_autoconfigure_scsi(void) | ||
155 | { | ||
156 | const struct sun_predefined_drives *p = NULL; | ||
157 | |||
158 | #ifdef SCSI_IOCTL_GET_IDLUN | ||
159 | unsigned int id[2]; | ||
160 | char buffer[2048]; | ||
161 | char buffer2[2048]; | ||
162 | FILE *pfd; | ||
163 | char *vendor; | ||
164 | char *model; | ||
165 | char *q; | ||
166 | int i; | ||
167 | |||
168 | if (ioctl(fd, SCSI_IOCTL_GET_IDLUN, &id)) | ||
169 | return NULL; | ||
170 | |||
171 | sprintf(buffer, | ||
172 | "Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n", | ||
173 | /* This is very wrong (works only if you have one HBA), | ||
174 | but I haven't found a way how to get hostno | ||
175 | from the current kernel */ | ||
176 | 0, | ||
177 | (id[0]>>16) & 0xff, | ||
178 | id[0] & 0xff, | ||
179 | (id[0]>>8) & 0xff | ||
180 | ); | ||
181 | pfd = fopen("/proc/scsi/scsi", "r"); | ||
182 | if (!pfd) { | ||
183 | return NULL; | ||
184 | } | ||
185 | while (fgets(buffer2, 2048, pfd)) { | ||
186 | if (strcmp(buffer, buffer2)) | ||
187 | continue; | ||
188 | if (!fgets(buffer2, 2048, pfd)) | ||
189 | break; | ||
190 | q = strstr(buffer2, "Vendor: "); | ||
191 | if (!q) | ||
192 | break; | ||
193 | q += 8; | ||
194 | vendor = q; | ||
195 | q = strstr(q, " "); | ||
196 | *q++ = '\0'; /* truncate vendor name */ | ||
197 | q = strstr(q, "Model: "); | ||
198 | if (!q) | ||
199 | break; | ||
200 | *q = '\0'; | ||
201 | q += 7; | ||
202 | model = q; | ||
203 | q = strstr(q, " Rev: "); | ||
204 | if (!q) | ||
205 | break; | ||
206 | *q = '\0'; | ||
207 | for (i = 0; i < SIZE(sun_drives); i++) { | ||
208 | if (*sun_drives[i].vendor && strcasecmp(sun_drives[i].vendor, vendor)) | ||
209 | continue; | ||
210 | if (!strstr(model, sun_drives[i].model)) | ||
211 | continue; | ||
212 | printf(_("Autoconfigure found a %s%s%s\n"), | ||
213 | sun_drives[i].vendor, | ||
214 | (*sun_drives[i].vendor) ? " " : "", | ||
215 | sun_drives[i].model); | ||
216 | p = sun_drives + i; | ||
217 | break; | ||
218 | } | ||
219 | break; | ||
220 | } | ||
221 | fclose(pfd); | ||
222 | #endif | ||
223 | return p; | ||
224 | } | ||
225 | |||
226 | static void | ||
227 | create_sunlabel(void) | ||
228 | { | ||
229 | struct hd_geometry geometry; | ||
230 | unsigned int ndiv; | ||
231 | int i; | ||
232 | unsigned char c; | ||
233 | const struct sun_predefined_drives *p = NULL; | ||
234 | |||
235 | fprintf(stderr, | ||
236 | _("Building a new sun disklabel. Changes will remain in memory only,\n" | ||
237 | "until you decide to write them. After that, of course, the previous\n" | ||
238 | "content won't be recoverable.\n\n")); | ||
239 | sun_other_endian = BB_LITTLE_ENDIAN; | ||
240 | memset(MBRbuffer, 0, sizeof(MBRbuffer)); | ||
241 | sunlabel->magic = SUN_SSWAP16(SUN_LABEL_MAGIC); | ||
242 | if (!floppy) { | ||
243 | puts(_("Drive type\n" | ||
244 | " ? auto configure\n" | ||
245 | " 0 custom (with hardware detected defaults)")); | ||
246 | for (i = 0; i < SIZE(sun_drives); i++) { | ||
247 | printf(" %c %s%s%s\n", | ||
248 | i + 'a', sun_drives[i].vendor, | ||
249 | (*sun_drives[i].vendor) ? " " : "", | ||
250 | sun_drives[i].model); | ||
251 | } | ||
252 | while (1) { | ||
253 | c = read_nonempty(_("Select type (? for auto, 0 for custom): ")); | ||
254 | if (c >= 'a' && c < 'a' + SIZE(sun_drives)) { | ||
255 | p = sun_drives + c - 'a'; | ||
256 | break; | ||
257 | } else if (c >= 'A' && c < 'A' + SIZE(sun_drives)) { | ||
258 | p = sun_drives + c - 'A'; | ||
259 | break; | ||
260 | } else if (c == '0') { | ||
261 | break; | ||
262 | } else if (c == '?' && scsi_disk) { | ||
263 | p = sun_autoconfigure_scsi(); | ||
264 | if (!p) | ||
265 | printf(_("Autoconfigure failed.\n")); | ||
266 | else | ||
267 | break; | ||
268 | } | ||
269 | } | ||
270 | } | ||
271 | if (!p || floppy) { | ||
272 | if (!ioctl(fd, HDIO_GETGEO, &geometry)) { | ||
273 | heads = geometry.heads; | ||
274 | sectors = geometry.sectors; | ||
275 | cylinders = geometry.cylinders; | ||
276 | } else { | ||
277 | heads = 0; | ||
278 | sectors = 0; | ||
279 | cylinders = 0; | ||
280 | } | ||
281 | if (floppy) { | ||
282 | sunlabel->nacyl = 0; | ||
283 | sunlabel->pcylcount = SUN_SSWAP16(cylinders); | ||
284 | sunlabel->rspeed = SUN_SSWAP16(300); | ||
285 | sunlabel->ilfact = SUN_SSWAP16(1); | ||
286 | sunlabel->sparecyl = 0; | ||
287 | } else { | ||
288 | heads = read_int(1,heads,1024,0,_("Heads")); | ||
289 | sectors = read_int(1,sectors,1024,0,_("Sectors/track")); | ||
290 | if (cylinders) | ||
291 | cylinders = read_int(1,cylinders-2,65535,0,_("Cylinders")); | ||
292 | else | ||
293 | cylinders = read_int(1,0,65535,0,_("Cylinders")); | ||
294 | sunlabel->nacyl = SUN_SSWAP16(read_int(0,2,65535,0, _("Alternate cylinders"))); | ||
295 | sunlabel->pcylcount = SUN_SSWAP16(read_int(0,cylinders+SUN_SSWAP16(sunlabel->nacyl), 65535,0, _("Physical cylinders"))); | ||
296 | sunlabel->rspeed = SUN_SSWAP16(read_int(1,5400,100000,0, _("Rotation speed (rpm)"))); | ||
297 | sunlabel->ilfact = SUN_SSWAP16(read_int(1,1,32,0, _("Interleave factor"))); | ||
298 | sunlabel->sparecyl = SUN_SSWAP16(read_int(0,0,sectors,0, _("Extra sectors per cylinder"))); | ||
299 | } | ||
300 | } else { | ||
301 | sunlabel->sparecyl = SUN_SSWAP16(p->sparecyl); | ||
302 | sunlabel->ncyl = SUN_SSWAP16(p->ncyl); | ||
303 | sunlabel->nacyl = SUN_SSWAP16(p->nacyl); | ||
304 | sunlabel->pcylcount = SUN_SSWAP16(p->pcylcount); | ||
305 | sunlabel->ntrks = SUN_SSWAP16(p->ntrks); | ||
306 | sunlabel->nsect = SUN_SSWAP16(p->nsect); | ||
307 | sunlabel->rspeed = SUN_SSWAP16(p->rspeed); | ||
308 | sunlabel->ilfact = SUN_SSWAP16(1); | ||
309 | cylinders = p->ncyl; | ||
310 | heads = p->ntrks; | ||
311 | sectors = p->nsect; | ||
312 | puts(_("You may change all the disk params from the x menu")); | ||
313 | } | ||
314 | |||
315 | snprintf((char *)(sunlabel->info), sizeof(sunlabel->info), | ||
316 | "%s%s%s cyl %d alt %d hd %d sec %d", | ||
317 | p ? p->vendor : "", (p && *p->vendor) ? " " : "", | ||
318 | p ? p->model : (floppy ? _("3,5\" floppy") : _("Linux custom")), | ||
319 | cylinders, SUN_SSWAP16(sunlabel->nacyl), heads, sectors); | ||
320 | |||
321 | sunlabel->ntrks = SUN_SSWAP16(heads); | ||
322 | sunlabel->nsect = SUN_SSWAP16(sectors); | ||
323 | sunlabel->ncyl = SUN_SSWAP16(cylinders); | ||
324 | if (floppy) | ||
325 | set_sun_partition(0, 0, cylinders * heads * sectors, LINUX_NATIVE); | ||
326 | else { | ||
327 | if (cylinders * heads * sectors >= 150 * 2048) { | ||
328 | ndiv = cylinders - (50 * 2048 / (heads * sectors)); /* 50M swap */ | ||
329 | } else | ||
330 | ndiv = cylinders * 2 / 3; | ||
331 | set_sun_partition(0, 0, ndiv * heads * sectors, LINUX_NATIVE); | ||
332 | set_sun_partition(1, ndiv * heads * sectors, cylinders * heads * sectors, LINUX_SWAP); | ||
333 | sunlabel->infos[1].flags |= 0x01; /* Not mountable */ | ||
334 | } | ||
335 | set_sun_partition(2, 0, cylinders * heads * sectors, SUN_WHOLE_DISK); | ||
336 | { | ||
337 | unsigned short *ush = (unsigned short *)sunlabel; | ||
338 | unsigned short csum = 0; | ||
339 | while (ush < (unsigned short *)(&sunlabel->csum)) | ||
340 | csum ^= *ush++; | ||
341 | sunlabel->csum = csum; | ||
342 | } | ||
343 | |||
344 | set_all_unchanged(); | ||
345 | set_changed(0); | ||
346 | get_boot(create_empty_sun); | ||
347 | } | ||
348 | |||
349 | static void | ||
350 | toggle_sunflags(int i, unsigned char mask) | ||
351 | { | ||
352 | if (sunlabel->infos[i].flags & mask) | ||
353 | sunlabel->infos[i].flags &= ~mask; | ||
354 | else | ||
355 | sunlabel->infos[i].flags |= mask; | ||
356 | set_changed(i); | ||
357 | } | ||
358 | |||
359 | static void | ||
360 | fetch_sun(uint *starts, uint *lens, uint *start, uint *stop) | ||
361 | { | ||
362 | int i, continuous = 1; | ||
363 | |||
364 | *start = 0; | ||
365 | *stop = cylinders * heads * sectors; | ||
366 | for (i = 0; i < partitions; i++) { | ||
367 | if (sunlabel->partitions[i].num_sectors | ||
368 | && sunlabel->infos[i].id | ||
369 | && sunlabel->infos[i].id != SUN_WHOLE_DISK) { | ||
370 | starts[i] = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors; | ||
371 | lens[i] = SUN_SSWAP32(sunlabel->partitions[i].num_sectors); | ||
372 | if (continuous) { | ||
373 | if (starts[i] == *start) | ||
374 | *start += lens[i]; | ||
375 | else if (starts[i] + lens[i] >= *stop) | ||
376 | *stop = starts[i]; | ||
377 | else | ||
378 | continuous = 0; | ||
379 | /* There will be probably more gaps | ||
380 | than one, so lets check afterwards */ | ||
381 | } | ||
382 | } else { | ||
383 | starts[i] = 0; | ||
384 | lens[i] = 0; | ||
385 | } | ||
386 | } | ||
387 | } | ||
388 | |||
389 | static uint *verify_sun_starts; | ||
390 | |||
391 | static int | ||
392 | verify_sun_cmp(int *a, int *b) | ||
393 | { | ||
394 | if (*a == -1) return 1; | ||
395 | if (*b == -1) return -1; | ||
396 | if (verify_sun_starts[*a] > verify_sun_starts[*b]) return 1; | ||
397 | return -1; | ||
398 | } | ||
399 | |||
400 | static void | ||
401 | verify_sun(void) | ||
402 | { | ||
403 | uint starts[8], lens[8], start, stop; | ||
404 | int i,j,k,starto,endo; | ||
405 | int array[8]; | ||
406 | |||
407 | verify_sun_starts = starts; | ||
408 | fetch_sun(starts,lens,&start,&stop); | ||
409 | for (k = 0; k < 7; k++) { | ||
410 | for (i = 0; i < 8; i++) { | ||
411 | if (k && (lens[i] % (heads * sectors))) { | ||
412 | printf(_("Partition %d doesn't end on cylinder boundary\n"), i+1); | ||
413 | } | ||
414 | if (lens[i]) { | ||
415 | for (j = 0; j < i; j++) | ||
416 | if (lens[j]) { | ||
417 | if (starts[j] == starts[i]+lens[i]) { | ||
418 | starts[j] = starts[i]; lens[j] += lens[i]; | ||
419 | lens[i] = 0; | ||
420 | } else if (starts[i] == starts[j]+lens[j]){ | ||
421 | lens[j] += lens[i]; | ||
422 | lens[i] = 0; | ||
423 | } else if (!k) { | ||
424 | if (starts[i] < starts[j]+lens[j] | ||
425 | && starts[j] < starts[i]+lens[i]) { | ||
426 | starto = starts[i]; | ||
427 | if (starts[j] > starto) | ||
428 | starto = starts[j]; | ||
429 | endo = starts[i]+lens[i]; | ||
430 | if (starts[j]+lens[j] < endo) | ||
431 | endo = starts[j]+lens[j]; | ||
432 | printf(_("Partition %d overlaps with others in " | ||
433 | "sectors %d-%d\n"), i+1, starto, endo); | ||
434 | } | ||
435 | } | ||
436 | } | ||
437 | } | ||
438 | } | ||
439 | } | ||
440 | for (i = 0; i < 8; i++) { | ||
441 | if (lens[i]) | ||
442 | array[i] = i; | ||
443 | else | ||
444 | array[i] = -1; | ||
445 | } | ||
446 | qsort(array,SIZE(array),sizeof(array[0]), | ||
447 | (int (*)(const void *,const void *)) verify_sun_cmp); | ||
448 | if (array[0] == -1) { | ||
449 | printf(_("No partitions defined\n")); | ||
450 | return; | ||
451 | } | ||
452 | stop = cylinders * heads * sectors; | ||
453 | if (starts[array[0]]) | ||
454 | printf(_("Unused gap - sectors 0-%d\n"),starts[array[0]]); | ||
455 | for (i = 0; i < 7 && array[i+1] != -1; i++) { | ||
456 | printf(_("Unused gap - sectors %d-%d\n"),starts[array[i]]+lens[array[i]],starts[array[i+1]]); | ||
457 | } | ||
458 | start = starts[array[i]] + lens[array[i]]; | ||
459 | if (start < stop) | ||
460 | printf(_("Unused gap - sectors %d-%d\n"),start,stop); | ||
461 | } | ||
462 | |||
463 | static void | ||
464 | add_sun_partition(int n, int sys) | ||
465 | { | ||
466 | uint start, stop, stop2; | ||
467 | uint starts[8], lens[8]; | ||
468 | int whole_disk = 0; | ||
469 | |||
470 | char mesg[256]; | ||
471 | int i, first, last; | ||
472 | |||
473 | if (sunlabel->partitions[n].num_sectors && sunlabel->infos[n].id) { | ||
474 | printf(_("Partition %d is already defined. Delete " | ||
475 | "it before re-adding it.\n"), n + 1); | ||
476 | return; | ||
477 | } | ||
478 | |||
479 | fetch_sun(starts,lens,&start,&stop); | ||
480 | if (stop <= start) { | ||
481 | if (n == 2) | ||
482 | whole_disk = 1; | ||
483 | else { | ||
484 | printf(_("Other partitions already cover the whole disk.\nDelete " | ||
485 | "some/shrink them before retry.\n")); | ||
486 | return; | ||
487 | } | ||
488 | } | ||
489 | snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR)); | ||
490 | while (1) { | ||
491 | if (whole_disk) | ||
492 | first = read_int(0, 0, 0, 0, mesg); | ||
493 | else | ||
494 | first = read_int(scround(start), scround(stop)+1, | ||
495 | scround(stop), 0, mesg); | ||
496 | if (display_in_cyl_units) | ||
497 | first *= units_per_sector; | ||
498 | else | ||
499 | /* Starting sector has to be properly aligned */ | ||
500 | first = (first + heads * sectors - 1) / (heads * sectors); | ||
501 | if (n == 2 && first != 0) | ||
502 | printf("\ | ||
503 | It is highly recommended that the third partition covers the whole disk\n\ | ||
504 | and is of type `Whole disk'\n"); | ||
505 | /* ewt asks to add: "don't start a partition at cyl 0" | ||
506 | However, edmundo@rano.demon.co.uk writes: | ||
507 | "In addition to having a Sun partition table, to be able to | ||
508 | boot from the disc, the first partition, /dev/sdX1, must | ||
509 | start at cylinder 0. This means that /dev/sdX1 contains | ||
510 | the partition table and the boot block, as these are the | ||
511 | first two sectors of the disc. Therefore you must be | ||
512 | careful what you use /dev/sdX1 for. In particular, you must | ||
513 | not use a partition starting at cylinder 0 for Linux swap, | ||
514 | as that would overwrite the partition table and the boot | ||
515 | block. You may, however, use such a partition for a UFS | ||
516 | or EXT2 file system, as these file systems leave the first | ||
517 | 1024 bytes undisturbed. */ | ||
518 | /* On the other hand, one should not use partitions | ||
519 | starting at block 0 in an md, or the label will | ||
520 | be trashed. */ | ||
521 | for (i = 0; i < partitions; i++) | ||
522 | if (lens[i] && starts[i] <= first && starts[i] + lens[i] > first) | ||
523 | break; | ||
524 | if (i < partitions && !whole_disk) { | ||
525 | if (n == 2 && !first) { | ||
526 | whole_disk = 1; | ||
527 | break; | ||
528 | } | ||
529 | printf(_("Sector %d is already allocated\n"), first); | ||
530 | } else | ||
531 | break; | ||
532 | } | ||
533 | stop = cylinders * heads * sectors; | ||
534 | stop2 = stop; | ||
535 | for (i = 0; i < partitions; i++) { | ||
536 | if (starts[i] > first && starts[i] < stop) | ||
537 | stop = starts[i]; | ||
538 | } | ||
539 | snprintf(mesg, sizeof(mesg), | ||
540 | _("Last %s or +size or +sizeM or +sizeK"), | ||
541 | str_units(SINGULAR)); | ||
542 | if (whole_disk) | ||
543 | last = read_int(scround(stop2), scround(stop2), scround(stop2), | ||
544 | 0, mesg); | ||
545 | else if (n == 2 && !first) | ||
546 | last = read_int(scround(first), scround(stop2), scround(stop2), | ||
547 | scround(first), mesg); | ||
548 | else | ||
549 | last = read_int(scround(first), scround(stop), scround(stop), | ||
550 | scround(first), mesg); | ||
551 | if (display_in_cyl_units) | ||
552 | last *= units_per_sector; | ||
553 | if (n == 2 && !first) { | ||
554 | if (last >= stop2) { | ||
555 | whole_disk = 1; | ||
556 | last = stop2; | ||
557 | } else if (last > stop) { | ||
558 | printf(_("You haven't covered the whole disk with " | ||
559 | "the 3rd partition, but your value\n" | ||
560 | "%d %s covers some other partition. " | ||
561 | "Your entry has been changed\n" | ||
562 | "to %d %s\n"), | ||
563 | scround(last), str_units(SINGULAR), | ||
564 | scround(stop), str_units(SINGULAR)); | ||
565 | last = stop; | ||
566 | } | ||
567 | } else if (!whole_disk && last > stop) | ||
568 | last = stop; | ||
569 | |||
570 | if (whole_disk) | ||
571 | sys = SUN_WHOLE_DISK; | ||
572 | set_sun_partition(n, first, last, sys); | ||
573 | } | ||
574 | |||
575 | static void | ||
576 | sun_delete_partition(int i) | ||
577 | { | ||
578 | unsigned int nsec; | ||
579 | |||
580 | if (i == 2 | ||
581 | && sunlabel->infos[i].id == SUN_WHOLE_DISK | ||
582 | && !sunlabel->partitions[i].start_cylinder | ||
583 | && (nsec = SUN_SSWAP32(sunlabel->partitions[i].num_sectors)) == heads * sectors * cylinders) | ||
584 | printf(_("If you want to maintain SunOS/Solaris compatibility, " | ||
585 | "consider leaving this\n" | ||
586 | "partition as Whole disk (5), starting at 0, with %u " | ||
587 | "sectors\n"), nsec); | ||
588 | sunlabel->infos[i].id = 0; | ||
589 | sunlabel->partitions[i].num_sectors = 0; | ||
590 | } | ||
591 | |||
592 | static void | ||
593 | sun_change_sysid(int i, int sys) | ||
594 | { | ||
595 | if (sys == LINUX_SWAP && !sunlabel->partitions[i].start_cylinder) { | ||
596 | read_maybe_empty( | ||
597 | _("It is highly recommended that the partition at offset 0\n" | ||
598 | "is UFS, EXT2FS filesystem or SunOS swap. Putting Linux swap\n" | ||
599 | "there may destroy your partition table and bootblock.\n" | ||
600 | "Type YES if you're very sure you would like that partition\n" | ||
601 | "tagged with 82 (Linux swap): ")); | ||
602 | if (strcmp (line_ptr, _("YES\n"))) | ||
603 | return; | ||
604 | } | ||
605 | switch (sys) { | ||
606 | case SUNOS_SWAP: | ||
607 | case LINUX_SWAP: | ||
608 | /* swaps are not mountable by default */ | ||
609 | sunlabel->infos[i].flags |= 0x01; | ||
610 | break; | ||
611 | default: | ||
612 | /* assume other types are mountable; | ||
613 | user can change it anyway */ | ||
614 | sunlabel->infos[i].flags &= ~0x01; | ||
615 | break; | ||
616 | } | ||
617 | sunlabel->infos[i].id = sys; | ||
618 | } | ||
619 | |||
620 | static void | ||
621 | sun_list_table(int xtra) | ||
622 | { | ||
623 | int i, w; | ||
624 | |||
625 | w = strlen(disk_device); | ||
626 | if (xtra) | ||
627 | printf( | ||
628 | _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d rpm\n" | ||
629 | "%d cylinders, %d alternate cylinders, %d physical cylinders\n" | ||
630 | "%d extra sects/cyl, interleave %d:1\n" | ||
631 | "%s\n" | ||
632 | "Units = %s of %d * 512 bytes\n\n"), | ||
633 | disk_device, heads, sectors, SUN_SSWAP16(sunlabel->rspeed), | ||
634 | cylinders, SUN_SSWAP16(sunlabel->nacyl), | ||
635 | SUN_SSWAP16(sunlabel->pcylcount), | ||
636 | SUN_SSWAP16(sunlabel->sparecyl), | ||
637 | SUN_SSWAP16(sunlabel->ilfact), | ||
638 | (char *)sunlabel, | ||
639 | str_units(PLURAL), units_per_sector); | ||
640 | else | ||
641 | printf( | ||
642 | _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d cylinders\n" | ||
643 | "Units = %s of %d * 512 bytes\n\n"), | ||
644 | disk_device, heads, sectors, cylinders, | ||
645 | str_units(PLURAL), units_per_sector); | ||
646 | |||
647 | printf(_("%*s Flag Start End Blocks Id System\n"), | ||
648 | w + 1, _("Device")); | ||
649 | for (i = 0 ; i < partitions; i++) { | ||
650 | if (sunlabel->partitions[i].num_sectors) { | ||
651 | uint32_t start = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors; | ||
652 | uint32_t len = SUN_SSWAP32(sunlabel->partitions[i].num_sectors); | ||
653 | printf("%s %c%c %9ld %9ld %9ld%c %2x %s\n", | ||
654 | partname(disk_device, i+1, w), /* device */ | ||
655 | (sunlabel->infos[i].flags & 0x01) ? 'u' : ' ', /* flags */ | ||
656 | (sunlabel->infos[i].flags & 0x10) ? 'r' : ' ', | ||
657 | (long) scround(start), /* start */ | ||
658 | (long) scround(start+len), /* end */ | ||
659 | (long) len / 2, len & 1 ? '+' : ' ', /* odd flag on end */ | ||
660 | sunlabel->infos[i].id, /* type id */ | ||
661 | partition_type(sunlabel->infos[i].id)); /* type name */ | ||
662 | } | ||
663 | } | ||
664 | } | ||
665 | |||
666 | #if ENABLE_FEATURE_FDISK_ADVANCED | ||
667 | |||
668 | static void | ||
669 | sun_set_alt_cyl(void) | ||
670 | { | ||
671 | sunlabel->nacyl = | ||
672 | SUN_SSWAP16(read_int(0,SUN_SSWAP16(sunlabel->nacyl), 65535, 0, | ||
673 | _("Number of alternate cylinders"))); | ||
674 | } | ||
675 | |||
676 | static void | ||
677 | sun_set_ncyl(int cyl) | ||
678 | { | ||
679 | sunlabel->ncyl = SUN_SSWAP16(cyl); | ||
680 | } | ||
681 | |||
682 | static void | ||
683 | sun_set_xcyl(void) | ||
684 | { | ||
685 | sunlabel->sparecyl = | ||
686 | SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->sparecyl), sectors, 0, | ||
687 | _("Extra sectors per cylinder"))); | ||
688 | } | ||
689 | |||
690 | static void | ||
691 | sun_set_ilfact(void) | ||
692 | { | ||
693 | sunlabel->ilfact = | ||
694 | SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->ilfact), 32, 0, | ||
695 | _("Interleave factor"))); | ||
696 | } | ||
697 | |||
698 | static void | ||
699 | sun_set_rspeed(void) | ||
700 | { | ||
701 | sunlabel->rspeed = | ||
702 | SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->rspeed), 100000, 0, | ||
703 | _("Rotation speed (rpm)"))); | ||
704 | } | ||
705 | |||
706 | static void | ||
707 | sun_set_pcylcount(void) | ||
708 | { | ||
709 | sunlabel->pcylcount = | ||
710 | SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->pcylcount), 65535, 0, | ||
711 | _("Number of physical cylinders"))); | ||
712 | } | ||
713 | #endif /* FEATURE_FDISK_ADVANCED */ | ||
714 | |||
715 | static void | ||
716 | sun_write_table(void) | ||
717 | { | ||
718 | unsigned short *ush = (unsigned short *)sunlabel; | ||
719 | unsigned short csum = 0; | ||
720 | |||
721 | while (ush < (unsigned short *)(&sunlabel->csum)) | ||
722 | csum ^= *ush++; | ||
723 | sunlabel->csum = csum; | ||
724 | if (lseek(fd, 0, SEEK_SET) < 0) | ||
725 | fdisk_fatal(unable_to_seek); | ||
726 | if (write(fd, sunlabel, SECTOR_SIZE) != SECTOR_SIZE) | ||
727 | fdisk_fatal(unable_to_write); | ||
728 | } | ||
729 | #endif /* SUN_LABEL */ |