Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 24 Jun 2015 18:40:35 +0000 (UTC)
From:      Marcel Moolenaar <marcel@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r284773 - stable/10/usr.bin/mkimg
Message-ID:  <201506241840.t5OIeZIs008503@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: marcel
Date: Wed Jun 24 18:40:34 2015
New Revision: 284773
URL: https://svnweb.freebsd.org/changeset/base/284773

Log:
  MFC r284269, r284270, r284655, r284656, r284658:
  VHD fixes for Microsoft Azure:
  1.  Round the image size to the VHD geometry and then round to a
      multiple of 1MB.
  2.  Change the creator OS from "FBSD" to "Wi2k". It matters...
  3.  Bump the VHD tool version and the mkimg version.
  
  Approved by:	re (gjb)

Modified:
  stable/10/usr.bin/mkimg/Makefile
  stable/10/usr.bin/mkimg/format.c
  stable/10/usr.bin/mkimg/vhd.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/usr.bin/mkimg/Makefile
==============================================================================
--- stable/10/usr.bin/mkimg/Makefile	Wed Jun 24 18:29:34 2015	(r284772)
+++ stable/10/usr.bin/mkimg/Makefile	Wed Jun 24 18:40:34 2015	(r284773)
@@ -4,7 +4,7 @@ PROG=	mkimg
 SRCS=	format.c image.c mkimg.c scheme.c
 MAN=	mkimg.1
 
-MKIMG_VERSION=20150222
+MKIMG_VERSION=20150620
 mkimg.o: Makefile
 
 CFLAGS+=-DMKIMG_VERSION=${MKIMG_VERSION}

Modified: stable/10/usr.bin/mkimg/format.c
==============================================================================
--- stable/10/usr.bin/mkimg/format.c	Wed Jun 24 18:29:34 2015	(r284772)
+++ stable/10/usr.bin/mkimg/format.c	Wed Jun 24 18:40:34 2015	(r284773)
@@ -78,14 +78,10 @@ format_selected(void)
 int
 format_write(int fd)
 {
-	lba_t size;
 	int error;
 
 	if (format == NULL)
 		return (ENOSYS);
-	size = image_get_size();
-	error = format->resize(size);
-	if (!error)
-		error = format->write(fd);
+	error = format->write(fd);
 	return (error);
 }

Modified: stable/10/usr.bin/mkimg/vhd.c
==============================================================================
--- stable/10/usr.bin/mkimg/vhd.c	Wed Jun 24 18:29:34 2015	(r284772)
+++ stable/10/usr.bin/mkimg/vhd.c	Wed Jun 24 18:40:34 2015	(r284773)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2014 Marcel Moolenaar
+ * Copyright (c) 2014, 2015 Marcel Moolenaar
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -62,6 +62,12 @@ __FBSDID("$FreeBSD$");
 #define	VHD_SECTOR_SIZE	512
 #define	VHD_BLOCK_SIZE	(4096 * VHD_SECTOR_SIZE)	/* 2MB blocks */
 
