[PATCH]: Many Sun label handling fixes

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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 <davem@xxxxxxxxxxxxx>

diff --git a/fdisk/fdisk.c b/fdisk/fdisk.c
index ecaac90..3f548d1 100644
--- a/fdisk/fdisk.c
+++ b/fdisk/fdisk.c
@@ -468,7 +468,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);
 }
@@ -1173,7 +1173,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,
@@ -1395,7 +1395,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 "
@@ -2600,7 +2600,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));
@@ -2624,7 +2624,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 312bfea..9a30fca 100644
--- a/fdisk/fdisksunlabel.h
+++ b/fdisk/fdisksunlabel.h
@@ -1,44 +1,80 @@
 #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;
+};
+
+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)
 
-#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))
-				 
 /* fdisk.c */
 extern unsigned char MBRbuffer[MAX_SECTOR_SIZE];
-extern unsigned int heads, cylinders;
+extern unsigned int heads, cylinders, sector_size;
 extern unsigned long long sectors;
 extern int show_begin;
 extern int sun_label;
@@ -49,17 +85,13 @@ extern void set_all_unchanged(void);
 extern void set_changed(int);
 
 /* fdisksunlabel.c */
-#define SUNOS_SWAP 3
-#define WHOLE_DISK 5
-
 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);
@@ -70,5 +102,5 @@ 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);
-
To unsubscribe from this list: send the line "unsubscribe util-linux-ng" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux