diff options
| author | Sheshadri Vasudevan <Sheshadri.Vasudevan@Sun.COM> | 2008-12-03 01:39:30 -0800 |
|---|---|---|
| committer | Sheshadri Vasudevan <Sheshadri.Vasudevan@Sun.COM> | 2008-12-03 01:39:30 -0800 |
| commit | c26dc428cee0f025b14a5ad03a7722f2a52f8383 (patch) | |
| tree | 8da849e326156c91dbd2a79ce00cce6a740a8cea /usr/src/cmd/format | |
| parent | 4ad13226f66b623d454251005ba7e1eeb218bbfb (diff) | |
| download | illumos-joyent-c26dc428cee0f025b14a5ad03a7722f2a52f8383.tar.gz | |
PSARC/2006/379 Solaris on Extended partition
6644364 Extended partitions need to be supported on Solaris
6713308 Macro UNUSED in fdisk.h needs to be changed since id 100 is Novell Netware 286's partition ID
6713318 Need to differentiate between solaris old partition and Linux swap
6745175 Partitions can be created using fdisk table with invalid partition line by "fdisk -F"
6745740 Multiple extended partition can be created by "fdisk -A"
Diffstat (limited to 'usr/src/cmd/format')
| -rw-r--r-- | usr/src/cmd/format/Makefile | 5 | ||||
| -rw-r--r-- | usr/src/cmd/format/menu_fdisk.c | 255 |
2 files changed, 213 insertions, 47 deletions
diff --git a/usr/src/cmd/format/Makefile b/usr/src/cmd/format/Makefile index 1060271ac4..e19d8342a7 100644 --- a/usr/src/cmd/format/Makefile +++ b/usr/src/cmd/format/Makefile @@ -53,8 +53,11 @@ $(ROOTETCDATA) := FILEMODE = 0644 $(ROOTETCDATA) := OWNER = root $(ROOTETCDATA) := GROUP = sys -LDLIBS += -ladm -lefi -ldiskmgt -lnvpair -ldevid +LDLIBS_i386= -lfdisk +LDLIBS_sparc= +LDLIBS += -ladm -lefi -ldiskmgt -lnvpair -ldevid $(LDLIBS_$(MACH)) +LINTFLAGS += -xerroff=E_NAME_DEF_NOT_USED2 CPPFLAGS += -D_EXTVTOC .KEEP_STATE: diff --git a/usr/src/cmd/format/menu_fdisk.c b/usr/src/cmd/format/menu_fdisk.c index 4ebadee5ab..01c4fadd57 100644 --- a/usr/src/cmd/format/menu_fdisk.c +++ b/usr/src/cmd/format/menu_fdisk.c @@ -38,6 +38,9 @@ #include <sys/dktp/fdisk.h> #include <sys/stat.h> #include <sys/dklabel.h> +#ifdef i386 +#include <libfdisk.h> +#endif #include "main.h" #include "analyze.h" @@ -105,6 +108,10 @@ static int get_solaris_part(); #endif /* __STDC__ */ + +#ifdef i386 +int extpart_init(ext_part_t **epp); +#endif /* * Handling the alignment problem of struct ipart. */ @@ -274,22 +281,23 @@ open_cur_file(int mode) char pbuf[MAXPATHLEN]; switch (mode) { - case FD_USE_P0_PATH: - (void) get_pname(&pbuf[0]); - dkpath = pbuf; - break; - case FD_USE_CUR_DISK_PATH: - if (cur_disk->fdisk_part.systid == SUNIXOS || - cur_disk->fdisk_part.systid == SUNIXOS2) { - (void) get_sname(&pbuf[0]); + case FD_USE_P0_PATH: + (void) get_pname(&pbuf[0]); dkpath = pbuf; - } else { - dkpath = cur_disk->disk_path; - } - break; - default: - err_print("Error: Invalid mode option for opening cur_file\n"); - fullabort(); + break; + case FD_USE_CUR_DISK_PATH: + if (cur_disk->fdisk_part.systid == SUNIXOS || + cur_disk->fdisk_part.systid == SUNIXOS2) { + (void) get_sname(&pbuf[0]); + dkpath = pbuf; + } else { + dkpath = cur_disk->disk_path; + } + break; + default: + err_print("Error: Invalid mode option for opening " + "cur_file\n"); + fullabort(); } /* Close previous cur_file */ @@ -388,7 +396,7 @@ update_cur_parts() for (i = 0; i < NDKMAP; i++) { #if defined(_SUNOS_VTOC_16) if (cur_parts->vtoc.v_part[i].p_tag && - cur_parts->vtoc.v_part[i].p_tag != V_ALTSCTR) { + cur_parts->vtoc.v_part[i].p_tag != V_ALTSCTR) { cur_parts->vtoc.v_part[i].p_start = 0; cur_parts->vtoc.v_part[i].p_size = 0; @@ -396,9 +404,9 @@ update_cur_parts() cur_parts->pinfo_map[i].dkl_nblk = 0; cur_parts->pinfo_map[i].dkl_cylno = 0; cur_parts->vtoc.v_part[i].p_tag = - default_vtoc_map[i].p_tag; + default_vtoc_map[i].p_tag; cur_parts->vtoc.v_part[i].p_flag = - default_vtoc_map[i].p_flag; + default_vtoc_map[i].p_flag; #if defined(_SUNOS_VTOC_16) } #endif @@ -412,14 +420,14 @@ update_cur_parts() cur_parts->pinfo_map[I_PARTITION].dkl_nblk = spc(); cur_parts->pinfo_map[I_PARTITION].dkl_cylno = 0; cur_parts->vtoc.v_part[C_PARTITION].p_start = - cur_parts->pinfo_map[C_PARTITION].dkl_cylno * nhead * nsect; + cur_parts->pinfo_map[C_PARTITION].dkl_cylno * nhead * nsect; cur_parts->vtoc.v_part[C_PARTITION].p_size = - cur_parts->pinfo_map[C_PARTITION].dkl_nblk; + cur_parts->pinfo_map[C_PARTITION].dkl_nblk; cur_parts->vtoc.v_part[I_PARTITION].p_start = - cur_parts->pinfo_map[I_PARTITION].dkl_cylno; + cur_parts->pinfo_map[I_PARTITION].dkl_cylno; cur_parts->vtoc.v_part[I_PARTITION].p_size = - cur_parts->pinfo_map[I_PARTITION].dkl_nblk; + cur_parts->pinfo_map[I_PARTITION].dkl_nblk; #endif /* defined(_SUNOS_VTOC_16) */ parts = cur_dtype->dtype_plist; @@ -440,6 +448,12 @@ get_solaris_part(int fd, struct ipart *ipart) int status; char *bootptr; struct dk_label update_label; + ushort_t found = 0; +#ifdef i386 + uint32_t relsec, numsec; + int pno, rval, ext_part_found = 0; + ext_part_t *epp; +#endif (void) lseek(fd, 0, 0); status = read(fd, (caddr_t)&boot_sec, NBPSCTR); @@ -459,6 +473,41 @@ get_solaris_part(int fd, struct ipart *ipart) bootptr = &boot_sec.parts[ipc]; (void) fill_ipart(bootptr, &ip); +#ifdef i386 + if (fdisk_is_dos_extended(ip.systid) && (ext_part_found == 0)) { + /* We support only one extended partition per disk */ + ext_part_found = 1; + (void) extpart_init(&epp); + rval = fdisk_get_solaris_part(epp, &pno, &relsec, + &numsec); + if (rval == FDISK_SUCCESS) { + /* + * Found a solaris partition inside the + * extended partition. Update the statistics. + */ + if (nhead != 0 && nsect != 0) { + pcyl = numsec / (nhead * nsect); + xstart = relsec / (nhead * nsect); + ncyl = pcyl - acyl; + } + solaris_offset = relsec; + found = 2; + ip.bootid = 0; + ip.beghead = ip.begsect = ip.begcyl = 0xff; + ip.endhead = ip.endsect = ip.endcyl = 0xff; + ip.systid = SUNIXOS2; + ip.relsect = relsec; + ip.numsect = numsec; + ipart->bootid = ip.bootid; + status = bcmp(&ip, ipart, + sizeof (struct ipart)); + bcopy(&ip, ipart, sizeof (struct ipart)); + } + libfdisk_fini(&epp); + continue; + } +#endif + /* * we are interested in Solaris and EFI partition types */ @@ -478,29 +527,31 @@ get_solaris_part(int fd, struct ipart *ipart) #ifdef DEBUG else { err_print("Critical geometry values are zero:\n" - "\tnhead = %d; nsect = %d\n", nhead, - nsect); + "\tnhead = %d; nsect = %d\n", nhead, nsect); } #endif /* DEBUG */ solaris_offset = (uint_t)lel(ip.relsect); + found = 1; break; } } - if (i == FD_NUMPART) { + if (!found) { err_print("Solaris fdisk partition not found\n"); return (-1); - } - - /* - * compare the previous and current Solaris partition - * but don't use bootid in determination of Solaris partition changes - */ - ipart->bootid = ip.bootid; - status = bcmp(&ip, ipart, sizeof (struct ipart)); + } else if (found == 1) { + /* + * Found a primary solaris partition. + * compare the previous and current Solaris partition + * but don't use bootid in determination of Solaris partition + * changes + */ + ipart->bootid = ip.bootid; + status = bcmp(&ip, ipart, sizeof (struct ipart)); - bcopy(&ip, ipart, sizeof (struct ipart)); + bcopy(&ip, ipart, sizeof (struct ipart)); + } /* if the disk partitioning has changed - get the VTOC */ if (status) { @@ -569,12 +620,17 @@ copy_solaris_part(struct ipart *ipart) char buf[MAXPATHLEN]; char *bootptr; struct stat statbuf; +#ifdef i386 + uint32_t relsec, numsec; + int pno, rval, ext_part_found = 0; + ext_part_t *epp; +#endif (void) get_pname(&buf[0]); if (stat(buf, &statbuf) == -1 || !S_ISCHR(statbuf.st_mode) || ((cur_label == L_TYPE_EFI) && - (cur_disk->disk_flags & DSK_LABEL_DIRTY))) { + (cur_disk->disk_flags & DSK_LABEL_DIRTY))) { /* * Make sure to reset solaris_offset to zero if it is * previously set by a selected disk that @@ -612,6 +668,36 @@ copy_solaris_part(struct ipart *ipart) bootptr = &mboot.parts[ipc]; (void) fill_ipart(bootptr, &ip); +#ifdef i386 + if (fdisk_is_dos_extended(ip.systid) && (ext_part_found == 0)) { + /* We support only one extended partition per disk */ + ext_part_found = 1; + (void) extpart_init(&epp); + rval = fdisk_get_solaris_part(epp, &pno, &relsec, + &numsec); + if (rval == FDISK_SUCCESS) { + /* + * Found a solaris partition inside the + * extended partition. Update the statistics. + */ + if (nhead != 0 && nsect != 0) { + pcyl = numsec / (nhead * nsect); + ncyl = pcyl - acyl; + } + solaris_offset = relsec; + ip.bootid = 0; + ip.beghead = ip.begsect = ip.begcyl = 0xff; + ip.endhead = ip.endsect = ip.endcyl = 0xff; + ip.systid = SUNIXOS2; + ip.relsect = relsec; + ip.numsect = numsec; + bcopy(&ip, ipart, sizeof (struct ipart)); + } + libfdisk_fini(&epp); + continue; + } +#endif + if (ip.systid == SUNIXOS || ip.systid == SUNIXOS2 || ip.systid == EFI_PMBR) { @@ -631,8 +717,7 @@ copy_solaris_part(struct ipart *ipart) #ifdef DEBUG else { err_print("Critical geometry values are zero:\n" - "\tnhead = %d; nsect = %d\n", nhead, - nsect); + "\tnhead = %d; nsect = %d\n", nhead, nsect); } #endif /* DEBUG */ @@ -655,7 +740,11 @@ auto_solaris_part(struct dk_label *label) struct ipart ip; char *bootptr; char pbuf[MAXPATHLEN]; - +#ifdef i386 + uint32_t relsec, numsec; + int pno, rval, ext_part_found = 0; + ext_part_t *epp; +#endif (void) get_pname(&pbuf[0]); if ((fd = open_disk(pbuf, O_RDONLY)) < 0) { @@ -679,6 +768,33 @@ auto_solaris_part(struct dk_label *label) bootptr = &mboot.parts[ipc]; (void) fill_ipart(bootptr, &ip); +#ifdef i386 + if (fdisk_is_dos_extended(ip.systid) && (ext_part_found == 0)) { + /* We support only one extended partition per disk */ + ext_part_found = 1; + (void) extpart_init(&epp); + rval = fdisk_get_solaris_part(epp, &pno, &relsec, + &numsec); + if (rval == FDISK_SUCCESS) { + /* + * Found a solaris partition inside the + * extended partition. Update the statistics. + */ + if ((label->dkl_nhead != 0) && + (label->dkl_nsect != 0)) { + label->dkl_pcyl = + numsec / (label->dkl_nhead * + label->dkl_nsect); + label->dkl_ncyl = label->dkl_pcyl - + label->dkl_acyl; + } + solaris_offset = relsec; + } + libfdisk_fini(&epp); + continue; + } +#endif + /* * if the disk has an EFI label, the nhead and nsect fields * the label may be zero. This protects us from FPE's, and @@ -697,11 +813,11 @@ auto_solaris_part(struct dk_label *label) #ifdef DEBUG else { err_print("Critical label fields aren't " - "non-zero:\n" - "\tlabel->dkl_nhead = %d; " - "label->dkl_nsect = " - "%d\n", label->dkl_nhead, - label->dkl_nsect); + "non-zero:\n" + "\tlabel->dkl_nhead = %d; " + "label->dkl_nsect = " + "%d\n", label->dkl_nhead, + label->dkl_nsect); } #endif /* DEBUG */ @@ -739,9 +855,56 @@ good_fdisk() } else { err_print("WARNING - "); err_print("This disk may be in use by an application " - "that has\n\t modified the fdisk table. Ensure " - "that this disk is\n\t not currently in use " - "before proceeding to use fdisk.\n"); + "that has\n\t modified the fdisk table. Ensure " + "that this disk is\n\t not currently in use " + "before proceeding to use fdisk.\n"); return (0); } } + + +#ifdef i386 +int +extpart_init(ext_part_t **epp) +{ + int rval, lf_op_flag = 0; + char p0_path[MAXPATHLEN]; + + get_pname(&p0_path[0]); + lf_op_flag |= FDISK_READ_DISK; + if ((rval = libfdisk_init(epp, p0_path, NULL, lf_op_flag)) != + FDISK_SUCCESS) { + switch (rval) { + /* + * FDISK_EBADLOGDRIVE and FDISK_ENOLOGDRIVE can + * be considered as soft errors and hence + * we do not exit + */ + case FDISK_EBADLOGDRIVE: + break; + case FDISK_ENOLOGDRIVE: + break; + case FDISK_ENOVGEOM: + err_print("Could not get virtual geometry for" + " this device\n"); + fullabort(); + break; + case FDISK_ENOPGEOM: + err_print("Could not get physical geometry for" + " this device\n"); + fullabort(); + break; + case FDISK_ENOLGEOM: + err_print("Could not get label geometry for " + " this device\n"); + fullabort(); + break; + default: + err_print("Failed to initialise libfdisk.\n"); + fullabort(); + break; + } + } + return (0); +} +#endif |
