Skip to content

Commit

Permalink
Merge pull request #10 from MuertoGB/dev
Browse files Browse the repository at this point in the history
103 merge to main
  • Loading branch information
MuertoGB authored Aug 7, 2023
2 parents 3e7029b + c85fc6c commit 7fef5a6
Show file tree
Hide file tree
Showing 44 changed files with 654 additions and 545 deletions.
16 changes: 15 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<h4 align="center">Version History</h4>
<p align="center">
<a href="#version-101">V1.0.2</a> •
<a href="#version-103">V1.0.3</a> •
<a href="#version-102">V1.0.2</a> •
<a href="#version-101">V1.0.1</a> •
<a href="#version-100">V1.0.0</a> •
<a href="#version-070">V0.7.0</a> •
Expand All @@ -14,6 +15,19 @@
<a href="#version-034">V0.3.4</a>
</p>

## Version 1.0.3

#### New:
- Updated the firmware parser with a new feature that attempts to force find the Fsys Store if it was not initially located within the NVRAM on the first pass. This change makes the application more reliable at extracting Fsys data from corrupt firmware.

#### Enhancements:
- Implemented a visual colour change in the presentation of NVRAM store labels in the main window. The manual has been updated to reflect this change.
- Improved the image validation logic.
- User interface improvements.

#### Bugs:
- Fixed a scenario that caused a crash when dragging and dropping a file onto the application executable and subsequently clicking "Create a Debug Log." This issue was caused by a malformed file path in specific scenarios, and was resolved by dynamically constructing the executable file path when necessary.

## Version 1.0.2

#### Enhancements:
Expand Down
11 changes: 8 additions & 3 deletions MANUAL.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ This section displays the name of the loaded file and includes two buttons. Clic

The file size of the loaded file is measured in bytes. If the file size is invalid, the label will appear red, and any discrepancy in bytes will be calculated and displayed.

> 🛈 8,388,615 (>7) would indicate the given file is 7 bytes too large.
> 🛈 8,388,615 (>7) would indicate the given firmware is 7 bytes too large.
---

Expand Down Expand Up @@ -183,8 +183,13 @@ The Hardware Configuration Code (HWC) is located in the Fsys store and is derive
<kbd>
<img src="files/manual/fsysinvalid.png">
</kbd>
<kbd>
<img src="files/manual/fsys_forced.png">
</kbd>

This section includes the checksum of the Fsys store and two buttons. If the CRC32 of the Fsys store is valid, the label will appear green and display the valid checksum. If the CRC32 is invalid, the label will appear red and display the invalid checksum. The presence of `[F]` appended to the checksum indicates the Fsys Store was force found by the application, and the firmware may be corrupt.

This section includes the checksum of the Fsys store and two buttons. If the CRC32 of the Fsys store is valid, the label will appear green and display the valid checksum. If the CRC32 is invalid, the label will appear red and display the invalid checksum. Clicking the "Wrench" button, which is enabled when the Fsys store checksum is invalid, will prompt a "Save As" dialog to export the binary file with a repaired Fsys CRC32 checksum. The "Save" button allows exporting of the 2048-byte (0x800h) Fsys store.
Clicking the "Wrench" button, which is enabled when the Fsys store checksum is invalid, will prompt a "Save As" dialog to export the binary file with a repaired Fsys CRC32 checksum. The "Save" button allows exporting of the 2048-byte (0x800h) Fsys store.

---

Expand Down Expand Up @@ -221,7 +226,7 @@ This section provides information about the firmware version, and includes one b
<img src="files/manual/nvramlocked.png">
</kbd>

This section is divided into four items. The first three items represent different NVRAM store types, indicating their status. Each store type will appear white when empty, green when data is present, and grey when the store is not found.
This section is divided into four items. The first three items represent different NVRAM store types, indicating their status. Each store type will appear green when empty, white when data is present, and grey when the store is not found.

