about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorjncronin <jncronin@21779fe5-bacf-4c11-b3ef-82bd0e1f58e8>2014-07-14 21:05:41 +0000
committerjncronin <jncronin@21779fe5-bacf-4c11-b3ef-82bd0e1f58e8>2014-07-14 21:05:41 +0000
commita7c0c3ce10b4a6a9a481ea486da625eac6ae3d58 (patch)
treede8bca74f74ffd62d970fbf2b2675d4b529b01a2
downloadmkgpt-a7c0c3ce10b4a6a9a481ea486da625eac6ae3d58.tar.gz
git-svn-id: https://www.tysos.org/svn/branches/tysila3/tload/mkgpt@549 21779fe5-bacf-4c11-b3ef-82bd0e1f58e8
-rw-r--r--Makefile.am12
-rw-r--r--configure.ac32
-rw-r--r--crc32.c328
-rw-r--r--fstypes.c64
-rw-r--r--fstypes.h35
-rw-r--r--guid.c203
-rw-r--r--guid.h44
-rw-r--r--mkgpt.c568
-rw-r--r--mkgpt.vcxproj78
-rw-r--r--part.h44
10 files changed, 1408 insertions, 0 deletions
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..04f820f
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,12 @@
+AUTOMAKE_OPTIONS = foreign subdir-objects
+
+CXXFLAGS = @CXXFLAGS@
+CPPFLAGS = @CPPFLAGS@
+CFLAGS = @CFLAGS@ -Wall -Wextra -pedantic -Werror -std=gnu99
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+
+bin_PROGRAMS = mkgpt
+mkgpt_SOURCES = mkgpt.c crc32.c fstypes.c guid.c
+noinst_HEADERS = fstypes.h guid.h part.h mkgpt.vcxproj
+
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..2e3c0b3
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,32 @@
+#                                               -*- Autoconf -*-
+# Process this file with autoconf to produce a configure script.
+AC_PREREQ([2.68])
+AC_INIT([mkgpt], [0.1])
+AM_INIT_AUTOMAKE
+AC_CONFIG_SRCDIR([mkgpt.c])
+
+# Checks for programs.
+AC_PROG_CC
+
+# Checks for libraries.
+
+# Checks for header files.
+AC_CHECK_HEADERS([stdint.h stdlib.h string.h stddef.h time.h])
+
+# Checks for typedefs, structures, and compiler characteristics.
+AC_C_INLINE
+AC_TYPE_INT16_T
+AC_TYPE_INT32_T
+AC_TYPE_OFF_T
+AC_TYPE_SIZE_T
+AC_TYPE_UINT16_T
+AC_TYPE_UINT32_T
+AC_TYPE_UINT64_T
+AC_TYPE_UINT8_T
+
+# Checks for library functions.
+AC_FUNC_MALLOC
+AC_CHECK_FUNCS([memset])
+
+AC_CONFIG_FILES([Makefile])
+AC_OUTPUT
diff --git a/crc32.c b/crc32.c
new file mode 100644
index 0000000..4d9eb02
--- /dev/null
+++ b/crc32.c
@@ -0,0 +1,328 @@
+/*++

+

+Copyright (c) 2004, Intel Corporation. All rights reserved.<BR>

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  crc32.c

+

+Abstract:

+

+  CalcuateCrc32 routine.

+

+  Modified to avoid EFI dependencies for mkgpt

+  

+--*/

+

+#include <stdlib.h>

+#include <stdint.h>

+

+uint32_t  mCrcTable[256] = {

+  0x00000000,

+  0x77073096,

+  0xEE0E612C,

+  0x990951BA,

+  0x076DC419,

+  0x706AF48F,

+  0xE963A535,

+  0x9E6495A3,

+  0x0EDB8832,

+  0x79DCB8A4,

+  0xE0D5E91E,

+  0x97D2D988,

+  0x09B64C2B,

+  0x7EB17CBD,

+  0xE7B82D07,

+  0x90BF1D91,

+  0x1DB71064,

+  0x6AB020F2,

+  0xF3B97148,

+  0x84BE41DE,

+  0x1ADAD47D,

+  0x6DDDE4EB,

+  0xF4D4B551,

+  0x83D385C7,

+  0x136C9856,

+  0x646BA8C0,

+  0xFD62F97A,

+  0x8A65C9EC,

+  0x14015C4F,

+  0x63066CD9,

+  0xFA0F3D63,

+  0x8D080DF5,

+  0x3B6E20C8,

+  0x4C69105E,

+  0xD56041E4,

+  0xA2677172,

+  0x3C03E4D1,

+  0x4B04D447,

+  0xD20D85FD,

+  0xA50AB56B,

+  0x35B5A8FA,

+  0x42B2986C,

+  0xDBBBC9D6,

+  0xACBCF940,

+  0x32D86CE3,

+  0x45DF5C75,

+  0xDCD60DCF,

+  0xABD13D59,

+  0x26D930AC,

+  0x51DE003A,

+  0xC8D75180,

+  0xBFD06116,

+  0x21B4F4B5,

+  0x56B3C423,

+  0xCFBA9599,

+  0xB8BDA50F,

+  0x2802B89E,

+  0x5F058808,

+  0xC60CD9B2,

+  0xB10BE924,

+  0x2F6F7C87,

+  0x58684C11,

+  0xC1611DAB,

+  0xB6662D3D,

+  0x76DC4190,

+  0x01DB7106,

+  0x98D220BC,

+  0xEFD5102A,

+  0x71B18589,

+  0x06B6B51F,

+  0x9FBFE4A5,

+  0xE8B8D433,

+  0x7807C9A2,

+  0x0F00F934,

+  0x9609A88E,

+  0xE10E9818,

+  0x7F6A0DBB,

+  0x086D3D2D,

+  0x91646C97,

+  0xE6635C01,

+  0x6B6B51F4,

+  0x1C6C6162,

+  0x856530D8,

+  0xF262004E,

+  0x6C0695ED,

+  0x1B01A57B,

+  0x8208F4C1,

+  0xF50FC457,

+  0x65B0D9C6,

+  0x12B7E950,

+  0x8BBEB8EA,

+  0xFCB9887C,

+  0x62DD1DDF,

+  0x15DA2D49,

+  0x8CD37CF3,

+  0xFBD44C65,

+  0x4DB26158,

+  0x3AB551CE,

+  0xA3BC0074,

+  0xD4BB30E2,

+  0x4ADFA541,

+  0x3DD895D7,

+  0xA4D1C46D,

+  0xD3D6F4FB,

+  0x4369E96A,

+  0x346ED9FC,

+  0xAD678846,

+  0xDA60B8D0,

+  0x44042D73,

+  0x33031DE5,

+  0xAA0A4C5F,

+  0xDD0D7CC9,

+  0x5005713C,

+  0x270241AA,

+  0xBE0B1010,

+  0xC90C2086,

+  0x5768B525,

+  0x206F85B3,

+  0xB966D409,

+  0xCE61E49F,

+  0x5EDEF90E,

+  0x29D9C998,

+  0xB0D09822,

+  0xC7D7A8B4,

+  0x59B33D17,

+  0x2EB40D81,

+  0xB7BD5C3B,

+  0xC0BA6CAD,

+  0xEDB88320,

+  0x9ABFB3B6,

+  0x03B6E20C,

+  0x74B1D29A,

+  0xEAD54739,

+  0x9DD277AF,

+  0x04DB2615,

+  0x73DC1683,

+  0xE3630B12,

+  0x94643B84,

+  0x0D6D6A3E,

+  0x7A6A5AA8,

+  0xE40ECF0B,

+  0x9309FF9D,

+  0x0A00AE27,

+  0x7D079EB1,

+  0xF00F9344,

+  0x8708A3D2,

+  0x1E01F268,

+  0x6906C2FE,

+  0xF762575D,

+  0x806567CB,

+  0x196C3671,

+  0x6E6B06E7,

+  0xFED41B76,

+  0x89D32BE0,

+  0x10DA7A5A,

+  0x67DD4ACC,

+  0xF9B9DF6F,

+  0x8EBEEFF9,

+  0x17B7BE43,

+  0x60B08ED5,

+  0xD6D6A3E8,

+  0xA1D1937E,

+  0x38D8C2C4,

+  0x4FDFF252,

+  0xD1BB67F1,

+  0xA6BC5767,

+  0x3FB506DD,

+  0x48B2364B,

+  0xD80D2BDA,

+  0xAF0A1B4C,

+  0x36034AF6,

+  0x41047A60,

+  0xDF60EFC3,

+  0xA867DF55,

+  0x316E8EEF,

+  0x4669BE79,

+  0xCB61B38C,

+  0xBC66831A,

+  0x256FD2A0,

+  0x5268E236,

+  0xCC0C7795,

+  0xBB0B4703,

+  0x220216B9,

+  0x5505262F,

+  0xC5BA3BBE,

+  0xB2BD0B28,

+  0x2BB45A92,

+  0x5CB36A04,

+  0xC2D7FFA7,

+  0xB5D0CF31,

+  0x2CD99E8B,

+  0x5BDEAE1D,

+  0x9B64C2B0,

+  0xEC63F226,

+  0x756AA39C,

+  0x026D930A,

+  0x9C0906A9,

+  0xEB0E363F,

+  0x72076785,

+  0x05005713,

+  0x95BF4A82,

+  0xE2B87A14,

+  0x7BB12BAE,

+  0x0CB61B38,

+  0x92D28E9B,

+  0xE5D5BE0D,

+  0x7CDCEFB7,

+  0x0BDBDF21,

+  0x86D3D2D4,

+  0xF1D4E242,

+  0x68DDB3F8,

+  0x1FDA836E,

+  0x81BE16CD,

+  0xF6B9265B,

+  0x6FB077E1,

+  0x18B74777,

+  0x88085AE6,

+  0xFF0F6A70,

+  0x66063BCA,

+  0x11010B5C,

+  0x8F659EFF,

+  0xF862AE69,

+  0x616BFFD3,

+  0x166CCF45,

+  0xA00AE278,

+  0xD70DD2EE,

+  0x4E048354,

+  0x3903B3C2,

+  0xA7672661,

+  0xD06016F7,

+  0x4969474D,

+  0x3E6E77DB,

+  0xAED16A4A,

+  0xD9D65ADC,

+  0x40DF0B66,

+  0x37D83BF0,

+  0xA9BCAE53,

+  0xDEBB9EC5,

+  0x47B2CF7F,

+  0x30B5FFE9,

+  0xBDBDF21C,

+  0xCABAC28A,

+  0x53B39330,

+  0x24B4A3A6,

+  0xBAD03605,

+  0xCDD70693,

+  0x54DE5729,

+  0x23D967BF,

+  0xB3667A2E,

+  0xC4614AB8,

+  0x5D681B02,

+  0x2A6F2B94,

+  0xB40BBE37,

+  0xC30C8EA1,

+  0x5A05DF1B,

+  0x2D02EF8D

+};

+

+int

+CalculateCrc32 (

+  uint8_t                           *Data,

+  size_t                            DataSize,

+  uint32_t							*CrcOut

+  )

+/*++

+

+Routine Description:

+

+  The CalculateCrc32 routine.

+

+Arguments:

+

+  Data        - The buffer contaning the data to be processed

+  DataSize    - The size of data to be processed

+  CrcOut      - A pointer to the caller allocated UINT32 that on

+                contains the CRC32 checksum of Data

+

+Returns:

+

+  EFI_SUCCESS               - Calculation is successful.

+  EFI_INVALID_PARAMETER     - Data / CrcOut = NULL, or DataSize = 0

+

+--*/

+{

+  uint32_t  Crc;

+  size_t   Index;

+  uint8_t   *Ptr;

+

+  if ((DataSize == 0) || (Data == NULL) || (CrcOut == NULL)) {

+    return -1;

+  }

+

+  Crc = 0xffffffff;

+  for (Index = 0, Ptr = Data; Index < DataSize; Index++, Ptr++) {

+    Crc = (Crc >> 8) ^ mCrcTable[(uint8_t) Crc ^ *Ptr];

+  }

+

+  *CrcOut = Crc ^ 0xffffffff;

+

+  return 0;

+}

diff --git a/fstypes.c b/fstypes.c
new file mode 100644
index 0000000..4dc44e3
--- /dev/null
+++ b/fstypes.c
@@ -0,0 +1,64 @@
+/* Copyright (C) 2014 by John Cronin

+ *

+ * Permission is hereby granted, free of charge, to any person obtaining a copy

+ * of this software and associated documentation files (the "Software"), to deal

+ * in the Software without restriction, including without limitation the rights

+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell

+ * copies of the Software, and to permit persons to whom the Software is

+ * furnished to do so, subject to the following conditions:

+

+ * The above copyright notice and this permission notice shall be included in

+ * all copies or substantial portions of the Software.

+

+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR

+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,

+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE

+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER

+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,

+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN

+ * THE SOFTWARE.

+ */

+

+#include "guid.h"

+#include <stddef.h>

+

+GUID fstypes[512];

+char *fsnames[512];

+

+#include "fstypes.h"

+

+void init_fstypes()

+{

+	int i;

+

+	for(i = 0; i < 512; i++)

+	{

+		string_to_guid(&fstypes[i], "00000000-0000-0000-0000-000000000000");

+		fsnames[i] = NULL;

+	}

+

+	string_to_guid(&fstypes[FSTYPE_EFI_SYSTEM], "C12A7328-F81F-11D2-BA4B-00A0C93EC93B");

+	fsnames[FSTYPE_EFI_SYSTEM] = "system";

+	string_to_guid(&fstypes[FSTYPE_BIOS_BOOT], "21686148-6449-6E6F-744E-656564454649");

+	fsnames[FSTYPE_BIOS_BOOT] = "bios";

+	string_to_guid(&fstypes[0x01], "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7");

+	fsnames[0x01] = "fat12";

+	string_to_guid(&fstypes[0x04], "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7");

+	fsnames[0x04] = "fat16";

+	string_to_guid(&fstypes[0x06], "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7");

+	fsnames[0x06] = "fat16b";

+	string_to_guid(&fstypes[0x07], "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7");

+	fsnames[0x07] = "ntfs";

+	string_to_guid(&fstypes[0x0b], "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7");

+	fsnames[0x0b] = "fat32";

+	string_to_guid(&fstypes[0x0c], "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7");

+	fsnames[0x0c] = "fat32x";

+	string_to_guid(&fstypes[0x0e], "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7");

+	fsnames[0x0e] = "fat16x";

+	string_to_guid(&fstypes[0x28], "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7");

+	fsnames[0x28] = "fat16+";

+	string_to_guid(&fstypes[0x29], "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7");

+	fsnames[0x29] = "fat32+";

+	string_to_guid(&fstypes[0x83], "0FC63DAF-8483-4772-8E79-3D69D8477DE4");

+	fsnames[0x83] = "linux";

+}

diff --git a/fstypes.h b/fstypes.h
new file mode 100644
index 0000000..6267701
--- /dev/null
+++ b/fstypes.h
@@ -0,0 +1,35 @@
+/* Copyright (C) 2014 by John Cronin

+ *

+ * Permission is hereby granted, free of charge, to any person obtaining a copy

+ * of this software and associated documentation files (the "Software"), to deal

+ * in the Software without restriction, including without limitation the rights

+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell

+ * copies of the Software, and to permit persons to whom the Software is

+ * furnished to do so, subject to the following conditions:

+

+ * The above copyright notice and this permission notice shall be included in

+ * all copies or substantial portions of the Software.

+

+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR

+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,

+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE

+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER

+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,

+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN

+ * THE SOFTWARE.

+ */

+

+#ifndef FSTYPES_H

+#define FSTYPES_H

+

+#include "guid.h"

+

+extern GUID fstypes[512];

+extern char *fsnames[512];

+

+#define FSTYPE_EFI_SYSTEM		256

+#define FSTYPE_BIOS_BOOT		257

+

+void init_fstypes();

+

+#endif

diff --git a/guid.c b/guid.c
new file mode 100644
index 0000000..8a71b7e
--- /dev/null
+++ b/guid.c
@@ -0,0 +1,203 @@
+/* Copyright (C) 2014 by John Cronin

+ *

+ * Permission is hereby granted, free of charge, to any person obtaining a copy

+ * of this software and associated documentation files (the "Software"), to deal

+ * in the Software without restriction, including without limitation the rights

+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell

+ * copies of the Software, and to permit persons to whom the Software is

+ * furnished to do so, subject to the following conditions:

+

+ * The above copyright notice and this permission notice shall be included in

+ * all copies or substantial portions of the Software.

+

+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR

+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,

+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE

+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER

+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,

+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN

+ * THE SOFTWARE.

+ */

+

+#include <stddef.h>

+#include <stdio.h>

+#include <stdlib.h>

+#include <time.h>

+

+#ifdef WINDOWS

+#include <windows.h>

+#include <wincrypt.h>

+#endif

+

+#include "guid.h"

+

+#define GUID_FMT "%08X-%04hX-%04hX-%02hhX%02hhX-%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX"

+

+static int rnd_init = 0;

+

+int guid_to_string(char *str, GUID *guid)

+{

+	if(guid == NULL)

+	{

+		fprintf(stderr, "guid_to_string: guid is null\n");

+		return -1;

+	}

+	if(str == NULL)

+	{

+		fprintf(stderr, "guid_to_string: str is null\n");

+		return -1;

+	}

+

+	sprintf(str, GUID_FMT, guid->data1, guid->data2, guid->data3, guid->data4[0], guid->data4[1],

+		guid->data4[2], guid->data4[3], guid->data4[4], guid->data4[5], guid->data4[6], guid->data4[7]);

+

+	return 0;

+}

+

+int string_to_guid(GUID *guid, char *str)

+{

+	if(guid == NULL)

+	{

+		fprintf(stderr, "string_to_guid: guid is null\n");

+		return -1;

+	}

+	if(str == NULL)

+	{

+		fprintf(stderr, "string_to_guid: str is null\n");

+		return -1;

+	}

+

+	sscanf(str, GUID_FMT, &guid->data1, &guid->data2, &guid->data3, &guid->data4[0], &guid->data4[1],

+		&guid->data4[2], &guid->data4[3], &guid->data4[4], &guid->data4[5], &guid->data4[6], &guid->data4[7]);

+

+	return 0;

+}

+

+int guid_to_bytestring(uint8_t *bytes, GUID *guid)

+{

+	int i;

+

+	if(guid == NULL)

+	{

+		fprintf(stderr, "guid_to_bytestring: guid is null\n");

+		return -1;

+	}

+	if(bytes == NULL)

+	{

+		fprintf(stderr, "guid_to_bytestring: bytes is null\n");

+		return -1;

+	}

+

+	*(uint32_t *)&bytes[0] = guid->data1;

+	*(uint16_t *)&bytes[4] = guid->data2;

+	*(uint16_t *)&bytes[6] = guid->data3;

+	for(i = 0; i < 8; i++)

+		bytes[8 + i] = guid->data4[i];

+

+	return 0;

+}

+

+int guid_is_zero(GUID *guid)

+{

+	int i;

+

+	if(guid->data1 != 0)

+		return 0;

+	if(guid->data2 != 0)

+		return 0;

+	if(guid->data3 != 0)

+		return 0;

+	for(i = 0; i < 8; i++)

+	{

+		if(guid->data4[i] != 0)

+			return 0;

+	}

+	return 1;

+}

+

+void init_rnd()

+{

+	/* Attempt to initialise the random number generator */

+	FILE *rnd = fopen("/dev/random", "r");

+	if(rnd != NULL)

+	{

+		unsigned int seed;

+		if(fread(&seed, 1, sizeof(unsigned int), rnd) == sizeof(unsigned int))

+		{

+			srand(seed);

+			fclose(rnd);

+			rnd_init = 1;

+			return;

+		}

+

+		fclose(rnd);

+	}

+

+#ifdef WINDOWS

+	{

+		HCRYPTPROV prov = 0;

+		if(!CryptAcquireContext(&prov, NULL, NULL, PROV_INTEL_SEC, CRYPT_VERIFYCONTEXT))

+		{

+			if(!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))

+				prov = 0;

+		}

+

+		if(prov != 0)

+		{

+			unsigned int seed;

+			CryptGenRandom(prov, sizeof(unsigned int), (BYTE *)&seed);

+			srand(seed);

+			rnd_init = 1;

+			return;

+		}

+	}

+#endif

+

+	{

+		time_t t = time(NULL);

+		struct tm *tmptr = gmtime(&t);

+		int seed = tmptr->tm_hour;

+		seed <<= 3;

+		seed ^= tmptr->tm_isdst;

+		seed <<= 3;

+		seed ^= tmptr->tm_mday;

+		seed <<= 3;

+		seed ^= tmptr->tm_min;

+		seed <<= 3;

+		seed ^= tmptr->tm_mon;

+		seed <<= 3;

+		seed ^= tmptr->tm_sec;

+		seed <<= 3;

+		seed ^= tmptr->tm_wday;

+		seed <<= 3;

+		seed ^= tmptr->tm_yday;

+		seed <<= 3;

+		seed ^= tmptr->tm_year;

+

+		srand((unsigned int)seed);

+		rnd_init = 1;

+		return;

+	}

+}

+

+uint8_t rnd_byte()

+{

+	if(rnd_init == 0)

+		init_rnd();

+

+	return (uint8_t)(rand() & 0xff);

+}

+

+int random_guid(GUID *guid)

+{

+	int i;

+

+	guid->data1 = (uint32_t)rnd_byte() | (((uint32_t)rnd_byte()) << 8) |

+		(((uint32_t)rnd_byte()) << 16) | (((uint32_t)rnd_byte()) << 24);

+	guid->data2 = (uint16_t)rnd_byte() | (((uint16_t)rnd_byte()) << 8);

+	guid->data3 = (uint16_t)rnd_byte() | (((uint16_t)((rnd_byte() & 0x0f) | 0x40)) << 8);

+	for(i = 0; i < 8; i++)

+		guid->data4[i] = rnd_byte();

+

+	return 0;

+}

diff --git a/guid.h b/guid.h
new file mode 100644
index 0000000..95a5e37
--- /dev/null
+++ b/guid.h
@@ -0,0 +1,44 @@
+/* Copyright (C) 2014 by John Cronin

+ *

+ * Permission is hereby granted, free of charge, to any person obtaining a copy

+ * of this software and associated documentation files (the "Software"), to deal

+ * in the Software without restriction, including without limitation the rights

+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell

+ * copies of the Software, and to permit persons to whom the Software is

+ * furnished to do so, subject to the following conditions:

+

+ * The above copyright notice and this permission notice shall be included in

+ * all copies or substantial portions of the Software.

+

+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR

+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,

+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE

+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER

+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,

+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN

+ * THE SOFTWARE.

+ */

+

+#ifndef GUID_H

+#define GUID_H

+

+#include <stdint.h>

+

+typedef struct _guid

+{

+	uint32_t data1;

+	uint16_t data2;

+	uint16_t data3;

+	uint8_t data4[8];

+} GUID;

+

+#define GUID_STRING_LENGTH		36

+#define GUID_BYTESTRING_LENGTH	16

+

+int guid_to_string(char *str, GUID *guid);

+int string_to_guid(GUID *guid, char *str);

+int guid_to_bytestring(uint8_t *bytes, GUID *guid);

+int random_guid(GUID *guid);

+int guid_is_zero(GUID *guid);

+

+#endif

diff --git a/mkgpt.c b/mkgpt.c
new file mode 100644
index 0000000..6ca6423
--- /dev/null
+++ b/mkgpt.c
@@ -0,0 +1,568 @@
+/* Copyright (C) 2014 by John Cronin

+ *

+ * Permission is hereby granted, free of charge, to any person obtaining a copy

+ * of this software and associated documentation files (the "Software"), to deal

+ * in the Software without restriction, including without limitation the rights

+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell

+ * copies of the Software, and to permit persons to whom the Software is

+ * furnished to do so, subject to the following conditions:

+

+ * The above copyright notice and this permission notice shall be included in

+ * all copies or substantial portions of the Software.

+

+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR

+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,

+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE

+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER

+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,

+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN

+ * THE SOFTWARE.

+ */

+

+#include "guid.h"

+#include "part.h"

+#include "fstypes.h"

+#include <stddef.h>

+#include <stdio.h>

+#include <string.h>

+#include <stdlib.h>

+#include <assert.h>

+#include <errno.h>

+#include <limits.h>

+

+void dump_help(char *fname);

+int check_parts();

+int parse_opts(int argc, char **argv);

+int parse_guid(char *str, GUID *guid);

+void write_output();

+

+int CalculateCrc32 (uint8_t *Data, size_t DataSize, uint32_t *CrcOut);

+

+size_t sect_size = 512;

+long image_sects = 0;

+PART *first_part = NULL;

+PART *last_part = NULL;

+FILE *output = NULL;

+GUID disk_guid;

+int part_count;

+int header_sectors;

+int first_usable_sector;

+int secondary_headers_sect;

+int secondary_gpt_sect;

+

+int main(int argc, char **argv)

+{

+	init_fstypes();

+	random_guid(&disk_guid);

+

+	if(parse_opts(argc, argv) != 0)

+		return -1;

+	

+	if(output == NULL)

+	{

+		fprintf(stderr, "no output file specifed\n");

+		dump_help(argv[0]);

+		return -1;

+	}

+	if(first_part == NULL)

+	{

+		fprintf(stderr, "no partitions specified\n");

+		dump_help(argv[0]);

+		return -1;

+	}

+

+	if(check_parts() != 0)

+		return -1;

+

+	write_output();

+	fclose(output);

+

+	return 0;

+}

+

+int parse_opts(int argc, char **argv)

+{

+	int i = 1;

+	int cur_part_id = 0;

+	PART *cur_part = NULL;

+

+	/* First, parse global options */

+	while(i < argc)

+	{

+		if(!strcmp(argv[i], "--output") || !strcmp(argv[i], "-o"))

+		{

+			i++;

+			if(i == argc || argv[i][0] == '-')

+			{

+				fprintf(stderr, "no output file specified\n");

+				return -1;

+			}

+

+			output = fopen(argv[i], "w+");

+			if(output == NULL)

+			{

+				fprintf(stderr, "unable to open %s for writing (%s)\n", argv[i],

+					strerror(errno));

+				return -1;

+			}

+			i++;

+		}

+		else if(!strcmp(argv[i], "--disk-guid"))

+		{

+			i++;

+			if(i == argc || argv[i][0] == '-')

+			{

+				fprintf(stderr, "no disk guid file specified\n");

+				return -1;

+			}

+

+			if(parse_guid(argv[i], &disk_guid) != 0)

+			{

+				fprintf(stderr, "invalid disk uuid (%s)\n", argv[i]);

+				return -1;

+			}

+			

+			i++;

+		}

+		else if(!strcmp(argv[i], "--help") || !strcmp(argv[i], "-h"))

+		{

+			dump_help(argv[0]);

+			return -1;

+		}

+		else if(!strcmp(argv[i], "--sector-size"))

+		{

+			i++;

+			if(i == argc || argv[i][0] == '-')

+			{

+				fprintf(stderr, "sector size not specified\n");

+				return -1;

+			}

+		

+			sect_size = atoi(argv[i]);

+

+			if(sect_size < 512 || sect_size > 4096 || sect_size % 512)

+			{

+				fprintf(stderr, "invalid sector size (%zu) - must be >= 512 and <= 4096 and "

+					"a multiple of 512", sect_size);

+				return -1;

+			}

+			i++;

+		}

+		else if(!strcmp(argv[i], "--image-size"))

+		{

+			i++;

+			if(i == argc || argv[i][0] == '-')

+			{

+				fprintf(stderr, "image size not specified\n");

+				return -1;

+			}

+		

+			image_sects = atoi(argv[i]);

+

+			i++;		

+		}

+		else if(!strcmp(argv[i], "--part") || !strcmp(argv[i], "-p"))

+			break;

+		else

+		{

+			fprintf(stderr, "unknown argument - %s\n", argv[i]);

+			dump_help(argv[0]);

+			return i;

+		}

+	}

+

+	/* Now parse partitions */

+	while(i < argc)

+	{

+		if(!strcmp(argv[i], "--part") || !strcmp(argv[i], "-p"))

+		{

+			/* Store the current partition data if there is one */

+			if(cur_part != NULL)

+			{

+				if(last_part == NULL)

+				{

+					first_part = last_part = cur_part;

+					cur_part->next = NULL;

+				}

+				else

+				{

+					last_part->next = cur_part;

+					last_part = cur_part;

+					cur_part->next = NULL;

+				}

+			}

+

+			/* Allocate a new partition structure */

+			cur_part = (PART *)malloc(sizeof(PART));

+			if(cur_part == NULL)

+			{

+				fprintf(stderr, "out of memory allocating partition structure\n");

+				return -1;

+			}

+			memset(cur_part, 0, sizeof(PART));

+			cur_part_id++;

+			cur_part->id = cur_part_id;

+

+			/* Get the filename of the partition image */

+			i++;

+			if(i == argc || argv[i][0] == '-')

+			{

+				fprintf(stderr, "no partition image specified for partition %i\n", cur_part_id);

+				return -1;

+			}

+			cur_part->src = fopen(argv[i], "r");

+			if(cur_part->src == NULL)

+			{

+				fprintf(stderr, "unable to open partition image (%s) for partition (%i) - %s\n", argv[i],

+					cur_part_id, strerror(errno));

+				return -1;

+			}

+

+			i++;

+		}

+		else if(!strcmp(argv[i], "--name") || !strcmp(argv[i], "-n"))

+		{

+			if(cur_part == NULL)

+			{

+				fprintf(stderr, "--part must be specified before --name argument\n");

+				return -1;

+			}

+

+			i++;

+			if(i == argc || argv[i][0] == '-')

+			{

+				fprintf(stderr, "partition name not specified %i\n", cur_part_id);

+				return -1;

+			}

+

+			cur_part->name = argv[i];

+

+			i++;

+		}

+		else if(!strcmp(argv[i], "--type") || (!strcmp(argv[i], "-t")))

+		{

+			if(cur_part == NULL)

+			{

+				fprintf(stderr, "--part must be specifed before --type argument\n");

+				return -1;

+			}

+

+			i++;

+			if(i == argc || argv[i][0] == '-')

+			{

+				fprintf(stderr, "partition type not specified %i\n", cur_part_id);

+				return -1;

+			}

+

+			if(parse_guid(argv[i], &cur_part->type) != 0)

+			{

+				fprintf(stderr, "invalid partition type (%s) for partition %i\n", argv[i], cur_part_id);

+				return -1;

+			}

+			

+			i++;

+		}

+		else if(!strcmp(argv[i], "--uuid") || (!strcmp(argv[i], "-u")))

+		{

+			if(cur_part == NULL)

+			{

+				fprintf(stderr, "--part must be specifed before --uuid argument\n");

+				return -1;

+			}

+

+			i++;

+			if(i == argc || argv[i][0] == '-')

+			{

+				fprintf(stderr, "partition uuid not specified %i\n", cur_part_id);

+				return -1;

+			}

+

+			if(parse_guid(argv[i], &cur_part->uuid) != 0)

+			{

+				fprintf(stderr, "invalid partition uuid (%s) for partition %i\n", argv[i], cur_part_id);

+				return -1;

+			}

+			

+			i++;

+		}

+		else

+		{

+			fprintf(stderr, "unknown argument - %s\n", argv[i]);

+			dump_help(argv[0]);

+			return i;

+		}

+	}

+

+	if(cur_part != NULL)

+	{

+		if(last_part == NULL)

+		{

+			first_part = last_part = cur_part;

+			cur_part->next = NULL;

+		}

+		else

+		{

+			last_part->next = cur_part;

+			last_part = cur_part;

+			cur_part->next = NULL;

+		}

+	}

+

+	return 0;

+}

+

+void dump_help(char *fname)

+{

+	printf("Usage: %s -o <output_file> [-h] [--sector-size sect_size] [partition def 0] [part def 1] ... [part def n]\n",

+		fname);

+

+}

+

+int parse_guid(char *str, GUID *guid)

+{

+	long mbr_id = -1;

+	int i;

+

+	/* detect request for random uuid */

+	if(!strcmp(str, "random") || !strcmp(str, "rnd"))

+		return random_guid(guid);

+

+	/* detect mbr partition id by number */

+	mbr_id = strtol(str, NULL, 0);

+	if(mbr_id == LONG_MIN || mbr_id == LONG_MAX)

+		mbr_id = -1;

+	

+	/* detect by name */

+	for(i = 0; i < 512; i++)

+	{

+		if(fsnames[i] == NULL)

+			continue;

+		if(!strcmp(fsnames[i], str))

+		{

+			mbr_id = i;

+			break;

+		}

+	}

+

+	if(mbr_id >= 0 && mbr_id <= 511)

+	{

+		if(guid_is_zero(&fstypes[mbr_id]))

+			return -1;

+		memcpy(guid, &fstypes[mbr_id], sizeof(GUID));

+		return 0;

+	}

+

+	/* try and parse as guid */

+	return string_to_guid(guid, str);

+}

+

+int check_parts()

