]> code.delx.au - refind/commitdiff
Added gptsync program files.
authorsrs5694 <srs5694@users.sourceforge.net>
Wed, 24 Apr 2013 23:28:33 +0000 (19:28 -0400)
committersrs5694 <srs5694@users.sourceforge.net>
Wed, 24 Apr 2013 23:28:33 +0000 (19:28 -0400)
15 files changed:
gptsync/AutoGen.c [new file with mode: 0644]
gptsync/AutoGen.h [new file with mode: 0644]
gptsync/Make.gnuefi [new file with mode: 0644]
gptsync/Make.tiano [new file with mode: 0644]
gptsync/Make.unix [new file with mode: 0644]
gptsync/Makefile [new file with mode: 0644]
gptsync/README.txt [new file with mode: 0644]
gptsync/gptsync.8 [new file with mode: 0644]
gptsync/gptsync.c [new file with mode: 0644]
gptsync/gptsync.h [new file with mode: 0644]
gptsync/gptsync.mak [new file with mode: 0644]
gptsync/lib.c [new file with mode: 0644]
gptsync/os_efi.c [new file with mode: 0644]
gptsync/os_unix.c [new file with mode: 0644]
gptsync/showpart.c [new file with mode: 0644]

diff --git a/gptsync/AutoGen.c b/gptsync/AutoGen.c
new file mode 100644 (file)
index 0000000..6423efc
--- /dev/null
@@ -0,0 +1,287 @@
+/**
+  DO NOT EDIT
+  FILE auto-generated
+  Module name:
+    AutoGen.c
+  Abstract:       Auto-generated AutoGen.c for building module or library.
+**/
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiApplicationEntryPoint.h>
+#include "AutoGen.h"
+
+GLOBAL_REMOVE_IF_UNREFERENCED GUID gEfiCallerIdGuid = {0xB8448DD1, 0xB146, 0x41B7, {0x9D, 0x66, 0x98, 0xB3, 0xA0, 0xA4, 0x04, 0xD3}};
+
+// Guids
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiAcpiTableGuid = { 0x8868E871, 0xE4F1, 0x11D3, { 0xBC, 0x22, 0x00, 0x80, 0xC7, 0x3C, 0x88, 0x81 }};
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiAcpi10TableGuid = { 0xEB9D2D30, 0x2D88, 0x11D3, { 0x9A, 0x16, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }};
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiAcpi20TableGuid = { 0x8868E871, 0xE4F1, 0x11D3, { 0xBC, 0x22, 0x00, 0x80, 0xC7, 0x3C, 0x88, 0x81 }};
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiDxeServicesTableGuid = { 0x05AD34BA, 0x6F02, 0x4214, { 0x95, 0x2E, 0x4D, 0xA0, 0x39, 0x8E, 0x2B, 0xB9 }};
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiEventReadyToBootGuid = { 0x7CE88FB3, 0x4BD7, 0x4679, { 0x87, 0xA8, 0xA8, 0xD8, 0xDE, 0xE5, 0x0D, 0x2B }};
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiEventVirtualAddressChangeGuid = { 0x13FA7698, 0xC831, 0x49C7, { 0x87, 0xEA, 0x8F, 0x43, 0xFC, 0xC2, 0x51, 0x96 }};
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiEventExitBootServicesGuid = { 0x27ABF055, 0xB1B8, 0x4C26, { 0x80, 0x48, 0x74, 0x8F, 0x37, 0xBA, 0xA2, 0xDF }};
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiFileInfoGuid = { 0x09576E92, 0x6D3F, 0x11D2, { 0x8E, 0x39, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B }};
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiFileSystemInfoGuid = { 0x09576E93, 0x6D3F, 0x11D2, { 0x8E, 0x39, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B }};
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiFileSystemVolumeLabelInfoIdGuid = { 0xDB47D7D3, 0xFE81, 0x11D3, { 0x9A, 0x35, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }};
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiGlobalVariableGuid = { 0x8BE4DF61, 0x93CA, 0x11D2, { 0xAA, 0x0D, 0x00, 0xE0, 0x98, 0x03, 0x2B, 0x8C }};
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiPartTypeLegacyMbrGuid = { 0x024DEE41, 0x33E7, 0x11D3, { 0x9D, 0x69, 0x00, 0x08, 0xC7, 0x81, 0xF3, 0x9F }};
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiPartTypeSystemPartGuid = { 0xC12A7328, 0xF81F, 0x11D2, { 0xBA, 0x4B, 0x00, 0xA0, 0xC9, 0x3E, 0xC9, 0x3B }};
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiSmbiosTableGuid = { 0xEB9D2D31, 0x2D88, 0x11D3, { 0x9A, 0x16, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }};
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiSasDevicePathGuid = { 0xd487ddb4, 0x008b, 0x11d9, { 0xaf, 0xdc, 0x00, 0x10, 0x83, 0xff, 0xca, 0x4d }};
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiMdePkgTokenSpaceGuid = { 0x914AEBE7, 0x4635, 0x459b, { 0xAA, 0x1C, 0x11, 0xE2, 0x19, 0xB0, 0x3A, 0x10 }};
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiEventLegacyBootGuid = { 0x2A571201, 0x4966, 0x47F6, { 0x8B, 0x86, 0xF3, 0x1E, 0x41, 0xF3, 0x2F, 0x10 }};
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiHobListGuid = { 0x7739F24C, 0x93D7, 0x11D4, { 0x9A, 0x3A, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }};
+
+// Protocols
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiComponentName2ProtocolGuid = { 0x6A7A5CFF, 0xE8D9, 0x4F70, { 0xBA, 0xDA, 0x75, 0xAB, 0x30, 0x25, 0xCE, 0x14 }};
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiDevicePathToTextProtocolGuid = { 0x8B843E20, 0x8132, 0x4852, { 0x90, 0xCC, 0x55, 0x1A, 0x4E, 0x4A, 0x7F, 0x1C }};
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiSimpleFileSystemProtocolGuid = { 0x964E5B22, 0x6459, 0x11D2, { 0x8E, 0x39, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B }};
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiSimpleTextInProtocolGuid = { 0x387477C1, 0x69C7, 0x11D2, { 0x8E, 0x39, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B }};
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiSimpleTextInputExProtocolGuid = {0xdd9e7534, 0x7762, 0x4698, { 0x8c, 0x14, 0xf5, 0x85, 0x17, 0xa6, 0x25, 0xaa } };
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiSimpleTextOutProtocolGuid = { 0x387477C2, 0x69C7, 0x11D2, { 0x8E, 0x39, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B }};
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiUnicodeCollationProtocolGuid = { 0x1D85CD7F, 0xF43D, 0x11D2, { 0x9A, 0x0C, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }};
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiUnicodeCollation2ProtocolGuid = {0xa4c751fc, 0x23ae, 0x4c3e, { 0x92, 0xe9, 0x49, 0x64, 0xcf, 0x63, 0xf3, 0x49 }};
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiAcpiS3SaveProtocolGuid = { 0x125F2DE1, 0xFB85, 0x440C, { 0xA5, 0x4C, 0x4D, 0x99, 0x35, 0x8A, 0x8D, 0x38 }};
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiBlockIoProtocolGuid = { 0x964E5B21, 0x6459, 0x11D2, { 0x8E, 0x39, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B }};
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiCpuArchProtocolGuid = { 0x26BACCB1, 0x6F42, 0x11D4, { 0xBC, 0xE7, 0x00, 0x80, 0xC7, 0x3C, 0x88, 0x81 }};
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiDebugPortProtocolGuid = { 0xEBA4E8D2, 0x3858, 0x41EC, { 0xA2, 0x81, 0x26, 0x47, 0xBA, 0x96, 0x60, 0xD0 }};
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiDevicePathProtocolGuid = { 0x09576E91, 0x6D3F, 0x11D2, { 0x8E, 0x39, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B }};
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiDiskIoProtocolGuid = { 0xCE345171, 0xBA0B, 0x11D2, { 0x8E, 0x4F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B }};
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiExtScsiPassThruProtocolGuid = { 0x143b7632, 0xb81b, 0x4cb7, {0xab, 0xd3, 0xb6, 0x25, 0xa5, 0xb9, 0xbf, 0xfe }};
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiFirmwareVolume2ProtocolGuid = { 0x220e73b6, 0x6bdb, 0x4413, { 0x84, 0x5, 0xb9, 0x74, 0xb1, 0x8, 0x61, 0x9a } };
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiGraphicsOutputProtocolGuid = { 0x9042A9DE, 0x23DC, 0x4A38, { 0x96, 0xFB, 0x7A, 0xDE, 0xD0, 0x80, 0x51, 0x6A }};
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiHiiFontProtocolGuid = {0xe9ca4775, 0x8657, 0x47fc, {0x97, 0xe7, 0x7e, 0xd6, 0x5a, 0x08, 0x43, 0x24}};
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiLegacy8259ProtocolGuid = { 0x38321dba, 0x4fe0, 0x4e17, { 0x8a, 0xec, 0x41, 0x30, 0x55, 0xea, 0xed, 0xc1 }};
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiLoadedImageProtocolGuid = { 0x5B1B31A1, 0x9562, 0x11D2, { 0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B }};
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiOEMBadgingProtocolGuid = { 0x170E13C0, 0xBF1B, 0x4218, { 0x87, 0x1D, 0x2A, 0xBD, 0xC6, 0xF8, 0x87, 0xBC }};
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiPciIoProtocolGuid = { 0x4CF5B200, 0x68B8, 0x4CA5, { 0x9E, 0xEC, 0xB2, 0x3E, 0x3F, 0x50, 0x02, 0x9A }};
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiScsiIoProtocolGuid = { 0x932F47e6, 0x2362, 0x4002, { 0x80, 0x3E, 0x3C, 0xD5, 0x4B, 0x13, 0x8F, 0x85 }};
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiScsiPassThruProtocolGuid = { 0xA59E8FCF, 0xBDA0, 0x43BB, { 0x90, 0xB1, 0xD3, 0x73, 0x2E, 0xCA, 0xA8, 0x77 }};
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiSimpleNetworkProtocolGuid = { 0xA19832B9, 0xAC25, 0x11D3, { 0x9A, 0x2D, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }};
+//GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiUgaDrawProtocolGuid = { 0x982C298B, 0xF4FA, 0x41CB, { 0xB8, 0x38, 0x77, 0xAA, 0x68, 0x8F, 0xB8, 0x39 }};
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiAbsolutePointerProtocolGuid = { 0x8D59D32B, 0xC655, 0x4AE9, { 0x9B, 0x15, 0xF2, 0x59, 0x04, 0x99, 0x2A, 0x43 } };
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiAcpiTableProtocolGuid = { 0xFFE06BDD, 0x6107, 0x46A6, { 0x7B, 0xB2, 0x5A, 0x9C, 0x7E, 0xC5, 0x27, 0x5C }};
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiEdidActiveProtocolGuid = { 0xBD8C1056, 0x9F36, 0x44EC, { 0x92, 0xA8, 0xA6, 0x33, 0x7F, 0x81, 0x79, 0x86 }};
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiEdidDiscoveredProtocolGuid = { 0x1C0C34F6, 0xD380, 0x41FA, { 0xA0, 0x49, 0x8A, 0xD0, 0x6C, 0x1A, 0x66, 0xAA }};
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiHiiDatabaseProtocolGuid = {0xef9fc172, 0xa1b2, 0x4693, {0xb3, 0x27, 0x6d, 0x32, 0xfc, 0x41, 0x60, 0x42}};
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiHiiImageProtocolGuid = {0x31a6406a, 0x6bdf, 0x4e46, {0xb2, 0xa2, 0xeb, 0xaa, 0x89, 0xc4, 0x09, 0x20}};
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiHiiProtocolGuid = { 0xd7ad636e, 0xb997, 0x459b, { 0xbf, 0x3f, 0x88, 0x46, 0x89, 0x79, 0x80, 0xe1 }};
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiSimplePointerProtocolGuid = { 0x31878C87, 0x0B75, 0x11D5, { 0x9A, 0x4F, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }};
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiSmbiosProtocolGuid = {0x3583ff6, 0xcb36, 0x4940, { 0x94, 0x7e, 0xb9, 0xb3, 0x9f, 0x4a, 0xfa, 0xf7}};
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiSecurityArchProtocolGuid = { 0xA46423E3, 0x4617, 0x49F1, { 0xB9, 0xFF, 0xD1, 0xBF, 0xA9, 0x11, 0x58, 0x39 }};
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiLegacyBiosProtocolGuid = { 0xdb9a1e3d, 0x45cb, 0x4abb, { 0x85, 0x3b, 0xe5, 0x38, 0x7f, 0xdb, 0x2e, 0x2d }};
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiLoadFile2ProtocolGuid = { 0x4006c0c1, 0xfcb3, 0x403e, {0x99, 0x6d, 0x4a, 0x6c, 0x87, 0x24, 0xe0, 0x6d }};
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiLoadFileProtocolGuid = { 0x56EC3091, 0x954C, 0x11D2, { 0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B }};
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiHiiPackageListProtocolGuid = { 0x6a1ee763, 0xd47a, 0x43b4, {0xaa, 0xbe, 0xef, 0x1d, 0xe2, 0xab, 0x56, 0xfc}};
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiDriverBindingProtocolGuid = { 0x18A031AB, 0xB443, 0x4D1A, { 0xA5, 0xC0, 0x0C, 0x09, 0x26, 0x1E, 0x9F, 0x71 }};
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiComponentNameProtocolGuid = { 0x107A772C, 0xD5E1, 0x11D4, { 0x9A, 0x46, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }};
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiDriverConfigurationProtocolGuid = { 0x107A772B, 0xD5E1, 0x11D4, { 0x9A, 0x46, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }};
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiDriverConfiguration2ProtocolGuid = { 0xBFD7DC1D, 0x24F1, 0x40D9, { 0x82, 0xE7, 0x2E, 0x09, 0xBB, 0x6B, 0x4E, 0xBE }};
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiDriverDiagnosticsProtocolGuid = { 0x0784924F, 0xE296, 0x11D4, { 0x9A, 0x49, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }};
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiDriverDiagnostics2ProtocolGuid = { 0x4D330321, 0x025F, 0x4AAC, { 0x90, 0xD8, 0x5E, 0xD9, 0x00, 0x17, 0x3B, 0x63 }};
+
+// Definition of PCDs used in this module
+//GLOBAL_REMOVE_IF_UNREFERENCED const BOOLEAN _gPcd_FixedAtBuild_PcdUgaConsumeSupport = _PCD_VALUE_PcdUgaConsumeSupport;
+
+// Definition of PCDs used in libraries
+
+#define _PCD_TOKEN_PcdMaximumLinkedListLength  2U
+#define _PCD_VALUE_PcdMaximumLinkedListLength  1000000U
+GLOBAL_REMOVE_IF_UNREFERENCED const UINT32 _gPcd_FixedAtBuild_PcdMaximumLinkedListLength = _PCD_VALUE_PcdMaximumLinkedListLength;
+extern const  UINT32  _gPcd_FixedAtBuild_PcdMaximumLinkedListLength;
+#define _PCD_GET_MODE_32_PcdMaximumLinkedListLength  _gPcd_FixedAtBuild_PcdMaximumLinkedListLength
+#define _PCD_SET_MODE_32_PcdMaximumLinkedListLength  ASSERT(FALSE)  // It is not allowed to set value for a FIXED_AT_BUILD PCD
+
+#define _PCD_TOKEN_PcdMaximumAsciiStringLength  3U
+#define _PCD_VALUE_PcdMaximumAsciiStringLength  1000000U
+GLOBAL_REMOVE_IF_UNREFERENCED const UINT32 _gPcd_FixedAtBuild_PcdMaximumAsciiStringLength = _PCD_VALUE_PcdMaximumAsciiStringLength;
+extern const  UINT32  _gPcd_FixedAtBuild_PcdMaximumAsciiStringLength;
+#define _PCD_GET_MODE_32_PcdMaximumAsciiStringLength  _gPcd_FixedAtBuild_PcdMaximumAsciiStringLength
+#define _PCD_SET_MODE_32_PcdMaximumAsciiStringLength  ASSERT(FALSE)  // It is not allowed to set value for a FIXED_AT_BUILD PCD
+
+#define _PCD_TOKEN_PcdMaximumUnicodeStringLength  4U
+#define _PCD_VALUE_PcdMaximumUnicodeStringLength  1000000U
+GLOBAL_REMOVE_IF_UNREFERENCED const UINT32 _gPcd_FixedAtBuild_PcdMaximumUnicodeStringLength = _PCD_VALUE_PcdMaximumUnicodeStringLength;
+extern const  UINT32  _gPcd_FixedAtBuild_PcdMaximumUnicodeStringLength;
+#define _PCD_GET_MODE_32_PcdMaximumUnicodeStringLength  _gPcd_FixedAtBuild_PcdMaximumUnicodeStringLength
+#define _PCD_SET_MODE_32_PcdMaximumUnicodeStringLength  ASSERT(FALSE)  // It is not allowed to set value for a FIXED_AT_BUILD PCD
+
+#define _PCD_TOKEN_PcdVerifyNodeInList  5U
+#define _PCD_VALUE_PcdVerifyNodeInList  ((BOOLEAN)0U)
+GLOBAL_REMOVE_IF_UNREFERENCED const BOOLEAN _gPcd_FixedAtBuild_PcdVerifyNodeInList = _PCD_VALUE_PcdVerifyNodeInList;
+extern const  BOOLEAN  _gPcd_FixedAtBuild_PcdVerifyNodeInList;
+#define _PCD_GET_MODE_BOOL_PcdVerifyNodeInList  _gPcd_FixedAtBuild_PcdVerifyNodeInList
+#define _PCD_SET_MODE_BOOL_PcdVerifyNodeInList  ASSERT(FALSE)  // It is not allowed to set value for a FIXED_AT_BUILD PCD
+
+#define _PCD_TOKEN_PcdDriverDiagnosticsDisable  6U
+#define _PCD_VALUE_PcdDriverDiagnosticsDisable  ((BOOLEAN)0U)
+GLOBAL_REMOVE_IF_UNREFERENCED const BOOLEAN _gPcd_FixedAtBuild_PcdDriverDiagnosticsDisable = _PCD_VALUE_PcdDriverDiagnosticsDisable;
+extern const  BOOLEAN  _gPcd_FixedAtBuild_PcdDriverDiagnosticsDisable;
+#define _PCD_GET_MODE_BOOL_PcdDriverDiagnosticsDisable  _gPcd_FixedAtBuild_PcdDriverDiagnosticsDisable
+#define _PCD_SET_MODE_BOOL_PcdDriverDiagnosticsDisable  ASSERT(FALSE)  // It is not allowed to set value for a FIXED_AT_BUILD PCD
+
+#define _PCD_TOKEN_PcdComponentNameDisable  7U
+#define _PCD_VALUE_PcdComponentNameDisable  ((BOOLEAN)0U)
+GLOBAL_REMOVE_IF_UNREFERENCED const BOOLEAN _gPcd_FixedAtBuild_PcdComponentNameDisable = _PCD_VALUE_PcdComponentNameDisable;
+extern const  BOOLEAN  _gPcd_FixedAtBuild_PcdComponentNameDisable;
+#define _PCD_GET_MODE_BOOL_PcdComponentNameDisable  _gPcd_FixedAtBuild_PcdComponentNameDisable
+#define _PCD_SET_MODE_BOOL_PcdComponentNameDisable  ASSERT(FALSE)  // It is not allowed to set value for a FIXED_AT_BUILD PCD
+
+#define _PCD_TOKEN_PcdDriverDiagnostics2Disable  8U
+#define _PCD_VALUE_PcdDriverDiagnostics2Disable  ((BOOLEAN)0U)
+GLOBAL_REMOVE_IF_UNREFERENCED const BOOLEAN _gPcd_FixedAtBuild_PcdDriverDiagnostics2Disable = _PCD_VALUE_PcdDriverDiagnostics2Disable;
+extern const  BOOLEAN  _gPcd_FixedAtBuild_PcdDriverDiagnostics2Disable;
+#define _PCD_GET_MODE_BOOL_PcdDriverDiagnostics2Disable  _gPcd_FixedAtBuild_PcdDriverDiagnostics2Disable
+#define _PCD_SET_MODE_BOOL_PcdDriverDiagnostics2Disable  ASSERT(FALSE)  // It is not allowed to set value for a FIXED_AT_BUILD PCD
+
+#define _PCD_TOKEN_PcdComponentName2Disable  9U
+#define _PCD_VALUE_PcdComponentName2Disable  ((BOOLEAN)0U)
+GLOBAL_REMOVE_IF_UNREFERENCED const BOOLEAN _gPcd_FixedAtBuild_PcdComponentName2Disable = _PCD_VALUE_PcdComponentName2Disable;
+extern const  BOOLEAN  _gPcd_FixedAtBuild_PcdComponentName2Disable;
+#define _PCD_GET_MODE_BOOL_PcdComponentName2Disable  _gPcd_FixedAtBuild_PcdComponentName2Disable
+#define _PCD_SET_MODE_BOOL_PcdComponentName2Disable  ASSERT(FALSE)  // It is not allowed to set value for a FIXED_AT_BUILD PCD
+
+#define _PCD_TOKEN_PcdUefiLibMaxPrintBufferSize  10U
+#define _PCD_VALUE_PcdUefiLibMaxPrintBufferSize  320U
+GLOBAL_REMOVE_IF_UNREFERENCED const UINT32 _gPcd_FixedAtBuild_PcdUefiLibMaxPrintBufferSize = _PCD_VALUE_PcdUefiLibMaxPrintBufferSize;
+extern const  UINT32  _gPcd_FixedAtBuild_PcdUefiLibMaxPrintBufferSize;
+#define _PCD_GET_MODE_32_PcdUefiLibMaxPrintBufferSize  _gPcd_FixedAtBuild_PcdUefiLibMaxPrintBufferSize
+#define _PCD_SET_MODE_32_PcdUefiLibMaxPrintBufferSize  ASSERT(FALSE)  // It is not allowed to set value for a FIXED_AT_BUILD PCD
+
+
+EFI_STATUS
+EFIAPI
+UefiBootServicesTableLibConstructor (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  );
+
+EFI_STATUS
+EFIAPI
+UefiRuntimeServicesTableLibConstructor (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  );
+
+EFI_STATUS
+EFIAPI
+UefiLibConstructor (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  );
+
+EFI_STATUS
+EFIAPI
+DxeServicesTableLibConstructor (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  );
+
+EFI_STATUS
+EFIAPI
+HobLibConstructor (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  );
+
+
+// VOID
+// EFIAPI
+// ProcessLibraryConstructorList (
+//   IN EFI_HANDLE        ImageHandle,
+//   IN EFI_SYSTEM_TABLE  *SystemTable
+//   )
+// {
+//   EFI_STATUS  Status;
+// 
+//   Status = UefiBootServicesTableLibConstructor (ImageHandle, SystemTable);
+//   ASSERT_EFI_ERROR (Status);
+// 
+//   Status = UefiRuntimeServicesTableLibConstructor (ImageHandle, SystemTable);
+//   ASSERT_EFI_ERROR (Status);
+// 
+//   Status = UefiLibConstructor (ImageHandle, SystemTable);
+//   ASSERT_EFI_ERROR (Status);
+// 
+//   Status = DxeServicesTableLibConstructor (ImageHandle, SystemTable);
+//   ASSERT_EFI_ERROR (Status);
+// 
+//   Status = HobLibConstructor (ImageHandle, SystemTable);
+//   ASSERT_EFI_ERROR (Status);
+// 
+// }
+
+
+
+// VOID
+// EFIAPI
+// ProcessLibraryDestructorList (
+//   IN EFI_HANDLE        ImageHandle,
+//   IN EFI_SYSTEM_TABLE  *SystemTable
+//   )
+// {
+//
+// }
+
+const UINT32 _gUefiDriverRevision = 0x00010000U;
+
+
+// EFI_STATUS
+// EFIAPI
+// ProcessModuleEntryPointList (
+//   IN EFI_HANDLE        ImageHandle,
+//   IN EFI_SYSTEM_TABLE  *SystemTable
+//   )
+// 
+// {
+//   return efi_main (ImageHandle, SystemTable);
+// }
+
+VOID
+EFIAPI
+ExitDriver (
+  IN EFI_STATUS  Status
+  )
+{
+  if (EFI_ERROR (Status)) {
+    ProcessLibraryDestructorList (gImageHandle, gST);
+  }
+  gBS->Exit (gImageHandle, Status, 0, NULL);
+}
+
+//GLOBAL_REMOVE_IF_UNREFERENCED const UINT8 _gDriverUnloadImageCount = 0U;
+
+// EFI_STATUS
+// EFIAPI
+// ProcessModuleUnloadList (
+//   IN EFI_HANDLE        ImageHandle
+//   )
+// {
+//   return EFI_SUCCESS;
+// }
+
+// Stuff added in effort to get Secure Boot working....
+
+#define _PCD_TOKEN_PcdDebugPropertyMask  11U
+#define _PCD_VALUE_PcdDebugPropertyMask  0x0fU
+GLOBAL_REMOVE_IF_UNREFERENCED const UINT8 _gPcd_FixedAtBuild_PcdDebugPropertyMask = _PCD_VALUE_PcdDebugPropertyMask;
+extern const  UINT8  _gPcd_FixedAtBuild_PcdDebugPropertyMask;
+#define _PCD_GET_MODE_8_PcdDebugPropertyMask  _gPcd_FixedAtBuild_PcdDebugPropertyMask
+//#define _PCD_SET_MODE_8_PcdDebugPropertyMask  ASSERT(FALSE)  // It is not allowed to set value for a FIXED_AT_BUILD PCD
+
+#define _PCD_TOKEN_PcdDebugClearMemoryValue  10U
+#define _PCD_VALUE_PcdDebugClearMemoryValue  0xAFU
+GLOBAL_REMOVE_IF_UNREFERENCED const UINT8 _gPcd_FixedAtBuild_PcdDebugClearMemoryValue = _PCD_VALUE_PcdDebugClearMemoryValue;
+extern const  UINT8  _gPcd_FixedAtBuild_PcdDebugClearMemoryValue;
+#define _PCD_GET_MODE_8_PcdDebugClearMemoryValue  _gPcd_FixedAtBuild_PcdDebugClearMemoryValue
+//#define _PCD_SET_MODE_8_PcdDebugClearMemoryValue  ASSERT(FALSE)  // It is not allowed to set value for a FIXED_AT_BUILD PCD
+
+#define _PCD_TOKEN_PcdDebugPrintErrorLevel  5U
+#define _PCD_VALUE_PcdDebugPrintErrorLevel  0x80000000U
+GLOBAL_REMOVE_IF_UNREFERENCED const UINT32 _gPcd_FixedAtBuild_PcdDebugPrintErrorLevel = _PCD_VALUE_PcdDebugPrintErrorLevel;
+extern const  UINT32  _gPcd_FixedAtBuild_PcdDebugPrintErrorLevel;
+#define _PCD_GET_MODE_32_PcdDebugPrintErrorLevel  _gPcd_FixedAtBuild_PcdDebugPrintErrorLevel
+//#define _PCD_SET_MODE_32_PcdDebugPrintErrorLevel  ASSERT(FALSE)  // It is not allowed to set value for a FIXED_AT_BUILD PCD
+
diff --git a/gptsync/AutoGen.h b/gptsync/AutoGen.h
new file mode 100644 (file)
index 0000000..a07912e
--- /dev/null
@@ -0,0 +1,51 @@
+/**
+  DO NOT EDIT
+  FILE auto-generated
+  Module name:
+    AutoGen.h
+  Abstract:       Auto-generated AutoGen.h for building module or library.
+**/
+
+#ifndef _AUTOGENH_B8448DD1_B146_41B7_9D66_98B3A0A404D3
+#define _AUTOGENH_B8448DD1_B146_41B7_9D66_98B3A0A404D3
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <Base.h>
+#include <Uefi.h>
+#include <Library/PcdLib.h>
+
+extern GUID  gEfiCallerIdGuid;
+
+#define EFI_CALLER_ID_GUID \
+  {0xB8448DD1, 0xB146, 0x41B7, {0x9D, 0x66, 0x98, 0xB3, 0xA0, 0xA4, 0x04, 0xD3}}
+
+// Definition of PCDs used in this module
+
+#define _PCD_TOKEN_PcdUgaConsumeSupport  16U
+#define _PCD_VALUE_PcdUgaConsumeSupport  ((BOOLEAN)1U)
+extern const  BOOLEAN  _gPcd_FixedAtBuild_PcdUgaConsumeSupport;
+#define _PCD_GET_MODE_BOOL_PcdUgaConsumeSupport  _gPcd_FixedAtBuild_PcdUgaConsumeSupport
+//#define _PCD_SET_MODE_BOOL_PcdUgaConsumeSupport  ASSERT(FALSE)  // It is not allowed to set value for a FIXED_AT_BUILD PCD
+
+// Definition of PCDs used in libraries is in AutoGen.c
+
+
+EFI_STATUS
+EFIAPI
+efi_main (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  );
+
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/gptsync/Make.gnuefi b/gptsync/Make.gnuefi
new file mode 100644 (file)
index 0000000..a38aa84
--- /dev/null
@@ -0,0 +1,37 @@
+#
+# gptsync/Make.gnuefi
+# Build control file for the gptsync tool, built with GNU-EFI
+#
+
+LOCAL_CPPFLAGS  = -I. -I../include
+LOCAL_LDFLAGS   = 
+LOCAL_LIBS      = 
+
+OBJS            = gptsync.o lib.o os_efi.o
+TARGET          = gptsync.efi
+
+include ../Make.common
+
+ifeq ($(ARCH),ia32)
+  ARCHNAME = gptsync_ia32.efi
+endif
+
+ifeq ($(ARCH),x86_64)
+  ARCHNAME = gptsync_x64.efi
+endif
+
+all: $(TARGET)
+
+#SHLIB_TARGET = $(subst .efi,.so,$(TARGET))
+
+#$(SHLIB_TARGET): $(OBJS)
+#      $(LD) $(LOCAL_LDFLAGS) $(LDFLAGS) $(OBJS) -o $@ $(LOCAL_LIBS) $(LIBS)
+
+$(TARGET): $(SHLIB_TARGET)
+       $(OBJCOPY) -j .text -j .sdata -j .data -j .dynamic -j .dynsym -j .rel \
+                  -j .rela -j .reloc --target=$(FORMAT) $< $@
+       chmod a-x $(TARGET)
+       mv $(TARGET) $(ARCHNAME)
+
+
+# EOF
diff --git a/gptsync/Make.tiano b/gptsync/Make.tiano
new file mode 100644 (file)
index 0000000..b6c46f2
--- /dev/null
@@ -0,0 +1,107 @@
+#
+# gptsync/Make.tiano
+# Build control file for gptsync utility, built with TianoCore EDK2
+#
+
+HOSTARCH        = $(shell uname -m | sed s,i[3456789]86,ia32,)
+ARCH            ?= $(HOSTARCH)
+
+# Note: IA64 options are untested; taken from Debian's rEFIt package.
+ifeq ($(ARCH),ia64)
+  # EFI specs allows only lower floating point partition to be used
+  ARCH_C_CFLAGS  = -frename-registers -mfixed-range=f32-f127
+  # TODO: Add ARCHDIR and FILENAME_CODE as appropriate
+endif
+
+ifeq ($(ARCH),ia32)
+  ARCH_C_FLAGS = -m32 -malign-double -DEFI32
+  ARCHDIR = Ia32
+  UC_ARCH = IA32
+  FILENAME_CODE = ia32
+  LD_CODE = elf_i386
+endif
+
+ifeq ($(ARCH),x86_64)
+  ARCH_C_FLAGS = "-DEFIAPI=__attribute__((ms_abi))" -mcmodel=large -m64 -DEFIX64
+  ARCHDIR = X64
+  UC_ARCH = X64
+  FILENAME_CODE = x64
+  LD_CODE = elf_x86_64
+endif
+
+EDK2BASE = /usr/local/UDK2010/MyWorkSpace
+#EDK2BASE = /usr/local/edk2
+
+# Below file defines TARGET (RELEASE or DEBUG) and TOOL_CHAIN_TAG (GCC44, GCC45, or GCC46)
+include $(EDK2BASE)/Conf/target.txt
+
+EFILIB          = $(EDK2BASE)/Build/Mde/$(TARGET)_$(TOOL_CHAIN_TAG)/$(UC_ARCH)/MdePkg/Library
+ALL_EFILIBS     = $(EFILIB)/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib/OUTPUT/BaseDebugPrintErrorLevelLib.lib \
+                 $(EFILIB)/BasePrintLib/BasePrintLib/OUTPUT/BasePrintLib.lib \
+                 $(EFILIB)/BasePcdLibNull/BasePcdLibNull/OUTPUT/BasePcdLibNull.lib \
+                 $(EFILIB)/UefiDebugLibConOut/UefiDebugLibConOut/OUTPUT/UefiDebugLibConOut.lib \
+                 $(EFILIB)/BaseLib/BaseLib/OUTPUT/BaseLib.lib \
+                 $(EFILIB)/BaseMemoryLib/BaseMemoryLib/OUTPUT/BaseMemoryLib.lib \
+                 $(EFILIB)/UefiBootServicesTableLib/UefiBootServicesTableLib/OUTPUT/UefiBootServicesTableLib.lib \
+                 $(EFILIB)/UefiMemoryAllocationLib/UefiMemoryAllocationLib/OUTPUT/UefiMemoryAllocationLib.lib \
+                 $(EFILIB)/UefiDevicePathLib/UefiDevicePathLib/OUTPUT/UefiDevicePathLib.lib \
+                 $(EFILIB)/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib/OUTPUT/UefiRuntimeServicesTableLib.lib \
+                 $(EFILIB)/UefiLib/UefiLib/OUTPUT/UefiLib.lib \
+                 $(EFILIB)/UefiApplicationEntryPoint/UefiApplicationEntryPoint/OUTPUT/UefiApplicationEntryPoint.lib
+
+INCLUDE_DIRS    = -I $(EDK2BASE)/MdePkg \
+                  -I $(EDK2BASE)/MdePkg/Include \
+                  -I $(EDK2BASE)/MdePkg/Include/$(ARCHDIR) \
+                 -I $(EDK2BASE)/EdkCompatibilityPkg/Foundation/Framework/Include \
+                 -I $(EDK2BASE)/EdkCompatibilityPkg/Foundation/Library/Dxe/Include \
+                 -I $(EDK2BASE)/MdeModulePkg/ \
+                  -I $(EDK2BASE)/MdeModulePkg/Include \
+                  -I $(EDK2BASE)/IntelFrameworkPkg/Include \
+                  -I $(EDK2BASE)/MdePkg/Include/$(ARCHDIR) \
+                 -I ../libeg \
+                 -I ../include \
+                 -I ..
+
+GPTSYNC_NAMES    = gptsync lib os_efi AutoGen ../EfiLib/BmLib
+OBJS             = $(GPTSYNC_NAMES:=.obj)
+BUILDME          = gptsync_$(FILENAME_CODE).efi
+
+OPTIMFLAGS      = -fno-strict-aliasing -mno-red-zone -Wno-address -Os
+DEBUGFLAGS      = -Wall -Wno-missing-braces -Wno-array-bounds -ffunction-sections -fdata-sections
+CFLAGS          = $(OPTIMFLAGS) -g -fshort-wchar -fno-stack-protector $(DEBUGFLAGS) -c -DHOST_EFI_EDK2 -D__MAKEWITH_TIANO
+#CFLAGS          = $(OPTIMFLAGS) -g -fshort-wchar -fno-stack-protector $(DEBUGFLAGS) -c -include AutoGen.h -DHOST_EFI_EDK2
+
+prefix          = /usr/bin/
+CC              = $(prefix)gcc
+AS              = $(prefix)as
+LD              = $(prefix)ld
+AR              = $(prefix)ar
+RANLIB          = $(prefix)ranlib
+OBJCOPY         = $(prefix)objcopy
+GENFW           = $(EDK2BASE)/BaseTools/Source/C/bin/GenFw
+
+
+LDSCRIPT = $(EDK2BASE)/BaseTools/Scripts/gcc4.4-ld-script
+
+LDFLAGS         = -nostdlib -n -q --gc-sections --script=$(EDK2BASE)/BaseTools/Scripts/gcc4.4-ld-script \
+                  --entry efi_main -u efi_main -m $(LD_CODE)
+
+%.obj: %.c
+       $(CC) $(ARCH_C_FLAGS) $(CFLAGS) $(INCLUDE_DIRS) -DNO_BUILTIN_VA_FUNCS -c $< -o $@
+       +make -C ../EfiLib -f Make.tiano
+
+ifneq (,$(filter %.efi,$(BUILDME)))
+
+DLL_TARGET = $(subst .efi,.dll,$(BUILDME))
+
+all: $(BUILDME)
+
+$(DLL_TARGET): $(OBJS)
+       $(LD) -o gptsync_$(FILENAME_CODE).dll $(LDFLAGS) --start-group $(ALL_EFILIBS) $(OBJS) --end-group
+
+$(BUILDME): $(DLL_TARGET)
+       $(OBJCOPY) --strip-unneeded $(DLL_TARGET)
+       $(GENFW) -e UEFI_APPLICATION -o $(BUILDME) $(DLL_TARGET)
+
+endif
+
diff --git a/gptsync/Make.unix b/gptsync/Make.unix
new file mode 100644 (file)
index 0000000..a1d7282
--- /dev/null
@@ -0,0 +1,74 @@
+#
+# Makefile for gptsync on Unix platforms
+#
+
+RM = rm -f
+CC = gcc
+
+GPTSYNC_TARGET = gptsync
+GPTSYNC_OBJS   = gptsync.unix.o lib.unix.o os_unix.gptsync.o
+
+SHOWPART_TARGET = showpart
+SHOWPART_OBJS   = showpart.unix.o lib.unix.o os_unix.showpart.o
+
+CPPFLAGS = -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I../include
+CFLAGS   = -Wall
+LDFLAGS  =
+LIBS     =
+
+# system-dependent additions
+
+system = $(shell uname)
+ifeq ($(system),Darwin)
+  CC        = gcc-4.0
+  # TODO: re-enable this once the code is no longer little-endian specific
+  #CFLAGS   += -arch i386 -arch ppc
+  #LDFLAGS  += -arch i386 -arch ppc
+  ifeq (/Developer/SDKs/MacOSX10.4u.sdk,$(wildcard /Developer/SDKs/MacOSX10.4u.sdk))
+    CPPFLAGS += -isysroot /Developer/SDKs/MacOSX10.4u.sdk
+    LDFLAGS  += -Wl,-syslibroot,/Developer/SDKs/MacOSX10.4u.sdk
+  endif
+endif
+
+# real making
+
+all: $(GPTSYNC_TARGET) $(SHOWPART_TARGET)
+
+$(GPTSYNC_TARGET): $(GPTSYNC_OBJS)
+       $(CC) $(LDFLAGS) -o $@ $(GPTSYNC_OBJS) $(LIBS)
+
+gptsync.unix.o: gptsync.c
+       $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@
+os_unix.gptsync.o: os_unix.c
+       $(CC) $(CPPFLAGS) -DPROGNAME=gptsync $(CFLAGS) -c $< -o $@
+
+$(SHOWPART_TARGET): $(SHOWPART_OBJS)
+       $(CC) $(LDFLAGS) -o $@ $(SHOWPART_OBJS) $(LIBS)
+
+showpart.unix.o: showpart.c
+       $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@
+os_unix.showpart.o: os_unix.c
+       $(CC) $(CPPFLAGS) -DPROGNAME=showpart -DNOREADONLYWARN $(CFLAGS) -c $< -o $@
+
+lib.unix.o: lib.c
+       $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@
+
+# additional dependencies
+
+gptsync.unix.o: gptsync.h ../include/syslinux_mbr.h
+os_unix.gptsync.o: gptsync.h
+
+showpart.unix.o: gptsync.h
+os_unix.showpart.o: gptsync.h
+
+lib.unix.o: gptsync.h
+
+# cleanup
+
+clean:
+       $(RM) *.o *~ *% $(GPTSYNC_TARGET) $(SHOWPART_TARGET)
+
+distclean: clean
+       $(RM) .depend
+
+# eof
diff --git a/gptsync/Makefile b/gptsync/Makefile
new file mode 100644 (file)
index 0000000..8987534
--- /dev/null
@@ -0,0 +1,29 @@
+# meta-Makefile for gptsync program; controls use of EFI build using
+# GNU-EFI vs. TianoCore EDK2 or build for Unix/Linux.
+#
+# Most of the functionality is in Make.tiano, Make.gnuefi, and
+# Make.unix; this Makefile just dispatches based on options
+# passed to it....
+
+TEXTFILES = gptsync.txt
+
+TARGET = tiano
+
+all:   $(TARGET)
+
+gnuefi:
+       +make -f Make.gnuefi gptsync.efi
+
+tiano:
+       +make -f Make.tiano
+
+unix:
+       +make -f Make.unix
+
+# utility rules
+
+clean:
+       rm -f *~ *.bak *.o *.obj *.so *.efi *.dll err.txt gptsync_*.txt gptsync showpart $(TEXTFILES)
+
+
+# DO NOT DELETE
diff --git a/gptsync/README.txt b/gptsync/README.txt
new file mode 100644 (file)
index 0000000..02a3c89
--- /dev/null
@@ -0,0 +1,45 @@
+This directory contains the source code for gptsync, which is a program for
+creating hybrid MBRs (http://www.rodsbooks.com/gdisk/hybrid.html).
+
+HYBRID MBRS ARE UGLY AND DANGEROUS HACKS, AND SHOULD NOT BE USED UNLESS
+ABSOLUTELY NECESSARY!
+
+Despite their dangers, hybrid MBRs are useful because Windows interprets
+hybrid MBR disks as having an MBR partition table, whereas OS X and Linux
+interpret such disks as having a GUID partition table (GPT). Since Windows
+ties its boot mode to the firmware type (MBR/BIOS and GPT/EFI), a hybrid
+MBR enables Windows to boot in BIOS mode from a disk that's primarily a GPT
+disk, such as a Macintosh OS X disk.
+
+Unfortunately, Apple uses hybrid MBRs as part of its workaround to enable
+Macs to boot Windows in BIOS mode while also supporting a standard EFI-mode
+boot of OS X. Many Linux distributions also install in BIOS mode on Macs,
+and so use hybrid MBRs; but it's usually possible to add an EFI-mode boot
+loader to get Macs to boot Linux in EFI mode, thus obviating the need for a
+hybrid MBR. Some Hackintosh installations rely on a hybrid MBR for reasons
+similar to those of OS X on a real Mac. Thus, you should use a hybrid MBR
+*ONLY* on a Mac that dual-boots with Windows or some other OS in BIOS mode
+or in very rare circumstances on other computers.
+
+The version of gptsync provided with rEFInd is heavily modified from the
+original rEFIt version of the program. Most notably, it's "smarter" about
+creating a hybrid MBR: It prioritizes placement of Windows (FAT and NTFS)
+partitions in the MBR side, followed by Linux partitions. Other partitions,
+such as OS X's HFS+ partitions, might not appear at all in the hybrid MBR,
+whereas they generally do appear in hybrid MBRs created by rEFIt's version
+of gptsync. In the rEFIt version of gptsync, OS X partitions can crowd out
+FAT or NTFS partitions, particularly on computers with shared FAT or NTFS
+partitions, multiple Windows installations, or triple-boots with OS X,
+Windows, and Linux. The rEFInd version of gptsync also checks the
+firmware's author and warns if you're trying to run the program on anything
+but Apple firmware, since in most such cases creating a hybrid MBR is *NOT*
+desirable.
+
+Although the Makefile supports building for both EFI (via the "gnuefi" and
+"tiano" targets) and Unix/Linux (via the "unix" target), the Unix build is
+currently broken; it returns a bogus error about an unknown GPT spec
+revision. If you want to create a hybrid MBR in an OS, you're better off
+using gdisk (http://www.rodsbooks.com/gdisk/), which provides much better
+control of the hybrid MBR creation process. gdisk may also be preferable if
+you have an unusual partition layout, many partitions, or specific
+requirements that you understand well.
diff --git a/gptsync/gptsync.8 b/gptsync/gptsync.8
new file mode 100644 (file)
index 0000000..0639e33
--- /dev/null
@@ -0,0 +1,16 @@
+.TH "gptsync" 8 "2006 Jul 2" "Debian" "rEFIt"
+.SH NAME
+gptsync \- GPT partition table to MBR partition table synchronisation
+.SH "SYNOPSIS"
+.BI "gptsync " "device"
+.SH "DESCRIPTION"
+Reads the GPT partition table on the device and synchronise content of
+MBR partition table on the device.  Useful for situations (as in
+mactel linux) where legacy operating systems require MBR partition
+table to function properly, while most other operating systems can
+work with GPT.
+
+.SH "Author"
+Written by Christoph Pfisterer. This manual page contributed for Debian by
+Junichi Uekawa <dancer@debian.org>, but may be used for others.
+
diff --git a/gptsync/gptsync.c b/gptsync/gptsync.c
new file mode 100644 (file)
index 0000000..2ba4418
--- /dev/null
@@ -0,0 +1,521 @@
+/*
+ * gptsync/gptsync.c
+ * Platform-independent code for syncing GPT and MBR
+ *
+ * Copyright (c) 2006-2007 Christoph Pfisterer
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the
+ *    distribution.
+ *
+ *  * Neither the name of Christoph Pfisterer nor the names of the
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/* Changes copyright (c) 2013 Roderick W. Smith */
+
+#include "gptsync.h"
+
+#include "syslinux_mbr.h"
+
+//
+// MBR functions
+//
+
+static UINTN check_mbr(VOID)
+{
+    UINTN       i, k;
+    BOOLEAN     found = FALSE;
+
+    // check each entry
+    for (i = 0; i < mbr_part_count; i++) {
+        // check for overlap
+        for (k = 0; k < mbr_part_count; k++) {
+            if (k != i && !(mbr_parts[i].start_lba > mbr_parts[k].end_lba || mbr_parts[k].start_lba > mbr_parts[i].end_lba)) {
+                Print(L"Status: MBR partition table is invalid, partitions overlap.\n");
+                return EFI_UNSUPPORTED;
+            }
+        }
+
+        // check for extended partitions
+        if (mbr_parts[i].mbr_type == 0x05 || mbr_parts[i].mbr_type == 0x0f || mbr_parts[i].mbr_type == 0x85) {
+            Print(L"Status: Extended partition found in MBR table, will not touch this disk.\n",
+                  gpt_parts[i].gpt_parttype->name);
+            return EFI_UNSUPPORTED;
+        }
+
+        // Check for matching GPT partitition; if not found, flag error
+        if ((mbr_parts[i].mbr_type != 0xEE) && (mbr_parts[i].mbr_type != 0x00)) {
+            found = FALSE;
+            for (k = 0; (k < gpt_part_count) && !found; k++) {
+               if ((mbr_parts[i].start_lba == gpt_parts[k].start_lba) && (mbr_parts[i].end_lba == gpt_parts[k].end_lba)) {
+                  found = TRUE;
+               } // if
+            } // for
+            if (!found) {
+               Print(L"Status: Found MBR partition with no matching GPT partition. Re-syncing could\n");
+               Print(L"destroy data; will not touch this disk.\n");
+               return EFI_UNSUPPORTED;
+            } // if
+        } // if
+
+    } // for
+
+    return 0;
+} // UINTN check_mbr()
+
+static UINTN write_mbr(VOID)
+{
+    UINTN               status;
+    UINTN               i, k;
+    UINT8               active;
+    UINT64              lba;
+    MBR_PART_INFO       *table;
+    BOOLEAN             have_bootcode;
+
+    Print(L"\nWriting new MBR...\n");
+
+    // read MBR data
+    status = read_sector(0, sector);
+    if (status != 0)
+        return status;
+
+    // write partition table
+    *((UINT16 *)(sector + 510)) = 0xaa55;
+
+    table = (MBR_PART_INFO *)(sector + 446);
+    active = 0x80;
+    for (i = 0; i < 4; i++) {
+        for (k = 0; k < new_mbr_part_count; k++) {
+            if (new_mbr_parts[k].index == i)
+                break;
+        }
+        if (k >= new_mbr_part_count) {
+            // unused entry
+            table[i].flags        = 0;
+            table[i].start_chs[0] = 0;
+            table[i].start_chs[1] = 0;
+            table[i].start_chs[2] = 0;
+            table[i].type         = 0;
+            table[i].end_chs[0]   = 0;
+            table[i].end_chs[1]   = 0;
+            table[i].end_chs[2]   = 0;
+            table[i].start_lba    = 0;
+            table[i].size         = 0;
+        } else {
+            if (new_mbr_parts[k].active) {
+                table[i].flags        = active;
+                active = 0x00;
+            } else
+                table[i].flags        = 0x00;
+            table[i].start_chs[0] = 0xfe;
+            table[i].start_chs[1] = 0xff;
+            table[i].start_chs[2] = 0xff;
+            table[i].type         = new_mbr_parts[k].mbr_type;
+            table[i].end_chs[0]   = 0xfe;
+            table[i].end_chs[1]   = 0xff;
+            table[i].end_chs[2]   = 0xff;
+
+            lba = new_mbr_parts[k].start_lba;
+            if (lba > 0xffffffffULL) {
+                Print(L"Warning: Partition %d starts beyond 2 TiB limit\n", i+1);
+                lba = 0xffffffffULL;
+            }
+            table[i].start_lba    = (UINT32)lba;
+
+            lba = new_mbr_parts[k].end_lba + 1 - new_mbr_parts[k].start_lba;
+            if (lba > 0xffffffffULL) {
+                Print(L"Warning: Partition %d extends beyond 2 TiB limit\n", i+1);
+                lba = 0xffffffffULL;
+            }
+            table[i].size         = (UINT32)lba;
+        }
+    }
+
+    // add boot code if necessary
+    have_bootcode = FALSE;
+    for (i = 0; i < MBR_BOOTCODE_SIZE; i++) {
+        if (sector[i] != 0) {
+            have_bootcode = TRUE;
+            break;
+        }
+    }
+    if (!have_bootcode) {
+        // no boot code found in the MBR, add the syslinux MBR code
+        SetMem(sector, MBR_BOOTCODE_SIZE, 0);
+        CopyMem(sector, syslinux_mbr, SYSLINUX_MBR_SIZE);
+    }
+
+    // write MBR data
+    status = write_sector(0, sector);
+    if (status != 0)
+        return status;
+
+    Print(L"MBR updated successfully!\n");
+
+    return 0;
+}
+
+//
+// GPT functions
+//
+
+static UINTN check_gpt(VOID)
+{
+    UINTN       i, k;
+
+    if (gpt_part_count == 0) {
+        Print(L"Status: No GPT partition table, no need to sync.\n");
+        return EFI_UNSUPPORTED;
+    }
+
+    // check each entry
+    for (i = 0; i < gpt_part_count; i++) {
+        // check sanity
+        if (gpt_parts[i].end_lba < gpt_parts[i].start_lba) {
+            Print(L"Status: GPT partition table is invalid.\n");
+            return EFI_UNSUPPORTED;
+        }
+        // check for overlap
+        for (k = 0; k < gpt_part_count; k++) {
+            if (k != i && !(gpt_parts[i].start_lba > gpt_parts[k].end_lba || gpt_parts[k].start_lba > gpt_parts[i].end_lba)) {
+                Print(L"Status: GPT partition table is invalid, partitions overlap.\n");
+                return EFI_UNSUPPORTED;
+            }
+        }
+
+        // check for partitions kind
+        if (gpt_parts[i].gpt_parttype->kind == GPT_KIND_FATAL) {
+            Print(L"Status: GPT partition of type '%s' found, will not touch this disk.\n",
+                  gpt_parts[i].gpt_parttype->name);
+            return EFI_UNSUPPORTED;
+        }
+    }
+
+    return 0;
+}
+
+//
+// compare GPT and MBR tables
+//
+
+#define ACTION_NONE        (0)
+#define ACTION_NOP         (1)
+#define ACTION_REWRITE     (2)
+
+// Copy a single GPT entry to the new_mbr_parts array.
+static VOID copy_gpt_to_new_mbr(UINTN gpt_num, UINTN mbr_num) {
+   new_mbr_parts[mbr_num].index     = mbr_num;
+   new_mbr_parts[mbr_num].start_lba = gpt_parts[gpt_num].start_lba;
+   new_mbr_parts[mbr_num].end_lba   = gpt_parts[gpt_num].end_lba;
+   new_mbr_parts[mbr_num].mbr_type  = gpt_parts[gpt_num].mbr_type;
+   new_mbr_parts[mbr_num].active    = FALSE;
+} // VOID copy_gpt_to_new_mbr()
+
+// A simple bubble sort for the MBR partitions.
+static VOID sort_mbr(PARTITION_INFO *parts) {
+   PARTITION_INFO one_part;
+   int c, d;
+
+   if (parts == NULL)
+      return;
+
+   for (c = 0 ; c < 3; c++) {
+      for (d = 1 ; d < 3 - c; d++) {
+         if ((parts[d].start_lba > parts[d + 1].start_lba) && (parts[d].start_lba > 0) && (parts[d + 1].start_lba > 0)) {
+            one_part           = parts[d];
+            parts[d]           = parts[d + 1];
+            parts[d + 1]       = one_part;
+            parts[d].index     = d;
+            parts[d + 1].index = d + 1;
+         } // if
+      } // for
+   } // for
+} // VOID sort_mbr()
+
+// Generate a hybrid MBR based on the current GPT. Stores the result in the
+// new_mbr_parts[] array.
+static VOID generate_hybrid_mbr(VOID) {
+    UINTN i, k, iter, count_active;
+    UINT64 first_used_lba;
+
+    i = 0;
+    new_mbr_part_count = 1;
+    first_used_lba = 0xFFFFFFFF;
+
+    // Copy partitions in three passes....
+    // First, do FAT and NTFS partitions....
+    do {
+        if ((gpt_parts[i].start_lba > 0) && (gpt_parts[i].end_lba > 0) &&
+            (gpt_parts[i].gpt_parttype->kind == GPT_KIND_BASIC_DATA) && /* MS Basic Data GPT type code */
+            (gpt_parts[i].mbr_type != 0x83)) {                          /* Not containing Linux filesystem */
+           copy_gpt_to_new_mbr(i, new_mbr_part_count);
+           if (new_mbr_parts[new_mbr_part_count].start_lba < first_used_lba)
+              first_used_lba = new_mbr_parts[new_mbr_part_count].start_lba;
+
+           new_mbr_part_count++;
+        }
+        i++;
+    } while (i < gpt_part_count && new_mbr_part_count <= 3);
+
+    // Second, do Linux partitions....
+    i = 0;
+    while (i < gpt_part_count && new_mbr_part_count <= 3) {
+        if ((gpt_parts[i].start_lba > 0) && (gpt_parts[i].end_lba > 0) &&
+            ((gpt_parts[i].gpt_parttype->kind == GPT_KIND_DATA) || (gpt_parts[i].gpt_parttype->kind == GPT_KIND_BASIC_DATA)) &&
+            (gpt_parts[i].mbr_type == 0x83)) {
+           copy_gpt_to_new_mbr(i, new_mbr_part_count);
+           if (new_mbr_parts[new_mbr_part_count].start_lba < first_used_lba)
+              first_used_lba = new_mbr_parts[new_mbr_part_count].start_lba;
+
+           new_mbr_part_count++;
+       }
+       i++;
+    } // while
+
+    // Third, do anything that's left to cover uncovered spaces; but this requires
+    // first creating the EFI protective entry, since we don't want to bother with
+    // anything already covered by this entry....
+    new_mbr_parts[0].index     = 0;
+    new_mbr_parts[0].start_lba = 1;
+    new_mbr_parts[0].end_lba   = (disk_size() > first_used_lba) ? (first_used_lba - 1) : disk_size() - 1;
+    new_mbr_parts[0].mbr_type  = 0xee;
+    i = 0;
+    while (i < gpt_part_count && new_mbr_part_count <= 3) {
+       if ((gpt_parts[i].start_lba > new_mbr_parts[0].end_lba) && (gpt_parts[i].end_lba > 0) &&
+           (gpt_parts[i].gpt_parttype->kind != GPT_KIND_BASIC_DATA) &&
+           (gpt_parts[i].mbr_type != 0x83)) {
+          copy_gpt_to_new_mbr(i, new_mbr_part_count);
+          new_mbr_part_count++;
+       }
+       i++;
+    } // while
+
+    // find matching partitions in the old MBR table, copy undetected details....
+    for (i = 1; i < new_mbr_part_count; i++) {
+       for (k = 0; k < mbr_part_count; k++) {
+           if (mbr_parts[k].start_lba == new_mbr_parts[i].start_lba) {
+               // keep type if not detected
+               if (new_mbr_parts[i].mbr_type == 0)
+                   new_mbr_parts[i].mbr_type = mbr_parts[k].mbr_type;
+               // keep active flag
+               new_mbr_parts[i].active = mbr_parts[k].active;
+               break;
+           } // if
+       } // for (k...)
+       if (new_mbr_parts[i].mbr_type == 0) {
+          // final fallback: set to a (hopefully) unused type
+          new_mbr_parts[i].mbr_type = 0xc0;
+       } // if
+    } // for (i...)
+
+    sort_mbr(new_mbr_parts);
+
+    // make sure there's exactly one active partition
+    for (iter = 0; iter < 3; iter++) {
+        // check
+        count_active = 0;
+        for (i = 0; i < new_mbr_part_count; i++)
+            if (new_mbr_parts[i].active)
+                count_active++;
+        if (count_active == 1)
+            break;
+
+        // set active on the first matching partition
+        if (count_active == 0) {
+            for (i = 0; i < new_mbr_part_count; i++) {
+                if ((iter >= 0 && (new_mbr_parts[i].mbr_type == 0x07 ||    // NTFS
+                                   new_mbr_parts[i].mbr_type == 0x0b ||    // FAT32
+                                   new_mbr_parts[i].mbr_type == 0x0c)) ||  // FAT32 (LBA)
+                    (iter >= 1 && (new_mbr_parts[i].mbr_type == 0x83)) ||  // Linux
+                    (iter >= 2 && i > 0)) {
+                    new_mbr_parts[i].active = TRUE;
+                    break;
+                }
+            }
+        } else if (count_active > 1 && iter == 0) {
+            // too many active partitions, try deactivating the ESP / EFI Protective entry
+            if ((new_mbr_parts[0].mbr_type == 0xee || new_mbr_parts[0].mbr_type == 0xef) &&
+                new_mbr_parts[0].active) {
+                new_mbr_parts[0].active = FALSE;
+            }
+        } else if (count_active > 1 && iter > 0) {
+            // too many active partitions, deactivate all but the first one
+            count_active = 0;
+            for (i = 0; i < new_mbr_part_count; i++)
+                if (new_mbr_parts[i].active) {
+                    if (count_active > 0)
+                        new_mbr_parts[i].active = FALSE;
+                    count_active++;
+                }
+        }
+    }
+} // VOID generate_hybrid_mbr()
+
+// Examine partitions and decide whether a rewrite is in order.
+// Note that this function MAY ask user for advice.
+// Note that this function assumes the new hybrid MBR has already
+// been computed and stored in new_mbr_parts[].
+static BOOLEAN should_rewrite(VOID) {
+   BOOLEAN retval = TRUE, all_identical = TRUE, invalid;
+   UINTN i, num_existing_hybrid = 0, num_new_hybrid = 0;
+
+   // Check to see if the proposed table is identical to the current one;
+   // if so, synchronizing is pointless....
+   for (i = 0; i < 4; i++) {
+      if ((new_mbr_parts[i].mbr_type != 0xEE) && (mbr_parts[i].mbr_type != 0xEE) &&
+          ((new_mbr_parts[i].active != mbr_parts[i].active) ||
+           (new_mbr_parts[i].start_lba != mbr_parts[i].start_lba) ||
+           (new_mbr_parts[i].end_lba != mbr_parts[i].end_lba) ||
+           (new_mbr_parts[i].mbr_type != mbr_parts[i].mbr_type)))
+         all_identical = FALSE;
+
+      // while we're looping, count the number of old & new hybrid partitions....
+      if ((mbr_parts[i].mbr_type != 0x00) && (mbr_parts[i].mbr_type != 0xEE))
+         num_existing_hybrid++;
+      if ((new_mbr_parts[i].mbr_type != 0x00) && (new_mbr_parts[i].mbr_type != 0xEE))
+         num_new_hybrid++;
+   } // for
+
+   if (all_identical) {
+      Print(L"Tables are synchronized, no need to sync.\n");
+      return FALSE;
+   }
+
+   // If there's nothing to hybridize, but an existing hybrid MBR exists, offer to replace
+   // the hybrid MBR with a protective MBR.
+   if ((num_new_hybrid == 0) && (num_existing_hybrid > 0)) {
+      Print(L"Found no partitions that could be hybridized, but an existing hybrid MBR exists.\n");
+      Print(L"If you proceed, a fresh protective MBR will be created. Do you want to create\n");
+      invalid = input_boolean(STR("this new protective MBR, erasing the hybrid MBR? [y/N] "), &retval);
+      if (invalid)
+         retval = FALSE;
+   } // if
+
+   // If existing hybrid MBR that's NOT identical to the new one, ask the user
+   // before overwriting the old one.
+   if ((num_new_hybrid > 0) && (num_existing_hybrid > 0)) {
+      Print(L"Existing hybrid MBR detected, but it's not identical to what this program\n");
+      Print(L"would generate. Do you want to see the hybrid MBR that this program would\n");
+      invalid = input_boolean(STR("generate? [y/N] "), &retval);
+      if (invalid)
+         retval = FALSE;
+   } // if
+
+   return retval;
+} // BOOLEAN should_rewrite()
+
+static UINTN analyze(VOID)
+{
+    UINTN   i, detected_parttype;
+    CHARN   *fsname;
+    UINTN   status;
+
+    new_mbr_part_count = 0;
+
+    // determine correct MBR types for GPT partitions
+    if (gpt_part_count == 0) {
+        Print(L"Status: No GPT partitions defined, nothing to sync.\n");
+        return 0;
+    }
+    for (i = 0; i < gpt_part_count; i++) {
+        gpt_parts[i].mbr_type = gpt_parts[i].gpt_parttype->mbr_type;
+        if (gpt_parts[i].gpt_parttype->kind == GPT_KIND_BASIC_DATA) {
+            // Basic Data: need to look at data in the partition
+            status = detect_mbrtype_fs(gpt_parts[i].start_lba, &detected_parttype, &fsname);
+            if (status != 0)
+               Print(L"Warning: Error %d when detecting filesystem type!\n", status);
+            if (detected_parttype)
+                gpt_parts[i].mbr_type = detected_parttype;
+            else
+                gpt_parts[i].mbr_type = 0x0b;  // fallback: FAT32
+        }
+        // NOTE: mbr_type may still be 0 if content detection fails for exotic GPT types or file systems
+    } // for
+
+    // generate the new table
+    generate_hybrid_mbr();
+    if (!should_rewrite())
+       return EFI_ABORTED;
+
+    // display table
+    Print(L"\nProposed new MBR partition table:\n");
+    Print(L" # A    Start LBA      End LBA  Type\n");
+    for (i = 0; i < new_mbr_part_count; i++) {
+        Print(L" %d %s %12lld %12lld  %02x  %s\n",
+              new_mbr_parts[i].index + 1,
+              new_mbr_parts[i].active ? STR("*") : STR(" "),
+              new_mbr_parts[i].start_lba,
+              new_mbr_parts[i].end_lba,
+              new_mbr_parts[i].mbr_type,
+              mbr_parttype_name(new_mbr_parts[i].mbr_type));
+    }
+
+    return 0;
+} // UINTN analyze()
+
+//
+// sync algorithm entry point
+//
+
+UINTN gptsync(VOID)
+{
+    UINTN   status = 0;
+    UINTN   status_gpt, status_mbr;
+    BOOLEAN proceed = FALSE;
+
+    Print(L"gptsync version %s\ncopyright (c) 2006-2007 Christoph Pfisterer & 2013 Roderick W. Smith\n", VERSION);
+
+    // get full information from disk
+    status_gpt = read_gpt();
+    status_mbr = read_mbr();
+    if (status_gpt != 0 || status_mbr != 0)
+        return (status_gpt || status_mbr);
+
+    // cross-check current situation
+    Print(L"\n");
+    status = check_gpt();   // check GPT for consistency
+    if (status != 0)
+        return status;
+    status = check_mbr();   // check MBR for consistency
+    if (status != 0)
+        return status;
+    status = analyze();     // analyze the situation & compose new MBR table
+    if (status != 0)
+        return status;
+    if (new_mbr_part_count == 0)
+        return status;
+
+    // offer user the choice what to do
+    status = input_boolean(STR("\nMay I update the MBR as printed above? [y/N] "), &proceed);
+    if (status != 0 || proceed != TRUE)
+        return status;
+
+    // adjust the MBR and write it back
+    status = write_mbr();
+    if (status != 0)
+        return status;
+
+    return status;
+}
diff --git a/gptsync/gptsync.h b/gptsync/gptsync.h
new file mode 100644 (file)
index 0000000..2a1bbf0
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ * gptsync/gptsync.h
+ * Common header for gptsync and showpart
+ *
+ * Copyright (c) 2006 Christoph Pfisterer
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the
+ *    distribution.
+ *
+ *  * Neither the name of Christoph Pfisterer nor the names of the
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/* Changes copyright (c) 2013 Roderick W. Smith */
+
+#define VERSION L"0.6.9"
+
+//
+// config
+//
+
+#if defined(EFI32) || defined(EFIX64)
+#define CONFIG_EFI
+#endif
+
+//
+// platform-dependent types
+//
+
+#ifdef CONFIG_EFI
+
+#ifdef __MAKEWITH_GNUEFI
+#include "efi.h"
+#include "efilib.h"
+#else
+#include "../include/tiano_includes.h"
+#endif
+
+#define copy_guid(destguid, srcguid) (CopyMem(destguid, srcguid, 16))
+#define guids_are_equal(guid1, guid2) (CompareMem(guid1, guid2, 16) == 0)
+
+typedef CHAR16 CHARN;
+#define STR(x) L##x
+
+#endif
+
+
+#ifndef CONFIG_EFI
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <fcntl.h>
+
+typedef int                 INTN;
+typedef unsigned int        UINTN;
+typedef unsigned char       UINT8;
+typedef unsigned short      UINT16;
+typedef unsigned long       UINT32;
+typedef unsigned long long  UINT64;
+typedef void                VOID;
+
+typedef int                 BOOLEAN;
+#ifndef FALSE
+#define FALSE (0)
+#endif
+#ifndef TRUE
+#define TRUE  (1)
+#endif
+
+typedef unsigned short      CHAR16;
+typedef char                CHARN;
+#define STR(x) x
+
+void Print(wchar_t *format, ...);
+
+// FUTURE: use STR(),  #define Print printf
+
+#define CopyMem     memcpy
+#define SetMem      memset
+#define CompareMem  memcmp
+
+#define copy_guid(destguid, srcguid) (memcpy(destguid, srcguid, 16))
+#define guids_are_equal(guid1, guid2) (memcmp(guid1, guid2, 16) == 0)
+
+#define EFI_UNSUPPORTED 1
+#define EFI_ABORTED     2
+
+#endif
+
+//
+// platform-independent types
+//
+
+typedef struct {
+    UINT8   flags;
+    UINT8   start_chs[3];
+    UINT8   type;
+    UINT8   end_chs[3];
+    UINT32  start_lba;
+    UINT32  size;
+} MBR_PART_INFO;
+
+typedef struct {
+    UINT8   type;
+    CHARN   *name;
+} MBR_PARTTYPE;
+
+typedef struct {
+    UINT64  signature;
+    UINT32  spec_revision;
+    UINT32  header_size;
+    UINT32  header_crc32;
+    UINT32  reserved;
+    UINT64  header_lba;
+    UINT64  alternate_header_lba;
+    UINT64  first_usable_lba;
+    UINT64  last_usable_lba;
+    UINT8   disk_guid[16];
+    UINT64  entry_lba;
+    UINT32  entry_count;
+    UINT32  entry_size;
+    UINT32  entry_crc32;
+} GPT_HEADER;
+
+typedef struct {
+    UINT8   type_guid[16];
+    UINT8   partition_guid[16];
+    UINT64  start_lba;
+    UINT64  end_lba;
+    UINT64  attributes;
+    CHAR16  name[36];
+} GPT_ENTRY;
+
+#define GPT_KIND_SYSTEM     (0)
+#define GPT_KIND_DATA       (1)
+#define GPT_KIND_BASIC_DATA (2)
+#define GPT_KIND_FATAL      (3)
+
+typedef struct {
+    UINT8   guid[16];
+    UINT8   mbr_type;
+    CHARN   *name;
+    UINTN   kind;
+} GPT_PARTTYPE;
+
+typedef struct {
+    UINTN   index;
+    UINT64  start_lba;
+    UINT64  end_lba;
+    UINTN   mbr_type;
+    UINT8   gpt_type[16];
+    GPT_PARTTYPE *gpt_parttype;
+    BOOLEAN active;
+} PARTITION_INFO;
+
+//
+// functions provided by the OS-specific module
+//
+
+UINT64 disk_size(VOID);
+UINTN read_sector(UINT64 lba, UINT8 *buffer);
+UINTN write_sector(UINT64 lba, UINT8 *buffer);
+UINTN input_boolean(CHARN *prompt, BOOLEAN *bool_out);
+
+//
+// vars and functions provided by the common lib module
+//
+
+extern UINT8           empty_guid[16];
+
+extern PARTITION_INFO  mbr_parts[4];
+extern UINTN           mbr_part_count;
+extern PARTITION_INFO  gpt_parts[128];
+extern UINTN           gpt_part_count;
+
+extern PARTITION_INFO  new_mbr_parts[4];
+extern UINTN           new_mbr_part_count;
+
+extern UINT8           sector[512];
+
+extern MBR_PARTTYPE    mbr_types[];
+extern GPT_PARTTYPE    gpt_types[];
+extern GPT_PARTTYPE    gpt_dummy_type;
+
+CHARN * mbr_parttype_name(UINT8 type);
+UINTN read_mbr(VOID);
+
+GPT_PARTTYPE * gpt_parttype(UINT8 *type_guid);
+UINTN read_gpt(VOID);
+
+UINTN detect_mbrtype_fs(UINT64 partlba, UINTN *parttype, CHARN **fsname);
+
+//
+// actual platform-independent programs
+//
+
+UINTN gptsync(VOID);
+UINTN showpart(VOID);
+
+/* EOF */
diff --git a/gptsync/gptsync.mak b/gptsync/gptsync.mak
new file mode 100644 (file)
index 0000000..004f7f7
--- /dev/null
@@ -0,0 +1,71 @@
+#\r
+# gptsync/gptsync.mak\r
+# Build control file for the gptsync tool\r
+# \r
+\r
+#\r
+# Include sdk.env environment\r
+#\r
+\r
+!include $(SDK_INSTALL_DIR)\build\$(SDK_BUILD_ENV)\sdk.env\r
+\r
+#\r
+# Set the base output name and entry point\r
+#\r
+\r
+BASE_NAME         = gptsync\r
+IMAGE_ENTRY_POINT = efi_main\r
+\r
+#\r
+# Globals needed by master.mak\r
+#\r
+\r
+TARGET_APP = $(BASE_NAME)\r
+SOURCE_DIR = $(SDK_INSTALL_DIR)\refit\$(BASE_NAME)\r
+BUILD_DIR  = $(SDK_BUILD_DIR)\refit\$(BASE_NAME)\r
+\r
+#\r
+# Include paths\r
+#\r
+\r
+!include $(SDK_INSTALL_DIR)\include\$(EFI_INC_DIR)\makefile.hdr\r
+INC = -I $(SDK_INSTALL_DIR)\include\$(EFI_INC_DIR) \\r
+      -I $(SDK_INSTALL_DIR)\include\$(EFI_INC_DIR)\$(PROCESSOR) \\r
+      -I $(SDK_INSTALL_DIR)\refit\include $(INC)\r
+\r
+#\r
+# Libraries\r
+#\r
+\r
+LIBS = $(LIBS) $(SDK_BUILD_DIR)\lib\libefi\libefi.lib\r
+\r
+#\r
+# Default target\r
+#\r
+\r
+all : dirs $(LIBS) $(OBJECTS)\r
+       @echo Copying $(BASE_NAME).efi to current directory\r
+       @copy $(SDK_BIN_DIR)\$(BASE_NAME).efi $(BASE_NAME)_$(SDK_BUILD_ENV).efi\r
+\r
+#\r
+# Program object files\r
+#\r
+\r
+OBJECTS = $(OBJECTS) \\r
+    $(BUILD_DIR)\$(BASE_NAME).obj \\r
+    $(BUILD_DIR)\lib.obj \\r
+    $(BUILD_DIR)\os_efi.obj \\r
+\r
+#\r
+# Source file dependencies\r
+#\r
+\r
+$(BUILD_DIR)\$(BASE_NAME).obj : $(*B).c $(INC_DEPS)\r
+$(BUILD_DIR)\lib.obj         : $(*B).c $(INC_DEPS)\r
+$(BUILD_DIR)\os_efi.obj              : $(*B).c $(INC_DEPS)\r
+\r
+#\r
+# Handoff to master.mak\r
+#\r
+\r
+!include $(SDK_INSTALL_DIR)\build\master.mak\r
diff --git a/gptsync/lib.c b/gptsync/lib.c
new file mode 100644 (file)
index 0000000..9a3ad45
--- /dev/null
@@ -0,0 +1,506 @@
+/*
+ * gptsync/lib.c
+ * Platform-independent code common to gptsync and showpart
+ *
+ * Copyright (c) 2006-2007 Christoph Pfisterer
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the
+ *    distribution.
+ *
+ *  * Neither the name of Christoph Pfisterer nor the names of the
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "gptsync.h"
+
+// variables
+
+UINT8           empty_guid[16] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
+
+PARTITION_INFO  mbr_parts[4];
+UINTN           mbr_part_count = 0;
+PARTITION_INFO  gpt_parts[128];
+UINTN           gpt_part_count = 0;
+
+PARTITION_INFO  new_mbr_parts[4];
+UINTN           new_mbr_part_count = 0;
+
+UINT8           sector[512];
+
+MBR_PARTTYPE    mbr_types[] = {
+    { 0x01, STR("FAT12 (CHS)") },
+    { 0x04, STR("FAT16 <32M (CHS)") },
+    { 0x05, STR("Extended (CHS)") },
+    { 0x06, STR("FAT16 (CHS)") },
+    { 0x07, STR("NTFS/HPFS") },
+    { 0x0b, STR("FAT32 (CHS)") },
+    { 0x0c, STR("FAT32 (LBA)") },
+    { 0x0e, STR("FAT16 (LBA)") },
+    { 0x0f, STR("Extended (LBA)") },
+    { 0x11, STR("Hidden FAT12 (CHS)") },
+    { 0x14, STR("Hidden FAT16 <32M (CHS)") },
+    { 0x16, STR("Hidden FAT16 (CHS)") },
+    { 0x17, STR("Hidden NTFS/HPFS") },
+    { 0x1b, STR("Hidden FAT32 (CHS)") },
+    { 0x1c, STR("Hidden FAT32 (LBA)") },
+    { 0x1e, STR("Hidden FAT16 (LBA)") },
+    { 0x82, STR("Linux swap / Solaris") },
+    { 0x83, STR("Linux") },
+    { 0x85, STR("Linux Extended") },
+    { 0x86, STR("NT FAT volume set") },
+    { 0x87, STR("NTFS volume set") },
+    { 0x8e, STR("Linux LVM") },
+    { 0xa5, STR("FreeBSD") },
+    { 0xa6, STR("OpenBSD") },
+    { 0xa7, STR("NeXTSTEP") },
+    { 0xa8, STR("Mac OS X UFS") },
+    { 0xa9, STR("NetBSD") },
+    { 0xab, STR("Mac OS X Boot") },
+    { 0xac, STR("Apple RAID") },
+    { 0xaf, STR("Mac OS X HFS+") },
+    { 0xbe, STR("Solaris Boot") },
+    { 0xbf, STR("Solaris") },
+    { 0xeb, STR("BeOS") },
+    { 0xee, STR("EFI Protective") },
+    { 0xef, STR("EFI System (FAT)") },
+    { 0xfd, STR("Linux RAID") },
+    { 0, NULL },
+};
+
+GPT_PARTTYPE    gpt_types[] = {
+    // Sony uses this one
+    { "\x32\x97\x01\xF4\x6E\x06\x12\x4E\x82\x73\x34\x6C\x56\x41\x49\x4F", 0x00, STR("Sony System (FAT)"), GPT_KIND_FATAL },
+    // Defined by EFI/UEFI specification
+    { "\x28\x73\x2A\xC1\x1F\xF8\xD2\x11\xBA\x4B\x00\xA0\xC9\x3E\xC9\x3B", 0xef, STR("EFI System (FAT)"), GPT_KIND_SYSTEM },
+    { "\x41\xEE\x4D\x02\xE7\x33\xD3\x11\x9D\x69\x00\x08\xC7\x81\xF3\x9F", 0x00, STR("MBR partition scheme"), GPT_KIND_FATAL },
+    // Generally well-known
+    { "\x16\xE3\xC9\xE3\x5C\x0B\xB8\x4D\x81\x7D\xF9\x2D\xF0\x02\x15\xAE", 0x00, STR("MS Reserved"), GPT_KIND_SYSTEM },
+    { "\xA2\xA0\xD0\xEB\xE5\xB9\x33\x44\x87\xC0\x68\xB6\xB7\x26\x99\xC7", 0x00, STR("Basic Data"), GPT_KIND_BASIC_DATA },
+    // From Wikipedia
+    { "\xAA\xC8\x08\x58\x8F\x7E\xE0\x42\x85\xD2\xE1\xE9\x04\x34\xCF\xB3", 0x00, STR("MS LDM Metadata"), GPT_KIND_FATAL },
+    { "\xA0\x60\x9B\xAF\x31\x14\x62\x4F\xBC\x68\x33\x11\x71\x4A\x69\xAD", 0x00, STR("MS LDM Data"), GPT_KIND_FATAL },
+    { "\x1E\x4C\x89\x75\xEB\x3A\xD3\x11\xB7\xC1\x7B\x03\xA0\x00\x00\x00", 0x00, STR("HP/UX Data"), GPT_KIND_DATA },
+    { "\x28\xE7\xA1\xE2\xE3\x32\xD6\x11\xA6\x82\x7B\x03\xA0\x00\x00\x00", 0x00, STR("HP/UX Service"), GPT_KIND_SYSTEM },
+    // From Linux repository, fs/partitions/efi.h
+    { "\x0F\x88\x9D\xA1\xFC\x05\x3B\x4D\xA0\x06\x74\x3F\x0F\x84\x91\x1E", 0xfd, STR("Linux RAID"), GPT_KIND_DATA },
+    { "\x6D\xFD\x57\x06\xAB\xA4\xC4\x43\x84\xE5\x09\x33\xC8\x4B\x4F\x4F", 0x82, STR("Linux Swap"), GPT_KIND_SYSTEM },
+    { "\x79\xD3\xD6\xE6\x07\xF5\xC2\x44\xA2\x3C\x23\x8F\x2A\x3D\xF9\x28", 0x8e, STR("Linux LVM"), GPT_KIND_DATA },
+    { "\xAF\x3D\xC6\x0F\x83\x84\x72\x47\x8E\x79\x3D\x69\xD8\x47\x7D\xE4", 0x83, STR("Linux Filesystem"), GPT_KIND_DATA },
+    // From Wikipedia
+    { "\x39\x33\xA6\x8D\x07\x00\xC0\x60\xC4\x36\x08\x3A\xC8\x23\x09\x08", 0x00, STR("Linux Reserved"), GPT_KIND_SYSTEM },
+    // From grub2 repository, grub/include/grub/gpt_partition.h
+    { "\x48\x61\x68\x21\x49\x64\x6F\x6E\x74\x4E\x65\x65\x64\x45\x46\x49", 0x00, STR("GRUB2 BIOS Boot"), GPT_KIND_SYSTEM },
+    // From FreeBSD repository, sys/sys/gpt.h
+    { "\xB4\x7C\x6E\x51\xCF\x6E\xD6\x11\x8F\xF8\x00\x02\x2D\x09\x71\x2B", 0xa5, STR("FreeBSD Data"), GPT_KIND_DATA },
+    { "\xB5\x7C\x6E\x51\xCF\x6E\xD6\x11\x8F\xF8\x00\x02\x2D\x09\x71\x2B", 0x00, STR("FreeBSD Swap"), GPT_KIND_SYSTEM },
+    { "\xB6\x7C\x6E\x51\xCF\x6E\xD6\x11\x8F\xF8\x00\x02\x2D\x09\x71\x2B", 0xa5, STR("FreeBSD UFS"), GPT_KIND_DATA },
+    { "\xB8\x7C\x6E\x51\xCF\x6E\xD6\x11\x8F\xF8\x00\x02\x2D\x09\x71\x2B", 0x00, STR("FreeBSD Vinum"), GPT_KIND_DATA },
+    { "\xBA\x7C\x6E\x51\xCF\x6E\xD6\x11\x8F\xF8\x00\x02\x2D\x09\x71\x2B", 0xa5, STR("FreeBSD ZFS"), GPT_KIND_DATA },
+    { "\x9D\x6B\xBD\x83\x41\x7F\xDC\x11\xBE\x0B\x00\x15\x60\xB8\x4F\x0F", 0xa5, STR("FreeBSD Boot"), GPT_KIND_DATA },
+    // From NetBSD repository, sys/sys/disklabel_gpt.h
+    { "\x32\x8D\xF4\x49\x0E\xB1\xDC\x11\xB9\x9B\x00\x19\xD1\x87\x96\x48", 0x00, STR("NetBSD Swap"), GPT_KIND_SYSTEM },
+    { "\x5A\x8D\xF4\x49\x0E\xB1\xDC\x11\xB9\x9B\x00\x19\xD1\x87\x96\x48", 0xa9, STR("NetBSD FFS"), GPT_KIND_DATA },
+    { "\x82\x8D\xF4\x49\x0E\xB1\xDC\x11\xB9\x9B\x00\x19\xD1\x87\x96\x48", 0xa9, STR("NetBSD LFS"), GPT_KIND_DATA },
+    { "\xAA\x8D\xF4\x49\x0E\xB1\xDC\x11\xB9\x9B\x00\x19\xD1\x87\x96\x48", 0xa9, STR("NetBSD RAID"), GPT_KIND_DATA },
+    { "\xC4\x19\xB5\x2D\x0E\xB1\xDC\x11\xB9\x9B\x00\x19\xD1\x87\x96\x48", 0xa9, STR("NetBSD CCD"), GPT_KIND_DATA },
+    { "\xEC\x19\xB5\x2D\x0E\xB1\xDC\x11\xB9\x9B\x00\x19\xD1\x87\x96\x48", 0xa9, STR("NetBSD CGD"), GPT_KIND_DATA },
+    // From http://developer.apple.com/mac/library/technotes/tn2006/tn2166.html
+//    { "\x00\x53\x46\x48\x00\x00\xAA\x11\xAA\x11\x00\x30\x65\x43\xEC\xAC", 0x00, STR("Mac OS X HFS+"), GPT_KIND_SYSTEM },
+    { "\x00\x53\x46\x48\x00\x00\xAA\x11\xAA\x11\x00\x30\x65\x43\xEC\xAC", 0xaf, STR("Mac OS X HFS+"), GPT_KIND_DATA },
+    { "\x00\x53\x46\x55\x00\x00\xAA\x11\xAA\x11\x00\x30\x65\x43\xEC\xAC", 0xa8, STR("Mac OS X UFS"), GPT_KIND_DATA },
+    { "\x74\x6F\x6F\x42\x00\x00\xAA\x11\xAA\x11\x00\x30\x65\x43\xEC\xAC", 0xab, STR("Mac OS X Boot"), GPT_KIND_DATA },
+    { "\x44\x49\x41\x52\x00\x00\xAA\x11\xAA\x11\x00\x30\x65\x43\xEC\xAC", 0xac, STR("Apple RAID"), GPT_KIND_DATA },
+    { "\x44\x49\x41\x52\x4F\x5F\xAA\x11\xAA\x11\x00\x30\x65\x43\xEC\xAC", 0xac, STR("Apple RAID (Offline)"), GPT_KIND_DATA },
+    { "\x65\x62\x61\x4C\x00\x6C\xAA\x11\xAA\x11\x00\x30\x65\x43\xEC\xAC", 0x00, STR("Apple Label"), GPT_KIND_SYSTEM },
+    // From Wikipedia
+    { "\x6F\x63\x65\x52\x65\x76\xAA\x11\xAA\x11\x00\x30\x65\x43\xEC\xAC", 0x00, STR("Apple TV Recovery"), GPT_KIND_DATA },
+    // From OpenSolaris repository, usr/src/uts/common/sys/efi_partition.h
+    { "\x7f\x23\x96\x6A\xD2\x1D\xB2\x11\x99\xa6\x08\x00\x20\x73\x66\x31", 0x00, STR("Solaris Reserved"), GPT_KIND_SYSTEM },
+    { "\x45\xCB\x82\x6A\xD2\x1D\xB2\x11\x99\xa6\x08\x00\x20\x73\x66\x31", 0xbf, STR("Solaris Boot"), GPT_KIND_DATA },
+    { "\x4D\xCF\x85\x6A\xD2\x1D\xB2\x11\x99\xa6\x08\x00\x20\x73\x66\x31", 0xbf, STR("Solaris Root"), GPT_KIND_DATA },
+    { "\x6F\xC4\x87\x6A\xD2\x1D\xB2\x11\x99\xa6\x08\x00\x20\x73\x66\x31", 0x00, STR("Solaris Swap"), GPT_KIND_SYSTEM },
+    { "\xC3\x8C\x89\x6A\xD2\x1D\xB2\x11\x99\xa6\x08\x00\x20\x73\x66\x31", 0xbf, STR("Solaris Usr / Apple ZFS"), GPT_KIND_DATA },
+    { "\x2B\x64\x8B\x6A\xD2\x1D\xB2\x11\x99\xa6\x08\x00\x20\x73\x66\x31", 0x00, STR("Solaris Backup"), GPT_KIND_SYSTEM },
+    { "\xC7\x2A\x8D\x6A\xD2\x1D\xB2\x11\x99\xa6\x08\x00\x20\x73\x66\x31", 0x00, STR("Solaris Reserved (Stand)"), GPT_KIND_SYSTEM },
+    { "\xE9\xF2\x8E\x6A\xD2\x1D\xB2\x11\x99\xa6\x08\x00\x20\x73\x66\x31", 0xbf, STR("Solaris Var"), GPT_KIND_DATA },
+    { "\x39\xBA\x90\x6A\xD2\x1D\xB2\x11\x99\xa6\x08\x00\x20\x73\x66\x31", 0xbf, STR("Solaris Home"), GPT_KIND_DATA },
+    { "\xA5\x83\x92\x6A\xD2\x1D\xB2\x11\x99\xa6\x08\x00\x20\x73\x66\x31", 0x00, STR("Solaris Alternate Sector"), GPT_KIND_SYSTEM },
+    { "\x3B\x5A\x94\x6A\xD2\x1D\xB2\x11\x99\xa6\x08\x00\x20\x73\x66\x31", 0x00, STR("Solaris Reserved (Cache)"), GPT_KIND_SYSTEM },
+    { "\xD1\x30\x96\x6A\xD2\x1D\xB2\x11\x99\xa6\x08\x00\x20\x73\x66\x31", 0x00, STR("Solaris Reserved"), GPT_KIND_SYSTEM },
+    { "\x67\x07\x98\x6A\xD2\x1D\xB2\x11\x99\xa6\x08\x00\x20\x73\x66\x31", 0x00, STR("Solaris Reserved"), GPT_KIND_SYSTEM },
+    // List sentinel
+    { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, NULL, 0 },
+};
+GPT_PARTTYPE    gpt_dummy_type =
+    { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, STR("Unknown"), GPT_KIND_FATAL };
+
+//
+// MBR functions
+//
+
+CHARN * mbr_parttype_name(UINT8 type)
+{
+    int i;
+
+    for (i = 0; mbr_types[i].name; i++)
+        if (mbr_types[i].type == type)
+            return mbr_types[i].name;
+    return STR("Unknown");
+}
+
+UINTN read_mbr(VOID)
+{
+    UINTN               status;
+    UINTN               i;
+    BOOLEAN             used;
+    MBR_PART_INFO       *table;
+
+    Print(L"\nCurrent MBR partition table:\n");
+
+    // read MBR data
+    status = read_sector(0, sector);
+    if (status != 0)
+        return status;
+
+    // check for validity
+    if (*((UINT16 *)(sector + 510)) != 0xaa55) {
+        Print(L" No MBR partition table present!\n");
+        return 1;
+    }
+    table = (MBR_PART_INFO *)(sector + 446);
+    for (i = 0; i < 4; i++) {
+        if (table[i].flags != 0x00 && table[i].flags != 0x80) {
+            Print(L" MBR partition table is invalid!\n");
+            return 1;
+        }
+    }
+
+    // check if used
+    used = FALSE;
+    for (i = 0; i < 4; i++) {
+        if (table[i].start_lba > 0 && table[i].size > 0) {
+            used = TRUE;
+            break;
+        }
+    }
+    if (!used) {
+        Print(L" No partitions defined\n");
+        return 0;
+    }
+
+    // dump current state & fill internal structures
+    Print(L" # A    Start LBA      End LBA  Type\n");
+    for (i = 0; i < 4; i++) {
+        if (table[i].start_lba == 0 || table[i].size == 0)
+            continue;
+
+        mbr_parts[mbr_part_count].index     = i;
+        mbr_parts[mbr_part_count].start_lba = (UINT64)table[i].start_lba;
+        mbr_parts[mbr_part_count].end_lba   = (UINT64)table[i].start_lba + (UINT64)table[i].size - 1;
+        mbr_parts[mbr_part_count].mbr_type  = table[i].type;
+        mbr_parts[mbr_part_count].active    = (table[i].flags == 0x80) ? TRUE : FALSE;
+
+        Print(L" %d %s %12lld %12lld  %02x  %s\n",
+              mbr_parts[mbr_part_count].index + 1,
+              mbr_parts[mbr_part_count].active ? STR("*") : STR(" "),
+              mbr_parts[mbr_part_count].start_lba,
+              mbr_parts[mbr_part_count].end_lba,
+              mbr_parts[mbr_part_count].mbr_type,
+              mbr_parttype_name(mbr_parts[mbr_part_count].mbr_type));
+
+        mbr_part_count++;
+    }
+
+    return 0;
+}
+
+//
+// GPT functions
+//
+
+GPT_PARTTYPE * gpt_parttype(UINT8 *type_guid)
+{
+    int i;
+
+    for (i = 0; gpt_types[i].name; i++)
+        if (guids_are_equal(gpt_types[i].guid, type_guid))
+            return &(gpt_types[i]);
+    return &gpt_dummy_type;
+}
+
+UINTN read_gpt(VOID)
+{
+    UINTN       status;
+    GPT_HEADER  *header;
+    GPT_ENTRY   *entry;
+    UINT64      entry_lba;
+    UINTN       entry_count, entry_size, i;
+
+    Print(L"\nCurrent GUID partition table:\n");
+
+    // read GPT header
+    status = read_sector(1, sector);
+    if (status != 0)
+        return status;
+
+    // check signature
+    header = (GPT_HEADER *)sector;
+    if (header->signature != 0x5452415020494645ULL) {
+        Print(L" No GPT partition table present!\n");
+        return 0;
+    }
+    if (header->spec_revision != 0x00010000UL) {
+        Print(L" Warning: Unknown GPT spec revision 0x%08x\n", header->spec_revision);
+    }
+    if ((512 % header->entry_size) > 0 || header->entry_size > 512) {
+        Print(L" Error: Invalid GPT entry size (misaligned or more than 512 bytes)\n");
+        return 0;
+    }
+
+    // read entries
+    entry_lba   = header->entry_lba;
+    entry_size  = header->entry_size;
+    entry_count = header->entry_count;
+
+    for (i = 0; i < entry_count; i++) {
+        if (((i * entry_size) % 512) == 0) {
+            status = read_sector(entry_lba, sector);
+            if (status != 0)
+                return status;
+            entry_lba++;
+        }
+        entry = (GPT_ENTRY *)(sector + ((i * entry_size) % 512));
+
+        if (guids_are_equal(entry->type_guid, empty_guid))
+            continue;
+        if (gpt_part_count == 0) {
+            Print(L" #      Start LBA      End LBA  Type\n");
+        }
+
+        gpt_parts[gpt_part_count].index     = i;
+        gpt_parts[gpt_part_count].start_lba = entry->start_lba;
+        gpt_parts[gpt_part_count].end_lba   = entry->end_lba;
+        gpt_parts[gpt_part_count].mbr_type  = 0;
+        copy_guid(gpt_parts[gpt_part_count].gpt_type, entry->type_guid);
+        gpt_parts[gpt_part_count].gpt_parttype = gpt_parttype(gpt_parts[gpt_part_count].gpt_type);
+        gpt_parts[gpt_part_count].active    = FALSE;
+
+        Print(L" %d   %12lld %12lld  %s\n",
+              gpt_parts[gpt_part_count].index + 1,
+              gpt_parts[gpt_part_count].start_lba,
+              gpt_parts[gpt_part_count].end_lba,
+              gpt_parts[gpt_part_count].gpt_parttype->name);
+
+        gpt_part_count++;
+    }
+    if (gpt_part_count == 0) {
+        Print(L" No partitions defined\n");
+        return 0;
+    }
+
+    return 0;
+}
+
+//
+// detect file system type
+//
+
+UINTN detect_mbrtype_fs(UINT64 partlba, UINTN *parttype, CHARN **fsname)
+{
+    UINTN   status;
+    UINTN   signature, score;
+    UINTN   sectsize, clustersize, reserved, fatcount, dirsize, sectcount, fatsize, clustercount;
+
+    *fsname = STR("Unknown");
+    *parttype = 0;
+
+    // READ sector 0 / offset 0K
+    status = read_sector(partlba, sector);
+    if (status != 0)
+        return status;
+
+    // detect XFS
+    signature = *((UINT32 *)(sector));
+    if (signature == 0x42534658) {
+        *parttype = 0x83;
+        *fsname = STR("XFS");
+        return 0;
+    }
+
+    // detect FAT and NTFS
+    sectsize = *((UINT16 *)(sector + 11));
+    clustersize = sector[13];
+    if (sectsize >= 512 && (sectsize & (sectsize - 1)) == 0 &&
+        clustersize > 0 && (clustersize & (clustersize - 1)) == 0) {
+        // preconditions for both FAT and NTFS are now met
+
+        if (CompareMem(sector + 3, "NTFS    ", 8) == 0) {
+            *parttype = 0x07;
+            *fsname = STR("NTFS");
+            return 0;
+        }
+
+        score = 0;
+        // boot jump
+        if ((sector[0] == 0xEB && sector[2] == 0x90) || 
+            sector[0] == 0xE9)
+            score++;
+        // boot signature
+        if (sector[510] == 0x55 && sector[511] == 0xAA)
+            score++;
+        // reserved sectors
+        reserved = *((UINT16 *)(sector + 14));
+        if (reserved == 1 || reserved == 32)
+            score++;
+        // number of FATs
+        fatcount = sector[16];
+        if (fatcount == 2)
+            score++;
+        // number of root dir entries
+        dirsize = *((UINT16 *)(sector + 17));
+        // sector count (16-bit and 32-bit versions)
+        sectcount = *((UINT16 *)(sector + 19));
+        if (sectcount == 0)
+            sectcount = *((UINT32 *)(sector + 32));
+        // media byte
+        if (sector[21] == 0xF0 || sector[21] >= 0xF8)
+            score++;
+        // FAT size in sectors
+        fatsize = *((UINT16 *)(sector + 22));
+        if (fatsize == 0)
+            fatsize = *((UINT32 *)(sector + 36));
+
+        // determine FAT type
+        dirsize = ((dirsize * 32) + (sectsize - 1)) / sectsize;
+        clustercount = sectcount - (reserved + (fatcount * fatsize) + dirsize);
+        clustercount /= clustersize;
+
+        if (score >= 3) {
+            if (clustercount < 4085) {
+                *parttype = 0x01;
+                *fsname = STR("FAT12");
+            } else if (clustercount < 65525) {
+                *parttype = 0x0e;
+                *fsname = STR("FAT16");
+            } else {
+                *parttype = 0x0c;
+                *fsname = STR("FAT32");
+            }
+            // TODO: check if 0e and 0c are okay to use, maybe we should use 06 and 0b instead...
+            return 0;
+        }
+    }
+
+    // READ sector 2 / offset 1K
+    status = read_sector(partlba + 2, sector);
+    if (status != 0)
+        return status;
+
+    // detect HFS+
+    signature = *((UINT16 *)(sector));
+    if (signature == 0x4442) {
+        *parttype = 0xaf;
+        if (*((UINT16 *)(sector + 0x7c)) == 0x2B48)
+            *fsname = STR("HFS Extended (HFS+)");
+        else
+            *fsname = STR("HFS Standard");
+        return 0;
+    } else if (signature == 0x2B48) {
+        *parttype = 0xaf;
+        *fsname = STR("HFS Extended (HFS+)");
+        return 0;
+    }
+
+    // detect ext2/ext3/ext4
+    signature = *((UINT16 *)(sector + 56));
+    if (signature == 0xEF53) {
+        *parttype = 0x83;
+        if (*((UINT16 *)(sector + 96)) & 0x02C0 ||
+            *((UINT16 *)(sector + 100)) & 0x0078)
+            *fsname = STR("ext4");
+        else if (*((UINT16 *)(sector + 92)) & 0x0004)
+            *fsname = STR("ext3");
+        else
+            *fsname = STR("ext2");
+        return 0;
+    }
+
+    // READ sector 128 / offset 64K
+    status = read_sector(partlba + 128, sector);
+    if (status != 0)
+        return status;
+
+    // detect btrfs
+    if (CompareMem(sector + 64, "_BHRfS_M", 8) == 0) {
+        *parttype = 0x83;
+        *fsname = STR("btrfs");
+        return 0;
+    }
+
+    // detect ReiserFS
+    if (CompareMem(sector + 52, "ReIsErFs", 8) == 0 ||
+        CompareMem(sector + 52, "ReIsEr2Fs", 9) == 0 ||
+        CompareMem(sector + 52, "ReIsEr3Fs", 9) == 0) {
+        *parttype = 0x83;
+        *fsname = STR("ReiserFS");
+        return 0;
+    }
+
+    // detect Reiser4
+    if (CompareMem(sector, "ReIsEr4", 7) == 0) {
+        *parttype = 0x83;
+        *fsname = STR("Reiser4");
+        return 0;
+    }
+
+    // READ sector 64 / offset 32K
+    status = read_sector(partlba + 64, sector);
+    if (status != 0)
+        return status;
+
+    // detect JFS
+    if (CompareMem(sector, "JFS1", 4) == 0) {
+        *parttype = 0x83;
+        *fsname = STR("JFS");
+        return 0;
+    }
+
+    // READ sector 16 / offset 8K
+    status = read_sector(partlba + 16, sector);
+    if (status != 0)
+        return status;
+
+    // detect ReiserFS
+    if (CompareMem(sector + 52, "ReIsErFs", 8) == 0 ||
+        CompareMem(sector + 52, "ReIsEr2Fs", 9) == 0 ||
+        CompareMem(sector + 52, "ReIsEr3Fs", 9) == 0) {
+        *parttype = 0x83;
+        *fsname = STR("ReiserFS");
+        return 0;
+    }
+
+    return 0;
+}
diff --git a/gptsync/os_efi.c b/gptsync/os_efi.c
new file mode 100644 (file)
index 0000000..91ee3a7
--- /dev/null
@@ -0,0 +1,274 @@
+/*
+ * gptsync/os_efi.c
+ * EFI glue for gptsync
+ *
+ * Copyright (c) 2006 Christoph Pfisterer
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the
+ *    distribution.
+ *
+ *  * Neither the name of Christoph Pfisterer nor the names of the
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "gptsync.h"
+#include "refit_call_wrapper.h"
+#ifdef __MAKEWITH_TIANO
+//#include "tiano_includes.h"
+#include "AutoGen.h"
+#endif
+
+// variables
+
+EFI_BLOCK_IO    *BlockIO = NULL;
+
+//
+// sector I/O functions
+//
+
+// Returns size of disk in blocks
+UINT64 disk_size(VOID) {
+   return (UINT64) BlockIO->Media->LastBlock;
+} // UINT64 disk_size()
+
+UINTN read_sector(UINT64 lba, UINT8 *buffer)
+{
+    EFI_STATUS          Status;
+
+    Status = refit_call5_wrapper(BlockIO->ReadBlocks, BlockIO, BlockIO->Media->MediaId, lba, 512, buffer);
+    if (EFI_ERROR(Status)) {
+        // TODO: report error
+        return 1;
+    }
+    return 0;
+}
+
+UINTN write_sector(UINT64 lba, UINT8 *buffer)
+{
+    EFI_STATUS          Status;
+
+    Status = refit_call5_wrapper(BlockIO->WriteBlocks, BlockIO, BlockIO->Media->MediaId, lba, 512, buffer);
+    if (EFI_ERROR(Status)) {
+        // TODO: report error
+        return 1;
+    }
+    return 0;
+}
+
+//
+// Keyboard input
+//
+
+static BOOLEAN ReadAllKeyStrokes(VOID)
+{
+    EFI_STATUS          Status;
+    BOOLEAN             GotKeyStrokes;
+    EFI_INPUT_KEY       Key;
+
+    GotKeyStrokes = FALSE;
+    for (;;) {
+        Status = refit_call2_wrapper(ST->ConIn->ReadKeyStroke, ST->ConIn, &Key);
+        if (Status == EFI_SUCCESS) {
+            GotKeyStrokes = TRUE;
+            continue;
+        }
+        break;
+    }
+    return GotKeyStrokes;
+}
+
+static VOID PauseForKey(VOID)
+{
+    UINTN               Index;
+
+    Print(L"\n* Hit any key to continue *");
+
+    if (ReadAllKeyStrokes()) {  // remove buffered key strokes
+        refit_call1_wrapper(BS->Stall, 5000000);     // 5 seconds delay
+        ReadAllKeyStrokes();    // empty the buffer again
+    }
+
+    refit_call3_wrapper(BS->WaitForEvent, 1, &ST->ConIn->WaitForKey, &Index);
+    ReadAllKeyStrokes();        // empty the buffer to protect the menu
+
+    Print(L"\n");
+}
+
+UINTN input_boolean(CHARN *prompt, BOOLEAN *bool_out)
+{
+    EFI_STATUS          Status;
+    UINTN               Index;
+    EFI_INPUT_KEY       Key;
+
+    Print(prompt);
+
+    if (ReadAllKeyStrokes()) {  // remove buffered key strokes
+        refit_call1_wrapper(BS->Stall, 500000);      // 0.5 seconds delay
+        ReadAllKeyStrokes();    // empty the buffer again
+    }
+
+    refit_call3_wrapper(BS->WaitForEvent, 1, &ST->ConIn->WaitForKey, &Index);
+    Status = refit_call2_wrapper(ST->ConIn->ReadKeyStroke, ST->ConIn, &Key);
+    if (EFI_ERROR(Status))
+        return 1;
+
+    if (Key.UnicodeChar == 'y' || Key.UnicodeChar == 'Y') {
+        Print(L"Yes\n");
+        *bool_out = TRUE;
+    } else {
+        Print(L"No\n");
+        *bool_out = FALSE;
+    }
+
+    ReadAllKeyStrokes();
+    return 0;
+}
+
+#ifdef __MAKEWITH_TIANO
+
+extern EFI_DXE_SERVICES  *gDS;
+
+// EFI_GUID gEfiDxeServicesTableGuid = { 0x05AD34BA, 0x6F02, 0x4214, { 0x95, 0x2E, 0x4D, 0xA0, 0x39, 0x8E, 0x2B, 0xB9 }};
+
+// Minimal initialization function
+static VOID InitializeLib(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable) {
+   gST            = SystemTable;
+   //    gImageHandle   = ImageHandle;
+   gBS            = SystemTable->BootServices;
+   //    gRS            = SystemTable->RuntimeServices;
+   gRT = SystemTable->RuntimeServices; // Some BDS functions need gRT to be set
+//   EfiGetSystemConfigurationTable (&gEfiDxeServicesTableGuid, (VOID **) &gDS);
+
+//   InitializeConsoleSim();
+}
+
+// EFI_GUID gEfiBlockIoProtocolGuid = { 0x964E5B21, 0x6459, 0x11D2, { 0x8E, 0x39, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B }};
+
+#define LibLocateHandle gBS->LocateHandleBuffer
+#define BlockIoProtocol gEfiBlockIoProtocolGuid
+
+#endif
+
+// Check firmware vendor; get verification to continue if it's not Apple.
+// Returns TRUE if Apple firmware or if user assents to use, FALSE otherwise.
+static BOOLEAN VerifyGoOn(VOID) {
+   BOOLEAN GoOn = TRUE;
+   UINTN invalid;
+
+   if (StriCmp(L"Apple", ST->FirmwareVendor) != 0) {
+      Print(L"Your firmware is made by %s.\n", ST->FirmwareVendor);
+      Print(L"Ordinarily, a hybrid MBR (which this program creates) should be used ONLY on\n");
+      Print(L"Apple Macs that dual-boot with Windows or some other BIOS-mode OS. Are you\n");
+      invalid = input_boolean(STR("SURE you want to continue? [y/N] "), &GoOn);
+      if (invalid)
+         GoOn = FALSE;
+   }
+   return GoOn;
+} // BOOLEAN VerifyGoOn()
+
+//
+// main entry point
+//
+
+EFI_STATUS
+EFIAPI
+efi_main    (IN EFI_HANDLE           ImageHandle,
+             IN EFI_SYSTEM_TABLE     *SystemTable)
+{
+    EFI_STATUS          Status;
+    UINTN               SyncStatus;
+    UINTN               Index;
+    UINTN               HandleCount;
+    EFI_HANDLE          *HandleBuffer;
+    EFI_HANDLE          DeviceHandle;
+    EFI_DEVICE_PATH     *DevicePath, *NextDevicePath;
+    BOOLEAN             Usable;
+
+    InitializeLib(ImageHandle, SystemTable);
+
+    Status = refit_call5_wrapper(BS->LocateHandleBuffer, ByProtocol, &BlockIoProtocol, NULL, &HandleCount, &HandleBuffer);
+    if (EFI_ERROR (Status)) {
+        Status = EFI_NOT_FOUND;
+        return Status;
+    }
+
+    if (!VerifyGoOn())
+       return EFI_ABORTED;
+
+    for (Index = 0; Index < HandleCount; Index++) {
+
+        DeviceHandle = HandleBuffer[Index];
+
+        // check device path
+        DevicePath = DevicePathFromHandle(DeviceHandle);
+        Usable = TRUE;
+        while (DevicePath != NULL && !IsDevicePathEndType(DevicePath)) {
+            NextDevicePath = NextDevicePathNode(DevicePath);
+
+            if (DevicePathType(DevicePath) == MESSAGING_DEVICE_PATH &&
+                (DevicePathSubType(DevicePath) == MSG_USB_DP ||
+                 DevicePathSubType(DevicePath) == MSG_USB_CLASS_DP ||
+                 DevicePathSubType(DevicePath) == MSG_1394_DP ||
+                 DevicePathSubType(DevicePath) == MSG_FIBRECHANNEL_DP))
+                Usable = FALSE;         // USB/FireWire/FC device
+            if (DevicePathType(DevicePath) == MEDIA_DEVICE_PATH)
+                Usable = FALSE;         // partition, El Torito entry, legacy BIOS device
+
+            DevicePath = NextDevicePath;
+        }
+        if (!Usable)
+            continue;
+
+        Status = refit_call3_wrapper(BS->HandleProtocol, DeviceHandle, &BlockIoProtocol, (VOID **) &BlockIO);
+        if (EFI_ERROR(Status)) {
+            // TODO: report error
+            BlockIO = NULL;
+        } else {
+            if (BlockIO->Media->BlockSize != 512)
+                BlockIO = NULL;    // optical media
+            else
+                break;
+        }
+
+    }
+
+    FreePool (HandleBuffer);
+
+    if (BlockIO == NULL) {
+        Print(L"Internal hard disk device not found!\n");
+        return EFI_NOT_FOUND;
+    }
+
+    SyncStatus = gptsync();
+
+    if (SyncStatus == 0)
+        PauseForKey();
+
+
+    if (SyncStatus)
+        return EFI_NOT_FOUND;
+    return EFI_SUCCESS;
+}
diff --git a/gptsync/os_unix.c b/gptsync/os_unix.c
new file mode 100644 (file)
index 0000000..a1df9bc
--- /dev/null
@@ -0,0 +1,272 @@
+/*
+ * gptsync/os_unix.c
+ * Unix OS glue for gptsync
+ *
+ * Copyright (c) 2006 Christoph Pfisterer
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the
+ *    distribution.
+ *
+ *  * Neither the name of Christoph Pfisterer nor the names of the
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "gptsync.h"
+
+#include <stdarg.h>
+
+#define STRINGIFY(s) #s
+#define STRINGIFY2(s) STRINGIFY(s)
+#define PROGNAME_S STRINGIFY2(PROGNAME)
+
+// variables
+
+static int      fd;
+
+//
+// error functions
+//
+
+void error(const char *msg, ...)
+{
+    va_list par;
+    char buf[4096];
+
+    va_start(par, msg);
+    vsnprintf(buf, 4096, msg, par);
+    va_end(par);
+
+    fprintf(stderr, PROGNAME_S ": %s\n", buf);
+}
+
+void errore(const char *msg, ...)
+{
+    va_list par;
+    char buf[4096];
+
+    va_start(par, msg);
+    vsnprintf(buf, 4096, msg, par);
+    va_end(par);
+
+    fprintf(stderr, PROGNAME_S ": %s: %s\n", buf, strerror(errno));
+}
+
+//
+// sector I/O functions
+//
+
+// Returns size of disk in blocks (currently bogus)
+UINT64 disk_size(VOID) {
+   return (UINT64) 0xFFFFFFFF;
+} // UINT64 disk_size()
+
+UINTN read_sector(UINT64 lba, UINT8 *buffer)
+{
+    off_t   offset;
+    off_t   result_seek;
+    ssize_t result_read;
+
+    offset = lba * 512;
+    result_seek = lseek(fd, offset, SEEK_SET);
+    if (result_seek != offset) {
+        errore("Seek to %llu failed", offset);
+        return 1;
+    }
+
+    result_read = read(fd, buffer, 512);
+    if (result_read < 0) {
+        errore("Data read failed at position %llu", offset);
+        return 1;
+    }
+    if (result_read != 512) {
+        errore("Data read fell short at position %llu", offset);
+        return 1;
+    }
+    return 0;
+}
+
+UINTN write_sector(UINT64 lba, UINT8 *buffer)
+{
+    off_t   offset;
+    off_t   result_seek;
+    ssize_t result_write;
+
+    offset = lba * 512;
+    result_seek = lseek(fd, offset, SEEK_SET);
+    if (result_seek != offset) {
+        errore("Seek to %llu failed", offset);
+        return 1;
+    }
+
+    result_write = write(fd, buffer, 512);
+    if (result_write < 0) {
+        errore("Data write failed at position %llu", offset);
+        return 1;
+    }
+    if (result_write != 512) {
+        errore("Data write fell short at position %llu", offset);
+        return 1;
+    }
+    return 0;
+}
+
+//
+// keyboard input
+//
+
+UINTN input_boolean(CHARN *prompt, BOOLEAN *bool_out)
+{
+    int c;
+
+    printf("%s", prompt);
+    fflush(NULL);
+
+    c = getchar();
+    if (c == EOF)
+        return 1;
+
+    if (c == 'y' || c == 'Y') {
+        printf("Yes\n");
+        *bool_out = TRUE;
+    } else {
+        printf("No\n");
+        *bool_out = FALSE;
+    }
+
+    return 0;
+}
+
+//
+// EFI-style print function
+//
+
+void Print(wchar_t *format, ...)
+{
+    va_list par;
+    char formatbuf[256];
+    char buf[4096];
+    int i;
+
+    for (i = 0; format[i]; i++)
+        formatbuf[i] = (format[i] > 255) ? '?' : (char)(format[i] & 0xff);
+    formatbuf[i] = 0;
+
+    va_start(par, format);
+    vsnprintf(buf, 4096, formatbuf, par);
+    va_end(par);
+
+    printf("%s", buf);
+}
+
+//
+// main entry point
+//
+
+int main(int argc, char *argv[])
+{
+    char        *filename;
+    struct stat sb;
+    int         filekind;
+    UINT64      filesize;
+    char        *reason;
+    int         status;
+
+    // argument check
+    if (argc != 2) {
+        fprintf(stderr, "Usage: " PROGNAME_S " <device>\n");
+        return 1;
+    }
+    filename = argv[1];
+
+    // set input to unbuffered
+    fflush(NULL);
+    setvbuf(stdin, NULL, _IONBF, 0);
+
+    // stat check
+    if (stat(filename, &sb) < 0) {
+        errore("Can't stat %.300s", filename);
+        return 1;
+    }
+
+    filekind = 0;
+    filesize = 0;
+    reason = NULL;
+    if (S_ISREG(sb.st_mode))
+        filesize = sb.st_size;
+    else if (S_ISBLK(sb.st_mode))
+        filekind = 1;
+    else if (S_ISCHR(sb.st_mode))
+        filekind = 2;
+    else if (S_ISDIR(sb.st_mode))
+        reason = "Is a directory";
+    else if (S_ISFIFO(sb.st_mode))
+        reason = "Is a FIFO";
+#ifdef S_ISSOCK
+    else if (S_ISSOCK(sb.st_mode))
+        reason = "Is a socket";
+#endif
+    else
+        reason = "Is an unknown kind of special file";
+
+    if (reason != NULL) {
+        error("%.300s: %s", filename, reason);
+        return 1;
+    }
+
+    // open file
+    fd = open(filename, O_RDWR);
+    if (fd < 0 && errno == EBUSY) {
+        fd = open(filename, O_RDONLY);
+#ifndef NOREADONLYWARN
+        if (fd >= 0)
+            printf("Warning: %.300s opened read-only\n", filename);
+#endif
+    }
+    if (fd < 0) {
+        errore("Can't open %.300s", filename);
+        return 1;
+    }
+
+    // (try to) guard against TTY character devices
+    if (filekind == 2) {
+        if (isatty(fd)) {
+            error("%.300s: Is a TTY device", filename);
+            return 1;
+        }
+    }
+
+    // run sync algorithm
+    status = PROGNAME();
+    printf("\n");
+
+    // close file
+    if (close(fd) != 0) {
+        errore("Error while closing %.300s", filename);
+        return 1;
+    }
+
+    return status;
+}
diff --git a/gptsync/showpart.c b/gptsync/showpart.c
new file mode 100644 (file)
index 0000000..5d727ed
--- /dev/null
@@ -0,0 +1,260 @@
+/*
+ * gptsync/showpart.c
+ * Platform-independent code for analyzing hard disk partitioning
+ *
+ * Copyright (c) 2006 Christoph Pfisterer
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the
+ *    distribution.
+ *
+ *  * Neither the name of Christoph Pfisterer nor the names of the
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "gptsync.h"
+
+//
+// memory string search
+//
+
+static INTN FindMem(VOID *Buffer, UINTN BufferLength, VOID *SearchString, UINTN SearchStringLength)
+{
+    UINT8 *BufferPtr;
+    UINTN Offset;
+    
+    BufferPtr = Buffer;
+    BufferLength -= SearchStringLength;
+    for (Offset = 0; Offset < BufferLength; Offset++, BufferPtr++) {
+        if (CompareMem(BufferPtr, SearchString, SearchStringLength) == 0)
+            return (INTN)Offset;
+    }
+    
+    return -1;
+}
+
+//
+// detect boot code
+//
+
+static UINTN detect_bootcode(UINT64 partlba, CHARN **bootcodename)
+{
+    UINTN   status;
+    BOOLEAN bootable;
+    
+    // read MBR data
+    status = read_sector(partlba, sector);
+    if (status != 0)
+        return status;
+    
+    // check bootable signature
+    if (*((UINT16 *)(sector + 510)) == 0xaa55 && sector[0] != 0)
+        bootable = TRUE;
+    else
+        bootable = FALSE;
+    *bootcodename = NULL;
+    
+    // detect specific boot codes
+    if (CompareMem(sector + 2, "LILO", 4) == 0 ||
+        CompareMem(sector + 6, "LILO", 4) == 0) {
+        *bootcodename = STR("LILO");
+        
+    } else if (CompareMem(sector + 3, "SYSLINUX", 8) == 0) {
+        *bootcodename = STR("SYSLINUX");
+        
+    } else if (FindMem(sector, 512, "ISOLINUX", 8) >= 0) {
+        *bootcodename = STR("ISOLINUX");
+        
+    } else if (FindMem(sector, 512, "Geom\0Hard Disk\0Read\0 Error", 26) >= 0) {
+        *bootcodename = STR("GRUB");
+        
+    } else if ((*((UINT32 *)(sector + 502)) == 0 &&
+                *((UINT32 *)(sector + 506)) == 50000 &&
+                *((UINT16 *)(sector + 510)) == 0xaa55) ||
+               FindMem(sector, 512, "Starting the BTX loader", 23) >= 0) {
+        *bootcodename = STR("FreeBSD");
+        
+    } else if (FindMem(sector, 512, "!Loading", 8) >= 0 ||
+               FindMem(sector, 512, "/cdboot\0/CDBOOT\0", 16) >= 0) {
+        *bootcodename = STR("OpenBSD");
+        
+    } else if (FindMem(sector, 512, "Not a bootxx image", 18) >= 0) {
+        *bootcodename = STR("NetBSD");
+        
+    } else if (FindMem(sector, 512, "NTLDR", 5) >= 0) {
+        *bootcodename = STR("Windows NTLDR");
+        
+    } else if (FindMem(sector, 512, "BOOTMGR", 7) >= 0) {
+        *bootcodename = STR("Windows BOOTMGR (Vista)");
+        
+    } else if (FindMem(sector, 512, "CPUBOOT SYS", 11) >= 0 ||
+               FindMem(sector, 512, "KERNEL  SYS", 11) >= 0) {
+        *bootcodename = STR("FreeDOS");
+        
+    } else if (FindMem(sector, 512, "OS2LDR", 6) >= 0 ||
+               FindMem(sector, 512, "OS2BOOT", 7) >= 0) {
+        *bootcodename = STR("eComStation");
+        
+    } else if (FindMem(sector, 512, "Be Boot Loader", 14) >= 0) {
+        *bootcodename = STR("BeOS");
+        
+    } else if (FindMem(sector, 512, "yT Boot Loader", 14) >= 0) {
+        *bootcodename = STR("ZETA");
+        
+    } else if (FindMem(sector, 512, "\x04" "beos\x06" "system\x05" "zbeos", 18) >= 0) {
+        *bootcodename = STR("Haiku");
+        
+    }
+    
+    if (FindMem(sector, 512, "Non-system disk", 15) >= 0)   // dummy FAT boot sector
+        *bootcodename = STR("None (Non-system disk message)");
+    
+    // TODO: Add a note if a specific code was detected, but the sector is not bootable?
+    
+    if (*bootcodename == NULL) {
+        if (bootable)
+            *bootcodename = STR("Unknown, but bootable");
+        else
+            *bootcodename = STR("None");
+    }
+    
+    return 0;
+}
+
+//
+// check one partition
+//
+
+static UINTN analyze_part(UINT64 partlba)
+{
+    UINTN   status;
+    UINTN   i;
+    CHARN   *bootcodename;
+    UINTN   parttype;
+    CHARN   *fsname;
+    
+    if (partlba == 0)
+        Print(L"\nMBR contents:\n");
+    else
+        Print(L"\nPartition at LBA %lld:\n", partlba);
+    
+    // detect boot code
+    status = detect_bootcode(partlba, &bootcodename);
+    if (status)
+        return status;
+    Print(L" Boot Code: %s\n", bootcodename);
+    
+    if (partlba == 0)
+        return 0;   // short-circuit MBR analysis
+    
+    // detect file system
+    status = detect_mbrtype_fs(partlba, &parttype, &fsname);
+    if (status)
+        return status;
+    Print(L" File System: %s\n", fsname);
+    
+    // cross-reference with partition table
+    for (i = 0; i < gpt_part_count; i++) {
+        if (gpt_parts[i].start_lba == partlba) {
+            Print(L" Listed in GPT as partition %d, type %s\n", i+1,
+                  gpt_parts[i].gpt_parttype->name);
+        }
+    }
+    for (i = 0; i < mbr_part_count; i++) {
+        if (mbr_parts[i].start_lba == partlba) {
+            Print(L" Listed in MBR as partition %d, type %02x  %s%s\n", i+1,
+                  mbr_parts[i].mbr_type,
+                  mbr_parttype_name(mbr_parts[i].mbr_type),
+                  mbr_parts[i].active ? STR(", active") : STR(""));
+        }
+    }
+    
+    return 0;
+}
+
+//
+// check all partitions
+//
+
+static UINTN analyze_parts(VOID)
+{
+    UINTN   i, k;
+    UINTN   status;
+    BOOLEAN is_dupe;
+    
+    // check MBR (bootcode only)
+    status = analyze_part(0);
+    if (status)
+        return status;
+    
+    // check partitions listed in GPT
+    for (i = 0; i < gpt_part_count; i++) {
+        status = analyze_part(gpt_parts[i].start_lba);
+        if (status)
+            return status;
+    }
+    
+    // check partitions listed in MBR, but not in GPT
+    for (i = 0; i < mbr_part_count; i++) {
+        if (mbr_parts[i].start_lba == 1 && mbr_parts[i].mbr_type == 0xee)
+            continue;   // skip EFI Protective entry
+        
+        is_dupe = FALSE;
+        for (k = 0; k < gpt_part_count; k++)
+            if (gpt_parts[k].start_lba == mbr_parts[i].start_lba)
+                is_dupe = TRUE;
+        
+        if (!is_dupe) {
+            status = analyze_part(mbr_parts[i].start_lba);
+            if (status)
+                return status;
+        }
+    }
+    
+    return 0;
+}
+
+//
+// display algorithm entry point
+//
+
+UINTN showpart(VOID)
+{
+    UINTN   status = 0;
+    UINTN   status_gpt, status_mbr;
+    
+    // get full information from disk
+    status_gpt = read_gpt();
+    status_mbr = read_mbr();
+    if (status_gpt != 0 || status_mbr != 0)
+        return (status_gpt || status_mbr);
+    
+    // analyze all partitions
+    status = analyze_parts();
+    if (status != 0)
+        return status;
+    
+    return status;
+}