The padlock item represents EFI Lock status. If the padlock icon is green and unlocked, it signifies that a Message Authentication Code (MAC) was not found, indicating that the EFI is likely not locked. Conversely, if the padlock icon is red and locked, it suggests that a Message Authentication Code (MAC) was found, indicating that the EFI is likely password locked.

Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<h1 align="center">
<img width="200" src="files/images/img128px.png" alt="SMCFT Logo">
<br>
Mac EFI Toolkit V1.0.2
Mac EFI Toolkit V1.0.3
</h1>

<h4 align="center">A tool for analysis of Mac BIOS firmware, with limited editing capabilities.</h4>
Expand Down Expand Up @@ -81,7 +81,7 @@ This application provides support for most Mac BIOS/UEFI, with the exception of

| Version| Release Date| Latest | Channel |
|--------|-------------|--------|---------|
|[1.0.2](https://github.com/MuertoGB/MacEfiToolkit/releases/latest)| 18th July, 2023 | Yes | Stable |
|[1.0.3](https://github.com/MuertoGB/MacEfiToolkit/releases/latest)| 7th August, 2023 | Yes | Stable |

> 📋 View the full changelog [here](CHANGELOG.md)
Expand Down
8 changes: 4 additions & 4 deletions files/app/version.xml
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<?xml version="1.0"?>
<data>
<MET>
<VersionString>1.0.2</VersionString>
<Build>1.0.2.230718.1355</Build>
<ReleaseDate>18.07.2023</ReleaseDate>
<VersionString>1.0.3</VersionString>
<Build>1.0.3.230807.2023</Build>
<ReleaseDate>07.08.2023</ReleaseDate>
<Channel>Stable</Channel>
<SHA256>e5c60bbfe544bab478110ff12c7d569c6aad7a0c3a7800035182732d7b15a9fa</SHA256>
<SHA256>5804dc0b606f72a8c982d08be4610c51ba1ad6b4a9e7272c0d6c279f2e4333d0</SHA256>
</MET>
</data>
Binary file modified files/images/met.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified files/images/met_alt.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified files/manual/apfsdxe.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified files/manual/apfslzma.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified files/manual/apfsno.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified files/manual/boardid.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified files/manual/crc.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified files/manual/created.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified files/manual/efiversion.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified files/manual/efiversionalt.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified files/manual/filesize.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified files/manual/filesizeinvalid.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified files/manual/fit.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified files/manual/fsys.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added files/manual/fsys_forced.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified files/manual/fsysinvalid.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified files/manual/hwc.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified files/manual/intelme.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified files/manual/modified.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified files/manual/nvram.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified files/manual/nvramlocked.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed files/manual/opencopymenu.png
Binary file not shown.
Binary file removed files/manual/openeditor.png
Binary file not shown.
Binary file modified files/manual/serial.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified files/manual/son.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified files/manual/title.png
221 changes: 103 additions & 118 deletions mefit/Common/FWBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ class FWBase
internal static string MeVersion = null;
internal static byte[] LoadedBinaryBytes = null;
internal static bool FirmwareLoaded = false;
internal static bool ForceFoundFsys = false;

internal static FileInfoStore FileInfoData;
internal static PdrSection PDRSectionData;
Expand Down Expand Up @@ -179,12 +180,25 @@ internal static void LoadFirmwareBaseData(byte[] sourceBytes, string fileName)
EfiLock = (SvsStoreData.PrimaryStoreBase != -1 && SvsStoreData.PrimaryStoreBytes != null)
? EfiLock = GetIsEfiLocked(SvsStoreData.PrimaryStoreBytes)
: EfiLockStatus.Unknown;

if (FsysStoreData.FsysBytes == null)
{
FsysStoreData = GetFsysStoreData(sourceBytes, false, true);

if (FsysStoreData.FsysBytes != null)
{
ForceFoundFsys = true;
Logger.WriteToLogFile($"Force found Fsys Store at {FsysStoreData.FsysBase:X}h." +
$" The image may be misaligned or corrupt ({FileInfoData.FileNameWithExt}).", LogType.Application);
}
}
}

internal static void ResetFirmwareBaseData()
{
LoadedBinaryPath = null;
LoadedBinaryBytes = null;
ForceFoundFsys = false;
FileInfoData = default;
PDRSectionData = default;
VssStoreData = default;
Expand All @@ -201,11 +215,14 @@ internal static void ResetFirmwareBaseData()

internal static bool IsValidImage(byte[] sourceBytes)
{
int dxeCore = BinaryUtils.GetBasePosition(sourceBytes, FSGuids.DXE_CORE);
int dxeCore = BinaryUtils.GetBasePosition(sourceBytes, FSGuids.DXE_CORE, 16, 16);

if (!Descriptor.DescriptorMode && dxeCore == -1)
if (!Descriptor.DescriptorMode)
{
return false;
if (dxeCore == -1)
{
return false;
}
}

return true;
Expand Down Expand Up @@ -280,125 +297,46 @@ private static PdrSection DefaultPdrSection()
#endregion

#region Fsys Store
internal static FsysStore GetFsysStoreData(byte[] sourceBytes, bool isFsysStoreOnly)
// Fsys resides in the NVRAM at either base: 20000h, or 22000h.
// Fsys size resides in the store at 0x09 and is 2 bytes in length,
// we should dynamically read it, not hardcode.
internal static FsysStore GetFsysStoreData(byte[] sourceBytes, bool isFsysStoreOnly, bool forceFind = false)
{
// Base should be zero if the isFsysStoreOnly flag is set
int fsysBase = 0;

// Arg to skip Fsys searching
if (!isFsysStoreOnly)
{
// First we need to locate the NVRAM section GUID
int guidBase = BinaryUtils.GetBasePosition(sourceBytes, FSGuids.NVRAM_SECTION_GUID, _biosBase, _biosLimit);
// Find the base position of Fsys Store
int fsysBase = FindFsysBase(sourceBytes, isFsysStoreOnly, forceFind);

if (guidBase == -1)
{
// NVRAM store was not found so return default data
return DefaultFsysRegion();
}

// Get NVRAM section size from header
byte[] sectionLengthBytes = BinaryUtils.GetBytesBaseLength(sourceBytes, guidBase + GUID_LENGTH, 4);
// Convert NVRAM section size to int32
int nvramLength = BitConverter.ToInt32(sectionLengthBytes, 0);
// Search for the Fsys store within bounds of the NVRAM section
fsysBase = BinaryUtils.GetBasePosition(sourceBytes, FSYS_SIG, guidBase - ZERO_VECTOR_LENGTH - GUID_LENGTH, nvramLength);

// Fsys store was not found within scope of the NVRAM section
if (fsysBase == -1)
{
return DefaultFsysRegion();
}
}

byte[] fsysStoreBytes = BinaryUtils.GetBytesBaseLength(sourceBytes, fsysBase, FSYS_RGN_SIZE);

// Fsys store was not loaded
if (fsysStoreBytes == null)
{
// If Fsys Store base is not found, return default data
if (fsysBase == -1)
return DefaultFsysRegion();
}

// Fsys store was not the correct size
if (fsysStoreBytes.Length != FSYS_RGN_SIZE)
{
return DefaultFsysRegion();
}
// Retrieve FsysStore bytes
byte[] fsysStoreBytes = GetFsysStoreBytes(sourceBytes, fsysBase);

// Get the Fsys store crc stored at 0x7FC (FSYS_RGN_SIZE - CRC32_LENGTH)
byte[] crcBytes = BinaryUtils.GetBytesBaseLength(sourceBytes, fsysBase + FSYS_CRC_POS, CRC32_LENGTH);
byte[] crcEndianBytes = crcBytes.Reverse().ToArray(); // We need to flip the bytes from little endian
string crcString = BitConverter.ToString(crcEndianBytes).Replace("-", "");
// If FsysStore is invalid, return default data
if (!IsValidFsysStore(fsysStoreBytes))
return DefaultFsysRegion();

// Manually calculate the Fsys store crc
uint uiCrcCalc = MacUtils.GetUintFsysCrc32(fsysStoreBytes);
// Retrieve CRC bytes and calculate CRC values
byte[] crcBytes = GetCrcBytes(sourceBytes, fsysBase);
string crcString = GetFlippedCrcString(crcBytes);
uint uiCrcCalc = CalculateFsysCrc(fsysStoreBytes);
string crcCalcString = uiCrcCalc.ToString("X8");

// Parse the serial number
int snDataStart = -1;

// Look for the lower case system serial number signature
if ((snDataStart = BinaryUtils.GetBasePosition(sourceBytes, SSN_LOWER_SIG, fsysBase, FSYS_RGN_SIZE)) != -1)
snDataStart += SSN_LOWER_SIG.Length;

// Look for the upper case system serial number signature
if (snDataStart == -1)
{
if ((snDataStart = BinaryUtils.GetBasePosition(sourceBytes, SSN_UPPER_SIG, fsysBase, FSYS_RGN_SIZE)) != -1)
snDataStart += SSN_UPPER_SIG.Length;
}

// Look for other ssn signatures
if (snDataStart == -1)
{
if ((snDataStart = BinaryUtils.GetBasePosition(sourceBytes, SSNP_LOWER_SIG, fsysBase, FSYS_RGN_SIZE)) != -1)
snDataStart += SSNP_LOWER_SIG.Length;
}

// Find and parse various signatures within FsysStore
int snDataStart = FindSignaturePosition(sourceBytes, fsysBase, FSYS_RGN_SIZE, SSN_LOWER_SIG, SSN_UPPER_SIG, SSNP_LOWER_SIG);
string serialString = ParseFsysString(sourceBytes, snDataStart);
if (serialString == null) snDataStart = -1;

// Parse the hardware configuration code
int hwcDataStart = -1;

// Look for the hardware configuration lower case signature
if ((hwcDataStart = BinaryUtils.GetBasePosition(sourceBytes, HWC_LOWER_SIG, fsysBase, FSYS_RGN_SIZE)) != -1)
hwcDataStart += HWC_LOWER_SIG.Length;

// Look for the hardware configuration upper case signature
if (hwcDataStart == -1)
{
if ((hwcDataStart = BinaryUtils.GetBasePosition(sourceBytes, HWC_UPPER_SIG, fsysBase, FSYS_RGN_SIZE)) != -1)
hwcDataStart += HWC_UPPER_SIG.Length;
}

int hwcDataStart = FindSignaturePosition(sourceBytes, fsysBase, FSYS_RGN_SIZE, HWC_LOWER_SIG, HWC_UPPER_SIG);
string hwcString = ParseFsysString(sourceBytes, hwcDataStart);
if (hwcString == null) hwcDataStart = -1;

// Parse the system order number
int sonDataStart = -1;

// Look for the system order number lower case signature
if ((sonDataStart = BinaryUtils.GetBasePosition(sourceBytes, SON_LOWER_SIG, fsysBase, FSYS_RGN_SIZE)) != -1)
{
sonDataStart += SON_LOWER_SIG.Length;
}

// Look for the system order number upper case signature
if (sonDataStart == -1)
{
if ((sonDataStart = BinaryUtils.GetBasePosition(sourceBytes, SON_UPPER_SIG, fsysBase, FSYS_RGN_SIZE)) != -1)
{
sonDataStart += SON_UPPER_SIG.Length;
}
}

int sonDataStart = FindSignaturePosition(sourceBytes, fsysBase, FSYS_RGN_SIZE, SON_LOWER_SIG, SON_UPPER_SIG);
string sonString = ParseFsysString(sourceBytes, sonDataStart);

// Trim trailing '/' from SON string if present
if (sonString != null && sonString.EndsWith("/"))
{
sonString = sonString.TrimEnd('/');
}

// Create and return FsysStore object
return new FsysStore
{
FsysBytes = fsysStoreBytes,
Expand All @@ -416,34 +354,82 @@ internal static FsysStore GetFsysStoreData(byte[] sourceBytes, bool isFsysStoreO

private static string ParseFsysString(byte[] sourceBytes, int basePos)
{
// If the base is -1 return null
if (basePos == -1)
{
// Return null if base position is invalid or data size is zero
if (basePos == -1 || sourceBytes[basePos] == 0)
return null;
}

// Read size of the indicated variable
int dataSize = sourceBytes[basePos];

// Invalid data size
// Return null if data size is invalid
if (dataSize == 0)
{
return null;
}

// Read the variable bytes
byte[] dataBytes = BinaryUtils.GetBytesBaseLength(sourceBytes, basePos + LITERAL_POS, dataSize);

// Invalid bytes
if (dataBytes == null || dataBytes.Length > dataSize)
{
// Return null if bytes are invalid or exceed the data size
if (dataBytes == null || dataBytes.Length != dataSize)
return null;
}

// Return string data
return _utf8.GetString(dataBytes);
}

private static int FindFsysBase(byte[] sourceBytes, bool isFsysStoreOnly, bool forceFind)
{
if (isFsysStoreOnly)
return 0;

if (forceFind)
return BinaryUtils.GetBasePosition(sourceBytes, FSYS_SIG, _biosBase, _biosLimit);

int guidBase = BinaryUtils.GetBasePosition(sourceBytes, FSGuids.NVRAM_SECTION_GUID, _biosBase, _biosLimit);

if (guidBase == -1)
return -1;

int nvramLength = BitConverter.ToInt32(BinaryUtils.GetBytesBaseLength(sourceBytes, guidBase + GUID_LENGTH, 4), 0);
return BinaryUtils.GetBasePosition(sourceBytes, FSYS_SIG, guidBase - ZERO_VECTOR_LENGTH - GUID_LENGTH, nvramLength);
}

private static bool IsValidFsysStore(byte[] fsysStoreBytes)
{
return fsysStoreBytes != null && fsysStoreBytes.Length == FSYS_RGN_SIZE;
}

private static string GetFlippedCrcString(byte[] crcBytes)
{
byte[] crcEndianBytes = crcBytes.Reverse().ToArray();
return BitConverter.ToString(crcEndianBytes).Replace("-", "");
}

private static uint CalculateFsysCrc(byte[] fsysStoreBytes)
{
return MacUtils.GetUintFsysCrc32(fsysStoreBytes);
}

private static int FindSignaturePosition(byte[] sourceBytes, int start, int limit, params byte[][] signatures)
{
foreach (byte[] sig in signatures)
{
int dataStart = BinaryUtils.GetBasePosition(sourceBytes, sig, start, limit);
if (dataStart != -1)
return dataStart + sig.Length;
}
return -1;
}

private static byte[] GetFsysStoreBytes(byte[] sourceBytes, int fsysBase)
{
return BinaryUtils.GetBytesBaseLength(sourceBytes, fsysBase, FSYS_RGN_SIZE);
}

private static byte[] GetCrcBytes(byte[] sourceBytes, int fsysBase)
{
return BinaryUtils.GetBytesBaseLength(sourceBytes, fsysBase + FSYS_CRC_POS, CRC32_LENGTH);
}

private static FsysStore DefaultFsysRegion()
{
return new FsysStore
Expand All @@ -461,7 +447,6 @@ private static FsysStore DefaultFsysRegion()
};
}

// Fsys resides in the NVRAM at either base: 20000h, or 22000h.
internal static readonly byte[] FSYS_SIG =
{
0x46, 0x73, 0x79, 0x73,
Expand Down
Loading

0 comments on commit 7fef5a6

Please sign in to comment.