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