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