From: David Miller <[EMAIL PROTECTED]>
Date: Fri, 29 Jun 2007 15:50:21 -0700 (PDT)

> 
> While working on Sun LDOMs I had opportunity to spot many errors in
> how fdisk creates Sun disk labels compared to the reality of what
> Solaris and other systems expect.
> 
> The worst offense was not setting the version, sane, and num_partition
> fields of the disk label.
> 
> That, as well as several other issues, are fixed in the patch below.
> 
> [FDISK]: Many significant improvements and fixes to Sun label handling.
> 
> 1) Properly describe the exact layout and fields of the sun disk
>    label.  Several fields were incorrectly mentioned and others
>    wrongly sized.
> 
> 2) Properly set the version, sane, and num_partitions fields.
> 
>    Because we weren't doing this, programs such as Solaris's format
>    and the Solaris kernel itself refused to recognize our disk labels
>    as valid.
> 
> 3) Move SSWAP*() macros into fdisksunlabel.c as there is no reason
>    for them to be exposed to the rest of fdisk.
> 
> 4) Kill the sun_predefined_drives array hack and assosciated code.
> 
>    Instead size the disk and figure out the geometry properly just
>    like the SGI and MSDOS partition handling do, by means of the
>    HD_GETGEO ioctl() and disksize().
> 
> 5) If the disk label read is found to not have the proper values
>    set in version, sane, or num_partitions, fix them, recompute the
>    label checksum, dirty the disk label, and let the user know what
>    we did and that the fixed values will be written out if they 'w'.
> 
>    This gives users an easy way to fix up disk labels created by
>    disk labelling programs which had this bug.
> 
> 6) Create a sun_sys_getid() function so that fdisk.c does not need
>    to reference the sun disk label details directly, just like the
>    SGI code does.
> 
> Signed-off-by: David S. Miller <[EMAIL PROTECTED]>

I just noticed there were some recent mildly conflicting changesets
in this area, so I've respun my patch against the current tree,
same changelog and singoff, thanks!

