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,
 };
 
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to