summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorToomas Soome <tsoome@me.com>2016-05-04 23:37:34 +0300
committerRichard Lowe <richlowe@richlowe.net>2016-12-04 10:44:40 -0500
commit5b5a71c445cf6577e9376190edd57004a2b09522 (patch)
treefe68b9b07292065970d3d05f4d545b7ecb0f2e73
parent55a424cb69d5e44a32d26e1c9fe02288d09a1663 (diff)
downloadillumos-joyent-5b5a71c445cf6577e9376190edd57004a2b09522.tar.gz
6964 mkfs_pcfs should detect GPT partition size and fat type for it
Reviewed by: Robert Mustacchi <rm@joyent.com> Reviewed by: Marcel Telka <marcel@telka.sk> Reviewed by: Yuri Pankov <yuri.pankov@gmail.com> Approved by: Richard Lowe <richlowe@richlowe.net>
-rw-r--r--usr/src/cmd/fs.d/pcfs/mkfs/Makefile1
-rw-r--r--usr/src/cmd/fs.d/pcfs/mkfs/mkfs.c208
2 files changed, 164 insertions, 45 deletions
diff --git a/usr/src/cmd/fs.d/pcfs/mkfs/Makefile b/usr/src/cmd/fs.d/pcfs/mkfs/Makefile
index 6e9829a447..352b271eb4 100644
--- a/usr/src/cmd/fs.d/pcfs/mkfs/Makefile
+++ b/usr/src/cmd/fs.d/pcfs/mkfs/Makefile
@@ -32,6 +32,7 @@ include ../../Makefile.fstype
OBJS= $(LIBPROG).o
SRCS= $(LIBPROG).c
+LDLIBS += -lefi
# for messaging catalog
#
diff --git a/usr/src/cmd/fs.d/pcfs/mkfs/mkfs.c b/usr/src/cmd/fs.d/pcfs/mkfs/mkfs.c
index f2f183bcef..96fe898b54 100644
--- a/usr/src/cmd/fs.d/pcfs/mkfs/mkfs.c
+++ b/usr/src/cmd/fs.d/pcfs/mkfs/mkfs.c
@@ -38,6 +38,8 @@
#include <sys/fdio.h>
#include <sys/dktp/fdisk.h>
#include <sys/dkio.h>
+#include <sys/vtoc.h>
+#include <sys/efi_partition.h>
#include <sys/sysmacros.h>
#include "mkfs_pcfs.h"
#include <sys/fs/pc_fs.h>
@@ -2217,6 +2219,151 @@ open_and_examine(char *dn, bpb_t *wbpb)
}
/*
+ * getdiskinfo
+ *
+ * Extracts information about disk path in dn. We need to return both a
+ * file descriptor and the device's suffix.
+ * Secondarily, we need to detect the FAT type and size when dealing with
+ * GPT partitions.
+ */
+static int
+getdiskinfo(char *dn, char **suffix)
+{
+ struct dk_minfo dkminfo;
+ struct stat di;
+ int rv, fd, reserved;
+ char *actualdisk = NULL;
+ dk_gpt_t *gpt = NULL;
+
+ actualdisk = stat_actual_disk(dn, &di, suffix);
+
+ /*
+ * Destination exists, now find more about it.
+ */
+ if (!(S_ISCHR(di.st_mode))) {
+ (void) fprintf(stderr,
+ gettext("Device name must indicate a "
+ "character special device: %s\n"), actualdisk);
+ exit(2);
+ } else if ((fd = open(actualdisk, O_RDWR)) < 0) {
+ perror(actualdisk);
+ exit(2);
+ }
+
+ /*
+ * Check the media sector size
+ */
+ if (ioctl(fd, DKIOCGMEDIAINFO, &dkminfo) != -1) {
+ if (dkminfo.dki_lbsize != 0 &&
+ ISP2(dkminfo.dki_lbsize / DEV_BSIZE) &&
+ dkminfo.dki_lbsize != DEV_BSIZE) {
+ (void) fprintf(stderr,
+ gettext("The device sector size %u is not "
+ "supported by pcfs!\n"), dkminfo.dki_lbsize);
+ (void) close(fd);
+ exit(2);
+ }
+ }
+
+ rv = efi_alloc_and_read(fd, &gpt);
+ /*
+ * We should see only VT_EINVAL, VT_EIO and VT_ERROR.
+ * VT_EINVAL is for the case there is no GPT label.
+ * VT_ERROR will happen if device does no support the ioctl, so
+ * we will exit only in case of VT_EIO and unknown value of rv.
+ */
+ if (rv < 0 && rv != VT_EINVAL && rv != VT_ERROR) {
+ switch (rv) {
+ case VT_EIO:
+ (void) fprintf(stderr,
+ gettext("IO Error reading EFI label\n"));
+ break;
+ default:
+ (void) fprintf(stderr,
+ gettext("Unknown Error %d reading EFI label\n"),
+ rv);
+ break;
+ }
+ (void) close(fd);
+ exit(2);
+ }
+ if (rv >= 0) {
+ DontUseFdisk = 1;
+ if (*suffix != NULL) {
+ (void) fprintf(stderr,
+ gettext("Can not use drive specifier \"%s\" with "
+ "GPT partitioning.\n"), *suffix);
+ efi_free(gpt);
+ (void) close(fd);
+ exit(2);
+ }
+ /* Can not use whole disk, 7 is GPT minor node "wd" */
+ if (rv == 7) {
+ (void) fprintf(stderr,
+ gettext("Device name must indicate a "
+ "partition: %s\n"), actualdisk);
+ efi_free(gpt);
+ (void) close(fd);
+ exit(2);
+ }
+
+ if (GetSize == 1) {
+ TotSize = gpt->efi_parts[rv].p_size;
+ GetSize = 0;
+ }
+
+ if (GetBPF == 1) {
+ if (GetResrvd == 1) {
+ /* FAT32 has 32 reserved sectors */
+ reserved = 32;
+ } else {
+ reserved = Resrvd;
+ }
+ /*
+ * The type of FAT is determined by the size of
+ * the partition - reserved sectors.
+ * The calculation is based on logic used in
+ * compute_cluster_size() and therefore we will not
+ * get into error situation when
+ * compute_cluster_size() will be called.
+ */
+ if (TotSize - reserved < FAT16_MAX_CLUSTERS) {
+ if (GetResrvd == 1)
+ reserved = 1;
+
+ if (TotSize - reserved < FAT12_MAX_CLUSTERS) {
+ int spc;
+ MakeFAT32 = 0;
+ Fatentsize = 12;
+ /*
+ * compute sectors per cluster
+ * for fat12
+ */
+ for (spc = 1; spc <= 64;
+ spc = spc * 2) {
+ if (TotSize - reserved <
+ spc * FAT12_MAX_CLUSTERS)
+ break;
+ }
+ if (GetSPC == 1) {
+ GetSPC = 0;
+ SecPerClust = spc;
+ }
+ } else {
+ MakeFAT32 = 0;
+ Fatentsize = 16;
+ }
+ } else {
+ MakeFAT32 = 1;
+ Fatentsize = 32;
+ }
+ }
+ efi_free(gpt);
+ }
+ return (fd);
+}
+
+/*
* open_and_seek
*
* Open the requested 'dev_name'. Seek to point where
@@ -2232,8 +2379,6 @@ open_and_seek(char *dn, bpb_t *wbpb, off64_t *seekto)
{
struct fd_char fdchar;
struct dk_geom dg;
- struct stat di;
- struct dk_minfo dkminfo;
char *actualdisk = NULL;
char *suffix = NULL;
int fd;
@@ -2271,9 +2416,10 @@ open_and_seek(char *dn, bpb_t *wbpb, off64_t *seekto)
* that scenario. Otherwise, try to find the device.
*/
if (Outputtofile)
- return (fd = prepare_image_file(dn, wbpb));
+ return (prepare_image_file(dn, wbpb));
- actualdisk = stat_actual_disk(dn, &di, &suffix);
+ /* Collect info about device */
+ fd = getdiskinfo(dn, &suffix);
/*
* Sanity check. If we've been provided a partition-specifying
@@ -2285,44 +2431,14 @@ open_and_seek(char *dn, bpb_t *wbpb, off64_t *seekto)
gettext("Using 'nofdisk' option precludes "
"appending logical drive\nspecifier "
"to the device name.\n"));
- exit(2);
- }
-
- /*
- * Destination exists, now find more about it.
- */
- if (!(S_ISCHR(di.st_mode))) {
- (void) fprintf(stderr,
- gettext("\n%s: device name must indicate a "
- "character special device.\n"), actualdisk);
- exit(2);
- } else if ((fd = open(actualdisk, O_RDWR)) < 0) {
- perror(actualdisk);
- exit(2);
- }
-
- /*
- * Check the media sector size
- */
- if (ioctl(fd, DKIOCGMEDIAINFO, &dkminfo) != -1) {
- if (dkminfo.dki_lbsize != 0 &&
- ISP2(dkminfo.dki_lbsize / DEV_BSIZE) &&
- dkminfo.dki_lbsize != DEV_BSIZE) {
- (void) fprintf(stderr,
- gettext("The device sector size %u is not "
- "supported by pcfs!\n"), dkminfo.dki_lbsize);
- (void) close(fd);
- exit(1);
- }
+ goto err_out;
}
/*
* Find appropriate partition if we were requested to do so.
*/
- if (suffix && !(seek_partn(fd, suffix, wbpb, seekto))) {
- (void) close(fd);
- exit(2);
- }
+ if (suffix && !(seek_partn(fd, suffix, wbpb, seekto)))
+ goto err_out;
if (!suffix) {
/*
@@ -2338,10 +2454,9 @@ open_and_seek(char *dn, bpb_t *wbpb, off64_t *seekto)
* case, they should have given us a partition specifier.
*/
if (DontUseFdisk) {
- if (!(seek_nofdisk(fd, wbpb, seekto))) {
- (void) close(fd);
- exit(2);
- }
+ if (!(seek_nofdisk(fd, wbpb, seekto)))
+ goto err_out;
+
find_fixed_details(fd, wbpb);
} else if (ioctl(fd, FDIOGCHAR, &fdchar) == -1) {
/*
@@ -2368,8 +2483,7 @@ open_and_seek(char *dn, bpb_t *wbpb, off64_t *seekto)
lookup_floppy(&fdchar, wbpb);
} else {
partn_lecture(actualdisk);
- (void) close(fd);
- exit(2);
+ goto err_out;
}
}
} else {
@@ -2383,6 +2497,10 @@ open_and_seek(char *dn, bpb_t *wbpb, off64_t *seekto)
}
return (fd);
+
+err_out:
+ (void) close(fd);
+ exit(2);
}
/*
@@ -2967,7 +3085,7 @@ write_rest(bpb_t *wbpb, char *efn, int dfd, int sfd, int remaining)
static
void
write_fat32_bootstuff(int fd, boot_sector_t *bsp,
- struct fat_od_fsi *fsinfop, off64_t seekto)
+ struct fat_od_fsi *fsinfop, off64_t seekto)
{
if (Verbose) {
(void) printf(gettext("Dump of the fs info sector"));
@@ -3018,7 +3136,7 @@ write_fat32_bootstuff(int fd, boot_sector_t *bsp,
static
void
write_bootsects(int fd, boot_sector_t *bsp, bpb_t *wbpb,
- struct fat_od_fsi *fsinfop, off64_t seekto)
+ struct fat_od_fsi *fsinfop, off64_t seekto)
{
if (MakeFAT32) {
/* Copy our BPB into bootsec structure */