public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: zwei4 <david.wei@intel.com>
To: edk2-devel@lists.01.org
Cc: David Wei <david.wei@intel.com>,
	Kelly Steele <kelly.steele@intel.com>,
	Mike Wu <mike.wu@intel.com>, Mang Guo <mang.guo@intel.com>
Subject: [Patch][edk2-platforms/devel-IntelAtomProcessorE3900 3/5] Library producing EEPROM raw data functionality.
Date: Mon, 23 Jul 2018 10:39:17 +0800	[thread overview]
Message-ID: <20180723023919.19796-3-david.wei@intel.com> (raw)
In-Reply-To: <20180723023919.19796-1-david.wei@intel.com>

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



  reply	other threads:[~2018-07-23  2:39 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-07-23  2:39 [Patch][edk2-platforms/devel-IntelAtomProcessorE3900 1/5] Add EepromApp zwei4
2018-07-23  2:39 ` zwei4 [this message]
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

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180723023919.19796-3-david.wei@intel.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox