From: David Miller Date: Fri, 29 Jun 2007 22:50:21 +0000 (-0700) Subject: fdisk: many significant improvements and fixes to Sun label handling X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=899736f12f276341294145f464dcc988cd94cb97;p=util-linux 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 --- diff --git a/fdisk/fdisk.c b/fdisk/fdisk.c index c4ab6d56..292b7a85 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 a1994e28..f67aa261 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 e322e66e..c8e06980 100644 --- a/fdisk/fdisksunlabel.h +++ b/fdisk/fdisksunlabel.h @@ -3,53 +3,86 @@ #include /* 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 */