+{

+	/* Iterate through the partitions, checking validity */

+	int cur_part_id = 0;

+	int cur_sect;

+	PART *cur_part;

+	int header_length;

+	int needed_file_length;

+

+	/* Count partitions */

+	cur_part = first_part;

+	part_count = 0;

+	while(cur_part)

+	{

+		part_count++;

+		cur_part = cur_part->next;

+	}

+

+	/* Determine the sectors needed for MBR, GPT header and partition entries */

+	cur_sect = 2;	/* MBR + GPT header */

+	header_length = part_count * 128;

+	header_sectors = header_length / sect_size;

+	if(header_length % sect_size)

+		header_sectors++;

+	cur_sect += header_sectors;

+	first_usable_sector = cur_sect;

+

+	cur_part = first_part;

+	while(cur_part)

+	{

+		long cur_part_file_len;

+

+		cur_part_id++;

+

+		if(guid_is_zero(&cur_part->type))

+		{

+			fprintf(stderr, "partition type not specified for partition %i\n", cur_part_id);

+			return -1;

+		}

+

+		if(guid_is_zero(&cur_part->uuid))

+			random_guid(&cur_part->uuid);

+

+		if(cur_part->sect_start == 0)

+			cur_part->sect_start = cur_sect;

+		else if(cur_part->sect_start < cur_sect)

+		{

+			fprintf(stderr, "unable to start partition %i at sector %i (would conflict with other data)\n",

+				cur_part_id, cur_part->sect_start);

+			return -1;

+		}

+

+		if(cur_part->name == NULL)

+		{

+			cur_part->name = (char *)malloc(128);

+			sprintf(cur_part->name, "part%i", cur_part_id);

+		}

+

+		fseek(cur_part->src, 0, SEEK_END);

+		cur_part_file_len = ftell(cur_part->src);

+		fseek(cur_part->src, 0, SEEK_SET);

+

+		if(cur_part->sect_length == 0)

+		{

+			cur_part->sect_length = cur_part_file_len / sect_size;

+			if(cur_part_file_len % sect_size)

+				cur_part->sect_length++;

+		}

+		cur_sect = cur_part->sect_start + cur_part->sect_length;

+

+		cur_part = cur_part->next;

+	}

+

+	/* Add space for the secondary GPT */

+	needed_file_length = cur_sect + 1 + header_sectors;

+

+	if(image_sects == 0)

+		image_sects = needed_file_length;

+	else if(image_sects < needed_file_length)

+	{

+		fprintf(stderr, "requested image size (%lu) is too small to hold the partitions\n", image_sects * sect_size);

+		return -1;

+	}

+

+	secondary_headers_sect = image_sects - 1 - header_sectors;

+	secondary_gpt_sect = image_sects - 1;

+

+	return 0;

+}

+

+void write_output()

+{

+	int i;

+	uint8_t *mbr, *gpt, *gpt2, *parts, *image_buf;

+	PART *cur_part;

+

+	/* Write MBR */

+	mbr = (uint8_t *)malloc(sect_size);

+	memset(mbr, 0, sect_size);

+

+	*(uint32_t *)&mbr[446] = 0x00020000;		/* boot indicator = 0, start CHS = 0x000200 */

+	mbr[446 + 4] = 0xee;						/* OSType = GPT Protective */

+	mbr[446 + 5] = 0xff;

+	mbr[446 + 6] = 0xff;

+	mbr[446 + 7] = 0xff;						/* EndingCHS = 0xffffff */

+	*(uint32_t *)&mbr[446 + 8] = 0x1;			/* StartingLBA = 1 */

+		

+	if(image_sects > 0xffffffff)

+		*(uint32_t *)&mbr[446 + 12] = 0xffffffff;

+	else

+		*(uint32_t *)&mbr[446 + 12] = (uint32_t)image_sects - 1;

+

+	mbr[510] = 0x55; mbr[511] = 0xaa;			/* Signature */

+

+	assert(fwrite(mbr, 1, sect_size, output) == sect_size);

+

+	/* Define GPT headers */

+	gpt = (uint8_t *)malloc(sect_size);

+	assert(gpt);

+	gpt2 = (uint8_t *)malloc(sect_size);

+	assert(gpt2);

+

+	memset(gpt, 0, sect_size);

+	memset(gpt2, 0, sect_size);

+

+	*(uint64_t *)&gpt[0] = 0x5452415020494645ULL;		/* Signature */

+	*(uint32_t *)&gpt[8] = 0x00010000UL;				/* Revision */

+	*(uint32_t *)&gpt[12] = 96;							/* HeaderSize */

+	*(uint32_t *)&gpt[16] = 0;							/* HeaderCRC32 */

+	*(uint32_t *)&gpt[20] = 0;							/* Reserved */

+	*(uint64_t *)&gpt[24] = 0x1;						/* MyLBA */

+	*(uint64_t *)&gpt[32] = secondary_gpt_sect;			/* AlternateLBA */

+	*(uint64_t *)&gpt[40] = first_usable_sector;		/* FirstUsableLBA */

+	*(uint64_t *)&gpt[48] = secondary_headers_sect - 1;	/* LastUsableLBA */

+	guid_to_bytestring(&gpt[56], &disk_guid);			/* DiskGUID */

+	*(uint64_t *)&gpt[72] = 0x2;						/* PartitionEntryLBA */

+	*(uint32_t *)&gpt[80] = part_count;					/* NumberOfPartitionEntries */

+	*(uint32_t *)&gpt[84] = 128;						/* SizeOfPartitionEntry */

+	*(uint32_t *)&gpt[88] = 0;							/* PartitionEntryArrayCRC32 */

+

+	/* Define GPT partition entries */

+	parts = (uint8_t *)malloc(header_sectors * sect_size);

+	assert(parts);

+	memset(parts, 0, header_sectors * sect_size);

+

+	cur_part = first_part;

+	i = 0;

+	while(cur_part)

+	{

+		int char_id;

+

+		guid_to_bytestring(&parts[i * 128], &cur_part->type);			/* PartitionTypeGUID */

+		guid_to_bytestring(&parts[i * 128 + 16], &cur_part->uuid);		/* UniquePartitionGUID */

+		*(uint64_t *)&parts[i * 128 + 32] = cur_part->sect_start;		/* StartingLBA */

+		*(uint64_t *)&parts[i * 128 + 40] = cur_part->sect_start + cur_part->sect_length - 1;	/* EndingLBA */

+		*(uint64_t *)&parts[i * 128 + 48] = cur_part->attrs;			/* Attributes */

+

+		for(char_id = 0; char_id < (int)strlen(cur_part->name) && char_id < 35; char_id++)

+			*(uint16_t *)&parts[i * 128 + 56 + char_id * 2] = (uint16_t)cur_part->name[char_id];

+

+		i++;

+		cur_part = cur_part->next;

+	}

+

+	/* Do CRC calculations on the partition table entries and GPT headers */

+	CalculateCrc32(parts, part_count * 128, (uint32_t *)&gpt[88]);

+	CalculateCrc32(gpt, 96, (uint32_t *)&gpt[16]);

+

+	memcpy(gpt2, gpt, 96);

+	*(uint32_t *)&gpt2[16] = 0;							/* HeaderCRC32 */

+	*(uint64_t *)&gpt2[24] = secondary_gpt_sect;		/* MyLBA */

+	*(uint64_t *)&gpt2[32] = 0x1;						/* AlternateLBA */

+	*(uint64_t *)&gpt2[72] = secondary_headers_sect;	/* PartitionEntryLBA */

+	CalculateCrc32(gpt2, 96, (uint32_t *)&gpt2[16]);

+

+	/* Write primary GPT and headers */

+	assert(fwrite(gpt, 1, sect_size, output) == sect_size);

+	assert(fwrite(parts, 1, header_sectors * sect_size, output) == header_sectors * sect_size);

+

+	/* Write partitions */

+	cur_part = first_part;

+	image_buf = (uint8_t *)malloc(sect_size);

+	while(cur_part)

+	{

+		size_t bytes_read;

+		size_t bytes_written = 0;

+

+		fseek(output, cur_part->sect_start * sect_size, SEEK_SET);

+		while((bytes_read = fread(image_buf, 1, sect_size, cur_part->src)) > 0)

+		{

+			size_t bytes_to_write = bytes_read;

+

+			/* Determine how much to write */

+			if((bytes_written + bytes_to_write) > (size_t)(cur_part->sect_length * sect_size))

+				bytes_to_write = cur_part->sect_length * sect_size - bytes_written;

+

+			assert(fwrite(image_buf, 1, bytes_to_write, output) == bytes_to_write);

+

+			bytes_written += bytes_to_write;

+		}

+

+		cur_part = cur_part->next;

+	}

+

+	/* Write secondary GPT partition headers and header */

+	fseek(output, secondary_headers_sect * sect_size, SEEK_SET);

+	assert(fwrite(parts, 1, header_sectors * sect_size, output) == header_sectors * sect_size);

+	fseek(output, secondary_gpt_sect * sect_size, SEEK_SET);

+	assert(fwrite(gpt2, 1, sect_size, output) == sect_size);

+}

diff --git a/mkgpt.vcxproj b/mkgpt.vcxproj
new file mode 100644
index 0000000..c9d7e97
--- /dev/null
+++ b/mkgpt.vcxproj
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{40443019-486A-4245-8816-9F1FEEB9FE9D}</ProjectGuid>

+    <RootNamespace>mkgpt</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <PlatformToolset>v110</PlatformToolset>

+    <CharacterSet>MultiByte</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <PlatformToolset>v110</PlatformToolset>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>MultiByte</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup />

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+    </ClCompile>

+    <Link>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+    </ClCompile>

+    <Link>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemGroup>

+    <ClInclude Include="fstypes.h" />

+    <ClInclude Include="guid.h" />

+    <ClInclude Include="part.h" />

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="crc32.c" />

+    <ClCompile Include="fstypes.c" />

+    <ClCompile Include="guid.c" />

+    <ClCompile Include="mkgpt.c" />

+  </ItemGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>
\ No newline at end of file
diff --git a/part.h b/part.h
new file mode 100644
index 0000000..19d43c8
--- /dev/null
+++ b/part.h
@@ -0,0 +1,44 @@
+/* Copyright (C) 2014 by John Cronin

+ *

+ * Permission is hereby granted, free of charge, to any person obtaining a copy

+ * of this software and associated documentation files (the "Software"), to deal

+ * in the Software without restriction, including without limitation the rights

+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell

+ * copies of the Software, and to permit persons to whom the Software is

+ * furnished to do so, subject to the following conditions:

+

+ * The above copyright notice and this permission notice shall be included in

+ * all copies or substantial portions of the Software.

+

+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR

+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,

+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE

+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER

+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,

+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN

+ * THE SOFTWARE.

+ */

+

+#ifndef PART_H

+#define PART_H

+

+#include <stdio.h>

+#include <stdint.h>

+#include "guid.h"

+

+typedef struct _part

+{

+	GUID type;

+	GUID uuid;

+	int id;

+	uint64_t attrs;

+	int sect_start;

+	int sect_length;

+	long src_length;

+	char *name;

+	FILE *src;

+

+	struct _part *next;

+} PART;

+

+#endif