source: MondoRescue/branches/stable/mindi-busybox/util-linux/fdisk_sun.c @ 1770

Last change on this file since 1770 was 1770, checked in by Bruno Cornec, 12 years ago
  • Better output for mindi-busybox revision
  • Remove dummy file created on NFS - report from Arnaud Tiger <arnaud.tiger_at_hp.com>
  • strace useful for debug
  • fix new versions for pb (2.0.0 for mindi and 1.7.2 for mindi-busybox)
  • fix build process for mindi-busybox + options used in that version (dd for label-partitions-as-necessary)
  • fix typo in label-partitions-as-necessary which doesn't seem to work
  • Update to busybox 1.7.2
  • perl is now required at restore time to support uuid swap partitions (and will be used for many other thigs

in the future for sure)

  • next mindi version will be 2.0.0 due to all the changes made in it (udev may break working distros)
  • small optimization in mindi on keyboard handling (one single find instead of multiple)
  • better interaction for USB device when launching mindi manually
  • attempt to automatically guess block disk size for ramdisk
  • fix typos in bkphw
  • Fix the remaining problem with UUID support for swap partitions
  • Updates mondoarchive man page for USB support
  • Adds preliminary Hardware support to mindi (Proliant SSSTK)
  • Tries to add udev support also for rhel4
  • Fix UUID support which was still broken.
  • Be conservative in test for the start-nfs script
  • Update config file for mindi-busybox for 1.7.2 migration
  • Try to run around a busybox bug (1.2.2 pb on inexistant links)
  • Add build content for mindi-busybox in pb
  • Remove distributions content for mindi-busybox
  • Fix a warning on inexistant raidtab
  • Solve problem on tmpfs in restore init (Problem of inexistant symlink and busybox)
  • Create MONDO_CACHE and use it everywhere + creation at start
  • Really never try to eject a USB device
  • Fix a issue with &> usage (replaced with 1> and 2>)
  • Adds magic file to depllist in order to have file working + ldd which helps for debugging issues
  • tty modes correct to avoid sh error messages
  • Use ext3 normally and not ext2 instead
  • USB device should be corrected after reading (take 1st part)
  • Adds a mount_USB_here function derived from mount_CDROM_here
  • usb detection place before /dev detection in device name at restore time
  • Fix when restoring from USB: media is asked in interactive mode
  • Adds USB support for mondorestore
  • mount_cdrom => mount_media
  • elilo.efi is now searched throughout /boot/efi and not in a fixed place as there is no standard
  • untar-and-softlink => untar (+ interface change)
  • suppress useless softlinks creation/removal in boot process
  • avoids udevd messages on groups
  • Increase # of disks to 99 as in mindi at restore time (should be a conf file parameter)
  • skip existing big file creation
  • seems to work correctly for USB mindi boot
  • Adds group and tty link to udev conf
  • Always load usb-torage (even 2.6) to initiate USB bus discovery
  • Better printing of messages
  • Attempt to fix a bug in supporting OpenSusE 10.3 kernel for initramfs (mindi may now use multiple regex for kernel initrd detection)
  • Links were not correctly done as non relative for modules in mindi
  • exclusion of modules denied now works
  • Also create modules in their ordinary place, so that classical modprobe works + copy modules.dep
  • Fix bugs for DENY_MODS handling
  • Add device /dev/console for udev
  • ide-generic should now really be excluded
  • Fix a bug in major number for tty
  • If udev then adds modprobe/insmod to rootfs
  • tty0 is also cretaed with udev
  • ide-generic put rather in DENY_MODS
  • udevd remove from deplist s handled in mindi directly
  • better default for mindi when using --usb
  • Handles dynamically linked busybox (in case we want to use it soon ;-)
  • Adds fixed devices to create for udev
  • ide-generic should not be part of the initrd when using libata v2
  • support a dynamically linked udev (case on Ubuntu 7.10 and Mandriva 2008.0 so should be quite generic) This will give incitation to move to dyn. linked binaries in the initrd which will help for other tasks (ia6 4)
  • Improvement in udev support (do not use cl options not available in busybox)
  • Udev in mindi
    • auto creation of the right links at boot time with udev-links.conf(from Mandriva 2008.0)
    • rework startup of udev as current makes kernel crash (from Mandriva 2008.0)
    • add support for 64 bits udev
  • Try to render MyInsmod? silent at boot time
  • Adds udev support (mandatory for newest distributions to avoid remapping of devices in a different way as on the original system)
  • We also need vaft format support for USB boot
  • Adds libusual support (Ubuntu 7.10 needs it for USB)
  • Improve Ubuntu/Debian? keyboard detection and support
  • pbinit adapted to new pb (0.8.10). Filtering of docs done in it
  • Suppress some mondo warnings and errors on USB again
  • Tries to fix lack of files in deb mindi package
  • Verify should now work for USB devices
  • More log/mesages improvement for USB support
  • - Supress g_erase_tmpdir_and_scratchdir
  • Improve some log messages for USB support
  • Try to improve install in mindi to avoid issues with isolinux.cfg not installed vene if in the pkg :-(
  • Improve mindi-busybox build
  • In conformity with pb 0.8.9
  • Add support for Ubuntu 7.10 in build process
  • Add USB Key button to Menu UI (CD streamer removed)
  • Attempt to fix error messages on tmp/scratch files at the end by removing those dir at the latest possible.
  • Fix a bug linked to the size of the -E param which could be used (Arnaud Tiger/René? Ribaud).
  • Integrate ~/.pbrc content into mondorescue.pb (required project-builder >= 0.8.7)
  • Put mondorescue in conformity with new pb filtering rules
  • Add USB support at restore time (no test done yet). New start-usb script PB varibale added where useful
  • Unmounting USB device before removal of temporary scratchdir
  • Stil refining USB copy back to mondo (one command was not executed)
  • No need to have the image subdor in the csratchdir when USB.
  • umount the USB partition before attempting to use it
  • Remove useless copy from mindi to mondo at end of USB handling

(risky merge, we are raising the limits of 2 diverging branches. The status of stable is not completely sure as such. Will need lots of tests, but it's not yet done :-()
(merge -r1692:1769 $SVN_M/branches/2.2.5)

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