From: David Miller <davem@xxxxxxxxxxxxx> 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 <davem@xxxxxxxxxxxxx> 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 majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html