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