+struct vhd_geom {
+	uint16_t	cylinders;
+	uint8_t		heads;
+	uint8_t		sectors;
+};
+
 struct vhd_footer {
 	uint64_t	cookie;
 #define	VHD_FOOTER_COOKIE	0x636f6e6563746978
@@ -75,14 +81,12 @@ struct vhd_footer {
 	uint32_t	creator_tool;
 #define	VHD_CREATOR_TOOL	0x2a696d67	/* FreeBSD mkimg */
 	uint32_t	creator_version;
-#define	VHD_CREATOR_VERSION	0x00010000
+#define	VHD_CREATOR_VERSION	0x00020000
 	uint32_t	creator_os;
-#define	VHD_CREATOR_OS		0x46425344
+#define	VHD_CREATOR_OS		0x5769326b	/* Wi2k */
 	uint64_t	original_size;
 	uint64_t	current_size;
-	uint16_t	cylinders;
-	uint8_t		heads;
-	uint8_t		sectors;
+	struct vhd_geom	geometry;
 	uint32_t	disk_type;
 #define	VHD_DISK_TYPE_FIXED	2
 #define	VHD_DISK_TYPE_DYNAMIC	3
@@ -111,46 +115,48 @@ vhd_checksum(void *buf, size_t sz)
 }
 
 static void
-vhd_geometry(struct vhd_footer *footer, uint64_t image_size)
+vhd_geometry(uint64_t image_size, struct vhd_geom *geom)
 {
 	lba_t imgsz;
 	long cth;
 
+	imgsz = image_size / VHD_SECTOR_SIZE;
+
 	/* Respect command line options if possible. */
 	if (nheads > 1 && nheads < 256 &&
 	    nsecs > 1 && nsecs < 256 &&
 	    ncyls < 65536) {
-		be16enc(&footer->cylinders, ncyls);
-		footer->heads = nheads;
-		footer->sectors = nsecs;
+		geom->cylinders = (ncyls != 0) ? ncyls :
+		    imgsz / (nheads * nsecs);
+		geom->heads = nheads;
+		geom->sectors = nsecs;
 		return;
 	}
 
-	imgsz = image_size / VHD_SECTOR_SIZE;
 	if (imgsz > 65536 * 16 * 255)
 		imgsz = 65536 * 16 * 255;
 	if (imgsz >= 65535 * 16 * 63) {
-		be16enc(&footer->cylinders, imgsz / (16 * 255));
-		footer->heads = 16;
-		footer->sectors = 255;
+		geom->cylinders = imgsz / (16 * 255);
+		geom->heads = 16;
+		geom->sectors = 255;
 		return;
 	}
-	footer->sectors = 17;
+	geom->sectors = 17;
 	cth = imgsz / 17;
-	footer->heads = (cth + 1023) / 1024;
-	if (footer->heads < 4)
-		footer->heads = 4;
-	if (cth >= (footer->heads * 1024) || footer->heads > 16) {
-		footer->heads = 16;
-		footer->sectors = 31;
+	geom->heads = (cth + 1023) / 1024;
+	if (geom->heads < 4)
+		geom->heads = 4;
+	if (cth >= (geom->heads * 1024) || geom->heads > 16) {
+		geom->heads = 16;
+		geom->sectors = 31;
 		cth = imgsz / 31;
 	}
-	if (cth >= (footer->heads * 1024)) {
-		footer->heads = 16;
-		footer->sectors = 63;
+	if (cth >= (geom->heads * 1024)) {
+		geom->heads = 16;
+		geom->sectors = 63;
 		cth = imgsz / 63;
 	}
-	be16enc(&footer->cylinders, cth / footer->heads);
+	geom->cylinders = cth / geom->heads;
 }
 
 static uint32_t
@@ -198,7 +204,8 @@ vhd_make_footer(struct vhd_footer *foote
 	be32enc(&footer->creator_os, VHD_CREATOR_OS);
 	be64enc(&footer->original_size, image_size);
 	be64enc(&footer->current_size, image_size);
-	vhd_geometry(footer, image_size);
+	vhd_geometry(image_size, &footer->geometry);
+	be16enc(&footer->geometry.cylinders, footer->geometry.cylinders);
 	be32enc(&footer->disk_type, disk_type);
 	mkimg_uuid(&id);
 	vhd_uuid_enc(&footer->id, &id);
@@ -206,23 +213,6 @@ vhd_make_footer(struct vhd_footer *foote
 }
 
 /*
- * We round the image size to 2MB for both the dynamic and
- * fixed VHD formats. For dynamic VHD, this is needed to
- * have the image size be a multiple of the grain size. For
- * fixed VHD this is not really needed, but makes sure that
- * it's easy to convert from fixed VHD to dynamic VHD.
- */
-static int
-vhd_resize(lba_t imgsz)
-{
-	uint64_t imagesz;
-
-	imagesz = imgsz * secsz;
-	imagesz = (imagesz + VHD_BLOCK_SIZE - 1) & ~(VHD_BLOCK_SIZE - 1);
-	return (image_set_size(imagesz / secsz));
-}
-
-/*
  * PART 2: Dynamic VHD support
  *
  * Notes:
@@ -262,6 +252,16 @@ _Static_assert(sizeof(struct vhd_dyn_hea
 #endif
 
 static int
+vhd_dyn_resize(lba_t imgsz)
+{
+	uint64_t imagesz;
+
+	imagesz = imgsz * secsz;
+	imagesz = (imagesz + VHD_BLOCK_SIZE - 1) & ~(VHD_BLOCK_SIZE - 1);
+	return (image_set_size(imagesz / secsz));
+}
+
+static int
 vhd_dyn_write(int fd)
 {
 	struct vhd_footer footer;
@@ -349,17 +349,45 @@ vhd_dyn_write(int fd)
 static struct mkimg_format vhd_dyn_format = {
 	.name = "vhd",
 	.description = "Virtual Hard Disk",
-	.resize = vhd_resize,
+	.resize = vhd_dyn_resize,
 	.write = vhd_dyn_write,
 };
 
 FORMAT_DEFINE(vhd_dyn_format);
 
 /*
- * PART 2: Fixed VHD
+ * PART 3: Fixed VHD
  */
 
 static int
+vhd_fix_resize(lba_t imgsz)
+{
+	struct vhd_geom geom;
+	int64_t imagesz;
+
+	/*
+	 * Round the image size to the pre-determined geometry that
+	 * matches the image size. This circular dependency implies
+	 * that we need to loop to handle boundary conditions.
+	 */
+	imgsz *= secsz;
+	imagesz = imgsz;
+	while (1) {
+		vhd_geometry(imagesz, &geom);
+		imagesz = (int64_t)geom.cylinders * geom.heads *
+		    geom.sectors * VHD_SECTOR_SIZE;
+		if (imagesz >= imgsz)
+			break;
+		imagesz += geom.heads * geom.sectors * VHD_SECTOR_SIZE;
+	}
+	/*
+	 * Azure demands that images are a whole number of megabytes.
+	 */
+	imagesz = (imagesz + 0xfffffULL) & ~0xfffffULL;
+	return (image_set_size(imagesz / secsz));
+}
+
+static int
 vhd_fix_write(int fd)
 {
 	struct vhd_footer footer;
@@ -379,7 +407,7 @@ vhd_fix_write(int fd)
 static struct mkimg_format vhd_fix_format = {
         .name = "vhdf",
         .description = "Fixed Virtual Hard Disk",
-        .resize = vhd_resize,
+        .resize = vhd_fix_resize,
         .write = vhd_fix_write,
 };
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201506241840.t5OIeZIs008503>