--- /dev/null
+/**
+ 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
+
--- /dev/null
+/**
+ 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
--- /dev/null
+#
+# 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
--- /dev/null
+#
+# 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
+
--- /dev/null
+#
+# 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
--- /dev/null
+# 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
--- /dev/null
+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.
--- /dev/null
+.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.
+
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+#\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
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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;
+}