Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 26 Jun 2014 15:25:43 +0000 (UTC)
From:      Marcel Moolenaar <marcel@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-user@freebsd.org
Subject:   svn commit: r267916 - user/marcel/mkimg
Message-ID:  <201406261525.s5QFPhPB049859@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: marcel
Date: Thu Jun 26 15:25:42 2014
New Revision: 267916
URL: http://svnweb.freebsd.org/changeset/base/267916

Log:
  In vhd_write(), construct the footer and write it out. Next in line
  is the dynamic header. After that, the block allocation table and
  the actual blocks. It's for the blocks we need some infrastructure
  support, because each data block is preceeded by a bitmap that tells
  whether a sector in that block has been written, etc. The point is
  that we interleave metadata with data and we don't have good support
  functions for writing chunks of the image yet.

Modified:
  user/marcel/mkimg/vhd.c

Modified: user/marcel/mkimg/vhd.c
==============================================================================
--- user/marcel/mkimg/vhd.c	Thu Jun 26 14:24:31 2014	(r267915)
+++ user/marcel/mkimg/vhd.c	Thu Jun 26 15:25:42 2014	(r267916)
@@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/errno.h>
 #include <stdlib.h>
 #include <string.h>
+#include <time.h>
 #include <unistd.h>
 #include <uuid.h>
 
@@ -51,7 +52,8 @@ __FBSDID("$FreeBSD$");
  * o   The timestamp is seconds since 1/1/2000 12:00:00 AM UTC
  */
 
-#define	VHD_BLOCK_SIZE	4096	/* 2MB blocks */
+#define	VHD_BLOCK_SIZE	4096	/* In sectors; 2MB blocks */
+#define	VHD_SECTOR_SIZE	512
 
 struct vhd_footer {
 	char		cookie[8];
@@ -64,7 +66,7 @@ struct vhd_footer {
 #define	VHD_VERSION		0x00010000
 	uint64_t	data_offset;
 	uint32_t	timestamp;
-	char		creator_tool;
+	char		creator_tool[4];
 #define	VHD_CREATOR_TOOL_MS_VPC	"vpc "		/* Virtual PC */
 #define	VHD_CREATOR_TOOL_MS_VS	"vs  "		/* Virtual Server */
 #define	VHD_CREATOR_TOOL_FBSD	"mkim"		/* FreeBSD mkimg */
@@ -90,7 +92,8 @@ struct vhd_footer {
 	uint8_t		saved_state;
 	uint8_t		_reserved[427];
 };
-_Static_assert(sizeof(struct vhd_footer) == 512, "Wrong size for footer");
+_Static_assert(sizeof(struct vhd_footer) == VHD_SECTOR_SIZE,
+    "Wrong size for footer");
 
 struct vhd_dyn_header {
 	uint64_t	cookie;
@@ -113,7 +116,8 @@ struct vhd_dyn_header {
 	} parent_locator[8];
 	char		_reserved2[256];
 };
-_Static_assert(sizeof(struct vhd_dyn_header) == 1024, "Wrong size for header");
+_Static_assert(sizeof(struct vhd_dyn_header) == VHD_SECTOR_SIZE * 2,
+    "Wrong size for header");
 
 static int
 vhd_resize(lba_t imgsz)
@@ -124,10 +128,76 @@ vhd_resize(lba_t imgsz)
 	return (image_set_size(imgsz));
 }
 
+static uint32_t
+vhd_checksum(void *buf, size_t sz)
+{
+	uint8_t *p = buf;
+	uint32_t sum;
+	size_t ofs;
+
+	sum = 0;
+	for (ofs = 0; ofs < sz; ofs++)
+		sum += p[ofs];
+	return (~sum);
+}
+
+static uint32_t
+vhd_timestamp(void)
+{
+	time_t t;
+
+	t = time(NULL);
+	return (t - 0x386d4380);
+}
+
+static void
+vhd_uuid_enc(void *buf, const uuid_t *uuid)
+{
+	uint8_t *p = buf;
+	int i;
+
+	be32enc(p, uuid->time_low);
+	be16enc(p + 4, uuid->time_mid);
+	be16enc(p + 6, uuid->time_hi_and_version);
+	p[8] = uuid->clock_seq_hi_and_reserved;
+	p[9] = uuid->clock_seq_low;
+	for (i = 0; i < _UUID_NODE_LEN; i++)
+		p[10 + i] = uuid->node[i];
+}
+
 static int
 vhd_write(int fd)
 {
+	struct vhd_footer footer;
+	struct vhd_dyn_header header;
+	uuid_t id;
+	uint64_t imgsz;
+
+	imgsz = image_get_size() * secsz;
+
+	memset(&footer, 0, sizeof(footer));
+	strncpy(footer.cookie, VHD_COOKIE_FREEBSD, sizeof(footer.cookie));
+	be32enc(&footer.features, VHD_FEATURES_RESERVED);
+	be32enc(&footer.version, VHD_VERSION);
+	be32enc(&footer.data_offset, VHD_SECTOR_SIZE);
+	be32enc(&footer.timestamp, vhd_timestamp());
+	strncpy(footer.creator_tool, VHD_CREATOR_TOOL_FBSD,
+	    sizeof(footer.creator_tool));
+	be32enc(&footer.creator_version, VHD_CREATOR_VERS_FBSD);
+	strncpy(footer.creator_os, VHD_CREATOR_OS_FREEBSD,
+	    sizeof(footer.creator_os));
+	be64enc(&footer.original_size, imgsz);
+	be64enc(&footer.current_size, imgsz);
+	/* XXX Geometry */
+	be32enc(&footer.disk_type, VHD_DISK_TYPE_DYNAMIC);
+	uuidgen(&id, 1);
+	vhd_uuid_enc(&footer.id, &id);
+	be32enc(&footer.checksum, vhd_checksum(&footer, sizeof(footer)));
+
+	if (sparse_write(fd, &footer, VHD_SECTOR_SIZE) < 0)
+		return (errno);
 
+	memset(&header, 0, sizeof(header));
 	return (image_copyout(fd));
 }
 



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