diff --git a/fdisk/fdisk.c b/fdisk/fdisk.c
index c4ab6d5..292b7a8 100644
--- a/fdisk/fdisk.c
+++ b/fdisk/fdisk.c
@@ -470,7 +470,7 @@ xmenu(void) {
 static int
 get_sysid(int i) {
        return (
-               sun_label ? sunlabel->infos[i].id :
+               sun_label ? sun_get_sysid(i) :
                sgi_label ? sgi_get_sysid(i) :
                ptes[i].part_table->sys_ind);
 }
@@ -1178,7 +1178,7 @@ get_partition(int warn, int max) {
                if ((!sun_label && !sgi_label && !pe->part_table->sys_ind)
                    || (sun_label &&
                        (!sunlabel->partitions[i].num_sectors ||
-                        !sunlabel->infos[i].id))
+                        !sunlabel->part_tags[i].tag))
                    || (sgi_label && (!sgi_get_num_sectors(i)))
                   )
                        fprintf(stderr,
@@ -1400,7 +1400,7 @@ change_sysid(void) {
                }
 
                 if (sys < 256) {
-                       if (sun_label && i == 2 && sys != WHOLE_DISK)
+                       if (sun_label && i == 2 && sys != SUN_TAG_BACKUP)
                                printf(_("Consider leaving partition 3 "
                                       "as Whole disk (5),\n"
                                       "as SunOS/Solaris expects it and "
@@ -2614,7 +2614,7 @@ main(int argc, char **argv) {
                                toggle_active(get_partition(1, partitions));
                        else if (sun_label)
                                toggle_sunflags(get_partition(1, partitions),
-                                               0x01);
+                                               SUN_FLAG_UNMNT);
                        else if (sgi_label)
                                sgi_set_bootpartition(
                                        get_partition(1, partitions));
@@ -2638,7 +2638,7 @@ main(int argc, char **argv) {
                                toggle_dos_compatibility_flag();
                        else if (sun_label)
                                toggle_sunflags(get_partition(1, partitions),
-                                               0x10);
+                                               SUN_FLAG_RONLY);
                        else if (sgi_label)
                                sgi_set_swappartition(
                                                get_partition(1, partitions));
diff --git a/fdisk/fdisksunlabel.c b/fdisk/fdisksunlabel.c
index a1994e2..248989c 100644
--- a/fdisk/fdisksunlabel.c
+++ b/fdisk/fdisksunlabel.c
@@ -36,25 +36,23 @@ static int     other_endian = 0;
 static int     scsi_disk = 0;
 static int     floppy = 0;
 
-#define LINUX_SWAP      0x82
-#define LINUX_NATIVE    0x83
-
 struct systypes sun_sys_types[] = {
-       {0, N_("Empty")},
-       {1, N_("Boot")},
-       {2, N_("SunOS root")},
-       {SUNOS_SWAP, N_("SunOS swap")},
-       {4, N_("SunOS usr")},
-       {WHOLE_DISK, N_("Whole disk")},
-       {6, N_("SunOS stand")},
-       {7, N_("SunOS var")},
-       {8, N_("SunOS home")},
-       {LINUX_SWAP, N_("Linux swap")},
-       {LINUX_NATIVE, N_("Linux native")},
-       {0x8e, N_("Linux LVM")},
-       {0xfd, N_("Linux raid autodetect")},/* New (2.2.x) raid partition
-                                              with autodetect using
-                                              persistent superblock */
+       {SUN_TAG_UNASSIGNED, N_("Unassigned")},
+       {SUN_TAG_BOOT, N_("Boot")},
+       {SUN_TAG_ROOT, N_("SunOS root")},
+       {SUN_TAG_SWAP, N_("SunOS swap")},
+       {SUN_TAG_USR, N_("SunOS usr")},
+       {SUN_TAG_BACKUP, N_("Whole disk")},
+       {SUN_TAG_STAND, N_("SunOS stand")},
+       {SUN_TAG_VAR, N_("SunOS var")},
+       {SUN_TAG_HOME, N_("SunOS home")},
+       {SUN_TAG_ALTSCTR, N_("SunOS alt sectors")},
+       {SUN_TAG_CACHE, N_("SunOS cachefs")},
+       {SUN_TAG_RESERVED, N_("SunOS reserved")},
+       {SUN_TAG_LINUX_SWAP, N_("Linux swap")},
+       {SUN_TAG_LINUX_NATIVE, N_("Linux native")},
+       {SUN_TAG_LINUX_LVM, N_("Linux LVM")},
+       {SUN_TAG_LINUX_RAID, N_("Linux raid autodetect")},
        { 0, NULL }
 };
 
@@ -65,10 +63,10 @@ static inline __u32 __swap32(__u32 x) {
         return (((__u32)(x) & 0xFF) << 24) | (((__u32)(x) & 0xFF00) << 8) | 
(((__u32)(x) & 0xFF0000) >> 8) | (((__u32)(x) & 0xFF000000) >> 24);
 }
 
-int
-get_num_sectors(struct sun_partition p) {
-       return SSWAP32(p.num_sectors);
-}
+#define SSWAP16(x) (other_endian ? __swap16(x) \
+                                : (__u16)(x))
+#define SSWAP32(x) (other_endian ? __swap32(x) \
+                                : (__u32)(x))
 
 #ifndef IDE0_MAJOR
 #define IDE0_MAJOR 3
@@ -76,7 +74,8 @@ get_num_sectors(struct sun_partition p) {
 #ifndef IDE1_MAJOR
 #define IDE1_MAJOR 22
 #endif
-void guess_device_type(int fd) {
+void guess_device_type(int fd)
+{
        struct stat bootstat;
 
        if (fstat (fd, &bootstat) < 0) {
@@ -97,9 +96,10 @@ void guess_device_type(int fd) {
        }
 }
 
-static void
-set_sun_partition(int i, unsigned int start, unsigned int stop, int sysid) {
-       sunlabel->infos[i].id = sysid;
+static void set_sun_partition(int i, __u32 start, __u32 stop, __u16 sysid)
+{
+       sunlabel->part_tags[i].tag = SSWAP16(sysid);
+       sunlabel->part_tags[i].flag = SSWAP16(0);
        sunlabel->partitions[i].start_cylinder =
                SSWAP32(start / (heads * sectors));
        sunlabel->partitions[i].num_sectors =
@@ -107,15 +107,15 @@ set_sun_partition(int i, unsigned int start, unsigned int 
stop, int sysid) {
        set_changed(i);
 }
 
-void
-sun_nolabel(void) {
+void sun_nolabel(void)
+{
        sun_label = 0;
        sunlabel->magic = 0;
        partitions = 4;
 }
 
-int
-check_sun_label(void) {
+int check_sun_label(void)
+{
        unsigned short *ush;
        int csum;
 
@@ -126,133 +126,67 @@ check_sun_label(void) {
                return 0;
        }
        other_endian = (sunlabel->magic == SUN_LABEL_MAGIC_SWAPPED);
+
        ush = ((unsigned short *) (sunlabel + 1)) - 1;
-       for (csum = 0; ush >= (unsigned short *)sunlabel;) csum ^= *ush--;
+       for (csum = 0; ush >= (unsigned short *)sunlabel;)
+               csum ^= *ush--;
+
        if (csum) {
                fprintf(stderr,_("Detected sun disklabel with wrong checksum.\n"
                                "Probably you'll have to set all the values,\n"
                                "e.g. heads, sectors, cylinders and 
partitions\n"
                                "or force a fresh label (s command in main 
menu)\n"));
        } else {
-               heads = SSWAP16(sunlabel->ntrks);
+               int need_fixing = 0;
+
+               heads = SSWAP16(sunlabel->nhead);
                cylinders = SSWAP16(sunlabel->ncyl);
                sectors = SSWAP16(sunlabel->nsect);
+
+               if (sunlabel->version != SSWAP32(SUN_LABEL_VERSION)) {
+                       fprintf(stderr,_("Detected sun disklabel with wrong 
version [0x%08x].\n"),
+                               sunlabel->version);
+                       need_fixing = 1;
+               }
+               if (sunlabel->sanity != SSWAP32(SUN_LABEL_SANE)) {
+                       fprintf(stderr,_("Detected sun disklabel with wrong 
sanity [0x%08x].\n"),
+                               sunlabel->sanity);
+                       need_fixing = 1;
+               }
+               if (sunlabel->num_partitions != SSWAP16(SUN_NUM_PARTITIONS)) {
+                       fprintf(stderr,_("Detected sun disklabel with wrong 
num_partitions [%u].\n"),
+                               sunlabel->num_partitions);
+                       need_fixing = 1;
+               }
+               if (need_fixing) {
+                       fprintf(stderr, _("Warning: Wrong values need to be "
+                                         "fixed up and will be corrected "
+                                         "by w(rite)\n"));
+                       sunlabel->version = SSWAP32(SUN_LABEL_VERSION);
+                       sunlabel->sanity = SSWAP32(SUN_LABEL_SANE);
+                       sunlabel->num_partitions = SSWAP16(SUN_NUM_PARTITIONS);
+
+                       ush = (unsigned short *)sunlabel;
+                       csum = 0;
+                       while(ush < (unsigned short *)(&sunlabel->cksum))
+                               csum ^= *ush++;
+                       sunlabel->cksum = csum;
+
+                       set_changed(0);
+               }
        }
        update_units();
        sun_label = 1;
-       partitions = 8;
+       partitions = SUN_NUM_PARTITIONS;
        return 1;
 }
 
-struct sun_predefined_drives {
-       char *vendor;
-       char *model;
-       unsigned short sparecyl;
-       unsigned short ncyl;
-       unsigned short nacyl;
-       unsigned short pcylcount;
-       unsigned short ntrks;
-       unsigned short nsect;
-       unsigned short rspeed;
-} sun_drives[] = {
-{"Quantum","ProDrive 80S",1,832,2,834,6,34,3662},
-{"Quantum","ProDrive 105S",1,974,2,1019,6,35,3662},
-{"CDC","Wren IV 94171-344",3,1545,2,1549,9,46,3600},
-{"IBM","DPES-31080",0,4901,2,4903,4,108,5400},
-{"IBM","DORS-32160",0,1015,2,1017,67,62,5400},
-{"IBM","DNES-318350",0,11199,2,11474,10,320,7200},
-{"SEAGATE","ST34371",0,3880,2,3882,16,135,7228},
-{"","SUN0104",1,974,2,1019,6,35,3662},
-{"","SUN0207",4,1254,2,1272,9,36,3600},
-{"","SUN0327",3,1545,2,1549,9,46,3600},
-{"","SUN0340",0,1538,2,1544,6,72,4200},
-{"","SUN0424",2,1151,2,2500,9,80,4400},
-{"","SUN0535",0,1866,2,2500,7,80,5400},
-{"","SUN0669",5,1614,2,1632,15,54,3600},
-{"","SUN1.0G",5,1703,2,1931,15,80,3597},
-{"","SUN1.05",0,2036,2,2038,14,72,5400},
-{"","SUN1.3G",6,1965,2,3500,17,80,5400},
-{"","SUN2.1G",0,2733,2,3500,19,80,5400},
-{"IOMEGA","Jaz",0,1019,2,1021,64,32,5394},
-};
-
-static struct sun_predefined_drives *
-sun_autoconfigure_scsi(void) {
-    struct sun_predefined_drives *p = NULL;
-
-#ifdef SCSI_IOCTL_GET_IDLUN
-    unsigned int id[2];
-    char buffer[2048];
-    char buffer2[2048];
-    FILE *pfd;
-    char *vendor;
-    char *model;
-    char *q;
-    int i;
-
-    if (!ioctl(fd, SCSI_IOCTL_GET_IDLUN, &id)) {
-        sprintf(buffer,
-            "Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n",
-#if 0                    
-            ((id[0]>>24)&0xff)-/*PROC_SCSI_SCSI+PROC_SCSI_FILE*/33,
-#else
-            /* This is very wrong (works only if you have one HBA),
-               but I haven't found a way how to get hostno
-               from the current kernel */
-            0,
-#endif                        
-            (id[0]>>16)&0xff,
-            id[0]&0xff,
-            (id[0]>>8)&0xff);
-        pfd = fopen("/proc/scsi/scsi","r");
-        if (pfd) {
-            while (fgets(buffer2,2048,pfd)) {
-               if (!strcmp(buffer, buffer2)) {
-                    if (fgets(buffer2,2048,pfd)) {
-                        q = strstr(buffer2,"Vendor: ");
-                        if (q) {
-                            q += 8;
-                            vendor = q;
-                           q = strstr(q," ");
-                           *q++ = 0;   /* truncate vendor name */
-                            q = strstr(q,"Model: ");
-                            if (q) {
-                                *q = 0;
-                                q += 7;
-                                model = q;
-                                q = strstr(q," Rev: ");
-                                if (q) {
-                                    *q = 0;
-                                    for (i = 0; i < SIZE(sun_drives); i++) {
-                                        if (*sun_drives[i].vendor && 
strcasecmp(sun_drives[i].vendor, vendor))
-                                            continue;
-                                        if (!strstr(model, 
sun_drives[i].model))
-                                            continue;
-                                        printf(_("Autoconfigure found a 
%s%s%s\n"),sun_drives[i].vendor,(*sun_drives[i].vendor) ? " " : 
"",sun_drives[i].model);
-                                        p = sun_drives + i;
-                                        break;
-                                    }
-                                }
-                            }
-                        }
-                    }
-                    break;
-                }
-            }
-            fclose(pfd);
-        }
-    }
-#endif
-    return p;
-}
-
 void create_sunlabel(void)
 {
        struct hd_geometry geometry;
+       unsigned long long llsectors, llcyls;
        unsigned int ndiv;
-       int i;
-       unsigned char c;
-       struct sun_predefined_drives *p = NULL;
+       int res, sec_fac;
 
        fprintf(stderr,
        _("Building a new sun disklabel. Changes will remain in memory only,\n"
@@ -265,116 +199,70 @@ void create_sunlabel(void)
 #endif
        memset(MBRbuffer, 0, sizeof(MBRbuffer));
        sunlabel->magic = SSWAP16(SUN_LABEL_MAGIC);
-       if (!floppy) {
-           puts(_("Drive type\n"
-                "   ?   auto configure\n"
-                "   0   custom (with hardware detected defaults)"));
-           for (i = 0; i < SIZE(sun_drives); i++) {
-               printf("   %c   %s%s%s\n",
-                      i + 'a', sun_drives[i].vendor,
-                      (*sun_drives[i].vendor) ? " " : "",
-                      sun_drives[i].model);
-           }
-           for (;;) {
-               c = read_char(_("Select type (? for auto, 0 for custom): "));
-               if (c >= 'a' && c < 'a' + SIZE(sun_drives)) {
-                   p = sun_drives + c - 'a';
-                   break;
-               } else if (c >= 'A' && c < 'A' + SIZE(sun_drives)) {
-                   p = sun_drives + c - 'A';
-                   break;
-               } else if (c == '0') {
-                   break;
-               } else if (c == '?' && scsi_disk) {
-                   p = sun_autoconfigure_scsi();
-                   if (!p)
-                       printf(_("Autoconfigure failed.\n"));
-                   else
-                       break;
-               }
-           }
-       }
-       if (!p || floppy) {
-           if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
+       sunlabel->sanity = SSWAP32(SUN_LABEL_SANE);
+       sunlabel->version = SSWAP32(SUN_LABEL_VERSION);
+       sunlabel->num_partitions = SSWAP16(SUN_NUM_PARTITIONS);
+
+       res = disksize(fd, &llsectors);
+       sec_fac = sector_size / 512;
+
+       if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
                heads = geometry.heads;
                sectors = geometry.sectors;
-               cylinders = geometry.cylinders;
-           } else {
-               heads = 0;
-               sectors = 0;
-               cylinders = 0;
-           }
-           if (floppy) {
-               sunlabel->nacyl = 0;
-               sunlabel->pcylcount = SSWAP16(cylinders);
-               sunlabel->rspeed = SSWAP16(300);
-               sunlabel->ilfact = SSWAP16(1);
-               sunlabel->sparecyl = 0;
-           } else {
-               heads = read_int(1,heads,1024,0,_("Heads"));
-               sectors = read_int(1,sectors,1024,0,_("Sectors/track"));
-               if (cylinders)
-                   cylinders = read_int(1,cylinders-2,65535,0,_("Cylinders"));
-               else
-                   cylinders = read_int(1,0,65535,0,_("Cylinders"));
-               sunlabel->nacyl =
-                       SSWAP16(read_int(0,2,65535,0,
-                                        _("Alternate cylinders")));
-               sunlabel->pcylcount =
-                       SSWAP16(read_int(0,cylinders+SSWAP16(sunlabel->nacyl),
-                                        65535,0,_("Physical cylinders")));
-               sunlabel->rspeed =
-                       SSWAP16(read_int(1,5400,100000,0,
-                                        _("Rotation speed (rpm)")));
-               sunlabel->ilfact =
-                       SSWAP16(read_int(1,1,32,0,_("Interleave factor")));
-               sunlabel->sparecyl =
-                       SSWAP16(read_int(0,0,sectors,0,
-                                        _("Extra sectors per cylinder")));
-           }
+               if (res == 0) {
+                       llcyls = llsectors / (heads * sectors * sec_fac);
+                       cylinders = llcyls;
+                       if (cylinders != llcyls)
+                               cylinders = ~0;
+               } else {
+                       cylinders = geometry.cylinders;
+                       fprintf(stderr,
+                               _("Warning:  BLKGETSIZE ioctl failed on %s.  "
+                                 "Using geometry cylinder value of %d.\n"
+                                 "This value may be truncated for devices"
+                                 " > 33.8 GB.\n"), disk_device, cylinders);
+               }
        } else {
-           sunlabel->sparecyl = SSWAP16(p->sparecyl);
-           sunlabel->ncyl = SSWAP16(p->ncyl);
-           sunlabel->nacyl = SSWAP16(p->nacyl);
-           sunlabel->pcylcount = SSWAP16(p->pcylcount);
-           sunlabel->ntrks = SSWAP16(p->ntrks);
-           sunlabel->nsect = SSWAP16(p->nsect);
-           sunlabel->rspeed = SSWAP16(p->rspeed);
-           sunlabel->ilfact = SSWAP16(1);
-           cylinders = p->ncyl;
-           heads = p->ntrks;
-           sectors = p->nsect;
-           puts(_("You may change all the disk params from the x menu"));
+               heads = read_int(1,1,1024,0,_("Heads"));
+               sectors = read_int(1,1,1024,0,_("Sectors/track"));
+               cylinders = read_int(1,1,65535,0,_("Cylinders"));
        }
 
-       snprintf(sunlabel->info, sizeof(sunlabel->info),
-                "%s%s%s cyl %d alt %d hd %d sec %llu",
-                p ? p->vendor : "", (p && *p->vendor) ? " " : "",
-                p ? p->model
-                  : (floppy ? _("3,5\" floppy") : _("Linux custom")),
-               cylinders, SSWAP16(sunlabel->nacyl), heads, sectors);
+       sunlabel->acyl   = SSWAP16(2);
+       sunlabel->pcyl   = SSWAP16(cylinders);
+       sunlabel->ncyl   = SSWAP16(cylinders - 2);
+       sunlabel->rpm    = SSWAP16(5400);
+       sunlabel->intrlv = SSWAP16(1);
+       sunlabel->apc    = SSWAP16(0);
 
-       sunlabel->ntrks = SSWAP16(heads);
+       sunlabel->nhead = SSWAP16(heads);
        sunlabel->nsect = SSWAP16(sectors);
        sunlabel->ncyl = SSWAP16(cylinders);
-       if (floppy)
-           set_sun_partition(0, 0, cylinders * heads * sectors, LINUX_NATIVE);
-       else {
-           if (cylinders * heads * sectors >= 150 * 2048) {
+
+       snprintf(sunlabel->label_id, sizeof(sunlabel->label_id),
+                "Linux cyl %d alt %d hd %d sec %llu",
+                cylinders, SSWAP16(sunlabel->acyl), heads, sectors);
+
+       if (cylinders * heads * sectors >= 150 * 2048) {
                ndiv = cylinders - (50 * 2048 / (heads * sectors)); /* 50M swap 
*/
-           } else
+       } else
                ndiv = cylinders * 2 / 3;
-           set_sun_partition(0, 0, ndiv * heads * sectors, LINUX_NATIVE);
-           set_sun_partition(1, ndiv * heads * sectors, cylinders * heads * 
sectors, LINUX_SWAP);
-           sunlabel->infos[1].flags |= 0x01; /* Not mountable */
-       }
-       set_sun_partition(2, 0, cylinders * heads * sectors, WHOLE_DISK);
+
+       set_sun_partition(0, 0, ndiv * heads * sectors,
+                         SUN_TAG_LINUX_NATIVE);
+       set_sun_partition(1, ndiv * heads * sectors,
+                         cylinders * heads * sectors,
+                         SUN_TAG_LINUX_SWAP);
+       sunlabel->part_tags[1].flag |= SSWAP16(SUN_FLAG_UNMNT);
+
+       set_sun_partition(2, 0, cylinders * heads * sectors, SUN_TAG_BACKUP);
+
        {
                unsigned short *ush = (unsigned short *)sunlabel;
                unsigned short csum = 0;
-               while(ush < (unsigned short *)(&sunlabel->csum))
+               while(ush < (unsigned short *)(&sunlabel->cksum))
                        csum ^= *ush++;
-               sunlabel->csum = csum;
+               sunlabel->cksum = csum;
        }
 
        set_all_unchanged();
@@ -382,24 +270,32 @@ void create_sunlabel(void)
        set_changed(0);
 }
 
-void
-toggle_sunflags(int i, unsigned char mask) {
-       if (sunlabel->infos[i].flags & mask)
-               sunlabel->infos[i].flags &= ~mask;
-       else sunlabel->infos[i].flags |= mask;
+void toggle_sunflags(int i, __u16 mask)
+{
+       struct sun_tag_flag *p = &sunlabel->part_tags[i];
+
+       p->flag ^= SSWAP16(mask);
+
        set_changed(i);
 }
 
-static void
-fetch_sun(unsigned int *starts, unsigned int *lens, unsigned int *start, 
unsigned int *stop) {
+static void fetch_sun(__u32 *starts, __u32 *lens, __u32 *start, __u32 *stop)
+{
        int i, continuous = 1;
-       *start = 0; *stop = cylinders * heads * sectors;
+
+       *start = 0;
+       *stop = cylinders * heads * sectors;
+
        for (i = 0; i < partitions; i++) {
-               if (sunlabel->partitions[i].num_sectors
-                   && sunlabel->infos[i].id
-                   && sunlabel->infos[i].id != WHOLE_DISK) {
-                       starts[i] = 
SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
-                       lens[i] = SSWAP32(sunlabel->partitions[i].num_sectors);
+               struct sun_partition *part = &sunlabel->partitions[i];
+               struct sun_tag_flag *tag = &sunlabel->part_tags[i];
+
+               if (part->num_sectors &&
+                   tag->tag != SSWAP16(SUN_TAG_UNASSIGNED) &&
+                   tag->tag != SSWAP16(SUN_TAG_BACKUP)) {
+                       starts[i] = (SSWAP32(part->start_cylinder) *
+                                    heads * sectors);
+                       lens[i] = SSWAP32(part->num_sectors);
                        if (continuous) {
                                if (starts[i] == *start)
                                        *start += lens[i];
@@ -419,24 +315,29 @@ fetch_sun(unsigned int *starts, unsigned int *lens, 
unsigned int *start, unsigne
 
 static unsigned int *verify_sun_starts;
 
-static int
-verify_sun_cmp(int *a, int *b) {
-    if (*a == -1) return 1;
-    if (*b == -1) return -1;
-    if (verify_sun_starts[*a] > verify_sun_starts[*b]) return 1;
+static int verify_sun_cmp(int *a, int *b)
+{
+    if (*a == -1)
+           return 1;
+    if (*b == -1)
+           return -1;
+    if (verify_sun_starts[*a] > verify_sun_starts[*b])
+           return 1;
     return -1;
 }
 
-void
-verify_sun(void) {
-    unsigned int starts[8], lens[8], start, stop;
+void verify_sun(void)
+{
+    __u32 starts[SUN_NUM_PARTITIONS], lens[SUN_NUM_PARTITIONS], start, stop;
     int i,j,k,starto,endo;
-    int array[8];
+    int array[SUN_NUM_PARTITIONS];
 
     verify_sun_starts = starts;
-    fetch_sun(starts,lens,&start,&stop);
+
+    fetch_sun(starts, lens, &start, &stop);
+
     for (k = 0; k < 7; k++) {
-       for (i = 0; i < 8; i++) {
+       for (i = 0; i < SUN_NUM_PARTITIONS; i++) {
            if (k && (lens[i] % (heads * sectors))) {
                printf(_("Partition %d doesn't end on cylinder boundary\n"), 
i+1);
            }
@@ -466,7 +367,7 @@ verify_sun(void) {
            }
        }
     }
-    for (i = 0; i < 8; i++) {
+    for (i = 0; i < SUN_NUM_PARTITIONS; i++) {
         if (lens[i])
             array[i] = i;
         else
@@ -480,31 +381,35 @@ verify_sun(void) {
     }
     stop = cylinders * heads * sectors;
     if (starts[array[0]])
-        printf(_("Unused gap - sectors 0-%d\n"),starts[array[0]]);
+        printf(_("Unused gap - sectors 0-%d\n"), starts[array[0]]);
     for (i = 0; i < 7 && array[i+1] != -1; i++) {
-        printf(_("Unused gap - sectors 
%d-%d\n"),starts[array[i]]+lens[array[i]],starts[array[i+1]]);
+        printf(_("Unused gap - sectors %d-%d\n"),
+              (starts[array[i]] + lens[array[i]]),
+              starts[array[i+1]]);
     }
-    start = starts[array[i]]+lens[array[i]];
+    start = (starts[array[i]] + lens[array[i]]);
     if (start < stop)
-        printf(_("Unused gap - sectors %d-%d\n"),start,stop);
+        printf(_("Unused gap - sectors %d-%d\n"), start, stop);
 }
 
-void
-add_sun_partition(int n, int sys) {
-       unsigned int start, stop, stop2;
-       unsigned int starts[8], lens[8];
+void add_sun_partition(int n, int sys)
+{
+       __u32 starts[SUN_NUM_PARTITIONS], lens[SUN_NUM_PARTITIONS];
+       struct sun_partition *part = &sunlabel->partitions[n];
+       struct sun_tag_flag *tag = &sunlabel->part_tags[n];
+       __u32 start, stop, stop2;
        int whole_disk = 0;
                
        char mesg[256];
        int i, first, last;
 
-       if (sunlabel->partitions[n].num_sectors && sunlabel->infos[n].id) {
+       if (part->num_sectors && tag->tag != SSWAP16(SUN_TAG_UNASSIGNED)) {
                printf(_("Partition %d is already defined.  Delete "
                        "it before re-adding it.\n"), n + 1);
                return;
        }
        
-       fetch_sun(starts,lens,&start,&stop);
+       fetch_sun(starts, lens, &start, &stop);
        if (stop <= start) {
                if (n == 2)
                        whole_disk = 1;
@@ -600,29 +505,37 @@ and is of type `Whole disk'\n");
        } else if (!whole_disk && last > stop)
                last = stop;
 
-       if (whole_disk) sys = WHOLE_DISK;
+       if (whole_disk)
+               sys = SUN_TAG_BACKUP;
+
        set_sun_partition(n, first, last, sys);
 }
 
-void
-sun_delete_partition(int i) {
+void sun_delete_partition(int i)
+{
+       struct sun_partition *part = &sunlabel->partitions[i];
+       struct sun_tag_flag *tag = &sunlabel->part_tags[i];
        unsigned int nsec;
 
-       if (i == 2 && sunlabel->infos[i].id == WHOLE_DISK && 
-           !sunlabel->partitions[i].start_cylinder && 
-           (nsec = SSWAP32(sunlabel->partitions[i].num_sectors))
+       if (i == 2 &&
+           tag->tag == SSWAP16(SUN_TAG_BACKUP) && 
+           !part->start_cylinder && 
+           (nsec = SSWAP32(part->num_sectors))
              == heads * sectors * cylinders)
                printf(_("If you want to maintain SunOS/Solaris compatibility, "
                       "consider leaving this\n"
                       "partition as Whole disk (5), starting at 0, with %u "
                       "sectors\n"), nsec);
-       sunlabel->infos[i].id = 0;
-       sunlabel->partitions[i].num_sectors = 0;
+       tag->tag = SSWAP16(SUN_TAG_UNASSIGNED);
+       part->num_sectors = 0;
 }
 
-void
-sun_change_sysid(int i, int sys) {
-       if (sys == LINUX_SWAP && !sunlabel->partitions[i].start_cylinder) {
+void sun_change_sysid(int i, __u16 sys)
+{
+       struct sun_partition *part = &sunlabel->partitions[i];
+       struct sun_tag_flag *tag = &sunlabel->part_tags[i];
+
+       if (sys == SUN_TAG_LINUX_SWAP && !part->start_cylinder) {
            read_chars(
              _("It is highly recommended that the partition at offset 0\n"
              "is UFS, EXT2FS filesystem or SunOS swap. Putting Linux swap\n"
@@ -633,22 +546,22 @@ sun_change_sysid(int i, int sys) {
                    return;
        }
        switch (sys) {
-       case SUNOS_SWAP:
-       case LINUX_SWAP:
+       case SUN_TAG_SWAP:
+       case SUN_TAG_LINUX_SWAP:
                /* swaps are not mountable by default */
-               sunlabel->infos[i].flags |= 0x01;
+               tag->flag |= SSWAP16(SUN_FLAG_UNMNT);
                break;
        default:
                /* assume other types are mountable;
                   user can change it anyway */
-               sunlabel->infos[i].flags &= ~0x01;
+               tag->flag &= ~SSWAP16(SUN_FLAG_UNMNT);
                break;
        }
-       sunlabel->infos[i].id = sys;
+       tag->tag = SSWAP16(sys);
 }
 
-void
-sun_list_table(int xtra) {
+void sun_list_table(int xtra)
+{
        int i, w;
        char *type;
 
@@ -658,14 +571,16 @@ sun_list_table(int xtra) {
                _("\nDisk %s (Sun disk label): %d heads, %llu sectors, %d rpm\n"
                "%d cylinders, %d alternate cylinders, %d physical cylinders\n"
                "%d extra sects/cyl, interleave %d:1\n"
-               "%s\n"
+               "Label ID: %s\n"
+               "Volume ID: %s\n"
                "Units = %s of %d * 512 bytes\n\n"),
-                      disk_device, heads, sectors, SSWAP16(sunlabel->rspeed),
-                      cylinders, SSWAP16(sunlabel->nacyl),
-                      SSWAP16(sunlabel->pcylcount),
-                      SSWAP16(sunlabel->sparecyl),
-                      SSWAP16(sunlabel->ilfact),
-                      (char *)sunlabel,
+                      disk_device, heads, sectors, SSWAP16(sunlabel->rpm),
+                      cylinders, SSWAP16(sunlabel->acyl),
+                      SSWAP16(sunlabel->pcyl),
+                      SSWAP16(sunlabel->apc),
+                      SSWAP16(sunlabel->intrlv),
+                      sunlabel->label_id,
+                      sunlabel->volume_id,
                       str_units(PLURAL), units_per_sector);
        else
                printf(
@@ -677,74 +592,82 @@ sun_list_table(int xtra) {
        printf(_("%*s Flag    Start       End    Blocks   Id  System\n"),
               w + 1, _("Device"));
        for (i = 0 ; i < partitions; i++) {
-               if (sunlabel->partitions[i].num_sectors) {
-                       __u32 start = 
SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
-                       __u32 len = 
SSWAP32(sunlabel->partitions[i].num_sectors);
+               struct sun_partition *part = &sunlabel->partitions[i];
+               struct sun_tag_flag *tag = &sunlabel->part_tags[i];
+
+               if (part->num_sectors) {
+                       __u32 start = SSWAP32(part->start_cylinder) * heads * 
sectors;
+                       __u32 len = SSWAP32(part->num_sectors);
                        printf(
                            "%s %c%c %9ld %9ld %9ld%c  %2x  %s\n",
 /* device */             partname(disk_device, i+1, w),
-/* flags */              (sunlabel->infos[i].flags & 0x01) ? 'u' : ' ',
-                         (sunlabel->infos[i].flags & 0x10) ? 'r' : ' ',
+/* flags */              (tag->flag & SSWAP16(SUN_FLAG_UNMNT)) ? 'u' : ' ',
+                         (tag->flag & SSWAP16(SUN_FLAG_RONLY)) ? 'r' : ' ',
 /* start */              (long) scround(start),
 /* end */                (long) scround(start+len),
 /* odd flag on end */    (long) len / 2, len & 1 ? '+' : ' ',
-/* type id */            sunlabel->infos[i].id,
-/* type name */                  (type = partition_type(sunlabel->infos[i].id))
+/* type id */            SSWAP16(tag->tag),
+/* type name */                  (type = partition_type(SSWAP16(tag->tag)))
                                ? type : _("Unknown"));
                }
        }
 }
 
-void
-sun_set_alt_cyl(void) {
-       sunlabel->nacyl =
-               SSWAP16(read_int(0,SSWAP16(sunlabel->nacyl), 65535, 0,
+void sun_set_alt_cyl(void)
+{
+       sunlabel->acyl =
+               SSWAP16(read_int(0,SSWAP16(sunlabel->acyl), 65535, 0,
                                 _("Number of alternate cylinders")));
 }
 
-void
-sun_set_ncyl(int cyl) {
+void sun_set_ncyl(int cyl)
+{
        sunlabel->ncyl = SSWAP16(cyl);
 }
 
-void
-sun_set_xcyl(void) {
-       sunlabel->sparecyl =
-               SSWAP16(read_int(0, SSWAP16(sunlabel->sparecyl), sectors, 0,
+void sun_set_xcyl(void)
+{
+       sunlabel->apc =
+               SSWAP16(read_int(0, SSWAP16(sunlabel->apc), sectors, 0,
                                 _("Extra sectors per cylinder")));
 }
 
-void
-sun_set_ilfact(void) {
-       sunlabel->ilfact =
-               SSWAP16(read_int(1, SSWAP16(sunlabel->ilfact), 32, 0,
+void sun_set_ilfact(void)
+{
+       sunlabel->intrlv =
+               SSWAP16(read_int(1, SSWAP16(sunlabel->intrlv), 32, 0,
                                 _("Interleave factor")));
 }
 
-void
-sun_set_rspeed(void) {
-       sunlabel->rspeed =
-               SSWAP16(read_int(1, SSWAP16(sunlabel->rspeed), 100000, 0,
+void sun_set_rspeed(void)
+{
+       sunlabel->rpm =
+               SSWAP16(read_int(1, SSWAP16(sunlabel->rpm), 100000, 0,
                                 _("Rotation speed (rpm)")));
 }
 
-void
-sun_set_pcylcount(void) {
-       sunlabel->pcylcount =
-               SSWAP16(read_int(0, SSWAP16(sunlabel->pcylcount), 65535, 0,
+void sun_set_pcylcount(void)
+{
+       sunlabel->pcyl =
+               SSWAP16(read_int(0, SSWAP16(sunlabel->pcyl), 65535, 0,
                                 _("Number of physical cylinders")));
 }
 
-void
-sun_write_table(void) {
+void sun_write_table(void)
+{
        unsigned short *ush = (unsigned short *)sunlabel;
        unsigned short csum = 0;
 
-       while(ush < (unsigned short *)(&sunlabel->csum))
+       while(ush < (unsigned short *)(&sunlabel->cksum))
                csum ^= *ush++;
-       sunlabel->csum = csum;
+       sunlabel->cksum = csum;
        if (lseek(fd, 0, SEEK_SET) < 0)
                fatal(unable_to_seek);
        if (write(fd, sunlabel, SECTOR_SIZE) != SECTOR_SIZE)
                fatal(unable_to_write);
 }
+
+int sun_get_sysid(int i)
+{
+       return SSWAP16(sunlabel->part_tags[i].tag);
+}
diff --git a/fdisk/fdisksunlabel.h b/fdisk/fdisksunlabel.h
index e322e66..c8e0698 100644
--- a/fdisk/fdisksunlabel.h
+++ b/fdisk/fdisksunlabel.h
@@ -3,53 +3,86 @@
 
 #include <linux/types.h>   /* for __u16, __u32 */
 
-typedef struct {
-       unsigned char info[128];   /* Informative text string */
-       unsigned char spare0[14];
-       struct sun_info {
-               unsigned char spare1;
-               unsigned char id;
-               unsigned char spare2;
-               unsigned char flags;
-       } infos[8];
-       unsigned char spare1[246]; /* Boot information etc. */
-       unsigned short rspeed;     /* Disk rotational speed */
-       unsigned short pcylcount;  /* Physical cylinder count */
-       unsigned short sparecyl;   /* extra sects per cylinder */
-       unsigned char spare2[4];   /* More magic... */
-       unsigned short ilfact;     /* Interleave factor */
-       unsigned short ncyl;       /* Data cylinder count */
-       unsigned short nacyl;      /* Alt. cylinder count */
-       unsigned short ntrks;      /* Tracks per cylinder */
-       unsigned short nsect;      /* Sectors per track */
-       unsigned char spare3[4];   /* Even more magic... */
-       struct sun_partition {
-               __u32 start_cylinder;
-               __u32 num_sectors;
-       } partitions[8];
-       unsigned short magic;      /* Magic number */
-       unsigned short csum;       /* Label xor'd checksum */
-} sun_partition;
+struct sun_partition {
+       __u32   start_cylinder;
+       __u32   num_sectors;
+};
 
-#define SUN_LABEL_MAGIC          0xDABE
-#define SUN_LABEL_MAGIC_SWAPPED  0xBEDA
-#define sunlabel ((sun_partition *)MBRbuffer)
-#define SSWAP16(x) (other_endian ? __swap16(x) \
-                                : (__u16)(x))
-#define SSWAP32(x) (other_endian ? __swap32(x) \
-                                : (__u32)(x))
-/* fdisksunlabel.c */
-#define SUNOS_SWAP 3
-#define WHOLE_DISK 5
+struct sun_tag_flag {
+       __u16   tag;
+#define SUN_TAG_UNASSIGNED     0x00    /* Unassigned partition */
+#define SUN_TAG_BOOT           0x01    /* Boot partition       */
+#define SUN_TAG_ROOT           0x02    /* Root filesystem      */
+#define SUN_TAG_SWAP           0x03    /* Swap partition       */
+#define SUN_TAG_USR            0x04    /* /usr filesystem      */
+#define SUN_TAG_BACKUP         0x05    /* Full-disk slice      */
+#define SUN_TAG_STAND          0x06    /* Stand partition      */
+#define SUN_TAG_VAR            0x07    /* /var filesystem      */
+#define SUN_TAG_HOME           0x08    /* /home filesystem     */
+#define SUN_TAG_ALTSCTR                0x09    /* Alt sector partition */
+#define SUN_TAG_CACHE          0x0a    /* Cachefs partition    */
+#define SUN_TAG_RESERVED       0x0b    /* SMI reserved data    */
+#define SUN_TAG_LINUX_SWAP     0x82    /* Linux SWAP           */
+#define SUN_TAG_LINUX_NATIVE   0x83    /* Linux filesystem     */
+#define SUN_TAG_LINUX_LVM      0x8e    /* Linux LVM            */
+#define SUN_TAG_LINUX_RAID     0xfd    /* LInux RAID           */
+
+       __u16   flag;
+#define SUN_FLAG_UNMNT         0x01    /* Unmountable partition*/
+#define SUN_FLAG_RONLY         0x10    /* Read only            */
+};
+
+#define SUN_LABEL_SIZE         512
+
+#define SUN_LABEL_ID_SIZE      128
+#define SUN_VOLUME_ID_SIZE     8
 
+#define SUN_LABEL_VERSION      0x00000001
+#define SUN_LABEL_SANE         0x600ddeee
+#define SUN_NUM_PARTITIONS     8
+
+struct sun_disk_label {
+       char                    label_id[SUN_LABEL_ID_SIZE];
+       __u32                   version;
+       char                    volume_id[SUN_VOLUME_ID_SIZE];
+       __u16                   num_partitions;
+       struct sun_tag_flag     part_tags[SUN_NUM_PARTITIONS];
+       __u32                   bootinfo[3];
+       __u32                   sanity;
+       __u32                   resv[10];
+       __u32                   part_timestamps[SUN_NUM_PARTITIONS];
+       __u32                   write_reinstruct;
+       __u32                   read_reinstruct;
+       __u8                    pad[148];
+       __u16                   rpm;
+       __u16                   pcyl;
+       __u16                   apc;
+       __u16                   resv1;
+       __u16                   resv2;
+       __u16                   intrlv;
+       __u16                   ncyl;
+       __u16                   acyl;
+       __u16                   nhead;
+       __u16                   nsect;
+       __u16                   resv3;
+       __u16                   resv4;
+       struct sun_partition    partitions[SUN_NUM_PARTITIONS];
+       __u16                   magic;
+       __u16                   cksum;
+};
+
+#define SUN_LABEL_MAGIC                0xDABE
+#define SUN_LABEL_MAGIC_SWAPPED        0xBEDA
+#define sunlabel ((struct sun_disk_label *)MBRbuffer)
+
+/* fdisksunlabel.c */
 extern struct systypes sun_sys_types[];
-extern int get_num_sectors(struct sun_partition p);
 extern void guess_device_type(int fd);
 extern int check_sun_label(void);
 extern void sun_nolabel(void);
 extern void create_sunlabel(void);
 extern void sun_delete_partition(int i);
-extern void sun_change_sysid(int i, int sys);
+extern void sun_change_sysid(int i, __u16 sys);
 extern void sun_list_table(int xtra);
 extern void verify_sun(void);
 extern void add_sun_partition(int n, int sys);
@@ -60,6 +93,7 @@ extern void sun_set_xcyl(void);
 extern void sun_set_ilfact(void);
 extern void sun_set_rspeed(void);
 extern void sun_set_pcylcount(void);
-extern void toggle_sunflags(int i, unsigned char mask);
+extern void toggle_sunflags(int i, __u16 mask);
+extern int sun_get_sysid(int i);
 
 #endif /* FDISK_SUN_LABEL_H */
-
To unsubscribe from this list: send the line "unsubscribe util-linux-ng" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to