public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [Patch][edk2-platforms/devel-IntelAtomProcessorE3900 1/5] Add EepromApp.
@ 2018-07-23  2:39 zwei4
  2018-07-23  2:39 ` [Patch][edk2-platforms/devel-IntelAtomProcessorE3900 3/5] Library producing EEPROM raw data functionality zwei4
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: zwei4 @ 2018-07-23  2:39 UTC (permalink / raw)
  To: edk2-devel; +Cc: David Wei, Kelly Steele, Mike Wu, Mang Guo

Add EepromApp which could read, write, verify and dump the EERPOM data.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: David Wei <david.wei@intel.com>
CC: Kelly Steele <kelly.steele@intel.com>
CC: Mike Wu  <mike.wu@intel.com>
CC: Mang Guo <mang.guo@intel.com>
---
 .../Common/Features/Eeprom/EepromApp/EepromApp.c   | 2090 ++++++++++++++++++++
 .../Common/Features/Eeprom/EepromApp/EepromApp.h   |  196 ++
 .../Common/Features/Eeprom/EepromApp/EepromApp.inf |   62 +
 3 files changed, 2348 insertions(+)
 create mode 100644 Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromApp/EepromApp.c
 create mode 100644 Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromApp/EepromApp.h
 create mode 100644 Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromApp/EepromApp.inf

diff --git a/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromApp/EepromApp.c b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromApp/EepromApp.c
new file mode 100644
index 0000000000..9e1eb66f54
--- /dev/null
+++ b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromApp/EepromApp.c
@@ -0,0 +1,2090 @@
+/** @file
+
+  This application will read/write/verify/dump the EERPOM data.
+
+  Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.<BR>
+
+  This program and the accompanying materials are licensed and made available under
+  the terms and conditions of the BSD License which accompanies this distribution.
+  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "EepromApp.h"
+
+BOOLEAN           gDebugFlag = FALSE;
+
+/**
+  UEFI application entry point which has an interface similar to a
+  standard C main function.
+
+  The ShellCEntryLib library instance wrappers the actual UEFI application
+  entry point and calls this ShellAppMain function.
+
+  @param[in] Argc     The number of items in Argv.
+  @param[in] Argv     Array of pointers to strings.
+
+  @retval    0        The application exited normally.
+  @retval    Other    An error occurred.
+
+**/
+INTN
+EFIAPI
+ShellAppMain (
+  IN UINTN      Argc,
+  IN CHAR16   **Argv
+  )
+{
+  BOOLEAN         InvalidFlag;
+  PROGRAM_INFO    ProgramInfo;
+  SHELL_STATUS    Status;
+
+  if (gDebugFlag) Print (L"%a(#%d) - Starting...\n", __FUNCTION__, __LINE__);
+
+  // Initialize Variables
+  InvalidFlag = FALSE;
+  Status      = SHELL_SUCCESS;
+  ZeroMem (&ProgramInfo, sizeof (ProgramInfo));
+
+
+  // Check for invalid conditions
+  if (Argv == NULL) {
+    if (gDebugFlag) Print (L"ERROR: [#%d] Internal coding error!\n", __LINE__);
+    Status = SHELL_INVALID_PARAMETER;
+    goto Exit;
+  }
+
+  // Parse CLI parameters
+  ParseParameters (Argc, Argv, &ProgramInfo);
+
+  // Print App version
+  Print (L"EepromApp - Version #%s\n", APP_VERSION);
+  Print (L"Copyright (c) %s Intel Corporation. All rights reserved.\n\n", APP_COPYRIGHT);
+
+  // Help requested?
+  if (ProgramInfo.HelpFlag) {
+    PrintHelp ();
+    goto Exit;
+  }
+
+  // Check for invalid states
+  if (CheckForInvalidOptions (&ProgramInfo) != SHELL_SUCCESS) {
+    InvalidFlag = TRUE;
+    Print (L"ERROR: Invalid CLI option(s)!\n");
+    goto Exit;
+  }
+
+  //
+  // Test GetValidEepromLibrary()
+  //
+  if (!ProgramInfo.ScanFlag) {
+    //
+    // Skip this if we are doing a scan.
+    //
+    Print (L"- GetValidEepromLibrary() = %a\n", mEepromLibraryString[GetValidEepromLibrary (TRUE, TRUE)]);
+  } else {
+    // Scanning
+    Status = ScanOption (&ProgramInfo);
+    if (Status != SHELL_SUCCESS) {
+      goto Exit;
+    }
+  }
+
+  // Check?
+  if (ProgramInfo.CheckFlag) {
+    if (ProgramInfo.ReadLibraryIndex > EEPROM_DATA_LIBRARY_INDEX_MAX) {
+      Print (L"ERROR: Library index you want to check is larger than %d!\n", EEPROM_DATA_LIBRARY_INDEX_MAX);
+      Status = SHELL_INVALID_PARAMETER;
+      goto Exit;
+    }
+    Status = CheckOption (&ProgramInfo);
+  } else
+
+  // Dump human?
+  if (ProgramInfo.DumpHumanFlag) {
+    if (ProgramInfo.DumpHumanLibraryIndex > EEPROM_DATA_LIBRARY_INDEX_MAX) {
+      Print (L"ERROR: Library index you want to check is larger than %d!\n", EEPROM_DATA_LIBRARY_INDEX_MAX);
+      Status = SHELL_INVALID_PARAMETER;
+      goto Exit;
+    }
+    Status = DumpHumanOption (&ProgramInfo);
+  } else
+
+  // Dump raw?
+  if (ProgramInfo.DumpRawFlag) {
+    if (ProgramInfo.DumpRawLibraryIndex > EEPROM_DATA_LIBRARY_INDEX_MAX) {
+      Print (L"ERROR: Library index you want to check is larger than %d!\n", EEPROM_DATA_LIBRARY_INDEX_MAX);
+      Status = SHELL_INVALID_PARAMETER;
+      goto Exit;
+    }
+    Status = DumpRawOption (&ProgramInfo);
+  } else
+
+  // Erase?
+  if (ProgramInfo.EraseFlag) {
+    if (ProgramInfo.EraseLibraryIndex > EEPROM_DATA_LIBRARY_INDEX_MAX) {
+      Print (L"ERROR: Library index you want to check is larger than %d!\n", EEPROM_DATA_LIBRARY_INDEX_MAX);
+      Status = SHELL_INVALID_PARAMETER;
+      goto Exit;
+    }
+    Status = EraseOption (&ProgramInfo);
+  } else
+
+  // Read?
+  if (ProgramInfo.ReadFlag) {
+    if (ProgramInfo.ReadLibraryIndex > EEPROM_DATA_LIBRARY_INDEX_MAX) {
+      Print (L"ERROR: Library index you want to read is larger than %d!\n", EEPROM_DATA_LIBRARY_INDEX_MAX);
+      Status = SHELL_INVALID_PARAMETER;
+      goto Exit;
+    }
+    if (ProgramInfo.ReadFileName == NULL) {
+      Print (L"ERROR: Missing the filename!\n");
+      Status = SHELL_INVALID_PARAMETER;
+      goto Exit;
+    }
+    Status = ReadOption (&ProgramInfo);
+  } else
+
+  // Verify?
+  if (ProgramInfo.VerifyFlag) {
+    if (ProgramInfo.VerifyLibraryIndex > EEPROM_DATA_LIBRARY_INDEX_MAX) {
+      Print (L"ERROR: Library index you want to verify is larger than %d!\n", EEPROM_DATA_LIBRARY_INDEX_MAX);
+      Status = SHELL_INVALID_PARAMETER;
+      goto Exit;
+    }
+    if (ProgramInfo.VerifyFileName == NULL) {
+      Print (L"ERROR: Missing the filename!\n");
+      Status = SHELL_INVALID_PARAMETER;
+      goto Exit;
+    }
+    Status = VerifyOption (&ProgramInfo);
+  } else
+
+  // Write?
+  if (ProgramInfo.WriteFlag) {
+    if (ProgramInfo.WriteLibraryIndex > EEPROM_DATA_LIBRARY_INDEX_MAX) {
+      Print (L"ERROR: Library index you want to write is larger than %d!\n", EEPROM_DATA_LIBRARY_INDEX_MAX);
+      Status = SHELL_INVALID_PARAMETER;
+      goto Exit;
+    }
+    if (ProgramInfo.WriteFileName == NULL) {
+      Print (L"ERROR: Missing the filename!\n");
+      Status = SHELL_INVALID_PARAMETER;
+      goto Exit;
+    }
+    Status = WriteOption (&ProgramInfo);
+  } else
+
+  // This is invalid
+  {
+    InvalidFlag = TRUE;
+    Print (L"ERROR: Invalid CLI option(s)!\n");
+  }
+
+Exit:
+  // Invalid?
+  if (InvalidFlag) {
+    Status = SHELL_INVALID_PARAMETER;
+  }
+
+  //
+  // Free resources
+  //
+  if (ProgramInfo.CheckFile != NULL) {
+    FreePool (ProgramInfo.CheckFile);
+    ProgramInfo.CheckFile = NULL;
+  }
+  if (ProgramInfo.DumpHumanFile != NULL) {
+    FreePool (ProgramInfo.DumpHumanFile);
+    ProgramInfo.DumpHumanFile = NULL;
+  }
+  if (ProgramInfo.DumpRawFile != NULL) {
+    FreePool (ProgramInfo.DumpRawFile);
+    ProgramInfo.DumpRawFile = NULL;
+  }
+  if (ProgramInfo.ReadFile != NULL) {
+    FreePool (ProgramInfo.ReadFile);
+    ProgramInfo.ReadFile = NULL;
+  }
+  if (ProgramInfo.VerifyFile != NULL) {
+    FreePool (ProgramInfo.VerifyFile);
+    ProgramInfo.VerifyFile = NULL;
+  }
+  if (ProgramInfo.WriteFile != NULL) {
+    FreePool (ProgramInfo.WriteFile);
+    ProgramInfo.WriteFile = NULL;
+  }
+
+  return Status;
+}
+
+SHELL_STATUS
+BufferToMemory (
+  IN  UINT8     *Buffer,
+  IN  UINT32     BufferSize,
+  OUT UINT8    **MemoryBuffer,
+  OUT UINT32    *MemoryBufferSize
+  )
+{
+  EFI_STATUS      EfiStatus;
+  UINT8          *ImageBuffer;
+  UINT32          ImageSize;
+  SHELL_STATUS    Status;
+
+  if (gDebugFlag) Print (L"%a(#%d) - Starting...\n", __FUNCTION__, __LINE__);
+
+  //
+  // Initialize variables
+  //
+  ImageBuffer = NULL;
+  ImageSize   = 0;
+  Status      = SHELL_SUCCESS;
+
+  //
+  // Sanity checks
+  //
+  if ((Buffer == NULL) || (BufferSize == 0)) {
+    if (gDebugFlag) Print (L"ERROR: [#%d] Internal coding error!\n", __LINE__);
+    Status = SHELL_INVALID_PARAMETER;
+    goto Exit;
+  }
+  if ((MemoryBuffer == NULL) || (MemoryBufferSize == NULL)) {
+    if (gDebugFlag) Print (L"ERROR: [#%d] Internal coding error!\n", __LINE__);
+    Status = SHELL_INVALID_PARAMETER;
+    goto Exit;
+  }
+
+  //
+  // Find out the size of the image
+  //
+  ImageSize = GetImageSize (EEPROM_MEMORY);
+  if (ImageSize > 0) {
+    //
+    // Something there to read
+    //
+    ImageBuffer = AllocateZeroPool (ImageSize);
+    if (ImageBuffer == NULL) {
+      Print (L"ERROR: [#%d] Failed to allocate buffer!\n", __LINE__);
+      Status = SHELL_OUT_OF_RESOURCES;
+      goto Exit;
+    }
+
+    //
+    // Read in the memory image
+    //
+    EfiStatus = ReadEeprom (EEPROM_MEMORY, 0, &ImageSize, ImageBuffer, NULL);
+    if (EFI_ERROR (EfiStatus)) {
+      Print (L"ERROR: [#%d] Failed to read image (%r)!\n", __LINE__, EfiStatus);
+      Status = SHELL_DEVICE_ERROR;
+      goto Exit;
+    }
+  }
+
+  //
+  // Write out file image to memory
+  //
+  EfiStatus = WriteEeprom (EEPROM_MEMORY, 0, &BufferSize, Buffer, NULL);
+  if (EFI_ERROR (EfiStatus)) {
+    Print (L"ERROR: [#%d] Failed to write image (%r)!\n", __LINE__, EfiStatus);
+    Status = SHELL_DEVICE_ERROR;
+    goto Exit;
+  }
+
+  //
+  // Send out info
+  //
+  *MemoryBuffer     = ImageBuffer;
+  *MemoryBufferSize = ImageSize;
+
+Exit:
+  if (EFI_ERROR (EfiStatus)) {
+    if (ImageBuffer != NULL) {
+      FreePool (ImageBuffer);
+      ImageBuffer = NULL;
+    }
+  }
+  return Status;
+}
+
+SHELL_STATUS
+CheckForInvalidOptions (
+  IN PROGRAM_INFO    *ProgramInfo
+  )
+{
+  BOOLEAN         InvalidFlag;
+  SHELL_STATUS    Status;
+
+  if (gDebugFlag) Print (L"%a(#%d) - Starting...\n", __FUNCTION__, __LINE__);
+
+  //
+  // Initialize variables
+  //
+  InvalidFlag = FALSE;
+  Status      = SHELL_SUCCESS;
+
+  //
+  // Sanity checks
+  //
+  if (ProgramInfo == NULL) {
+    if (gDebugFlag) Print (L"ERROR: [#%d] Internal coding error!\n", __LINE__);
+    Status = SHELL_INVALID_PARAMETER;
+    goto Exit;
+  }
+
+  //
+  // Dump ProgramInfo for debugging
+  //
+  if (gDebugFlag) DumpProgramInfo (ProgramInfo);
+
+  //
+  // Check for invalid options
+  //
+  if ((ProgramInfo->DumpRawFlag || ProgramInfo->DumpHumanFlag) && (ProgramInfo->ReadFlag)) {
+    InvalidFlag = TRUE;
+    Print (L"ERROR: You can't dump and read at the same time!\n");
+  } else
+
+  if ((ProgramInfo->DumpRawFlag || ProgramInfo->DumpHumanFlag) && (ProgramInfo->VerifyFlag)) {
+    InvalidFlag = TRUE;
+    Print (L"ERROR: You can't dump and verify at the same time!\n");
+  } else
+
+  if ((ProgramInfo->DumpRawFlag || ProgramInfo->DumpHumanFlag) && (ProgramInfo->WriteFlag)) {
+    InvalidFlag = TRUE;
+    Print (L"ERROR: You can't dump and write at the same time!\n");
+  } else
+
+  if (ProgramInfo->CheckFlag && ProgramInfo->ReadFlag) {
+    InvalidFlag = TRUE;
+    Print (L"ERROR: You can't check and read at the same time!\n");
+  } else
+
+  if (ProgramInfo->CheckFlag && ProgramInfo->VerifyFlag) {
+    InvalidFlag = TRUE;
+    Print (L"ERROR: You can't check and verify at the same time!\n");
+  } else
+
+  if (ProgramInfo->CheckFlag && ProgramInfo->WriteFlag) {
+    InvalidFlag = TRUE;
+    Print (L"ERROR: You can't check and write at the same time!\n");
+  } else
+
+  if (ProgramInfo->ReadFlag && ProgramInfo->VerifyFlag) {
+    InvalidFlag = TRUE;
+    Print (L"ERROR: You can't read and verify at the same time!\n");
+  } else
+
+  if (ProgramInfo->ReadFlag && ProgramInfo->WriteFlag) {
+    InvalidFlag = TRUE;
+    Print (L"ERROR: You can't read and write at the same time!\n");
+  } else
+
+  if (ProgramInfo->VerifyFlag && ProgramInfo->WriteFlag) {
+    InvalidFlag = TRUE;
+    Print (L"ERROR: You can't verify and write at the same time!\n");
+  } else
+
+  if (ProgramInfo->CheckFlag && (ProgramInfo->CheckLibraryIndex == EEPROM_EEPROM) &&
+      (!(ProgramInfo->BusFlag && ProgramInfo->AddressFlag) && !ProgramInfo->ScanFlag)) {
+    InvalidFlag = TRUE;
+    Print (L"ERROR: You can't check the security of the image in the EEPROM without specifying the EEPROM bus & address!\n");
+  } else
+
+  if (ProgramInfo->ReadFlag && (ProgramInfo->ReadLibraryIndex == EEPROM_EEPROM) &&
+      (!(ProgramInfo->BusFlag && ProgramInfo->AddressFlag) && !ProgramInfo->ScanFlag)) {
+    InvalidFlag = TRUE;
+    Print (L"ERROR: You can't read the image from the EEPROM without specifying the EEPROM bus & address!\n");
+  } else
+
+  if (ProgramInfo->VerifyFlag && (ProgramInfo->VerifyLibraryIndex == EEPROM_EEPROM) &&
+      (!(ProgramInfo->BusFlag && ProgramInfo->AddressFlag) && !ProgramInfo->ScanFlag)) {
+    InvalidFlag = TRUE;
+    Print (L"ERROR: You can't verify the image in the EEPROM without specifying the EEPROM bus & address!\n");
+  } else
+
+  if (ProgramInfo->WriteFlag && (ProgramInfo->VerifyLibraryIndex == EEPROM_EEPROM) &&
+      (!(ProgramInfo->BusFlag && ProgramInfo->AddressFlag) && !ProgramInfo->ScanFlag)) {
+    InvalidFlag = TRUE;
+    Print (L"ERROR: You can't write the image in the EEPROM without specifying the EEPROM bus & address!\n");
+  } else
+
+  if (ProgramInfo->AddressFlag) {
+    if (ProgramInfo->AddressValue > 0x7F) {
+      Print (L"ERROR: I2C slave address is too large!\n");
+      Status = SHELL_INVALID_PARAMETER;
+      goto Exit;
+    }
+  } else
+
+  if (ProgramInfo->BusFlag) {
+    if (ProgramInfo->BusValue > 7) {
+      Print (L"ERROR: I2C bus number is too large!\n");
+      Status = SHELL_INVALID_PARAMETER;
+      goto Exit;
+    }
+  }
+
+  //
+  // Set return value
+  //
+  if (InvalidFlag) {
+    Status = SHELL_INVALID_PARAMETER;
+  }
+
+Exit:
+  return Status;
+}
+
+SHELL_STATUS
+CheckOption (
+  IN PROGRAM_INFO    *ProgramInfo
+  )
+{
+  EFI_STATUS              EfiStatus;
+  UINT8                  *ImageBuffer;
+  UINT32                  ImageSize;
+  SHELL_STATUS            Status;
+
+  if (gDebugFlag) Print (L"%a(#%d) - Starting...\n", __FUNCTION__, __LINE__);
+
+  //
+  // Initialize variables
+  //
+  ImageBuffer = NULL;
+  Status      = SHELL_SUCCESS;
+
+  //
+  // Sanity checks
+  //
+  if (ProgramInfo == NULL) {
+    if (gDebugFlag) Print (L"ERROR: [#%d] Internal coding error!\n", __LINE__);
+    Status = SHELL_INVALID_PARAMETER;
+    goto Exit;
+  }
+  if (ProgramInfo->CheckFileName != NULL) {
+    if ((ProgramInfo->CheckFile == NULL) || (ProgramInfo->CheckFileSize == 0)) {
+      if (gDebugFlag) Print (L"ERROR: [#%d] Image file is empty!\n", __LINE__);
+      Status = SHELL_INVALID_PARAMETER;
+      goto Exit;
+    }
+  }
+
+  //
+  // Checking security of file image
+  //
+  Print (L"  - Validating...\n");
+  if (ProgramInfo->CheckFileName != NULL) {
+    //
+    // Swap File buffer with EEPROM_MEMORY
+    //
+    Status = BufferToMemory (ProgramInfo->CheckFile, ProgramInfo->CheckFileSize, &ImageBuffer, &ImageSize);
+    if (Status != SHELL_SUCCESS) {
+      Print (L"ERROR: [#%d] Failed to retrieve original memory image (%r)!\n", __LINE__, Status);
+      Status = SHELL_DEVICE_ERROR;
+      goto Exit;
+    }
+
+    //
+    // Validate image
+    //
+    EfiStatus = ValidateEeprom (EEPROM_MEMORY);
+    Print (L"  - File validation status = %r\n", EfiStatus);
+
+    //
+    // Was there something in memory before?
+    //
+    if (ImageBuffer != NULL) {
+      //
+      // Restore memory image
+      //
+      EfiStatus = WriteEeprom (EEPROM_MEMORY, 0, &ImageSize, ImageBuffer, NULL);
+      if (EFI_ERROR (EfiStatus)) {
+        Print (L"ERROR: [#%d] Failed to restore original memory image (%r)!\n", __LINE__, EfiStatus);
+        Status = SHELL_DEVICE_ERROR;
+        goto Exit;
+      }
+
+      //
+      // Revalidate the memory image
+      //
+      EfiStatus = ValidateEeprom (EEPROM_MEMORY);
+      if (EFI_ERROR (EfiStatus)) {
+        Print (L"ERROR: [#%d] Failed to validate original memory image (%r)!\n", __LINE__, EfiStatus);
+        Status = SHELL_DEVICE_ERROR;
+        goto Exit;
+      }
+    }
+  } else
+
+  //
+  // Just validate the current image
+  //
+  {
+    EfiStatus = ValidateEeprom (ProgramInfo->CheckLibraryIndex);
+    Print (L"  - Image validation status = %r\n", EfiStatus);
+  }
+
+  Status = SHELL_SUCCESS;
+
+Exit:
+  //
+  // Free resources
+  //
+  if (ImageBuffer != NULL) {
+    FreePool (ImageBuffer);
+    ImageBuffer = NULL;
+  }
+  return Status;
+}
+
+SHELL_STATUS
+DumpHumanOption (
+  IN PROGRAM_INFO    *ProgramInfo
+  )
+{
+  CHAR8                   AsciiData[16];
+  VOID                   *Buffer;
+  UINT32                  BufferSize;
+  UINT32                  count;
+  EEPROM_FUNCTION_INFO    EepromInfo;
+  EFI_STATUS              EfiStatus;
+  VOID                   *FunctionInfo;
+  GENERIC_HEADER         *GenericHeader;
+  UINT8                  *Hash;
+  UINT32                  HashSize;
+  UINT8                  *ImageBuffer;
+  UINT32                  ImageSize;
+  UINT32                  index;
+  UINT8                   LibraryIndex;
+  UINT8                  *Ptr;
+  UINT8                  *Signature;
+  UINT32                  SignatureSize;
+  SHELL_STATUS            Status;
+  UINT32                  StructureSize;
+
+  if (gDebugFlag) Print (L"%a(#%d) - Starting...\n", __FUNCTION__, __LINE__);
+
+  //
+  // Initialize variables
+  //
+  ZeroMem (&EepromInfo, sizeof (EEPROM_FUNCTION_INFO));
+  EepromInfo.Bus          = ProgramInfo->BusValue;
+  EepromInfo.Address      = ProgramInfo->AddressValue;
+  EepromInfo.LibraryIndex = EEPROM_EEPROM;
+  Buffer                  = NULL;
+  FunctionInfo            = NULL;
+  Hash                    = NULL;
+  HashSize                = 0;
+  ImageBuffer             = NULL;
+  LibraryIndex            = ProgramInfo->DumpHumanLibraryIndex;
+  Signature               = NULL;
+  SignatureSize           = 0;
+  Status                  = SHELL_SUCCESS;
+
+  //
+  // Sanity checks
+  //
+  if (ProgramInfo == NULL) {
+    if (gDebugFlag) Print (L"ERROR: [#%d] Internal coding error!\n", __LINE__);
+    Status = SHELL_INVALID_PARAMETER;
+    goto Exit;
+  }
+  if (ProgramInfo->DumpHumanFileName != NULL) {
+    if ((ProgramInfo->DumpHumanFile == NULL) || (ProgramInfo->DumpHumanFileSize == 0)) {
+      if (gDebugFlag) Print (L"ERROR: [#%d] Image file is empty!\n", __LINE__);
+      Status = SHELL_INVALID_PARAMETER;
+      goto Exit;
+    }
+  }
+
+  if (ProgramInfo->DumpHumanFileName != NULL) {
+    //
+    // Swap File buffer with EEPROM_MEMORY
+    //
+    Status = BufferToMemory (ProgramInfo->DumpHumanFile, ProgramInfo->DumpHumanFileSize, &ImageBuffer, &ImageSize);
+    if (Status != SHELL_SUCCESS) {
+      Print (L"ERROR: [#%d] Failed to retrieve original memory image (%r)!\n", __LINE__, Status);
+      Status = SHELL_DEVICE_ERROR;
+      goto Exit;
+    }
+
+    //
+    // Point to EEPROM_MEMORY library
+    //
+    LibraryIndex = EEPROM_MEMORY;
+  }
+
+  //
+  // Parse the image into human readable form
+  //
+  index = 0;
+  EfiStatus = EFI_SUCCESS;
+  while (!EFI_ERROR (EfiStatus)) {
+    EfiStatus = GetNextEepromStructure (LibraryIndex, &index, (UINT8 **) &Buffer, &BufferSize);
+    if (!EFI_ERROR (EfiStatus)) {
+      //
+      // Got a structure
+      //
+      GenericHeader = (GENERIC_HEADER *) Buffer;
+      CopyMem (AsciiData, GenericHeader->signature, sizeof (GenericHeader->signature));
+      AsciiData[sizeof (GenericHeader->signature)] = 0;
+      StructureSize = GenericHeader->length;
+      if (GenericHeader->signature[0] != '$') {
+        Print (L"ERROR: [#%d] Structure signature [%a] doesn't start with $!\n", __LINE__, AsciiData);
+        EfiStatus = EFI_COMPROMISED_DATA;
+        continue;
+      }
+      //
+      // Dump generic header info
+      //
+      Print (L"Signature           = %a\n",   AsciiData);
+      Print (L"Major version       = %04x\n", GenericHeader->vermajor);
+      Print (L"Minor version       = %04x\n", GenericHeader->verminor);
+      Print (L"Length              = %08x\n", StructureSize);
+      //
+      // Check for $AcpiTbl
+      //
+      if (AsciiStrnCmp (GenericHeader->signature, "$AcpiTbl", 8) == 0) {
+        ACPI_TABLE   *AcpiTable;
+        AcpiTable = (ACPI_TABLE *) Buffer;
+        Ptr       = (UINT8 *) Buffer + sizeof (ACPI_TABLE);
+        if (ProgramInfo->VerboseFlag) DumpParagraph (Ptr, (AcpiTable->length - (Ptr - (UINT8 *) Buffer)));
+      } else
+      //
+      // Check for $BrdInfo
+      //
+      if (AsciiStrnCmp (GenericHeader->signature, "$BrdInfo", 8) == 0) {
+        BOARD_INFO_TABLE   *BoardInfo;
+        BoardInfo = (BOARD_INFO_TABLE *) Buffer;
+        ZeroMem (AsciiData, 17);
+        CopyMem (AsciiData, BoardInfo->manuname, 16);
+        Print (L"Manufacturing name  = %a\n", AsciiData);
+        ZeroMem (AsciiData, 17);
+        CopyMem (AsciiData, BoardInfo->brdname, 16);
+        Print (L"Board name          = %a\n", AsciiData);
+        ZeroMem (AsciiData, 17);
+        CopyMem (AsciiData, BoardInfo->brdserial, 16);
+        Print (L"Board serial #      = %a\n",   AsciiData);
+        Print (L"Board ID            = %08x\n", BoardInfo->boardid);
+        Print (L"Fab ID              = %08x\n", BoardInfo->fabid);
+        Print (L"EC ID               = %08x\n", BoardInfo->ecid);
+        Print (L"Board type          = ");
+        if (BoardInfo->boardtype == 0) {
+          Print (L"Main board (RedBox)\n");
+        } else
+        if (BoardInfo->boardtype == 1) {
+          Print (L"Plug-in board\n");
+        } else
+        {
+          Print (L"[%02x] - Unknown\n", BoardInfo->boardtype);
+        }
+      } else
+      //
+      // Check for $EeprMap
+      //
+      if (AsciiStrnCmp (GenericHeader->signature, "$EeprMap", 8) == 0) {
+        EEPROM_MAP          *EepromMap;
+        EEPROM_MAP_RECORD   *MapRecord;
+        EepromMap = (EEPROM_MAP *) Buffer;
+        MapRecord = (EEPROM_MAP_RECORD *) ((UINT8 *) Buffer + sizeof (EEPROM_MAP));
+        ZeroMem (AsciiData, 17);
+        CopyMem (AsciiData, EepromMap->partlabel, 16);
+        Print (L"Part label          = %a\n",   AsciiData);
+        Print (L"Block length        = %08x\n", EepromMap->blklength);
+        Print (L"Page size           = %04x\n", EepromMap->pagesize);
+        Print (L"Total part size     = %08x\n", EepromMap->partsize);
+        Print (L"I2C bus number      = %02x\n", EepromMap->busnumber);
+        Print (L"Map master          = ");
+        if (EepromMap->master == 0) {
+          Print (L"Not the master map\n");
+        } else
+        if (EepromMap->master == 1) {
+          Print (L"Master map\n");
+        } else
+        {
+          Print (L"[%02x] - Unknown\n", EepromMap->master);
+        }
+        Print (L"I2C speed           = ");
+        if (EepromMap->speed == 1) {
+          Print (L"100KHz (Standard speed)\n");
+        } else
+        if (EepromMap->speed == 2) {
+          Print (L"400KHz (Fast speed)\n");
+        } else
+        if (EepromMap->speed == 3) {
+          Print (L"3.4MHz (High speed)\n");
+        } else
+        {
+          Print (L"[%02x] - Unknown\n", EepromMap->speed);
+        }
+        //
+        // Loop thru map records
+        //
+        while ((UINT8 *) MapRecord < ((UINT8 *) Buffer + EepromMap->length)) {
+          ZeroMem (AsciiData, 17);
+          CopyMem (AsciiData, MapRecord->maplabel, 16);
+          Print (L" - Record label     = %a\n",   AsciiData);
+          Print (L"   - Record length  = %08x\n", MapRecord->length);
+          Print (L"   - Binary offset  = %08x\n", MapRecord->offset);
+          Print (L"   - I2C address    = %02x\n", MapRecord->address);
+          //
+          // Increment record
+          //
+          MapRecord++;
+        }
+      } else
+      //
+      // Check for $Eeprom$ structure
+      //
+      if (AsciiStrnCmp (GenericHeader->signature, "$Eeprom$", 8) == 0) {
+        EEPROM_HEADER   *EepromHeader;
+        EepromHeader = (EEPROM_HEADER *) Buffer;
+        Print (L"Image length        = %08x\n", EepromHeader->structlength);
+        Print (L"Image CRC32         = %08x\n", EepromHeader->crc32);
+        Print (L"Image CRC32 length  = %08x\n", EepromHeader->crclength);
+        Print (L"Image version       = %08x\n", EepromHeader->version);
+      } else
+      //
+      // Check for $GpioDat
+      //
+      if (AsciiStrnCmp (GenericHeader->signature, "$GpioDat", 8) == 0) {
+        GPIO_DATA_HEADER   *GpioHeader;
+        GPIO_DATA_RECORD   *GpioRecord;
+        GpioHeader = (GPIO_DATA_HEADER *) Buffer;
+        GpioRecord = (GPIO_DATA_RECORD *)  ((UINT8 *) Buffer + sizeof (GPIO_DATA_HEADER));
+        //
+        // Loop thru GPIO records
+        //
+        while ((UINT8 *) GpioRecord < ((UINT8 *) Buffer + GpioHeader->length)) {
+          ZeroMem (AsciiData, 17);
+          CopyMem (AsciiData, GpioRecord->gpiolabel, 16);
+          Print (L" - GPIO label       = %a\n",   AsciiData);
+          Print (L"   - Record length  = %08x\n", GpioRecord->length);
+          Print (L"   - GPIO offset    = %08x\n", GpioRecord->offset);
+          Print (L"   - GPIO AND data  = %08x\n", GpioRecord->anddata);
+          Print (L"   - GPIO OR data   = %08x\n", GpioRecord->ordata);
+          Print (L"   - GPIO data size = %08x\n", GpioRecord->datasize);
+          Print (L"   - GPIO data type = ");
+          if (GpioRecord->datasize == 0) {
+            Print (L"IO\n");
+          } else
+          if (GpioRecord->datasize == 1) {
+            Print (L"MMIO\n");
+          } else
+          if (GpioRecord->datasize == 2) {
+            Print (L"PCI\n");
+          } else
+          if (GpioRecord->datasize == 3) {
+            Print (L"PCIe\n");
+          } else
+          if (GpioRecord->datasize == 4) {
+            Print (L"PAD offset\n");
+          } else
+          {
+            Print (L"[%02x] - Unknown\n", GpioRecord->datasize);
+          }
+          //
+          // Increment record
+          //
+          GpioRecord++;
+        }
+      } else
+      //
+      // Check for $HdCodec
+      //
+      if (AsciiStrnCmp (GenericHeader->signature, "$HdCodec", 8) == 0) {
+        HDA_CODEC   *HdaCodec;
+        HdaCodec = (HDA_CODEC *) Buffer;
+        Ptr      = (UINT8 *) Buffer + sizeof (HDA_CODEC);
+        if (ProgramInfo->VerboseFlag) DumpParagraph (Ptr, (HdaCodec->length - (Ptr - (UINT8 *) Buffer)));
+      } else
+      //
+      // Check for $Logo$
+      //
+      if (AsciiStrnCmp (GenericHeader->signature, "$Logo$", 6) == 0) {
+        LOGO_DATA   *LogoData;
+        LogoData = (LOGO_DATA *) Buffer;
+        Ptr      = (UINT8 *) Buffer + sizeof (LOGO_DATA);
+        if (ProgramInfo->VerboseFlag) DumpParagraph (Ptr, (LogoData->length - (Ptr - (UINT8 *) Buffer)));
+      } else
+      //
+      // Check for $MacInfo
+      //
+      if (AsciiStrnCmp (GenericHeader->signature, "$MacInfo", 8) == 0) {
+        NIC_INFO   *NicInfo;
+        NicInfo = (NIC_INFO *) Buffer;
+        ZeroMem (AsciiData, 9);
+        CopyMem (AsciiData, NicInfo->nicid, 8);
+        Print (L"NIC ID              = %a\n",   AsciiData);
+        Print (L"MAC address         = %12x\n", NicInfo->macaddr);
+        Print (L"NIC number          = %2x\n",  NicInfo->nicnum);
+        Ptr = (UINT8 *) Buffer + sizeof (NIC_INFO);
+        if (ProgramInfo->VerboseFlag) DumpParagraph (Ptr, (NicInfo->length - (Ptr - (UINT8 *) Buffer)));
+      } else
+      //
+      // Check for $MemCnfg
+      //
+      if (AsciiStrnCmp (GenericHeader->signature, "$MemCnfg", 8) == 0) {
+        UINT8         Slot;
+        MEMORY_SPD   *MemoryData;
+        MemoryData = (MEMORY_SPD *) Buffer;
+        Print (L"SPD slot flags      = %04x\n", MemoryData->spdslot);
+        for (Slot = 0; Slot < 16; Slot++) {
+          if (MemoryData->spdslot & (1 << Slot)) {
+            Print (L"  - Slot %d support.\n", Slot + 1);
+          }
+        }
+        Ptr = (UINT8 *) Buffer + sizeof (MEMORY_SPD);
+        if (ProgramInfo->VerboseFlag) DumpParagraph (Ptr, (MemoryData->length - (Ptr - (UINT8 *) Buffer)));
+      } else
+      //
+      // Check for $PromSig
+      //
+      if (AsciiStrnCmp (GenericHeader->signature, "$PromSig", 8) == 0) {
+        UINT16            HashType;
+        SIGNATURE_DATA   *SignatureData;
+        SignatureData = (SIGNATURE_DATA *) Buffer;
+        Hash          = (UINT8 *) Buffer + sizeof (SIGNATURE_DATA);
+        HashType = (SignatureData->hashtype & 0x7FFF);
+        Print (L"Hash type           = ");
+        if (HashType == HASH_NONE) {
+          Print (L"None\n");
+          HashSize = 0;
+        } else
+        if (HashType == HASH_MD5) {
+          Print (L"MD5\n");
+          HashSize = MD5DigestSize;
+        } else
+        if (HashType == HASH_SHA1) {
+          Print (L"SHA1\n");
+          HashSize = SHA1DigestSize;
+        } else
+        if (HashType == HASH_SHA256) {
+          Print (L"SHA256\n");
+          HashSize = SHA256DigestSize;
+        } else
+        if (HashType == HASH_SHA384) {
+          Print (L"SHA384\n");
+          HashSize = SHA384DigestSize;
+        } else
+        if (HashType == HASH_SHA512) {
+          Print (L"SHA512\n");
+          HashSize = SHA512DigestSize;
+        } else
+        {
+          Print (L"[%04x] Unknown\n", HashType);
+        }
+        Print (L"Hash signed         = ");
+        if (HashType != SignatureData->hashtype) {
+          Print (L"True\n");
+          Signature     = Hash + HashSize;
+          SignatureSize = 256;
+        } else {
+          Print (L"False\n");
+          Signature     = NULL;
+          SignatureSize = 0;
+        }
+        // Dump hash
+        Print (L"Hash                = ");
+        for (count = 0; count < HashSize; count++) {
+          if (((count % 0x10) == 0) && (count > 0)) {
+            Print (L"\n                      ");
+          }
+          Print (L"%02X", Hash[count]);
+        }
+        Print (L"\n");
+        // Dump signed hash
+        if (HashType != SignatureData->hashtype) {
+          Print (L"Signed Hash         = ");
+          for (count = 0; count < SignatureSize; count++) {
+            if (((count % 0x10) == 0) && (count > 0)) {
+              Print (L"\n                      ");
+            }
+            Print (L"%02X", Signature[count]);
+          }
+          Print (L"\n");
+        }
+      } else
+      //
+      // Check for $uCode$
+      //
+      if (AsciiStrnCmp (GenericHeader->signature, "$uCode$", 7) == 0) {
+        MICROCODE   *MicrocodeData;
+        MicrocodeData = (MICROCODE *) Buffer;
+        Ptr      = (UINT8 *) Buffer + sizeof (MICROCODE);
+        if (ProgramInfo->VerboseFlag) DumpParagraph (Ptr, (MicrocodeData->length - (Ptr - (UINT8 *) Buffer)));
+      } else
+      //
+      // Check for $Video$
+      //
+      if (AsciiStrnCmp (GenericHeader->signature, "$Video$", 7) == 0) {
+        VIDEO_DATA   *VideoData;
+        VideoData = (VIDEO_DATA *) Buffer;
+        Ptr       = (UINT8 *) Buffer + sizeof (VIDEO_DATA);
+        if (ProgramInfo->VerboseFlag) DumpParagraph (Ptr, (VideoData->length - (Ptr - (UINT8 *) Buffer)));
+      } else
+      //
+      // Unknown structure
+      //
+      {
+        Ptr = (UINT8 *) Buffer + sizeof (GENERIC_HEADER);
+        if (ProgramInfo->VerboseFlag) DumpParagraph (Ptr, (GenericHeader->length - (Ptr - (UINT8 *) Buffer)));
+      }
+    }
+    Print (L"\n");
+  }
+
+  if (ProgramInfo->CheckFileName != NULL) {
+    //
+    // Restore EEPROM_MEMORY from temp buffer
+    //
+    if (ImageBuffer != NULL) {
+      //
+      // Restore memory image
+      //
+      EfiStatus = WriteEeprom (EEPROM_MEMORY, 0, &ImageSize, ImageBuffer, NULL);
+      if (EFI_ERROR (EfiStatus)) {
+        Print (L"ERROR: [#%d] Failed to restore original memory image (%r)!\n", __LINE__, EfiStatus);
+        Status = SHELL_DEVICE_ERROR;
+        goto Exit;
+      }
+
+      //
+      // Re-validate the memory image
+      //
+      EfiStatus = ValidateEeprom (EEPROM_MEMORY);
+      if (EFI_ERROR (EfiStatus)) {
+        Print (L"ERROR: [#%d] Failed to validate original memory image (%r)!\n", __LINE__, EfiStatus);
+        Status = SHELL_DEVICE_ERROR;
+        goto Exit;
+      }
+    }
+  }
+
+Exit:
+  //
+  // Free resources
+  //
+  if (Buffer != NULL) {
+    FreePool (Buffer);
+    Buffer = NULL;
+  }
+  if (ImageBuffer != NULL) {
+    FreePool (ImageBuffer);
+    ImageBuffer = NULL;
+  }
+  return Status;
+}
+
+VOID
+DumpParagraph (
+  IN   VOID   *Ptr,
+  IN   UINTN   Count
+  )
+{
+  CHAR8     AsciiBuffer[17];
+  UINT8    *Data;
+  UINTN     Index;
+  UINTN     Paragraphs;
+  UINTN     PlaceHolder;
+  UINT8     PlaceHolders;
+
+  if (gDebugFlag) Print (L"%a(#%d) - Starting...\n", __FUNCTION__, __LINE__);
+
+  // Check for invalid conditions
+  if (Ptr == NULL) {
+    if (gDebugFlag) Print (L"ERROR: [#%d] Internal coding error!\n", __LINE__);
+    goto Exit;
+  }
+
+  // Start dumping the buffer
+  if (Count > 0 ) {
+    // Initialize variables
+    Data = (UINT8 *) Ptr;
+    Paragraphs = Count / 16;
+    if ((Paragraphs * 16) < Count) {
+      Paragraphs++;
+    }
+    PlaceHolder  = Paragraphs;
+    PlaceHolders = 0;
+    while (PlaceHolder > 0) {
+      PlaceHolders++;
+      PlaceHolder >>= 4;
+    }
+
+    // Print Header
+    PrintChar (PlaceHolders + 5, L" ");
+    Print (DIVIDING_LINE);
+    PrintChar (PlaceHolders + 5, L" ");
+    Print (L"| x0 x1 x2 x3  x4 x5 x6 x7  x8 x9 xA xB  xC xD xE xF |      String      |\n");
+    Print (L" +");
+    PrintChar (PlaceHolders + 3, L"-");
+    Print (DIVIDING_LINE);
+
+    // Print data
+    for (Index = 0; Index < (Paragraphs * 16); Index++) {
+      if (Index % 0x10 == 0x00) {
+        if ((Index > 0) && ((Index / 0x10) % 0x04 == 0x00) && (Paragraphs > 6)) {
+          Print (L" +");
+          PrintChar (PlaceHolders + 3, L"-");
+          Print (DIVIDING_LINE);
+        }
+        Print (L" | %0*xx | ", PlaceHolders, (Index / 0x10));
+      }
+
+      // Print the data or a filler
+      if (Index < Count) {
+        Print (L"%02x ", Data[Index]);
+        if ((Data[Index] < 32) || (Data[Index] > 126)) {
+          // Not printable
+          AsciiBuffer[(Index % 0x10)] = '.';
+        } else {
+          // Printable
+          AsciiBuffer[(Index % 0x10)] = Data[Index];
+        }
+      } else {
+        Print (L"   ");
+        AsciiBuffer[(Index % 0x10)] = ' ';
+      }
+
+      // Print break or line end if needed
+      if (Index % 0x10 == 0x0F) {
+        AsciiBuffer[16] = 0x00;
+        Print (L"| %a |\n", AsciiBuffer);
+      } else if (Index % 0x04 == 0x03) {
+        Print (L" ");
+      }
+    }
+
+    // Print footer
+    Print (L" +");
+    PrintChar (PlaceHolders + 3, L"-");
+    Print (DIVIDING_LINE);
+  }
+
+Exit:
+  return;
+}
+
+VOID
+DumpProgramInfo (
+  IN PROGRAM_INFO    *ProgramInfo
+  )
+{
+  if (gDebugFlag) Print (L"%a(#%d) - Starting...\n", __FUNCTION__, __LINE__);
+
+  Print (L"ProgramInfo                @ %08x\n", ProgramInfo);
+  Print (L" - HelpFlag                = %02x\n", ProgramInfo->HelpFlag);
+  Print (L" - AddressFlag             = %02x\n", ProgramInfo->AddressFlag);
+  Print (L"   - AddressValue          = %02x\n", ProgramInfo->AddressValue);
+  Print (L" - BusFlag                 = %02x\n", ProgramInfo->BusFlag);
+  Print (L"   - BusValue              = %02x\n", ProgramInfo->BusValue);
+  Print (L" - CheckFlag               = %02x\n", ProgramInfo->CheckFlag);
+  Print (L"   - CheckLibraryIndex     = %02x\n", ProgramInfo->CheckLibraryIndex);
+  Print (L"   - CheckFile             = %08x\n", ProgramInfo->CheckFile);
+  Print (L"   - CheckFileName         = %s\n",   ProgramInfo->CheckFileName);
+  Print (L"   - CheckFileSize         = %08x\n", ProgramInfo->CheckFileSize);
+  Print (L" - DumpHumanFlag           = %02x\n", ProgramInfo->DumpHumanFlag);
+  Print (L"   - DumpHumanLibraryIndex = %02x\n", ProgramInfo->DumpHumanLibraryIndex);
+  Print (L"   - DumpHumanFile         = %08x\n", ProgramInfo->DumpHumanFile);
+  Print (L"   - DumpHumanFileName     = %s\n",   ProgramInfo->DumpHumanFileName);
+  Print (L"   - DumpHumanFileSize     = %08x\n", ProgramInfo->DumpHumanFileSize);
+  Print (L" - DumpRawFlag             = %02x\n", ProgramInfo->DumpRawFlag);
+  Print (L"   - DumpRawLibraryIndex   = %02x\n", ProgramInfo->DumpRawLibraryIndex);
+  Print (L"   - DumpRawFile           = %08x\n", ProgramInfo->DumpRawFile);
+  Print (L"   - DumpRawFileName       = %s\n",   ProgramInfo->DumpRawFileName);
+  Print (L"   - DumpRawFileSize       = %08x\n", ProgramInfo->DumpRawFileSize);
+  Print (L" - EraseFlag               = %02x\n", ProgramInfo->EraseFlag);
+  Print (L"   - EraseLibraryIndex     = %02x\n", ProgramInfo->EraseLibraryIndex);
+  Print (L" - ReadFlag                = %02x\n", ProgramInfo->ReadFlag);
+  Print (L"   - ReadLibraryIndex      = %02x\n", ProgramInfo->ReadLibraryIndex);
+  Print (L"   - ReadFile              = %08x\n", ProgramInfo->ReadFile);
+  Print (L"   - ReadFileName          = %s\n",   ProgramInfo->ReadFileName);
+  Print (L"   - ReadFileSize          = %08x\n", ProgramInfo->ReadFileSize);
+  Print (L" - ScanFlag                = %02x\n", ProgramInfo->ScanFlag);
+  Print (L" - VerifyFlag              = %02x\n", ProgramInfo->VerifyFlag);
+  Print (L"   - VerifyLibraryIndex    = %02x\n", ProgramInfo->VerifyLibraryIndex);
+  Print (L"   - VerifyFile            = %08x\n", ProgramInfo->VerifyFile);
+  Print (L"   - VerifyFileName        = %s\n",   ProgramInfo->VerifyFileName);
+  Print (L"   - VerifyFileSize        = %08x\n", ProgramInfo->VerifyFileSize);
+  Print (L" - WriteFlag               = %02x\n", ProgramInfo->WriteFlag);
+  Print (L"   - WriteLibraryIndex     = %02x\n", ProgramInfo->WriteLibraryIndex);
+  Print (L"   - WriteFile             = %08x\n", ProgramInfo->WriteFile);
+  Print (L"   - WriteFileName         = %s\n",   ProgramInfo->WriteFileName);
+  Print (L"   - WriteFileSize         = %08x\n", ProgramInfo->WriteFileSize);
+}
+
+SHELL_STATUS
+DumpRawOption (
+  IN PROGRAM_INFO    *ProgramInfo
+  )
+{
+  EEPROM_FUNCTION_INFO    EepromInfo;
+  EFI_STATUS              EfiStatus;
+  VOID                   *FunctionInfo;
+  SHELL_STATUS            Status;
+
+  if (gDebugFlag) Print (L"%a(#%d) - Starting...\n", __FUNCTION__, __LINE__);
+
+  //
+  // Initialize variables
+  //
+  ZeroMem (&EepromInfo, sizeof (EEPROM_FUNCTION_INFO));
+  EepromInfo.Bus          = ProgramInfo->BusValue;
+  EepromInfo.Address      = ProgramInfo->AddressValue;
+  EepromInfo.LibraryIndex = EEPROM_EEPROM;
+  FunctionInfo            = NULL;
+  Status                  = SHELL_SUCCESS;
+
+  //
+  // Sanity checks
+  //
+  if (ProgramInfo == NULL) {
+    if (gDebugFlag) Print (L"ERROR: [#%d] Internal coding error!\n", __LINE__);
+    Status = SHELL_INVALID_PARAMETER;
+    goto Exit;
+  }
+  if (ProgramInfo->DumpRawFileName != NULL) {
+    if ((ProgramInfo->DumpRawFile == NULL) || (ProgramInfo->DumpRawFileSize == 0)) {
+      if (gDebugFlag) Print (L"ERROR: [#%d] Image file is empty!\n", __LINE__);
+      Status = SHELL_INVALID_PARAMETER;
+      goto Exit;
+    }
+  }
+
+  //
+  // Read in the image file
+  //
+  if (ProgramInfo->DumpRawFileName == NULL) {
+    //
+    // Find out the size of the image
+    //
+    ProgramInfo->DumpRawFileSize = GetImageSize (ProgramInfo->DumpRawLibraryIndex);
+    ProgramInfo->DumpRawFile     = AllocateZeroPool (ProgramInfo->DumpRawFileSize);
+    if (ProgramInfo->DumpRawFile == NULL) {
+      Print (L"ERROR: [#%d] Failed to allocate buffer!\n", __LINE__);
+      Status = SHELL_OUT_OF_RESOURCES;
+      goto Exit;
+    }
+
+    //
+    // Read in the image
+    //
+    if (ProgramInfo->DumpRawLibraryIndex == EEPROM_EEPROM) {
+      FunctionInfo = (VOID *) &EepromInfo;
+    }
+    EfiStatus = ReadEeprom (ProgramInfo->DumpRawLibraryIndex, 0, &ProgramInfo->DumpRawFileSize, ProgramInfo->DumpRawFile, FunctionInfo);
+    if (EFI_ERROR (EfiStatus)) {
+      Print (L"ERROR: [#%d] Failed to read image file (%r)!\n", __LINE__, EfiStatus);
+      Status = SHELL_DEVICE_ERROR;
+      goto Exit;
+    }
+  }
+
+  //
+  // Dump the image
+  //
+  DumpParagraph (ProgramInfo->DumpRawFile, ProgramInfo->DumpRawFileSize);
+
+  //
+  // Set exit value
+  //
+  Status = SHELL_SUCCESS;
+
+Exit:
+  return Status;
+}
+
+SHELL_STATUS
+EraseOption (
+  IN PROGRAM_INFO    *ProgramInfo
+  )
+{
+  EFI_STATUS              EfiStatus;
+  SHELL_STATUS            Status;
+
+  if (gDebugFlag) Print (L"%a(#%d) - Starting...\n", __FUNCTION__, __LINE__);
+
+  //
+  // Initialize variables
+  //
+  Status = SHELL_SUCCESS;
+
+  EfiStatus = EraseEeprom (ProgramInfo->EraseLibraryIndex);
+  if (EFI_ERROR (EfiStatus)) {
+    Print (L"ERROR: [#%d] Failed to erase image file (%r)!\n", __LINE__, EfiStatus);
+    Status = SHELL_DEVICE_ERROR;
+  }
+  return Status;
+}
+
+UINTN
+GetHexOrDecFromString (
+  CHAR16 *Arg
+  )
+{
+  CHAR16 Str[2];
+
+  Str[0] = Arg[0];
+  Str[1] = Arg[1];
+
+  if (StrCmp (Str, L"0x") == 0 ||
+    StrCmp (Str, L"0X") == 0) {
+    return StrHexToUintn (Arg);
+  } else{
+    return StrDecimalToUintn (Arg);
+  }
+}
+
+VOID
+ParseParameters (
+  IN UINTN            Argc,
+  IN CHAR16         **Argv,
+  IN PROGRAM_INFO    *ProgramInfo
+  )
+{
+  EFI_STATUS   EfiStatus;
+  UINTN        Index;
+
+  if (gDebugFlag) Print (L"%a(#%d) - Starting...\n", __FUNCTION__, __LINE__);
+
+  // Sanity checks
+  if ((Argv == NULL) || (ProgramInfo == NULL)) {
+    if (gDebugFlag) Print (L"ERROR: [#%d] Internal coding error!\n", __LINE__);
+    goto Exit;
+  }
+
+  // Clear ProgramInfo
+  ZeroMem (ProgramInfo, sizeof (ProgramInfo));
+
+  for (Index = 1; Index < Argc; Index++) {
+    // Convert to lowercase for easier parsing
+    ToLower (Argv[Index]);
+
+    // Check for Debug option
+    if (StrCmp (Argv[Index], L"--debug") == 0) {
+      // Debug option detected
+      gDebugFlag = TRUE;
+      Print (L"Enabling debug mode...\n");
+    } else
+
+    // Check for Help option
+    if ((StrCmp (Argv[Index], L"-h") == 0)     ||
+        (StrCmp (Argv[Index], L"--help") == 0) ||
+        (StrCmp (Argv[Index], L"-?") == 0)) {
+      // Help option detected
+      ProgramInfo->HelpFlag = TRUE;
+    } else
+
+    // Check for Address option
+    if ((StrCmp (Argv[Index], L"-a") == 0) || (StrCmp (Argv[Index], L"--address") == 0)) {
+      // Address option detected
+      ProgramInfo->AddressFlag = TRUE;
+      if (Index + 1 < Argc) {
+        // Get Slave address
+        if (Argv[Index + 1][0] != L'-') {
+          ProgramInfo->AddressValue = (UINT8) (GetHexOrDecFromString (Argv[Index + 1]) & 0xFF);
+          Index++;
+        }
+      }
+    } else
+
+    // Check for Bus option
+    if ((StrCmp (Argv[Index], L"-b") == 0) || (StrCmp (Argv[Index], L"--bus") == 0)) {
+      // Bus option detected
+      ProgramInfo->BusFlag = TRUE;
+      if (Index + 1 < Argc) {
+        // Get bus number
+        if (Argv[Index + 1][0] != L'-') {
+          ProgramInfo->BusValue = (UINT8) (GetHexOrDecFromString (Argv[Index + 1]) & 0xFF);
+          Index++;
+        }
+      }
+    } else
+
+    // Check for Check security option
+    if ((StrCmp (Argv[Index], L"-c") == 0) || (StrCmp (Argv[Index], L"--check") == 0)) {
+      // Check security option detected
+      ProgramInfo->CheckFlag = TRUE;
+      if (Index + 1 < Argc) {
+        // Get Library Index
+        if (Argv[Index + 1][0] != L'-') {
+          ProgramInfo->CheckLibraryIndex = (UINT8) (GetHexOrDecFromString (Argv[Index + 1]) & 0xFF);
+          Index++;
+        }
+      }
+      if (Index + 1 < Argc) {
+        // Get Filename
+        if (Argv[Index + 1][0] != L'-') {
+          ProgramInfo->CheckFileName = Argv[Index + 1];
+          Index++;
+          // Read in file
+          ProgramInfo->CheckFile = NULL;
+          EfiStatus = ReadFileData (ProgramInfo->CheckFileName, &ProgramInfo->CheckFile, &ProgramInfo->CheckFileSize);
+          if (EFI_ERROR (EfiStatus)) {
+            Print (L"ERROR: [#%d] Failed to read image file (%r)!\n", __LINE__, EfiStatus);
+          }
+        }
+      }
+    } else
+
+    // Check for Dump raw option
+    if ((StrCmp (Argv[Index], L"-d") == 0) || (StrCmp (Argv[Index], L"--dump") == 0)) {
+      // Dump raw option detected
+      ProgramInfo->DumpRawFlag = TRUE;
+      if (Index + 1 < Argc) {
+        // Get Library Index
+        if (Argv[Index + 1][0] != L'-') {
+          ProgramInfo->DumpRawLibraryIndex = (UINT8) (GetHexOrDecFromString (Argv[Index + 1]) & 0xFF);
+          Index++;
+        }
+      }
+      if (Index + 1 < Argc) {
+        // Get Filename
+        if (Argv[Index + 1][0] != L'-') {
+          ProgramInfo->DumpRawFileName = Argv[Index + 1];
+          Index++;
+          // Read in file
+          ProgramInfo->DumpRawFile = NULL;
+          EfiStatus = ReadFileData (ProgramInfo->DumpRawFileName, &ProgramInfo->DumpRawFile, &ProgramInfo->DumpRawFileSize);
+          if (EFI_ERROR (EfiStatus)) {
+            Print (L"ERROR: [#%d] Failed to read image file (%r)!\n", __LINE__, EfiStatus);
+          }
+        }
+      }
+    } else
+
+    // Check for Dump human option
+    if ((StrCmp (Argv[Index], L"-dh") == 0) || (StrCmp (Argv[Index], L"--dumphuman") == 0)) {
+      // Dump human option detected
+      ProgramInfo->DumpHumanFlag = TRUE;
+      if (Index + 1 < Argc) {
+        // Get Library Index
+        if (Argv[Index + 1][0] != L'-') {
+          ProgramInfo->DumpHumanLibraryIndex = (UINT8) (GetHexOrDecFromString (Argv[Index + 1]) & 0xFF);
+          Index++;
+        }
+      }
+      if (Index + 1 < Argc) {
+        // Get Filename
+        if (Argv[Index + 1][0] != L'-') {
+          ProgramInfo->DumpHumanFileName = Argv[Index + 1];
+          Index++;
+          // Read in file
+          ProgramInfo->DumpHumanFile = NULL;
+          EfiStatus = ReadFileData (ProgramInfo->DumpHumanFileName, &ProgramInfo->DumpHumanFile, &ProgramInfo->DumpHumanFileSize);
+          if (EFI_ERROR (EfiStatus)) {
+            Print (L"ERROR: [#%d] Failed to read image file (%r)!\n", __LINE__, EfiStatus);
+          }
+        }
+      }
+    } else
+
+    // Check for erase option
+    if ((StrCmp (Argv[Index], L"-e") == 0) || (StrCmp (Argv[Index], L"--erase") == 0)) {
+      // Check security option detected
+      ProgramInfo->EraseFlag = TRUE;
+      if (Index + 1 < Argc) {
+        // Get Library Index
+        if (Argv[Index + 1][0] != L'-') {
+          ProgramInfo->EraseLibraryIndex = (UINT8) (GetHexOrDecFromString (Argv[Index + 1]) & 0xFF);
+          Index++;
+        }
+      }
+    } else
+
+    // Check for Read option
+    if ((StrCmp (Argv[Index], L"-r") == 0) || (StrCmp (Argv[Index], L"--read") == 0)) {
+      // Read option detected
+      ProgramInfo->ReadFlag = TRUE;
+      if (Index + 1 < Argc) {
+        // Get Library Index
+        if (Argv[Index + 1][0] != L'-') {
+          ProgramInfo->ReadLibraryIndex = (UINT8) (GetHexOrDecFromString (Argv[Index + 1]) & 0xFF);
+          Index++;
+        }
+      }
+      if (Index + 1 < Argc) {
+        // Get Filename
+        if (Argv[Index + 1][0] != L'-') {
+          ProgramInfo->ReadFileName = Argv[Index + 1];
+          Index++;
+        }
+      }
+    } else
+
+    // Check for Scan option
+    if ((StrCmp (Argv[Index], L"-s") == 0) || (StrCmp (Argv[Index], L"--scan") == 0)) {
+      // Scan option detected
+      ProgramInfo->ScanFlag = TRUE;
+    } else
+
+    // Check for Verbose option
+    if ((StrCmp (Argv[Index], L"--verbose") == 0)) {
+      // Verbose option detected
+      ProgramInfo->VerboseFlag = TRUE;
+    } else
+
+    // Check for Verify option
+    if ((StrCmp (Argv[Index], L"-v") == 0) || (StrCmp (Argv[Index], L"--verify") == 0)) {
+      // Verify option detected
+      ProgramInfo->VerifyFlag = TRUE;
+      if (Index + 1 < Argc) {
+        // Get Library Index
+        if (Argv[Index + 1][0] != L'-') {
+          ProgramInfo->VerifyLibraryIndex = (UINT8) (GetHexOrDecFromString (Argv[Index + 1]) & 0xFF);
+          Index++;
+        }
+      }
+      if (Index + 1 < Argc) {
+        // Get Filename
+        if (Argv[Index + 1][0] != L'-') {
+          ProgramInfo->VerifyFileName = Argv[Index + 1];
+          Index++;
+          // Read in file
+          ProgramInfo->VerifyFile = NULL;
+          EfiStatus = ReadFileData (ProgramInfo->VerifyFileName, &ProgramInfo->VerifyFile, &ProgramInfo->VerifyFileSize);
+          if (EFI_ERROR (EfiStatus)) {
+            Print (L"ERROR: [#%d] Failed to read image file (%r)!\n", __LINE__, EfiStatus);
+          }
+        }
+      }
+    } else
+
+    // Check for Write option
+    if ((StrCmp (Argv[Index], L"-w") == 0) || (StrCmp (Argv[Index], L"--write") == 0)) {
+      // Write option detected
+      ProgramInfo->WriteFlag = TRUE;
+      if (Index + 1 < Argc) {
+        // Get Library Index
+        if (Argv[Index + 1][0] != L'-') {
+          ProgramInfo->WriteLibraryIndex = (UINT8) (GetHexOrDecFromString (Argv[Index + 1]) & 0xFF);
+          Index++;
+        }
+      }
+      if (Index + 1 < Argc) {
+        // Get Filename
+        if (Argv[Index + 1][0] != L'-') {
+          ProgramInfo->WriteFileName = Argv[Index + 1];
+          Index++;
+          // Read in file
+          ProgramInfo->WriteFile = NULL;
+          EfiStatus = ReadFileData (ProgramInfo->WriteFileName, &ProgramInfo->WriteFile, &ProgramInfo->WriteFileSize);
+          if (EFI_ERROR (EfiStatus)) {
+            Print (L"ERROR: [#%d] Failed to read image file (%r)!\n", __LINE__, EfiStatus);
+          }
+        }
+      }
+    } else
+
+    // All that's left is Unknown
+    {
+      // Unkown option
+      Print (L"Unknown! - Argv[%d]: \"%s\"\n", Index, Argv[Index]);
+    }
+  }
+
+Exit:
+  return;
+}
+
+VOID
+PrintChar (
+  IN UINT8    Count,
+  IN CHAR16   *Char
+)
+{
+  UINTN Index;
+
+  // Check for invalid conditions
+  if (Char == NULL) {
+    Print (L"ERROR: [#%d] Internal coding error!\n", __LINE__);
+    goto Exit;
+  }
+
+  for (Index = 0; Index < Count; Index++) {
+    Print (L"%s", Char);
+  }
+
+Exit:
+  return;
+}
+
+VOID
+PrintHelp (VOID)
+{
+  Print (L" EepromApp.efi is a tool to read/write/dump the EERPOM data.\n");
+  Print (L"\n");
+  Print (L" Switches:\n");
+  Print (L" -a  #            Sets the I2C slave address (7-bit).\n");
+  Print (L" -b  #            Sets the I2C bus number.\n");
+  Print (L" -c  # filename   Check security of the image.\n");
+  Print (L" -d  # filename   Dumps the image in raw format.\n");
+  Print (L" -dh # filename   Dumps the image in human readable format.\n");
+  Print (L" -e  #            Erase that image.\n");
+  Print (L" -h               Dumps this help info.\n");
+  Print (L" -r  # filename   Reads the image from the library index into the file.\n");
+  Print (L"                  - This reads the entire EEPROM part, not just the image.\n");
+  Print (L" -s               Scans all of the buses looking for images.\n");
+  Print (L" -v  # filename   Verifies the image in library index with the file.\n");
+  Print (L" --verbose        Turns on verbosity.\n");
+  Print (L" -w  # filename   Writes the image from the file to the library index.\n");
+  Print (L"\n");
+  Print (L" Library:\n");
+  Print (L"  0 - Null library\n");
+  Print (L"  1 - EEPROM library\n");
+  Print (L"  2 - FV library\n");
+  Print (L"  3 - Memory library\n");
+  Print (L"\n");
+  Print (L" Examples:\n");
+  Print (L"   EepromApp.efi -b  6 -a 0x53 -d 1            - Dump the EEPROM image in raw\n");
+  Print (L"                                                 format from I2C #6, 0x53.\n");
+  Print (L"   EepromApp.efi -r  3 Test.bin                - Write the memory image to\n");
+  Print (L"                                                 Test.bin.\n");
+  Print (L"   EepromApp.efi -s -w  1 Test.bin             - Write Test.bin to the EERPOM\n");
+  Print (L"                                                 last found during the scan.\n");
+  Print (L"   EepromApp.efi -b  4 -a 0x5F -w 1 Test.bin   - Write Test.bin to the EERPOM\n");
+  Print (L"                                                 on I2C #4, 0x5F.\n");
+  Print (L"   EepromApp.efi -dh 0 Test.bin                - Dump Test.bin in human\n");
+  Print (L"                                                 readable form.\n");
+  Print (L"   EepromApp.efi -s -c 1                       - Scan the EEPROM buses for\n");
+  Print (L"                                                 images and check the security\n");
+  Print (L"                                                 of the last one found.\n");
+  Print (L"\n");
+}
+
+//
+// Read data from file
+//
+EFI_STATUS
+ReadFileData (
+  IN  CHAR16    *FileName,
+  OUT UINT8    **Buffer,
+  OUT UINT32    *BufferSize
+  )
+{
+  EFI_STATUS             Status;
+  SHELL_FILE_HANDLE      FileHandle;
+  UINT64                 Size;
+  VOID                   *NewBuffer;
+  UINTN                  ReadSize;
+
+  if (gDebugFlag) Print (L"%a(#%d) - Starting...\n", __FUNCTION__, __LINE__);
+
+  //
+  // Initialize variables
+  //
+  FileHandle = NULL;
+  NewBuffer  = NULL;
+  Size       = 0;
+
+  //
+  // Sanity checks
+  //
+  if (FileName == NULL) {
+    if (gDebugFlag) Print (L"ERROR: [#%d] FileName not set!\n", __LINE__);
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  if (Buffer == NULL) {
+    if (gDebugFlag) Print (L"ERROR: [#%d] Buffer pointer is NULL!\n", __LINE__);
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  if (*Buffer != NULL) {
+    if (gDebugFlag) Print (L"ERROR: [#%d] *Buffer pointer is not NULL!\n", __LINE__);
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+
+  //
+  // Open file
+  //
+  Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ, 0);
+  if (EFI_ERROR (Status)) {
+    Print (L"ERROR: [#%d] Failed to open file %s (%r)\n", __LINE__, FileName, Status);
+    goto Exit;
+  }
+
+  //
+  // Sanity check to make sure it isn't a directory
+  //
+  Status = FileHandleIsDirectory (FileHandle);
+  if (!EFI_ERROR (Status)) {
+    Print (L"ERROR: [#%d] Failed to determine if %s was a directory (%r)\n", __LINE__, FileName, Status);
+    Status = EFI_NOT_FOUND;
+    goto Exit;
+  }
+
+  //
+  // Get file size
+  //
+  Status = FileHandleGetSize (FileHandle, &Size);
+  if (EFI_ERROR (Status)) {
+    Print (L"ERROR: [#%d] Failed to get size of %s (%r)\n", __LINE__, FileName, Status);
+    goto Exit;
+  }
+
+  //
+  // Allocate buffer
+  //
+  NewBuffer = AllocatePool ((UINTN) Size);
+
+  //
+  // Read in file
+  //
+  ReadSize = (UINTN) Size;
+  Status = FileHandleRead (FileHandle, &ReadSize, NewBuffer);
+  if (EFI_ERROR (Status)) {
+    Print (L"ERROR: [#%d] Failed to read %s (%r)\n", __LINE__, FileName, Status);
+    goto Exit;
+  } else if (ReadSize != (UINTN) Size) {
+    Print (L"ERROR: [#%d] Failed to read the right number of bytes. Should have been %08x and read %08x\n", __LINE__, Size, ReadSize);
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+
+Exit:
+  //
+  // Free resources
+  //
+  if (FileHandle != NULL) {
+    ShellCloseFile (&FileHandle);
+  }
+
+  //
+  // Set output contents
+  //
+  if (!EFI_ERROR (Status)) {
+    *BufferSize = (UINT32) Size;
+    *Buffer     = NewBuffer;
+  } else {
+    *BufferSize = 0;
+    *Buffer     = NULL;
+  }
+
+  return Status;
+}
+
+SHELL_STATUS
+ReadOption (
+  IN PROGRAM_INFO    *ProgramInfo
+  )
+{
+  EEPROM_FUNCTION_INFO    EepromInfo;
+  EFI_STATUS              EfiStatus;
+  VOID                   *FunctionInfo;
+  SHELL_STATUS            Status;
+
+  if (gDebugFlag) Print (L"%a(#%d) - Starting...\n", __FUNCTION__, __LINE__);
+
+  //
+  // Initialize variables
+  //
+  ZeroMem (&EepromInfo, sizeof (EEPROM_FUNCTION_INFO));
+  EepromInfo.Bus          = ProgramInfo->BusValue;
+  EepromInfo.Address      = ProgramInfo->AddressValue;
+  EepromInfo.LibraryIndex = EEPROM_EEPROM;
+  FunctionInfo            = NULL;
+  Status                  = SHELL_SUCCESS;
+
+  //
+  // Sanity checks
+  //
+  if (ProgramInfo == NULL) {
+    if (gDebugFlag) Print (L"ERROR: [#%d] Internal coding error!\n", __LINE__);
+    Status = SHELL_INVALID_PARAMETER;
+    goto Exit;
+  }
+
+  //
+  // Find out the size of the image
+  //
+  Print (L"  - Reading %a to %s", mEepromLibraryString[ProgramInfo->ReadLibraryIndex], ProgramInfo->ReadFileName);
+  if (ProgramInfo->ReadLibraryIndex == EEPROM_EEPROM) {
+    Print (L" via bus #%d @ 0x%02x", ProgramInfo->BusValue, ProgramInfo->AddressValue);
+    FunctionInfo = (VOID *) &EepromInfo;
+  }
+  Print (L"...\n");
+  ProgramInfo->ReadFileSize = GetImageSize (ProgramInfo->ReadLibraryIndex);
+  ProgramInfo->ReadFile     = AllocateZeroPool (ProgramInfo->ReadFileSize);
+  if (ProgramInfo->ReadFile == NULL) {
+    Print (L"ERROR: [#%d] Failed to allocate buffer!\n", __LINE__);
+    Status = SHELL_OUT_OF_RESOURCES;
+    goto Exit;
+  }
+
+  //
+  // Fill buffer from library
+  //
+  EfiStatus = ReadEeprom (ProgramInfo->ReadLibraryIndex, 0, &ProgramInfo->ReadFileSize, ProgramInfo->ReadFile, FunctionInfo);
+  if (EFI_ERROR (EfiStatus)) {
+    Print (L"ERROR: [#%d] Failed to read image file (%r)!\n", __LINE__, EfiStatus);
+    Status = SHELL_DEVICE_ERROR;
+    goto Exit;
+  }
+
+  //
+  // Write out the image file
+  //
+  EfiStatus = WriteFileData (ProgramInfo->ReadFileName, ProgramInfo->ReadFile, ProgramInfo->ReadFileSize);
+  if (EFI_ERROR (EfiStatus)) {
+    Print (L"ERROR: [#%d] Failed to write image file (%r)!\n", __LINE__, EfiStatus);
+    Status = SHELL_DEVICE_ERROR;
+    goto Exit;
+  }
+
+  Print (L"  - Image %a written to %s\n", mEepromLibraryString[ProgramInfo->ReadLibraryIndex], ProgramInfo->ReadFileName);
+
+Exit:
+  //
+  // Free resources
+  //
+  return Status;
+}
+
+SHELL_STATUS
+ScanOption (
+  IN PROGRAM_INFO    *ProgramInfo
+  )
+{
+  UINT8                   Buffer[2];
+  UINT8                   Bus;
+  EEPROM_FUNCTION_INFO    EepromInfo;
+  EFI_STATUS              EfiStatus;
+  UINT8                   index;
+  UINT8                   ScanSize;
+  UINT32                  Size;
+  SHELL_STATUS            Status;
+
+  if (gDebugFlag) Print (L"%a(#%d) - Starting...\n", __FUNCTION__, __LINE__);
+
+  //
+  // Initialize variables
+  //
+  ZeroMem (&EepromInfo, sizeof (EEPROM_FUNCTION_INFO));
+  EepromInfo.LibraryIndex = EEPROM_EEPROM;
+  ScanSize                = 0;
+  Size                    = 0;
+  Status                  = SHELL_NOT_FOUND;
+
+  //
+  // Loop thru I2C buses for images
+  //
+  EepromInfo.ScanSize = &ScanSize;
+  for (Bus = 0; Bus < 8; Bus++) {
+    if (gDebugFlag) Print (L" - Scanning bus #%d\n", Bus);
+    EepromInfo.Bus = Bus;
+    ScanSize       = 0;
+    EfiStatus = ReadEeprom (EEPROM_EEPROM, 0, &Size, Buffer, &EepromInfo);
+    if (!EFI_ERROR (EfiStatus)) {
+      //
+      // Dump any images found
+      //
+      Status = SHELL_SUCCESS;
+      for (index = 0; index < ScanSize; index++) {
+        Print (L"  - Found image on I2C bus #%d, address 0x%02x\n", Bus, EepromInfo.ScanBuffer[index]);
+        ProgramInfo->BusFlag      = TRUE;
+        ProgramInfo->BusValue     = Bus;
+        ProgramInfo->AddressFlag  = TRUE;
+        ProgramInfo->AddressValue = EepromInfo.ScanBuffer[index];
+      }
+    }
+  }
+
+  //
+  // Free resources
+  //
+  if (EepromInfo.ScanBuffer != NULL) {
+    FreePool (EepromInfo.ScanBuffer);
+    EepromInfo.ScanBuffer = NULL;
+  }
+
+  return Status;
+}
+
+/**
+  Convert a null-terminated unicode string, in-place, to all lowercase.
+  Then return it.
+
+  @param  Str    The null-terminated string to be converted to all lowercase.
+
+  @return        The null-terminated string converted into all lowercase.
+**/
+CHAR16 *
+ToLower (
+  IN OUT  CHAR16 *Str
+  )
+{
+  UINTN Index;
+
+  // Check for invalid conditions
+  if (Str == NULL) {
+    if (gDebugFlag) Print (L"ERROR: [#%d] Internal coding error!\n", __LINE__);
+    goto Exit;
+  }
+
+  for (Index = 0; Str[Index] != L'\0'; Index++) {
+    if ((Str[Index] >= L'A') && (Str[Index] <= L'Z')) {
+      Str[Index] -= (CHAR16)(L'A' - L'a');
+    }
+  }
+
+Exit:
+  return Str;
+}
+
+SHELL_STATUS
+VerifyOption (
+  IN PROGRAM_INFO    *ProgramInfo
+  )
+{
+  EEPROM_FUNCTION_INFO    EepromInfo;
+  EFI_STATUS              EfiStatus;
+  VOID                   *FunctionInfo;
+  UINT8                  *ImageBuffer;
+  UINT32                  ImageSize;
+  UINT32                  index;
+  SHELL_STATUS            Status;
+
+  if (gDebugFlag) Print (L"%a(#%d) - Starting...\n", __FUNCTION__, __LINE__);
+
+  //
+  // Initialize variables
+  //
+  ZeroMem (&EepromInfo, sizeof (EEPROM_FUNCTION_INFO));
+  EepromInfo.Bus          = ProgramInfo->BusValue;
+  EepromInfo.Address      = ProgramInfo->AddressValue;
+  EepromInfo.LibraryIndex = EEPROM_EEPROM;
+  FunctionInfo            = NULL;
+  ImageBuffer             = NULL;
+  Status                  = SHELL_SUCCESS;
+
+  //
+  // Sanity checks
+  //
+  if (ProgramInfo == NULL) {
+    if (gDebugFlag) Print (L"ERROR: [#%d] Internal coding error!\n", __LINE__);
+    Status = SHELL_INVALID_PARAMETER;
+    goto Exit;
+  }
+  if ((ProgramInfo->VerifyFile == NULL) || (ProgramInfo->VerifyFileSize == 0)) {
+    if (gDebugFlag) Print (L"ERROR: [#%d] Image file is empty!\n", __LINE__);
+    Status = SHELL_INVALID_PARAMETER;
+    goto Exit;
+  }
+
+  //
+  // Find out the size of the image
+  //
+  Print (L"  - Comparing %s to %a", ProgramInfo->VerifyFileName, mEepromLibraryString[ProgramInfo->VerifyLibraryIndex]);
+  if (ProgramInfo->VerifyLibraryIndex == EEPROM_EEPROM) {
+    Print (L" via bus #%d @ 0x%02x", ProgramInfo->BusValue, ProgramInfo->AddressValue);
+    FunctionInfo = (VOID *) &EepromInfo;
+  }
+  Print (L"...\n");
+  ImageSize   = GetImageSize (ProgramInfo->VerifyLibraryIndex);
+  ImageBuffer = AllocateZeroPool (ImageSize);
+  if (ImageBuffer == NULL) {
+    Print (L"ERROR: [#%d] Failed to allocate buffer!\n", __LINE__);
+    Status = SHELL_OUT_OF_RESOURCES;
+    goto Exit;
+  }
+
+  //
+  // Read in the memory image
+  //
+  EfiStatus = ReadEeprom (ProgramInfo->VerifyLibraryIndex, 0, &ImageSize, ImageBuffer, FunctionInfo);
+  if (EFI_ERROR (EfiStatus)) {
+    Print (L"ERROR: [#%d] Failed to read image file (%r)!\n", __LINE__, EfiStatus);
+    Status = SHELL_DEVICE_ERROR;
+    goto Exit;
+  }
+
+  //
+  // Compare images
+  //
+  if ((ImageSize != ProgramInfo->VerifyFileSize) && (ProgramInfo->VerifyLibraryIndex != EEPROM_EEPROM)) {
+    Print (L"ERROR: [#%d] Image size does not match file size!\n", __LINE__);
+    Status = SHELL_DEVICE_ERROR;
+    goto Exit;
+  }
+  for (index = 0; index < ImageSize; index++) {
+    if (ProgramInfo->VerifyFile[index] != ImageBuffer[index]) {
+      if (((index + 1) > ProgramInfo->VerifyFileSize) && (ProgramInfo->VerifyLibraryIndex == EEPROM_EEPROM)) {
+        //
+        // Getting image size from ReadEeprom with a size of 0 for EEPROM_EEPROM will return the size of the part, not the image.
+        //
+        break;
+      } else {
+        Print (L"ERROR: [#%d] Failed to verify file & image @ %08x [%02x:%02x]\n", __LINE__, index, ProgramInfo->VerifyFile[index], ImageBuffer[index]);
+        Status = SHELL_DEVICE_ERROR;
+        goto Exit;
+      }
+    }
+  }
+  Print (L"  - Image %s compared to %a successfully\n", ProgramInfo->VerifyFileName, mEepromLibraryString[ProgramInfo->VerifyLibraryIndex]);
+
+Exit:
+  //
+  // Free resources
+  //
+  if (ImageBuffer != NULL) {
+    FreePool (ImageBuffer);
+    ImageBuffer = NULL;
+  }
+  return Status;
+}
+
+EFI_STATUS
+WriteFileData (
+  IN  CHAR16   *FileName,
+  IN  UINT8    *Buffer,
+  IN  UINTN     BufferSize
+  )
+{
+  SHELL_FILE_HANDLE               FileHandle;
+  EFI_STATUS                      Status;
+
+  if (gDebugFlag) Print (L"%a(#%d) - Starting...\n", __FUNCTION__, __LINE__);
+
+  //
+  // Sanity checks
+  //
+  if (FileName == NULL) {
+    if (gDebugFlag) Print (L"ERROR: [#%d] FileName not set!\n", __LINE__);
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  if (Buffer == NULL) {
+    if (gDebugFlag) Print (L"ERROR: [#%d] Buffer pointer is NULL!\n", __LINE__);
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+
+  //
+  // Is the requested file a directory?
+  //
+  if (ShellIsDirectory (FileName) == EFI_SUCCESS) {
+    Print (L"ERROR: [#%d] File is a directory! Can not be saved.\n", __LINE__);
+    Status = EFI_LOAD_ERROR;
+    goto Exit;
+  }
+
+  //
+  // If file exists, delete it
+  //
+  Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE, 0);
+  if (!EFI_ERROR (Status)) {
+    //
+    // the file exits, delete it
+    //
+    Status = ShellDeleteFile (&FileHandle);
+    if (EFI_ERROR (Status) || Status == EFI_WARN_DELETE_FAILURE) {
+      Print (L"ERROR: [#%d] Deleteing existing file failed!\n", __LINE__);
+      Status = EFI_LOAD_ERROR;
+      goto Exit;
+    }
+  }
+
+  //
+  // Create file
+  //
+  Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, 0);
+  if (EFI_ERROR (Status)) {
+    Print (L"ERROR: [#%d] Creating file failed!\n", __LINE__);
+    Status = EFI_LOAD_ERROR;
+    goto Exit;
+  }
+
+  //
+  // Write buffer to file
+  //
+  Status = ShellWriteFile (FileHandle, &BufferSize, Buffer);
+  if (EFI_ERROR (Status)) {
+    ShellDeleteFile (&FileHandle);
+    Status = EFI_LOAD_ERROR;
+    goto Exit;
+  }
+
+  Status = EFI_SUCCESS;
+
+Exit:
+  //
+  // Free resources
+  //
+  if (FileHandle != NULL) {
+    ShellCloseFile (&FileHandle);
+  }
+
+  return Status;
+}
+
+SHELL_STATUS
+WriteOption (
+  IN PROGRAM_INFO    *ProgramInfo
+  )
+{
+  EEPROM_FUNCTION_INFO    EepromInfo;
+  EFI_STATUS              EfiStatus;
+  VOID                   *FunctionInfo;
+  SHELL_STATUS            Status;
+
+  if (gDebugFlag) Print (L"%a(#%d) - Starting...\n", __FUNCTION__, __LINE__);
+
+  //
+  // Initialize variables
+  //
+  ZeroMem (&EepromInfo, sizeof (EEPROM_FUNCTION_INFO));
+  EepromInfo.Bus          = ProgramInfo->BusValue;
+  EepromInfo.Address      = ProgramInfo->AddressValue;
+  EepromInfo.LibraryIndex = EEPROM_EEPROM;
+  FunctionInfo            = NULL;
+  Status                  = SHELL_SUCCESS;
+
+  //
+  // Sanity checks
+  //
+  if (ProgramInfo == NULL) {
+    if (gDebugFlag) Print (L"ERROR: [#%d] Internal coding error!\n", __LINE__);
+    Status = SHELL_INVALID_PARAMETER;
+    goto Exit;
+  }
+  if ((ProgramInfo->WriteFile == NULL) || (ProgramInfo->WriteFileSize == 0)) {
+    if (gDebugFlag) Print (L"ERROR: [#%d] Image file is empty!\n", __LINE__);
+    Status = SHELL_INVALID_PARAMETER;
+    goto Exit;
+  }
+
+  //
+  // Write image out
+  //
+  Print (L"  - Writing %s to %a", ProgramInfo->WriteFileName, mEepromLibraryString[ProgramInfo->WriteLibraryIndex]);
+  if (ProgramInfo->WriteLibraryIndex == EEPROM_EEPROM) {
+    Print (L" via bus #%d @ 0x%02x", ProgramInfo->BusValue, ProgramInfo->AddressValue);
+    FunctionInfo = (VOID *) &EepromInfo;
+  }
+  Print (L"...\n");
+  EfiStatus = WriteEeprom (ProgramInfo->WriteLibraryIndex, 0, &ProgramInfo->WriteFileSize, ProgramInfo->WriteFile, FunctionInfo);
+  if (EFI_ERROR (EfiStatus)) {
+    Print (L"ERROR: [#%d] Failed to write image file (%r)!\n", __LINE__, EfiStatus);
+    Status = SHELL_DEVICE_ERROR;
+    goto Exit;
+  }
+  Print (L"  - Image %s written to %a\n", ProgramInfo->WriteFileName, mEepromLibraryString[ProgramInfo->WriteLibraryIndex]);
+
+  //
+  // Validate image
+  //
+  Print (L"  - Validating image...\n");
+  EfiStatus = ValidateEeprom (ProgramInfo->WriteLibraryIndex);
+  Print (L"  - Image validation status = %r\n", EfiStatus);
+
+Exit:
+  return Status;
+}
+
diff --git a/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromApp/EepromApp.h b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromApp/EepromApp.h
new file mode 100644
index 0000000000..7babb6555e
--- /dev/null
+++ b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromApp/EepromApp.h
@@ -0,0 +1,196 @@
+/** @file
+
+  This application will read/write/verify/dump the EERPOM data.
+
+  Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.<BR>
+
+  This program and the accompanying materials are licensed and made available under
+  the terms and conditions of the BSD License which accompanies this distribution.
+  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+
+**/
+
+#ifndef _EEPROM_APP_H_
+#define _EEPROM_APP_H_
+
+#include <Uefi.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/EepromDataLib.h>
+#include <Library/EepromLib.h>
+#include <Library/FileHandleLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PrintLib.h>
+#include <Library/ShellCEntryLib.h>
+#include <Library/ShellLib.h>
+#include <Library/TimerLib.h>
+#include <Library/UefiLib.h>
+
+// Defines
+#define   APP_VERSION          L"1.00.00"
+#define   APP_COPYRIGHT        L"2017 - 2018"
+#define   DIVIDING_LINE        L"+----------------------------------------------------+------------------+\n"
+
+#define   MD5DigestSize        0x10
+#define   SHA1DigestSize       0x14
+#define   SHA256DigestSize     0x20
+#define   SHA384DigestSize     0x30
+#define   SHA512DigestSize     0x40
+
+// Structures
+typedef struct {
+  BOOLEAN    HelpFlag;
+  BOOLEAN    AddressFlag;
+  UINT8      AddressValue;
+  BOOLEAN    BusFlag;
+  UINT8      BusValue;
+  BOOLEAN    CheckFlag;
+  UINT8      CheckLibraryIndex;
+  UINT8     *CheckFile;
+  CHAR16    *CheckFileName;
+  UINT32     CheckFileSize;
+  BOOLEAN    DumpHumanFlag;
+  UINT8      DumpHumanLibraryIndex;
+  UINT8     *DumpHumanFile;
+  CHAR16    *DumpHumanFileName;
+  UINT32     DumpHumanFileSize;
+  BOOLEAN    DumpRawFlag;
+  UINT8      DumpRawLibraryIndex;
+  UINT8     *DumpRawFile;
+  CHAR16    *DumpRawFileName;
+  UINT32     DumpRawFileSize;
+  BOOLEAN    EraseFlag;
+  UINT8      EraseLibraryIndex;
+  BOOLEAN    ReadFlag;
+  UINT8      ReadLibraryIndex;
+  UINT8     *ReadFile;
+  CHAR16    *ReadFileName;
+  UINT32     ReadFileSize;
+  BOOLEAN    ScanFlag;
+  BOOLEAN    VerboseFlag;
+  BOOLEAN    VerifyFlag;
+  UINT8      VerifyLibraryIndex;
+  UINT8     *VerifyFile;
+  CHAR16    *VerifyFileName;
+  UINT32     VerifyFileSize;
+  BOOLEAN    WriteFlag;
+  UINT8      WriteLibraryIndex;
+  UINT8     *WriteFile;
+  CHAR16    *WriteFileName;
+  UINT32     WriteFileSize;
+} PROGRAM_INFO;
+
+// Headers
+SHELL_STATUS
+BufferToMemory (
+  IN  UINT8     *Buffer,
+  IN  UINT32     BufferSize,
+  OUT UINT8    **MemoryBuffer,
+  OUT UINT32    *MemoryBufferSize
+  );
+
+SHELL_STATUS
+CheckForInvalidOptions (
+  IN PROGRAM_INFO    *ProgramInfo
+  );
+
+SHELL_STATUS
+CheckOption (
+  IN PROGRAM_INFO    *ProgramInfo
+  );
+
+SHELL_STATUS
+DumpHumanOption (
+  IN PROGRAM_INFO    *ProgramInfo
+  );
+
+VOID
+DumpParagraph (
+  IN   VOID   *Ptr,
+  IN   UINTN   Count
+  );
+
+VOID
+DumpProgramInfo (
+  IN PROGRAM_INFO    *ProgramInfo
+  );
+
+SHELL_STATUS
+DumpRawOption (
+  IN PROGRAM_INFO    *ProgramInfo
+  );
+
+SHELL_STATUS
+EraseOption (
+  IN PROGRAM_INFO    *ProgramInfo
+  );
+
+UINTN
+GetHexOrDecFromString (
+  CHAR16 *Arg
+  );
+
+VOID
+ParseParameters (
+  IN UINTN            Argc,
+  IN CHAR16         **Argv,
+  IN PROGRAM_INFO    *ProgramInfo
+  );
+
+VOID
+PrintChar (
+  IN UINT8    Count,
+  IN CHAR16   *Char
+);
+
+VOID
+PrintHelp (VOID);
+
+EFI_STATUS
+ReadFileData (
+  IN  CHAR16    *FileName,
+  OUT UINT8    **Buffer,
+  OUT UINT32    *BufferSize
+  );
+
+SHELL_STATUS
+ReadOption (
+  IN PROGRAM_INFO    *ProgramInfo
+  );
+
+SHELL_STATUS
+ScanOption (
+  IN PROGRAM_INFO    *ProgramInfo
+  );
+
+CHAR16 *
+ToLower (
+  IN OUT  CHAR16 *Str
+  );
+
+SHELL_STATUS
+VerifyOption (
+  IN PROGRAM_INFO    *ProgramInfo
+  );
+
+EFI_STATUS
+WriteFileData (
+  IN  CHAR16   *FileName,
+  IN  UINT8    *Buffer,
+  IN  UINTN     BufferSize
+  );
+
+SHELL_STATUS
+WriteOption (
+  IN PROGRAM_INFO    *ProgramInfo
+  );
+
+#endif  // _EEPROM_APP_H_
\ No newline at end of file
diff --git a/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromApp/EepromApp.inf b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromApp/EepromApp.inf
new file mode 100644
index 0000000000..a13974891b
--- /dev/null
+++ b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromApp/EepromApp.inf
@@ -0,0 +1,62 @@
+## @file
+#
+#  This application will read/write/verify/dump the EERPOM data.
+#
+#  Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution. The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = EepromApp
+  FILE_GUID                      = 84CF6CBE-EEDC-4219-9CAB-9510B8D9834F
+  MODULE_TYPE                    = UEFI_APPLICATION
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = ShellCEntryLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC
+#
+
+[Sources]
+  EepromApp.c
+  EepromApp.h
+
+[Packages]
+  MdePkg/MdePkg.dec
+  ShellPkg/ShellPkg.dec
+  BroxtonPlatformPkg/PlatformPkg.dec
+  BroxtonSiPkg/BroxtonSiPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  DebugLib
+  EepromDataLib
+  EepromLib
+  FileHandleLib
+  MemoryAllocationLib
+  PcdLib
+  PrintLib
+  ShellCEntryLib
+  ShellLib
+  TimerLib
+  UefiApplicationEntryPoint
+  UefiLib
+
+[Guids]
+
+[Protocols]
+
+[Pcd]
+
-- 
2.14.1.windows.1



^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [Patch][edk2-platforms/devel-IntelAtomProcessorE3900 3/5] Library producing EEPROM raw data functionality.
  2018-07-23  2:39 [Patch][edk2-platforms/devel-IntelAtomProcessorE3900 1/5] Add EepromApp zwei4
@ 2018-07-23  2:39 ` zwei4
  2018-07-23  2:39 ` [Patch][edk2-platforms/devel-IntelAtomProcessorE3900 4/5] Common EEPROM library instance zwei4
  2018-07-23  2:39 ` [Patch][edk2-platforms/devel-IntelAtomProcessorE3900 5/5] EEPROM header files zwei4
  2 siblings, 0 replies; 4+ messages in thread
From: zwei4 @ 2018-07-23  2:39 UTC (permalink / raw)
  To: edk2-devel; +Cc: David Wei, Kelly Steele, Mike Wu, Mang Guo

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: David Wei <david.wei@intel.com>
CC: Kelly Steele <kelly.steele@intel.com>
CC: Mike Wu  <mike.wu@intel.com>
CC: Mang Guo <mang.guo@intel.com>
---
 .../EepromDataLib/EEPROM/EepromDataEepromLib.c     | 1628 ++++++++++++++++++++
 .../EepromDataLib/EEPROM/EepromDataEepromLib.h     |  213 +++
 .../Features/Eeprom/EepromDataLib/EEPROM/HobData.c |  142 ++
 .../Eeprom/EepromDataLib/EEPROM/HobDataPei.c       |  123 ++
 .../Features/Eeprom/EepromDataLib/EEPROM/I2cLib.c  | 1164 ++++++++++++++
 .../Features/Eeprom/EepromDataLib/EEPROM/I2cLib.h  |  181 +++
 .../Features/Eeprom/EepromDataLib/EepromDataLib.c  |  216 +++
 .../Features/Eeprom/EepromDataLib/EepromDataLib.h  |  290 ++++
 .../Eeprom/EepromDataLib/EepromDataLib.inf         |   80 +
 .../Eeprom/EepromDataLib/EepromDataNullLib.inf     |   40 +
 .../Eeprom/EepromDataLib/EepromDataPeiLib.inf      |   75 +
 .../Eeprom/EepromDataLib/FV/EepromDataFvLib.c      |  172 +++
 .../Eeprom/EepromDataLib/FV/EepromDataFvLib.h      |   32 +
 .../Features/Eeprom/EepromDataLib/FV/GetImage.c    |  114 ++
 .../Features/Eeprom/EepromDataLib/FV/GetImagePei.c |  113 ++
 .../EepromDataLib/Memory/EepromDataMemoryLib.c     |  242 +++
 .../EepromDataLib/Memory/EepromDataMemoryLib.h     |   58 +
 .../Features/Eeprom/EepromDataLib/Memory/HobData.c |  142 ++
 .../Eeprom/EepromDataLib/Memory/HobDataPei.c       |  123 ++
 .../Eeprom/EepromDataLib/MemoryAllocation.c        |   67 +
 .../Eeprom/EepromDataLib/MemoryAllocationPei.c     |  481 ++++++
 .../Eeprom/EepromDataLib/Null/EepromDataNullLib.c  |   67 +
 .../Eeprom/EepromDataLib/Null/EepromDataNullLib.h  |   24 +
 23 files changed, 5787 insertions(+)
 create mode 100644 Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/EEPROM/EepromDataEepromLib.c
 create mode 100644 Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/EEPROM/EepromDataEepromLib.h
 create mode 100644 Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/EEPROM/HobData.c
 create mode 100644 Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/EEPROM/HobDataPei.c
 create mode 100644 Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/EEPROM/I2cLib.c
 create mode 100644 Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/EEPROM/I2cLib.h
 create mode 100644 Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/EepromDataLib.c
 create mode 100644 Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/EepromDataLib.h
 create mode 100644 Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/EepromDataLib.inf
 create mode 100644 Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/EepromDataNullLib.inf
 create mode 100644 Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/EepromDataPeiLib.inf
 create mode 100644 Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/FV/EepromDataFvLib.c
 create mode 100644 Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/FV/EepromDataFvLib.h
 create mode 100644 Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/FV/GetImage.c
 create mode 100644 Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/FV/GetImagePei.c
 create mode 100644 Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/Memory/EepromDataMemoryLib.c
 create mode 100644 Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/Memory/EepromDataMemoryLib.h
 create mode 100644 Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/Memory/HobData.c
 create mode 100644 Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/Memory/HobDataPei.c
 create mode 100644 Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/MemoryAllocation.c
 create mode 100644 Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/MemoryAllocationPei.c
 create mode 100644 Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/Null/EepromDataNullLib.c
 create mode 100644 Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/Null/EepromDataNullLib.h

diff --git a/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/EEPROM/EepromDataEepromLib.c b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/EEPROM/EepromDataEepromLib.c
new file mode 100644
index 0000000000..6f8e98c38d
--- /dev/null
+++ b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/EEPROM/EepromDataEepromLib.c
@@ -0,0 +1,1628 @@
+/** @file
+  EEPROM raw data library instance.
+
+  Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "EepromDataEepromLib.h"
+
+LIST_ENTRY         *gEepromPartsHeadLink = NULL;
+EEPROM_PART_INFO   *gEepromParts         = NULL;
+
+EFI_STATUS
+EFIAPI
+CreateBlockList (
+  IN       UINT32        Offset,
+  IN       UINT32       *Size,
+  IN       VOID         *FunctionInfo,
+  IN OUT   BLOCK_LIST   *BlockListHead
+  )
+{
+  UINT8                   Address;
+  EEPROM_FUNCTION_INFO   *EepromInfo;
+  BLOCK_LIST             *BlockList;
+  UINT16                  BlockOffset;
+  UINT32                  ReadCount;
+  UINT32                  ReadOffset;
+  EFI_STATUS              Status;
+
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Starting\n", __FUNCTION__, __LINE__));
+
+  //
+  // Initialize variables
+  //
+  EepromInfo = (EEPROM_FUNCTION_INFO *) FunctionInfo;
+  Status     = EFI_SUCCESS;
+
+  //
+  // Sanity checks
+  //
+  if ((Size == NULL) || (FunctionInfo == NULL) || (BlockListHead == NULL)) {
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+
+  //
+  // Debug info
+  //
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Bus = 0x%02x   Address = 0x%02x\n", __FUNCTION__, __LINE__, EepromInfo->Bus, EepromInfo->Address));
+
+  //
+  // Initialize first linked entry
+  //
+  BlockList = EepromAllocatePool (sizeof (BLOCK_LIST));
+  if (BlockList == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Exit;
+  }
+  BlockList->Address   = EepromInfo->Address;
+  BlockList->Signature = BLOCK_LIST_SIGNATURE;
+  BlockList->Size      = 0;
+  ReadCount            = *Size;
+  ReadOffset           = Offset;
+  while (ReadCount > 0) {
+    Address = GetMapAddress (
+                ReadOffset,
+                &BlockOffset,
+                FunctionInfo
+                );
+    if (ReadCount == *Size) {
+      //
+      // Beginning of list search.
+      //
+      BlockList->Offset = BlockOffset;
+    }
+    if (Address == BlockList->Address) {
+      //
+      // Same address range, increment size.
+      //
+      BlockList->Size++;
+    } else if (Address != INVALID_I2C_ADDRESS) {
+      //
+      // Dump this block of info
+      //
+      if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Address = 0x%08x\n", __FUNCTION__, __LINE__, BlockList->Address));
+      if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Offset  = 0x%08x\n", __FUNCTION__, __LINE__, BlockList->Offset));
+      if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Size    = 0x%08x\n", __FUNCTION__, __LINE__, BlockList->Size));
+      //
+      // New address range, create new PageList.
+      //
+      InsertTailList (&BlockListHead->Link, &BlockList->Link);
+      BlockList = EepromAllocatePool (sizeof (BLOCK_LIST));
+      if (BlockList == NULL) {
+        Status = EFI_OUT_OF_RESOURCES;
+        goto Exit;
+      }
+      BlockList->Address   = Address;
+      BlockList->Offset    = BlockOffset;
+      BlockList->Signature = BLOCK_LIST_SIGNATURE;
+      BlockList->Size      = 1;
+    } else if (BlockList->Size == 0) {
+      //
+      // GetMapAddress failed to find an address for this offset
+      //
+      Status = EFI_NO_MAPPING;
+      goto Exit;
+    }
+    //
+    // Decrement read counter
+    //
+    ReadCount--;
+    //
+    // Increment read offset
+    //
+    ReadOffset++;
+  }
+  //
+  // Dump this block of info
+  //
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Address = 0x%08x\n", __FUNCTION__, __LINE__, BlockList->Address));
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Offset  = 0x%08x\n", __FUNCTION__, __LINE__, BlockList->Offset));
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Size    = 0x%08x\n", __FUNCTION__, __LINE__, BlockList->Size));
+  //
+  // Insert last record
+  //
+  InsertTailList (&BlockListHead->Link, &BlockList->Link);
+
+Exit:
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - Ending with %r\n", __FUNCTION__, __LINE__, Status));
+  }
+  return Status;
+}
+
+VOID
+EFIAPI
+DestroyBlockList (
+  IN  BLOCK_LIST  *BlockListHead
+  )
+{
+  BLOCK_LIST    *BlockList;
+  LIST_ENTRY    *Node;
+
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Starting\n", __FUNCTION__, __LINE__));
+
+  //
+  // Sanity checks
+  //
+  if (BlockListHead == NULL) {
+    goto Exit;
+  }
+  if (IsListEmpty (&BlockListHead->Link)) {
+    goto Exit;
+  }
+
+  //
+  // Walk block list and free memory
+  //
+  Node = GetFirstNode (&BlockListHead->Link);
+  do {
+    BlockList = BLOCK_LIST_FROM_THIS (Node);
+    Node      = GetNextNode (&BlockListHead->Link, Node);
+    RemoveEntryList (&BlockList->Link);
+    BlockList = EepromFreePool (BlockList);
+  } while (!IsNull (&BlockListHead->Link, Node));
+
+Exit:
+  //
+  // Free block list head
+  //
+  BlockListHead = EepromFreePool (BlockListHead);
+  return;
+}
+
+VOID
+EFIAPI
+DumpEepromMap (VOID)
+{
+  EEPROM_MAP_INFO    *CurrentEepromMap;
+  EEPROM_PART_INFO   *CurrentEepromParts;
+  LIST_ENTRY         *MapNode;
+  LIST_ENTRY         *PartNode;
+
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Starting\n", __FUNCTION__, __LINE__));
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - gEepromPartsHeadLink = 0x%08x\n", __FUNCTION__, __LINE__, gEepromPartsHeadLink));
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d)   - HeadLink->ForwardLink = 0x%08x\n", __FUNCTION__, __LINE__, gEepromPartsHeadLink->ForwardLink));
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d)   - HeadLink->BackLink    = 0x%08x\n", __FUNCTION__, __LINE__, gEepromPartsHeadLink->BackLink));
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - gEepromParts         = 0x%08x\n", __FUNCTION__, __LINE__, gEepromParts));
+
+  if ((gEepromParts != NULL) && (gEepromPartsHeadLink != NULL)) {
+    PartNode = GetFirstNode (gEepromPartsHeadLink);
+    do {
+      CurrentEepromParts = EEPROM_PART_INFO_FROM_THIS (PartNode);
+      if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d)   - PartNode            = %08x   HeadLink = %08x\n", __FUNCTION__, __LINE__, PartNode, gEepromPartsHeadLink));
+      DEBUG ((DEBUG_INFO, "%a (#%4d)   - EEPROM bus number   = 0x%08x\n", __FUNCTION__, __LINE__, CurrentEepromParts->BusNumber));
+      DEBUG ((DEBUG_INFO, "%a (#%4d)   - EEPROM address      = 0x%08x\n", __FUNCTION__, __LINE__, CurrentEepromParts->Address));
+      DEBUG ((DEBUG_INFO, "%a (#%4d)   - EEPROM speed        = 0x%08x\n", __FUNCTION__, __LINE__, CurrentEepromParts->PartSpeed));
+      DEBUG ((DEBUG_INFO, "%a (#%4d)   - EEPROM part size    = 0x%08x\n", __FUNCTION__, __LINE__, CurrentEepromParts->PartSize));
+      DEBUG ((DEBUG_INFO, "%a (#%4d)   - EEPROM block length = 0x%08x\n", __FUNCTION__, __LINE__, CurrentEepromParts->BlockLength));
+      DEBUG ((DEBUG_INFO, "%a (#%4d)   - EEPROM page size    = 0x%08x\n", __FUNCTION__, __LINE__, CurrentEepromParts->PageSize));
+      DEBUG ((DEBUG_INFO, "%a (#%4d)   - EEPROM master map   = 0x%08x\n", __FUNCTION__, __LINE__, CurrentEepromParts->Master));
+      //
+      // Dump map records
+      //
+      MapNode = GetFirstNode (&CurrentEepromParts->MapHeadLink);
+      do {
+        CurrentEepromMap = EEPROM_MAP_INFO_FROM_THIS (MapNode);
+        if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d)     - MapNode = %08x   HeadLink = %08x\n", __FUNCTION__, __LINE__, MapNode, &CurrentEepromParts->MapHeadLink));
+        DEBUG ((DEBUG_INFO, "%a (#%4d)     - Address = 0x%08x\n", __FUNCTION__, __LINE__, CurrentEepromMap->Address));
+        DEBUG ((DEBUG_INFO, "%a (#%4d)     - Offset  = 0x%08x\n", __FUNCTION__, __LINE__, CurrentEepromMap->Offset));
+        //
+        // Get next record
+        //
+        MapNode = GetNextNode (&CurrentEepromParts->MapHeadLink, MapNode);
+      } while (!IsNull (&CurrentEepromParts->MapHeadLink, MapNode));
+      //
+      // Get next record
+      //
+      PartNode = GetNextNode (gEepromPartsHeadLink, PartNode);
+    } while (!IsNull (gEepromPartsHeadLink, PartNode));
+  } else {
+    DEBUG ((DEBUG_INFO, "%a (#%4d) - WARNING: gEepromParts or gEepromPartsHeadLink is bad!\n", __FUNCTION__, __LINE__));
+  }
+}
+
+EFI_STATUS
+EFIAPI
+FillEepromMap (
+  IN OUT   VOID      *FunctionInfo
+  )
+{
+  CHAR8                   AsciiBuffer[32];
+  UINT8                  *Buffer;
+  BOOLEAN                 CheckBuffer;
+  EEPROM_MAP_INFO        *CurrentEepromMap;
+  EEPROM_PART_INFO       *CurrentEepromParts;
+  EEPROM_MAP             *EepromHeader;
+  EEPROM_FUNCTION_INFO   *EepromInfo;
+  UINT32                  index;
+  EEPROM_MAP_RECORD      *MapRecord;
+  UINT32                  MaxRecord;
+  UINT8                  *Ptr;
+  UINT32                  Size;
+  EFI_STATUS              Status;
+
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Starting\n", __FUNCTION__, __LINE__));
+
+  //
+  // Initialize variables
+  //
+  Buffer             = NULL;
+  CurrentEepromParts = NULL;
+  EepromInfo         = NULL;
+
+  //
+  // Sanity checks
+  //
+  if (FunctionInfo == NULL) {
+    //
+    // EEPROM function info is outside of range. Bail.
+    //
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: FunctionInfo == NULL!\n", __FUNCTION__, __LINE__));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  } else {
+    EepromInfo = (EEPROM_FUNCTION_INFO *) FunctionInfo;
+    if (EepromInfo->Buffer != NULL) {
+      CheckBuffer = TRUE;
+    } else {
+      CheckBuffer = FALSE;
+    }
+  }
+  if (CheckBuffer) {
+    //
+    // We'll be checking the passed in buffer for the map.
+    //
+    if ((EepromInfo->Buffer == NULL) || (EepromInfo->Size == 0)) {
+      //
+      // EEPROM function info is outside of range. Bail.
+      //
+      DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: FunctionInfo->Buffer == NULL or FunctionInfo->Size == 0!\n", __FUNCTION__, __LINE__));
+      Status = EFI_INVALID_PARAMETER;
+      goto Exit;
+    }
+  }
+  if ((EepromInfo->Bus > MAX_I2C_BUS) || (EepromInfo->Address > MAX_I2C_ADDRESS)) {
+    //
+    // EEPROM function info is outside of range. Bail.
+    //
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: FunctionInfo->Bus > 7 or FunctionInfo->Address >= 0x80!\n", __FUNCTION__, __LINE__));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+
+  //
+  // Debug info
+  //
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - gEepromPartsHeadLink = 0x%08x   gEepromParts = 0x%08x\n", __FUNCTION__, __LINE__, gEepromPartsHeadLink, gEepromParts));
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Bus                  = 0x%02x         Address      = 0x%02x\n", __FUNCTION__, __LINE__, EepromInfo->Bus, EepromInfo->Address));
+
+  //
+  // Is our map valid?
+  //
+  if ((gEepromParts != NULL) && (gEepromPartsHeadLink != NULL)) {
+    //
+    // Parse list of part records to see if we already have this map.
+    //
+    if (SearchEepromPartList (EepromInfo->Bus, EepromInfo->Address) != NULL) {
+      //
+      // Yep. Bail.
+      //
+      if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Already have valid EEPROM map.\n", __FUNCTION__, __LINE__));
+      Status = EFI_SUCCESS;
+      goto Exit;
+    } else {
+      if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Failed to find EEPROM map. Trying to add it.\n", __FUNCTION__, __LINE__));
+    }
+  } else {
+    //
+    // Make sure our parts buffer is pointing to NULL.
+    //
+    gEepromPartsHeadLink = EepromFreePool (gEepromPartsHeadLink);
+    gEepromParts         = EepromFreePool (gEepromParts);
+  }
+
+  //
+  // Create read buffer
+  //
+  if (CheckBuffer) {
+    //
+    // Use the passed in buffer.
+    //
+    Buffer = EepromInfo->Buffer;
+  } else {
+    if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Allocating buffer to hold first 4KB.\n", __FUNCTION__, __LINE__));
+    Size   = 4 * 1024;
+    Buffer = EepromAllocatePool (Size);
+    if (Buffer == NULL) {
+      Status = EFI_OUT_OF_RESOURCES;
+      goto Exit;
+    }
+  }
+
+  //
+  // Fill in map
+  //   1. Read in 4KB from PcdEepromBus|PcdEepromAddress.
+  //   2. Jump the structures looking for $EeprMap structure.
+  //   3. Load EEPROM map records from this structure.
+  //
+  if (CheckBuffer) {
+    Size = EepromInfo->Size;
+  } else {
+    //
+    // Step #1: Load buffer with first 4KB of data from the EEPROM
+    //
+    if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Reading first 4KB of EEPROM data.\n", __FUNCTION__, __LINE__));
+    //
+    // Read EEPROM
+    //
+    Ptr  = Buffer;
+    Size = 4 * 1024;
+    //
+    // Get first 8 bytes
+    //
+    Status = I2cReadPages (EepromInfo->Bus, EepromInfo->Address, 0, 8, Ptr);
+    if (EFI_ERROR (Status)) {
+      goto Exit;
+    }
+    //
+    // Sanity check EEPROM contents
+    //
+    AsciiSPrint (AsciiBuffer, 32, "%8a", (CHAR8 *) Ptr);
+    if (AsciiStrnCmp (AsciiBuffer, "$Eeprom$", 0x08) != 0) {
+      //
+      // Not a vallid EEPROM image. Bail.
+      //
+      Status = EFI_NO_MAPPING;
+      goto Exit;
+    }
+    //
+    // Read in 4KB
+    //
+    Ptr    = Buffer;
+    Status = I2cReadPages (EepromInfo->Bus, EepromInfo->Address, 0, Size, Ptr);
+    if (EFI_ERROR (Status)) {
+      goto Exit;
+    }
+  }
+
+  //
+  // Step #2: Search for $EeprMap
+  //
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Looking for $EeprMap structure.\n", __FUNCTION__, __LINE__));
+  Status       = EFI_NO_MAPPING;
+  EepromHeader = (EEPROM_MAP *) Buffer;
+  Ptr          = Buffer;
+  while (Ptr[0] == '$') {
+    AsciiSPrint (AsciiBuffer, 32, "%8a", EepromHeader->signature);
+    AsciiBuffer[8] = 0;
+    if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Structure = %a @ 0x%08x\n", __FUNCTION__, __LINE__, AsciiBuffer, EepromHeader));
+    if (AsciiStrnCmp (EepromHeader->signature, "$EeprMap", 0x08) != 0) {
+      //
+      // This is not our structure. Skip to next structure.
+      //
+      EepromHeader = (EEPROM_MAP *) ((UINT8 *) EepromHeader + EepromHeader->length + (EepromHeader->length % 0x10));
+      if ((UINT8 *) EepromHeader > (Buffer + Size)) {
+        //
+        // Didn't find $EeprMap structure
+        //
+        Status = EFI_NO_MAPPING;
+        break;
+      } else {
+        continue;
+      }
+    } else {
+      //
+      // Found $EeprMap. Create memory buffer.
+      //
+      if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Allocating buffer to hold new EEPROM map.\n", __FUNCTION__, __LINE__));
+      CurrentEepromParts = EepromAllocatePool (sizeof (EEPROM_PART_INFO));
+      if (CurrentEepromParts == NULL) {
+        Status = EFI_OUT_OF_RESOURCES;
+        goto Exit;
+      }
+      //
+      // Copy data into new EEPROM map
+      //
+      CurrentEepromParts->Signature   = EEPROM_PART_INFO_SIGNATURE;
+      CurrentEepromParts->Address     = EepromInfo->Address;
+      CurrentEepromParts->BusNumber   = EepromInfo->Bus;
+      CurrentEepromParts->PartSpeed   = EepromHeader->speed;
+      CurrentEepromParts->PartSize    = EepromHeader->partsize;
+      CurrentEepromParts->BlockLength = EepromHeader->blklength;
+      CurrentEepromParts->PageSize    = EepromHeader->pagesize;
+      CurrentEepromParts->Master      = EepromHeader->master;
+      if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - EEPROM bus number   = 0x%08x\n", __FUNCTION__, __LINE__, CurrentEepromParts->BusNumber));
+      if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - EEPROM address      = 0x%08x\n", __FUNCTION__, __LINE__, CurrentEepromParts->Address));
+      if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - EEPROM speed        = 0x%08x\n", __FUNCTION__, __LINE__, CurrentEepromParts->PartSpeed));
+      if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - EEPROM part size    = 0x%08x\n", __FUNCTION__, __LINE__, CurrentEepromParts->PartSize));
+      if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - EEPROM block length = 0x%08x\n", __FUNCTION__, __LINE__, CurrentEepromParts->BlockLength));
+      if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - EEPROM master map   = 0x%08x\n", __FUNCTION__, __LINE__, CurrentEepromParts->Master));
+      Status = EFI_SUCCESS;
+      break;
+    }
+  };
+  //
+  // Check for error condition
+  //
+  if (EFI_ERROR (Status)) {
+    //
+    // Failed to find $EeprMap
+    //
+    Status = EFI_NO_MAPPING;
+    goto Exit;
+  }
+  //
+  // Insert record
+  //
+  if (gEepromParts == NULL) {
+    // First record, setup head link
+    gEepromParts         = CurrentEepromParts;
+    gEepromPartsHeadLink = EepromAllocatePool (sizeof (LIST_ENTRY));
+    if (gEepromPartsHeadLink == NULL) {
+      Status = EFI_OUT_OF_RESOURCES;
+      goto Exit;
+    }
+    InitializeListHead (gEepromPartsHeadLink);
+  }
+  InsertTailList (gEepromPartsHeadLink, &CurrentEepromParts->Link);
+
+  //
+  // Step #3: Load in EEPROM map records
+  //
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Loading EEPROM map.\n", __FUNCTION__, __LINE__));
+  MapRecord = (EEPROM_MAP_RECORD *) ((UINT8 *) EepromHeader + sizeof (EEPROM_MAP));
+  MaxRecord = (UINT32) (((UINT8 *) EepromHeader + EepromHeader->length) - (UINT8 *) MapRecord) / sizeof (EEPROM_MAP_RECORD);
+  index     = 0;
+  while (index < MaxRecord) {
+    if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d)   - 0x%08x of 0x%08x @ 0x%08x\n", __FUNCTION__, __LINE__, index, MaxRecord, MapRecord));
+    //
+    // Need a new link record
+    //
+    CurrentEepromMap = EepromAllocatePool (sizeof (EEPROM_MAP_INFO));
+    if (CurrentEepromMap == NULL) {
+      Status = EFI_OUT_OF_RESOURCES;
+      goto Exit;
+    }
+    //
+    // Update memory EEPROM map
+    //
+    CurrentEepromMap->Signature = EEPROM_MAP_INFO_SIGNATURE;
+    CurrentEepromMap->Address   = MapRecord->address;
+    CurrentEepromMap->Offset    = MapRecord->offset;
+    if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d)   -       Map[%04x] = %08x\n", __FUNCTION__, __LINE__, index, CurrentEepromMap));
+    if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d)   -   Address[%04x] = %08x\n", __FUNCTION__, __LINE__, index, CurrentEepromMap->Address));
+    if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d)   -    Offset[%04x] = %08x\n", __FUNCTION__, __LINE__, index, CurrentEepromMap->Offset));
+    //
+    // Insert record
+    //
+    if (index == 0) {
+      // First record, setup head link
+      InitializeListHead (&CurrentEepromParts->MapHeadLink);
+    }
+    InsertTailList (&CurrentEepromParts->MapHeadLink, &CurrentEepromMap->Link);
+    //
+    // Point to next record
+    //
+    MapRecord++;
+    index++;
+  }
+
+  //
+  // Set flag
+  //
+  Status = EFI_SUCCESS;
+
+Exit:
+  //
+  // Free resources
+  //
+  Buffer = EepromFreePool (Buffer);
+
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - Ending with %r\n", __FUNCTION__, __LINE__, Status));
+  }
+  return Status;
+}
+
+UINT8
+EFIAPI
+GetMapAddress (
+   IN      UINT32    ReadOffset,
+   OUT     UINT16   *BlockOffset,
+   IN      VOID     *FunctionInfo
+   )
+{
+  EEPROM_FUNCTION_INFO   *EepromInfo;
+  EEPROM_MAP_INFO        *EepromMapInfo;
+  EEPROM_PART_INFO       *EepromPartInfo;
+
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Starting\n", __FUNCTION__, __LINE__));
+
+  //
+  // Initialize variables
+  //
+  EepromInfo = (EEPROM_FUNCTION_INFO *) FunctionInfo;
+
+  //
+  // Sanity Checks
+  //
+  if ((BlockOffset == NULL) || (FunctionInfo == NULL)){
+    goto Exit;
+  }
+
+  //
+  // Get part info
+  //
+  EepromPartInfo = SearchEepromPartList (EepromInfo->Bus, EepromInfo->Address);
+  if (EepromPartInfo != NULL) {
+    //
+    // Found the right EEPROM part record.
+    //
+    EepromMapInfo = SearchEepromMapList (EepromPartInfo, INVALID_I2C_ADDRESS, ReadOffset);
+    if (EepromMapInfo != NULL) {
+      //
+      // Found the right EEPROM part/map record. Return block offset and I2C address.
+      //
+      *BlockOffset = (UINT16) ((ReadOffset % EepromPartInfo->BlockLength) & 0xFFFF);
+      return EepromMapInfo->Address;
+    }
+  }
+
+Exit:
+  return INVALID_I2C_ADDRESS;
+}
+
+EFI_STATUS
+EFIAPI
+I2cReadPages (
+  IN       UINT8     Bus,
+  IN       UINT8     Address,
+  IN       UINT16    Offset,
+  IN       UINT32    Size,
+  IN OUT   UINT8    *Buffer
+  )
+{
+  UINT32              CurrentCount;
+  UINT16              CurrentOffset;
+  EEPROM_PART_INFO   *EepromPartInfo;
+  UINT32              I2cBaseAddress;
+  UINT16              index;
+  UINT8               PageOffset[2];
+  UINT16              PageSize;
+  UINT8               PartSpeed;
+  UINT8              *Ptr;
+  UINT32              ReadCount;
+  UINT16              RetryCount;
+  EFI_STATUS          Status;
+
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Starting\n", __FUNCTION__, __LINE__));
+
+  //
+  // Initialize variables
+  //
+  CurrentCount   = 0;
+  EepromPartInfo = SearchEepromPartList (Bus, Address);
+  I2cBaseAddress = 0;
+  Ptr            = Buffer;
+  RetryCount     = 3;
+
+  //
+  // Sanity checks
+  //
+  if (Ptr == NULL) {
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  if ((Bus > MAX_I2C_BUS) || (Address > MAX_I2C_ADDRESS)) {
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  //
+  // Set page size & part speed
+  //
+  if (EepromPartInfo == NULL) {
+    //
+    // No page size available. Use default size.
+    //
+    PageSize  = DEFAULT_PAGE_SIZE;
+    PartSpeed = Standard_Speed; // default to 100KHz (Standard speed)
+  } else {
+    PageSize  = EepromPartInfo->PageSize;
+    PartSpeed = EepromPartInfo->PartSpeed;
+  }
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Bus          = %02x         Address    = %02x\n", __FUNCTION__, __LINE__, Bus, Address));
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Offset       = %08x   Size       = %08x\n", __FUNCTION__, __LINE__, Offset, Size));
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - PageSize     = %02x         PartSpeed  = %02x\n", __FUNCTION__, __LINE__, PageSize, PartSpeed));
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Buffer       = %08x\n", __FUNCTION__, __LINE__, Buffer));
+  //
+  // Init I2C controller
+  //
+  Status = I2cInit (Bus, Address, PartSpeed, &I2cBaseAddress);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - I2cInit() = %r\n", __FUNCTION__, __LINE__, Status));
+    goto Exit;
+  }
+  //
+  // Read data from part
+  //
+  while (CurrentCount < Size) {
+    //
+    // Set offset
+    //
+    CurrentOffset = (UINT16) (Offset + CurrentCount);
+    //
+    // Calculate ReadCount
+    //
+    ReadCount = PageSize;
+    if ((Size - CurrentCount) < PageSize) {
+      ReadCount = Size - CurrentCount;
+    }
+    //
+    // Adjust for page boundaries
+    //
+    if (((CurrentOffset % PageSize) + ReadCount) > PageSize) {
+      //
+      // Read to page boundary
+      //
+      ReadCount = PageSize - (CurrentOffset % PageSize);
+    }
+    if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Size         = %08x\n", __FUNCTION__, __LINE__, Size));
+    if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - CurrentCount = %08x\n", __FUNCTION__, __LINE__, CurrentCount));
+    if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - PageSize     = %08x\n", __FUNCTION__, __LINE__, PageSize));
+    if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - ReadCount    = %08x\n", __FUNCTION__, __LINE__, ReadCount));
+    //
+    // Set offset
+    //
+    PageOffset[0] = (CurrentOffset >> 8) & 0xFF;   // MSB offset
+    PageOffset[1] = (CurrentOffset >> 0) & 0xFF;   // LSB offset
+    Status = I2cSetOffset (I2cBaseAddress, PageOffset, 2);
+    if (EFI_ERROR (Status)) {
+      if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_ERROR, "%a (#%4d) - I2cSetOffset() = %r [%02x:%02x:%04x]\n", __FUNCTION__, __LINE__, Status, Bus, Address, (Offset + CurrentCount)));
+      goto Exit;
+    }
+    //
+    // Read a page
+    //
+    for (index = 0; index < ReadCount; index++) {
+      if ((index == 0) && (ReadCount - 1 != index)) {
+        // First byte, but not only byte
+        Status = I2cRead (I2cBaseAddress, Ptr, TRUE, FALSE);
+      } else if ((index == 0) && (ReadCount - 1 == index)) {
+        // First and only byte
+        Status = I2cRead (I2cBaseAddress, Ptr, TRUE, TRUE);
+      } else if (ReadCount - 1 == index) {
+        // Last byte of page
+        Status = I2cRead (I2cBaseAddress, Ptr, FALSE, TRUE);
+      } else {
+        // Everything else
+        Status = I2cRead (I2cBaseAddress, Ptr, FALSE, FALSE);
+      }
+      if (EFI_ERROR (Status)) {
+        //
+        // Something went wrong. Bail from this for loop.
+        //
+        DEBUG ((DEBUG_ERROR, "%a (#%4d) - I2cRead() = %r\n", __FUNCTION__, __LINE__, Status));
+        break;
+      }
+      Ptr++;
+    }
+    //
+    // Check for error condition and try it again
+    //
+    if (Status == EFI_NO_RESPONSE) {
+      //
+      // Nobody home at this slave address
+      //
+      goto Exit;
+    }
+    if (EFI_ERROR (Status)) {
+      if (RetryCount-- > 0) {
+        //
+        // Try it again.
+        //
+        Ptr = &Buffer[CurrentCount];
+      } else {
+        DEBUG ((DEBUG_ERROR, "%a (#%4d) - Offset = %08x\n", __FUNCTION__, __LINE__, (Offset + CurrentCount + index)));
+        goto Exit;
+      }
+    } else {
+      //
+      // Update variables
+      //
+      CurrentCount += ReadCount;
+    }
+  }
+
+Exit:
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - Ending with %r\n", __FUNCTION__, __LINE__, Status));
+  }
+  return Status;
+}
+
+EFI_STATUS
+EFIAPI
+I2cWritePages (
+  IN       UINT8      Bus,
+  IN       UINT8      Address,
+  IN       UINT16     Offset,
+  IN       UINT32     Size,
+  IN OUT   UINT8     *Buffer
+  )
+{
+  UINT32              CurrentCount;
+  UINT16              CurrentOffset;
+  EEPROM_PART_INFO   *EepromPartInfo;
+  UINT32              I2cBaseAddress;
+  UINT16              index;
+  UINT8               PageOffset[2];
+  UINT16              PageSize;
+  UINT8               PartSpeed;
+  UINT8              *Ptr;
+  UINT16              RetryCount;
+  EFI_STATUS          Status;
+  UINT32              WriteCount;
+
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Starting\n", __FUNCTION__, __LINE__));
+
+  //
+  // Initialize variables
+  //
+  CurrentCount   = 0;
+  EepromPartInfo = SearchEepromPartList (Bus, Address);
+  I2cBaseAddress = 0;
+  Ptr            = Buffer;
+  RetryCount     = 3;
+
+  //
+  // Sanity checks
+  //
+  if (Ptr == NULL) {
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  if ((Bus > MAX_I2C_BUS) || (Address > MAX_I2C_ADDRESS)) {
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  //
+  // Set page size & part speed
+  //
+  if (EepromPartInfo == NULL) {
+    //
+    // No page size available. Assume 32 bytes per page.
+    //
+    PageSize  = 32;
+    PartSpeed = 1; // default to 100KHz (Standard speed)
+  } else {
+    PageSize  = EepromPartInfo->PageSize;
+    PartSpeed = EepromPartInfo->PartSpeed;
+  }
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Bus          = %02x         Address    = %02x\n", __FUNCTION__, __LINE__, Bus, Address));
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Offset       = %08x   Size       = %08x\n", __FUNCTION__, __LINE__, Offset, Size));
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - PageSize     = %02x         PartSpeed  = %02x\n", __FUNCTION__, __LINE__, PageSize, PartSpeed));
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Buffer       = %08x\n", __FUNCTION__, __LINE__, Buffer));
+  //
+  // Init I2C controller
+  //
+  Status = I2cInit (Bus, Address, PartSpeed, &I2cBaseAddress);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - I2cInit() = %r\n", __FUNCTION__, __LINE__, Status));
+    goto Exit;
+  }
+  //
+  // Write data to part
+  //
+  while (CurrentCount < Size) {
+    //
+    // Set pointer
+    //
+    Ptr = &Buffer[CurrentCount];
+    //
+    // Set offset
+    //
+    CurrentOffset = (UINT16) (Offset + CurrentCount);
+    //
+    // Calculate WriteCount
+    //
+    WriteCount = PageSize;
+    if ((Size - CurrentCount) < PageSize) {
+      WriteCount = Size - CurrentCount;
+    }
+    //
+    // Adjust for page boundaries
+    //
+    if (((CurrentOffset % PageSize) + WriteCount) > PageSize) {
+      //
+      // Write to page boundary
+      //
+      WriteCount = PageSize - (CurrentOffset % PageSize);
+    }
+    if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Size         = %08x\n", __FUNCTION__, __LINE__, Size));
+    if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - CurrentCount = %08x\n", __FUNCTION__, __LINE__, CurrentCount));
+    if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - PageSize     = %08x\n", __FUNCTION__, __LINE__, PageSize));
+    if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - WriteCount   = %08x\n", __FUNCTION__, __LINE__, WriteCount));
+    //
+    // Set offset
+    //
+    PageOffset[0] = (CurrentOffset >> 8) & 0xFF;   // MSB offset
+    PageOffset[1] = (CurrentOffset >> 0) & 0xFF;   // LSB offset
+    Status = I2cSetOffset (I2cBaseAddress, PageOffset, 2);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "%a (#%4d) - I2cSetOffset() = %r\n", __FUNCTION__, __LINE__, Status));
+      goto Exit;
+    }
+    //
+    // Write a page
+    //
+    for (index = 0; index < WriteCount; index++) {
+      if (WriteCount - 1 == index) {
+        // Last byte of the page
+        Status = I2cWrite (I2cBaseAddress, *Ptr, FALSE, TRUE);
+      } else {
+        // Everything else
+        Status = I2cWrite (I2cBaseAddress, *Ptr, FALSE, FALSE);
+      }
+      if (EFI_ERROR (Status)) {
+        //
+        // Something went wrong. Bail from this for loop.
+        //
+        DEBUG ((DEBUG_ERROR, "%a (#%4d) - I2cWrite() = %r\n", __FUNCTION__, __LINE__, Status));
+        break;
+      }
+      Ptr++;
+    }
+    if (Status == EFI_NO_RESPONSE) {
+      //
+      // Nobody home at this slave address
+      //
+      goto Exit;
+    }
+    //
+    // Check for error condition and try it again
+    //
+    if (EFI_ERROR (Status)) {
+      if (RetryCount-- == 0) {
+        DEBUG ((DEBUG_ERROR, "%a (#%4d) - Offset = %08x\n", __FUNCTION__, __LINE__, (Offset + CurrentCount + index)));
+        goto Exit;
+      }
+    } else {
+      //
+      // Update variables
+      //
+      CurrentCount += WriteCount;
+      if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - CurrentCount = %08x   WriteCount = %08x\n", __FUNCTION__, __LINE__, CurrentCount, WriteCount));
+    }
+    //
+    // Make sure write is done
+    //
+    Status = I2cPoll (I2cBaseAddress);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "%a (#%4d) - I2cPoll() = %r\n", __FUNCTION__, __LINE__, Status));
+      goto Exit;
+    }
+  }
+
+Exit:
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - Ending with %r\n", __FUNCTION__, __LINE__, Status));
+  }
+  return Status;
+}
+
+EFI_STATUS
+EFIAPI
+LoadEepromMap (VOID)
+{
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+ReadEepromBlockList (
+  IN OUT   UINT8        *Buffer,
+  IN       VOID         *FunctionInfo,
+  IN       BLOCK_LIST   *BlockListHead
+  )
+{
+  BLOCK_LIST             *CurrentBlockList;
+  EEPROM_FUNCTION_INFO   *EepromInfo;
+  LIST_ENTRY             *Node;
+  UINT8                  *Ptr;
+  UINT32                  ReadCount;
+  EFI_STATUS              Status;
+
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Starting\n", __FUNCTION__, __LINE__));
+
+  //
+  // Initialize variables
+  //
+  EepromInfo = (EEPROM_FUNCTION_INFO *) FunctionInfo;
+  Ptr        = Buffer;
+  ReadCount  = 0;
+  Status     = EFI_SUCCESS;
+
+  //
+  // Sanity checks
+  //
+  if ((Buffer == NULL) || (FunctionInfo == NULL) || (BlockListHead == NULL)) {
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+
+  //
+  // Read data into buffer
+  //
+  DEBUG ((DEBUG_INFO, "%a (#%4d) - Reading from EEPROM...\n", __FUNCTION__, __LINE__));
+  Node = GetFirstNode (&BlockListHead->Link);
+  do {
+    //
+    // Read in a block
+    //
+    CurrentBlockList = BLOCK_LIST_FROM_THIS (Node);
+    if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) -               buffer @ %08x\n", __FUNCTION__, __LINE__, Buffer));
+    if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) -                  bus = %08x\n", __FUNCTION__, __LINE__, EepromInfo->Bus));
+    if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) -              address = %08x\n", __FUNCTION__, __LINE__, CurrentBlockList->Address));
+    if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) -               offset = %08x\n", __FUNCTION__, __LINE__, CurrentBlockList->Offset));
+    if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) -                  ptr @ %08x\n", __FUNCTION__, __LINE__, Ptr));
+    Status = I2cReadPages (EepromInfo->Bus, CurrentBlockList->Address, CurrentBlockList->Offset, CurrentBlockList->Size, Ptr);
+    if (EFI_ERROR (Status)) {
+      goto Exit;
+    }
+    //
+    // Get next record
+    //
+    Ptr += CurrentBlockList->Size;
+    Node = GetNextNode (&BlockListHead->Link, Node);
+  } while (!IsNull (&BlockListHead->Link, Node));
+
+Exit:
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - Ending with %r\n", __FUNCTION__, __LINE__, Status));
+  }
+  return Status;
+}
+
+//
+// Desc:        Reads from the EEPROM and copies to the passed in buffer.
+// Variables:   Offset         Start copying from the offset
+//              Size           Size of the buffer and the number of bytes to copy
+//                             - If size = 0, then return image size
+//              Buffer         Storage buffer for the copied data from the EEPROM
+//              FunctionInfo   Pointer to function specific data
+// Return:      EFI_SUCCESS             Data copied successfully
+//              EFI_UNSUPPORTED         This function is not supported
+//              EFI_INVALID_PARAMETER   One of the parameters is invalid
+//              EFI_NOT_READY           Called before all necessary protocols available
+//              EFI_DEVICE_ERROR        Communication error with device
+//
+EFI_STATUS
+EFIAPI
+ReadEepromEeprom (
+  IN       UINT32    Offset,
+  IN OUT   UINT32   *Size,
+  IN OUT   UINT8    *Buffer,
+  IN OUT   VOID     *FunctionInfo
+  )
+{
+  BLOCK_LIST             *BlockList;
+  EEPROM_FUNCTION_INFO   *EepromInfo;
+  EEPROM_PART_INFO       *EepromPartInfo;
+  EFI_STATUS              Status;
+
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Starting\n", __FUNCTION__, __LINE__));
+
+  //
+  // Initialize variables
+  //
+  BlockList            = NULL;
+  EepromInfo           = (EEPROM_FUNCTION_INFO *) FunctionInfo;
+  EepromPartInfo       = NULL;
+  Status               = EFI_SUCCESS;
+  LoadEepromMap ();
+
+  //
+  // Sanity checks
+  //
+  // NOTE: Input parameters already checked in wrapper function.
+  //
+  if (FunctionInfo == NULL) {
+    //
+    // This needs to be pointing to something. Bail.
+    //
+    if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_ERROR, "%a (#%4d) - FunctionInfo == NULL!\n", __FUNCTION__, __LINE__));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  if (EepromInfo->LibraryIndex != EEPROM_EEPROM) {
+    if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_ERROR, "%a (#%4d) - LibraryIndex != EEPROM_EEPROM!\n", __FUNCTION__, __LINE__));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+
+  //
+  // Scan I2C bus for images?
+  //
+  if (EepromInfo->ScanSize != NULL) {
+    Status = ScanI2cBusForImages (EepromInfo->Bus, &(EepromInfo->ScanBuffer), EepromInfo->ScanSize);
+    goto Exit;
+  }
+
+  //
+  // Make sure we have the EEPROM map for this part
+  //
+  Status = FillEepromMap (FunctionInfo);
+  if (EFI_ERROR (Status)) {
+    goto Exit;
+  }
+
+  //
+  // Dump current mappings
+  //
+  DumpEepromMap ();
+
+  //
+  // Do they just want the size of the EEPROM part?
+  //
+  if (*Size == 0) {
+    //
+    // Return EEPROM part size
+    //
+    EepromPartInfo = SearchEepromPartList (EepromInfo->Bus, EepromInfo->Address);
+    if (EepromPartInfo == NULL) {
+      //
+      // Failed to find part info. Bail.
+      //
+      Status = EFI_NO_MAPPING;
+    } else {
+      //
+      // Return EEPROM part size.
+      //
+      *Size = EepromPartInfo->PartSize;
+      Status = EFI_BUFFER_TOO_SMALL;
+    }
+    goto Exit;
+  }
+
+  //
+  // Initialize block list head
+  //
+  BlockList = EepromAllocatePool (sizeof (BLOCK_LIST));
+  InitializeListHead (&BlockList->Link);
+
+  //
+  // Create list of blocks to read
+  //
+  Status = CreateBlockList (
+             Offset,         // Offset in EEPROM to start reading data from
+             Size,           // Number of bytes to read
+             FunctionInfo,   // Pointer to function specific data
+             BlockList       // Head block list
+             );
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - CreateBlockList() = %r\n", __FUNCTION__, __LINE__, Status));
+  if (EFI_ERROR (Status)) {
+    goto Exit;
+  }
+
+  //
+  // Read the list into the buffer
+  //
+  Status = ReadEepromBlockList (
+             Buffer,
+             FunctionInfo,
+             BlockList
+             );
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - ReadEepromBlockList() = %r\n", __FUNCTION__, __LINE__, Status));
+  if (EFI_ERROR (Status)) {
+    goto Exit;
+  }
+
+Exit:
+  //
+  // Free resources
+  //
+  DestroyBlockList (BlockList);
+
+  if (EFI_ERROR (Status) && (Status != EFI_BUFFER_TOO_SMALL)) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - Ending with %r\n", __FUNCTION__, __LINE__, Status));
+  }
+  //
+  // Save off pointers for use across LIB instances
+  //
+  SaveEepromMap ();
+
+  return Status;
+}
+
+EFI_STATUS
+EFIAPI
+SaveEepromMap (VOID)
+{
+  //
+  // Initialize variables
+  //
+  PcdSet64S (PcdEepromParts,         (UINTN) gEepromParts);
+  PcdSet64S (PcdEepromPartsHeadLink, (UINTN) gEepromPartsHeadLink);
+
+  //
+  // Save to HOB if needed
+  //
+  if (!PcdGetBool (PcdEepromMapHobValid)) {
+    //
+    // HOB is not valid, load it into HOB.
+    //
+
+    //
+    // Toggle flag
+    //
+    PcdSetBoolS (PcdEepromMapHobValid, TRUE);
+  }
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+ScanI2cBusForImages (
+  IN       UINT8     I2cBus,
+  IN OUT   UINT8   **Addresses,
+  IN OUT   UINT8    *AddressesSize
+  )
+{
+  BOOLEAN         AddressArray[MAX_I2C_ADDRESS];
+  UINT8           AddressCount;
+  EEPROM_HEADER   EepromHeader;
+  UINT8           index;
+  EFI_STATUS      Status;
+
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Starting\n", __FUNCTION__, __LINE__));
+
+  //
+  // Initialize variables
+  //
+  ZeroMem (AddressArray, MAX_I2C_ADDRESS);
+  ZeroMem (&EepromHeader, sizeof (EEPROM_HEADER));
+  AddressCount = 0;
+  Status       = EFI_SUCCESS;
+
+  //
+  // Sanity checks
+  //
+  if (Addresses == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Addresses buffer is NULL!\n", __FUNCTION__, __LINE__));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  if (AddressesSize == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: AddressesSize buffer is NULL!\n", __FUNCTION__, __LINE__));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+
+  //
+  // Make sure Addresses is empty
+  //
+  *Addresses     = EepromFreePool (*Addresses);
+  *AddressesSize = 0;
+
+  //
+  // Scan bus for possible images
+  //
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Scanning bus %02x.\n", __FUNCTION__, __LINE__, I2cBus));
+  for (index = 0; index < MAX_I2C_ADDRESS; index++) {
+    //
+    // Check for somebody home
+    //
+    if (mEepromDataLibDebugFlag &&((index % 0x10) == 0)) DEBUG ((DEBUG_INFO, "."));
+    Status = I2cReadPages (I2cBus, index, 0, sizeof (EEPROM_HEADER), (UINT8 *) &EepromHeader);
+    if (!EFI_ERROR (Status) && (AsciiStrnCmp (EepromHeader.signature, "$Eeprom$", 0x08) == 0)) {
+      //
+      // Update array and count, since this devices starts with $Eeprom$
+      //
+      AddressArray[index] = TRUE;
+      AddressCount++;
+    }
+  }
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, " [%d]\n", AddressCount));
+
+  //
+  // Give return values
+  //
+  *AddressesSize = AddressCount;
+
+  //
+  // Scan array for possible images
+  //
+  if (AddressCount > 0) {
+    //
+    // Allocate return buffer
+    //
+    *Addresses = EepromAllocatePool (AddressCount);
+    if (*Addresses == NULL) {
+      DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Unable to allocate buffer for Addresses!\n", __FUNCTION__, __LINE__));
+      Status = EFI_OUT_OF_RESOURCES;
+      *AddressesSize = 0;
+      goto Exit;
+    }
+    //
+    // Fill return buffer
+    //
+    for (index = MAX_I2C_ADDRESS; index > 0; index--) {
+      if (AddressArray[index - 1]) {
+        //
+        // Here's one
+        //
+        if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Possible image on bus %02x, address %02x.\n", __FUNCTION__, __LINE__, I2cBus, index - 1));
+        (*Addresses)[--AddressCount] = index - 1;
+        if (AddressCount == 0) {
+          //
+          // We've accounted for them all. Bail.
+          //
+          Status = EFI_SUCCESS;
+          goto Exit;
+        }
+      }
+    }
+  }
+
+Exit:
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - Ending with %r\n", __FUNCTION__, __LINE__, Status));
+  }
+  return Status;
+}
+
+EEPROM_MAP_INFO *
+EFIAPI
+SearchEepromMapList (
+  IN  EEPROM_PART_INFO   *EepromPartInfo,
+  IN  UINT8               Address,
+  IN  UINT32              Offset
+  )
+{
+  EEPROM_MAP_INFO   *EepromMapInfo;
+  LIST_ENTRY        *Node;
+
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Starting\n", __FUNCTION__, __LINE__));
+
+  //
+  // Sanity checks
+  //
+  if (EepromPartInfo == NULL) {
+    goto Exit;
+  }
+  if ((Address > MAX_I2C_ADDRESS) && (Address != INVALID_I2C_ADDRESS)) {
+    goto Exit;
+  }
+
+  Node = GetFirstNode (&EepromPartInfo->MapHeadLink);
+  do {
+    EepromMapInfo = EEPROM_MAP_INFO_FROM_THIS (Node);
+    if (EepromMapInfo->Address == Address) {
+      //
+      // Found the right Address. Bail.
+      //
+      return EepromMapInfo;
+    }
+    if (Address == INVALID_I2C_ADDRESS) {
+      //
+      // Looking for an offset match.
+      //
+      if ((Offset >= EepromMapInfo->Offset) && (Offset < (EepromMapInfo->Offset + EepromPartInfo->BlockLength))) {
+        //
+        // Found the right offset. Bail.
+        //
+        return EepromMapInfo;
+      }
+    }
+    //
+    // Get next record
+    //
+    Node = GetNextNode (&EepromPartInfo->MapHeadLink, Node);
+  } while (!IsNull (&EepromPartInfo->MapHeadLink, Node));
+
+Exit:
+  return NULL;
+}
+
+EEPROM_PART_INFO *
+EFIAPI
+SearchEepromPartList (
+  IN  UINT8    Bus,
+  IN  UINT8    Address
+  )
+{
+  EEPROM_MAP_INFO    *EepromMapInfo;
+  EEPROM_PART_INFO   *EepromPartInfo;
+  LIST_ENTRY         *Node;
+
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Starting\n", __FUNCTION__, __LINE__));
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - gEepromParts         = %08x\n", __FUNCTION__, __LINE__, gEepromParts));
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - gEepromPartsHeadLink = %08x\n", __FUNCTION__, __LINE__, gEepromPartsHeadLink));
+
+  //
+  // Sanity checks
+  //
+  if ((gEepromParts == NULL) || (gEepromPartsHeadLink == NULL)) {
+    return NULL;
+  }
+  if ((Bus > MAX_I2C_BUS) || (Address > MAX_I2C_ADDRESS)) {
+    return NULL;
+  }
+
+  Node = GetFirstNode (gEepromPartsHeadLink);
+  do {
+    if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d)   - Node               = %08x\n", __FUNCTION__, __LINE__, Node));
+    EepromPartInfo = EEPROM_PART_INFO_FROM_THIS (Node);
+    if (EepromPartInfo->BusNumber == Bus) {
+      //
+      // Is this our root address?
+      //
+      if (EepromPartInfo->Address == Address) {
+        //
+        // Yep.
+        //
+        return EepromPartInfo;
+      }
+      //
+      // Found the right Bus, is it the right address?
+      //
+      EepromMapInfo = SearchEepromMapList (
+                        EepromPartInfo,
+                        Address,
+                        0x00000000
+                        );
+      if (EepromMapInfo == NULL) {
+        //
+        // Not our record
+        //
+      } else {
+        //
+        // Found the right record. Bail.
+        //
+        return EepromPartInfo;
+      }
+    }
+    //
+    // Get next record
+    //
+    Node = GetNextNode (gEepromPartsHeadLink, Node);
+  } while (!IsNull (gEepromPartsHeadLink, Node));
+  return NULL;
+}
+
+EFI_STATUS
+EFIAPI
+WriteEepromBlockList (
+  IN   UINT8        *Buffer,
+  IN   VOID         *FunctionInfo,
+  IN   BLOCK_LIST   *BlockListHead
+  )
+{
+  BLOCK_LIST             *CurrentBlockList;
+  EEPROM_FUNCTION_INFO   *EepromInfo;
+  LIST_ENTRY             *Node;
+  UINT8                  *Ptr;
+  UINT32                  ReadCount;
+  EFI_STATUS              Status;
+
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Starting\n", __FUNCTION__, __LINE__));
+
+  //
+  // Initialize variables
+  //
+  EepromInfo = (EEPROM_FUNCTION_INFO *) FunctionInfo;
+  ReadCount  = 0;
+  Status     = EFI_SUCCESS;
+
+  //
+  // Sanity checks
+  //
+  if ((Buffer == NULL) || (FunctionInfo == NULL) || (BlockListHead == NULL)) {
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+
+  //
+  // Write data from buffer
+  //
+  DEBUG ((DEBUG_INFO, "%a (#%4d) - Writing to EEPROM...\n", __FUNCTION__, __LINE__));
+  Node = GetFirstNode (&BlockListHead->Link);
+  do {
+    //
+    // Write out a block
+    //
+    CurrentBlockList = BLOCK_LIST_FROM_THIS (Node);
+    Ptr              = Buffer + CurrentBlockList->Offset;
+    Status = I2cWritePages (EepromInfo->Bus, CurrentBlockList->Address, CurrentBlockList->Offset, CurrentBlockList->Size, Ptr);
+    if (EFI_ERROR (Status)) {
+      goto Exit;
+    }
+    //
+    // Get next record
+    //
+    Node = GetNextNode (&BlockListHead->Link, Node);
+  } while (!IsNull (&BlockListHead->Link, Node));
+
+Exit:
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - Ending with %r\n", __FUNCTION__, __LINE__, Status));
+  }
+  return Status;
+}
+
+//
+// Desc:        Writes to the EEPROM and copies to the passed in buffer.
+// Variables:   Offset         Start copying from the offset
+//              Size           Size of the buffer and the number of bytes to copy
+//              Buffer         Storage buffer for the copied data to the EEPROM
+//              FunctionInfo   Pointer to function specific data
+// Return:      EFI_SUCCESS             Data copied successfully
+//              EFI_UNSUPPORTED         This function is not supported
+//              EFI_INVALID_PARAMETER   One of the parameters is invalid
+//              EFI_NOT_READY           Called before all necessary protocols available
+//              EFI_DEVICE_ERROR        Communication error with device
+//
+EFI_STATUS
+EFIAPI
+WriteEepromEeprom (
+  IN       UINT32    Offset,
+  IN OUT   UINT32   *Size,
+  IN OUT   UINT8    *Buffer,
+  IN OUT   VOID     *FunctionInfo
+  )
+{
+  BLOCK_LIST             *BlockList;
+  EEPROM_FUNCTION_INFO   *EepromInfo;
+  EEPROM_PART_INFO       *EepromPartInfo;
+  EFI_STATUS              Status;
+
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Starting\n", __FUNCTION__, __LINE__));
+
+  //
+  // Initialize variables
+  //
+  BlockList            = NULL;
+  EepromInfo           = (EEPROM_FUNCTION_INFO *) FunctionInfo;
+  EepromPartInfo       = NULL;
+  Status               = EFI_SUCCESS;
+  LoadEepromMap ();
+
+  //
+  // Sanity checks
+  //
+  // NOTE: Input parameters already checked in wrapper function.
+  //
+  if (FunctionInfo == NULL) {
+    //
+    // This needs to be pointing to something. Bail.
+    //
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  if (EepromInfo->LibraryIndex != EEPROM_EEPROM) {
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+
+  //
+  // Grab the EEPROM map from the passed in buffer
+  //
+  EepromInfo->Buffer = Buffer;
+  EepromInfo->Size   = *Size;
+  Status = FillEepromMap (FunctionInfo);
+  if (EFI_ERROR (Status)) {
+    if (Status == EFI_NO_RESPONSE) {
+      //
+      // Nobody home, bail.
+      //
+      goto Exit;
+    }
+    //
+    // We don't already have the EEPROM map in the buffer. See if there's one already in the part.
+    //
+    if (*Size == 0) {
+      //
+      // Asking for EEPROM image size. We don't know so bail.
+      //
+      Status = EFI_NOT_READY;
+      goto Exit;
+    } else {
+      EepromInfo->Buffer = NULL;
+      EepromInfo->Size   = 0;
+      Status = FillEepromMap (FunctionInfo);
+      if (EFI_ERROR (Status)) {
+        goto Exit;
+      }
+    }
+  }
+
+  //
+  // Dump current mappings
+  //
+  DumpEepromMap ();
+
+  //
+  // Do they just want the size of the EEPROM part?
+  //
+  if (*Size == 0) {
+    //
+    // Return EEPROM part size
+    //
+    EepromPartInfo = SearchEepromPartList (EepromInfo->Bus, EepromInfo->Address);
+    if (EepromPartInfo == NULL) {
+      //
+      // Failed to find part info. Bail.
+      //
+      Status = EFI_NO_MAPPING;
+    } else {
+      //
+      // Return EEPROM part size.
+      //
+      *Size = EepromPartInfo->PartSize;
+      Status = EFI_BUFFER_TOO_SMALL;
+    }
+    goto Exit;
+  }
+
+  //
+  // Initialize block list head
+  //
+  BlockList = EepromAllocatePool (sizeof (BLOCK_LIST));
+  InitializeListHead (&BlockList->Link);
+
+  //
+  // Create list of blocks to write
+  //
+  Status = CreateBlockList (
+             Offset,         // Offset in EEPROM to start writing data to
+             Size,           // Number of bytes to write
+             FunctionInfo,   // Pointer to function specific data
+             BlockList       // Head block list
+             );
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - CreateBlockList() = %r\n", __FUNCTION__, __LINE__, Status));
+  if (EFI_ERROR (Status)) {
+    goto Exit;
+  }
+
+  //
+  // Write the list from the buffer
+  //
+  Status = WriteEepromBlockList (
+             Buffer,
+             FunctionInfo,
+             BlockList
+             );
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - WriteEepromBlockList() = %r\n", __FUNCTION__, __LINE__, Status));
+  if (EFI_ERROR (Status)) {
+    goto Exit;
+  }
+
+Exit:
+  //
+  // Free resources
+  //
+  DestroyBlockList (BlockList);
+
+  if (EFI_ERROR (Status) && (Status != EFI_BUFFER_TOO_SMALL)) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - Ending with %r\n", __FUNCTION__, __LINE__, Status));
+  }
+  //
+  // Save off pointers for use across LIB instances
+  //
+  SaveEepromMap ();
+
+  return Status;
+}
+
diff --git a/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/EEPROM/EepromDataEepromLib.h b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/EEPROM/EepromDataEepromLib.h
new file mode 100644
index 0000000000..931d778400
--- /dev/null
+++ b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/EEPROM/EepromDataEepromLib.h
@@ -0,0 +1,213 @@
+/** @file
+  Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _EEPROM_DATA_EEPROM_LIB_
+#define _EEPROM_DATA_EEPROM_LIB_
+////
+//// Header files
+////
+#include <Uefi.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/EepromDataLib.h>
+#include <Library/PrintLib.h>
+#include <Library/TimerLib.h>
+
+#include <EepromStruct.h>
+#include "I2cLib.h"
+
+//
+// Defines
+//
+#define   BLOCK_LIST_SIGNATURE          SIGNATURE_32 ('B', 'k', 'L', 't')
+#define   EEPROM_MAP_INFO_SIGNATURE     SIGNATURE_32 ('E', 'm', 'M', 'p')
+#define   EEPROM_PART_INFO_SIGNATURE    SIGNATURE_32 ('E', 'm', 'P', 't')
+
+#define   DEFAULT_PAGE_SIZE             0x10
+#define   EEPROM_HOB_HEADER_SIGNATURE   SIGNATURE_32 ('e', 'H', 'B', 'e')
+#define   EEPROM_HOB_HEADER_VERSION     0x00000001
+#define   EEPROM_HOB_MAX_DATA_SIZE      (30 * 1024)
+
+//
+// Structures
+//
+typedef struct {
+  UINT32       Signature;
+  LIST_ENTRY   Link;
+  UINT8        Address;
+  UINT16       Offset;
+  UINT32       Size;
+} BLOCK_LIST;
+
+typedef struct {
+  UINT32       Signature;
+  LIST_ENTRY   Link;
+  UINT8        Address;
+  UINT32       Offset;
+} EEPROM_MAP_INFO;
+
+typedef struct {
+   UINT32    Signature;
+   UINT32    Version;
+   UINT16    BlockNumber;
+   UINT16    BlockSize;
+   UINT32    Reserved;
+} EEPROM_MEMORY_HOB_HEADER;
+
+typedef struct {
+  UINT32             Signature;
+  LIST_ENTRY         Link;
+  UINT8              Address;
+  UINT32             BlockLength;
+  UINT8              BusNumber;
+  BOOLEAN            Master;
+  UINT16             PageSize;
+  UINT32             PartSize;
+  UINT8              PartSpeed;
+  LIST_ENTRY         MapHeadLink;
+} EEPROM_PART_INFO;
+
+//
+// Functions
+//
+EFI_STATUS
+EFIAPI
+CopyEepromMap (VOID);
+
+EFI_STATUS
+EFIAPI
+CreateBlockList (
+  IN       UINT32        Offset,
+  IN       UINT32       *Size,
+  IN       VOID         *FunctionInfo,
+  IN OUT   BLOCK_LIST   *BlockListHead
+  );
+
+VOID
+EFIAPI
+DestroyPageList (
+  IN  BLOCK_LIST  *BlockListHead
+  );
+
+VOID
+EFIAPI
+DumpEepromMap (VOID);
+
+EFI_STATUS
+EFIAPI
+FillEepromMap (
+  IN OUT   VOID      *FunctionInfo
+  );
+
+UINT8
+EFIAPI
+GetMapAddress (
+   IN      UINT32    ReadOffset,
+   OUT     UINT16   *BlockOffset,
+   IN      VOID     *FunctionInfo
+   );
+
+EFI_STATUS
+EFIAPI
+I2cReadPages (
+  IN       UINT8     Bus,
+  IN       UINT8     Address,
+  IN       UINT16    Offset,
+  IN       UINT32    Size,
+  IN OUT   UINT8    *Buffer
+  );
+
+EFI_STATUS
+EFIAPI
+I2cWritePages (
+  IN       UINT8      Bus,
+  IN       UINT8      Address,
+  IN       UINT16     Offset,
+  IN       UINT32     Size,
+  IN OUT   UINT8     *Buffer
+  );
+
+EFI_STATUS
+EFIAPI
+LoadEepromMap (VOID);
+
+EFI_STATUS
+EFIAPI
+ReadEepromBlockList (
+  IN OUT   UINT8        *Buffer,
+  IN       VOID         *FunctionInfo,
+  IN       BLOCK_LIST   *BlockListHead
+  );
+
+EFI_STATUS
+EFIAPI
+SaveEepromMap (VOID);
+
+EFI_STATUS
+EFIAPI
+ScanI2cBusForImages (
+  IN       UINT8     I2cBus,
+  IN OUT   UINT8   **Addresses,
+  IN OUT   UINT8    *AddressesSize
+  );
+
+EEPROM_MAP_INFO *
+EFIAPI
+SearchEepromMapList (
+  IN  EEPROM_PART_INFO   *EepromPartInfo,
+  IN  UINT8               Address,
+  IN  UINT32              Offset
+  );
+
+EEPROM_PART_INFO *
+EFIAPI
+SearchEepromPartList (
+  IN  UINT8    Bus,
+  IN  UINT8    Address
+  );
+
+EFI_STATUS
+EFIAPI
+WriteEepromBlockList (
+  IN   UINT8        *Buffer,
+  IN   VOID         *FunctionInfo,
+  IN   BLOCK_LIST   *BlockListHead
+  );
+
+//
+// CR macros
+//
+#define BLOCK_LIST_FROM_THIS(a) \
+  CR (a, \
+      BLOCK_LIST, \
+      Link, \
+      BLOCK_LIST_SIGNATURE \
+      )
+
+#define EEPROM_MAP_INFO_FROM_THIS(a) \
+  CR (a, \
+      EEPROM_MAP_INFO, \
+      Link, \
+      EEPROM_MAP_INFO_SIGNATURE \
+      )
+
+#define EEPROM_PART_INFO_FROM_THIS(a) \
+  CR (a, \
+      EEPROM_PART_INFO, \
+      Link, \
+      EEPROM_PART_INFO_SIGNATURE \
+      )
+
+#endif // _EEPROM_DATA_EEPROM_LIB_
diff --git a/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/EEPROM/HobData.c b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/EEPROM/HobData.c
new file mode 100644
index 0000000000..46523dbd7b
--- /dev/null
+++ b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/EEPROM/HobData.c
@@ -0,0 +1,142 @@
+/** @file
+  Memory EEPROM raw data library instance.
+
+  Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "EepromDataEepromLib.h"
+#include <PiDxe.h>
+#include <Library/HobLib.h>
+
+EFI_STATUS
+EFIAPI
+GetEepromDataHobData (VOID)
+{
+  UINT8                        *BlockData;
+  BOOLEAN                       BlockFound;
+  UINT16                        BlockNumber;
+  UINT32                        BlockSize;
+  UINT8                        *Buffer;
+  EFI_HOB_GUID_TYPE            *GuidHobPtr;
+  UINT16                        LastBlockNumber;
+  EEPROM_MEMORY_HOB_HEADER     *MemoryHobHeader;
+  EFI_STATUS                    Status;
+
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Starting...\n", __FUNCTION__, __LINE__));
+
+  //
+  // Initialize variables
+  //
+  Buffer = NULL;
+  Status = EFI_SUCCESS;
+
+  if (PcdGetBool (PcdEepromMemoryHobPresent)) {
+    //
+    // Clear PCD values
+    //
+    PcdSet64 (PcdEepromMemoryPointer, 0);
+    PcdSet32 (PcdEepromMemorySize,    0);
+
+    //
+    // Gather HOB data into coherent chunk by looping thru the HOBs looking for the blocks in order.
+    //
+    LastBlockNumber = 0;
+    while (TRUE) {
+      //
+      // Reset to the beginning of the HOBs
+      //
+      BlockFound = FALSE;
+      GuidHobPtr = GetFirstGuidHob (&gEepromVariableGuid);
+      while (GuidHobPtr != NULL) {
+        //
+        // Get Memory HOB header pointer
+        //
+        MemoryHobHeader = GET_GUID_HOB_DATA (GuidHobPtr);
+        BlockData       = (UINT8 *) MemoryHobHeader + sizeof (EEPROM_MEMORY_HOB_HEADER);
+        BlockNumber     = MemoryHobHeader->BlockNumber;
+        BlockSize       = MemoryHobHeader->BlockSize;
+
+        //
+        // Is this our block?
+        //
+        if ((LastBlockNumber == BlockNumber) && (MemoryHobHeader->Signature == EEPROM_HOB_HEADER_SIGNATURE)) {
+          //
+          // Yep. Copy existing buffer to larger buffer.
+          //
+          Buffer = EepromAllocateCopyPool (PcdGet32 (PcdEepromMemorySize) + BlockSize, (UINT8 *) PcdGet64 (PcdEepromMemoryPointer));
+          if (Buffer == NULL) {
+            DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Unable to allocate buffer!\n", __FUNCTION__, __LINE__));
+            Status = EFI_OUT_OF_RESOURCES;
+            goto Exit;
+          }
+
+          //
+          // Append new data
+          //
+          CopyMem (Buffer + PcdGet32 (PcdEepromMemorySize), BlockData, BlockSize);
+
+          //
+          // Free old buffer and update PCDs
+          //
+          if (PcdGet64 (PcdEepromMemoryPointer) != 0) {
+            //
+            // Buffer exists. Free it.
+            //
+            EepromFreePool ((UINT8 *) (UINTN) PcdGet64 (PcdEepromMemoryPointer));
+          }
+          BlockSize += PcdGet32 (PcdEepromMemorySize);
+          PcdSet64 (PcdEepromMemoryPointer, (UINTN) Buffer);
+          PcdSet32 (PcdEepromMemorySize,    BlockSize);
+
+          //
+          // Increment counter and set flag
+          //
+          LastBlockNumber++;
+          BlockFound = TRUE;
+          break;
+        }
+
+        //
+        // Skip past present HOB to get next HOB
+        //
+        GuidHobPtr = GET_NEXT_HOB (GuidHobPtr);
+        GuidHobPtr = GetNextGuidHob (&gEepromVariableGuid, GuidHobPtr);
+      }
+      if (!BlockFound) {
+        //
+        // We're done. Bail.
+        //
+        break;
+      }
+    }
+
+    //
+    // Toggle flag.
+    //
+    PcdSetBool (PcdEepromMemoryHobPresent, FALSE);
+  }
+
+Exit:
+  return Status;
+}
+
+EFI_STATUS
+EFIAPI
+SetEepromDataHobData (VOID)
+{
+  //
+  // Not supported in DXE.
+  //
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Starting...\n", __FUNCTION__, __LINE__));
+  return EFI_UNSUPPORTED;
+}
+
diff --git a/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/EEPROM/HobDataPei.c b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/EEPROM/HobDataPei.c
new file mode 100644
index 0000000000..6ee99d512e
--- /dev/null
+++ b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/EEPROM/HobDataPei.c
@@ -0,0 +1,123 @@
+/** @file
+  Memory EEPROM raw data library instance.
+
+  Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "EepromDataEepromLib.h"
+#include <PiPei.h>
+#include <Library/HobLib.h>
+
+EFI_STATUS
+EFIAPI
+GetEepromDataHobData (VOID)
+{
+  //
+  // Not supported in PEI.
+  //
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Starting...\n", __FUNCTION__, __LINE__));
+  return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+EFIAPI
+SetEepromDataHobData (VOID)
+{
+  UINT8                        *BlockData;
+  UINT16                        BlockNumber;
+  UINT16                        BlockSize;
+  UINT8                        *ImageData;
+  UINT32                        ImageSize;
+  EEPROM_MEMORY_HOB_HEADER     *MemoryHobHeader;
+  UINT32                        Offset;
+  EFI_STATUS                    Status;
+
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Starting...\n", __FUNCTION__, __LINE__));
+
+  //
+  // Initialize variables
+  //
+  BlockData = NULL;
+  ImageData = (UINT8 *) (UINTN) PcdGet64 (PcdEepromMemoryPointer);
+  ImageSize = PcdGet32 (PcdEepromMemorySize);
+  Status    = EFI_SUCCESS;
+
+  if (!PcdGetBool (PcdEepromMemoryHobPresent) && (ImageData != NULL) && (ImageSize != 0)) {
+    //
+    // No HOB yet. Create one.
+    //
+    BlockNumber = 0;
+    Offset      = 0;
+    while (ImageSize > 0) {
+      //
+      // Adjust block size
+      //
+      if (ImageSize > EEPROM_HOB_MAX_DATA_SIZE) {
+        BlockSize = EEPROM_HOB_MAX_DATA_SIZE;
+      } else {
+        BlockSize = (UINT16) ImageSize;
+      }
+
+      //
+      // Create Block data buffer
+      //
+      BlockData = EepromFreePool (BlockData);
+      BlockData = EepromAllocatePool (BlockSize + sizeof (EEPROM_MEMORY_HOB_HEADER));
+      if (BlockData == NULL) {
+        DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Unable to allocate buffer!\n", __FUNCTION__, __LINE__));
+        Status = EFI_OUT_OF_RESOURCES;
+        goto Exit;
+      }
+
+      //
+      // Setup header
+      //
+      MemoryHobHeader = (EEPROM_MEMORY_HOB_HEADER *) BlockData;
+      MemoryHobHeader->Signature   = EEPROM_HOB_HEADER_SIGNATURE;
+      MemoryHobHeader->Version     = EEPROM_HOB_HEADER_VERSION;
+      MemoryHobHeader->BlockNumber = BlockNumber;
+      MemoryHobHeader->BlockSize   = BlockSize;
+      MemoryHobHeader->Reserved    = 0x00000000;
+
+      //
+      // Copy data into buffer
+      //
+      CopyMem (
+        (BlockData + sizeof (EEPROM_MEMORY_HOB_HEADER)),
+        (ImageData + Offset),
+        (BlockSize + sizeof (EEPROM_MEMORY_HOB_HEADER))
+        );
+
+      //
+      // Create GUID HOB
+      //
+      BuildGuidDataHob (&gEepromVariableGuid, BlockData, BlockSize);
+
+      //
+      // Adjust pointers and such
+      //
+      Offset      += BlockSize;
+      BlockNumber += 1;
+      ImageSize   -= BlockSize;
+    }
+
+    //
+    // Toggle flag.
+    //
+    PcdSetBool (PcdEepromMemoryHobPresent, TRUE);
+  }
+
+Exit:
+  BlockData = EepromFreePool (BlockData);
+  return Status;
+}
+
diff --git a/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/EEPROM/I2cLib.c b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/EEPROM/I2cLib.c
new file mode 100644
index 0000000000..32f9d3f7e4
--- /dev/null
+++ b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/EEPROM/I2cLib.c
@@ -0,0 +1,1164 @@
+/** @file
+  I2C library instance.
+
+  Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.<BR>
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "I2cLib.h"
+
+//
+// List of I2C controllers
+//
+LPSS_PCI_DEVICE_INFO  mLpssPciDeviceList[] = {
+  {0, DEFAULT_PCI_BUS_NUMBER_SC, PCI_DEVICE_NUMBER_LPSS_I2C0,   PCI_FUNCTION_NUMBER_LPSS_I2C0, LPSS_I2C0_TMP_BAR0 + (LPSS_I2C_TMP_BAR0_DELTA*0), LPSS_I2C0_TMP_BAR0 + (LPSS_I2C_TMP_BAR0_DELTA*0) + LPSS_I2C_TMP_BAR1_OFFSET},
+  {0, DEFAULT_PCI_BUS_NUMBER_SC, PCI_DEVICE_NUMBER_LPSS_I2C0,   PCI_FUNCTION_NUMBER_LPSS_I2C1, LPSS_I2C0_TMP_BAR0 + (LPSS_I2C_TMP_BAR0_DELTA*1), LPSS_I2C0_TMP_BAR0 + (LPSS_I2C_TMP_BAR0_DELTA*1) + LPSS_I2C_TMP_BAR1_OFFSET},
+  {0, DEFAULT_PCI_BUS_NUMBER_SC, PCI_DEVICE_NUMBER_LPSS_I2C0,   PCI_FUNCTION_NUMBER_LPSS_I2C2, LPSS_I2C0_TMP_BAR0 + (LPSS_I2C_TMP_BAR0_DELTA*2), LPSS_I2C0_TMP_BAR0 + (LPSS_I2C_TMP_BAR0_DELTA*2) + LPSS_I2C_TMP_BAR1_OFFSET},
+  {0, DEFAULT_PCI_BUS_NUMBER_SC, PCI_DEVICE_NUMBER_LPSS_I2C0,   PCI_FUNCTION_NUMBER_LPSS_I2C3, LPSS_I2C0_TMP_BAR0 + (LPSS_I2C_TMP_BAR0_DELTA*3), LPSS_I2C0_TMP_BAR0 + (LPSS_I2C_TMP_BAR0_DELTA*3) + LPSS_I2C_TMP_BAR1_OFFSET},
+  {0, DEFAULT_PCI_BUS_NUMBER_SC, PCI_DEVICE_NUMBER_LPSS_I2C1,   PCI_FUNCTION_NUMBER_LPSS_I2C4, LPSS_I2C0_TMP_BAR0 + (LPSS_I2C_TMP_BAR0_DELTA*4), LPSS_I2C0_TMP_BAR0 + (LPSS_I2C_TMP_BAR0_DELTA*4) + LPSS_I2C_TMP_BAR1_OFFSET},
+  {0, DEFAULT_PCI_BUS_NUMBER_SC, PCI_DEVICE_NUMBER_LPSS_I2C1,   PCI_FUNCTION_NUMBER_LPSS_I2C5, LPSS_I2C0_TMP_BAR0 + (LPSS_I2C_TMP_BAR0_DELTA*5), LPSS_I2C0_TMP_BAR0 + (LPSS_I2C_TMP_BAR0_DELTA*5) + LPSS_I2C_TMP_BAR1_OFFSET},
+  {0, DEFAULT_PCI_BUS_NUMBER_SC, PCI_DEVICE_NUMBER_LPSS_I2C1,   PCI_FUNCTION_NUMBER_LPSS_I2C6, LPSS_I2C0_TMP_BAR0 + (LPSS_I2C_TMP_BAR0_DELTA*6), LPSS_I2C0_TMP_BAR0 + (LPSS_I2C_TMP_BAR0_DELTA*6) + LPSS_I2C_TMP_BAR1_OFFSET},
+  {0, DEFAULT_PCI_BUS_NUMBER_SC, PCI_DEVICE_NUMBER_LPSS_I2C1,   PCI_FUNCTION_NUMBER_LPSS_I2C7, LPSS_I2C0_TMP_BAR0 + (LPSS_I2C_TMP_BAR0_DELTA*7), LPSS_I2C0_TMP_BAR0 + (LPSS_I2C_TMP_BAR0_DELTA*7) + LPSS_I2C_TMP_BAR1_OFFSET}
+};
+#define LPSS_PCI_DEVICE_NUMBER  (sizeof (mLpssPciDeviceList) / sizeof (LPSS_PCI_DEVICE_INFO))
+
+//
+// List of I2C controller clock values
+//
+LPSS_I2C_CLOCK_SCL_INFO  mLPSS_I2C_CLOCK_SCL_INFO[] = {
+  {0x244, 0x2D0, 0x64, 0xC8, 0x06, 0x13},
+  {0x244, 0x2D0, 0x64, 0xC8, 0x06, 0x13},
+  {0x244, 0x2D0, 0x64, 0xC8, 0x06, 0x13},
+  {0x244, 0x2DA, 0x1E, 0x3C, 0x06, 0x13},
+  {0x244, 0x2DA, 0x1E, 0x50, 0x06, 0x13},
+  {0x244, 0x2D0, 0x69, 0xC8, 0x06, 0x13},
+  {0x244, 0x2D0, 0x69, 0xC8, 0x06, 0x13},
+  {0x244, 0x2D0, 0x70, 0xC8, 0x06, 0x13}
+};
+#define LPSS_I2C_CLOCK_SCL_INFO_NUMBER  (sizeof (mLPSS_I2C_CLOCK_SCL_INFO) / sizeof (LPSS_I2C_CLOCK_SCL_INFO))
+
+//
+// List of I2C controller PAD settings
+//
+BXT_GPIO_PAD_INIT  mLPSS_PAD_INFO[] = {
+  BXT_GPIO_PAD_CONF (L"GPIO_124 LPSS_I2C0_SDA", M1, NA, NA, NA, NA, Wake_Disabled, P_20K_H, NA, NA, D1RxDRx1I, EnPu, GPIO_PADBAR + 0x0000, WEST),
+  BXT_GPIO_PAD_CONF (L"GPIO_125 LPSS_I2C0_SCL", M1, NA, NA, NA, NA, Wake_Disabled, P_20K_H, NA, NA, D1RxDRx1I, EnPu, GPIO_PADBAR + 0x0008, WEST),
+  BXT_GPIO_PAD_CONF (L"GPIO_126 LPSS_I2C1_SDA", M1, NA, NA, NA, NA, Wake_Disabled, P_20K_H, NA, NA, D1RxDRx1I, EnPu, GPIO_PADBAR + 0x0010, WEST),
+  BXT_GPIO_PAD_CONF (L"GPIO_127 LPSS_I2C1_SCL", M1, NA, NA, NA, NA, Wake_Disabled, P_20K_H, NA, NA, D1RxDRx1I, EnPu, GPIO_PADBAR + 0x0018, WEST),
+  BXT_GPIO_PAD_CONF (L"GPIO_128 LPSS_I2C2_SDA", M1, NA, NA, NA, NA, Wake_Disabled, P_20K_H, NA, NA, D1RxDRx1I, EnPu, GPIO_PADBAR + 0x0020, WEST),
+  BXT_GPIO_PAD_CONF (L"GPIO_129 LPSS_I2C2_SCL", M1, NA, NA, NA, NA, Wake_Disabled, P_20K_H, NA, NA, D1RxDRx1I, EnPu, GPIO_PADBAR + 0x0028, WEST),
+  BXT_GPIO_PAD_CONF (L"GPIO_130 LPSS_I2C3_SDA", M1, NA, NA, NA, NA, Wake_Disabled, P_20K_H, NA, NA, D1RxDRx1I, EnPu, GPIO_PADBAR + 0x0030, WEST),
+  BXT_GPIO_PAD_CONF (L"GPIO_131 LPSS_I2C3_SCL", M1, NA, NA, NA, NA, Wake_Disabled, P_20K_H, NA, NA, D1RxDRx1I, EnPu, GPIO_PADBAR + 0x0038, WEST),
+  BXT_GPIO_PAD_CONF (L"GPIO_132 LPSS_I2C4_SDA", M1, NA, NA, NA, NA, Wake_Disabled, P_20K_H, NA, NA, D1RxDRx1I, EnPu, GPIO_PADBAR + 0x0040, WEST),
+  BXT_GPIO_PAD_CONF (L"GPIO_133 LPSS_I2C4_SCL", M1, NA, NA, NA, NA, Wake_Disabled, P_20K_H, NA, NA, D1RxDRx1I, EnPu, GPIO_PADBAR + 0x0048, WEST),
+  BXT_GPIO_PAD_CONF (L"GPIO_134 LPSS_I2C5_SDA", M1, NA, NA, NA, NA, Wake_Disabled, P_20K_H, NA, NA, D1RxDRx1I, EnPu, GPIO_PADBAR + 0x0050, WEST),
+  BXT_GPIO_PAD_CONF (L"GPIO_135 LPSS_I2C5_SCL", M1, NA, NA, NA, NA, Wake_Disabled, P_20K_H, NA, NA, D1RxDRx1I, EnPu, GPIO_PADBAR + 0x0058, WEST),
+  BXT_GPIO_PAD_CONF (L"GPIO_136 LPSS_I2C6_SDA", M1, NA, NA, NA, NA, Wake_Disabled, P_20K_H, NA, NA, D1RxDRx1I, EnPu, GPIO_PADBAR + 0x0060, WEST),
+  BXT_GPIO_PAD_CONF (L"GPIO_137 LPSS_I2C6_SCL", M1, NA, NA, NA, NA, Wake_Disabled, P_20K_H, NA, NA, D1RxDRx1I, EnPu, GPIO_PADBAR + 0x0068, WEST),
+  BXT_GPIO_PAD_CONF (L"GPIO_138 LPSS_I2C7_SDA", M1, NA, NA, NA, NA, Wake_Disabled, P_20K_H, NA, NA, D0RxDRx0I, EnPu, GPIO_PADBAR + 0x0070, WEST),
+  BXT_GPIO_PAD_CONF (L"GPIO_139 LPSS_I2C7_SCL", M1, NA, NA, NA, NA, Wake_Disabled, P_20K_H, NA, NA, D0RxDRx0I, EnPu, GPIO_PADBAR + 0x0078, WEST)
+};
+
+BOOLEAN   gI2cDebugFlag = FALSE;
+
+////
+//// Internal I2C functions
+////
+//
+//  Desc:   Clears the interrupts on this I2C controller
+//  Input:  I2cBaseAddress        - Pointer to the MMIO base address for the I2C controller
+//  Output: NA
+//
+VOID
+I2cClearInterrupts (
+  IN UINT32       I2cBaseAddress
+  )
+{
+  MmioRead32 (I2cBaseAddress + R_IC_CLR_INTR);
+  return;
+}
+
+//
+//  Desc:   Clears the TX Abort on this I2C controller
+//  Input:  I2cBaseAddress        - Pointer to the MMIO base address for the I2C controller
+//  Output: NA
+//
+VOID
+I2cClearTxAbort (
+  IN UINT32       I2cBaseAddress
+  )
+{
+  MmioRead32 (I2cBaseAddress + R_IC_CLR_TX_ABRT);
+  return;
+}
+
+//
+//  Desc:   Disable this I2C controller
+//  Input:  I2cBaseAddress        - Pointer to the MMIO base address for the I2C controller
+//  Output: Status                - EFI_SUCCESS   - I2C host controller is completely inactive
+//                                  EFI_NOT_READY - I2C host controller is still in an enabled state
+//
+EFI_STATUS
+I2cDisable (
+  IN UINT32       I2cBaseAddress
+  )
+{
+  UINT32       NumTries;
+  EFI_STATUS   Status;
+
+  //
+  // Initialize variables
+  //
+  Status = EFI_SUCCESS;
+
+  //
+  // Disable I2C controller
+  //
+  MmioWrite32 (I2cBaseAddress + R_IC_ENABLE, 0);
+  NumTries = 10000;   // 0.1 seconds
+  while (0 != (MmioRead32 (I2cBaseAddress + R_IC_ENABLE_STATUS) & 0x03)) {
+    MicroSecondDelay (10);
+    NumTries --;
+    if (0 == NumTries) {
+      Status = EFI_NOT_READY;
+      goto Exit;
+    }
+  }
+
+Exit:
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - Ending with %r\n", __FUNCTION__, __LINE__, Status));
+  }
+  return Status;
+}
+
+/**
+  Enable I2C host controller
+
+  @param[in]  I2CBaseAddress    - BAR0 address of I2C host controller
+
+  @retval EFI_SUCCESS           - I2C host controller is in an enabled state.
+  @retval EFI_NOT_READY         - I2C host controller is still inactive.
+**/
+EFI_STATUS
+I2cEnable (
+  IN UINT32       I2cBaseAddress
+  )
+{
+  UINT32       NumTries;
+  EFI_STATUS   Status;
+
+  //
+  // Initialize variables
+  //
+  NumTries = 10000;   // 0.1 seconds
+  Status   = EFI_SUCCESS;
+
+  //
+  // Enable I2C controller
+  //
+  MmioWrite32 (I2cBaseAddress + R_IC_ENABLE, I2C_ENABLE_ENABLE);
+  while (I2C_ENABLE_ENABLE != (MmioRead32 (I2cBaseAddress + R_IC_ENABLE_STATUS) & I2C_ENABLE_ENABLE)) {
+    MicroSecondDelay (10);
+    NumTries --;
+    if (0 == NumTries) {
+      Status = EFI_NOT_READY;
+      goto Exit;
+    }
+  }
+
+Exit:
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - Ending with %r\n", __FUNCTION__, __LINE__, Status));
+  }
+  return Status;
+}
+
+UINT16
+I2cGetTxAbortStatus (
+  IN UINT32       I2cBaseAddress
+  )
+{
+  UINT16   TxAbortStatus;
+
+  if (I2cBaseAddress == 0) {
+    TxAbortStatus = 0xFFFF;
+  } else {
+    TxAbortStatus = (UINT16) (MmioRead32 (I2cBaseAddress + R_IC_TX_ABRT_SOURCE) & 0xFFFF);
+  }
+  return TxAbortStatus;
+}
+
+/**
+  Get I2C controller raw interrupt status
+
+  @param[in]  I2CBaseAddress    - BAR0 address of I2C host controller
+
+  @retval UINT16                - Raw interrupt status bit flags
+**/
+UINT16
+I2cGetRawStatus (
+  IN UINT32       I2cBaseAddress
+  )
+{
+  UINT16   RawStatus;
+
+  if (I2cBaseAddress == 0) {
+    RawStatus = 0xFFFF;
+  } else {
+    RawStatus = (UINT16) (MmioRead32 (I2cBaseAddress + R_IC_RAW_INTR_STAT) & 0x3FFF);
+  }
+
+  return RawStatus;
+}
+
+/**
+  Get I2C controller RX FIFO count
+
+  @param[in]  I2CBaseAddress    - BAR0 address of I2C host controller
+
+  @retval UINT16                - RX FIFO count
+**/
+UINT16
+I2cGetRxFifo (
+  IN UINT32       I2cBaseAddress
+  )
+{
+  UINT16   RxFifo;
+
+  if (I2cBaseAddress == 0) {
+    RxFifo = 0xFFFF;
+  } else {
+    RxFifo = (UINT16) (MmioRead32 (I2cBaseAddress + R_IC_RXFLR) & 0x01FF);
+  }
+
+  return RxFifo;
+}
+
+/**
+  Get I2C controller status
+
+  @param[in]  I2CBaseAddress    - BAR0 address of I2C host controller
+
+  @retval UINT16                - Status bit flags
+**/
+UINT16
+I2cGetStatus (
+  IN UINT32       I2cBaseAddress
+  )
+{
+  UINT16   I2cStatus;
+
+  if (I2cBaseAddress == 0) {
+    I2cStatus = 0xFFFF;
+  } else {
+    I2cStatus = (UINT16) (MmioRead32 (I2cBaseAddress + R_IC_STATUS) & 0x007F);
+  }
+
+  return I2cStatus;
+}
+
+/**
+  Get I2C controller TX FIFO count
+
+  @param[in]  I2CBaseAddress    - BAR0 address of I2C host controller
+
+  @retval UINT16                - TX FIFO count
+**/
+UINT16
+I2cGetTxFifo (
+  IN UINT32       I2cBaseAddress
+  )
+{
+  UINT16   TxFifo;
+
+  if (I2cBaseAddress == 0) {
+    TxFifo = 0xFFFF;
+  } else {
+    TxFifo = (UINT16) (MmioRead32 (I2cBaseAddress + R_IC_TXFLR) & 0x01FF);
+  }
+
+  return TxFifo;
+}
+
+EFI_STATUS
+I2cProgramPad (
+  IN   UINT8   Bus
+  )
+{
+  UINT8        index;
+  EFI_STATUS   Status;
+
+  if (gI2cDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Programming PADs for bus #%d\n", __FUNCTION__, __LINE__, Bus));
+
+  //
+  // Initialize variables
+  //
+  Status = EFI_SUCCESS;
+
+  //
+  // Sanity checks
+  //
+  if (Bus > MAX_I2C_BUS) {
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+
+  //
+  // Program SDA/SCL
+  //
+  for (index = 0; index < 2; index++) {
+    if (gI2cDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Programming PAD %s\n", __FUNCTION__, __LINE__, mLPSS_PAD_INFO[(Bus * 2) + index].pad_name));
+    GpioPadConfigTable (1, &mLPSS_PAD_INFO[(Bus * 2) + index]);
+  }
+
+  //
+  // Pause a bit
+  //
+  MicroSecondDelay (EEPROM_ROUTINE_DELAY);
+
+Exit:
+  return Status;
+}
+
+/**
+  Set the I2C controller bus clock frequency.
+
+  The software and controller do a best case effort of using the specified
+  frequency for the I2C bus.  If the frequency does not match exactly then
+  the controller will use a slightly lower frequency for the I2C to avoid
+  exceeding the operating conditions for any of the I2C devices on the bus.
+  For example if 400 KHz was specified and the controller's divide network
+  only supports 402 KHz or 398 KHz then the controller would be set to 398
+  KHz.  However if the desired frequency is 400 KHz and the controller only
+  supports 1 MHz and 100 KHz then this routine would return EFI_UNSUPPORTED.
+
+  @param[in]  Bus               - I2C Bus number to which the I2C device has been connected
+  @param[in]  I2CBaseAddress    - BAR0 address of I2C host controller
+
+  @retval EFI_SUCCESS           - The bus frequency was set successfully.
+**/
+EFI_STATUS
+I2cSetBusFrequency (
+  IN  UINT8    Bus,
+  IN  UINT32   I2cBaseAddress
+  )
+{
+  EFI_STATUS   Status;
+
+  //
+  // Initialize variables
+  //
+  Status = EFI_SUCCESS;
+
+  if (gI2cDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - I2cBusFrequencySet bus: %d\n", __FUNCTION__, __LINE__, Bus));
+  ASSERT ((Bus < LPSS_I2C_CLOCK_SCL_INFO_NUMBER));
+  //
+  //  Set the 100 KHz clock divider according to SV result and I2C spec
+  //
+  MmioWrite32 (I2cBaseAddress + R_IC_SS_SCL_HCNT, (UINT16) mLPSS_I2C_CLOCK_SCL_INFO[Bus].SS_SCL_HCNT);
+  MmioWrite32 (I2cBaseAddress + R_IC_SS_SCL_LCNT, (UINT16) mLPSS_I2C_CLOCK_SCL_INFO[Bus].SS_SCL_LCNT);
+  if (gI2cDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - I2cBusFrequencySet R_IC_SS_SCL_HCNT: 0x%08X, R_IC_SS_SCL_LCNT: 0x%08X\r\n",
+                       __FUNCTION__,
+                       __LINE__,
+                       MmioRead32 (I2cBaseAddress + R_IC_SS_SCL_HCNT),
+                       MmioRead32 (I2cBaseAddress + R_IC_SS_SCL_LCNT)));
+  //
+  //  Set the 400 KHz clock divider according to SV result and I2C spec
+  //
+  MmioWrite32 (I2cBaseAddress + R_IC_FS_SCL_HCNT, (UINT16) mLPSS_I2C_CLOCK_SCL_INFO[Bus].FS_SCL_HCNT);
+  MmioWrite32 (I2cBaseAddress + R_IC_FS_SCL_LCNT, (UINT16) mLPSS_I2C_CLOCK_SCL_INFO[Bus].FS_SCL_LCNT);
+  if (gI2cDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - I2cBusFrequencySet R_IC_FS_SCL_HCNT: 0x%08X, R_IC_FS_SCL_LCNT: 0x%08X\r\n",
+                       __FUNCTION__,
+                       __LINE__,
+                       MmioRead32 (I2cBaseAddress + R_IC_FS_SCL_HCNT),
+                       MmioRead32 (I2cBaseAddress + R_IC_FS_SCL_LCNT)));
+  //
+  //  Set the 3.4MHz clock divider according to SV result and I2C spec
+  //
+  MmioWrite32 (I2cBaseAddress + R_IC_HS_SCL_HCNT, (UINT16)mLPSS_I2C_CLOCK_SCL_INFO[Bus].HS_SCL_HCNT);
+  MmioWrite32 (I2cBaseAddress + R_IC_HS_SCL_LCNT, (UINT16)mLPSS_I2C_CLOCK_SCL_INFO[Bus].HS_SCL_LCNT);
+  if (gI2cDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - I2cBusFrequencySet R_IC_HS_SCL_HCNT: 0x%08X, R_IC_HS_SCL_LCNT: 0x%08X\r\n",
+                       __FUNCTION__,
+                       __LINE__,
+                       MmioRead32 (I2cBaseAddress + R_IC_HS_SCL_HCNT),
+                       MmioRead32 (I2cBaseAddress + R_IC_HS_SCL_LCNT)));
+
+  //
+  // Set hold register
+  //
+  MmioWrite32 (I2cBaseAddress + R_IC_SDA_HOLD, (UINT16) 0x06);
+  if (gI2cDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - I2cBusFrequencySet R_IC_SDA_HOLD: 0x%08X\r\n", __FUNCTION__, __LINE__, MmioRead32 (I2cBaseAddress + R_IC_SDA_HOLD)));
+
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - Ending with %r\n", __FUNCTION__, __LINE__, Status));
+  }
+  return Status;
+}
+
+/**
+  Program LPSS I2C PCI controller's BAR0 and enable memory decode.
+
+  @param[in]  Bus               - I2C Bus number to which the I2C device has been connected
+
+  @retval EFI_SUCCESS           - I2C controller's BAR0 is programmed and memory decode enabled.
+  @retval EFI_NOT_READY         - I2C controller's is not exist or its function has been disabled.
+  @retval EFI_DEVICE_ERROR      - I2C controller can't be enabled.
+**/
+EFI_STATUS
+ProgramPciLpssI2C (
+  IN UINT8        Bus
+  )
+{
+  UINT32       Data32;
+  UINT32       I2CBar0;
+  UINT32       I2CBar1;
+  UINTN        PciMmBase;
+  UINT32       PmcBase;
+  EFI_STATUS   Status;
+  UINT32       I2cPortDisable[] = {
+    B_PMC_FUNC_DIS_LPSS_I2C0,
+    B_PMC_FUNC_DIS_LPSS_I2C1,
+    B_PMC_FUNC_DIS_LPSS_I2C2,
+    B_PMC_FUNC_DIS_LPSS_I2C3,
+    B_PMC_FUNC_DIS_LPSS_I2C4,
+    B_PMC_FUNC_DIS_LPSS_I2C5,
+    B_PMC_FUNC_DIS_LPSS_I2C6,
+    B_PMC_FUNC_DIS_LPSS_I2C7
+  };
+
+  //
+  // Initialize variables
+  //
+  PciMmBase = 0;
+  Status    = EFI_SUCCESS;
+
+  //
+  // Set PADs to I2C mode
+  //
+  I2cProgramPad (Bus);
+
+  //
+  // Check PMC disable register
+  //
+  PmcBase = PMC_BASE_ADDRESS;
+  Data32  = MmioRead32 (PmcBase + R_PMC_FUNC_DIS);
+
+  if (Data32 == 0xFFFFFFFF) {
+    if (gI2cDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - ProgramPciLpssI2C() PMC disable register not available. [%08x]\n", __FUNCTION__, __LINE__, PMC_BASE_ADDRESS));
+  } else {
+    if ((Data32 & I2cPortDisable[Bus]) != 0) {
+      // This I2C port is disabled. Turn it on.
+      Data32 &= ~I2cPortDisable[Bus];
+      MmioWrite32 (PmcBase + R_PMC_FUNC_DIS, Data32);
+      if (gI2cDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - ProgramPciLpssI2C() enable I2C controller #%x\n", __FUNCTION__, __LINE__, Bus));
+      // Make sure it took.
+      if (Data32 != MmioRead32 (PmcBase + R_PMC_FUNC_DIS)) {
+        DEBUG ((DEBUG_ERROR, "%a (#%4d) - ProgramPciLpssI2C() failed to enable I2C controller #%x [%08x:%08x]\n",
+            __FUNCTION__,
+            __LINE__,
+            Bus,
+            Data32,
+            MmioRead32 (PmcBase + R_PMC_FUNC_DIS)));
+        Status = EFI_DEVICE_ERROR;
+        goto Exit;
+      }
+    }
+  }
+
+  if (gI2cDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - ProgramPciLpssI2C()------------BusNo=%x\n", __FUNCTION__, __LINE__, Bus));
+
+  PciMmBase = MmPciAddress (
+                mLpssPciDeviceList[Bus].Segment,
+                mLpssPciDeviceList[Bus].BusNum,
+                mLpssPciDeviceList[Bus].DeviceNum,
+                mLpssPciDeviceList[Bus].FunctionNum,
+                0
+                );
+  if (gI2cDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Program Pci Lpss I2C Device  %x %x %x PciMmBase:%x\n",
+                       __FUNCTION__,
+                       __LINE__,
+                       mLpssPciDeviceList[Bus].BusNum,
+                       mLpssPciDeviceList[Bus].DeviceNum,
+                       mLpssPciDeviceList[Bus].FunctionNum, PciMmBase));
+
+  //
+  // Check if device present
+  //
+  if (MmioRead32 (PciMmBase) != 0xFFFFFFFF) {
+    if ((MmioRead32 (PciMmBase + R_LPSS_IO_STSCMD) & B_LPSS_IO_STSCMD_MSE)) {
+      //
+      // In Pei stage, we always disable Bus master, and memory space enabling for BAR re-programming
+      // In DXE stage, will read existing BAR value instead of re-programming
+      //
+      I2CBar0 = MmioRead32 (PciMmBase + R_LPSS_IO_BAR) & B_LPSS_IO_BAR_BA;
+      I2CBar1 = MmioRead32 (PciMmBase + R_LPSS_IO_BAR1) & B_LPSS_IO_BAR_BA;
+      if ((I2CBar0 != (UINT32) mLpssPciDeviceList[Bus].Bar0) || (I2CBar1 != (UINT32) mLpssPciDeviceList[Bus].Bar1)) {
+        mLpssPciDeviceList[Bus].Bar0 = MmioRead32 (PciMmBase + R_LPSS_IO_BAR) & B_LPSS_IO_BAR_BA;     // get the address allocated.
+        mLpssPciDeviceList[Bus].Bar1 = MmioRead32 (PciMmBase + R_LPSS_IO_BAR1) & B_LPSS_IO_BAR_BA;
+        if (gI2cDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Get bar0:0x%x bar1:0x%x\n",
+                             __FUNCTION__,
+                             __LINE__,
+                             mLpssPciDeviceList[Bus].Bar0,
+                             mLpssPciDeviceList[Bus].Bar1));
+      }
+    } else {
+      //
+      // Program BAR 0
+      //
+      ASSERT (((mLpssPciDeviceList[Bus].Bar0 & B_LPSS_IO_BAR_BA) == mLpssPciDeviceList[Bus].Bar0) && (mLpssPciDeviceList[Bus].Bar0 != 0));
+      MmioWrite32 ((UINTN) (PciMmBase + R_LPSS_IO_BAR), (UINT32) (mLpssPciDeviceList[Bus].Bar0 & B_LPSS_IO_BAR_BA));
+      //
+      // Program BAR 1
+      //
+      ASSERT (((mLpssPciDeviceList[Bus].Bar1 & B_LPSS_IO_BAR1_BA) == mLpssPciDeviceList[Bus].Bar1) && (mLpssPciDeviceList[Bus].Bar1 != 0));
+      MmioWrite32 ((UINTN) (PciMmBase + R_LPSS_IO_BAR1), (UINT32) (mLpssPciDeviceList[Bus].Bar1 & B_LPSS_IO_BAR1_BA));
+      //
+      // Bus Master Enable & Memory Space Enable
+      //
+      MmioOr32 ((UINTN) (PciMmBase + R_LPSS_IO_STSCMD), (UINT32) (B_LPSS_IO_STSCMD_BME | B_LPSS_IO_STSCMD_MSE));
+      ASSERT (MmioRead32 (mLpssPciDeviceList[Bus].Bar0) != 0xFFFFFFFF);
+    }
+
+    //
+    // Release Resets
+    //
+    MmioWrite32 (mLpssPciDeviceList[Bus].Bar0 + R_LPSS_IO_MEM_RESETS, B_LPSS_IO_MEM_HC_RESET_REL | B_LPSS_IO_MEM_iDMA_RESET_REL);
+
+    if (gI2cDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - ProgramPciLpssI2C() Programmed()\n", __FUNCTION__, __LINE__));
+    Status = EFI_SUCCESS;
+    goto Exit;
+  } else {
+     DEBUG ((DEBUG_ERROR, "%a (#%4d) - Pci Lpss I2C Device  %x %x %x does not exist!\n",
+       __FUNCTION__,
+       __LINE__,
+       mLpssPciDeviceList[Bus].BusNum,
+       mLpssPciDeviceList[Bus].DeviceNum,
+       mLpssPciDeviceList[Bus].FunctionNum));
+
+     Status = EFI_NOT_READY;
+     goto Exit;
+  }
+
+Exit:
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - Ending with %r\n", __FUNCTION__, __LINE__, Status));
+  }
+  return Status;
+}
+
+////
+//// Public I2C functions
+////
+//
+//  Desc:   Initializes the controller and returns the MMIO base address
+//  Input:  Bus                   - I2C controller, 0 based
+//          Address               - 7-bit slave address
+//          Speed                 - Uses the I2C_SPEED enum to set the controller speed
+//          I2cBaseAddress        - Pointer to the MMIO base address for the I2C controller
+//  Output: EFI_SUCCESS           - Initialization completed successfully
+//          EFI_DEVICE_ERROR      - I2C controller error
+//          EFI_INVALID_PARAMETER - Invalid input parameter
+//
+EFI_STATUS
+I2cInit (
+  IN       UINT8     Bus,
+  IN       UINT16    Address,
+  IN       UINT8     Speed,
+  IN OUT   UINT32   *I2cBaseAddress
+  )
+{
+  UINT32       BaseAddress;
+  UINTN        PciMmBase;
+  EFI_STATUS   Status;
+
+  //
+  //  Sanity checks
+  //
+  if (Bus > MAX_I2C_BUS) {
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  if (Address > MAX_I2C_ADDRESS) {
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  if (Speed > Max_Speed) {
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  if (I2cBaseAddress == NULL) {
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+
+  //
+  // Initialize variables
+  //
+  *I2cBaseAddress = 0;
+
+  //
+  // Get current MMIO base address
+  //
+  PciMmBase = MmPciAddress (
+                mLpssPciDeviceList[Bus].Segment,
+                mLpssPciDeviceList[Bus].BusNum,
+                mLpssPciDeviceList[Bus].DeviceNum,
+                mLpssPciDeviceList[Bus].FunctionNum,
+                0
+                );
+  BaseAddress = MmioRead32 (PciMmBase + R_LPSS_IO_BAR) & B_LPSS_IO_BAR_BA;
+  if (gI2cDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - I2CBaseAddress = 0x%08x:0x%08x \n", __FUNCTION__, __LINE__, BaseAddress, (UINT32) mLpssPciDeviceList[Bus].Bar0));
+
+  //
+  // Skip reinit if targeting the same I2C bus
+  //
+  if (BaseAddress == (UINT32) mLpssPciDeviceList[Bus].Bar0) {
+    MmioWrite32 (BaseAddress + R_IC_TAR, Address);
+    *I2cBaseAddress = BaseAddress;
+    Status = EFI_SUCCESS;
+    goto Exit;
+  }
+
+  //
+  // Program I2C controller
+  //
+  Status = ProgramPciLpssI2C (Bus);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - ProgramPciLpssI2C failed! %r\n", __FUNCTION__, __LINE__, Status));
+    goto Exit;
+  }
+
+  //
+  // Retrieve I2C MMIO base address
+  //
+  BaseAddress = (UINT32) mLpssPciDeviceList[Bus].Bar0;
+  if (gI2cDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - I2CBaseAddress = 0x%x \n", __FUNCTION__, __LINE__, BaseAddress));
+
+  //
+  // Reset controller
+  //
+  Status = I2cReset (BaseAddress, Bus, Address, Speed);
+  if (EFI_ERROR (Status)) {
+    goto Exit;
+  }
+
+  //
+  // Pause a bit
+  //
+  MicroSecondDelay (EEPROM_ROUTINE_DELAY);
+
+  //
+  // Pass out MMIO base
+  //
+  *I2cBaseAddress = BaseAddress;
+  Status = EFI_SUCCESS;
+
+Exit:
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - Ending with %r\n", __FUNCTION__, __LINE__, Status));
+  }
+  return Status;
+}
+
+//
+//  Desc:   Polls the I2C controller with reads until it responds.
+//  Input:  I2cBaseAddress        - Pointer to the MMIO base address for the I2C controller
+//  Output: EFI_SUCCESS           - Initialization completed successfully
+//          EFI_DEVICE_ERROR      - I2C controller error
+//
+EFI_STATUS
+I2cPoll (
+  IN       UINT32     I2cBaseAddress
+  )
+{
+  EFI_STATUS   Status;
+  UINT16       Timeout;
+  UINT8        Value;
+
+  //
+  // Use a read to poll the slave
+  //
+  Status  = EFI_DEVICE_ERROR;
+  Timeout = 0;
+  while (EFI_ERROR (Status) && Timeout < 1000) {
+    MicroSecondDelay (10);
+    Status = I2cRead (I2cBaseAddress, &Value, TRUE, TRUE);
+    Timeout++;
+  }
+
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - Ending with %r\n", __FUNCTION__, __LINE__, Status));
+  }
+  return Status;
+}
+
+//
+//  Desc:   Read a byte from the I2C controller
+//  Input:  I2cBaseAddress        - MMIO base address for the I2C controller
+//          Data                  - Pointer to where to store the data
+//          Start                 - Send start bit?
+//          End                   - Send end bit?
+//  Output: EFI_SUCCESS           - Read completed successfully
+//          EFI_DEVICE_ERROR      - I2C controller error
+//          EFI_INVALID_PARAMETER - Invalid input parameter
+//
+EFI_STATUS
+I2cRead (
+  IN       UINT32     I2cBaseAddress,
+  IN OUT   UINT8     *Data,
+  IN       BOOLEAN    Start,
+  IN       BOOLEAN    End
+  )
+{
+  UINT32      Data32;
+  EFI_STATUS  Status;
+
+  if (gI2cDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Starting\n", __FUNCTION__, __LINE__));
+
+  //
+  // Sanity checks
+  //
+  if (Data == NULL) {
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+
+  //
+  // Send CMD for read
+  //
+  Data32 = B_READ_CMD;
+  Status = I2cSendCommand (I2cBaseAddress, &Data32, Start, End);
+  *Data  = (UINT8) (Data32 & 0xFF);
+
+Exit:
+  //
+  // Pause a bit
+  //
+  MicroSecondDelay (EEPROM_ROUTINE_DELAY);
+  //
+  // Display error messages
+  //
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - Ending with %r\n", __FUNCTION__, __LINE__, Status));
+  }
+  return Status;
+}
+
+//
+//  Desc:   Resets the I2C controller into a known good state
+//  Input:  I2cBaseAddress        - MMIO base address for the I2C controller
+//          Bus                   - I2C controller, 0 based
+//          Address               - 7-bit slave address
+//          Speed                 - Uses the I2C_SPEED enum to set the controller speed
+//  Output: EFI_SUCCESS           - Write completed successfully
+//          EFI_DEVICE_ERROR      - I2C controller error
+//          EFI_INVALID_PARAMETER - Invalid input parameter
+//
+EFI_STATUS
+I2cReset (
+  IN       UINT32    I2cBaseAddress,
+  IN       UINT8     Bus,
+  IN       UINT16    Address,
+  IN       UINT8     Speed
+  )
+{
+  UINT16       I2cMode;
+  UINT32       NumTries;
+  EFI_STATUS   Status;
+
+  //
+  // Wait for master activity to stop
+  //
+  NumTries = 10000; // 1 seconds
+  while ((STAT_MST_ACTIVITY == (I2cGetStatus (I2cBaseAddress) & STAT_MST_ACTIVITY))) {
+    MicroSecondDelay (10);
+    NumTries--;
+    if (0 == NumTries) {
+      DEBUG ((DEBUG_ERROR, "%a(#%4d) - Try timeout\n", __FUNCTION__, __LINE__));
+      Status = EFI_DEVICE_ERROR;
+      goto Exit;
+    }
+  }
+  //
+  // Abort controller
+  //
+  MmioWrite32 (I2cBaseAddress + R_IC_ENABLE, I2C_ENABLE_ABORT);
+  MicroSecondDelay (10 * EEPROM_ROUTINE_DELAY);
+  //
+  // Disable I2C controller
+  //
+  Status = I2cDisable (I2cBaseAddress);
+  if (gI2cDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - I2cDisable Status = %r\n", __FUNCTION__, __LINE__, Status));
+  if (EFI_ERROR (Status)) {
+    goto Exit;
+  }
+  MicroSecondDelay (EEPROM_ROUTINE_DELAY);
+  //
+  // Set I2C controller speed
+  //
+  I2cSetBusFrequency (Bus, I2cBaseAddress); // Set I2cMode
+  MicroSecondDelay (EEPROM_ROUTINE_DELAY);
+  switch (Speed) {
+    case Standard_Speed:
+      //100K
+      I2cMode = V_SPEED_STANDARD;
+      break;
+
+    case Fast_Speed:
+      //400K
+      I2cMode = V_SPEED_FAST;
+      break;
+
+    case High_Speed:
+      //3.4M
+      I2cMode = V_SPEED_HIGH;
+      break;
+
+    default:
+      //400K
+      I2cMode = V_SPEED_FAST;
+  }
+  I2cMode |= B_IC_RESTART_EN | B_IC_SLAVE_DISABLE | B_MASTER_MODE;
+  //
+  // Set slave address
+  //
+  MmioWrite32 (I2cBaseAddress + R_IC_INTR_MASK, 0x0);
+  if (Address > MAX_I2C_ADDRESS) {
+    Address = (Address & 0x3FF) | IC_TAR_10BITADDR_MASTER;
+  }
+  MmioWrite32 (I2cBaseAddress + R_IC_TAR, Address);
+  MicroSecondDelay (EEPROM_ROUTINE_DELAY);
+  //
+  // Set RX & TX FIFO full threshold to 1 byte
+  //
+  MmioWrite32 (I2cBaseAddress + R_IC_RX_TL, 0);
+  MmioWrite32 (I2cBaseAddress + R_IC_TX_TL, 0);
+  MicroSecondDelay (EEPROM_ROUTINE_DELAY);
+  //
+  // Set I2C Mode
+  //
+  MmioWrite32 (I2cBaseAddress + R_IC_CON, I2cMode);
+  if (gI2cDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - I2cMode: 0x%04x\r\n", __FUNCTION__, __LINE__, I2cMode));
+  MicroSecondDelay (EEPROM_ROUTINE_DELAY);
+  //
+  // Enable I2C controller
+  //
+  Status = I2cEnable (I2cBaseAddress);
+  if (gI2cDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - I2cEnable Status = %r\n", __FUNCTION__, __LINE__, Status));
+  if (EFI_ERROR (Status)) {
+    goto Exit;
+  }
+  MicroSecondDelay (EEPROM_ROUTINE_DELAY);
+  //
+  // Clear TX abort
+  //
+  I2cClearTxAbort (I2cBaseAddress);
+  MicroSecondDelay (EEPROM_ROUTINE_DELAY);
+  //
+  // Clear interrupts
+  //
+  I2cClearInterrupts (I2cBaseAddress);
+  MicroSecondDelay (EEPROM_ROUTINE_DELAY);
+
+Exit:
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - Ending with %r\n", __FUNCTION__, __LINE__, Status));
+  }
+  return Status;
+}
+
+//
+//  Desc:   Write a byte to the I2C controller
+//  Input:  I2cBaseAddress        - MMIO base address for the I2C controller
+//          Data                  - Data from the I2C controller
+//          Start                 - Send start bit?
+//          End                   - Send end bit?
+//  Output: EFI_SUCCESS           - Write completed successfully
+//          EFI_DEVICE_ERROR      - I2C controller error
+//          EFI_INVALID_PARAMETER - Invalid input parameter
+//
+EFI_STATUS
+I2cSendCommand (
+  IN       UINT32     I2cBaseAddress,
+  IN       UINT32    *Data,
+  IN       BOOLEAN    Start,
+  IN       BOOLEAN    End
+  )
+{
+  BOOLEAN     CommandSent;
+  UINT32      Count;
+  UINT32      CountOut;
+  UINT32      Data32;
+  BOOLEAN     ReadFlag;
+  EFI_STATUS  Status;
+  UINT16      TxAbortStatus;
+
+  //
+  // Initialize variables
+  //
+  CommandSent = FALSE;
+  Count       = 0;
+  CountOut    = 0x00000100;
+  Status      = EFI_NOT_READY;
+  if ((*Data & B_READ_CMD) == B_READ_CMD) {
+    ReadFlag = TRUE;
+  } else {
+    ReadFlag = FALSE;
+  }
+
+  //
+  // Send a command byte
+  //
+  while (CountOut-- > 0) {
+    //
+    // Check for NACK
+    //
+    if ((I2cGetRawStatus (I2cBaseAddress) & I2C_INTR_TX_ABRT) != 0) {
+      TxAbortStatus = I2cGetTxAbortStatus (I2cBaseAddress);
+      DEBUG ((DEBUG_ERROR, "%a (#%4d) - TX ABRT [%04x]\n", __FUNCTION__, __LINE__, TxAbortStatus));
+      if (gI2cDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - RX FIFO = %04x\n", __FUNCTION__, __LINE__, I2cGetRxFifo (I2cBaseAddress)));
+      if (gI2cDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - TX FIFO = %04x\n", __FUNCTION__, __LINE__, I2cGetTxFifo (I2cBaseAddress)));
+      //
+      // Clear TX Abort
+      //
+      I2cClearTxAbort (I2cBaseAddress);
+      MicroSecondDelay (EEPROM_WRITE_TIMEOUT);
+      //
+      // Clear interrupts
+      //
+      I2cClearInterrupts (I2cBaseAddress);
+      MicroSecondDelay (EEPROM_WRITE_TIMEOUT);
+      //
+      // Set status
+      //
+      if (TxAbortStatus & (I2C_ABRT_7B_ADDR_NOACK | I2C_ABRT_10ADDR1_NOACK | I2C_ABRT_10ADDR2_NOACK)) {
+        DEBUG ((DEBUG_ERROR, "%a(#%4d) - Nobody home!\n", __FUNCTION__, __LINE__));
+        Status = EFI_NO_RESPONSE;
+      } else {
+        Status = EFI_DEVICE_ERROR;
+      }
+      goto Exit;
+    }
+    //
+    // Determine if another byte was received and we were expecting it
+    //
+    if (((I2cGetStatus (I2cBaseAddress) & STAT_RFNE) != 0) && ReadFlag) {
+      *Data = MmioRead32 (I2cBaseAddress + R_IC_DATA_CMD) & 0xFF;
+      if (gI2cDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - MmioRead32, byte 0x%02x was received [%d:%d]\n", __FUNCTION__, __LINE__, *Data, Start, End));
+      MicroSecondDelay (FIFO_WRITE_DELAY);
+      //
+      // Now empty the RX FIFO if stop bit set
+      //
+      while (End && ((I2cGetStatus (I2cBaseAddress) & STAT_RFNE) == STAT_RFNE)) {
+        MmioRead32 (I2cBaseAddress + R_IC_DATA_CMD);
+        MicroSecondDelay (FIFO_WRITE_DELAY);
+      }
+      if (gI2cDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - RX FIFO = %04x\n", __FUNCTION__, __LINE__, I2cGetRxFifo (I2cBaseAddress)));
+      if (gI2cDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - TX FIFO = %04x\n", __FUNCTION__, __LINE__, I2cGetTxFifo (I2cBaseAddress)));
+      Status = EFI_SUCCESS;
+      goto Exit;
+    }
+    //
+    // Wait for room in TX buffer
+    //
+    if ((I2cGetStatus (I2cBaseAddress) & STAT_TFNF) == 0) {
+      MicroSecondDelay (FIFO_WRITE_DELAY);
+      continue;
+    }
+    if (!CommandSent) {
+      //
+      // Send CMD
+      //
+      Data32 = *Data;
+      if (Start) Data32 |= B_CMD_RESTART;
+      if (End)   Data32 |= B_CMD_STOP;
+      MmioWrite32 (I2cBaseAddress + R_IC_DATA_CMD, Data32);
+      CommandSent = TRUE;
+    }
+    //
+    // Add a small delay to work around some odd behavior being seen.  Without this delay bytes get dropped.
+    //
+    MicroSecondDelay (EEPROM_WRITE_TIMEOUT);
+    //
+    // Time out check for write CMD
+    //
+    while (!ReadFlag) {
+      if ((I2cGetRawStatus (I2cBaseAddress) & I2C_INTR_TX_ABRT) != 0) {
+        TxAbortStatus = I2cGetTxAbortStatus (I2cBaseAddress);
+        DEBUG ((DEBUG_ERROR, "%a (#%4d) - TX ABRT [%04x]\n", __FUNCTION__, __LINE__, TxAbortStatus));
+        //
+        // Clear TX Abort
+        //
+        I2cClearTxAbort (I2cBaseAddress);
+        MicroSecondDelay (EEPROM_WRITE_TIMEOUT);
+        //
+        // Clear interrupts
+        //
+        I2cClearInterrupts (I2cBaseAddress);
+        MicroSecondDelay (EEPROM_WRITE_TIMEOUT);
+        //
+        // Set status
+        //
+        if (TxAbortStatus & (I2C_ABRT_7B_ADDR_NOACK | I2C_ABRT_10ADDR1_NOACK | I2C_ABRT_10ADDR2_NOACK)) {
+          DEBUG ((DEBUG_ERROR, "%a(#%4d) - Nobody home!\n", __FUNCTION__, __LINE__));
+          Status = EFI_NO_RESPONSE;
+        } else {
+          Status = EFI_DEVICE_ERROR;
+        }
+      }
+      if (I2cGetTxFifo (I2cBaseAddress) == 0) {
+        if (gI2cDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - MmioRead32, byte 0x%04x was sent [%d:%d]\n", __FUNCTION__, __LINE__, Data32, Start, End));
+        if (gI2cDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - RX FIFO = %04x\n", __FUNCTION__, __LINE__, I2cGetRxFifo (I2cBaseAddress)));
+        if (gI2cDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - TX FIFO = %04x\n", __FUNCTION__, __LINE__, I2cGetTxFifo (I2cBaseAddress)));
+        Status = EFI_SUCCESS;
+        goto Exit;
+      }
+      MicroSecondDelay (EEPROM_WRITE_TIMEOUT);
+      if (Count++ < 1024) { //to avoid sys hung without ul-pmc device on RVP
+        continue; //Waiting the last request to get data and make (ReceiveDataEnd > ReadBuffer) =TRUE.
+      } else {
+        DEBUG ((DEBUG_ERROR, "%a (#%4d) - hardware timeout, 1024 times try!\n", __FUNCTION__, __LINE__));
+        Status = EFI_TIMEOUT;
+        goto Exit;
+      }
+    }
+  }
+
+  //
+  // Check for count out
+  //
+  if (CountOut == 0) {
+    Status = EFI_TIMEOUT;
+  }
+
+Exit:
+  //
+  // Pause a bit
+  //
+  MicroSecondDelay (EEPROM_ROUTINE_DELAY);
+  //
+  // Display error messages
+  //
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - Ending with %r   [%x]\n", __FUNCTION__, __LINE__, Status, CountOut));
+  }
+  return Status;
+}
+
+//
+//  Desc:   Set I2C target slave offset
+//  Input:  I2cBaseAddress        - MMIO base address for the I2C controller
+//          Offset                - Pointer to offset data
+//          Size                  - Size of the offset data
+//  Output: EFI_SUCCESS           - Write completed successfully
+//          EFI_DEVICE_ERROR      - I2C controller error
+//          EFI_INVALID_PARAMETER - Invalid input parameter
+//
+EFI_STATUS
+I2cSetOffset (
+  IN       UINT32     I2cBaseAddress,
+  IN       UINT8     *Offset,
+  IN       UINT8      Size
+  )
+{
+  UINT8        index;
+  EFI_STATUS   Status;
+
+  if (gI2cDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Starting\n", __FUNCTION__, __LINE__));
+
+  //
+  //  Sanity checks
+  //
+  if (Offset == NULL) {
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  if (Size == 0) {
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  //
+  // Set offset
+  //
+  for (index = 0; index < Size; index++) {
+    if (index == 0) {
+      //
+      // First byte of the offset
+      //
+      Status = I2cWrite (I2cBaseAddress, Offset[index], TRUE, FALSE);
+    } else {
+      Status = I2cWrite (I2cBaseAddress, Offset[index], FALSE, FALSE);
+    }
+    if (EFI_ERROR (Status)) {
+      goto Exit;
+    }
+    //
+    // Pause a bit
+    //
+    MicroSecondDelay (EEPROM_WRITE_TIMEOUT);
+  }
+
+Exit:
+  //
+  // Pause a bit
+  //
+  MicroSecondDelay (EEPROM_ROUTINE_DELAY);
+  //
+  // Display error messages
+  //
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - Ending with %r\n", __FUNCTION__, __LINE__, Status));
+  }
+  return Status;
+}
+
+//
+//  Desc:   Write a byte to the I2C controller
+//  Input:  I2cBaseAddress        - MMIO base address for the I2C controller
+//          Data                  - Data from the I2C controller
+//          Start                 - Send start bit?
+//          End                   - Send end bit?
+//  Output: EFI_SUCCESS           - Write completed successfully
+//          EFI_DEVICE_ERROR      - I2C controller error
+//          EFI_INVALID_PARAMETER - Invalid input parameter
+//
+EFI_STATUS
+I2cWrite (
+  IN       UINT32     I2cBaseAddress,
+  IN       UINT8      Data,
+  IN       BOOLEAN    Start,
+  IN       BOOLEAN    End
+  )
+{
+  UINT32      Data32;
+  EFI_STATUS  Status;
+
+  if (gI2cDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Starting\n", __FUNCTION__, __LINE__));
+
+  //
+  // Send CMD for write
+  //
+  Data32 = Data;
+  Status = I2cSendCommand (I2cBaseAddress, &Data32, Start, End);
+  //
+  // Pause a bit
+  //
+  MicroSecondDelay (EEPROM_ROUTINE_DELAY);
+  //
+  // Display error messages
+  //
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - Ending with %r\n", __FUNCTION__, __LINE__, Status));
+  }
+  return Status;
+}
+
diff --git a/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/EEPROM/I2cLib.h b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/EEPROM/I2cLib.h
new file mode 100644
index 0000000000..4134caa6a6
--- /dev/null
+++ b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/EEPROM/I2cLib.h
@@ -0,0 +1,181 @@
+/** @file
+  Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _EEPROM_I2C_LIB_
+#define _EEPROM_I2C_LIB_
+////
+//// Header files
+////
+#include <Uefi.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/EepromDataLib.h>
+#include <Library/GpioLib.h>
+#include <Library/PcdLib.h>
+#include <Library/TimerLib.h>
+
+#include <PlatformBaseAddresses.h>
+#include <SaAccess.h>
+#include <ScAccess.h>
+#include <ScRegs/RegsI2c.h>
+
+//
+// Defines
+//
+#define   EEPROM_WRITE_TIMEOUT        5
+#define   FIFO_WRITE_DELAY            5
+#define   EEPROM_ROUTINE_DELAY        10
+#define   INVALID_I2C_ADDRESS         0xFF
+#define   MAX_I2C_ADDRESS             0x7F
+#define   MAX_I2C_BUS                 7
+
+//
+// Enums
+//
+typedef enum {
+  Standard_Speed = 1,
+  Fast_Speed     = 2,
+  High_Speed     = 3,
+  Max_Speed      = 3
+} I2C_SPEED;
+
+//
+// Externs
+//
+extern BOOLEAN   gI2cDebugFlag;
+
+//
+// Structures
+//
+typedef struct _LPSS_PCI_DEVICE_INFO {
+  UINT8        Segment;
+  UINT8        BusNum;
+  UINT8        DeviceNum;
+  UINT8        FunctionNum;
+  UINT32       Bar0;
+  UINT32       Bar1;
+} LPSS_PCI_DEVICE_INFO;
+
+typedef struct _LPSS_I2C_CLOCK_SCL_INFO {
+  UINT16       SS_SCL_HCNT;
+  UINT16       SS_SCL_LCNT;
+  UINT16       FS_SCL_HCNT;
+  UINT16       FS_SCL_LCNT;
+  UINT16       HS_SCL_HCNT;
+  UINT16       HS_SCL_LCNT;
+} LPSS_I2C_CLOCK_SCL_INFO;
+
+//
+// Functions
+//
+//
+//  Desc:   Initializes the controller and returns the MMIO base address
+//  Input:  Bus                   - I2C controller, 0 based
+//          Address               - 7-bit slave address
+//          Speed                 - Uses the I2C_SPEED enum to set the controller speed
+//          I2cBaseAddress        - Pointer to the MMIO base address for the I2C controller
+//  Output: EFI_SUCCESS           - Initialization completed successfully
+//          EFI_DEVICE_ERROR      - I2C controller error
+//          EFI_INVALID_PARAMETER - Invalid input parameter
+//
+EFI_STATUS
+I2cInit (
+  IN       UINT8     Bus,
+  IN       UINT16    Address,
+  IN       UINT8     Speed,
+  IN OUT   UINT32   *I2cBaseAddress
+  );
+
+EFI_STATUS
+I2cPoll (
+  IN       UINT32     I2cBaseAddress
+  );
+
+//
+//  Desc:   Read a byte from the I2C controller
+//  Input:  I2cBaseAddress        - MMIO base address for the I2C controller
+//          Data                  - Pointer to where to store the data
+//          Start                 - Send start bit?
+//          End                   - Send end bit?
+//  Output: EFI_SUCCESS           - Read completed successfully
+//          EFI_DEVICE_ERROR      - I2C controller error
+//          EFI_INVALID_PARAMETER - Invalid input parameter
+//
+EFI_STATUS
+I2cRead (
+  IN       UINT32     I2cBaseAddress,
+  IN OUT   UINT8     *Data,
+  IN       BOOLEAN    Start,
+  IN       BOOLEAN    End
+  );
+
+//
+//  Desc:   Resets the I2C controller into a known good state
+//  Input:  I2cBaseAddress        - MMIO base address for the I2C controller
+//  Output: EFI_SUCCESS           - Write completed successfully
+//          EFI_DEVICE_ERROR      - I2C controller error
+//          EFI_INVALID_PARAMETER - Invalid input parameter
+//
+EFI_STATUS
+I2cReset (
+  IN       UINT32    I2cBaseAddress,
+  IN       UINT8     Bus,
+  IN       UINT16    Address,
+  IN       UINT8     Speed
+  );
+
+EFI_STATUS
+I2cSendCommand (
+  IN       UINT32     I2cBaseAddress,
+  IN       UINT32    *Data,
+  IN       BOOLEAN    Start,
+  IN       BOOLEAN    End
+  );
+
+//
+//  Desc:   Set I2C slave offset
+//  Input:  I2cBaseAddress        - MMIO base address for the I2C controller
+//          Offset                - Pointer to offset data
+//          Size                  - Size of the offset data
+//  Output: EFI_SUCCESS           - Write completed successfully
+//          EFI_DEVICE_ERROR      - I2C controller error
+//          EFI_INVALID_PARAMETER - Invalid input parameter
+//
+EFI_STATUS
+I2cSetOffset (
+  IN       UINT32     I2cBaseAddress,
+  IN       UINT8     *Offset,
+  IN       UINT8      Size
+  );
+
+//
+//  Desc:   Write a byte to the I2C controller
+//  Input:  I2cBaseAddress        - MMIO base address for the I2C controller
+//          Data                  - Data from the I2C controller
+//          Start                 - Send start bit?
+//          End                   - Send end bit?
+//  Output: EFI_SUCCESS           - Write completed successfully
+//          EFI_DEVICE_ERROR      - I2C controller error
+//          EFI_INVALID_PARAMETER - Invalid input parameter
+//
+EFI_STATUS
+I2cWrite (
+  IN       UINT32     I2cBaseAddress,
+  IN       UINT8      Data,
+  IN       BOOLEAN    Start,
+  IN       BOOLEAN    End
+  );
+
+#endif // _EEPROM_I2C_LIB_
+
diff --git a/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/EepromDataLib.c b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/EepromDataLib.c
new file mode 100644
index 0000000000..e5ffc85491
--- /dev/null
+++ b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/EepromDataLib.c
@@ -0,0 +1,216 @@
+/** @file
+  Common EEPROM raw data library instance.
+
+  Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "EepromDataLib.h"
+
+BOOLEAN                      mEepromDataLibDebugFlag = FALSE;
+EEPROM_DATA_LIBRARY_INDEX    mEepromDataLibIndex[EEPROM_DATA_LIBRARY_INDEX_MAX];
+CHAR8                       *mEepromLibraryString[EEPROM_DATA_LIBRARY_INDEX_MAX] = {
+                              {"EEPROM_NULL"},
+                              {"EEPROM_EEPROM"},
+                              {"EEPROM_FV"},
+                              {"EEPROM_MEMORY"}
+                             };
+
+//
+// Desc:        Reads from the EEPROM and copies to the passed in buffer.
+// Variables:   LibraryIndex   Determines which raw data library to use
+//              Offset         Start copying from the offset
+//              Size           Size of the buffer and the number of bytes to copy
+//                             - If set to 0, then return size of EEPROM binary
+//              Buffer         Storage buffer for the copied data from the EEPROM
+//              FunctionInfo   Pointer to function specific data
+// Return:      EFI_SUCCESS             Data copied successfully
+//              EFI_UNSUPPORTED         This function is not supported
+//              EFI_INVALID_PARAMETER   One of the parameters is invalid
+//              EFI_NOT_READY           Called before all necessary library available
+//              EFI_DEVICE_ERROR        Communication error with device
+//
+EFI_STATUS
+EFIAPI
+ReadEeprom (
+  IN       UINT8     LibraryIndex,
+  IN       UINT32    Offset,
+  IN OUT   UINT32   *Size,
+  IN OUT   UINT8    *Buffer,
+  IN OUT   VOID     *FunctionInfo
+  )
+{
+  EFI_STATUS   Status;
+
+  //
+  // Sanity checks
+  //
+  if (LibraryIndex >= EEPROM_DATA_LIBRARY_INDEX_MAX) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - LibraryIndex out of range\n", __FUNCTION__, __LINE__));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  if (Size == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - Size == NULL\n", __FUNCTION__, __LINE__));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  if (Buffer == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - Buffer == NULL\n", __FUNCTION__, __LINE__));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  if (mEepromDataLibIndex[LibraryIndex].Active == FALSE) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - Library %a is not active\n", __FUNCTION__, __LINE__, mEepromLibraryString[LibraryIndex]));
+    Status = EFI_NOT_READY;
+    goto Exit;
+  }
+
+  //
+  // Call function
+  //
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Calling EEPROM raw library %a read function\n", __FUNCTION__, __LINE__, mEepromLibraryString[LibraryIndex]));
+  Status = mEepromDataLibIndex[LibraryIndex].ReadFunction (Offset, Size, Buffer, FunctionInfo);
+
+Exit:
+  if (EFI_ERROR (Status) && (Status != EFI_BUFFER_TOO_SMALL)) {
+    if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_ERROR, "%a (#%4d) - Ending with %r\n", __FUNCTION__, __LINE__, Status));
+  }
+  return Status;
+}
+
+//
+// Desc:        Writes to the EEPROM and copies to the passed in buffer.
+// Variables:   LibraryIndex   Determines which raw data library to use
+//              Offset         Start copying from the offset
+//                             - If set to 0, then return size of EEPROM binary
+//              Size           Size of the buffer and the number of bytes to copy
+//              Buffer         Data to be copied to the EEPROM
+//              FunctionInfo   Pointer to function specific data
+// Return:      EFI_SUCCESS             Data copied successfully
+//              EFI_UNSUPPORTED         This function is not supported
+//              EFI_INVALID_PARAMETER   One of the parameters is invalid
+//              EFI_NOT_READY           Called before all necessary library available
+//              EFI_DEVICE_ERROR        Communication error with device
+//
+EFI_STATUS
+EFIAPI
+WriteEeprom (
+  IN       UINT8     LibraryIndex,
+  IN       UINT32    Offset,
+  IN OUT   UINT32   *Size,
+  IN OUT   UINT8    *Buffer,
+  IN OUT   VOID     *FunctionInfo
+  )
+{
+  EFI_STATUS   Status;
+
+  //
+  // Sanity checks
+  //
+  if (LibraryIndex >= EEPROM_DATA_LIBRARY_INDEX_MAX) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - LibraryIndex out of range\n", __FUNCTION__, __LINE__));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  if (Size == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - Size == NULL\n", __FUNCTION__, __LINE__));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  if (Buffer == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - Buffer == NULL\n", __FUNCTION__, __LINE__));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  if (mEepromDataLibIndex[LibraryIndex].Active == FALSE) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - Library %a is not active\n", __FUNCTION__, __LINE__, mEepromLibraryString[LibraryIndex]));
+    Status = EFI_NOT_READY;
+    goto Exit;
+  }
+
+  //
+  // Call function
+  //
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Calling EEPROM raw library %a write function\n", __FUNCTION__, __LINE__, mEepromLibraryString[LibraryIndex]));
+  Status = mEepromDataLibIndex[LibraryIndex].WriteFunction (Offset, Size, Buffer, FunctionInfo);
+
+Exit:
+  if (EFI_ERROR (Status) && (Status != EFI_BUFFER_TOO_SMALL)) {
+    if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_ERROR, "%a (#%4d) - Ending with %r\n", __FUNCTION__, __LINE__, Status));
+  }
+  return Status;
+}
+
+//
+// Desc:        Registers the raw data libraries
+// Variables:   None
+// Return:      EFI_SUCCESS, anything else will cause an ASSERT
+//
+EFI_STATUS
+EFIAPI
+EepromDataNullInitConstructor (VOID)
+{
+  //
+  // 00 - NULL raw library
+  //
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Loading EEPROM NULL raw data library into slot #%02x\n", __FUNCTION__, __LINE__, EEPROM_NULL));
+  mEepromDataLibIndex[EEPROM_NULL].Active        = TRUE;
+  mEepromDataLibIndex[EEPROM_NULL].ReadFunction  = ReadEepromNull;
+  mEepromDataLibIndex[EEPROM_NULL].WriteFunction = WriteEepromNull;
+
+  return EFI_SUCCESS;
+}
+
+//
+// Desc:        Registers the raw data libraries
+// Variables:   None
+// Return:      EFI_SUCCESS, anything else will cause an ASSERT
+//
+EFI_STATUS
+EFIAPI
+EepromDataInitConstructor (VOID)
+{
+  //
+  // 00 - NULL raw library
+  //
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Loading EEPROM NULL raw data library into slot #%02x\n", __FUNCTION__, __LINE__, EEPROM_NULL));
+  mEepromDataLibIndex[EEPROM_NULL].Active        = TRUE;
+  mEepromDataLibIndex[EEPROM_NULL].ReadFunction  = ReadEepromNull;
+  mEepromDataLibIndex[EEPROM_NULL].WriteFunction = WriteEepromNull;
+
+  //
+  // 01 - EEPROM raw library
+  //
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Loading EEPROM raw data library into slot #%02x\n", __FUNCTION__, __LINE__, EEPROM_EEPROM));
+  mEepromDataLibIndex[EEPROM_EEPROM].Active        = TRUE;
+  mEepromDataLibIndex[EEPROM_EEPROM].ReadFunction  = ReadEepromEeprom;
+  mEepromDataLibIndex[EEPROM_EEPROM].WriteFunction = WriteEepromEeprom;
+
+  //
+  // 02 - FV raw library
+  //
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Loading EEPROM FV raw data library into slot #%02x\n", __FUNCTION__, __LINE__, EEPROM_FV));
+  mEepromDataLibIndex[EEPROM_FV].Active        = TRUE;
+  mEepromDataLibIndex[EEPROM_FV].ReadFunction  = ReadEepromFv;
+  mEepromDataLibIndex[EEPROM_FV].WriteFunction = WriteEepromFv;
+
+  //
+  // 03 - Memory raw library
+  //
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Loading EEPROM memory raw data library into slot #%02x\n", __FUNCTION__, __LINE__, EEPROM_MEMORY));
+  mEepromDataLibIndex[EEPROM_MEMORY].Active        = TRUE;
+  mEepromDataLibIndex[EEPROM_MEMORY].ReadFunction  = ReadEepromMemory;
+  mEepromDataLibIndex[EEPROM_MEMORY].WriteFunction = WriteEepromMemory;
+
+  return EFI_SUCCESS;
+}
+
diff --git a/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/EepromDataLib.h b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/EepromDataLib.h
new file mode 100644
index 0000000000..899487ab46
--- /dev/null
+++ b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/EepromDataLib.h
@@ -0,0 +1,290 @@
+/** @file
+  Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _EEPROM_DATA_LIB_COMMON_
+#define _EEPROM_DATA_LIB_COMMON_
+////
+//// Header files
+////
+#include <Uefi.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/EepromDataLib.h>
+#include <Library/PrintLib.h>
+
+////
+//// Defines
+////
+#define ALLOCATION_HOB_HEADER_SIGNATURE   SIGNATURE_32 ('e', 'H', 'B', 'a')
+#define MAX_EEPROM_HOB_SIZE               (25 * 1024)
+#define MAX_EEPROM_ALLOCATION_FLAG        ((MAX_EEPROM_HOB_SIZE / 0x10) / 8)
+#define MAX_EEPROM_ALLOCATION_SIZE        (MAX_EEPROM_HOB_SIZE - MAX_EEPROM_ALLOCATION_FLAG)
+
+////
+//// TypeDefs
+////
+typedef
+EFI_STATUS
+(EFIAPI *NEM_TO_MEMORY_EEPROM_FUNCTION) (VOID);
+
+typedef
+EFI_STATUS
+(EFIAPI *READ_EEPROM_FUNCTION) (
+  IN       UINT32    Offset,
+  IN OUT   UINT32   *Size,
+  IN OUT   UINT8    *Buffer,
+  IN OUT   VOID     *FunctionInfo
+  );
+
+typedef
+EFI_STATUS
+(EFIAPI *WRITE_EEPROM_FUNCTION) (
+  IN       UINT32    Offset,
+  IN OUT   UINT32   *Size,
+  IN OUT   UINT8    *Buffer,
+  IN OUT   VOID     *FunctionInfo
+  );
+
+////
+//// Structures
+////
+typedef struct {
+   BOOLEAN                         Active;
+   READ_EEPROM_FUNCTION            ReadFunction;
+   WRITE_EEPROM_FUNCTION           WriteFunction;
+} EEPROM_DATA_LIBRARY_INDEX;
+
+typedef struct {
+ UINT32   Signature;
+  UINT8   UsageFlag[MAX_EEPROM_ALLOCATION_FLAG];   // Size / paragraph / byte size
+} EEPROM_ALLOCATION_STRUCT;
+
+////
+//// Functions
+////
+//
+// Desc:        Copies any data from NEM into real memory
+// Variables:   NONE
+// Return:      EFI_SUCCESS             Data copied successfully
+//              EFI_UNSUPPORTED         This function is not supported
+//              EFI_INVALID_PARAMETER   One of the parameters is invalid
+//
+EFI_STATUS
+EFIAPI
+NemToMemoryEepromEeprom (VOID);
+
+//
+// Desc:        Reads from the EEPROM and copies to the passed in buffer.
+// Variables:   Offset         Start copying from the offset
+//              Size           Size of the buffer and the number of bytes to copy
+//              Buffer         Storage buffer for the copied data from the EEPROM
+//              FunctionInfo   Pointer to function specific data
+// Return:      EFI_SUCCESS             Data copied successfully
+//              EFI_UNSUPPORTED         This function is not supported
+//              EFI_INVALID_PARAMETER   One of the parameters is invalid
+//              EFI_NOT_READY           Called before all necessary protocols available
+//              EFI_DEVICE_ERROR        Communication error with device
+//
+EFI_STATUS
+EFIAPI
+ReadEepromEeprom (
+  IN       UINT32    Offset,
+  IN OUT   UINT32   *Size,
+  IN OUT   UINT8    *Buffer,
+  IN OUT   VOID     *FunctionInfo
+  );
+
+//
+// Desc:        Writes to the EEPROM and copies to the passed in buffer.
+// Variables:   Offset         Start copying from the offset
+//              Size           Size of the buffer and the number of bytes to copy
+//              Buffer         Storage buffer for the copied data to the EEPROM
+//              FunctionInfo   Pointer to function specific data
+// Return:      EFI_SUCCESS             Data copied successfully
+//              EFI_UNSUPPORTED         This function is not supported
+//              EFI_INVALID_PARAMETER   One of the parameters is invalid
+//              EFI_NOT_READY           Called before all necessary protocols available
+//              EFI_DEVICE_ERROR        Communication error with device
+//
+EFI_STATUS
+EFIAPI
+WriteEepromEeprom (
+  IN       UINT32    Offset,
+  IN OUT   UINT32   *Size,
+  IN OUT   UINT8    *Buffer,
+  IN OUT   VOID     *FunctionInfo
+  );
+
+//
+// Desc:        Copies any data from NEM into real memory
+// Variables:   NONE
+// Return:      EFI_SUCCESS             Data copied successfully
+//              EFI_UNSUPPORTED         This function is not supported
+//              EFI_INVALID_PARAMETER   One of the parameters is invalid
+//
+EFI_STATUS
+EFIAPI
+NemToMemoryEepromFv (VOID);
+
+//
+// Desc:        Reads from the EEPROM and copies to the passed in buffer.
+// Variables:   Offset         Start copying from the offset
+//              Size           Size of the buffer and the number of bytes to copy
+//              Buffer         Storage buffer for the copied data from the EEPROM
+//              FunctionInfo   Pointer to function specific data
+// Return:      EFI_SUCCESS             Data copied successfully
+//              EFI_UNSUPPORTED         This function is not supported
+//              EFI_INVALID_PARAMETER   One of the parameters is invalid
+//              EFI_NOT_READY           Called before all necessary protocols available
+//              EFI_DEVICE_ERROR        Communication error with device
+//
+EFI_STATUS
+EFIAPI
+ReadEepromFv (
+  IN       UINT32    Offset,
+  IN OUT   UINT32   *Size,
+  IN OUT   UINT8    *Buffer,
+  IN OUT   VOID     *FunctionInfo
+  );
+
+//
+// Desc:        Writes to the EEPROM and copies to the passed in buffer.
+// Variables:   Offset         Start copying from the offset
+//              Size           Size of the buffer and the number of bytes to copy
+//              Buffer         Storage buffer for the copied data to the EEPROM
+//              FunctionInfo   Pointer to function specific data
+// Return:      EFI_SUCCESS             Data copied successfully
+//              EFI_UNSUPPORTED         This function is not supported
+//              EFI_INVALID_PARAMETER   One of the parameters is invalid
+//              EFI_NOT_READY           Called before all necessary protocols available
+//              EFI_DEVICE_ERROR        Communication error with device
+//
+EFI_STATUS
+EFIAPI
+WriteEepromFv (
+  IN       UINT32    Offset,
+  IN OUT   UINT32   *Size,
+  IN OUT   UINT8    *Buffer,
+  IN OUT   VOID     *FunctionInfo
+  );
+
+//
+// Desc:        Copies any data from NEM into real memory
+// Variables:   NONE
+// Return:      EFI_SUCCESS             Data copied successfully
+//              EFI_UNSUPPORTED         This function is not supported
+//              EFI_INVALID_PARAMETER   One of the parameters is invalid
+//
+EFI_STATUS
+EFIAPI
+NemToMemoryEepromMemory (VOID);
+
+//
+// Desc:        Reads from the EEPROM and copies to the passed in buffer.
+// Variables:   Offset         Start copying from the offset
+//              Size           Size of the buffer and the number of bytes to copy
+//              Buffer         Storage buffer for the copied data from the EEPROM
+//              FunctionInfo   Pointer to function specific data
+// Return:      EFI_SUCCESS             Data copied successfully
+//              EFI_UNSUPPORTED         This function is not supported
+//              EFI_INVALID_PARAMETER   One of the parameters is invalid
+//              EFI_NOT_READY           Called before all necessary protocols available
+//              EFI_DEVICE_ERROR        Communication error with device
+//
+EFI_STATUS
+EFIAPI
+ReadEepromMemory (
+  IN       UINT32    Offset,
+  IN OUT   UINT32   *Size,
+  IN OUT   UINT8    *Buffer,
+  IN OUT   VOID     *FunctionInfo
+  );
+
+//
+// Desc:        Writes to the EEPROM and copies to the passed in buffer.
+// Variables:   Offset         Start copying from the offset
+//              Size           Size of the buffer and the number of bytes to copy
+//              Buffer         Storage buffer for the copied data to the EEPROM
+//              FunctionInfo   Pointer to function specific data
+// Return:      EFI_SUCCESS             Data copied successfully
+//              EFI_UNSUPPORTED         This function is not supported
+//              EFI_INVALID_PARAMETER   One of the parameters is invalid
+//              EFI_NOT_READY           Called before all necessary protocols available
+//              EFI_DEVICE_ERROR        Communication error with device
+//
+EFI_STATUS
+EFIAPI
+WriteEepromMemory (
+  IN       UINT32    Offset,
+  IN OUT   UINT32   *Size,
+  IN OUT   UINT8    *Buffer,
+  IN OUT   VOID     *FunctionInfo
+  );
+
+//
+// Desc:        Copies any data from NEM into real memory
+// Variables:   NONE
+// Return:      EFI_SUCCESS             Data copied successfully
+//              EFI_UNSUPPORTED         This function is not supported
+//              EFI_INVALID_PARAMETER   One of the parameters is invalid
+//
+EFI_STATUS
+EFIAPI
+NemToMemoryEepromNull (VOID);
+
+//
+// Desc:        Reads from the EEPROM and copies to the passed in buffer.
+// Variables:   Offset         Start copying from the offset
+//              Size           Size of the buffer and the number of bytes to copy
+//              Buffer         Storage buffer for the copied data from the EEPROM
+//              FunctionInfo   Pointer to function specific data
+// Return:      EFI_SUCCESS             Data copied successfully
+//              EFI_UNSUPPORTED         This function is not supported
+//              EFI_INVALID_PARAMETER   One of the parameters is invalid
+//              EFI_NOT_READY           Called before all necessary protocols available
+//              EFI_DEVICE_ERROR        Communication error with device
+//
+EFI_STATUS
+EFIAPI
+ReadEepromNull (
+  IN       UINT32    Offset,
+  IN OUT   UINT32   *Size,
+  IN OUT   UINT8    *Buffer,
+  IN OUT   VOID     *FunctionInfo
+  );
+
+//
+// Desc:        Writes to the EEPROM and copies to the passed in buffer.
+// Variables:   Offset         Start copying from the offset
+//              Size           Size of the buffer and the number of bytes to copy
+//              Buffer         Storage buffer for the copied data to the EEPROM
+//              FunctionInfo   Pointer to function specific data
+// Return:      EFI_SUCCESS             Data copied successfully
+//              EFI_UNSUPPORTED         This function is not supported
+//              EFI_INVALID_PARAMETER   One of the parameters is invalid
+//              EFI_NOT_READY           Called before all necessary protocols available
+//              EFI_DEVICE_ERROR        Communication error with device
+//
+EFI_STATUS
+EFIAPI
+WriteEepromNull (
+  IN       UINT32    Offset,
+  IN OUT   UINT32   *Size,
+  IN OUT   UINT8    *Buffer,
+  IN OUT   VOID     *FunctionInfo
+  );
+
+#endif // _EEPROM_DATA_LIB_COMMON_
+
diff --git a/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/EepromDataLib.inf b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/EepromDataLib.inf
new file mode 100644
index 0000000000..67416aef46
--- /dev/null
+++ b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/EepromDataLib.inf
@@ -0,0 +1,80 @@
+## @file
+#  Library producing EEPROM raw data functionality.
+#
+#  Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution. The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php.
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010017
+  BASE_NAME                      = EepromDataLib
+  FILE_GUID                      = D3055446-DA60-4A6D-8D9C-D44CC2C42CA0
+  VERSION_STRING                 = 1.0
+  MODULE_TYPE                    = BASE
+  LIBRARY_CLASS                  = EepromDataLib
+  CONSTRUCTOR                    = EepromDataInitConstructor
+
+[Depex]
+  TRUE
+
+[Guids]
+  gEepromVariableGuid
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  DebugLib
+  GpioLib
+  HobLib
+  MemoryAllocationLib
+  PcdLib
+  PrintLib
+  UefiBootServicesTableLib
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  BroxtonPlatformPkg/PlatformPkg.dec
+  BroxtonSiPkg/BroxtonSiPkg.dec
+
+[Pcd]
+  gPlatformModuleTokenSpaceGuid.PcdEepromFvImageFile
+  gPlatformModuleTokenSpaceGuid.PcdEepromMapHobValid
+  gPlatformModuleTokenSpaceGuid.PcdEepromMemoryHobPresent
+  gPlatformModuleTokenSpaceGuid.PcdEepromMemoryPointer
+  gPlatformModuleTokenSpaceGuid.PcdEepromMemorySize
+  gPlatformModuleTokenSpaceGuid.PcdEepromParts
+  gPlatformModuleTokenSpaceGuid.PcdEepromPartsHeadLink
+  gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress   ## SOMETIMES_CONSUMES
+  gEfiBxtTokenSpaceGuid.PcdPmcGcrBaseAddress          ## SOMETIMES_CONSUMES
+
+[Protocols]
+  gEfiLoadedImageProtocolGuid
+  gEfiFirmwareVolume2ProtocolGuid
+
+[Sources]
+  EepromDataLib.c
+  EepromDataLib.h
+  MemoryAllocation.c
+  EEPROM/EepromDataEepromLib.c
+  EEPROM/EepromDataEepromLib.h
+  EEPROM/HobData.c
+  EEPROM/I2cLib.c
+  EEPROM/I2cLib.h
+  FV/EepromDataFvLib.c
+  FV/EepromDataFvLib.h
+  FV/GetImage.c
+  Memory/EepromDataMemoryLib.c
+  Memory/EepromDataMemoryLib.h
+  Memory/HobData.c
+  Null/EepromDataNullLib.c
+  Null/EepromDataNullLib.h
+
diff --git a/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/EepromDataNullLib.inf b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/EepromDataNullLib.inf
new file mode 100644
index 0000000000..71cec046d6
--- /dev/null
+++ b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/EepromDataNullLib.inf
@@ -0,0 +1,40 @@
+## @file
+#  Library producing EEPROM raw data functionality.
+#
+#  Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution. The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php.
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010017
+  BASE_NAME                      = EepromDataNullLib
+  FILE_GUID                      = 5FFC9D08-59AD-41EE-B237-6BDE9B900A73
+  VERSION_STRING                 = 1.0
+  MODULE_TYPE                    = BASE
+  LIBRARY_CLASS                  = EepromDataNullLib
+  CONSTRUCTOR                    = EepromDataNullInitConstructor
+
+[Depex]
+  TRUE
+
+[LibraryClasses]
+  BaseLib
+  DebugLib
+
+[Packages]
+  MdePkg/MdePkg.dec
+
+[Sources]
+  EepromDataLib.c
+  EepromDataLib.h
+  Null/EepromDataNullLib.c
+  Null/EepromDataNullLib.h
+
diff --git a/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/EepromDataPeiLib.inf b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/EepromDataPeiLib.inf
new file mode 100644
index 0000000000..86a047e4df
--- /dev/null
+++ b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/EepromDataPeiLib.inf
@@ -0,0 +1,75 @@
+## @file
+#  Library producing EEPROM raw data functionality.
+#
+#  Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution. The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php.
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010017
+  BASE_NAME                      = EepromDataPeiLib
+  FILE_GUID                      = 6341E204-DEC0-402B-BD12-40D221ED5E54
+  VERSION_STRING                 = 1.0
+  MODULE_TYPE                    = BASE
+  LIBRARY_CLASS                  = EepromDataPeiLib
+  CONSTRUCTOR                    = EepromDataInitConstructor
+
+[Depex]
+  TRUE
+
+[Guids]
+  gEepromVariableGuid
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  DebugLib
+  GpioLib
+  HobLib
+  PcdLib
+  PeiServicesLib
+  PrintLib
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  BroxtonPlatformPkg/PlatformPkg.dec
+  BroxtonSiPkg/BroxtonSiPkg.dec
+
+[Pcd]
+  gPlatformModuleTokenSpaceGuid.PcdEepromFvImageFile
+  gPlatformModuleTokenSpaceGuid.PcdEepromMapHobValid
+  gPlatformModuleTokenSpaceGuid.PcdEepromMemoryHobPresent
+  gPlatformModuleTokenSpaceGuid.PcdEepromMemoryPointer
+  gPlatformModuleTokenSpaceGuid.PcdEepromMemorySize
+  gPlatformModuleTokenSpaceGuid.PcdEepromParts
+  gPlatformModuleTokenSpaceGuid.PcdEepromPartsHeadLink
+  gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress   ## SOMETIMES_CONSUMES
+  gEfiBxtTokenSpaceGuid.PcdPmcGcrBaseAddress          ## SOMETIMES_CONSUMES
+
+[Sources]
+  EepromDataLib.c
+  EepromDataLib.h
+  MemoryAllocationPei.c
+  EEPROM/EepromDataEepromLib.c
+  EEPROM/EepromDataEepromLib.h
+  EEPROM/HobDataPei.c
+  EEPROM/I2cLib.c
+  EEPROM/I2cLib.h
+  FV/EepromDataFvLib.c
+  FV/EepromDataFvLib.h
+  FV/GetImagePei.c
+  Memory/EepromDataMemoryLib.c
+  Memory/EepromDataMemoryLib.h
+  Memory/HobDataPei.c
+  Null/EepromDataNullLib.c
+  Null/EepromDataNullLib.h
+
diff --git a/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/FV/EepromDataFvLib.c b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/FV/EepromDataFvLib.c
new file mode 100644
index 0000000000..c503a83720
--- /dev/null
+++ b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/FV/EepromDataFvLib.c
@@ -0,0 +1,172 @@
+/** @file
+  FV EEPROM raw data library instance.
+
+  Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "EepromDataFvLib.h"
+
+//
+// Desc:        Reads from the EEPROM and copies to the passed in buffer.
+// Variables:   Offset         Start copying from the offset
+//              Size           Size of the buffer and the number of bytes to copy
+//                             - If set to 0, then return size of EEPROM binary
+//              Buffer         Storage buffer for the copied data from the EEPROM
+//              FunctionInfo   Pointer to function specific data
+// Return:      EFI_SUCCESS             Data copied successfully
+//              EFI_UNSUPPORTED         This function is not supported
+//              EFI_INVALID_PARAMETER   One of the parameters is invalid
+//              EFI_NOT_READY           Called before all necessary protocols available
+//              EFI_DEVICE_ERROR        Communication error with device
+//
+EFI_STATUS
+EFIAPI
+ReadEepromFv (
+  IN       UINT32    Offset,
+  IN OUT   UINT32   *Size,
+  IN OUT   UINT8    *Buffer,
+  IN OUT   VOID     *FunctionInfo
+  )
+{
+  VOID               *Address;
+  FV_FUNCTION_INFO   *FvInfo;
+  EFI_GUID            FvSectionGuid;
+  UINTN               FvSize;
+  VOID               *Ptr;
+  EFI_STATUS          Status;
+
+  //
+  // Initialize variables
+  //
+  CopyMem (&FvSectionGuid, PcdGetPtr (PcdEepromFvImageFile), sizeof (EFI_GUID));
+  Address = NULL;
+  FvInfo  = (FV_FUNCTION_INFO *) FunctionInfo;
+  FvSize  = 0;
+
+  //
+  // Sanity checks
+  //
+  // NOTE: Input parameters already checked in wrapper function.
+  //
+  if (FvInfo != NULL) {
+    if ((FvInfo->LibraryIndex == EEPROM_FV) & (FvInfo->FvFileGuid != NULL)) {
+      //
+      // Looking for a different FV file than the EEPROM image
+      //
+      CopyMem (&FvSectionGuid, FvInfo->FvFileGuid, sizeof (EFI_GUID));
+    }
+  }
+
+  //
+  // Grab file from FV
+  //
+  Status = GetImage (
+             &FvSectionGuid,
+             &Address,
+             &FvSize
+             );
+
+  if (!EFI_ERROR (Status)) {
+    //
+    // EEPROM image is present in FV
+    //
+    if (Address != NULL) {
+      Ptr = Address;
+      DEBUG ((DEBUG_INFO, "%a (#%4d) - Found EEPROM image @ 0x%08x.\n", __FUNCTION__, __LINE__, Address));
+      if (*Size == 0) {
+        //
+        // Nothing to copy, return FV EEPROM size.
+        //
+        *Size = (UINT32) FvSize;
+        Status = EFI_BUFFER_TOO_SMALL;
+        DEBUG ((DEBUG_INFO, "%a (#%4d) - EEPROM size = 0x%08x\n", __FUNCTION__, __LINE__, *Size));
+      } else {
+        //
+        // Figure out the correct buffer size.
+        //
+        if ((*Size + Offset) > FvSize) {
+          //
+          // Buffer is larger than what is left in the FV. Update the passed in size.
+          //
+          if (FvSize < Offset) {
+            //
+            // Offset is larger than the FV size. Return 0.
+            //
+            *Size = 0;
+          } else {
+            if (((UINT32) FvSize - Offset) > *Size) {
+              //
+              // Buffer isn't large enough. Bail.
+              //
+              *Size = (UINT32) FvSize - Offset;
+              Status = EFI_BUFFER_TOO_SMALL;
+              goto Exit;
+            } else {
+              *Size = (UINT32) FvSize - Offset;
+            }
+          }
+        }
+        DEBUG ((DEBUG_INFO, "%a (#%4d) - Copying 0x%08x bytes of data starting at offset 0x%08x...\n", __FUNCTION__, __LINE__, *Size, Offset));
+        if (*Size > 0) {
+          //
+          // Asking to copy something
+          //
+          Address = (VOID *) ((UINT8 *) Address + Offset);
+          CopyMem ((VOID *) Buffer, Address, *Size);
+        }
+      }
+      //
+      // GetImage () allocated buffer for Address, now clear it
+      //
+      FreePool (Ptr);
+      Ptr = NULL;
+    }
+  }
+
+Exit:
+  if (EFI_ERROR (Status) && (Status != EFI_BUFFER_TOO_SMALL)) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - Ending with %r\n", __FUNCTION__, __LINE__, Status));
+  }
+  return Status;
+}
+
+//
+// Desc:        Writes to the EEPROM and copies to the passed in buffer.
+// Variables:   Offset         Start copying from the offset
+//              Size           Size of the buffer and the number of bytes to copy
+//                             - If set to 0, then return size of EEPROM binary
+//              Buffer         Data to be copied to the EEPROM
+//              FunctionInfo   Pointer to function specific data
+// Return:      EFI_SUCCESS             Data copied successfully
+//              EFI_UNSUPPORTED         This function is not supported
+//              EFI_INVALID_PARAMETER   One of the parameters is invalid
+//              EFI_NOT_READY           Called before all necessary protocols available
+//              EFI_DEVICE_ERROR        Communication error with device
+//
+EFI_STATUS
+EFIAPI
+WriteEepromFv (
+  IN       UINT32    Offset,
+  IN OUT   UINT32   *Size,
+  IN OUT   UINT8    *Buffer,
+  IN OUT   VOID     *FunctionInfo
+  )
+{
+  //
+  // Sanity checks
+  //
+  // NOTE: Input parameters already checked in wrapper function.
+  //
+
+  return EFI_UNSUPPORTED;
+}
+
diff --git a/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/FV/EepromDataFvLib.h b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/FV/EepromDataFvLib.h
new file mode 100644
index 0000000000..10544e27d5
--- /dev/null
+++ b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/FV/EepromDataFvLib.h
@@ -0,0 +1,32 @@
+/** @file
+  Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _EEPROM_DATA_FV_LIB_
+#define _EEPROM_DATA_FV_LIB_
+
+#include <Uefi.h>
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/EepromDataLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+EFI_STATUS
+EFIAPI
+GetImage (
+  IN  EFI_GUID            *NameGuid,
+  OUT VOID               **Buffer,
+  OUT UINTN               *Size
+  );
+
+#endif // _EEPROM_DATA_FV_LIB_
diff --git a/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/FV/GetImage.c b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/FV/GetImage.c
new file mode 100644
index 0000000000..434d9d9496
--- /dev/null
+++ b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/FV/GetImage.c
@@ -0,0 +1,114 @@
+/** @file
+  FV EEPROM raw data library instance.
+
+  Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "EepromDataFvLib.h"
+
+#include <PiDxe.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Protocol/FirmwareVolume2.h>
+#include <Protocol/LoadedImage.h>
+
+EFI_STATUS
+EFIAPI
+GetImage (
+  IN  EFI_GUID            *NameGuid,
+  OUT VOID               **Buffer,
+  OUT UINTN               *Size
+  )
+{
+  UINT32                          AuthenticationStatus;
+  EFI_FIRMWARE_VOLUME2_PROTOCOL  *Fv;
+  EFI_HANDLE                     *HandleBuffer;
+  UINTN                           HandleCount;
+  EFI_FIRMWARE_VOLUME2_PROTOCOL  *ImageFv;
+  UINTN                           Index;
+  EFI_STATUS                      Status;
+
+  Status  = EFI_NOT_FOUND;
+  ImageFv = NULL;
+
+  Status = gBS->LocateHandleBuffer (
+                  ByProtocol,
+                  &gEfiFirmwareVolume2ProtocolGuid,
+                  NULL,
+                  &HandleCount,
+                  &HandleBuffer
+                  );
+  if (EFI_ERROR (Status)) {
+    //
+    // Couldn't find the FV2 protocol. Bail.
+    //
+    goto Exit;
+  }
+
+  //
+  // Find desired image in all FVs
+  //
+  for (Index = 0; Index < HandleCount; ++Index) {
+    Status = gBS->HandleProtocol (
+                    HandleBuffer[Index],
+                    &gEfiFirmwareVolume2ProtocolGuid,
+                    (VOID **) &Fv
+                    );
+    if (EFI_ERROR (Status)) {
+      goto Exit;
+    }
+    if ((ImageFv != NULL) && (Fv == ImageFv)) {
+      continue;
+    }
+
+    //
+    // Found an FV, try to find file.
+    //
+    *Buffer = NULL;
+    *Size   = 0;
+    Status  = Fv->ReadSection (
+                    Fv,
+                    NameGuid,
+                    EFI_SECTION_RAW,
+                    0,
+                    Buffer,
+                    Size,
+                    &AuthenticationStatus
+                    );
+    if (!EFI_ERROR (Status)) {
+      //
+      // Found the file. Bail.
+      //
+      break;
+    }
+  }
+
+  //
+  // Did we find the file?
+  //
+  if (Index == HandleCount) {
+    //
+    // Nope. Clear buffer and size, then bail.
+    //
+    *Buffer = NULL;
+    *Size   = 0;
+    Status  = EFI_NOT_FOUND;
+  } else {
+    Status = EFI_SUCCESS;
+  }
+
+Exit:
+  if (HandleBuffer != NULL) {
+    FreePool (HandleBuffer);
+    HandleBuffer = NULL;
+  }
+  return Status;
+}
diff --git a/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/FV/GetImagePei.c b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/FV/GetImagePei.c
new file mode 100644
index 0000000000..8e8b4e23ab
--- /dev/null
+++ b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/FV/GetImagePei.c
@@ -0,0 +1,113 @@
+/** @file
+  FV EEPROM raw data PEI library instance.
+
+  Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "EepromDataFvLib.h"
+
+#include <PiPei.h>
+#include <Library/PeiServicesLib.h>
+
+EFI_STATUS
+EFIAPI
+GetImage (
+  IN  EFI_GUID            *NameGuid,
+  OUT VOID               **Buffer,
+  OUT UINTN               *Size
+  )
+{
+  BOOLEAN                      FileFound;
+  EFI_PEI_FILE_HANDLE          FileHandle;
+  EFI_FV_FILE_INFO             FileInfo;
+  UINTN                        Instance;
+  EFI_COMMON_SECTION_HEADER   *Section;
+  EFI_STATUS                   Status;
+  EFI_PEI_FV_HANDLE            VolumeHandle;
+
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Starting...\n", __FUNCTION__, __LINE__));
+
+  //
+  // Initialize variables
+  //
+  FileFound = FALSE;
+  Instance  = 0;
+
+  //
+  // Search FVs for the file
+  //
+  while (TRUE) {
+    //
+    // Search thru the FVs
+    //
+    Status = PeiServicesFfsFindNextVolume (Instance++, &VolumeHandle);
+    if (EFI_ERROR (Status)) {
+      //
+      // Error or end of FVs.
+      //
+      if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_ERROR, "%a (#%4d) - PeiServicesFfsFindNextVolume() -> %r\n", __FUNCTION__, __LINE__, Status));
+      goto Exit;
+    }
+    //
+    // Search the FV for the file.
+    //
+    Status = PeiServicesFfsFindFileByName (NameGuid, VolumeHandle, &FileHandle);
+    if (EFI_ERROR (Status)) {
+      //
+      // File not found. Continue search.
+      //
+      if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_ERROR, "%a (#%4d) - PeiServicesFfsFindFileByName() -> %r\n", __FUNCTION__, __LINE__, Status));
+      continue;
+    }
+    //
+    // Search the file for the section.
+    //
+    Status = PeiServicesFfsFindSectionData (EFI_SECTION_RAW, FileHandle, Buffer);
+    if (EFI_ERROR (Status)) {
+      //
+      // Section not found. Continue search.
+      //
+      if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_ERROR, "%a (#%4d) - PeiServicesFfsFindSectionData() -> %r\n", __FUNCTION__, __LINE__, Status));
+      continue;
+    }
+    //
+    // We've got the file and section.
+    //
+    Status = PeiServicesFfsGetFileInfo (FileHandle, &FileInfo);
+    if (EFI_ERROR (Status)) {
+      //
+      // File info error. Continue search.
+      //
+      if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_ERROR, "%a (#%4d) - PeiServicesFfsGetFileInfo() -> %r\n", __FUNCTION__, __LINE__, Status));
+      continue;
+    }
+    FileFound = TRUE;
+    Section = (EFI_COMMON_SECTION_HEADER *) FileInfo.Buffer;
+    if (IS_SECTION2 (Section)) {
+      ASSERT (SECTION2_SIZE (Section) > 0x00FFFFFF);
+      *Size = SECTION2_SIZE (Section) - sizeof (EFI_COMMON_SECTION_HEADER2);
+    } else {
+      *Size = SECTION_SIZE (Section) - sizeof (EFI_COMMON_SECTION_HEADER);
+    }
+    break;
+  }
+
+  if (FileFound) {
+    Status = EFI_SUCCESS;
+  } else {
+    *Buffer = NULL;
+    *Size   = 0;
+  }
+
+Exit:
+  return Status;
+}
diff --git a/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/Memory/EepromDataMemoryLib.c b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/Memory/EepromDataMemoryLib.c
new file mode 100644
index 0000000000..2ea1d8b4bf
--- /dev/null
+++ b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/Memory/EepromDataMemoryLib.c
@@ -0,0 +1,242 @@
+/** @file
+  Memory EEPROM raw data library instance.
+
+  Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "EepromDataMemoryLib.h"
+
+//
+// Desc:        Reads from the EEPROM copy in memory and copies to the passed in buffer.
+// Variables:   Offset         Start copying from the offset
+//              Size           Size of the buffer and the number of bytes to copy
+//              Buffer         Storage buffer for the copied data from the EEPROM
+//              FunctionInfo   Pointer to function specific data
+// Return:      EFI_SUCCESS             Data copied successfully
+//              EFI_BUFFER_TOO_SMALL    Passed in buffer is too small to hold the data
+//                                      requested
+//
+EFI_STATUS
+EFIAPI
+ReadEepromMemory (
+  IN       UINT32    Offset,
+  IN OUT   UINT32   *Size,
+  IN OUT   UINT8    *Buffer,
+  IN OUT   VOID     *FunctionInfo
+  )
+{
+  UINT8         *Address;
+  UINT8         *EepromMemoryPtr;
+  UINT32         EepromMemorySize;
+  EFI_STATUS     Status;
+
+  //
+  // Try to load data from HOB
+  //
+  GetEepromDataHobData ();
+
+  //
+  // Initialize variables
+  //
+  Address          = NULL;
+  EepromMemoryPtr  = (UINT8 *) (UINTN) PcdGet64 (PcdEepromMemoryPointer);
+  EepromMemorySize = PcdGet32 (PcdEepromMemorySize);
+  Status           = EFI_SUCCESS;
+
+  //
+  // Sanity checks
+  //
+  // NOTE: Input parameters already checked in wrapper function.
+  //
+
+  if ((EepromMemoryPtr == NULL) || (EepromMemorySize == 0)) {
+    //
+    // Memory pointer not loaded yet.
+    //
+    Status = EFI_SUCCESS;
+    *Size  = 0;
+    goto Exit;
+  }
+
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - EepromMemoryPtr  = 0x%08x\n", __FUNCTION__, __LINE__, PcdGet64 (PcdEepromMemoryPointer)));
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - EepromMemorySize = 0x%08x\n", __FUNCTION__, __LINE__, PcdGet32 (PcdEepromMemorySize)));
+  Address = EepromMemoryPtr;
+  if (*Size == 0) {
+    //
+    // Nothing to copy, return EEPROM size.
+    //
+    *Size = EepromMemorySize;
+    if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - EEPROM size = 0x%08x\n", __FUNCTION__, __LINE__, *Size));
+    Status = EFI_BUFFER_TOO_SMALL;
+    goto Exit;
+  } else {
+    //
+    // Figure out the correct buffer size.
+    //
+    if ((*Size + Offset) > EepromMemorySize) {
+      //
+      // Buffer is larger than what is left in the FV. Update the passed in size.
+      //
+      if (EepromMemorySize < Offset) {
+        //
+        // Offset is larger than the FV size. Return 0.
+        //
+        *Size = 0;
+      } else {
+        if ((EepromMemorySize - Offset) > *Size) {
+          //
+          // Buffer isn't large enough. Bail.
+          //
+          *Size = EepromMemorySize - Offset;
+          Status = EFI_BUFFER_TOO_SMALL;
+          goto Exit;
+        } else {
+          *Size = EepromMemorySize - Offset;
+        }
+      }
+    }
+    if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Copying 0x%08x bytes of data...\n", __FUNCTION__, __LINE__, *Size));
+    if (*Size > 0) {
+      //
+      // Asking to copy something
+      //
+      Address = Address + Offset;
+      CopyMem ((VOID *) Buffer, (VOID *) Address, *Size);
+    }
+  }
+
+Exit:
+  if (EFI_ERROR (Status) && (Status != EFI_BUFFER_TOO_SMALL)) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - Ending with %r\n", __FUNCTION__, __LINE__, Status));
+  }
+  return Status;
+}
+
+//
+// Desc:        Writes to the EEPROM memory copy and copies to the passed in buffer.
+// Variables:   Offset         Start copying from the offset
+//              Size           Size of the buffer and the number of bytes to copy
+//              Buffer         Data to be copied to the EEPROM
+//              FunctionInfo   Pointer to function specific data
+// Return:      EFI_SUCCESS             Data copied successfully
+//              EFI_BUFFER_TOO_SMALL    Passed in buffer is too small to hold the data
+//                                      requested
+//              EFI_OUT_OF_RESOURCES    Unable to allocate memory
+//
+EFI_STATUS
+EFIAPI
+WriteEepromMemory (
+  IN       UINT32    Offset,
+  IN OUT   UINT32   *Size,
+  IN OUT   UINT8    *Buffer,
+  IN OUT   VOID     *FunctionInfo
+  )
+{
+  UINT8         *EepromMemoryPtr;
+  UINT32         EepromMemorySize;
+  EFI_STATUS     Status;
+  UINT8         *TempBuffer;
+  UINT32         TempSize;
+
+  //
+  // Initialize variables
+  //
+  EepromMemoryPtr  = (UINT8 *) (UINTN) PcdGet64 (PcdEepromMemoryPointer);
+  EepromMemorySize = PcdGet32 (PcdEepromMemorySize);
+  Status           = EFI_SUCCESS;
+  TempBuffer       = NULL;
+  TempSize         = 0;
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - EepromMemoryPtr  = 0x%08x\n", __FUNCTION__, __LINE__, EepromMemoryPtr));
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - EepromMemorySize = 0x%08x\n", __FUNCTION__, __LINE__, EepromMemorySize));
+
+  //
+  // Sanity checks
+  //
+  // NOTE: Input parameters already checked in wrapper function.
+  //
+
+  if (*Size == 0) {
+    //
+    // Return current EEPROM size.
+    //
+    *Size = EepromMemorySize;
+    if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - EEPROM size = 0x%08x\n", __FUNCTION__, __LINE__, *Size));
+    Status = EFI_BUFFER_TOO_SMALL;
+    goto Exit;
+  } else {
+    //
+    // Asking to write data into memory EEPROM buffer.
+    //
+    if ((Offset + *Size) > EepromMemorySize) {
+      if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Incoming buffer is larger than existing buffer.\n", __FUNCTION__, __LINE__));
+      //
+      // Current memory buffer isn't large enough. Save current buffer/size off.
+      //
+      TempBuffer = EepromMemoryPtr;
+      TempSize   = EepromMemorySize;
+      //
+      // Clear memory buffer/size.
+      //
+      EepromMemoryPtr  = NULL;
+      EepromMemorySize = 0;
+    }
+    if (EepromMemorySize == 0) {
+      if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Memory buffer is NULL, allocating pool.\n", __FUNCTION__, __LINE__));
+      //
+      // Need to allocate buffer.
+      //
+      EepromMemoryPtr = EepromAllocatePool (*Size + Offset);
+      if (EepromMemoryPtr == NULL) {
+        //
+        // Failed to allocate space.
+        //
+        Status = EFI_OUT_OF_RESOURCES;
+        goto Exit;
+      }
+      EepromMemorySize = *Size + Offset;
+    }
+    //
+    // If there is a temp buffer, copy that content over first.
+    //
+    if ((TempBuffer != NULL) && (TempSize > 0)) {
+      if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Copying temp buffer to memory buffer.\n", __FUNCTION__, __LINE__));
+      CopyMem ((VOID *) EepromMemoryPtr, (VOID *) TempBuffer, TempSize);
+      TempBuffer = EepromFreePool (TempBuffer);
+    }
+    //
+    // Copy input buffer to memory buffer.
+    //
+    if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Found EEPROM image @ %08x.\n", __FUNCTION__, __LINE__, EepromMemoryPtr));
+    if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Copying 0x%08x bytes of data, starting at offset 0x%08x...\n", __FUNCTION__, __LINE__, *Size, Offset));
+    CopyMem ((VOID *) (EepromMemoryPtr + Offset), (VOID *) Buffer, *Size);
+  }
+
+Exit:
+  if (Status == EFI_SUCCESS) {
+    //
+    // Save off buffer info
+    //
+    PcdSet64 (PcdEepromMemoryPointer, (UINTN) EepromMemoryPtr);
+    PcdSet32 (PcdEepromMemorySize,    EepromMemorySize);
+
+    //
+    // Update HOB
+    //
+    SetEepromDataHobData ();
+  }
+
+  if (EFI_ERROR (Status) && (Status != EFI_BUFFER_TOO_SMALL)) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - Ending with %r\n", __FUNCTION__, __LINE__, Status));
+  }
+  return Status;
+}
+
diff --git a/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/Memory/EepromDataMemoryLib.h b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/Memory/EepromDataMemoryLib.h
new file mode 100644
index 0000000000..839515d764
--- /dev/null
+++ b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/Memory/EepromDataMemoryLib.h
@@ -0,0 +1,58 @@
+/** @file
+  Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _EEPROM_DATA_MEMORY_LIB_
+#define _EEPROM_DATA_MEMORY_LIB_
+////
+//// Header files
+////
+#include <Uefi.h>
+
+#include <Guid/EepromVariable.h>
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/EepromDataLib.h>
+#include <Library/PcdLib.h>
+
+////
+//// Defines
+////
+#define   MEMORY_HOB_HEADER_SIGNATURE   SIGNATURE_32 ('e', 'H', 'B', 'm')
+#define   MEMORY_HOB_HEADER_VERSION     0x00000001
+#define   MEMORY_HOB_MAX_DATA_SIZE      (30 * 1024)
+
+////
+//// Structures
+////
+typedef struct {
+   UINT32    Signature;
+   UINT32    Version;
+   UINT16    BlockNumber;
+   UINT16    BlockSize;
+   UINT32    Reserved;
+} MEMORY_HOB_HEADER;
+
+////
+//// Functions
+////
+EFI_STATUS
+EFIAPI
+GetEepromDataHobData (VOID);
+
+EFI_STATUS
+EFIAPI
+SetEepromDataHobData (VOID);
+
+#endif // _EEPROM_DATA_MEMORY_LIB_
+
diff --git a/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/Memory/HobData.c b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/Memory/HobData.c
new file mode 100644
index 0000000000..03e263e8d8
--- /dev/null
+++ b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/Memory/HobData.c
@@ -0,0 +1,142 @@
+/** @file
+  Memory EEPROM raw data library instance.
+
+  Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "EepromDataMemoryLib.h"
+#include <PiDxe.h>
+#include <Library/HobLib.h>
+
+EFI_STATUS
+EFIAPI
+GetEepromDataHobData (VOID)
+{
+  UINT8                        *BlockData;
+  BOOLEAN                       BlockFound;
+  UINT16                        BlockNumber;
+  UINT32                        BlockSize;
+  UINT8                        *Buffer;
+  EFI_HOB_GUID_TYPE            *GuidHobPtr;
+  UINT16                        LastBlockNumber;
+  MEMORY_HOB_HEADER            *MemoryHobHeader;
+  EFI_STATUS                    Status;
+
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Starting...\n", __FUNCTION__, __LINE__));
+
+  //
+  // Initialize variables
+  //
+  Buffer = NULL;
+  Status = EFI_SUCCESS;
+
+  if (PcdGetBool (PcdEepromMemoryHobPresent)) {
+    //
+    // Clear PCD values
+    //
+    PcdSet64 (PcdEepromMemoryPointer, 0);
+    PcdSet32 (PcdEepromMemorySize,    0);
+
+    //
+    // Gather HOB data into coherent chunk by looping thru the HOBs looking for the blocks in order.
+    //
+    LastBlockNumber = 0;
+    while (TRUE) {
+      //
+      // Reset to the beginning of the HOBs
+      //
+      BlockFound = FALSE;
+      GuidHobPtr = GetFirstGuidHob (&gEepromVariableGuid);
+      while (GuidHobPtr != NULL) {
+        //
+        // Get Memory HOB header pointer
+        //
+        MemoryHobHeader = GET_GUID_HOB_DATA (GuidHobPtr);
+        BlockData       = (UINT8 *) MemoryHobHeader + sizeof (MEMORY_HOB_HEADER);
+        BlockNumber     = MemoryHobHeader->BlockNumber;
+        BlockSize       = MemoryHobHeader->BlockSize;
+
+        //
+        // Is this our block?
+        //
+        if ((LastBlockNumber == BlockNumber) && (MemoryHobHeader->Signature == MEMORY_HOB_HEADER_SIGNATURE)) {
+          //
+          // Yep. Copy existing buffer to larger buffer.
+          //
+          Buffer = EepromAllocateCopyPool (PcdGet32 (PcdEepromMemorySize) + BlockSize, (UINT8 *) PcdGet64 (PcdEepromMemoryPointer));
+          if (Buffer == NULL) {
+            DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Unable to allocate buffer!\n", __FUNCTION__, __LINE__));
+            Status = EFI_OUT_OF_RESOURCES;
+            goto Exit;
+          }
+
+          //
+          // Append new data
+          //
+          CopyMem (Buffer + PcdGet32 (PcdEepromMemorySize), BlockData, BlockSize);
+
+          //
+          // Free old buffer and update PCDs
+          //
+          if (PcdGet64 (PcdEepromMemoryPointer) != 0) {
+            //
+            // Buffer exists. Free it.
+            //
+            EepromFreePool ((UINT8 *) (UINTN) PcdGet64 (PcdEepromMemoryPointer));
+          }
+          BlockSize += PcdGet32 (PcdEepromMemorySize);
+          PcdSet64 (PcdEepromMemoryPointer, (UINTN) Buffer);
+          PcdSet32 (PcdEepromMemorySize,    BlockSize);
+
+          //
+          // Increment counter and set flag
+          //
+          LastBlockNumber++;
+          BlockFound = TRUE;
+          break;
+        }
+
+        //
+        // Skip past present HOB to get next HOB
+        //
+        GuidHobPtr = GET_NEXT_HOB (GuidHobPtr);
+        GuidHobPtr = GetNextGuidHob (&gEepromVariableGuid, GuidHobPtr);
+      }
+      if (!BlockFound) {
+        //
+        // We're done. Bail.
+        //
+        break;
+      }
+    }
+
+    //
+    // Toggle flag.
+    //
+    PcdSetBool (PcdEepromMemoryHobPresent, FALSE);
+  }
+
+Exit:
+  return Status;
+}
+
+EFI_STATUS
+EFIAPI
+SetEepromDataHobData (VOID)
+{
+  //
+  // Not supported in DXE.
+  //
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Starting...\n", __FUNCTION__, __LINE__));
+  return EFI_UNSUPPORTED;
+}
+
diff --git a/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/Memory/HobDataPei.c b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/Memory/HobDataPei.c
new file mode 100644
index 0000000000..e975d11bf0
--- /dev/null
+++ b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/Memory/HobDataPei.c
@@ -0,0 +1,123 @@
+/** @file
+  Memory EEPROM raw data library instance.
+
+  Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "EepromDataMemoryLib.h"
+#include <PiPei.h>
+#include <Library/HobLib.h>
+
+EFI_STATUS
+EFIAPI
+GetEepromDataHobData (VOID)
+{
+  //
+  // Not supported in PEI.
+  //
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Starting...\n", __FUNCTION__, __LINE__));
+  return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+EFIAPI
+SetEepromDataHobData (VOID)
+{
+  UINT8                        *BlockData;
+  UINT16                        BlockNumber;
+  UINT16                        BlockSize;
+  UINT8                        *ImageData;
+  UINT32                        ImageSize;
+  MEMORY_HOB_HEADER            *MemoryHobHeader;
+  UINT32                        Offset;
+  EFI_STATUS                    Status;
+
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Starting...\n", __FUNCTION__, __LINE__));
+
+  //
+  // Initialize variables
+  //
+  BlockData = NULL;
+  ImageData = (UINT8 *) (UINTN) PcdGet64 (PcdEepromMemoryPointer);
+  ImageSize = PcdGet32 (PcdEepromMemorySize);
+  Status    = EFI_SUCCESS;
+
+  if (!PcdGetBool (PcdEepromMemoryHobPresent) && (ImageData != NULL) && (ImageSize != 0)) {
+    //
+    // No HOB yet. Create one.
+    //
+    BlockNumber = 0;
+    Offset      = 0;
+    while (ImageSize > 0) {
+      //
+      // Adjust block size
+      //
+      if (ImageSize > MEMORY_HOB_MAX_DATA_SIZE) {
+        BlockSize = MEMORY_HOB_MAX_DATA_SIZE;
+      } else {
+        BlockSize = (UINT16) ImageSize;
+      }
+
+      //
+      // Create Block data buffer
+      //
+      BlockData = EepromFreePool (BlockData);
+      BlockData = EepromAllocatePool (BlockSize + sizeof (MEMORY_HOB_HEADER));
+      if (BlockData == NULL) {
+        DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Unable to allocate buffer!\n", __FUNCTION__, __LINE__));
+        Status = EFI_OUT_OF_RESOURCES;
+        goto Exit;
+      }
+
+      //
+      // Setup header
+      //
+      MemoryHobHeader = (MEMORY_HOB_HEADER *) BlockData;
+      MemoryHobHeader->Signature   = MEMORY_HOB_HEADER_SIGNATURE;
+      MemoryHobHeader->Version     = MEMORY_HOB_HEADER_VERSION;
+      MemoryHobHeader->BlockNumber = BlockNumber;
+      MemoryHobHeader->BlockSize   = BlockSize;
+      MemoryHobHeader->Reserved    = 0x00000000;
+
+      //
+      // Copy data into buffer
+      //
+      CopyMem (
+        (BlockData + sizeof (MEMORY_HOB_HEADER)),
+        (ImageData + Offset),
+        (BlockSize + sizeof (MEMORY_HOB_HEADER))
+        );
+
+      //
+      // Create GUID HOB
+      //
+      BuildGuidDataHob (&gEepromVariableGuid, BlockData, BlockSize);
+
+      //
+      // Adjust pointers and such
+      //
+      Offset      += BlockSize;
+      BlockNumber += 1;
+      ImageSize   -= BlockSize;
+    }
+
+    //
+    // Toggle flag.
+    //
+    PcdSetBool (PcdEepromMemoryHobPresent, TRUE);
+  }
+
+Exit:
+  BlockData = EepromFreePool (BlockData);
+  return Status;
+}
+
diff --git a/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/MemoryAllocation.c b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/MemoryAllocation.c
new file mode 100644
index 0000000000..4d4b9ed322
--- /dev/null
+++ b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/MemoryAllocation.c
@@ -0,0 +1,67 @@
+/** @file
+  Common EEPROM memory allocation code.
+
+  Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "EepromDataLib.h"
+
+#include <Library/MemoryAllocationLib.h>
+
+//
+// Desc:        Copies the contents of an existing memory pool into a new memory pool of equal or greater size.
+// Variables:   Size           Size of the pool to copy existing pool into
+//              SourcePointer  Pointer to the source buffer to copy
+// Return:      Pointer        Pointer to your copy of the pool
+//
+VOID*
+EFIAPI
+EepromAllocateCopyPool (
+  IN  UINTN    Size,
+  IN  VOID    *SourcePointer
+  )
+{
+  return AllocateCopyPool (Size, SourcePointer);
+}
+
+//
+// Desc:        Creates a new memory pool.
+// Variables:   Size           Size of the pool requested
+// Return:      Pointer        Pointer the new pool
+//
+VOID*
+EFIAPI
+EepromAllocatePool (
+  IN  UINTN   Size
+  )
+{
+  return AllocateZeroPool (Size);
+}
+
+//
+// Desc:        Frees a memory pool.
+// Variables:   Pointer        Pointer to the beginning of the pool to be freed
+// Return:      Pointer        NULL
+//
+VOID*
+EFIAPI
+EepromFreePool (
+  IN  VOID  *Pointer
+  )
+{
+  if (Pointer != NULL) {
+    FreePool (Pointer);
+  }
+
+  return NULL;
+}
+
diff --git a/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/MemoryAllocationPei.c b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/MemoryAllocationPei.c
new file mode 100644
index 0000000000..250666ffbc
--- /dev/null
+++ b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/MemoryAllocationPei.c
@@ -0,0 +1,481 @@
+/** @file
+  Common EEPROM memory allocation code. This is necessary in PEI
+  becuase PEI doesn't have working FreePool code and this code
+  uses alot of pool allocation for temporary storage.
+
+  Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "EepromDataLib.h"
+
+#include <PiPei.h>
+#include <Library/EepromLib.h>
+#include <Library/HobLib.h>
+
+//
+// Desc:        Frees an existing EEPROM memory allocation from the EEPROM heap.
+// Variables:   HobPointer     Pointer to the EEPROM memory allocation HOB
+//              Offset         Pointer to the beginning of the pool to free
+// Return:      Status         EFI_SUCCESS           - Successfully freed pool
+//                             EFI_INVALID_PARAMETER - Invalid input parameter
+//
+EFI_STATUS
+EFIAPI
+ClearEepromAllocation (
+  IN EEPROM_ALLOCATION_STRUCT   *Header,
+  IN VOID                       *Offset
+  )
+{
+  UINT8         bit;
+  UINT16        ByteCount;
+  UINTN         HeapPointer;
+  UINTN         index;
+  UINT16        Size;
+  UINTN         StartIndex;
+  EFI_STATUS    Status;
+
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Starting...\n", __FUNCTION__, __LINE__));
+
+  //
+  // Initialize variables
+  //
+  HeapPointer  = (UINTN) Header + sizeof (EEPROM_ALLOCATION_STRUCT);
+  HeapPointer += 0x10 - (HeapPointer % 0x10);
+  Size         = 0;
+  StartIndex   = ((UINTN) Offset - HeapPointer) / 0x10;
+  Status       = EFI_SUCCESS;
+
+  //
+  // Sanity checks
+  //
+  if ((Header == NULL) || (Offset == NULL)) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Header or Offset is NULL!\n", __FUNCTION__, __LINE__));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  if (HeapPointer > (UINTN) Offset) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: HeapPointer > Offset!\n", __FUNCTION__, __LINE__));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  if (((UINTN) Offset % 0x10) != 0) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Offset not paragraph aligned [%08x]!\n", __FUNCTION__, __LINE__, Offset));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+
+  //
+  // Clear flags
+  //
+  for (index = StartIndex; index < (MAX_EEPROM_ALLOCATION_FLAG * 8); index++) {
+    ByteCount = (UINT16) (index / 8);
+    bit       = (1 << (index % 8));
+    // Check usage flag
+    if (Header->UsageFlag[ByteCount] & bit) {
+      // Used. Reset flag
+      Header->UsageFlag[ByteCount] &= ~bit;
+      Size++;
+    } else {
+      // Available. End of this allocation, bail.
+      break;
+    }
+  }
+
+Exit:
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Header = %08x\n", __FUNCTION__, __LINE__, Header));
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Size   = %08x\n", __FUNCTION__, __LINE__, Size * 0x10));
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Heap   = %08x\n", __FUNCTION__, __LINE__, HeapPointer));
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Start  = %08x\n", __FUNCTION__, __LINE__, StartIndex));
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Offset = %08x\n", __FUNCTION__, __LINE__, Offset));
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - Ending with %r\n", __FUNCTION__, __LINE__, Status));
+  }
+  return Status;
+}
+
+//
+// Desc:        Dumps the EEPROM memory allocation status.
+// Variables:   HobPointer     Pointer to the EEPROM memory allocation HOB
+// Return:      NA
+//
+VOID
+EFIAPI
+DumpAllocationTable (
+  IN EEPROM_ALLOCATION_STRUCT   *Header
+  )
+{
+  UINT8     bit;
+  UINT16    ByteCount;
+  UINTN     count;
+  UINTN     index;
+
+  if (mEepromDataLibDebugFlag) {
+    //
+    // Loop thru and display blocks
+    //
+    count = 0;
+    for (index = 0; index < (MAX_EEPROM_ALLOCATION_FLAG * 8); index++) {
+      ByteCount = (UINT16) (index / 8);
+      bit       = (1 << (index % 8));
+      if (count == 0) {
+        DEBUG ((DEBUG_INFO, "%04x - ", index));
+      }
+      // Check usage flag
+      if (Header->UsageFlag[ByteCount] & bit) {
+        // Used.
+        DEBUG ((DEBUG_INFO, "*"));
+      } else {
+        // Available
+        DEBUG ((DEBUG_INFO, " "));
+      }
+      count++;
+      if (count == (8 * 8)) {
+        DEBUG ((DEBUG_INFO, "\n"));
+        count = 0;
+      }
+    }
+  }
+}
+
+//
+// Desc:        Finds the first fit for the requested pool size.
+// Variables:   HobPointer     Pointer to the EEPROM memory allocation HOB
+//              Size           Size of the requested pool
+// Return:      Pointer        Pointer to the pool or NULL if no room
+//
+VOID*
+EFIAPI
+FindEepromAllocationOffset (
+  IN EEPROM_ALLOCATION_STRUCT   *Header,
+  IN UINT16                      Size
+  )
+{
+  UINT8     bit;
+  UINTN     beginingIndex;
+  UINT16    ByteCount;
+  UINT16    CurrentSize;
+  UINTN     HeapPointer;
+  UINTN     index;
+  VOID     *ReturnPointer;
+  UINTN     StartIndex;
+
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Starting...\n", __FUNCTION__, __LINE__));
+
+  //
+  // Initialize variables
+  //
+  CurrentSize    = 0;
+  HeapPointer    = (UINTN) Header + sizeof (EEPROM_ALLOCATION_STRUCT);
+  HeapPointer   += 0x10 - (HeapPointer % 0x10);
+  ReturnPointer  = NULL;
+  StartIndex     = 0;
+
+  //
+  // Sanity checks
+  //
+  if (Header == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Header is NULL!\n", __FUNCTION__, __LINE__));
+    goto Exit;
+  }
+  if ((Size == 0) || (Size > MAX_EEPROM_ALLOCATION_SIZE)) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Size is either 0 or > %08x!\n", __FUNCTION__, __LINE__, MAX_EEPROM_ALLOCATION_SIZE));
+    goto Exit;
+  }
+
+  //
+  // Loop thru flags looking for enough to make up size
+  // - Size is in flag units already
+  //
+  if (Size < 0x20) {
+    // For small allocations
+    beginingIndex = 0;
+  } else {
+    // For larger allocations
+    beginingIndex = 0x20;
+  }
+  for (index = beginingIndex; index < (MAX_EEPROM_ALLOCATION_FLAG * 8); index++) {
+    ByteCount = (UINT16) (index / 8);
+    bit       = (1 << (index % 8));
+    // Check usage flag
+    if (Header->UsageFlag[ByteCount] & bit) {
+      // Used. Reset count.
+      CurrentSize = 0;
+    } else {
+      // Available
+      if ((index == 0) || ((CurrentSize == 1) && (index != 1))) {
+        // Block after empty block, except first block
+        StartIndex = index;
+      }
+      CurrentSize++;
+    }
+    // Do we have enough room?
+    if (CurrentSize > Size) {
+      // Yep. Set usage flags, leaving the last one cleared.
+      for (index = StartIndex; index < StartIndex + Size; index++) {
+        ByteCount = (UINT16) (index / 8);
+        bit       = (1 << (index % 8));
+        Header->UsageFlag[ByteCount] |= bit;
+      }
+      // Set pointer
+      ReturnPointer = (VOID *) (HeapPointer + (StartIndex * 0x10));
+      // Bail
+      break;
+    }
+  }
+
+  //
+  // Display error if no room
+  //
+  if (ReturnPointer == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: No room on heap!\n", __FUNCTION__, __LINE__));
+  }
+
+Exit:
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Header = %08x\n", __FUNCTION__, __LINE__, Header));
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Size   = %08x\n", __FUNCTION__, __LINE__, Size * 0x10));
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Heap   = %08x\n", __FUNCTION__, __LINE__, HeapPointer));
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Start  = %08x\n", __FUNCTION__, __LINE__, StartIndex));
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Offset = %08x\n", __FUNCTION__, __LINE__, ReturnPointer));
+  return ReturnPointer;
+}
+
+//
+// Desc:        Finds or allocates a memory buffer for the PEI EEPROM code to use as a heap.
+// Variables:   NA
+// Return:      Pointer        Eeprom Memory HOB
+//
+EEPROM_ALLOCATION_STRUCT*
+EFIAPI
+GetEepromMemoryHob (VOID)
+{
+  EEPROM_ALLOCATION_STRUCT      AllocationHeader;
+  EEPROM_ALLOCATION_STRUCT     *HeaderPointer;
+  EFI_HOB_GUID_TYPE            *GuidHobPtr;
+
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Starting...\n", __FUNCTION__, __LINE__));
+
+  //
+  // If HOB already there, just return pointer to it
+  //
+  GuidHobPtr = GetFirstGuidHob (&gEepromVariableGuid);
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - GuidHobPtr = %08x\n", __FUNCTION__, __LINE__, GuidHobPtr));
+  while (GuidHobPtr != NULL) {
+    //
+    // Get Memory HOB header pointer
+    //
+    HeaderPointer = GET_GUID_HOB_DATA (GuidHobPtr);
+    if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - HeaderPointer = %08x\n", __FUNCTION__, __LINE__, HeaderPointer));
+    //
+    // Is this our block?
+    //
+    if (HeaderPointer->Signature == ALLOCATION_HOB_HEADER_SIGNATURE) {
+      //
+      // Yep
+      //
+      goto Exit;
+    }
+    //
+    // Skip past present HOB to get next HOB
+    //
+    GuidHobPtr = GET_NEXT_HOB (GuidHobPtr);
+    GuidHobPtr = GetNextGuidHob (&gEepromVariableGuid, GuidHobPtr);
+    if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - GuidHobPtr = %08x\n", __FUNCTION__, __LINE__, GuidHobPtr));
+  }
+
+  //
+  // Create HOB
+  //
+  DisplayStackPointer (__FUNCTION__, __LINE__);
+  ZeroMem (&AllocationHeader, sizeof (EEPROM_ALLOCATION_STRUCT));
+  AllocationHeader.Signature = ALLOCATION_HOB_HEADER_SIGNATURE;
+  HeaderPointer = BuildGuidDataHob (&gEepromVariableGuid, &AllocationHeader, MAX_EEPROM_HOB_SIZE);
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - HeaderPointer = %08x\n", __FUNCTION__, __LINE__, HeaderPointer));
+  DisplayStackPointer (__FUNCTION__, __LINE__);
+
+Exit:
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - AllocationHob @ %08x\n", __FUNCTION__, __LINE__, HeaderPointer));
+  return HeaderPointer;
+}
+
+//
+// Desc:        Copies the contents of an existing memory pool into a new memory pool of equal or greater size.
+// Variables:   Size           Size of the pool to copy existing pool into
+//              SourcePointer  Pointer to the source buffer to copy
+// Return:      Pointer        Pointer to your copy of the pool
+//
+VOID*
+EFIAPI
+EepromAllocateCopyPool (
+  IN  UINTN    Size,
+  IN  VOID    *SourcePointer
+  )
+{
+  VOID    *PoolPointer;
+
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Starting...\n", __FUNCTION__, __LINE__));
+
+  //
+  // Sanity checks
+  //
+  if (SourcePointer == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: SourcePointer is NULL!\n", __FUNCTION__, __LINE__));
+    PoolPointer = NULL;
+    goto Exit;
+  }
+  if ((Size == 0) || (Size > MAX_EEPROM_ALLOCATION_SIZE)) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Size is either 0 or > %08x!\n", __FUNCTION__, __LINE__, MAX_EEPROM_ALLOCATION_SIZE));
+    PoolPointer = NULL;
+    goto Exit;
+  }
+
+  //
+  // Get pool for copy
+  //
+  PoolPointer = EepromAllocatePool (Size);
+  if (PoolPointer == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: PoolPointer is NULL!\n", __FUNCTION__, __LINE__));
+    goto Exit;
+  }
+
+  //
+  // Copy source into new pool
+  //
+  CopyMem (PoolPointer, SourcePointer, Size);
+
+Exit:
+  return PoolPointer;
+}
+
+//
+// Desc:        Creates a new memory pool.
+// Variables:   Size           Size of the pool requested
+// Return:      Pointer        Pointer the new pool
+//
+VOID*
+EFIAPI
+EepromAllocatePool (
+  IN  UINTN   Size
+  )
+{
+  EEPROM_ALLOCATION_STRUCT   *AllocationHobHeader;
+  UINT16                      ConvertedSize;
+  UINT16                      PoolSize;
+  VOID                       *ReturnPointer;
+
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Starting...\n", __FUNCTION__, __LINE__));
+
+  //
+  // Sanity checking
+  //
+  if ((Size == 0) || (Size > MAX_EEPROM_ALLOCATION_SIZE)) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Size is either 0 or > %08x!\n", __FUNCTION__, __LINE__, MAX_EEPROM_ALLOCATION_SIZE));
+    ReturnPointer = NULL;
+    goto Exit;
+  }
+
+  //
+  // Convert size to paragraphs and add one for the guard
+  //
+  ConvertedSize  = (UINT16) (Size & 0xFFFF);
+  PoolSize       = ConvertedSize / 0x10;
+  if ((ConvertedSize % 0x10) > 0) {
+    //
+    // Size it up to the next paragraph
+    //
+    PoolSize++;
+  }
+
+  //
+  // Get or create EEPROM allocation pool HOB
+  //
+  AllocationHobHeader = GetEepromMemoryHob ();
+  if (AllocationHobHeader == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: AllocationHobHeader is NULL!\n", __FUNCTION__, __LINE__));
+    ReturnPointer = NULL;
+    goto Exit;
+  }
+
+  //
+  // Find first available fit and set usage flags
+  //
+  ReturnPointer = FindEepromAllocationOffset (AllocationHobHeader, PoolSize);
+  if (ReturnPointer == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: ReturnPointer is NULL!\n", __FUNCTION__, __LINE__));
+    goto Exit;
+  }
+
+  //
+  // Zero pool
+  //
+  ZeroMem (ReturnPointer, Size);
+
+  //
+  // Dump pool
+  //
+  DumpAllocationTable (AllocationHobHeader);
+
+Exit:
+  return ReturnPointer;
+}
+
+//
+// Desc:        Frees a memory pool.
+// Variables:   Pointer        Pointer to the beginning of the pool to be freed
+// Return:      Pointer        NULL
+//
+VOID*
+EFIAPI
+EepromFreePool (
+  IN  VOID  *Pointer
+  )
+{
+  EEPROM_ALLOCATION_STRUCT   *AllocationHobHeader;
+  EFI_STATUS                  Status;
+
+  if (mEepromDataLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Starting...\n", __FUNCTION__, __LINE__));
+
+  //
+  // Get EEPROM allocation pool HOB
+  //
+  AllocationHobHeader = GetEepromMemoryHob ();
+  if (AllocationHobHeader == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: AllocationHobHeader is NULL!\n", __FUNCTION__, __LINE__));
+    goto Exit;
+  }
+
+  //
+  // Sanity checks
+  //
+  if (Pointer == NULL) {
+    // Nothing to do. Bail.
+    goto Exit;
+  }
+  if ((UINTN) Pointer > ((UINTN) AllocationHobHeader + MAX_EEPROM_ALLOCATION_SIZE)) {
+    // Past our heap. Bail.
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: This is not our pool [%08x]!\n", __FUNCTION__, __LINE__, Pointer));
+    goto Exit;
+  }
+
+  //
+  // Find allocation and clear usage flags
+  //
+  Status = ClearEepromAllocation (AllocationHobHeader, Pointer);
+
+  //
+  // Dump pool
+  //
+  DumpAllocationTable (AllocationHobHeader);
+
+Exit:
+  return NULL;
+}
+
diff --git a/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/Null/EepromDataNullLib.c b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/Null/EepromDataNullLib.c
new file mode 100644
index 0000000000..6ac9a16b57
--- /dev/null
+++ b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/Null/EepromDataNullLib.c
@@ -0,0 +1,67 @@
+/** @file
+  Null EEPROM raw data library instance.
+
+  Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "EepromDataNullLib.h"
+
+//
+// Desc:        Reads from the EEPROM and copies to the passed in buffer.
+// Variables:   Offset         Start copying from the offset
+//              Size           Size of the buffer and the number of bytes to copy
+//                             - If set to 0, then return size of EEPROM binary
+//              Buffer         Storage buffer for the copied data from the EEPROM
+//              FunctionInfo   Pointer to function specific data
+// Return:      EFI_SUCCESS             Data copied successfully
+//              EFI_UNSUPPORTED         This function is not supported
+//              EFI_INVALID_PARAMETER   One of the parameters is invalid
+//              EFI_NOT_READY           Called before all necessary protocols available
+//              EFI_DEVICE_ERROR        Communication error with device
+//
+EFI_STATUS
+EFIAPI
+ReadEepromNull (
+  IN       UINT32    Offset,
+  IN OUT   UINT32   *Size,
+  IN OUT   UINT8    *Buffer,
+  IN OUT   VOID     *FunctionInfo
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+//
+// Desc:        Writes to the EEPROM and copies to the passed in buffer.
+// Variables:   Offset         Start copying from the offset
+//              Size           Size of the buffer and the number of bytes to copy
+//                             - If set to 0, then return size of EEPROM binary
+//              Buffer         Data to be copied to the EEPROM
+//              FunctionInfo   Pointer to function specific data
+// Return:      EFI_SUCCESS             Data copied successfully
+//              EFI_UNSUPPORTED         This function is not supported
+//              EFI_INVALID_PARAMETER   One of the parameters is invalid
+//              EFI_NOT_READY           Called before all necessary protocols available
+//              EFI_DEVICE_ERROR        Communication error with device
+//
+EFI_STATUS
+EFIAPI
+WriteEepromNull (
+  IN       UINT32    Offset,
+  IN OUT   UINT32   *Size,
+  IN OUT   UINT8    *Buffer,
+  IN OUT   VOID     *FunctionInfo
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
diff --git a/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/Null/EepromDataNullLib.h b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/Null/EepromDataNullLib.h
new file mode 100644
index 0000000000..255cdec9d1
--- /dev/null
+++ b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromDataLib/Null/EepromDataNullLib.h
@@ -0,0 +1,24 @@
+/** @file
+  Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _EEPROM_DATA_NULL_LIB_
+#define _EEPROM_DATA_NULL_LIB_
+////
+//// Header files
+////
+#include <Uefi.h>
+
+#include <Library/DebugLib.h>
+#include <Library/EepromDataLib.h>
+
+#endif // _EEPROM_DATA_NULL_LIB_
-- 
2.14.1.windows.1



^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [Patch][edk2-platforms/devel-IntelAtomProcessorE3900 4/5] Common EEPROM library instance.
  2018-07-23  2:39 [Patch][edk2-platforms/devel-IntelAtomProcessorE3900 1/5] Add EepromApp zwei4
  2018-07-23  2:39 ` [Patch][edk2-platforms/devel-IntelAtomProcessorE3900 3/5] Library producing EEPROM raw data functionality zwei4
@ 2018-07-23  2:39 ` zwei4
  2018-07-23  2:39 ` [Patch][edk2-platforms/devel-IntelAtomProcessorE3900 5/5] EEPROM header files zwei4
  2 siblings, 0 replies; 4+ messages in thread
From: zwei4 @ 2018-07-23  2:39 UTC (permalink / raw)
  To: edk2-devel; +Cc: David Wei, Kelly Steele, Mike Wu, Mang Guo

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: David Wei <david.wei@intel.com>
CC: Kelly Steele <kelly.steele@intel.com>
CC: Mike Wu  <mike.wu@intel.com>
CC: Mang Guo <mang.guo@intel.com>
---
 .../Common/Features/Eeprom/EepromLib/EepromLib.c   | 1011 ++++++++++++++++++++
 .../Common/Features/Eeprom/EepromLib/EepromLib.h   |   76 ++
 .../Common/Features/Eeprom/EepromLib/EepromLib.inf |   63 ++
 .../Features/Eeprom/EepromLib/EepromNullLib.inf    |   36 +
 .../Features/Eeprom/EepromLib/EepromPeiLib.inf     |   62 ++
 .../Features/Eeprom/EepromLib/Null/EepromNullLib.c |   82 ++
 .../Features/Eeprom/EepromLib/Null/EepromNullLib.h |   26 +
 .../Eeprom/EepromLib/Pei/ValidateHashPei.c         |  251 +++++
 .../Features/Eeprom/EepromLib/ValidateHash.c       |  399 ++++++++
 9 files changed, 2006 insertions(+)
 create mode 100644 Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromLib/EepromLib.c
 create mode 100644 Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromLib/EepromLib.h
 create mode 100644 Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromLib/EepromLib.inf
 create mode 100644 Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromLib/EepromNullLib.inf
 create mode 100644 Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromLib/EepromPeiLib.inf
 create mode 100644 Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromLib/Null/EepromNullLib.c
 create mode 100644 Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromLib/Null/EepromNullLib.h
 create mode 100644 Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromLib/Pei/ValidateHashPei.c
 create mode 100644 Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromLib/ValidateHash.c

diff --git a/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromLib/EepromLib.c b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromLib/EepromLib.c
new file mode 100644
index 0000000000..6ab06da2be
--- /dev/null
+++ b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromLib/EepromLib.c
@@ -0,0 +1,1011 @@
+/** @file
+  Common EEPROM library instance.
+
+  Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "EepromLib.h"
+
+BOOLEAN     *gImageValidFlag;
+UINT32       mCrcTable[256];
+BOOLEAN      mCrcInitFlag        = FALSE;
+BOOLEAN      mEepromLibDebugFlag = TRUE;
+
+/**
+  This internal function reverses bits for 32bit data.
+
+  @param  Value                 The data to be reversed.
+
+  @return                       Data reversed.
+
+**/
+UINT32
+EFIAPI
+ReverseBits (
+  UINT32  Value
+  )
+{
+  UINTN   Index;
+  UINT32  NewValue;
+
+  NewValue = 0;
+  for (Index = 0; Index < 32; Index++) {
+    if ((Value & (1 << Index)) != 0) {
+      NewValue = NewValue | (1 << (31 - Index));
+    }
+  }
+
+  return NewValue;
+}
+
+/**
+  Initialize CRC32 table.
+
+**/
+VOID
+EFIAPI
+InitializeCrc32Table (
+  VOID
+  )
+{
+  UINTN   TableEntry;
+  UINTN   Index;
+  UINT32  Value;
+
+  for (TableEntry = 0; TableEntry < 256; TableEntry++) {
+    Value = ReverseBits ((UINT32) TableEntry);
+    for (Index = 0; Index < 8; Index++) {
+      if ((Value & 0x80000000) != 0) {
+        Value = (Value << 1) ^ 0x04C11DB7;
+      } else {
+        Value = Value << 1;
+      }
+    }
+
+    mCrcTable[TableEntry] = ReverseBits (Value);
+  }
+  mCrcInitFlag = TRUE;
+}
+
+/*++
+
+Routine Description:
+
+  The CalculateCrc32 routine.
+
+Arguments:
+
+  Data        - The buffer contaning the data to be processed
+  DataSize    - The size of data to be processed
+  CrcOut      - A pointer to the caller allocated UINT32 that on
+                contains the CRC32 checksum of Data
+
+Returns:
+
+  EFI_SUCCESS               - Calculation is successful.
+  EFI_INVALID_PARAMETER     - Data / CrcOut = NULL, or DataSize = 0
+
+--*/
+EFI_STATUS
+EFIAPI
+CalculateCrc32 (
+  IN     UINT8    *Data,
+  IN     UINTN     DataSize,
+  IN OUT UINT32   *CrcOut
+  )
+{
+  UINT32  Crc;
+  UINTN   Index;
+  UINT8   *Ptr;
+
+  if (mEepromLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Starting...\n", __FUNCTION__, __LINE__));
+
+  // Sanity checks
+  if ((DataSize == 0) || (Data == NULL) || (CrcOut == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // Table initialized?
+  if (!mCrcInitFlag) InitializeCrc32Table ();
+
+  Crc = 0xFFFFFFFF;
+  for (Index = 0, Ptr = Data; Index < DataSize; Index++, Ptr++) {
+    Crc = (Crc >> 8) ^ mCrcTable[(UINT8) Crc ^ *Ptr];
+  }
+
+  *CrcOut = Crc ^ 0xFFFFFFFF;
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+EepromLibNemToMemory (VOID)
+{
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+EraseEeprom (
+  IN       UINT8    LibraryIndex
+  )
+{
+  UINT8                  *Buffer;
+  EEPROM_FUNCTION_INFO    EepromInfo;
+  UINT32                  Size;
+  EFI_STATUS              Status;
+
+  if (mEepromLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Starting...\n", __FUNCTION__, __LINE__));
+
+  //
+  // Initialize variables
+  //
+  ZeroMem (&EepromInfo, sizeof (EEPROM_FUNCTION_INFO));
+  EepromInfo.Bus          = PcdGet8 (PcdEepromBus);
+  EepromInfo.Address      = PcdGet8 (PcdEepromAddress);
+  EepromInfo.LibraryIndex = EEPROM_EEPROM;
+  Size                    = sizeof (GENERIC_HEADER);
+  Buffer                  = EepromAllocatePool (Size);
+
+  //
+  // Sanity checks
+  //
+  if (LibraryIndex >= EEPROM_DATA_LIBRARY_INDEX_MAX) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Library index is larger than %d!\n", __FUNCTION__, __LINE__, EEPROM_DATA_LIBRARY_INDEX_MAX - 1));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  if (Buffer == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Buffer pointer is NULL!\n", __FUNCTION__, __LINE__));
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Exit;
+  }
+
+  //
+  // Try to erase the first header, thereby invalidating the image.
+  //
+  Status = WriteEeprom (LibraryIndex, 0, &Size, Buffer, &EepromInfo);
+  if (EFI_ERROR (Status)) {
+    //
+    // Failed, so bail.
+    //
+    goto Exit;
+  }
+
+  //
+  // Clear the valid status for this image.
+  //
+  gImageValidFlag[LibraryIndex] = FALSE;
+
+Exit:
+  //
+  // Free resources
+  //
+  Buffer = EepromFreePool (Buffer);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - Ending with %r\n", __FUNCTION__, __LINE__, Status));
+  }
+  return Status;
+}
+
+EFI_STATUS
+EFIAPI
+GetEepromStructure (
+  IN       UINT8      LibraryIndex,
+  IN OUT   CHAR8      Signature[EEPROM_SIGNATURE_SIZE],
+  IN OUT   UINT8    **Buffer,
+  IN OUT   UINT32    *Size
+  )
+{
+  GENERIC_HEADER   *EepromHeader;
+  UINT32            Index;
+  EFI_STATUS        Status;
+
+  if (mEepromLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Starting...\n", __FUNCTION__, __LINE__));
+
+  //
+  // Initialize variables
+  //
+  EepromHeader = NULL;
+  Status       = EFI_SUCCESS;
+
+  //
+  // Sanity checks
+  //
+  if (LibraryIndex >= EEPROM_DATA_LIBRARY_INDEX_MAX) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Library index is larger than %d!\n", __FUNCTION__, __LINE__, EEPROM_DATA_LIBRARY_INDEX_MAX - 1));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  if (Signature == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Signature pointer is NULL!\n", __FUNCTION__, __LINE__));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  if (Buffer == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Buffer pointer is NULL!\n", __FUNCTION__, __LINE__));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  if (Size == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Size pointer is NULL!\n", __FUNCTION__, __LINE__));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+
+  //
+  // Start at the beginning structure and loop thru the image looking for the requested structure
+  //
+  Index = 0;
+  while (!EFI_ERROR (Status)) {
+    //
+    // Make sure buffer is empty
+    //
+    *Buffer = EepromFreePool (*Buffer);
+    Status = GetNextEepromStructure (LibraryIndex, &Index, Buffer, Size);
+    if (*Size != 0) {
+      //
+      // The buffer isn't empty
+      //
+      EepromHeader = (GENERIC_HEADER *) *Buffer;
+      if (AsciiStrnCmp (EepromHeader->signature, Signature, AsciiStrLen (Signature)) == 0) {
+        //
+        // This is our structure. Bail.
+        //
+        goto Exit;
+      }
+    }
+    *Buffer = EepromFreePool (*Buffer);
+  }
+
+  //
+  // Didn't find it. Error out.
+  //
+  DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Failed to find %a structure!\n", __FUNCTION__, __LINE__, Signature));
+  Status = EFI_NOT_FOUND;
+
+Exit:
+  if (EFI_ERROR (Status)) {
+    *Buffer = EepromFreePool (*Buffer);
+    *Size   = 0;
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - Ending with %r\n", __FUNCTION__, __LINE__, Status));
+  }
+  return Status;
+}
+
+UINT32
+EFIAPI
+GetImageSize (
+  IN       UINT8      LibraryIndex
+  )
+{
+  EEPROM_HEADER           EepromHeader;
+  EEPROM_FUNCTION_INFO    EepromInfo;
+  UINT32                  Size;
+  EFI_STATUS              Status;
+
+  if (mEepromLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Starting...\n", __FUNCTION__, __LINE__));
+
+  //
+  // Initialize variables
+  //
+  ZeroMem (&EepromInfo, sizeof (EEPROM_FUNCTION_INFO));
+  EepromInfo.Bus          = PcdGet8 (PcdEepromBus);
+  EepromInfo.Address      = PcdGet8 (PcdEepromAddress);
+  EepromInfo.LibraryIndex = EEPROM_EEPROM;
+
+  //
+  // Sanity checks
+  //
+  if (LibraryIndex >= EEPROM_DATA_LIBRARY_INDEX_MAX) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Library index is larger than %d!\n", __FUNCTION__, __LINE__, EEPROM_DATA_LIBRARY_INDEX_MAX - 1));
+    Size = 0;
+    goto Exit;
+  }
+
+  //
+  // Grab $Eeprom$ structure which should be the first structure at offset 0
+  //
+  Size = sizeof (EEPROM_HEADER);
+  ZeroMem (&EepromHeader, Size);
+  Status = ReadEeprom (LibraryIndex, 0, &Size, (UINT8 *) &EepromHeader, &EepromInfo);
+  if (EFI_ERROR (Status) || (AsciiStrnCmp (EepromHeader.signature, "$Eeprom$", 8) != 0)) {
+    //
+    // Oops!
+    //
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Failed to find $Eeprom$ structure!\n", __FUNCTION__, __LINE__));
+    //
+    // Try ReadEeprom() method
+    //
+    Size   = 0;
+    Status = ReadEeprom (LibraryIndex, 0, &Size, (UINT8 *) &EepromHeader, &EepromInfo);
+    if ((Status != EFI_BUFFER_TOO_SMALL) || (Status != EFI_SUCCESS)) {
+      //
+      // Didn't find size.
+      //
+      Status = EFI_NOT_FOUND;
+      goto Exit;
+    }
+  }
+
+  //
+  // Return size
+  //
+  Size = EepromHeader.structlength;
+  if (mEepromLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Image size = %08x\n", __FUNCTION__, __LINE__, Size));
+
+Exit:
+  return Size;
+}
+
+EFI_STATUS
+EFIAPI
+GetNextEepromStructure (
+  IN       UINT8      LibraryIndex,
+  IN OUT   UINT32    *Index,
+  IN OUT   UINT8    **Buffer,
+  IN OUT   UINT32    *Size
+  )
+{
+  CHAR8                  *AsciiString;
+  EEPROM_FUNCTION_INFO    EepromInfo;
+  UINT32                  ImageSize;
+  UINT32                  Offset;
+  EFI_STATUS              Status;
+  GENERIC_HEADER          Structure;
+  UINT8                  *TempBuffer;
+  UINT32                  TempSize;
+
+  if (mEepromLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Starting...\n", __FUNCTION__, __LINE__));
+
+  //
+  // Initialize variables
+  //
+  ZeroMem (&EepromInfo, sizeof (EEPROM_FUNCTION_INFO));
+  EepromInfo.Bus          = PcdGet8 (PcdEepromBus);
+  EepromInfo.Address      = PcdGet8 (PcdEepromAddress);
+  EepromInfo.LibraryIndex = EEPROM_EEPROM;
+  Status                  = EFI_SUCCESS;
+  TempBuffer              = NULL;
+  TempSize                = 0;
+
+  //
+  // Sanity checks
+  //
+  if (LibraryIndex >= EEPROM_DATA_LIBRARY_INDEX_MAX) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Library index is larger than %d!\n", __FUNCTION__, __LINE__, EEPROM_DATA_LIBRARY_INDEX_MAX - 1));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  if (Buffer == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Buffer pointer is NULL!\n", __FUNCTION__, __LINE__));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  if (Size == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Size pointer is NULL!\n", __FUNCTION__, __LINE__));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+
+  //
+  // Make sure the incoming buffer is empty
+  //
+  *Buffer = EepromFreePool (*Buffer);
+  *Size   = 0;
+
+  //
+  // Grab the image size
+  //
+  ImageSize = GetImageSize (LibraryIndex);
+  if (ImageSize == 0) {
+    //
+    // Oops!
+    //
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Failed to get image size!\n", __FUNCTION__, __LINE__));
+    Status = EFI_NOT_FOUND;
+    goto Exit;
+  }
+
+  //
+  // Paragraph align offset
+  //
+  Offset = *Index + (*Index % 0x10);
+
+  //
+  // Sanity check to make sure we are still in the image
+  //
+  if (Offset >= ImageSize) {
+    if (mEepromLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - WARNING: Went past the end of the image!\n", __FUNCTION__, __LINE__));
+    Status = EFI_END_OF_FILE;
+    goto Exit;
+  }
+  
+  //
+  // Read in the next header
+  //
+  TempSize = sizeof (GENERIC_HEADER);
+  Status = ReadEeprom (LibraryIndex, Offset, &TempSize, (UINT8 *) &Structure, &EepromInfo);
+  if (EFI_ERROR (Status)) {
+    //
+    // Got an error!
+    //
+    goto Exit;
+  }
+  //
+  // Check to see if this is a valid structure
+  //
+  if (Structure.signature[0] != '$') {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Failed to find structure signature starting with $!\n", __FUNCTION__, __LINE__));
+    Status = EFI_VOLUME_CORRUPTED;
+    goto Exit;
+  }
+
+  //
+  // This is our structure!
+  //
+  TempSize   = Structure.length;
+  TempBuffer = EepromAllocatePool (TempSize);
+  if (TempBuffer == NULL) {
+    //
+    // Failed to allocate pool
+    //
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Failed to allocate pool for Buffer!\n", __FUNCTION__, __LINE__));
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Exit;
+  }
+
+  //
+  // Some debug info
+  //
+  AsciiString = Structure.signature;
+  AsciiString[sizeof (Structure.signature)] = 0;
+  if (mEepromLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Structure[%04x] = %a\n", __FUNCTION__, __LINE__, Offset, AsciiString));
+
+  //
+  // Grab the structure
+  //
+  Status = ReadEeprom (LibraryIndex, Offset, &TempSize, TempBuffer, &EepromInfo);
+  if (mEepromLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - ReadEeprom() -> %r\n", __FUNCTION__, __LINE__, Status));
+  if (!EFI_ERROR (Status)) {
+    //
+    // Got a valid structure. Point Index to end of the structure..
+    //
+    *Index = Offset + TempSize;
+    //
+    // Pass out data
+    //
+    *Buffer = TempBuffer;
+    *Size   = TempSize;
+  }
+
+Exit:
+  if (EFI_ERROR (Status)) {
+    TempBuffer = EepromFreePool (TempBuffer);
+    if (Status != EFI_END_OF_FILE) {
+      DEBUG ((DEBUG_ERROR, "%a (#%4d) - Ending with %r\n", __FUNCTION__, __LINE__, Status));
+    }
+  }
+  return Status;
+}
+
+UINT8
+EFIAPI
+GetValidEepromLibrary (
+  IN       BOOLEAN   CopyToMemory,
+  IN       BOOLEAN   MemoryInitialized
+  )
+{
+  UINT8                  *EepromAutoList;
+  EEPROM_FUNCTION_INFO    EepromInfo;
+  UINT8                   FirstValidImage;
+  UINT8                  *ImageBuffer;
+  UINT32                  ImageSize;
+  UINT8                   index;
+  UINT8                   Library;
+  UINT32                  Size;
+  EFI_STATUS              Status;
+
+  if (mEepromLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Starting...\n", __FUNCTION__, __LINE__));
+
+  //
+  // Initialize variables
+  //
+  ZeroMem (&EepromInfo, sizeof (EEPROM_FUNCTION_INFO));
+  EepromAutoList          = (UINT8 *) PcdGetPtr (PcdEepromAutoPriority);
+  EepromInfo.Bus          = PcdGet8 (PcdEepromBus);
+  EepromInfo.Address      = PcdGet8 (PcdEepromAddress);
+  EepromInfo.LibraryIndex = EEPROM_EEPROM;
+  FirstValidImage         = EEPROM_NULL;
+  ImageBuffer             = NULL;
+
+  //
+  // Sanity checks
+  //
+  if (EepromAutoList == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: PCD PcdEepromAutoPriority is empty!\n", __FUNCTION__, __LINE__));
+    Library = EEPROM_NULL;
+    goto Exit;
+  }
+
+  //
+  // Display current stack pointer
+  //
+  DisplayStackPointer (__FUNCTION__, __LINE__);
+
+  //
+  // Loop thru PcdEepromAutoPriority looking for a validated image.
+  //
+  index = 0;
+  while (EepromAutoList[index] != 0xFF) {
+    Library = EepromAutoList[index];
+    if (Library >= EEPROM_DATA_LIBRARY_INDEX_MAX) {
+      //
+      // We're in the weeds. Bail.
+      //
+      DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: PCD PcdEepromAutoPriority contains invalid value!\n", __FUNCTION__, __LINE__));
+      Library = EEPROM_NULL;
+      goto Exit;
+    }
+    if (gImageValidFlag[Library]) {
+      //
+      // This library is valid, bail.
+      //
+      FirstValidImage = Library;
+      break;
+    }
+    //
+    // Point to next library
+    //
+    index++;
+  }
+  //
+  // Check to see if we need to validate and copy into memory
+  //
+  if (!CopyToMemory) {
+    //
+    // Nope. Bail.
+    //
+    goto Exit;
+  }
+  //
+  // Display current stack pointer
+  //
+  DisplayStackPointer (__FUNCTION__, __LINE__);
+  //
+  // If nothing is valid, try validating them all
+  //
+  if (FirstValidImage == EEPROM_NULL) {
+    //
+    // Couldn't find a validated image. Try validating them all.
+    //
+    index = 0;
+    while (EepromAutoList[index] != 0xFF) {
+      Library = EepromAutoList[index];
+      if (mEepromLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Trying to validate library %a...\n", __FUNCTION__, __LINE__, mEepromLibraryString[Library]));
+      Status = ValidateEeprom (Library);
+      if (mEepromLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Validating %a -> %r\n", __FUNCTION__, __LINE__, mEepromLibraryString[Library], Status));
+      if (!EFI_ERROR (Status) || (Status == EFI_MEDIA_CHANGED)) {
+        //
+        // This one is valid. Bail.
+        //
+        if (FirstValidImage == EEPROM_NULL) {
+          FirstValidImage = Library;
+        }
+      }
+      //
+      // Point to next library
+      //
+      index++;
+    }
+  }
+  //
+  // Display current stack pointer
+  //
+  DisplayStackPointer (__FUNCTION__, __LINE__);
+  //
+  // Determine which image to copy to memory
+  //
+  if (gImageValidFlag[EEPROM_MEMORY]) {
+    //
+    // Yep. Bail.
+    //
+    Library = EEPROM_MEMORY;
+    goto Exit;
+  }
+  if (gImageValidFlag[EEPROM_EEPROM]) {
+    Library = EEPROM_EEPROM;
+  }
+  if (gImageValidFlag[EEPROM_FV]) {
+    Library = EEPROM_FV;
+  }
+  if (gImageValidFlag[EEPROM_EEPROM] && gImageValidFlag[EEPROM_FV]) {
+    BOARD_INFO_TABLE   *EepromBoardInfo;
+    BOARD_INFO_TABLE   *FvBoardInfo;
+    EEPROM_HEADER      *EepromEepromHeader;
+    EEPROM_HEADER      *FvEepromHeader;
+    //
+    // Initialize variables
+    //
+    EepromBoardInfo    = NULL;
+    EepromEepromHeader = NULL;
+    FvBoardInfo        = NULL;
+    FvEepromHeader     = NULL;
+    Library            = EEPROM_NULL;
+    //
+    // Get BoardInfo records
+    //
+    Size = 0;
+    Status = GetEepromStructure (EEPROM_EEPROM, "$BrdInfo", (UINT8 **) &EepromBoardInfo, &Size);
+    if (EFI_ERROR (Status) || (Size == 0) || (EepromBoardInfo == NULL)) {
+      DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Failed to get EEPROM Board Info structure! (%r)\n", __FUNCTION__, __LINE__, Status));
+      Library = EEPROM_FV;
+    } else {
+      Size = 0;
+      Status = GetEepromStructure (EEPROM_FV, "$BrdInfo", (UINT8 **) &FvBoardInfo, &Size);
+      if (EFI_ERROR (Status) || (Size == 0) || (FvBoardInfo == NULL)) {
+        DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Failed to get FV Board Info structure! (%r)\n", __FUNCTION__, __LINE__, Status));
+        Library = EEPROM_EEPROM;
+      } else {
+        //
+        // Compare BoardInfo records
+        //
+        if ((CompareMem (EepromBoardInfo->manuname, FvBoardInfo->manuname, 16) == 0) &&
+            (CompareMem (EepromBoardInfo->brdname,  FvBoardInfo->brdname, 16)  == 0) &&
+            (EepromBoardInfo->boardid   == FvBoardInfo->boardid)                     &&
+            (EepromBoardInfo->fabid     == FvBoardInfo->fabid)                       &&
+            (EepromBoardInfo->ecid      == FvBoardInfo->ecid)                        &&
+            (EepromBoardInfo->boardtype == FvBoardInfo->boardtype)) {
+          //
+          // Get EepromHeader records
+          //
+          Size = 0;
+          Status = GetEepromStructure (EEPROM_EEPROM, "$Eeprom$", (UINT8 **) &EepromEepromHeader, &Size);
+          if (EFI_ERROR (Status) || (Size == 0) || (EepromEepromHeader == NULL)) {
+            DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Failed to get EEPROM header structure! (%r)\n", __FUNCTION__, __LINE__, Status));
+            Library = EEPROM_FV;
+          } else {
+            Size = 0;
+            Status = GetEepromStructure (EEPROM_FV, "$Eeprom$", (UINT8 **) &FvEepromHeader, &Size);
+            if (EFI_ERROR (Status) || (Size == 0) || (FvEepromHeader == NULL)) {
+              DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Failed to get FV header structure! (%r)\n", __FUNCTION__, __LINE__, Status));
+              Library = EEPROM_EEPROM;
+            } else {
+              //
+              // Compare image versions
+              //
+              if (EepromEepromHeader->version > FvEepromHeader->version) {
+                Library = EEPROM_EEPROM;
+              } else {
+                Library = EEPROM_FV;
+              }
+            }
+          }
+        } else {
+          //
+          // FV gets priority since BoardInfo data doesn't match
+          //
+          Library = EEPROM_FV;
+        }
+      }
+    }
+    //
+    // Free resources
+    //
+    EepromBoardInfo    = EepromFreePool (EepromBoardInfo);
+    EepromEepromHeader = EepromFreePool (EepromEepromHeader);
+    FvBoardInfo        = EepromFreePool (FvBoardInfo);
+    FvEepromHeader     = EepromFreePool (FvEepromHeader);
+  }
+  //
+  // Display current stack pointer
+  //
+  DisplayStackPointer (__FUNCTION__, __LINE__);
+  //
+  // If we don't have memory, then bail so we don't take up all of the stack space in NEM.
+  //
+  if (!MemoryInitialized) {
+    goto Exit;
+  }
+  //
+  // We have a validated image and it is not in memory. Copy it in.
+  // 1. Ask for the image size so we can allocate a large enough buffer.
+  // 2. Read the image into the buffer.
+  // 3. Write it to memory.
+  // 4. Validate the memory copy.
+  //
+  DEBUG ((DEBUG_INFO, "%a (#%4d) - Copying %a to EEPROM_MEMORY\n", __FUNCTION__, __LINE__, mEepromLibraryString[Library]));
+  ImageSize = GetImageSize (Library);
+  if (ImageSize != 0) {
+    //
+    // Something to copy
+    //
+    ImageBuffer = EepromAllocatePool (ImageSize);
+    if (ImageBuffer == NULL) {
+      DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Failed to allocate pool!\n", __FUNCTION__, __LINE__));
+    } else {
+      //
+      // Read in entire image
+      //
+      Status = ReadEeprom (Library, 0, &ImageSize, ImageBuffer, &EepromInfo);
+      if (EFI_ERROR (Status)) {
+        DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Reading image from %a returned %r!\n", __FUNCTION__, __LINE__, mEepromLibraryString[Library], Status));
+      } else {
+        //
+        // Got the image, write to memory
+        //
+        Status = WriteEeprom (EEPROM_MEMORY, 0, &ImageSize, ImageBuffer, NULL);
+        if (EFI_ERROR (Status)) {
+          DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Writing image to %a returned %r!\n", __FUNCTION__, __LINE__, mEepromLibraryString[EEPROM_MEMORY], Status));
+        } else {
+          //
+          // Validate memory image
+          //
+          Status = ValidateEeprom (EEPROM_MEMORY);
+          if (EFI_ERROR (Status) && (Status != EFI_MEDIA_CHANGED)) {
+            DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Validating image returned %r!\n", __FUNCTION__, __LINE__, Status));
+          } else {
+            //
+            // Return EEPROM_MEMORY
+            //
+            Library = EEPROM_MEMORY;
+          }
+        }
+      }
+    }
+  }
+
+Exit:
+  //
+  // Free resources
+  //
+  ImageBuffer = EepromFreePool (ImageBuffer);
+  if (FirstValidImage == EEPROM_NULL) {
+    //
+    // Nothing is valid. Return default NULL.
+    //
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Failed to find a valid image in list PcdEepromAutoPriority!\n", __FUNCTION__, __LINE__));
+    Library = EEPROM_NULL;
+  }
+
+  //
+  // Display current stack pointer
+  //
+  DisplayStackPointer (__FUNCTION__, __LINE__);
+
+  if (mEepromLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Returning library %a\n", __FUNCTION__, __LINE__, mEepromLibraryString[Library]));
+  return Library;
+}
+
+EFI_STATUS
+EFIAPI
+ValidateEeprom (
+  IN       UINT8    LibraryIndex
+  )
+{
+  UINT32                  Count;
+  UINT32                  Crc32;
+  UINT32                  Crc32Size;
+  EEPROM_HEADER          *EepromHeader;
+  EEPROM_FUNCTION_INFO    EepromInfo;
+  UINT8                  *Hash;
+  UINT32                  HashSize;
+  UINT16                  HashType;
+  UINT8                  *ImageBuffer;
+  UINT32                  ImageSize;
+  SIGNATURE_DATA         *Signature;
+  UINT8                  *SignedHash;
+  UINT32                  SignedHashSize;
+  EFI_STATUS              Status;
+  GENERIC_HEADER         *Structure;
+  INTN                    Test;
+
+  if (mEepromLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Starting...\n", __FUNCTION__, __LINE__));
+
+  //
+  // Initialize variables
+  //
+  ZeroMem (&EepromInfo, sizeof (EEPROM_FUNCTION_INFO));
+  Crc32Size               = 0;
+  EepromHeader            = NULL;
+  EepromInfo.Bus          = PcdGet8 (PcdEepromBus);
+  EepromInfo.Address      = PcdGet8 (PcdEepromAddress);
+  EepromInfo.LibraryIndex = EEPROM_EEPROM;
+  Hash                    = NULL;
+  ImageBuffer             = NULL;
+  SignedHash              = NULL;
+  SignedHashSize          = 0;
+  Status                  = EFI_SUCCESS;
+  Structure               = NULL;
+
+  //
+  // Sanity checks
+  //
+  if (LibraryIndex >= EEPROM_DATA_LIBRARY_INDEX_MAX) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Library index is larger than %d!\n", __FUNCTION__, __LINE__, EEPROM_DATA_LIBRARY_INDEX_MAX - 1));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+
+  //
+  // Get image size
+  //
+  ImageSize = GetImageSize (LibraryIndex);
+  if (ImageSize == 0) {
+    //
+    // Oops!
+    //
+    Status = EFI_NOT_FOUND;
+    goto Exit;
+  }
+  //
+  // Get a buffer to hold the image
+  //
+  ImageBuffer = EepromAllocatePool (ImageSize);
+  if (ImageBuffer == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Unable to allocate 0x%08x bytes for the image buffer!\n", __FUNCTION__, __LINE__, ImageSize));
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Exit;
+  }
+  //
+  // Read in the image
+  //
+  Status = ReadEeprom (LibraryIndex, 0, &ImageSize, ImageBuffer, &EepromInfo);
+  if (EFI_ERROR (Status)) {
+    //
+    // Oops!!!
+    //
+    goto Exit;
+  }
+  EepromHeader = (EEPROM_HEADER *) ImageBuffer;
+  //
+  // Verify structure order
+  //
+  Count     = 0;
+  Structure = (GENERIC_HEADER *) ImageBuffer;
+  while ((UINT8 *) Structure < (UINT8 *) (ImageBuffer + ImageSize)) {
+    //
+    // Increment count
+    //
+    Count++;
+    //
+    // Sanity check header
+    //
+    if (Count == 1) {
+      //
+      // First structure must be $Eeprom$
+      //
+      Test = AsciiStrnCmp (Structure->signature, "$Eeprom$", 8);
+      //
+      // Set CRC32 size
+      //
+      Crc32Size = EepromHeader->crclength;
+    } else if (Count == 2) {
+      //
+      // Second structure must be $EeprMap
+      //
+      Test = AsciiStrnCmp (Structure->signature, "$EeprMap", 8);
+    } else if (Count == 3) {
+      //
+      // Third structure must be $BrdInfo
+      //
+      Test = AsciiStrnCmp (Structure->signature, "$BrdInfo", 8);
+    } else {
+      //
+      // All header signatures begin with $
+      //
+      Test = AsciiStrnCmp (Structure->signature, "$", 0x01);
+    }
+    if (Test != 0) {
+      //
+      // Sanity check failed! Bail.
+      //
+      DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Image is corrupted!\n", __FUNCTION__, __LINE__));
+      Status = EFI_VOLUME_CORRUPTED;
+      goto Exit;
+    }
+    if (AsciiStrnCmp (Structure->signature, "$PromSig", 8) == 0) {
+      //
+      // Check if this is the last structure
+      //
+      Signature = (SIGNATURE_DATA *) Structure;
+      HashSize  = Signature->length - sizeof (SIGNATURE_DATA);
+      Hash      = ((UINT8 *) Signature) + sizeof (SIGNATURE_DATA);
+      HashType  = Signature->hashtype;
+      if (((UINT8 *) Signature - ImageBuffer) + Signature->length + (Structure->length % 0x10) != ImageSize) {
+        //
+        // Oops! $PromSig is not the last structure.
+        //
+        DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: $PromSig structure is not the last structure!\n", __FUNCTION__, __LINE__));
+        Status = EFI_VOLUME_CORRUPTED;
+        goto Exit;
+      }
+    }
+    //
+    // Get next structure on paragraph boundary
+    //
+    Structure = (GENERIC_HEADER *) ((UINT8 *) Structure + Structure->length + (Structure->length % 0x10));
+  }
+  //
+  // Verify CRC32
+  //
+  Crc32 = EepromHeader->crc32;
+  EepromHeader->crc32 = 0;
+  CalculateCrc32 (ImageBuffer, Crc32Size, &EepromHeader->crc32);
+  if (EepromHeader->crc32 != Crc32) {
+    //
+    // Oops!
+    //
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: CRC32 check failed! [%08x:%08x]\n", __FUNCTION__, __LINE__, EepromHeader->crc32, Crc32));
+    Status = EFI_SECURITY_VIOLATION;
+    goto Exit;
+  }
+  //
+  // Verify hash
+  //
+  Status = EFI_SUCCESS;
+  if (HashSize > 0) {
+    //
+    // Check hash
+    //
+    Status = SignedHashCheck (LibraryIndex, ImageBuffer, Crc32Size, Signature);
+    if (EFI_ERROR (Status) && (Status != EFI_MEDIA_CHANGED)) {
+      DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Failed to verify the hash!\n", __FUNCTION__, __LINE__));
+      goto Exit;
+    }
+  }
+
+Exit:
+  //
+  // Free resources
+  //
+  ImageBuffer = EepromFreePool (ImageBuffer);
+  if (EFI_ERROR (Status) && (Status != EFI_MEDIA_CHANGED)) {
+    gImageValidFlag[LibraryIndex] = FALSE;
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - Ending with %r\n", __FUNCTION__, __LINE__, Status));
+  } else {
+    //
+    // Might need to go to a bit flag here to indicate CRC32, hash, and signed hash pass. First round in PEI will only be
+    // able to get CRC32 pass since hash is supported by OpenSSL library and it is HUGE.
+    //
+    gImageValidFlag[LibraryIndex] = TRUE;
+  }
+  return Status;
+}
+
+//
+// Desc:        Registers the raw data libraries
+// Variables:   None
+// Return:      EFI_SUCCESS, anything else will cause an ASSERT
+//
+EFI_STATUS
+EFIAPI
+EepromInitConstructor (VOID)
+{
+  if (mEepromLibDebugFlag) DEBUG ((DEBUG_INFO, "%a (#%4d) - Starting...\n", __FUNCTION__, __LINE__));
+  //
+  // Initiliaze CRC32 tables
+  //
+  if (!mCrcInitFlag) InitializeCrc32Table ();
+
+  //
+  // Initiliaze Library valid flags pointer from PCD. This uses the fact that the PCD library currently just passes out
+  // a pointer to it's internal DB. There is no need to update the PCD, since the pointer already points to the internal
+  // PCD copy. If the PCD library changes to include a CRC check of it's data, then we'll have to start using the PcdSetPtr()
+  // function to set the internal PCD value.
+  //
+  gImageValidFlag = PcdGetPtr (PcdEepromLibraryValid);
+
+  return EFI_SUCCESS;
+}
+
diff --git a/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromLib/EepromLib.h b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromLib/EepromLib.h
new file mode 100644
index 0000000000..83871a4ddf
--- /dev/null
+++ b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromLib/EepromLib.h
@@ -0,0 +1,76 @@
+/** @file
+  Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _EEPROM_LIB_COMMON_
+#define _EEPROM_LIB_COMMON_
+////
+//// Header files
+////
+#include <Uefi.h>
+
+#include <Guid/EepromVariable.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/EepromDataLib.h>
+#include <Library/EepromLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PrintLib.h>
+
+#include <EepromStruct.h>
+
+
+////
+//// Defines
+////
+#define   HASH_SIGNED_FLAG             (1 << 15)
+#define   HASH_TYPE_MASK               0x00FF
+#define   MAX_HASH_TYPE                5
+#define   MAX_DIGEST_SIZE              SHA512_DIGEST_SIZE
+#define   EFI_CERT_TYPE_RSA2048_SIZE   256
+
+////
+//// TypeDefs
+////
+
+////
+//// Structures
+////
+
+////
+//// Functions
+////
+EFI_STATUS
+EFIAPI
+CalculateCrc32 (
+  IN     UINT8    *Data,
+  IN     UINTN     DataSize,
+  IN OUT UINT32   *CrcOut
+  );
+
+EFI_STATUS
+EFIAPI
+EepromLibNemToMemory (VOID);
+
+EFI_STATUS
+EFIAPI
+SignedHashCheck (
+  IN       UINT8             LibraryIndex,
+  IN       UINT8            *ImageBuffer,
+  IN       UINT32            Crc32Size,
+  IN       SIGNATURE_DATA   *Signature
+  );
+
+#endif // _EEPROM_LIB_COMMON_
+
diff --git a/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromLib/EepromLib.inf b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromLib/EepromLib.inf
new file mode 100644
index 0000000000..b7ccb920aa
--- /dev/null
+++ b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromLib/EepromLib.inf
@@ -0,0 +1,63 @@
+## @file
+#  Library producing EEPROM structure data functionality.
+#
+#  Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution. The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php.
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010017
+  BASE_NAME                      = EepromLib
+  FILE_GUID                      = 20AF98D0-BE4F-44FB-8C60-CA992FA121D1
+  VERSION_STRING                 = 1.0
+  MODULE_TYPE                    = BASE
+  LIBRARY_CLASS                  = EepromLib
+  CONSTRUCTOR                    = EepromInitConstructor
+
+[Depex]
+  TRUE
+
+[Guids]
+  gEepromVariableGuid
+
+[LibraryClasses]
+  BaseCryptLib
+  BaseLib
+  BaseMemoryLib
+  DebugLib
+  EepromDataLib
+  MemoryAllocationLib
+  PcdLib
+  PrintLib
+  UefiRuntimeServicesTableLib
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  CryptoPkg/CryptoPkg.dec
+  BroxtonPlatformPkg/PlatformPkg.dec
+  BroxtonSiPkg/BroxtonSiPkg.dec
+
+[Pcd]
+  gPlatformModuleTokenSpaceGuid.PcdEepromAutoPriority
+  gPlatformModuleTokenSpaceGuid.PcdEepromAddress
+  gPlatformModuleTokenSpaceGuid.PcdEepromBus
+  gPlatformModuleTokenSpaceGuid.PcdEepromInMemoryFlag
+  gPlatformModuleTokenSpaceGuid.PcdEepromLibraryValid
+  gPlatformModuleTokenSpaceGuid.PcdEepromMemoryPointer
+  gPlatformModuleTokenSpaceGuid.PcdEepromMemorySize
+  gPlatformModuleTokenSpaceGuid.PcdEepromPublicKeyFile
+
+[Sources]
+  EepromLib.c
+  EepromLib.h
+  ValidateHash.c
+
diff --git a/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromLib/EepromNullLib.inf b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromLib/EepromNullLib.inf
new file mode 100644
index 0000000000..0aa2137e1b
--- /dev/null
+++ b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromLib/EepromNullLib.inf
@@ -0,0 +1,36 @@
+## @file
+#  Library producing EEPROM structure data functionality.
+#
+#  Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution. The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php.
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010017
+  BASE_NAME                      = EepromNullLib
+  FILE_GUID                      = E4E838B1-7D70-42C7-A531-9C8EF44FA748
+  VERSION_STRING                 = 1.0
+  MODULE_TYPE                    = BASE
+  LIBRARY_CLASS                  = EepromNullLib
+
+[Depex]
+  TRUE
+
+[LibraryClasses]
+  DebugLib
+
+[Packages]
+  MdePkg/MdePkg.dec
+  BroxtonPlatformPkg/PlatformPkg.dec
+
+[Sources]
+  Null/EepromNullLib.c
+  Null/EepromNullLib.h
diff --git a/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromLib/EepromPeiLib.inf b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromLib/EepromPeiLib.inf
new file mode 100644
index 0000000000..0f619fd2f5
--- /dev/null
+++ b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromLib/EepromPeiLib.inf
@@ -0,0 +1,62 @@
+## @file
+#  Library producing EEPROM structure data functionality.
+#
+#  Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution. The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php.
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010017
+  BASE_NAME                      = EepromPeiLib
+  FILE_GUID                      = 2B91CA36-CDBC-4A3B-BDE7-404BA69C8C55
+  VERSION_STRING                 = 1.0
+  MODULE_TYPE                    = BASE
+  LIBRARY_CLASS                  = EepromPeiLib
+  CONSTRUCTOR                    = EepromInitConstructor
+
+[Depex]
+  TRUE
+
+[Guids]
+  gEepromVariableGuid
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  DebugLib
+  EepromDataLib
+  MemoryAllocationLib
+  PcdLib
+  PeiServicesLib
+  PrintLib
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  BroxtonPlatformPkg/PlatformPkg.dec
+  BroxtonSiPkg/BroxtonSiPkg.dec
+
+[Pcd]
+  gPlatformModuleTokenSpaceGuid.PcdEepromAutoPriority
+  gPlatformModuleTokenSpaceGuid.PcdEepromAddress
+  gPlatformModuleTokenSpaceGuid.PcdEepromBus
+  gPlatformModuleTokenSpaceGuid.PcdEepromInMemoryFlag
+  gPlatformModuleTokenSpaceGuid.PcdEepromLibraryValid
+  gPlatformModuleTokenSpaceGuid.PcdEepromMemoryPointer
+  gPlatformModuleTokenSpaceGuid.PcdEepromMemorySize
+
+[Ppis]
+  gEfiPeiReadOnlyVariable2PpiGuid               ## SOMETIMES_CONSUMES
+
+[Sources]
+  EepromLib.c
+  EepromLib.h
+  Pei/ValidateHashPei.c
diff --git a/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromLib/Null/EepromNullLib.c b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromLib/Null/EepromNullLib.c
new file mode 100644
index 0000000000..612408a0e0
--- /dev/null
+++ b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromLib/Null/EepromNullLib.c
@@ -0,0 +1,82 @@
+/** @file
+  Common EEPROM library instance.
+
+  Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "EepromNullLib.h"
+
+EFI_STATUS
+EFIAPI
+EraseEeprom (
+  IN       UINT8    LibraryIndex
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+EFIAPI
+GetEepromStructure (
+  IN       UINT8      LibraryIndex,
+  IN OUT   CHAR8      Signature[EEPROM_SIGNATURE_SIZE],
+  IN OUT   UINT8    **Buffer,
+  IN OUT   UINT32    *Size
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+UINT32
+EFIAPI
+GetImageSize (
+  IN       UINT8      LibraryIndex
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+EFIAPI
+GetNextEepromStructure (
+  IN       UINT8      LibraryIndex,
+  IN OUT   UINT32    *Index,
+  IN OUT   UINT8    **Buffer,
+  IN OUT   UINT32    *Size
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+UINT8
+EFIAPI
+GetValidEepromLibrary (
+  IN       BOOLEAN   CopyToMemory,
+  IN       BOOLEAN   MemoryInitialized
+  )
+{
+  return EEPROM_NULL;
+}
+
+VOID
+InitializeEepromPcds (VOID)
+{
+}
+
+EFI_STATUS
+EFIAPI
+ValidateEeprom (
+  IN       UINT8    LibraryIndex
+  )
+{
+  return EFI_UNSUPPORTED;
+}
diff --git a/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromLib/Null/EepromNullLib.h b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromLib/Null/EepromNullLib.h
new file mode 100644
index 0000000000..3d576202b5
--- /dev/null
+++ b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromLib/Null/EepromNullLib.h
@@ -0,0 +1,26 @@
+/** @file
+  Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _EEPROM_NULL_LIB_COMMON_
+#define _EEPROM_NULL_LIB_COMMON_
+////
+//// Header files
+////
+#include <Uefi.h>
+#include <EepromStruct.h>
+
+#include <Library/DebugLib.h>
+#include <Library/EepromDataLib.h>
+#include <Library/EepromLib.h>
+
+#endif // _EEPROM_NULL_LIB_COMMON_
diff --git a/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromLib/Pei/ValidateHashPei.c b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromLib/Pei/ValidateHashPei.c
new file mode 100644
index 0000000000..b039d9885b
--- /dev/null
+++ b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromLib/Pei/ValidateHashPei.c
@@ -0,0 +1,251 @@
+/** @file
+  Common EEPROM library instance.
+
+  Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "EepromLib.h"
+
+#include <PiPei.h>
+#include <Library/HobLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Ppi/ReadOnlyVariable2.h>
+
+UINTN
+EFIAPI
+DisplayStackPointer (
+  IN   CHAR8    *Function,
+  IN   UINTN     LineNumber
+  )
+{
+  EFI_HOB_HANDOFF_INFO_TABLE   *Hob;
+  UINTN                         Temp;
+  
+  Hob  = GetHobList ();
+  Temp = 0;
+  if ((Hob != NULL) & (mEepromDataLibDebugFlag)) {
+    DEBUG ((DEBUG_INFO, "%a (#%4d) - INFO: FreeTop    = %08x\n", __FUNCTION__, __LINE__, Hob->EfiFreeMemoryTop));
+    DEBUG ((DEBUG_INFO, "%a (#%4d) - INFO: FreeBottom = %08x\n", __FUNCTION__, __LINE__, Hob->EfiFreeMemoryBottom));
+    Temp = (UINTN) Hob->EfiFreeMemoryBottom;
+  }
+
+  return Temp;
+}
+
+EFI_STATUS
+EFIAPI
+GetEepromVariable (
+  IN       UINT8             LibraryIndex,
+  OUT      UINT8           **Buffer,
+  OUT      UINT32           *BufferSize
+  )
+{
+  UINT32                            Attributes;
+  UINT8                            *Data;
+  EFI_STATUS                        Status;
+  CHAR16                            VariableName[32];
+  EFI_PEI_READ_ONLY_VARIABLE2_PPI  *VariableServices;
+  UINTN                             VariableSize;
+
+  //
+  // Initialize variables
+  //
+  Attributes   = 0;
+  Data         = NULL;
+  Status       = EFI_SUCCESS;
+  UnicodeSPrint (VariableName, 32, L"PromSig-%d", LibraryIndex);
+
+  //
+  // Sanity checks
+  //
+  if (LibraryIndex >= EEPROM_DATA_LIBRARY_INDEX_MAX) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Library index is larger than %d!\n", __FUNCTION__, __LINE__, EEPROM_DATA_LIBRARY_INDEX_MAX - 1));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  if ((*Buffer != NULL) || (BufferSize == NULL)) {
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+
+  //
+  // Find variable services
+  //
+  Status = PeiServicesLocatePpi (&gEfiPeiReadOnlyVariable2PpiGuid, 0, NULL, (VOID **) &VariableServices);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Failed to locate Variable PPI! [%r]\n", __FUNCTION__, __LINE__, Status));
+    goto Exit;
+  }
+
+  //
+  // Get variable size
+  //
+  VariableSize = 0;
+  Status = VariableServices->GetVariable (
+                               VariableServices,       // *This
+                               VariableName,           // Variable name in Unicode
+                               &gEepromVariableGuid,   // Variable GUID
+                               NULL,                   // Attributes
+                               &VariableSize,          // Data size
+                               NULL                    // Data
+                               );
+  if (Status != EFI_BUFFER_TOO_SMALL) {
+    if (Status == EFI_NOT_FOUND) {
+      //
+      // No variable to find
+      //
+      *Buffer     = NULL;
+      *BufferSize = 0;
+      Status = EFI_SUCCESS;
+      goto Exit;
+    } else {
+      //
+      // Oops!
+      //
+      DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Failed to get size of variable! [%r]\n", __FUNCTION__, __LINE__, Status));
+      goto Exit;
+    }
+  }
+
+  //
+  // Allocate buffer
+  //
+  Data = EepromAllocatePool (VariableSize);
+  if (Data == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Failed to allocate buffer! [%r]\n", __FUNCTION__, __LINE__, Status));
+    goto Exit;
+  }
+
+  //
+  // Get variable
+  //
+  Status = VariableServices->GetVariable (
+                               VariableServices,       // *This
+                               VariableName,           // Variable name in Unicode
+                               &gEepromVariableGuid,   // Variable GUID
+                               NULL,                   // Attributes
+                               &VariableSize,          // Data size
+                               Data                    // Data
+                               );
+  if (EFI_ERROR (Status)) {
+    //
+    // Failed to get data
+    //
+    *Buffer     = NULL;
+    *BufferSize = 0;
+  } else {
+    *Buffer     = Data;
+    *BufferSize = VariableSize;
+  }
+
+Exit:
+  if (EFI_ERROR (Status)) {
+    Data = EepromFreePool (Data);
+  }
+  return Status;
+}
+
+BOOLEAN
+EFIAPI
+InPeiPhase (VOID)
+{
+  return TRUE;
+}
+
+EFI_STATUS
+EFIAPI
+SignedHashCheck (
+  IN       UINT8             LibraryIndex,
+  IN       UINT8            *ImageBuffer,
+  IN       UINT32            Crc32Size,
+  IN       SIGNATURE_DATA   *Signature
+  )
+{
+  UINT8             *Hash;
+  UINT32             HashSize;
+  EFI_STATUS         Status;
+  UINT8             *Variable;
+  UINT32             VariableSize;
+
+  //
+  // Initialize variables
+  //
+  Hash         = ((UINT8 *) Signature) + sizeof (SIGNATURE_DATA);
+  HashSize     = Signature->length - sizeof (SIGNATURE_DATA);
+  Status       = EFI_UNSUPPORTED;
+  Variable     = NULL;
+  VariableSize = 0;
+
+  //
+  // Sanity checks
+  //
+  if (LibraryIndex >= EEPROM_DATA_LIBRARY_INDEX_MAX) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Library index is larger than %d!\n", __FUNCTION__, __LINE__, EEPROM_DATA_LIBRARY_INDEX_MAX - 1));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  if (Signature == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Buffer is NULL!\n", __FUNCTION__, __LINE__));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  if (Signature->hashtype == 0) {
+    //
+    // Nothing to do. Bail.
+    //
+    Status = EFI_SUCCESS;
+    goto Exit;
+  }
+
+  //
+  // Get stored hash
+  //
+  Status = GetEepromVariable (LibraryIndex, &Variable, &VariableSize);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Failed to get variable! [%r]\n", __FUNCTION__, __LINE__, Status));
+    goto Exit;
+  }
+
+  //
+  // Sanity checks
+  //
+  if (VariableSize == 0) {
+    //
+    // Nothing stored for this library. Bail.
+    //
+    Status = EFI_MEDIA_CHANGED;
+    goto Exit;
+  }
+  if (VariableSize != HashSize) {
+    Status = EFI_MEDIA_CHANGED;
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Stored size doesn't match real size! [%r]\n", __FUNCTION__, __LINE__, Status));
+    goto Exit;
+  }
+
+  //
+  // Compare stored to real
+  //
+  if (CompareMem (Variable, Hash, HashSize) != 0) {
+    //
+    // Failed security match
+    //
+    Status = EFI_SECURITY_VIOLATION;
+  } else {
+    Status = EFI_SUCCESS;
+  }
+
+Exit:
+  Variable = EepromFreePool (Variable);
+  return Status;
+}
+
diff --git a/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromLib/ValidateHash.c b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromLib/ValidateHash.c
new file mode 100644
index 0000000000..355033cbef
--- /dev/null
+++ b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/EepromLib/ValidateHash.c
@@ -0,0 +1,399 @@
+/** @file
+  Common EEPROM library instance.
+
+  Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "EepromLib.h"
+
+#include <Library/BaseCryptLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+
+CONST UINT8  mRsaE[] = {0x01, 0x00, 0x01};
+CONST UINT8  mHashSizeLookup[] = {
+               0x00,
+               MD5_DIGEST_SIZE,
+               SHA1_DIGEST_SIZE,
+               SHA256_DIGEST_SIZE,
+               SHA384_DIGEST_SIZE,
+               SHA512_DIGEST_SIZE
+               };
+
+UINTN
+EFIAPI
+DisplayStackPointer (
+  IN   CHAR8    *Function,
+  IN   UINTN     LineNumber
+  )
+{
+  UINT8   *Temp;
+  
+  Temp = AllocatePool (1);
+  if (mEepromDataLibDebugFlag) {
+    DEBUG ((DEBUG_INFO, "%a (#%4d) - INFO: FreeBottom = %08x\n", __FUNCTION__, __LINE__, Temp));
+  }
+
+  return (UINTN) Temp;
+}
+
+BOOLEAN
+EFIAPI
+InPeiPhase (VOID)
+{
+  return FALSE;
+}
+
+EFI_STATUS
+EFIAPI
+SetEepromVariable (
+  IN       UINT8             LibraryIndex,
+  IN       UINT8            *Buffer,
+  IN       UINT32            BufferSize
+  )
+{
+  UINT32       Attributes;
+  EFI_STATUS   Status;
+  CHAR16       VariableName[32];
+
+  //
+  // Initialize variables
+  //
+  Attributes = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS;
+  Status     = EFI_SUCCESS;
+  UnicodeSPrint (VariableName, 32, L"PromSig-%d", LibraryIndex);
+
+  //
+  // Sanity checks
+  //
+  if (LibraryIndex >= EEPROM_DATA_LIBRARY_INDEX_MAX) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Library index is larger than %d!\n", __FUNCTION__, __LINE__, EEPROM_DATA_LIBRARY_INDEX_MAX - 1));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  if ((Buffer == NULL) && (BufferSize > 0)) {
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+
+  //
+  // Set variable
+  //
+  Status = gRT->SetVariable (
+                  VariableName,           // Variable name in UniCode
+                  &gEepromVariableGuid,   // Variable GUID
+                  Attributes,             // Attributes
+                  BufferSize,             // Data size
+                  Buffer                  // Data
+                  );
+
+Exit:
+  return Status;
+}
+
+EFI_STATUS
+EFIAPI
+SignedHashCheck (
+  IN       UINT8             LibraryIndex,
+  IN       UINT8            *ImageBuffer,
+  IN       UINT32            Crc32Size,
+  IN       SIGNATURE_DATA   *Signature
+  )
+{
+  UINT8              Digest[MAX_DIGEST_SIZE];
+  FV_FUNCTION_INFO   FvInfo;
+  EFI_GUID           FvPublicKeyFile;
+  UINT8             *Hash;
+  UINT32             HashSize;
+  BOOLEAN            HashStatus;
+  UINT16             HashType;
+  UINT8             *PublicKey;
+  UINT32             PublicKeySize;
+  VOID              *Rsa;
+  BOOLEAN            RsaStatus;
+  UINT8             *SignedHash;
+  UINT32             SignedHashSize;
+  EFI_STATUS         Status;
+
+  //
+  // Initialize variables
+  //
+  CopyMem (&FvPublicKeyFile, PcdGetPtr (PcdEepromPublicKeyFile), sizeof (EFI_GUID));
+  ZeroMem (&FvInfo, sizeof (FV_FUNCTION_INFO));
+  FvInfo.LibraryIndex = EEPROM_FV;
+  FvInfo.FvFileGuid   = &FvPublicKeyFile;
+  Hash                = ((UINT8 *) Signature) + sizeof (SIGNATURE_DATA);
+  HashType            = Signature->hashtype;
+  HashSize            = mHashSizeLookup[HashType & HASH_TYPE_MASK];
+  PublicKey           = NULL;
+  PublicKeySize       = 0;
+  Rsa                 = NULL;
+  SignedHash          = NULL;
+  SignedHashSize      = 0;
+  Status              = EFI_UNSUPPORTED;
+  if (HashType & HASH_SIGNED_FLAG) {
+    SignedHash     = ((UINT8 *) Signature) + sizeof (SIGNATURE_DATA) + HashSize;
+    SignedHashSize = Signature->length - sizeof (SIGNATURE_DATA) - HashSize;
+  }
+
+  //
+  // Sanity checks
+  //
+  if (LibraryIndex >= EEPROM_DATA_LIBRARY_INDEX_MAX) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Library index is larger than %d!\n", __FUNCTION__, __LINE__, EEPROM_DATA_LIBRARY_INDEX_MAX - 1));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  if ((ImageBuffer == NULL) || (Signature == NULL)) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Buffer is NULL!\n", __FUNCTION__, __LINE__));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  if (Crc32Size == 0) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Buffer size is 0!\n", __FUNCTION__, __LINE__));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  if (HashType == 0) {
+    //
+    // Nothing to do. Bail.
+    //
+    Status = EFI_SUCCESS;
+    goto Exit;
+  }
+  if ((HashType & HASH_TYPE_MASK) > MAX_HASH_TYPE) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: HashType out of bounds! [%04x]\n", __FUNCTION__, __LINE__, HashType));
+    Status = EFI_COMPROMISED_DATA;
+    goto Exit;
+  }
+  if ((Hash == NULL) || (HashSize == 0)) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Buffer or buffer size is NULL!\n", __FUNCTION__, __LINE__));
+    Status = EFI_COMPROMISED_DATA;
+    goto Exit;
+  }
+  if ((SignedHashSize != 256) && (SignedHashSize != 0)) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: SignedHashSize failed! [%02x]\n", __FUNCTION__, __LINE__, SignedHashSize));
+    Status = EFI_COMPROMISED_DATA;
+    goto Exit;
+  }
+
+  //
+  // Clear existing NvStorage variable if it exists. gEepromVariableGuid:L"PromSig-#"
+  //
+  Status = SetEepromVariable (LibraryIndex, NULL, 0);
+  if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Failed to delete variable PromSig-%d! [%r]\n", __FUNCTION__, __LINE__, LibraryIndex, Status));
+    goto Exit;
+  }
+
+  //
+  // Figure out what hash is being used
+  //
+  switch (HashType & HASH_TYPE_MASK) {
+    case HASH_NONE:
+      //
+      // Nothing to do. Bail.
+      //
+      break;
+    case HASH_MD5:
+      //
+      // MD5 hashing
+      //
+      ZeroMem (Digest, MAX_DIGEST_SIZE);
+      HashStatus = Md5HashAll (ImageBuffer, Crc32Size, Digest);
+      if (!HashStatus) {
+        DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Image failed MD5 hash check!\n", __FUNCTION__, __LINE__));
+        Status = EFI_SECURITY_VIOLATION;
+        goto Exit;
+      }
+      if (CompareMem (Digest, Hash, MD5_DIGEST_SIZE) != 0) {
+        DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Image failed MD5 hash check!\n", __FUNCTION__, __LINE__));
+        Status = EFI_SECURITY_VIOLATION;
+        goto Exit;
+      }
+      HashSize = MD5_DIGEST_SIZE;
+      break;
+    case HASH_SHA1:
+      //
+      // SHA1 hashing
+      //
+      ZeroMem (Digest, MAX_DIGEST_SIZE);
+      HashStatus = Sha1HashAll (ImageBuffer, Crc32Size, Digest);
+      if (!HashStatus) {
+        DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Image failed SHA1 hash check!\n", __FUNCTION__, __LINE__));
+        Status = EFI_SECURITY_VIOLATION;
+        goto Exit;
+      }
+      if (CompareMem (Digest, Hash, SHA1_DIGEST_SIZE) != 0) {
+        DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Image failed SHA1 hash check!\n", __FUNCTION__, __LINE__));
+        Status = EFI_SECURITY_VIOLATION;
+        goto Exit;
+      }
+      HashSize = SHA1_DIGEST_SIZE;
+      break;
+    case HASH_SHA256:
+      //
+      // SHA256 hashing
+      //
+      ZeroMem (Digest, MAX_DIGEST_SIZE);
+      HashStatus = Sha256HashAll (ImageBuffer, Crc32Size, Digest);
+      if (!HashStatus) {
+        DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Image failed SHA256 hash check!\n", __FUNCTION__, __LINE__));
+        Status = EFI_SECURITY_VIOLATION;
+        goto Exit;
+      }
+      if (CompareMem (Digest, Hash, SHA256_DIGEST_SIZE) != 0) {
+        DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Image failed SHA256 hash check!\n", __FUNCTION__, __LINE__));
+        Status = EFI_SECURITY_VIOLATION;
+        goto Exit;
+      }
+      HashSize = SHA256_DIGEST_SIZE;
+      break;
+    case HASH_SHA384:
+      //
+      // SHA384 hashing
+      //
+      ZeroMem (Digest, MAX_DIGEST_SIZE);
+      HashStatus = Sha384HashAll (ImageBuffer, Crc32Size, Digest);
+      if (!HashStatus) {
+        DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Image failed SHA384 hash check!\n", __FUNCTION__, __LINE__));
+        Status = EFI_SECURITY_VIOLATION;
+        goto Exit;
+      }
+      if (CompareMem (Digest, Hash, SHA384_DIGEST_SIZE) != 0) {
+        DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Image failed SHA384 hash check!\n", __FUNCTION__, __LINE__));
+        Status = EFI_SECURITY_VIOLATION;
+        goto Exit;
+      }
+      HashSize = SHA384_DIGEST_SIZE;
+      break;
+    case HASH_SHA512:
+      //
+      // SHA512 hashing
+      //
+      ZeroMem (Digest, MAX_DIGEST_SIZE);
+      HashStatus = Sha512HashAll (ImageBuffer, Crc32Size, Digest);
+      if (!HashStatus) {
+        DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Image failed SHA512 hash check!\n", __FUNCTION__, __LINE__));
+        Status = EFI_SECURITY_VIOLATION;
+        goto Exit;
+      }
+      if (CompareMem (Digest, Hash, SHA512_DIGEST_SIZE) != 0) {
+        DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Image failed SHA512 hash check!\n", __FUNCTION__, __LINE__));
+        Status = EFI_SECURITY_VIOLATION;
+        goto Exit;
+      }
+      HashSize = SHA512_DIGEST_SIZE;
+      break;
+    default:
+      //
+      // Oops!
+      //
+      DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Unknown hash type [%04x]!\n", __FUNCTION__, __LINE__, HashType));
+      Status = EFI_VOLUME_CORRUPTED;
+      goto Exit;
+      break;
+  }
+
+  //
+  // Does this have a signed hash?
+  //
+  if ((HashType & HASH_SIGNED_FLAG) != HASH_SIGNED_FLAG) {
+    //
+    // Nope. Bail.
+    //
+    Status = EFI_SUCCESS;
+    goto
Exit;
+  }
+
+  //
+  // Get size of public key file in FV
+  //
+  PublicKey = EepromAllocatePool (2);
+  Status = ReadEeprom (EEPROM_FV, 0, &PublicKeySize, PublicKey, &FvInfo);
+  if ((Status != EFI_BUFFER_TOO_SMALL) || (PublicKeySize == 0)) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - Finding Public key file size returned with %r and a size of %08x\n", __FUNCTION__, __LINE__, Status, PublicKeySize));
+    Status = EFI_COMPROMISED_DATA;
+    goto Exit;
+  }
+
+  //
+  // Allocate buffer for public key
+  //
+  PublicKey = EepromFreePool (PublicKey);
+  PublicKey = EepromAllocatePool (PublicKeySize);
+  if (PublicKey == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Exit;
+  }
+
+  //
+  // Read in Public key from FV
+  //
+  Status = ReadEeprom (EEPROM_FV, 0, &PublicKeySize, PublicKey, &FvInfo);
+  if (EFI_ERROR (Status)) {
+    goto Exit;
+  }
+
+  //
+  // Verify signature
+  //
+  Rsa = RsaNew ();
+  if (Rsa == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - RsaNew() returned NULL buffer!\n", __FUNCTION__, __LINE__));
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Exit;
+  }
+
+  //
+  // Set RSA Key Components.
+  // NOTE: Only N and E are needed to be set as RSA public key for signature verification.
+  //
+  RsaStatus = RsaSetKey (Rsa, RsaKeyN, PublicKey, EFI_CERT_TYPE_RSA2048_SIZE);
+  if (!RsaStatus) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - RsaSetKey(RsaKeyN) failed!\n", __FUNCTION__, __LINE__));
+    Status = EFI_ABORTED;
+    goto Exit;
+  }
+
+  RsaStatus = RsaSetKey (Rsa, RsaKeyE, mRsaE, sizeof (mRsaE));
+  if (!RsaStatus) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - RsaSetKey(RsaKeyE) failed!\n", __FUNCTION__, __LINE__));
+    Status = EFI_ABORTED;
+    goto Exit;
+  }
+
+  RsaStatus = RsaPkcs1Verify (Rsa, Hash, HashSize, SignedHash, SignedHashSize);
+  if (!RsaStatus) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - RsaPkcs1Verify() failed!\n", __FUNCTION__, __LINE__));
+    Status = EFI_SECURITY_VIOLATION;
+    goto Exit;
+  }
+
+Exit:
+  if (Rsa != NULL) {
+    RsaFree (Rsa);
+  }
+  PublicKey = EepromFreePool (PublicKey);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a (#%4d) - Ending with %r\n", __FUNCTION__, __LINE__, Status));
+  } else if (HashType != 0) {
+    //
+    // This is where a copy of the $PromSig data is stored in NvStorage. gEepromVariableGuid:L"PromSig-#"
+    //
+    Status = SetEepromVariable (LibraryIndex, Hash, (HashSize + SignedHashSize));
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "%a (#%4d) - ERROR: Failed to delete variable PromSig-%d! [%r]\n", __FUNCTION__, __LINE__, LibraryIndex, Status));
+    }
+  }
+  return Status;
+}
+
-- 
2.14.1.windows.1



^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [Patch][edk2-platforms/devel-IntelAtomProcessorE3900 5/5] EEPROM header files.
  2018-07-23  2:39 [Patch][edk2-platforms/devel-IntelAtomProcessorE3900 1/5] Add EepromApp zwei4
  2018-07-23  2:39 ` [Patch][edk2-platforms/devel-IntelAtomProcessorE3900 3/5] Library producing EEPROM raw data functionality zwei4
  2018-07-23  2:39 ` [Patch][edk2-platforms/devel-IntelAtomProcessorE3900 4/5] Common EEPROM library instance zwei4
@ 2018-07-23  2:39 ` zwei4
  2 siblings, 0 replies; 4+ messages in thread
From: zwei4 @ 2018-07-23  2:39 UTC (permalink / raw)
  To: edk2-devel; +Cc: David Wei, Kelly Steele, Mike Wu, Mang Guo

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: David Wei <david.wei@intel.com>
CC: Kelly Steele <kelly.steele@intel.com>
CC: Mike Wu  <mike.wu@intel.com>
CC: Mang Guo <mang.guo@intel.com>
---
 .../Common/Features/Eeprom/Include/EepromStruct.h  | 189 +++++++++++++++++++++
 .../Features/Eeprom/Include/Guid/EepromVariable.h  |  26 +++
 .../Eeprom/Include/Library/EepromDataLib.h         | 158 +++++++++++++++++
 .../Features/Eeprom/Include/Library/EepromLib.h    | 110 ++++++++++++
 .../Common/Features/Eeprom/ReadMe.txt              |  62 +++++++
 5 files changed, 545 insertions(+)
 create mode 100644 Platform/BroxtonPlatformPkg/Common/Features/Eeprom/Include/EepromStruct.h
 create mode 100644 Platform/BroxtonPlatformPkg/Common/Features/Eeprom/Include/Guid/EepromVariable.h
 create mode 100644 Platform/BroxtonPlatformPkg/Common/Features/Eeprom/Include/Library/EepromDataLib.h
 create mode 100644 Platform/BroxtonPlatformPkg/Common/Features/Eeprom/Include/Library/EepromLib.h
 create mode 100644 Platform/BroxtonPlatformPkg/Common/Features/Eeprom/ReadMe.txt

diff --git a/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/Include/EepromStruct.h b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/Include/EepromStruct.h
new file mode 100644
index 0000000000..e3d0fa6199
--- /dev/null
+++ b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/Include/EepromStruct.h
@@ -0,0 +1,189 @@
+/** @file
+  Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _EEPROM_LAYOUT_H_
+#define _EEPROM_LAYOUT_H_
+
+#pragma pack(1)
+
+typedef struct {
+    CHAR8   signature[8];
+    UINT16  vermajor;
+    UINT16  verminor;
+    UINT32  length;
+}GENERIC_HEADER;
+
+
+typedef struct {
+    CHAR8   signature[8];
+    UINT16  vermajor;
+    UINT16  verminor;
+    UINT32  length;
+    UINT32  structlength;
+    UINT32  crc32;
+    UINT32  crclength;
+    UINT32  version;
+    CHAR8   reserved[16];
+}EEPROM_HEADER;
+
+
+typedef struct {
+    CHAR8   signature[8];
+    UINT16  vermajor;
+    UINT16  verminor;
+    UINT32  length;
+    CHAR8   reserved[16];
+//  UINT8   acpitbl[0];
+}ACPI_TABLE;
+
+
+typedef struct {
+    CHAR8   signature[8];
+    UINT16  vermajor;
+    UINT16  verminor;
+    UINT32  length;
+    CHAR8   manuname[16];
+    CHAR8   brdname[16];
+    CHAR8   brdserial[16];
+    UINT32  boardid;
+    UINT32  fabid;
+    UINT32  ecid;
+    UINT8   boardtype;
+    CHAR8   reserved[19];
+}BOARD_INFO_TABLE;
+
+
+typedef struct {
+    CHAR8   signature[8];
+    UINT16  vermajor;
+    UINT16  verminor;
+    UINT32  length;
+    CHAR8   partlabel[16];
+    UINT32  blklength;
+    UINT16  pagesize;
+    UINT32  partsize;
+    UINT8   busnumber;
+    UINT8   master;
+    UINT8   speed;
+    CHAR8   reserved[3];
+//  UINT8   mapdata[0];
+}EEPROM_MAP;
+
+
+typedef struct {
+    CHAR8   maplabel[16];
+    UINT32  length;
+    UINT32  offset;
+    UINT8   address;
+    CHAR8   reserved[7];
+}EEPROM_MAP_RECORD;
+
+
+typedef struct {
+    CHAR8   signature[8];
+    UINT16  vermajor;
+    UINT16  verminor;
+    UINT32  length;
+    CHAR8   reserved[16];
+//  UINT8   gpiodata[0];
+}GPIO_DATA_HEADER;
+
+
+typedef struct {
+    CHAR8   gpiolabel[16];
+    UINT32  length;
+    UINT32  offset;
+    UINT32  anddata;
+    UINT32  ordata;
+    UINT8   datasize;
+    UINT8   datatype;
+    CHAR8   reserved[14];
+}GPIO_DATA_RECORD;
+
+
+typedef struct {
+    CHAR8   signature[8];
+    UINT16  vermajor;
+    UINT16  verminor;
+    UINT32  length;
+    CHAR8   reserved[16];
+//  UINT8   hdacodec[0];
+}HDA_CODEC;
+
+
+typedef struct {
+    CHAR8   signature[8];
+    UINT16  vermajor;
+    UINT16  verminor;
+    UINT32  length;
+    UINT16  spdslot;
+    CHAR8   reserved[14];
+//  UINT8   spddata[0];
+}MEMORY_SPD;
+
+
+typedef struct {
+    CHAR8   signature[8];
+    UINT16  vermajor;
+    UINT16  verminor;
+    UINT32  length;
+    CHAR8   nicid[8];
+    CHAR8   macaddr[6];
+    UINT16  nicnum;
+    CHAR8   reserved[16];
+//  UINT8   nicdata[0];
+}NIC_INFO;
+
+
+typedef struct {
+    CHAR8   signature[8];
+    UINT16  vermajor;
+    UINT16  verminor;
+    UINT32  length;
+    UINT16  hashtype;
+    CHAR8   reserved[14];
+//  UINT8   eepromsig[0];
+}SIGNATURE_DATA;
+
+
+typedef struct {
+    CHAR8   signature[8];
+    UINT16  vermajor;
+    UINT16  verminor;
+    UINT32  length;
+    CHAR8   reserved[16];
+//  UINT8   ucodedata[0];
+}MICROCODE;
+
+
+typedef struct {
+    CHAR8   signature[8];
+    UINT16  vermajor;
+    UINT16  verminor;
+    UINT32  length;
+    CHAR8   reserved[16];
+//  UINT8   videodata[0];
+}VIDEO_DATA;
+
+
+typedef struct {
+    CHAR8   signature[8];
+    UINT16  vermajor;
+    UINT16  verminor;
+    UINT32  length;
+    CHAR8   reserved[16];
+//  UINT8   logodata[0];
+}LOGO_DATA;
+
+#pragma pack()
+#endif
diff --git a/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/Include/Guid/EepromVariable.h b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/Include/Guid/EepromVariable.h
new file mode 100644
index 0000000000..47b0590467
--- /dev/null
+++ b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/Include/Guid/EepromVariable.h
@@ -0,0 +1,26 @@
+/** @file
+  GUIDs used for EEPROM variable code.
+
+  Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.<BR>
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _EEPROM_VARIABLE_H_
+#define _EEPROM_VARIABLE_H_
+
+
+#define EEPROM_VARIABLE_GUID \
+{ 0xEE96CA33, 0x5F59, 0x4594, 0x98, 0x69, 0x07, 0xF7, 0x9A, 0xA3, 0xC0, 0x6F }
+
+extern EFI_GUID gEepromVariableGuid;
+
+#endif
+
diff --git a/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/Include/Library/EepromDataLib.h b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/Include/Library/EepromDataLib.h
new file mode 100644
index 0000000000..0d71b3d1bc
--- /dev/null
+++ b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/Include/Library/EepromDataLib.h
@@ -0,0 +1,158 @@
+/** @file
+  Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _EEPROM_DATA_LIB_
+#define _EEPROM_DATA_LIB_
+////
+//// Header files
+////
+#include <Uefi.h>
+
+
+////
+//// Defines
+////
+
+////
+//// Enums
+////
+typedef enum {
+  EEPROM_NULL                   = 0,
+  EEPROM_EEPROM                 = 1,
+  EEPROM_FV                     = 2,
+  EEPROM_MEMORY                 = 3,
+  EEPROM_DATA_LIBRARY_INDEX_MAX = 4
+} EEPROM_DATA_LIBRARY_TYPE;
+
+
+////
+//// Externs
+////
+extern BOOLEAN    mEepromDataLibDebugFlag;
+extern CHAR8     *mEepromLibraryString[EEPROM_DATA_LIBRARY_INDEX_MAX];
+
+
+////
+//// Structures
+////
+typedef struct {
+  UINT8                   LibraryIndex;
+  UINT8                   Address;
+  UINT8                   Bus;
+  UINT32                  Size;         // NOTE: Set this to 0x00.
+  UINT8                  *Buffer;       // NOTE: Set this to NULL.
+  UINT8                  *ScanBuffer;   // NOTE: Should be NULL unless requesting a scan on that I2C bus
+  UINT8                  *ScanSize;     // NOTE: Should be NULL unless requesting a scan on that I2C bus
+} EEPROM_FUNCTION_INFO;
+
+//
+// Should only use this if you need to get a different file from the FV.
+//
+typedef struct {
+  UINT8                   LibraryIndex;
+  EFI_GUID               *FvFileGuid;
+} FV_FUNCTION_INFO;
+
+
+////
+//// Functions
+////
+//
+// Desc:        Copies the contents of an existing memory pool into a new memory pool of equal or greater size.
+// Variables:   Size           Size of the pool to copy existing pool into
+//              SourcePointer  Pointer to the source buffer to copy
+// Return:      Pointer        Pointer to your copy of the pool
+//
+VOID*
+EFIAPI
+EepromAllocateCopyPool (
+  IN  UINTN    Size,
+  IN  VOID    *SourcePointer
+  );
+
+//
+// Desc:        Creates a new memory pool.
+// Variables:   Size           Size of the pool requested
+// Return:      Pointer        Pointer the new pool
+//
+VOID*
+EFIAPI
+EepromAllocatePool (
+  IN  UINTN   Size
+  );
+
+EFI_STATUS
+EFIAPI
+EepromDataLibNemToMemory (VOID);
+
+//
+// Desc:        Frees a memory pool.
+// Variables:   Pointer        Pointer to the beginning of the pool to be freed
+// Return:      Pointer        NULL
+//
+VOID*
+EFIAPI
+EepromFreePool (
+  IN  VOID  *Pointer
+  );
+
+//
+// Desc:        Reads from the EEPROM and copies to the passed in buffer.
+// Variables:   LibraryIndex   Determines which raw data library to use
+//              Offset         Start copying from the offset
+//              Size           Size of the buffer and the number of bytes to copy
+//                             - If set to 0, then return size of EEPROM binary
+//              Buffer         Storage buffer for the copied data from the EEPROM
+//              FunctionInfo   Pointer to function specific data
+// Return:      EFI_SUCCESS             Data copied successfully
+//              EFI_UNSUPPORTED         This function is not supported
+//              EFI_INVALID_PARAMETER   One of the parameters is invalid
+//              EFI_NOT_READY           Called before all necessary library available
+//              EFI_DEVICE_ERROR        Communication error with device
+//
+EFI_STATUS
+EFIAPI
+ReadEeprom (
+  IN       UINT8     LibraryIndex,
+  IN       UINT32    Offset,
+  IN OUT   UINT32   *Size,
+  IN OUT   UINT8    *Buffer,
+  IN OUT   VOID     *FunctionInfo
+  );
+
+//
+// Desc:        Writes to the EEPROM and copies to the passed in buffer.
+// Variables:   LibraryIndex   Determines which raw data library to use
+//              Offset         Start copying from the offset
+//              Size           Size of the buffer and the number of bytes to copy
+//                             - If set to 0, then return size of EEPROM binary
+//              Buffer         Data to be copied to the EEPROM
+//              FunctionInfo   Pointer to function specific data
+// Return:      EFI_SUCCESS             Data copied successfully
+//              EFI_UNSUPPORTED         This function is not supported
+//              EFI_INVALID_PARAMETER   One of the parameters is invalid
+//              EFI_NOT_READY           Called before all necessary library available
+//              EFI_DEVICE_ERROR        Communication error with device
+//
+EFI_STATUS
+EFIAPI
+WriteEeprom (
+  IN       UINT8     LibraryIndex,
+  IN       UINT32    Offset,
+  IN OUT   UINT32   *Size,
+  IN OUT   UINT8    *Buffer,
+  IN OUT   VOID     *FunctionInfo
+  );
+
+#endif // _EEPROM_DATA_LIB_
+
diff --git a/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/Include/Library/EepromLib.h b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/Include/Library/EepromLib.h
new file mode 100644
index 0000000000..b386e8c7bc
--- /dev/null
+++ b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/Include/Library/EepromLib.h
@@ -0,0 +1,110 @@
+/** @file
+  Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _EEPROM_LIB_
+#define _EEPROM_LIB_
+////
+//// Header files
+////
+#include <Uefi.h>
+
+#include <EepromStruct.h>
+
+
+////
+//// defines
+////
+#define EEPROM_SIGNATURE_SIZE   9
+
+
+////
+//// Enums
+////
+typedef enum {
+  HASH_NONE        = 0,
+  HASH_MD5         = 1,
+  HASH_SHA1        = 2,
+  HASH_SHA256      = 3,
+  HASH_SHA384      = 4,
+  HASH_SHA512      = 5
+} EEPROM_HASH_TYPE;
+
+
+////
+//// Functions
+////
+UINTN
+EFIAPI
+DisplayStackPointer (
+  IN   CHAR8    *Function,
+  IN   UINTN     LineNumber
+  );
+
+EFI_STATUS
+EFIAPI
+EraseEeprom (
+  IN       UINT8     LibraryIndex
+  );
+
+EFI_STATUS
+EFIAPI
+GetEepromStructure (
+  IN       UINT8      LibraryIndex,
+  IN OUT   CHAR8      Signature[EEPROM_SIGNATURE_SIZE],
+  IN OUT   UINT8    **Buffer,
+  IN OUT   UINT32    *Size
+  );
+
+UINT32
+EFIAPI
+GetImageSize (
+  IN       UINT8      LibraryIndex
+  );
+
+EFI_STATUS
+EFIAPI
+GetNextEepromStructure (
+  IN       UINT8      LibraryIndex,
+  IN OUT   UINT32    *Index,
+  IN OUT   UINT8    **Buffer,
+  IN OUT   UINT32    *Size
+  );
+
+UINT8
+EFIAPI
+GetValidEepromLibrary (
+  IN       BOOLEAN   CopyToMemory,
+  IN       BOOLEAN   MemoryInitialized
+  );
+
+BOOLEAN
+EFIAPI
+InPeiPhase (VOID);
+
+EFI_STATUS
+EFIAPI
+ValidateEeprom (
+  IN       UINT8     LibraryIndex
+  );
+
+//
+// Desc:        Registers the raw data libraries
+// Variables:   None
+// Return:      EFI_SUCCESS
+//
+EFI_STATUS
+EFIAPI
+EepromInitConstructor (VOID);
+
+#endif // _EEPROM_LIB_
+
diff --git a/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/ReadMe.txt b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/ReadMe.txt
new file mode 100644
index 0000000000..5179b97e3d
--- /dev/null
+++ b/Platform/BroxtonPlatformPkg/Common/Features/Eeprom/ReadMe.txt
@@ -0,0 +1,62 @@
+## @file
+#  Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php.
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+==========================================================================================
+                                   EEPROM PCDs
+==========================================================================================
+[PcdsFixedAtBuild]
+  ## I2C bus the master EEPROM is hanging on
+  gPlatformModuleTokenSpaceGuid.PcdEepromBus|0x06|UINT8|0xEEEE2000
+  ## 7-bit address of the master EEPROM
+  gPlatformModuleTokenSpaceGuid.PcdEepromAddress|0x53|UINT8|0xEEEE2001
+  ## Priority order of EEPROM data libraries
+  ## 00 - Null; 01 - EEPROM; 02 - FV; 03 - Memory; FF - End of list
+  ## Memory should be first
+  gPlatformModuleTokenSpaceGuid.PcdEepromAutoPriority|{0x03, 0x01, 0x02, 0x00, 0xFF}|VOID*|0xEEEE2002
+  ## Public key file GUID - 5D8A38A3-FBBD-4077-8105-11170C2AF54D
+  gPlatformModuleTokenSpaceGuid.PcdEepromPublicKeyFile|{0xA3, 0x38, 0x8A, 0x5D, 0xBD, 0xFB, 0x77, 0x40, 0x81, 0x05, 0x11, 0x17, 0x0C, 0x2A, 0xF5, 0x4D}|VOID*|0xEEEE2003
+  ## FV EEPROM Image file GUID - BFBD3DAC-01EB-4FEB-A9DE-BCC9D1BA5531
+  gPlatformModuleTokenSpaceGuid.PcdEepromFvImageFile|{0xAC, 0x3D, 0xBD, 0xBF, 0xEB, 0x01, 0xEB, 0x4F, 0xA9, 0xDE, 0xBC, 0xC9, 0xD1, 0xBA, 0x55, 0x31}|VOID*|0xEEEE2004
+
+[PcdsDynamic, PcdsDynamicEx]
+  ## Used to store the EEPROM memory buffer pointer
+  gPlatformModuleTokenSpaceGuid.PcdEepromMemoryPointer|0|UINT64|0xEEEE0000
+  ## Used to store the EEPROM memory buffer size
+  gPlatformModuleTokenSpaceGuid.PcdEepromMemorySize|0|UINT32|0xEEEE0001
+  ## Used to store the EEPROM data library valid flags
+  gPlatformModuleTokenSpaceGuid.PcdEepromLibraryValid|{0x00, 0x00, 0x00, 0x00}|VOID*|0xEEEE0002
+  ## Flag to indicate that a HOB exists with EEPROM_MEMORY data
+  gPlatformModuleTokenSpaceGuid.PcdEepromMemoryHobPresent|FALSE|BOOLEAN|0xEEEE0003
+  ## Pointer to the Part head link
+  gPlatformModuleTokenSpaceGuid.PcdEepromPartsHeadLink|0|UINT64|0xEEEE0004
+  ## Pointer to the Parts table
+  gPlatformModuleTokenSpaceGuid.PcdEepromParts|0|UINT64|0xEEEE0005
+  ## Flag to tell if EEPROM Map is in memory
+  gPlatformModuleTokenSpaceGuid.PcdEepromInMemoryFlag|0|BOOLEAN|0xEEEE0006
+  ## Flag to tell if EEPROM Map is in HOB
+  gPlatformModuleTokenSpaceGuid.PcdEepromMapHobValid|0|BOOLEAN|0xEEEE0007
+
+
+==========================================================================================
+                                   EEPROM GUIDs
+==========================================================================================
+[Guids]
+  # GUID for EEPROM variables - {EE96CA33-5F59-4594-9869-07F79AA3C06F}
+  gEepromVariableGuid = { 0xEE96CA33, 0x5F59, 0x4594, { 0x98, 0x69, 0x07, 0xF7, 0x9A, 0xA3, 0xC0, 0x6F }}
+
+
+==========================================================================================
+                                   Generating EEPROM binary
+==========================================================================================
+ Use the GenerateBinary.py script as a guide on how to create the EEPROM binary.
+
-- 
2.14.1.windows.1



^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2018-07-23  2:39 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-07-23  2:39 [Patch][edk2-platforms/devel-IntelAtomProcessorE3900 1/5] Add EepromApp zwei4
2018-07-23  2:39 ` [Patch][edk2-platforms/devel-IntelAtomProcessorE3900 3/5] Library producing EEPROM raw data functionality zwei4
2018-07-23  2:39 ` [Patch][edk2-platforms/devel-IntelAtomProcessorE3900 4/5] Common EEPROM library instance zwei4
2018-07-23  2:39 ` [Patch][edk2-platforms/devel-IntelAtomProcessorE3900 5/5] EEPROM header files zwei4

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox