]> git.proxmox.com Git - mirror_edk2.git/commitdiff
Add missing module for duet package.
authorklu2 <klu2@6f19259b-4bc3-4df7-8a09-765794883524>
Fri, 18 Apr 2008 03:09:54 +0000 (03:09 +0000)
committerklu2 <klu2@6f19259b-4bc3-4df7-8a09-765794883524>
Fri, 18 Apr 2008 03:09:54 +0000 (03:09 +0000)
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@5088 6f19259b-4bc3-4df7-8a09-765794883524

29 files changed:
DuetPkg/EfiLdr/Debug.c [new file with mode: 0644]
DuetPkg/EfiLdr/Debug.h [new file with mode: 0644]
DuetPkg/EfiLdr/EfiLdr.h [new file with mode: 0644]
DuetPkg/EfiLdr/EfiLdr.inf [new file with mode: 0644]
DuetPkg/EfiLdr/EfiLdrHandoff.h [new file with mode: 0644]
DuetPkg/EfiLdr/EfiLoader.c [new file with mode: 0644]
DuetPkg/EfiLdr/Ia32/EfiLdr.inf [new file with mode: 0644]
DuetPkg/EfiLdr/Ia32/Makefile [new file with mode: 0644]
DuetPkg/EfiLdr/PeLoader.c [new file with mode: 0644]
DuetPkg/EfiLdr/PeLoader.h [new file with mode: 0644]
DuetPkg/EfiLdr/Support.c [new file with mode: 0644]
DuetPkg/EfiLdr/Support.h [new file with mode: 0644]
DuetPkg/EfiLdr/X64/EfiLdr.inf [new file with mode: 0644]
DuetPkg/EfiLdr/X64/Makefile [new file with mode: 0644]
DuetPkg/EfiLdr/efildr.c [new file with mode: 0644]
DuetPkg/FSVariable/FSVariable.c [new file with mode: 0644]
DuetPkg/FSVariable/FSVariable.dxs [new file with mode: 0644]
DuetPkg/FSVariable/FSVariable.h [new file with mode: 0644]
DuetPkg/FSVariable/FSVariable.inf [new file with mode: 0644]
DuetPkg/FSVariable/FileStorage.c [new file with mode: 0644]
DuetPkg/FSVariable/MemStorage.c [new file with mode: 0644]
DuetPkg/FSVariable/VariableStorage.h [new file with mode: 0644]
DuetPkg/FvbRuntimeService/DUETFwh.dxs [new file with mode: 0644]
DuetPkg/FvbRuntimeService/DUETFwh.inf [new file with mode: 0644]
DuetPkg/FvbRuntimeService/FWBlockService.c [new file with mode: 0644]
DuetPkg/FvbRuntimeService/FileIo.c [new file with mode: 0644]
DuetPkg/FvbRuntimeService/FileIo.h [new file with mode: 0644]
DuetPkg/FvbRuntimeService/FvbInfo.c [new file with mode: 0644]
DuetPkg/FvbRuntimeService/FwBlockService.h [new file with mode: 0644]

diff --git a/DuetPkg/EfiLdr/Debug.c b/DuetPkg/EfiLdr/Debug.c
new file mode 100644 (file)
index 0000000..2cc8c73
--- /dev/null
@@ -0,0 +1,93 @@
+/*++\r
+\r
+Copyright (c) 2006, Intel Corporation                                                         \r
+All rights reserved. This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
+                                                                                          \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+\r
+Module Name:\r
+  Debug.c\r
+\r
+Abstract:\r
+\r
+Revision History:\r
+\r
+--*/\r
+#include "EfiLdr.h"\r
+#include "Debug.h"\r
+\r
+UINT8 *mCursor;\r
+UINT8 mHeaderIndex = 10;\r
+\r
+VOID\r
+PrintHeader (\r
+  CHAR8 Char\r
+  )\r
+{\r
+  *(UINT8 *)(UINTN)(0x000b8000 + mHeaderIndex) = Char;\r
+  mHeaderIndex += 2;\r
+}\r
+\r
+VOID\r
+ClearScreen (\r
+  VOID\r
+  )\r
+{\r
+  UINT32 Index;\r
+\r
+  mCursor = (UINT8 *)(UINTN)(0x000b8000 + 160);\r
+  for (Index = 0; Index < 80 * 49; Index++) {\r
+    *mCursor = ' ';\r
+    mCursor += 2;\r
+  }\r
+  mCursor = (UINT8 *)(UINTN)(0x000b8000 + 160);\r
+}\r
+\r
+VOID\r
+PrintValue64 (\r
+  UINT64 Value\r
+  )\r
+{\r
+  PrintValue ((UINT32) RShiftU64 (Value, 32));\r
+  PrintValue ((UINT32) Value);\r
+}\r
+\r
+VOID\r
+PrintValue (\r
+  UINT32 Value\r
+  )\r
+{\r
+  UINT32 Index;\r
+  UINT8  Char;\r
+\r
+  for (Index = 0; Index < 8; Index++) {\r
+    Char = (UINT8)((Value >> ((7 - Index) * 4)) & 0x0f) + '0';\r
+    if (Char > '9') {\r
+      Char = Char - '0' - 10 + 'A';\r
+    }\r
+    *mCursor = Char;\r
+    mCursor += 2;\r
+  }\r
+}\r
+\r
+VOID\r
+PrintString (\r
+  UINT8 *String\r
+  )\r
+{\r
+  UINT32 Index;\r
+\r
+  for (Index = 0; String[Index] != 0; Index++) {\r
+    if (String[Index] == '\n') {\r
+      mCursor = (UINT8 *)(UINTN)(0xb8000 + (((((UINTN)mCursor - 0xb8000) + 160) / 160) * 160));\r
+    } else {\r
+      *mCursor = String[Index];\r
+      mCursor += 2;\r
+    }\r
+  }\r
+}\r
+\r
diff --git a/DuetPkg/EfiLdr/Debug.h b/DuetPkg/EfiLdr/Debug.h
new file mode 100644 (file)
index 0000000..9939109
--- /dev/null
@@ -0,0 +1,49 @@
+/*++\r
+\r
+Copyright (c) 2006, Intel Corporation                                                         \r
+All rights reserved. This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
+                                                                                          \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+\r
+Module Name:\r
+  Debug.h\r
+\r
+Abstract:\r
+\r
+Revision History:\r
+\r
+--*/\r
+\r
+#ifndef _EFILDR_DEBUG_H_\r
+#define _EFILDR_DEBUG_H_\r
+\r
+VOID\r
+PrintHeader (\r
+  CHAR8 Char\r
+  );\r
+\r
+VOID \r
+PrintValue (\r
+  UINT32 Value\r
+  );\r
+\r
+VOID\r
+PrintValue64 (\r
+  UINT64 Value\r
+  );\r
+\r
+VOID \r
+PrintString (\r
+  UINT8 *String\r
+  );\r
+\r
+VOID \r
+ClearScreen (\r
+  VOID\r
+  );\r
+\r
+#endif\r
diff --git a/DuetPkg/EfiLdr/EfiLdr.h b/DuetPkg/EfiLdr/EfiLdr.h
new file mode 100644 (file)
index 0000000..b1d0e1c
--- /dev/null
@@ -0,0 +1,115 @@
+/*++\r
+\r
+Copyright (c) 2006, Intel Corporation                                                         \r
+All rights reserved. This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
+                                                                                          \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+\r
+Module Name:\r
+  EfiLdr.c\r
+\r
+Abstract:\r
+\r
+Revision History:\r
+\r
+--*/\r
+\r
+#ifndef _DUET_EFI_LOADER_H_\r
+#define _DUET_EFI_LOADER_H_\r
+\r
+#include "FrameworkDxe.h"\r
+#include "Uefi.h"\r
+#include "EfiLdrHandoff.h"\r
+\r
+#include <Protocol/LoadedImage.h>\r
+#include <Protocol/EdkDecompress.h>\r
+#include <IndustryStandard/PeImage.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+\r
+#define INT15_E820_AddressRangeMemory   1\r
+#define INT15_E820_AddressRangeReserved 2\r
+#define INT15_E820_AddressRangeACPI     3\r
+#define INT15_E820_AddressRangeNVS      4\r
+\r
+#define EFI_FIRMWARE_BASE_ADDRESS  0x00200000\r
+\r
+#define EFI_DECOMPRESSED_BUFFER_ADDRESS 0x00600000\r
+\r
+#define EFI_MAX_MEMORY_DESCRIPTORS 64\r
+\r
+#define LOADED_IMAGE_SIGNATURE     EFI_SIGNATURE_32('l','d','r','i')\r
+\r
+typedef struct {\r
+  UINTN                       Signature;\r
+  CHAR16                      *Name;          // Displayable name\r
+  UINTN                       Type;\r
+\r
+  BOOLEAN                     Started;        // If entrypoint has been called\r
+  VOID                        *StartImageContext;\r
+\r
+  EFI_IMAGE_ENTRY_POINT       EntryPoint;     // The image's entry point\r
+  EFI_LOADED_IMAGE_PROTOCOL   Info;           // loaded image protocol\r
+\r
+  // \r
+  EFI_PHYSICAL_ADDRESS        ImageBasePage;  // Location in memory\r
+  UINTN                       NoPages;        // Number of pages \r
+  UINT8                       *ImageBase;     // As a char pointer\r
+  UINT8                       *ImageEof;      // End of memory image\r
+\r
+  // relocate info\r
+  UINT8                       *ImageAdjust;   // Bias for reloc calculations\r
+  UINTN                       StackAddress;\r
+  UINT8                       *FixupData;     //  Original fixup data\r
+} EFILDR_LOADED_IMAGE;\r
+\r
+#pragma pack(4)\r
+typedef struct {          \r
+  UINT64       BaseAddress;\r
+  UINT64       Length;\r
+  UINT32       Type;\r
+} BIOS_MEMORY_MAP_ENTRY;\r
+#pragma pack()\r
+\r
+typedef struct {          \r
+  UINT32                MemoryMapSize;\r
+  BIOS_MEMORY_MAP_ENTRY MemoryMapEntry[1];\r
+} BIOS_MEMORY_MAP;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+UefiDecompressGetInfo (\r
+  IN      EFI_TIANO_DECOMPRESS_PROTOCOL *This,\r
+  IN      VOID                          *Source,\r
+  IN      UINT32                        SrcSize,\r
+  OUT     UINT32                        *DstSize,\r
+  OUT     UINT32                        *ScratchSize\r
+  );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+TianoDecompress (\r
+  IN      EFI_TIANO_DECOMPRESS_PROTOCOL *This,\r
+  IN      VOID                          *Source,\r
+  IN      UINT32                        SrcSize,\r
+  IN OUT  VOID                          *Destination,\r
+  IN      UINT32                        DstSize,\r
+  IN OUT  VOID                          *Scratch,\r
+  IN      UINT32                        ScratchSize\r
+  );\r
+\r
+EFILDR_LOADED_IMAGE    DxeCoreImage;\r
+EFILDR_LOADED_IMAGE    DxeIplImage;\r
+\r
+typedef\r
+VOID\r
+(* EFI_MAIN_ENTRYPOINT) (\r
+    IN EFILDRHANDOFF  *Handoff\r
+    )\r
+;\r
+\r
+#endif //_DUET_EFI_LOADER_H_
\ No newline at end of file
diff --git a/DuetPkg/EfiLdr/EfiLdr.inf b/DuetPkg/EfiLdr/EfiLdr.inf
new file mode 100644 (file)
index 0000000..d829ca2
--- /dev/null
@@ -0,0 +1,58 @@
+#/*++\r
+# \r
+# Copyright (c) 2006, Intel Corporation                                                         \r
+# All rights reserved. This program and the accompanying materials                          \r
+# are licensed and made available under the terms and conditions of the BSD License         \r
+# which accompanies this distribution.  The full text of the license may be found at        \r
+# http://opensource.org/licenses/bsd-license.php                                            \r
+#                                                                                           \r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+#\r
+#  Module Name:\r
+#    EfiLdr.inf\r
+#\r
+#  Abstract:\r
+#\r
+#--*/\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = EfiLoader\r
+  FILE_GUID                      = 7E374E25-8E01-4FEE-87F2-390C23C606CD\r
+  #MODULE_TYPE                    = USER_DEFINED\r
+  MODULE_TYPE                    = UEFI_APPLICATION\r
+  VERSION_STRING                 = 1.0\r
+  EDK_RELEASE_VERSION            = 0x00020000\r
+  EFI_SPECIFICATION_VERSION      = 0x00020000\r
+  ENTRY_POINT                    = EfiLoader\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+  IntelFrameworkPkg/IntelFrameworkPkg.dec\r
+  IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec\r
+\r
+[LibraryClasses]\r
+  BaseLib\r
+  BaseMemoryLib\r
+  UefiApplicationEntryPoint\r
+  BaseUefiTianoDecompressLib\r
+  \r
+[Sources.common]\r
+  Debug.h\r
+  PeLoader.h\r
+  Support.h\r
+  EfiLdrHandoff.h\r
+  EfiLdr.h\r
+  EfiLoader.c\r
+  Debug.c\r
+  PeLoader.c\r
+  Support.c\r
+  \r
+[BuildOptions.common]\r
+  #MSFT:*_*_IA32_DLINK_FLAGS = /out:"$(BIN_DIR)\SecMain.exe" /base:0x10000000 /pdb:"$(BIN_DIR)\SecMain.pdb" /LIBPATH:"$(VCINSTALLDIR)\Lib" /LIBPATH:"$(VCINSTALLDIR)\PlatformSdk\Lib" /NOLOGO /SUBSYSTEM:CONSOLE /NODEFAULTLIB /IGNORE:4086 /MAP /OPT:REF /DEBUG /MACHINE:I386 /LTCG Kernel32.lib MSVCRTD.lib Gdi32.lib User32.lib Winmm.lib\r
+  MSFT:*_*_IA32_CC_FLAGS = /nologo /W4 /WX /Gy /c /D UNICODE /Od /FI$(DEST_DIR_DEBUG)/AutoGen.h /EHs-c- /GF /Gs8192 /Zi /Gm /D _CRT_SECURE_NO_WARNINGS /D _CRT_SECURE_NO_DEPRECATE\r
+  MSFT:*_*_IA32_PP_FLAGS = /nologo /E /TC /FI$(DEST_DIR_DEBUG)/AutoGen.h\r
+  MSFT:*_*_IA32_ASM_FLAGS = /nologo /W3 /WX /c /coff /Cx /Zd /W0 /Zi\r
+  MSFT:*_*_IA32_ASMLINK_FLAGS       = /link /nologo /tiny  \r
diff --git a/DuetPkg/EfiLdr/EfiLdrHandoff.h b/DuetPkg/EfiLdr/EfiLdrHandoff.h
new file mode 100644 (file)
index 0000000..786b6cb
--- /dev/null
@@ -0,0 +1,56 @@
+/*++\r
+\r
+Copyright (c) 2006, Intel Corporation                                                         \r
+All rights reserved. This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
+                                                                                          \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+\r
+Module Name:\r
+  EfiLdrHandoff.h\r
+\r
+Abstract:\r
+\r
+Revision History:\r
+\r
+--*/\r
+\r
+#ifndef _EFILDR_HANDOFF_H_\r
+#define _EFILDR_HANDOFF_H_\r
+\r
+#define EFILDR_BASE_SEGMENT 0x2000\r
+#define EFILDR_LOAD_ADDRESS        (EFILDR_BASE_SEGMENT << 4)\r
+#define EFILDR_HEADER_ADDRESS      (EFILDR_LOAD_ADDRESS+0x2000)\r
+\r
+#define EFILDR_CB_VA        0x00\r
+\r
+typedef struct _EFILDRHANDOFF {\r
+    UINTN                    MemDescCount;\r
+    EFI_MEMORY_DESCRIPTOR   *MemDesc;\r
+    VOID                    *BfvBase;\r
+    UINTN                   BfvSize;\r
+    VOID                    *DxeIplImageBase;\r
+    UINTN                   DxeIplImageSize;\r
+    VOID                    *DxeCoreImageBase;\r
+    UINTN                   DxeCoreImageSize;\r
+    VOID                    *DxeCoreEntryPoint;\r
+} EFILDRHANDOFF;\r
+\r
+typedef struct {\r
+    UINT32       CheckSum;\r
+    UINT32       Offset;\r
+    UINT32       Length;\r
+    UINT8        FileName[52];\r
+} EFILDR_IMAGE;\r
+\r
+typedef struct {          \r
+    UINT32       Signature;     \r
+    UINT32       HeaderCheckSum;\r
+    UINT32       FileLength;\r
+    UINT32       NumberOfImages;\r
+} EFILDR_HEADER;\r
+\r
+#endif\r
diff --git a/DuetPkg/EfiLdr/EfiLoader.c b/DuetPkg/EfiLdr/EfiLoader.c
new file mode 100644 (file)
index 0000000..382b780
--- /dev/null
@@ -0,0 +1,266 @@
+/*++\r
+\r
+Copyright (c) 2006, Intel Corporation                                                         \r
+All rights reserved. This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
+                                                                                          \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+\r
+Module Name:\r
+  EfiLoader.c\r
+\r
+Abstract:\r
+\r
+Revision History:\r
+\r
+--*/\r
+\r
+#include "EfiLdr.h"\r
+#include "Support.h"\r
+#include "Debug.h"\r
+#include "PeLoader.h"\r
+\r
+VOID\r
+EfiLoader (\r
+  UINT32    BiosMemoryMapBaseAddress\r
+  )\r
+{\r
+  BIOS_MEMORY_MAP       *BiosMemoryMap;    \r
+  EFILDR_HEADER         *EFILDRHeader;\r
+  EFILDR_IMAGE          *EFILDRImage;\r
+  EFI_MEMORY_DESCRIPTOR EfiMemoryDescriptor[EFI_MAX_MEMORY_DESCRIPTORS];\r
+  EFI_STATUS            Status;\r
+  UINTN                 NumberOfMemoryMapEntries;\r
+  UINT32                DestinationSize;\r
+  UINT32                ScratchSize;\r
+  UINTN                 BfvPageNumber;\r
+  UINTN                 BfvBase;\r
+  EFI_MAIN_ENTRYPOINT   EfiMainEntrypoint;\r
+  static EFILDRHANDOFF  Handoff;\r
+\r
+PrintHeader ('A');\r
+\r
+  ClearScreen();\r
+  PrintString("EFI Loader\n");\r
+\r
+//  PrintString("&BiosMemoryMapBaseAddress = ");   \r
+//  PrintValue64 ((UINT64)(&BiosMemoryMapBaseAddress));\r
+//  PrintString("  BiosMemoryMapBaseAddress = ");   \r
+//  PrintValue(BiosMemoryMapBaseAddress);\r
+//  PrintString("\n");\r
+\r
+  //\r
+  // Add all EfiConventionalMemory descriptors to the table.  If there are partial pages, then\r
+  // round the start address up to the next page, and round the length down to a page boundry.\r
+  //\r
+  BiosMemoryMap = (BIOS_MEMORY_MAP *)(UINTN)(BiosMemoryMapBaseAddress);\r
+  NumberOfMemoryMapEntries = 0;\r
+  GenMemoryMap (&NumberOfMemoryMapEntries, EfiMemoryDescriptor, BiosMemoryMap);\r
+\r
+  //\r
+  // Get information on where the image is in memory\r
+  //\r
+\r
+  EFILDRHeader = (EFILDR_HEADER *)(UINTN)(EFILDR_HEADER_ADDRESS);\r
+  EFILDRImage  = (EFILDR_IMAGE *)(UINTN)(EFILDR_HEADER_ADDRESS + sizeof(EFILDR_HEADER));\r
+\r
+PrintHeader ('D');\r
+\r
+  //\r
+  // Point to the 4th image (Bfv)\r
+  //\r
+    \r
+  EFILDRImage += 3;\r
+\r
+  //\r
+  // Decompress the image\r
+  //\r
+\r
+  Status = UefiDecompressGetInfo (\r
+             NULL, \r
+             (VOID *)(UINTN)(EFILDR_HEADER_ADDRESS + EFILDRImage->Offset),\r
+             EFILDRImage->Length,\r
+             &DestinationSize, \r
+             &ScratchSize\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    CpuDeadLoop();\r
+  }\r
+\r
+  Status = TianoDecompress (\r
+             NULL, \r
+             (VOID *)(UINTN)(EFILDR_HEADER_ADDRESS + EFILDRImage->Offset),\r
+             EFILDRImage->Length,\r
+             (VOID *)(UINTN)EFI_DECOMPRESSED_BUFFER_ADDRESS,\r
+             DestinationSize, \r
+             (VOID *)(UINTN)((EFI_DECOMPRESSED_BUFFER_ADDRESS + DestinationSize + 0x1000) & 0xfffff000),\r
+             ScratchSize\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    CpuDeadLoop();\r
+  }\r
+\r
+  BfvPageNumber = EFI_SIZE_TO_PAGES (DestinationSize);\r
+  BfvBase = (UINTN) FindSpace (BfvPageNumber, &NumberOfMemoryMapEntries, EfiMemoryDescriptor, EfiRuntimeServicesData, EFI_MEMORY_WB);\r
+  if (BfvBase == 0) {\r
+    CpuDeadLoop();\r
+  }\r
+  ZeroMem ((VOID *)(UINTN)BfvBase, BfvPageNumber * EFI_PAGE_SIZE);\r
+  CopyMem ((VOID *)(UINTN)BfvBase, (VOID *)(UINTN)EFI_DECOMPRESSED_BUFFER_ADDRESS, DestinationSize);\r
+\r
+PrintHeader ('B');\r
+\r
+  //\r
+  // Point to the 2nd image (DxeIpl)\r
+  //\r
+    \r
+  EFILDRImage -= 2;\r
+\r
+  //\r
+  // Decompress the image\r
+  //\r
+\r
+  Status = UefiDecompressGetInfo (\r
+             NULL, \r
+             (VOID *)(UINTN)(EFILDR_HEADER_ADDRESS + EFILDRImage->Offset),\r
+             EFILDRImage->Length,\r
+             &DestinationSize, \r
+             &ScratchSize\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    CpuDeadLoop();\r
+  }\r
+\r
+  Status = TianoDecompress (\r
+             NULL, \r
+             (VOID *)(UINTN)(EFILDR_HEADER_ADDRESS + EFILDRImage->Offset),\r
+             EFILDRImage->Length,\r
+             (VOID *)(UINTN)EFI_DECOMPRESSED_BUFFER_ADDRESS,\r
+             DestinationSize, \r
+             (VOID *)(UINTN)((EFI_DECOMPRESSED_BUFFER_ADDRESS + DestinationSize + 0x1000) & 0xfffff000),\r
+             ScratchSize\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    CpuDeadLoop();\r
+  }\r
+\r
+  //\r
+  // Load and relocate the EFI PE/COFF Firmware Image \r
+  //\r
+  Status = EfiLdrPeCoffLoadPeImage (\r
+             (VOID *)(UINTN)(EFI_DECOMPRESSED_BUFFER_ADDRESS), \r
+             &DxeIplImage, \r
+             &NumberOfMemoryMapEntries, \r
+             EfiMemoryDescriptor\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    CpuDeadLoop();\r
+  }\r
+\r
+//  PrintString("Image.NoPages = ");   \r
+//  PrintValue(Image.NoPages);\r
+//  PrintString("\n");\r
+\r
+PrintHeader ('C');\r
+\r
+  //\r
+  // Point to the 3rd image (DxeMain)\r
+  //\r
+    \r
+  EFILDRImage++;\r
+\r
+  //\r
+  // Decompress the image\r
+  //\r
+\r
+  Status = UefiDecompressGetInfo (\r
+             NULL, \r
+             (VOID *)(UINTN)(EFILDR_HEADER_ADDRESS + EFILDRImage->Offset),\r
+             EFILDRImage->Length,\r
+             &DestinationSize, \r
+             &ScratchSize\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    CpuDeadLoop();\r
+  }\r
+\r
+  Status = TianoDecompress (\r
+             NULL, \r
+             (VOID *)(UINTN)(EFILDR_HEADER_ADDRESS + EFILDRImage->Offset),\r
+             EFILDRImage->Length,\r
+             (VOID *)(UINTN)EFI_DECOMPRESSED_BUFFER_ADDRESS,\r
+             DestinationSize, \r
+             (VOID *)(UINTN)((EFI_DECOMPRESSED_BUFFER_ADDRESS + DestinationSize + 0x1000) & 0xfffff000),\r
+             ScratchSize\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    CpuDeadLoop();\r
+  }\r
+\r
+  //\r
+  // Load and relocate the EFI PE/COFF Firmware Image \r
+  //\r
+  Status = EfiLdrPeCoffLoadPeImage (\r
+             (VOID *)(UINTN)(EFI_DECOMPRESSED_BUFFER_ADDRESS), \r
+             &DxeCoreImage, \r
+             &NumberOfMemoryMapEntries, \r
+             EfiMemoryDescriptor\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    CpuDeadLoop();\r
+  }\r
+\r
+PrintHeader ('E');\r
+\r
+  //\r
+  // Display the table of memory descriptors.\r
+  //\r
+\r
+//  PrintString("\nEFI Memory Descriptors\n");   \r
+/*\r
+  {\r
+  UINTN Index;\r
+  for (Index = 0; Index < NumberOfMemoryMapEntries; Index++) {\r
+    PrintString("Type = ");   \r
+    PrintValue(EfiMemoryDescriptor[Index].Type);\r
+    PrintString("  Start = ");   \r
+    PrintValue((UINT32)(EfiMemoryDescriptor[Index].PhysicalStart));\r
+    PrintString("  NumberOfPages = ");   \r
+    PrintValue((UINT32)(EfiMemoryDescriptor[Index].NumberOfPages));\r
+    PrintString("\n");\r
+  }\r
+  }\r
+*/\r
+\r
+  //\r
+  // Jump to EFI Firmware\r
+  //\r
+\r
+  if (DxeIplImage.EntryPoint != NULL) {\r
+\r
+    Handoff.MemDescCount      = NumberOfMemoryMapEntries;\r
+    Handoff.MemDesc           = EfiMemoryDescriptor;\r
+    Handoff.BfvBase           = (VOID *)(UINTN)BfvBase;\r
+    Handoff.BfvSize           = BfvPageNumber * EFI_PAGE_SIZE;\r
+    Handoff.DxeIplImageBase   = (VOID *)(UINTN)DxeIplImage.ImageBasePage;\r
+    Handoff.DxeIplImageSize   = DxeIplImage.NoPages * EFI_PAGE_SIZE;\r
+    Handoff.DxeCoreImageBase  = (VOID *)(UINTN)DxeCoreImage.ImageBasePage;\r
+    Handoff.DxeCoreImageSize  = DxeCoreImage.NoPages * EFI_PAGE_SIZE;\r
+    Handoff.DxeCoreEntryPoint = (VOID *)(UINTN)DxeCoreImage.EntryPoint;\r
+\r
+    EfiMainEntrypoint = (EFI_MAIN_ENTRYPOINT)(UINTN)DxeIplImage.EntryPoint;\r
+    EfiMainEntrypoint (&Handoff);\r
+  }\r
+\r
+PrintHeader ('F');\r
+\r
+  //\r
+  // There was a problem loading the image, so HALT the system.\r
+  //\r
+\r
+  CpuDeadLoop();\r
+}\r
+\r
diff --git a/DuetPkg/EfiLdr/Ia32/EfiLdr.inf b/DuetPkg/EfiLdr/Ia32/EfiLdr.inf
new file mode 100644 (file)
index 0000000..ba87791
--- /dev/null
@@ -0,0 +1,27 @@
+#/*++\r
+# \r
+# Copyright (c) 2006, Intel Corporation                                                         \r
+# All rights reserved. This program and the accompanying materials                          \r
+# are licensed and made available under the terms and conditions of the BSD License         \r
+# which accompanies this distribution.  The full text of the license may be found at        \r
+# http://opensource.org/licenses/bsd-license.php                                            \r
+#                                                                                           \r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+#\r
+#  Module Name:\r
+#    EfiLdr.inf\r
+#\r
+#  Abstract:\r
+#\r
+#--*/\r
+\r
+[defines]\r
+BASE_NAME       = EfiLoader\r
+COMPONENT_TYPE  = FILE\r
+BUILD_TYPE      = CUSTOM_MAKEFILE\r
+FILE_GUID       = 7E374E25-8E01-4FEE-87F2-390C23C606CD\r
+\r
+[sources.common]\r
+\r
+[nmake.common]\r
diff --git a/DuetPkg/EfiLdr/Ia32/Makefile b/DuetPkg/EfiLdr/Ia32/Makefile
new file mode 100644 (file)
index 0000000..61cadf7
--- /dev/null
@@ -0,0 +1,183 @@
+#/*++\r
+#\r
+#  Copyright (c) 2006 - 2007, Intel Corporation                                                         \r
+#  All rights reserved. This program and the accompanying materials                          \r
+#  are licensed and made available under the terms and conditions of the BSD License         \r
+#  which accompanies this distribution.  The full text of the license may be found at        \r
+#  http://opensource.org/licenses/bsd-license.php                                            \r
+#                                                                                            \r
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+#  \r
+#  Module Name:  \r
+#    Makefile\r
+#  \r
+#  Abstract:\r
+#   \r
+#--*/\r
+\r
+#\r
+# Globals\r
+#\r
+BIN_DIR     = $(BUILD_DIR)\$(PROCESSOR)\r
+TOOLCHAIN   = TOOLCHAIN_$(PROCESSOR)\r
+\r
+TOOLBIN_DIR = $(BUILD_DIR)\Tools\r
+\r
+#\r
+# Include CommonTools.env enviroment\r
+#\r
+\r
+!INCLUDE $(BUILD_DIR)\PlatformTools.env\r
+\r
+#\r
+# Include paths\r
+#\r
+INC = -I $(SOURCE_DIR)\. -I $(SOURCE_DIR)\.\$(PROCESSOR) $(INC)\r
+INC = -I $(EDK_SOURCE)\Foundation\ \\r
+      -I $(EDK_SOURCE)\Foundation\Include \\r
+      -I $(EDK_SOURCE)\Foundation\Include\$(PROCESSOR) \\r
+      -I $(EDK_SOURCE)\Foundation\Efi \\r
+      -I $(EDK_SOURCE)\Foundation\Efi\Include \\r
+      -I $(EDK_SOURCE)\Foundation\Framework \\r
+      -I $(EDK_SOURCE)\Foundation\Framework\Include \\r
+      -I $(EDK_SOURCE)\Foundation\Library\Dxe\Include \\r
+      -I $(EDK_SOURCE)\Foundation\Library\Pei\Include \\r
+      -I $(EDK_SOURCE)\Foundation\Include\Pei \\r
+      $(INC)\r
+\r
+LDRDEP = $(BUILD_DIR)\..\Loader\EfiLdr\Efildr.c \\r
+         $(BUILD_DIR)\..\Loader\EfiLdr\EfiLdrHandoff.h \\r
+         $(BUILD_DIR)\..\Loader\EfiLdr\EfiLoader.c \\r
+         $(BUILD_DIR)\..\Loader\EfiLdr\Debug.c \\r
+         $(BUILD_DIR)\..\Loader\EfiLdr\Debug.h \\r
+         $(BUILD_DIR)\..\Loader\EfiLdr\PeLoader.c \\r
+         $(BUILD_DIR)\..\Loader\EfiLdr\PeLoader.h \\r
+         $(BUILD_DIR)\..\Loader\EfiLdr\Support.c \\r
+         $(BUILD_DIR)\..\Loader\EfiLdr\Support.h\r
+\r
+all : \\r
+  $(BIN_DIR)\BootSect.com \\r
+  $(BIN_DIR)\Bs16.com     \\r
+  $(BIN_DIR)\Bs32.com     \\r
+  $(BIN_DIR)\Gpt.com      \\r
+  $(BIN_DIR)\Mbr.com      \\r
+  $(BIN_DIR)\Start.com    \\r
+  $(BIN_DIR)\Start16.com  \\r
+  $(BIN_DIR)\Start32.com  \\r
+  $(BIN_DIR)\Efi32.com2   \\r
+  $(BIN_DIR)\Efildr.efi   \\r
+\r
+\r
+loader :      \\r
+  Fv\Efildr   \\r
+  Fv\Efildr16 \\r
+  Fv\Efildr20 \\r
+\r
+\r
+#\r
+# Generate loader object\r
+#\r
+$(BIN_DIR)\BootSect.obj: $(BUILD_DIR)\..\Loader\BootSector\BootSect.asm\r
+  $(ASM16) /c /omf /Fo$(BIN_DIR)\BootSect.obj $(BUILD_DIR)\..\Loader\BootSector\BootSect.asm \r
+\r
+$(BIN_DIR)\BootSect.com: $(BIN_DIR)\BootSect.obj\r
+  cd $(BIN_DIR)\r
+  $(ASMLINK16) /tiny BootSect.obj,BootSect.com,BootSect.map,,,\r
+\r
+$(BIN_DIR)\Bs16.obj: $(BUILD_DIR)\..\Loader\BootSector\Bs16.asm\r
+  $(ASM16) /c /omf /Fo$(BIN_DIR)\Bs16.obj $(BUILD_DIR)\..\Loader\BootSector\Bs16.asm \r
+\r
+$(BIN_DIR)\Bs16.com: $(BIN_DIR)\Bs16.obj\r
+  cd $(BIN_DIR)\r
+  $(ASMLINK16) /tiny Bs16.obj,Bs16.com,Bs16.map,,,\r
+\r
+$(BIN_DIR)\Bs32.obj: $(BUILD_DIR)\..\Loader\BootSector\Bs32.asm\r
+  $(ASM16) /c /omf /Fo$(BIN_DIR)\Bs32.obj $(BUILD_DIR)\..\Loader\BootSector\Bs32.asm \r
+\r
+$(BIN_DIR)\Bs32.com: $(BIN_DIR)\Bs32.obj\r
+  cd $(BIN_DIR)\r
+  $(ASMLINK16) /tiny Bs32.obj,Bs32.com,Bs32.map,,,\r
+\r
+$(BIN_DIR)\Gpt.obj: $(BUILD_DIR)\..\Loader\BootSector\Gpt.asm\r
+  $(ASM16) /c /omf /Fo$(BIN_DIR)\Gpt.obj $(BUILD_DIR)\..\Loader\BootSector\Gpt.asm \r
+\r
+$(BIN_DIR)\Gpt.com: $(BIN_DIR)\Gpt.obj\r
+  cd $(BIN_DIR)\r
+  $(ASMLINK16) /tiny Gpt.obj,Gpt.com,Gpt.map,,,\r
+\r
+$(BIN_DIR)\Mbr.obj: $(BUILD_DIR)\..\Loader\BootSector\Mbr.asm\r
+  $(ASM16) /c /omf /Fo$(BIN_DIR)\Mbr.obj $(BUILD_DIR)\..\Loader\BootSector\Mbr.asm \r
+\r
+$(BIN_DIR)\Mbr.com: $(BIN_DIR)\Mbr.obj\r
+  cd $(BIN_DIR)\r
+  $(ASMLINK16) /tiny Mbr.obj,Mbr.com,Mbr.map,,,\r
+\r
+$(BIN_DIR)\Start.obj: $(BUILD_DIR)\..\Loader\BootSector\Start.asm\r
+  $(ASM16) /c /omf /Fo$(BIN_DIR)\Start.obj $(BUILD_DIR)\..\Loader\BootSector\Start.asm \r
+\r
+$(BIN_DIR)\Start.com: $(BIN_DIR)\Start.obj\r
+  cd $(BIN_DIR)\r
+  $(ASMLINK16) /tiny Start.obj,Start.com,Start.map,,,\r
+\r
+$(BIN_DIR)\Start16.obj: $(BUILD_DIR)\..\Loader\BootSector\Start16.asm\r
+  $(ASM16) /c /omf /Fo$(BIN_DIR)\Start16.obj $(BUILD_DIR)\..\Loader\BootSector\Start16.asm \r
+\r
+$(BIN_DIR)\Start16.com: $(BIN_DIR)\Start16.obj\r
+  cd $(BIN_DIR)\r
+  $(ASMLINK16) /tiny Start16.obj,Start16.com,Start16.map,,,\r
+\r
+$(BIN_DIR)\Start32.obj: $(BUILD_DIR)\..\Loader\BootSector\Start32.asm\r
+  $(ASM16) /c /omf /Fo$(BIN_DIR)\Start32.obj $(BUILD_DIR)\..\Loader\BootSector\Start32.asm \r
+\r
+$(BIN_DIR)\Start32.com: $(BIN_DIR)\Start32.obj\r
+  cd $(BIN_DIR)\r
+  $(ASMLINK16) /tiny Start32.obj,Start32.com,Start32.map,,,\r
+\r
+$(BIN_DIR)\Efi32.obj: $(BUILD_DIR)\..\Loader\BootSector\Efi32.asm\r
+  $(ASM16) /c /omf /Fo$(BIN_DIR)\Efi32.obj $(BUILD_DIR)\..\Loader\BootSector\Efi32.asm \r
+\r
+$(BIN_DIR)\Efi32.com: $(BIN_DIR)\Efi32.obj\r
+  cd $(BIN_DIR)\r
+  $(ASMLINK16) /tiny Efi32.obj,Efi32.com,Efi32.map,,,\r
+\r
+$(BIN_DIR)\Efi32.com2: $(BIN_DIR)\Efi32.com\r
+  $(TOOLBIN_DIR)\Splitfile $(BIN_DIR)\Efi32.com 135168\r
+\r
+$(BIN_DIR)\Efildr.obj: $(LDRDEP)\r
+  $(CC) $(C_FLAGS) $(BUILD_DIR)\..\Loader\EfiLdr\Efildr.c\r
+\r
+$(BIN_DIR)\Efildr.dll: $(BIN_DIR)\Efildr.obj\r
+  $(LINK) /nologo /MACHINE:X86 /SUBSYSTEM:CONSOLE /NODEFAULTLIB /INCREMENTAL:NO \\r
+          /MAP /FIXED /BASE:0x00010000 /OPT:REF /ALIGN:32 /MERGE:.data=.text \\r
+          /MERGE:.rdata=.text /DRIVER /ENTRY:EfiLoader $(BIN_DIR)\Efildr.obj \\r
+          $(BIN_DIR)\CompilerStub.lib $(BIN_DIR)\EfiCommonLib.lib $(BIN_DIR)\PeiLib.lib \\r
+          /OUT:$(BIN_DIR)\Efildr.dll /IGNORE:4078,4096\r
+\r
+$(BIN_DIR)\Efildr.efi: $(BIN_DIR)\Efildr.dll\r
+  $(TOOLBIN_DIR)\FwImage app $(BIN_DIR)\Efildr.dll $(BIN_DIR)\Efildr.efi\r
+\r
+#\r
+# Generate loader binary\r
+#\r
+Fv\EfiMain.z : Fv\EfiMain.fv\r
+  $(TOOLBIN_DIR)\Eficompress -tTiano Fv\EfiMain.fv Fv\EfiMain.z\r
\r
+Fv\DxeMain.z : $(BIN_DIR)\DxeMain.efi\r
+  $(TOOLBIN_DIR)\Eficompress -tTiano $(BIN_DIR)\DxeMain.efi Fv\DxeMain.z\r
\r
+Fv\DxeIpl.z : $(BIN_DIR)\DxeIpl.efi\r
+  $(TOOLBIN_DIR)\Eficompress -tTiano $(BIN_DIR)\DxeIpl.efi Fv\DxeIpl.z\r
+\r
+Fv\Efildr32: $(BIN_DIR)\Efildr.efi Fv\DxeIpl.z Fv\DxeMain.z Fv\EfiMain.z\r
+  $(TOOLBIN_DIR)\Efildrimage Fv\Efildr32 $(BIN_DIR)\Efildr.efi Fv\DxeIpl.z Fv\DxeMain.z Fv\EfiMain.z\r
+\r
+Fv\Efildr: $(BIN_DIR)\Start.com $(BIN_DIR)\Efi32.com2 Fv\Efildr32\r
+  copy /b $(BIN_DIR)\Start.com+$(BIN_DIR)\Efi32.com2+Fv\Efildr32 Fv\Efildr\r
+\r
+Fv\Efildr16: $(BIN_DIR)\Start16.com $(BIN_DIR)\Efi32.com2 Fv\Efildr32\r
+  copy /b $(BIN_DIR)\Start16.com+$(BIN_DIR)\Efi32.com2+Fv\Efildr32 Fv\Efildr16\r
+\r
+Fv\Efildr20: $(BIN_DIR)\Start32.com $(BIN_DIR)\Efi32.com2 Fv\Efildr32\r
+  copy /b $(BIN_DIR)\Start32.com+$(BIN_DIR)\Efi32.com2+Fv\Efildr32 Fv\Efildr20\r
+\r
diff --git a/DuetPkg/EfiLdr/PeLoader.c b/DuetPkg/EfiLdr/PeLoader.c
new file mode 100644 (file)
index 0000000..73608da
--- /dev/null
@@ -0,0 +1,641 @@
+/*++\r
+\r
+Copyright (c) 2006, Intel Corporation                                                         \r
+All rights reserved. This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
+                                                                                          \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+\r
+Module Name:\r
+  PeLoader.c\r
+\r
+Abstract:\r
+\r
+Revision History:\r
+\r
+--*/\r
+#include "EfiLdr.h"\r
+#include "Debug.h"\r
+#include "Support.h"\r
+\r
+STATIC\r
+EFI_STATUS\r
+EfiLdrPeCoffLoadPeRelocate (\r
+  IN EFILDR_LOADED_IMAGE      *Image,\r
+  IN EFI_IMAGE_DATA_DIRECTORY *RelocDir,\r
+  IN UINTN                     Adjust,\r
+  IN UINTN                    *NumberOfMemoryMapEntries,\r
+  IN EFI_MEMORY_DESCRIPTOR    *EfiMemoryDescriptor\r
+  );\r
+\r
+STATIC\r
+EFI_STATUS\r
+EfiLdrPeCoffImageRead (\r
+    IN VOID                 *FHand,\r
+    IN UINTN                Offset,\r
+    IN OUT UINTN            ReadSize,\r
+    OUT VOID                *Buffer\r
+    );\r
+\r
+STATIC\r
+VOID *\r
+EfiLdrPeCoffImageAddress (\r
+  IN EFILDR_LOADED_IMAGE     *Image,\r
+  IN UINTN                   Address\r
+  );\r
+\r
+\r
+EFI_STATUS\r
+EfiLdrPeCoffSetImageType (\r
+  IN OUT EFILDR_LOADED_IMAGE      *Image,\r
+  IN UINTN                        ImageType\r
+  );\r
+\r
+EFI_STATUS\r
+EfiLdrPeCoffCheckImageMachineType (\r
+  IN UINT16           MachineType\r
+  );\r
+\r
+EFI_STATUS\r
+EfiLdrGetPeImageInfo (\r
+  IN  VOID                    *FHand,\r
+  OUT UINT64                  *ImageBase,\r
+  OUT UINT32                  *ImageSize\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  EFI_IMAGE_DOS_HEADER              DosHdr;\r
+  EFI_IMAGE_OPTIONAL_HEADER_UNION   PeHdr;\r
+\r
+  ZeroMem (&DosHdr, sizeof(DosHdr));\r
+  ZeroMem (&PeHdr, sizeof(PeHdr));\r
+\r
+  //\r
+  // Read image headers\r
+  //\r
+\r
+  EfiLdrPeCoffImageRead (FHand, 0, sizeof(DosHdr), &DosHdr);\r
+  if (DosHdr.e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  EfiLdrPeCoffImageRead (FHand, DosHdr.e_lfanew, sizeof(PeHdr), &PeHdr);\r
+\r
+  if (PeHdr.Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+    \r
+  //\r
+  // Verify machine type\r
+  //\r
+\r
+  Status = EfiLdrPeCoffCheckImageMachineType (PeHdr.Pe32.FileHeader.Machine);\r
+  if (EFI_ERROR(Status)) {\r
+    return Status;\r
+  }\r
+\r
+  if (PeHdr.Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+    *ImageBase = (UINT32)PeHdr.Pe32.OptionalHeader.ImageBase;\r
+  } else if (PeHdr.Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
+    *ImageBase = PeHdr.Pe32Plus.OptionalHeader.ImageBase;\r
+  } else {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+  \r
+  *ImageSize = PeHdr.Pe32.OptionalHeader.SizeOfImage;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EfiLdrPeCoffLoadPeImage (\r
+  IN VOID                     *FHand,\r
+  IN EFILDR_LOADED_IMAGE      *Image,\r
+  IN UINTN                    *NumberOfMemoryMapEntries,\r
+  IN EFI_MEMORY_DESCRIPTOR    *EfiMemoryDescriptor\r
+  )\r
+{\r
+  EFI_IMAGE_DOS_HEADER            DosHdr;\r
+  EFI_IMAGE_OPTIONAL_HEADER_UNION PeHdr;\r
+  EFI_IMAGE_SECTION_HEADER        *FirstSection;\r
+  EFI_IMAGE_SECTION_HEADER        *Section;\r
+  UINTN                           Index;\r
+  EFI_STATUS                      Status;\r
+  UINT8                           *Base;\r
+  UINT8                           *End;\r
+  EFI_IMAGE_DATA_DIRECTORY        *DirectoryEntry;\r
+  UINTN                           DirCount;\r
+  EFI_IMAGE_DEBUG_DIRECTORY_ENTRY TempDebugEntry;\r
+  EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry;\r
+  UINTN                           CodeViewSize;\r
+  UINTN                           CodeViewOffset;\r
+  UINTN                           CodeViewFileOffset;\r
+  UINTN                           OptionalHeaderSize;\r
+  UINTN                           PeHeaderSize;\r
+  UINT32                          NumberOfRvaAndSizes;\r
+  EFI_IMAGE_DATA_DIRECTORY        *DataDirectory;\r
+  UINT64                          ImageBase;\r
+\r
+  ZeroMem (&DosHdr, sizeof(DosHdr));\r
+  ZeroMem (&PeHdr, sizeof(PeHdr));\r
+\r
+  //\r
+  // Read image headers\r
+  //\r
+\r
+  EfiLdrPeCoffImageRead (FHand, 0, sizeof(DosHdr), &DosHdr);\r
+  if (DosHdr.e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r
+//    DEBUG ((D_LOAD, "PeCoffLoadPeImage: Dos header signature not found\n"));\r
+PrintHeader ('F');\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  EfiLdrPeCoffImageRead (FHand, DosHdr.e_lfanew, sizeof(PeHdr), &PeHdr);\r
+\r
+  if (PeHdr.Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) {\r
+//    DEBUG ((D_LOAD, "PeCoffLoadPeImage: PE image header signature not found\n"));\r
+PrintHeader ('G');\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+    \r
+  //\r
+  // Set the image subsystem type\r
+  //\r
+\r
+  Status = EfiLdrPeCoffSetImageType (Image, PeHdr.Pe32.OptionalHeader.Subsystem);\r
+  if (EFI_ERROR(Status)) {\r
+//    DEBUG ((D_LOAD, "PeCoffLoadPeImage: Subsystem type not known\n"));\r
+PrintHeader ('H');\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Verify machine type\r
+  //\r
+\r
+  Status = EfiLdrPeCoffCheckImageMachineType (PeHdr.Pe32.FileHeader.Machine);\r
+  if (EFI_ERROR(Status)) {\r
+//    DEBUG ((D_LOAD, "PeCoffLoadPeImage: Incorrect machine type\n"));\r
+PrintHeader ('I');\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Compute the amount of memory needed to load the image and \r
+  // allocate it.  This will include all sections plus the codeview debug info.\r
+  // Since the codeview info is actually outside of the image, we calculate\r
+  // its size seperately and add it to the total.\r
+  //\r
+  // Memory starts off as data\r
+  //\r
+\r
+  CodeViewSize       = 0;\r
+  CodeViewFileOffset = 0;\r
+  if (PeHdr.Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+    DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(PeHdr.Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);\r
+  } else if (PeHdr.Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
+    DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(PeHdr.Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);\r
+  } else {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+  for (DirCount = 0; \r
+       (DirCount < DirectoryEntry->Size / sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY)) && (CodeViewSize == 0);\r
+       DirCount++) {\r
+    Status = EfiLdrPeCoffImageRead (\r
+               FHand, \r
+               DirectoryEntry->VirtualAddress + DirCount * sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY),\r
+               sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY),\r
+               &TempDebugEntry\r
+               );\r
+    if (!EFI_ERROR (Status)) {\r
+      if (TempDebugEntry.Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {\r
+        CodeViewSize = TempDebugEntry.SizeOfData;\r
+        CodeViewFileOffset = TempDebugEntry.FileOffset;\r
+      }\r
+    }\r
+  }\r
+    \r
+  CodeViewOffset = PeHdr.Pe32.OptionalHeader.SizeOfImage + PeHdr.Pe32.OptionalHeader.SectionAlignment;\r
+  Image->NoPages = EFI_SIZE_TO_PAGES (CodeViewOffset + CodeViewSize);\r
+\r
+  //\r
+  // Compute the amount of memory needed to load the image and \r
+  // allocate it.  Memory starts off as data\r
+  //\r
+\r
+  Image->ImageBasePage = (EFI_PHYSICAL_ADDRESS)FindSpace (Image->NoPages, NumberOfMemoryMapEntries, EfiMemoryDescriptor, EfiRuntimeServicesCode, EFI_MEMORY_WB);\r
+  if (Image->ImageBasePage == 0) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  if (EFI_ERROR(Status)) {\r
+PrintHeader ('J');\r
+    return Status;\r
+  }\r
+\r
+//  DEBUG((D_LOAD, "LoadPe: new image base %lx\n", Image->ImageBasePage));\r
+  Image->Info.ImageBase = (VOID *)(UINTN)Image->ImageBasePage;\r
+  Image->Info.ImageSize = (Image->NoPages << EFI_PAGE_SHIFT) - 1;\r
+  Image->ImageBase      = (UINT8 *)(UINTN)Image->ImageBasePage;\r
+  Image->ImageEof       = Image->ImageBase + Image->Info.ImageSize;\r
+  Image->ImageAdjust    = Image->ImageBase;\r
+\r
+  //\r
+  // Copy the Image header to the base location\r
+  //\r
+  Status = EfiLdrPeCoffImageRead (\r
+             FHand, \r
+             0, \r
+             PeHdr.Pe32.OptionalHeader.SizeOfHeaders, \r
+             Image->ImageBase\r
+             );\r
+\r
+  if (EFI_ERROR(Status)) {\r
+PrintHeader ('K');\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Load each directory of the image into memory... \r
+  //  Save the address of the Debug directory for later\r
+  //\r
+  if (PeHdr.Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+    NumberOfRvaAndSizes = PeHdr.Pe32.OptionalHeader.NumberOfRvaAndSizes;\r
+    DataDirectory = PeHdr.Pe32.OptionalHeader.DataDirectory;\r
+  } else {\r
+    NumberOfRvaAndSizes = PeHdr.Pe32Plus.OptionalHeader.NumberOfRvaAndSizes;\r
+    DataDirectory = PeHdr.Pe32Plus.OptionalHeader.DataDirectory;\r
+  }\r
+  DebugEntry = NULL;\r
+  for (Index = 0; Index < NumberOfRvaAndSizes; Index++) {\r
+    if ((DataDirectory[Index].VirtualAddress != 0) && (DataDirectory[Index].Size != 0)) {\r
+      Status = EfiLdrPeCoffImageRead (\r
+                 FHand,\r
+                 DataDirectory[Index].VirtualAddress,\r
+                 DataDirectory[Index].Size,\r
+                 Image->ImageBase + DataDirectory[Index].VirtualAddress\r
+                 );\r
+      if (EFI_ERROR(Status)) {\r
+        return Status;\r
+      }\r
+      if (Index == EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {\r
+        DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) (Image->ImageBase + DataDirectory[Index].VirtualAddress);\r
+      }\r
+    }\r
+  }\r
+\r
+  //\r
+  // Load each section of the image\r
+  //\r
+\r
+  // BUGBUG: change this to use the in memory copy\r
+  if (PeHdr.Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+    OptionalHeaderSize = sizeof(EFI_IMAGE_OPTIONAL_HEADER32);\r
+    PeHeaderSize       = sizeof(EFI_IMAGE_NT_HEADERS32);\r
+  } else {\r
+    OptionalHeaderSize = sizeof(EFI_IMAGE_OPTIONAL_HEADER64);\r
+    PeHeaderSize       = sizeof(EFI_IMAGE_NT_HEADERS64);\r
+  }\r
+  FirstSection = (EFI_IMAGE_SECTION_HEADER *) (\r
+                   Image->ImageBase +\r
+                   DosHdr.e_lfanew + \r
+                   PeHeaderSize + \r
+                   PeHdr.Pe32.FileHeader.SizeOfOptionalHeader - \r
+                   OptionalHeaderSize\r
+                   );\r
+\r
+  Section = FirstSection;\r
+  for (Index=0; Index < PeHdr.Pe32.FileHeader.NumberOfSections; Index += 1) {\r
+\r
+    //\r
+    // Compute sections address\r
+    //\r
+\r
+    Base = EfiLdrPeCoffImageAddress (Image, (UINTN)Section->VirtualAddress);\r
+    End = EfiLdrPeCoffImageAddress (Image, (UINTN)(Section->VirtualAddress + Section->Misc.VirtualSize));\r
+        \r
+    if (EFI_ERROR(Status) || !Base || !End) {\r
+//      DEBUG((D_LOAD|D_ERROR, "LoadPe: Section %d was not loaded\n", Index));\r
+PrintHeader ('L');\r
+      return EFI_LOAD_ERROR;\r
+    }\r
+\r
+//    DEBUG((D_LOAD, "LoadPe: Section %d, loaded at %x\n", Index, Base));\r
+\r
+    //\r
+    // Read the section\r
+    //\r
\r
+    if (Section->SizeOfRawData) {\r
+      Status = EfiLdrPeCoffImageRead (FHand, Section->PointerToRawData, Section->SizeOfRawData, Base);\r
+      if (EFI_ERROR(Status)) {\r
+PrintHeader ('M');\r
+        return Status;\r
+      }\r
+    }\r
+\r
+    //\r
+    // If raw size is less then virt size, zero fill the remaining\r
+    //\r
+\r
+    if (Section->SizeOfRawData < Section->Misc.VirtualSize) {\r
+      ZeroMem (\r
+        Base + Section->SizeOfRawData, \r
+        Section->Misc.VirtualSize - Section->SizeOfRawData\r
+        );\r
+    }\r
+\r
+    //\r
+    // Next Section\r
+    //\r
+\r
+    Section += 1;\r
+  }\r
+\r
+  //\r
+  // Copy in CodeView information if it exists\r
+  //\r
+  if (CodeViewSize != 0) {\r
+    Status = EfiLdrPeCoffImageRead (FHand, CodeViewFileOffset, CodeViewSize, Image->ImageBase + CodeViewOffset);\r
+    DebugEntry->RVA = (UINT32) (CodeViewOffset);\r
+  }\r
+\r
+  //\r
+  // Apply relocations only if needed\r
+  //\r
+  if (PeHdr.Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+    ImageBase = (UINT64)PeHdr.Pe32.OptionalHeader.ImageBase;\r
+  } else {\r
+    ImageBase = PeHdr.Pe32Plus.OptionalHeader.ImageBase;\r
+  }\r
+  if ((UINTN)(Image->ImageBase) != (UINTN) (ImageBase)) {\r
+    Status = EfiLdrPeCoffLoadPeRelocate (\r
+               Image,\r
+               &DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC],\r
+               (UINTN) Image->ImageBase - (UINTN)ImageBase,\r
+               NumberOfMemoryMapEntries,\r
+               EfiMemoryDescriptor\r
+               );\r
+\r
+    if (EFI_ERROR(Status)) {\r
+PrintHeader ('N');\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Use exported EFI specific interface if present, else use the image's entry point\r
+  //\r
+  Image->EntryPoint = (EFI_IMAGE_ENTRY_POINT)(UINTN)\r
+                        (EfiLdrPeCoffImageAddress(\r
+                           Image, \r
+                           PeHdr.Pe32.OptionalHeader.AddressOfEntryPoint\r
+                           ));\r
+\r
+  return Status;\r
+}\r
+\r
+STATIC\r
+EFI_STATUS\r
+EfiLdrPeCoffLoadPeRelocate (\r
+  IN EFILDR_LOADED_IMAGE      *Image,\r
+  IN EFI_IMAGE_DATA_DIRECTORY *RelocDir,\r
+  IN UINTN                     Adjust,\r
+  IN UINTN                    *NumberOfMemoryMapEntries,\r
+  IN EFI_MEMORY_DESCRIPTOR    *EfiMemoryDescriptor\r
+  )\r
+{\r
+  EFI_IMAGE_BASE_RELOCATION   *RelocBase;\r
+  EFI_IMAGE_BASE_RELOCATION   *RelocBaseEnd;\r
+  UINT16                      *Reloc;\r
+  UINT16                      *RelocEnd;\r
+  UINT8                       *Fixup;\r
+  UINT8                       *FixupBase;\r
+  UINT16                      *F16;\r
+  UINT32                      *F32;\r
+  UINT64                      *F64;\r
+  UINT8                       *FixupData;\r
+  UINTN                       NoFixupPages;\r
+\r
+  //\r
+  // Find the relocation block\r
+  //\r
+\r
+  RelocBase = EfiLdrPeCoffImageAddress (Image, RelocDir->VirtualAddress);\r
+  RelocBaseEnd = EfiLdrPeCoffImageAddress (Image, RelocDir->VirtualAddress + RelocDir->Size);\r
+  if (!RelocBase || !RelocBaseEnd) {\r
+PrintHeader ('O');\r
+    return EFI_LOAD_ERROR;\r
+  }\r
+\r
+  NoFixupPages = EFI_SIZE_TO_PAGES(RelocDir->Size / sizeof(UINT16) * sizeof(UINTN));\r
+  Image->FixupData = (UINT8*) FindSpace (NoFixupPages, NumberOfMemoryMapEntries, EfiMemoryDescriptor, EfiRuntimeServicesData, EFI_MEMORY_WB);\r
+  if (Image->FixupData == 0) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  //\r
+  // Run the whole relocation block\r
+  //\r
+\r
+  FixupData = Image->FixupData;\r
+  while (RelocBase < RelocBaseEnd) {\r
+           \r
+    Reloc = (UINT16 *) ((UINT8 *) RelocBase + sizeof(EFI_IMAGE_BASE_RELOCATION));\r
+    RelocEnd = (UINT16 *) ((UINT8 *) RelocBase + RelocBase->SizeOfBlock);\r
+    FixupBase = EfiLdrPeCoffImageAddress (Image, RelocBase->VirtualAddress);\r
+    if ((UINT8 *) RelocEnd < Image->ImageBase || (UINT8 *) RelocEnd > Image->ImageEof) {\r
+PrintHeader ('P');\r
+      return EFI_LOAD_ERROR;\r
+    }\r
+\r
+    //\r
+    // Run this relocation record\r
+    //\r
+\r
+    while (Reloc < RelocEnd) {\r
+\r
+      Fixup = FixupBase + (*Reloc & 0xFFF);\r
+      switch ((*Reloc) >> 12) {\r
+\r
+      case EFI_IMAGE_REL_BASED_ABSOLUTE:\r
+        break;\r
+\r
+      case EFI_IMAGE_REL_BASED_HIGH:\r
+        F16 = (UINT16 *) Fixup;\r
+        *F16  = (UINT16) (*F16 + (UINT16)(((UINT32)Adjust) >> 16));\r
+        if (FixupData != NULL) {\r
+          *(UINT16 *) FixupData = *F16;\r
+          FixupData = FixupData + sizeof(UINT16);\r
+        }\r
+        break;\r
+\r
+      case EFI_IMAGE_REL_BASED_LOW:\r
+        F16 = (UINT16 *) Fixup;\r
+        *F16 = *F16 + (UINT16) Adjust;\r
+        if (FixupData != NULL) {\r
+          *(UINT16 *) FixupData = *F16;\r
+          FixupData = FixupData + sizeof(UINT16);\r
+        }\r
+        break;\r
+\r
+      case EFI_IMAGE_REL_BASED_HIGHLOW:\r
+        F32 = (UINT32 *) Fixup;\r
+        *F32 = *F32 + (UINT32) Adjust;\r
+        if (FixupData != NULL) {\r
+          FixupData = ALIGN_POINTER(FixupData, sizeof(UINT32));\r
+          *(UINT32 *) FixupData = *F32;\r
+          FixupData = FixupData + sizeof(UINT32);\r
+        }\r
+        break;\r
+\r
+      case EFI_IMAGE_REL_BASED_DIR64:\r
+        F64 = (UINT64 *) Fixup;\r
+        *F64 = *F64 + (UINT64) Adjust;\r
+        if (FixupData != NULL) {\r
+          FixupData = ALIGN_POINTER(FixupData, sizeof(UINT64));\r
+          *(UINT64 *) FixupData = *F64;\r
+          FixupData = FixupData + sizeof(UINT64);\r
+        }\r
+        break;\r
+\r
+      case EFI_IMAGE_REL_BASED_HIGHADJ:\r
+        CpuDeadLoop();                 // BUGBUG: not done\r
+        break;\r
+\r
+      default:\r
+//        DEBUG((D_LOAD|D_ERROR, "PeRelocate: unknown fixed type\n"));\r
+PrintHeader ('Q');\r
+        CpuDeadLoop();\r
+        return EFI_LOAD_ERROR;\r
+      }\r
+\r
+      // Next reloc record\r
+      Reloc += 1;\r
+    }\r
+\r
+    // next reloc block\r
+    RelocBase = (EFI_IMAGE_BASE_RELOCATION *) RelocEnd;\r
+  }\r
+\r
+  //\r
+  // Add Fixup data to whole Image (assume Fixup data just below the image), so that there is no hole in the descriptor.\r
+  // Because only NoPages or ImageBasePage will be used in EfiLoader(), we update these 2 fields.\r
+  //\r
+  Image->NoPages += NoFixupPages;\r
+  Image->ImageBasePage -= (NoFixupPages << EFI_PAGE_SHIFT);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+STATIC\r
+EFI_STATUS\r
+EfiLdrPeCoffImageRead (\r
+  IN VOID                 *FHand,\r
+  IN UINTN                Offset,\r
+  IN OUT UINTN            ReadSize,\r
+  OUT VOID                *Buffer\r
+  )\r
+{\r
+  CopyMem (Buffer, (VOID *)((UINTN)FHand + Offset), ReadSize);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+STATIC\r
+VOID *\r
+EfiLdrPeCoffImageAddress (\r
+  IN EFILDR_LOADED_IMAGE     *Image,\r
+  IN UINTN                   Address\r
+  )\r
+{\r
+  UINT8        *FixedAddress;\r
+\r
+  FixedAddress = Image->ImageAdjust + Address;\r
+\r
+  if ((FixedAddress < Image->ImageBase) || (FixedAddress > Image->ImageEof)) {\r
+//    DEBUG((D_LOAD|D_ERROR, "PeCoffImageAddress: pointer is outside of image\n"));\r
+    FixedAddress = NULL;\r
+  }\r
+\r
+//  DEBUG((\r
+//    D_LOAD,\r
+//    "PeCoffImageAddress: ImageBase %x, ImageEof %x, Address %x, FixedAddress %x\n", \r
+//    Image->ImageBase,\r
+//    Image->ImageEof,\r
+//    Address,\r
+//    FixedAddress\r
+//    ));\r
+    return FixedAddress;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+EfiLdrPeCoffSetImageType (\r
+  IN OUT EFILDR_LOADED_IMAGE      *Image,\r
+  IN UINTN                        ImageType\r
+  )\r
+{\r
+  EFI_MEMORY_TYPE                 CodeType;\r
+  EFI_MEMORY_TYPE                 DataType;\r
+\r
+  switch (ImageType) {\r
+  case EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION:\r
+    CodeType = EfiLoaderCode;\r
+    DataType = EfiLoaderData;\r
+    break;\r
+\r
+  case EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER:\r
+    CodeType = EfiBootServicesCode;\r
+    DataType = EfiBootServicesData;\r
+    break;\r
+\r
+  case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER:\r
+    CodeType = EfiRuntimeServicesCode;\r
+    DataType = EfiRuntimeServicesData;\r
+    break;\r
+\r
+  default:\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Image->Type = ImageType;\r
+  Image->Info.ImageCodeType = CodeType;    \r
+  Image->Info.ImageDataType = DataType;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EfiLdrPeCoffCheckImageMachineType (\r
+  IN UINT16           MachineType\r
+  )\r
+{\r
+  EFI_STATUS          Status;\r
+\r
+  Status = EFI_UNSUPPORTED;\r
+\r
+#if EFI32\r
+  if (MachineType == EFI_IMAGE_MACHINE_IA32) {\r
+    Status = EFI_SUCCESS;\r
+  }\r
+#endif\r
+\r
+#if EFIX64\r
+  if (MachineType == EFI_IMAGE_MACHINE_X64) {\r
+    Status = EFI_SUCCESS;\r
+  }\r
+#endif\r
+\r
+#if EFI64\r
+  if (MachineType == EFI_IMAGE_MACHINE_IA64) {\r
+    Status = EFI_SUCCESS;\r
+  }\r
+#endif\r
+\r
+  return Status;\r
+}\r
+\r
diff --git a/DuetPkg/EfiLdr/PeLoader.h b/DuetPkg/EfiLdr/PeLoader.h
new file mode 100644 (file)
index 0000000..895c0b7
--- /dev/null
@@ -0,0 +1,42 @@
+/*++\r
+\r
+Copyright (c) 2006, Intel Corporation                                                         \r
+All rights reserved. This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
+                                                                                          \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+\r
+Module Name:\r
+  PeLoader.h\r
+\r
+Abstract:\r
+\r
+Revision History:\r
+\r
+--*/\r
+\r
+#ifndef _EFILDR_PELOADER_H_\r
+#define _EFILDR_PELOADER_H_\r
+\r
+#include "EfiLdr.h"\r
+\r
+EFI_STATUS\r
+EfiLdrGetPeImageInfo (\r
+  IN VOID                     *FHand,\r
+  OUT UINT64                  *ImageBase,\r
+  OUT UINT32                  *ImageSize\r
+  );\r
+\r
+EFI_STATUS\r
+EfiLdrPeCoffLoadPeImage (\r
+  IN VOID                     *FHand,\r
+  IN EFILDR_LOADED_IMAGE      *Image,\r
+  IN UINTN                    *NumberOfMemoryMapEntries,\r
+  IN EFI_MEMORY_DESCRIPTOR    *EfiMemoryDescriptor\r
+  );\r
+\r
+\r
+#endif\r
diff --git a/DuetPkg/EfiLdr/Support.c b/DuetPkg/EfiLdr/Support.c
new file mode 100644 (file)
index 0000000..0335d20
--- /dev/null
@@ -0,0 +1,237 @@
+/*++\r
+\r
+Copyright (c) 2006, Intel Corporation                                                         \r
+All rights reserved. This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
+                                                                                          \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+\r
+Module Name:\r
+  Support.c\r
+\r
+Abstract:\r
+\r
+Revision History:\r
+\r
+--*/\r
+#include "EfiLdr.h"\r
+\r
+EFI_STATUS\r
+EfiAddMemoryDescriptor(\r
+  UINTN                 *NoDesc,\r
+  EFI_MEMORY_DESCRIPTOR *Desc,\r
+  EFI_MEMORY_TYPE       Type,\r
+  EFI_PHYSICAL_ADDRESS  BaseAddress,\r
+  UINT64                NoPages,\r
+  UINT64                Attribute\r
+  )\r
+{\r
+  UINTN  NumberOfDesc;\r
+  UINT64 Temp;\r
+  UINTN  Index;\r
+\r
+  if (NoPages == 0) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // See if the new memory descriptor needs to be carved out of an existing memory descriptor\r
+  //\r
+\r
+  NumberOfDesc = *NoDesc;\r
+  for (Index = 0; Index < NumberOfDesc; Index++) {\r
+\r
+    if (Desc[Index].Type == EfiConventionalMemory) {\r
+\r
+      Temp = DivU64x32 ((BaseAddress - Desc[Index].PhysicalStart), EFI_PAGE_SIZE) + NoPages;\r
+\r
+      if ((Desc[Index].PhysicalStart < BaseAddress) && (Desc[Index].NumberOfPages >= Temp)) {\r
+        if (Desc[Index].NumberOfPages > Temp) {\r
+          Desc[*NoDesc].Type          = EfiConventionalMemory;\r
+          Desc[*NoDesc].PhysicalStart = BaseAddress + MultU64x32 (NoPages, EFI_PAGE_SIZE);\r
+          Desc[*NoDesc].NumberOfPages = Desc[Index].NumberOfPages - Temp;\r
+          Desc[*NoDesc].VirtualStart  = 0;\r
+          Desc[*NoDesc].Attribute     = Desc[Index].Attribute;\r
+          *NoDesc = *NoDesc + 1;\r
+        }\r
+        Desc[Index].NumberOfPages = Temp - NoPages;\r
+      }\r
+\r
+      if ((Desc[Index].PhysicalStart == BaseAddress) && (Desc[Index].NumberOfPages == NoPages)) {\r
+        Desc[Index].Type      = Type;\r
+        Desc[Index].Attribute = Attribute;\r
+        return EFI_SUCCESS;\r
+      }\r
+\r
+      if ((Desc[Index].PhysicalStart == BaseAddress) && (Desc[Index].NumberOfPages > NoPages)) {\r
+        Desc[Index].NumberOfPages -= NoPages;\r
+        Desc[Index].PhysicalStart += MultU64x32 (NoPages, EFI_PAGE_SIZE);\r
+      }\r
+    }\r
+  }\r
+\r
+  //\r
+  // Add the new memory descriptor\r
+  //\r
+\r
+  Desc[*NoDesc].Type          = Type;\r
+  Desc[*NoDesc].PhysicalStart = BaseAddress;\r
+  Desc[*NoDesc].NumberOfPages = NoPages;\r
+  Desc[*NoDesc].VirtualStart  = 0;\r
+  Desc[*NoDesc].Attribute     = Attribute;\r
+  *NoDesc = *NoDesc + 1;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+UINTN\r
+FindSpace (\r
+  UINTN                       NoPages,\r
+  IN UINTN                    *NumberOfMemoryMapEntries,\r
+  IN EFI_MEMORY_DESCRIPTOR    *EfiMemoryDescriptor,\r
+  EFI_MEMORY_TYPE             Type,\r
+  UINT64                      Attribute\r
+  )\r
+{\r
+  EFI_PHYSICAL_ADDRESS        MaxPhysicalStart;\r
+  UINT64                      MaxNoPages;\r
+  UINTN                       Index;\r
+  EFI_MEMORY_DESCRIPTOR       *CurrentMemoryDescriptor;\r
+\r
+  MaxPhysicalStart = 0;\r
+  MaxNoPages       = 0;\r
+  CurrentMemoryDescriptor = NULL;\r
+  for (Index = 0; Index < *NumberOfMemoryMapEntries; Index++) {\r
+    if (EfiMemoryDescriptor[Index].PhysicalStart + LShiftU64(EfiMemoryDescriptor[Index].NumberOfPages, EFI_PAGE_SHIFT) <= 0x100000) {\r
+      continue;\r
+    }\r
+    if ((EfiMemoryDescriptor[Index].Type == EfiConventionalMemory) && \r
+        (EfiMemoryDescriptor[Index].NumberOfPages >= NoPages)) {\r
+      if (EfiMemoryDescriptor[Index].PhysicalStart > MaxPhysicalStart) {\r
+        if (EfiMemoryDescriptor[Index].PhysicalStart + LShiftU64(EfiMemoryDescriptor[Index].NumberOfPages, EFI_PAGE_SHIFT) <= 0x100000000) {\r
+          MaxPhysicalStart = EfiMemoryDescriptor[Index].PhysicalStart;\r
+          MaxNoPages       = EfiMemoryDescriptor[Index].NumberOfPages;\r
+          CurrentMemoryDescriptor = &EfiMemoryDescriptor[Index];\r
+        }\r
+      }\r
+    }\r
+    if ((EfiMemoryDescriptor[Index].Type == EfiReservedMemoryType) ||\r
+        (EfiMemoryDescriptor[Index].Type >= EfiACPIReclaimMemory) ) {\r
+      continue;\r
+    }\r
+    if ((EfiMemoryDescriptor[Index].Type == EfiRuntimeServicesCode) ||\r
+        (EfiMemoryDescriptor[Index].Type == EfiRuntimeServicesData)) {\r
+      break;\r
+    }\r
+  }\r
\r
+  if (MaxPhysicalStart == 0) {\r
+    return 0;\r
+  }\r
+\r
+  if (MaxNoPages != NoPages) {\r
+    CurrentMemoryDescriptor->NumberOfPages = MaxNoPages - NoPages;\r
+    EfiMemoryDescriptor[*NumberOfMemoryMapEntries].Type          = Type;\r
+    EfiMemoryDescriptor[*NumberOfMemoryMapEntries].PhysicalStart = MaxPhysicalStart + LShiftU64(MaxNoPages - NoPages, EFI_PAGE_SHIFT);\r
+    EfiMemoryDescriptor[*NumberOfMemoryMapEntries].NumberOfPages = NoPages;\r
+    EfiMemoryDescriptor[*NumberOfMemoryMapEntries].VirtualStart  = 0;\r
+    EfiMemoryDescriptor[*NumberOfMemoryMapEntries].Attribute     = Attribute;\r
+    *NumberOfMemoryMapEntries = *NumberOfMemoryMapEntries + 1;\r
+  } else {\r
+    CurrentMemoryDescriptor->Type      = Type;\r
+    CurrentMemoryDescriptor->Attribute = Attribute;\r
+  }\r
+\r
+  return (UINTN)(MaxPhysicalStart + LShiftU64(MaxNoPages - NoPages, EFI_PAGE_SHIFT));\r
+}\r
+\r
+VOID\r
+GenMemoryMap (\r
+  UINTN                 *NumberOfMemoryMapEntries,\r
+  EFI_MEMORY_DESCRIPTOR *EfiMemoryDescriptor,\r
+  BIOS_MEMORY_MAP       *BiosMemoryMap\r
+  )\r
+{\r
+  UINT64                BaseAddress;\r
+  UINT64                Length;\r
+  EFI_MEMORY_TYPE       Type;\r
+  UINTN                 Index;\r
+  UINTN                 Attr;\r
+  UINT64                Ceiling;\r
+\r
+  Ceiling = 0xFFFFFFFF;\r
+  for (Index = 0; Index < BiosMemoryMap->MemoryMapSize / sizeof(BIOS_MEMORY_MAP_ENTRY); Index++) {\r
+\r
+    switch (BiosMemoryMap->MemoryMapEntry[Index].Type) { \r
+    case (INT15_E820_AddressRangeMemory):\r
+      Type = EfiConventionalMemory;\r
+      Attr = EFI_MEMORY_WB;\r
+      break;\r
+    case (INT15_E820_AddressRangeReserved):\r
+      Type = EfiReservedMemoryType;\r
+      Attr = EFI_MEMORY_UC;\r
+      break;\r
+    case (INT15_E820_AddressRangeACPI):\r
+      Type = EfiACPIReclaimMemory;\r
+      Attr = EFI_MEMORY_WB;\r
+      break;\r
+    case (INT15_E820_AddressRangeNVS):\r
+      Type = EfiACPIMemoryNVS;\r
+      Attr = EFI_MEMORY_UC;\r
+      break;\r
+    default:\r
+      // We should not get here, according to ACPI 2.0 Spec.\r
+      // BIOS behaviour of the Int15h, E820h\r
+      Type = EfiReservedMemoryType;\r
+      Attr = EFI_MEMORY_UC;\r
+      break;\r
+    }\r
+    if (Type == EfiConventionalMemory) {\r
+      BaseAddress = BiosMemoryMap->MemoryMapEntry[Index].BaseAddress;\r
+      Length      = BiosMemoryMap->MemoryMapEntry[Index].Length;\r
+      if (BaseAddress & EFI_PAGE_MASK) {\r
+        Length      = Length + (BaseAddress & EFI_PAGE_MASK) - EFI_PAGE_SIZE;\r
+        BaseAddress = LShiftU64 (RShiftU64 (BaseAddress, EFI_PAGE_SHIFT) + 1, EFI_PAGE_SHIFT);\r
+      }\r
+    } else {\r
+      BaseAddress = BiosMemoryMap->MemoryMapEntry[Index].BaseAddress;\r
+      Length      = BiosMemoryMap->MemoryMapEntry[Index].Length + (BaseAddress & EFI_PAGE_MASK);\r
+      BaseAddress = LShiftU64 (RShiftU64 (BaseAddress, EFI_PAGE_SHIFT), EFI_PAGE_SHIFT);\r
+      if (Length & EFI_PAGE_MASK) {\r
+        Length = LShiftU64 (RShiftU64 (Length, EFI_PAGE_SHIFT) + 1, EFI_PAGE_SHIFT);\r
+      }\r
+      //\r
+      // Update Memory Ceiling\r
+      //\r
+      if ((BaseAddress >= 0x100000) && (BaseAddress < 0x100000000)) {\r
+        if (Ceiling > BaseAddress) {\r
+          Ceiling = BaseAddress;\r
+        }\r
+      }\r
+    }\r
+    EfiAddMemoryDescriptor (\r
+      NumberOfMemoryMapEntries,\r
+      EfiMemoryDescriptor,\r
+      Type,\r
+      (EFI_PHYSICAL_ADDRESS)BaseAddress,\r
+      RShiftU64 (Length, EFI_PAGE_SHIFT),\r
+      Attr\r
+      );\r
+  }\r
+\r
+  //\r
+  // Update MemoryMap according to Ceiling\r
+  //\r
+  for (Index = 0; Index < *NumberOfMemoryMapEntries; Index++) {\r
+    if ((EfiMemoryDescriptor[Index].Type == EfiConventionalMemory) &&\r
+        (EfiMemoryDescriptor[Index].PhysicalStart > 0x100000) && \r
+        (EfiMemoryDescriptor[Index].PhysicalStart < 0x100000000)) {\r
+      if (EfiMemoryDescriptor[Index].PhysicalStart >= Ceiling) {\r
+        EfiMemoryDescriptor[Index].Type = EfiReservedMemoryType;\r
+      }\r
+    }\r
+  }\r
+}\r
diff --git a/DuetPkg/EfiLdr/Support.h b/DuetPkg/EfiLdr/Support.h
new file mode 100644 (file)
index 0000000..360f425
--- /dev/null
@@ -0,0 +1,50 @@
+/*++\r
+\r
+Copyright (c) 2006, Intel Corporation                                                         \r
+All rights reserved. This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
+                                                                                          \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+\r
+Module Name:\r
+  Support.h\r
+\r
+Abstract:\r
+\r
+Revision History:\r
+\r
+--*/\r
+\r
+#ifndef _EFILDR_SUPPORT_H_\r
+#define _EFILDR_SUPPORT_H_\r
+\r
+EFI_STATUS\r
+EfiAddMemoryDescriptor(\r
+  UINTN                 *NoDesc,\r
+  EFI_MEMORY_DESCRIPTOR *Desc,\r
+  EFI_MEMORY_TYPE       Type,\r
+  EFI_PHYSICAL_ADDRESS  BaseAddress,\r
+  UINT64                NoPages,\r
+  UINT64                Attribute\r
+  );\r
+\r
+UINTN\r
+FindSpace(\r
+  UINTN                       NoPages,\r
+  IN UINTN                    *NumberOfMemoryMapEntries,\r
+  IN EFI_MEMORY_DESCRIPTOR    *EfiMemoryDescriptor,\r
+  EFI_MEMORY_TYPE             Type,\r
+  UINT64                      Attribute\r
+  );\r
+\r
+VOID\r
+GenMemoryMap (\r
+  UINTN                 *NumberOfMemoryMapEntries,\r
+  EFI_MEMORY_DESCRIPTOR *EfiMemoryDescriptor,\r
+  BIOS_MEMORY_MAP       *BiosMemoryMap\r
+  );\r
+\r
+#endif\r
diff --git a/DuetPkg/EfiLdr/X64/EfiLdr.inf b/DuetPkg/EfiLdr/X64/EfiLdr.inf
new file mode 100644 (file)
index 0000000..ba87791
--- /dev/null
@@ -0,0 +1,27 @@
+#/*++\r
+# \r
+# Copyright (c) 2006, Intel Corporation                                                         \r
+# All rights reserved. This program and the accompanying materials                          \r
+# are licensed and made available under the terms and conditions of the BSD License         \r
+# which accompanies this distribution.  The full text of the license may be found at        \r
+# http://opensource.org/licenses/bsd-license.php                                            \r
+#                                                                                           \r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+#\r
+#  Module Name:\r
+#    EfiLdr.inf\r
+#\r
+#  Abstract:\r
+#\r
+#--*/\r
+\r
+[defines]\r
+BASE_NAME       = EfiLoader\r
+COMPONENT_TYPE  = FILE\r
+BUILD_TYPE      = CUSTOM_MAKEFILE\r
+FILE_GUID       = 7E374E25-8E01-4FEE-87F2-390C23C606CD\r
+\r
+[sources.common]\r
+\r
+[nmake.common]\r
diff --git a/DuetPkg/EfiLdr/X64/Makefile b/DuetPkg/EfiLdr/X64/Makefile
new file mode 100644 (file)
index 0000000..dc31b13
--- /dev/null
@@ -0,0 +1,186 @@
+#/*++\r
+#\r
+#  Copyright (c) 2006 - 2007, Intel Corporation                                                         \r
+#  All rights reserved. This program and the accompanying materials                          \r
+#  are licensed and made available under the terms and conditions of the BSD License         \r
+#  which accompanies this distribution.  The full text of the license may be found at        \r
+#  http://opensource.org/licenses/bsd-license.php                                            \r
+#                                                                                            \r
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+#  \r
+#  Module Name:  \r
+#    Makefile\r
+#  \r
+#  Abstract:\r
+#   \r
+#--*/\r
+\r
+#\r
+# Globals\r
+#\r
+BIN_DIR     = $(BUILD_DIR)\$(PROCESSOR)\r
+TOOLCHAIN   = TOOLCHAIN_$(PROCESSOR)\r
+\r
+TOOLBIN_DIR = $(BUILD_DIR)\Tools\r
+\r
+#\r
+# Include CommonTools.env enviroment\r
+#\r
+\r
+!INCLUDE $(BUILD_DIR)\PlatformTools.env\r
+\r
+#\r
+# Include paths\r
+#\r
+INC = -I $(SOURCE_DIR)\. -I $(SOURCE_DIR)\.\$(PROCESSOR) $(INC)\r
+INC = -I $(EDK_SOURCE)\Foundation\ \\r
+      -I $(EDK_SOURCE)\Foundation\Include \\r
+      -I $(EDK_SOURCE)\Foundation\Include\$(PROCESSOR) \\r
+      -I $(EDK_SOURCE)\Foundation\Efi \\r
+      -I $(EDK_SOURCE)\Foundation\Efi\Include \\r
+      -I $(EDK_SOURCE)\Foundation\Framework \\r
+      -I $(EDK_SOURCE)\Foundation\Framework\Include \\r
+      -I $(EDK_SOURCE)\Foundation\Library\Dxe\Include \\r
+      -I $(EDK_SOURCE)\Foundation\Library\Pei\Include \\r
+      -I $(EDK_SOURCE)\Foundation\Include\Pei \\r
+      $(INC)\r
+\r
+LDRDEP = $(BUILD_DIR)\..\Loader\EfiLdr\Efildr.c \\r
+         $(BUILD_DIR)\..\Loader\EfiLdr\EfiLdrHandoff.h \\r
+         $(BUILD_DIR)\..\Loader\EfiLdr\EfiLoader.c \\r
+         $(BUILD_DIR)\..\Loader\EfiLdr\Debug.c \\r
+         $(BUILD_DIR)\..\Loader\EfiLdr\Debug.h \\r
+         $(BUILD_DIR)\..\Loader\EfiLdr\PeLoader.c \\r
+         $(BUILD_DIR)\..\Loader\EfiLdr\PeLoader.h \\r
+         $(BUILD_DIR)\..\Loader\EfiLdr\Support.c \\r
+         $(BUILD_DIR)\..\Loader\EfiLdr\Support.h\r
+\r
+all : \\r
+  $(BIN_DIR)\BootSect.com   \\r
+  $(BIN_DIR)\Bs16.com       \\r
+  $(BIN_DIR)\Bs32.com       \\r
+  $(BIN_DIR)\Gpt.com        \\r
+  $(BIN_DIR)\Mbr.com        \\r
+  $(BIN_DIR)\Start64.com    \\r
+  $(BIN_DIR)\St16_64.com    \\r
+  $(BIN_DIR)\St32_64.com    \\r
+  $(BIN_DIR)\Efi64.com2     \\r
+  $(BIN_DIR)\Efildr.efi     \\r
+\r
+\r
+loader :      \\r
+  Fv\Efildr   \\r
+  Fv\Efildr16 \\r
+  Fv\Efildr20 \\r
+\r
+\r
+#\r
+# Generate loader object\r
+#\r
+$(BIN_DIR)\BootSect.obj: $(BUILD_DIR)\..\Loader\BootSector\BootSect.asm\r
+  $(ASM16) /c /omf /Fo$(BIN_DIR)\BootSect.obj $(BUILD_DIR)\..\Loader\BootSector\BootSect.asm \r
+\r
+$(BIN_DIR)\BootSect.com: $(BIN_DIR)\BootSect.obj\r
+  cd $(BIN_DIR)\r
+  $(ASMLINK16) /tiny BootSect.obj,BootSect.com,BootSect.map,,,\r
+\r
+$(BIN_DIR)\Bs16.obj: $(BUILD_DIR)\..\Loader\BootSector\Bs16.asm\r
+  $(ASM16) /c /omf /Fo$(BIN_DIR)\Bs16.obj $(BUILD_DIR)\..\Loader\BootSector\Bs16.asm \r
+\r
+$(BIN_DIR)\Bs16.com: $(BIN_DIR)\Bs16.obj\r
+  cd $(BIN_DIR)\r
+  $(ASMLINK16) /tiny Bs16.obj,Bs16.com,Bs16.map,,,\r
+\r
+$(BIN_DIR)\Bs32.obj: $(BUILD_DIR)\..\Loader\BootSector\Bs32.asm\r
+  $(ASM16) /c /omf /Fo$(BIN_DIR)\Bs32.obj $(BUILD_DIR)\..\Loader\BootSector\Bs32.asm \r
+\r
+$(BIN_DIR)\Bs32.com: $(BIN_DIR)\Bs32.obj\r
+  cd $(BIN_DIR)\r
+  $(ASMLINK16) /tiny Bs32.obj,Bs32.com,Bs32.map,,,\r
+\r
+$(BIN_DIR)\Gpt.obj: $(BUILD_DIR)\..\Loader\BootSector\Gpt.asm\r
+  $(ASM16) /c /omf /Fo$(BIN_DIR)\Gpt.obj $(BUILD_DIR)\..\Loader\BootSector\Gpt.asm \r
+\r
+$(BIN_DIR)\Gpt.com: $(BIN_DIR)\Gpt.obj\r
+  cd $(BIN_DIR)\r
+  $(ASMLINK16) /tiny Gpt.obj,Gpt.com,Gpt.map,,,\r
+\r
+$(BIN_DIR)\Mbr.obj: $(BUILD_DIR)\..\Loader\BootSector\Mbr.asm\r
+  $(ASM16) /c /omf /Fo$(BIN_DIR)\Mbr.obj $(BUILD_DIR)\..\Loader\BootSector\Mbr.asm \r
+\r
+$(BIN_DIR)\Mbr.com: $(BIN_DIR)\Mbr.obj\r
+  cd $(BIN_DIR)\r
+  $(ASMLINK16) /tiny Mbr.obj,Mbr.com,Mbr.map,,,\r
+\r
+$(BIN_DIR)\Start64.obj: $(BUILD_DIR)\..\Loader\BootSector\Start64.asm\r
+  $(ASM16) /c /omf /Fo$(BIN_DIR)\Start64.obj $(BUILD_DIR)\..\Loader\BootSector\Start64.asm \r
+\r
+$(BIN_DIR)\Start64.com: $(BIN_DIR)\Start64.obj\r
+  cd $(BIN_DIR)\r
+  $(ASMLINK16) /tiny Start64.obj,Start64.com,Start64.map,,,\r
+\r
+$(BIN_DIR)\St16_64.obj: $(BUILD_DIR)\..\Loader\BootSector\St16_64.asm\r
+  $(ASM16) /c /omf /Fo$(BIN_DIR)\St16_64.obj $(BUILD_DIR)\..\Loader\BootSector\St16_64.asm \r
+\r
+$(BIN_DIR)\St16_64.com: $(BIN_DIR)\St16_64.obj\r
+  cd $(BIN_DIR)\r
+  $(ASMLINK16) /tiny St16_64.obj,St16_64.com,St16_64.map,,,\r
+\r
+$(BIN_DIR)\St32_64.obj: $(BUILD_DIR)\..\Loader\BootSector\St32_64.asm\r
+  $(ASM16) /c /omf /Fo$(BIN_DIR)\St32_64.obj $(BUILD_DIR)\..\Loader\BootSector\St32_64.asm \r
+\r
+$(BIN_DIR)\St32_64.com: $(BIN_DIR)\St32_64.obj\r
+  cd $(BIN_DIR)\r
+  $(ASMLINK16) /tiny St32_64.obj,St32_64.com,St32_64.map,,,\r
+\r
+$(BIN_DIR)\Efi64.obj: $(BUILD_DIR)\..\Loader\BootSector\Efi64.asm\r
+  $(ASM16) /c /omf /Fo$(BIN_DIR)\Efi64.obj $(BUILD_DIR)\..\Loader\BootSector\Efi64.asm \r
+\r
+$(BIN_DIR)\Efi64.com: $(BIN_DIR)\Efi64.obj\r
+  cd $(BIN_DIR)\r
+  $(ASMLINK16) /tiny Efi64.obj,Efi64.com,Efi64.map,,,\r
+\r
+$(BIN_DIR)\Efi64.com2: $(BIN_DIR)\Efi64.com\r
+  $(TOOLBIN_DIR)\Splitfile $(BIN_DIR)\Efi64.com 135168\r
+\r
+$(BIN_DIR)\Efildr.obj: $(LDRDEP)\r
+  $(CC) $(C_FLAGS) $(BUILD_DIR)\..\Loader\EfiLdr\Efildr.c\r
+\r
+$(BIN_DIR)\Efildr.dll: $(BIN_DIR)\Efildr.obj\r
+  $(LINK) /nologo /MACHINE:AMD64 /SUBSYSTEM:CONSOLE /NODEFAULTLIB /INCREMENTAL:NO \\r
+          /MAP /FIXED /BASE:0x00010000 /OPT:REF /ALIGN:32 /MERGE:.data=.text \\r
+          /MERGE:.rdata=.text /DRIVER /ENTRY:EfiLoader $(BIN_DIR)\Efildr.obj \\r
+          $(BIN_DIR)\CompilerStub.lib $(BIN_DIR)\EfiCommonLib.lib $(BIN_DIR)\PeiLib.lib \\r
+          /OUT:$(BIN_DIR)\Efildr.dll /IGNORE:4078,4096\r
+\r
+$(BIN_DIR)\Efildr.efi: $(BIN_DIR)\Efildr.dll\r
+  $(TOOLBIN_DIR)\FwImage app $(BIN_DIR)\Efildr.dll $(BIN_DIR)\Efildr.efi\r
+\r
+#\r
+# Generate loader binary\r
+#\r
+Fv\EfiMain.z : Fv\EfiMain.fv\r
+  $(TOOLBIN_DIR)\Eficompress -tTiano Fv\EfiMain.fv Fv\EfiMain.z\r
\r
+Fv\DxeMain.z : $(BIN_DIR)\DxeMain.efi\r
+  $(TOOLBIN_DIR)\Eficompress -tTiano $(BIN_DIR)\DxeMain.efi Fv\DxeMain.z\r
\r
+Fv\DxeIpl.z : $(BIN_DIR)\DxeIpl.efi\r
+  $(TOOLBIN_DIR)\Eficompress -tTiano $(BIN_DIR)\DxeIpl.efi Fv\DxeIpl.z\r
+\r
+Fv\Efildr64: $(BIN_DIR)\Efildr.efi Fv\DxeIpl.z Fv\DxeMain.z Fv\EfiMain.z\r
+  $(TOOLBIN_DIR)\Efildrimage Fv\Efildr64 $(BIN_DIR)\Efildr.efi Fv\DxeIpl.z Fv\DxeMain.z Fv\EfiMain.z\r
+\r
+Fv\Efildr: $(BIN_DIR)\Start64.com $(BIN_DIR)\Efi64.com2 Fv\Efildr64\r
+  copy /b $(BIN_DIR)\Start64.com+$(BIN_DIR)\Efi64.com2+Fv\Efildr64 Fv\EfildrPure\r
+  $(TOOLBIN_DIR)\GenPage Fv\EfildrPure Fv\Efildr\r
+\r
+Fv\Efildr16: $(BIN_DIR)\St16_64.com $(BIN_DIR)\Efi64.com2 Fv\Efildr64\r
+  copy /b $(BIN_DIR)\St16_64.com+$(BIN_DIR)\Efi64.com2+Fv\Efildr64 Fv\Efildr16Pure\r
+  $(TOOLBIN_DIR)\GenPage Fv\Efildr16Pure Fv\Efildr16\r
+\r
+Fv\Efildr20: $(BIN_DIR)\St32_64.com $(BIN_DIR)\Efi64.com2 Fv\Efildr64\r
+  copy /b $(BIN_DIR)\St32_64.com+$(BIN_DIR)\Efi64.com2+Fv\Efildr64 Fv\Efildr20Pure\r
+  $(TOOLBIN_DIR)\GenPage Fv\Efildr20Pure Fv\Efildr20\r
+\r
diff --git a/DuetPkg/EfiLdr/efildr.c b/DuetPkg/EfiLdr/efildr.c
new file mode 100644 (file)
index 0000000..5cf7db6
--- /dev/null
@@ -0,0 +1,28 @@
+/*++\r
+\r
+Copyright (c) 2006, Intel Corporation                                                         \r
+All rights reserved. This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
+                                                                                          \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+\r
+Module Name:\r
+  EfiLdr.c\r
+\r
+Abstract:\r
+\r
+Revision History:\r
+\r
+--*/\r
+\r
+//\r
+// BUGBUG, include all C files\r
+//\r
+#include "EfiLoader.c"\r
+#include "PeLoader.c"\r
+#include "Support.c"\r
+#include "Debug.c"\r
+\r
diff --git a/DuetPkg/FSVariable/FSVariable.c b/DuetPkg/FSVariable/FSVariable.c
new file mode 100644 (file)
index 0000000..0413691
--- /dev/null
@@ -0,0 +1,1356 @@
+/*++\r
+\r
+Copyright (c) 2006 - 2007, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+  FSVariable.c\r
+\r
+Abstract:\r
+\r
+  Provide support functions for variable services.\r
+\r
+--*/\r
+\r
+#include "FSVariable.h"\r
+\r
+VARIABLE_STORE_HEADER mStoreHeaderTemplate = {\r
+  VARIABLE_STORE_SIGNATURE,\r
+  VOLATILE_VARIABLE_STORE_SIZE,\r
+  VARIABLE_STORE_FORMATTED,\r
+  VARIABLE_STORE_HEALTHY,\r
+  0,\r
+  0\r
+};\r
+\r
+//\r
+// Don't use module globals after the SetVirtualAddress map is signaled\r
+//\r
+VARIABLE_GLOBAL  *mGlobal;\r
+\r
+STATIC\r
+VOID\r
+EFIAPI\r
+OnVirtualAddressChange (\r
+  IN EFI_EVENT        Event,\r
+  IN VOID             *Context\r
+  );\r
+\r
+STATIC\r
+VOID\r
+EFIAPI\r
+OnSimpleFileSystemInstall (\r
+  IN EFI_EVENT        Event,\r
+  IN VOID             *Context\r
+  );\r
+\r
+STATIC\r
+BOOLEAN\r
+IsValidVariableHeader (\r
+  IN  VARIABLE_HEADER   *Variable\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This code checks if variable header is valid or not.\r
+\r
+Arguments:\r
+  Variable        Pointer to the Variable Header.\r
+\r
+Returns:\r
+  TRUE            Variable header is valid.\r
+  FALSE           Variable header is not valid.\r
+\r
+--*/\r
+{\r
+  if (Variable == NULL ||\r
+      Variable->StartId != VARIABLE_DATA ||\r
+      (sizeof (VARIABLE_HEADER) + Variable->NameSize + Variable->DataSize) > MAX_VARIABLE_SIZE\r
+      ) {\r
+    return FALSE;\r
+  }\r
+\r
+  return TRUE;\r
+}\r
+\r
+STATIC\r
+VARIABLE_STORE_STATUS\r
+GetVariableStoreStatus (\r
+  IN VARIABLE_STORE_HEADER *VarStoreHeader\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This code gets the current status of Variable Store.\r
+\r
+Arguments:\r
+\r
+  VarStoreHeader  Pointer to the Variable Store Header.\r
+\r
+Returns:\r
+\r
+  EfiRaw        Variable store status is raw\r
+  EfiValid      Variable store status is valid\r
+  EfiInvalid    Variable store status is invalid\r
+\r
+--*/\r
+{\r
+  if ((VarStoreHeader->Signature == mStoreHeaderTemplate.Signature) &&\r
+      (VarStoreHeader->Format == mStoreHeaderTemplate.Format) &&\r
+      (VarStoreHeader->State == mStoreHeaderTemplate.State)\r
+     ) {\r
+    return EfiValid;\r
+  } else if (VarStoreHeader->Signature == VAR_DEFAULT_VALUE_32 &&\r
+           VarStoreHeader->Size == VAR_DEFAULT_VALUE_32 &&\r
+           VarStoreHeader->Format == VAR_DEFAULT_VALUE &&\r
+           VarStoreHeader->State == VAR_DEFAULT_VALUE\r
+          ) {\r
+\r
+    return EfiRaw;\r
+  } else {\r
+    return EfiInvalid;\r
+  }\r
+}\r
+\r
+STATIC\r
+UINT8 *\r
+GetVariableDataPtr (\r
+  IN  VARIABLE_HEADER   *Variable\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This code gets the pointer to the variable data.\r
+\r
+Arguments:\r
+\r
+  Variable            Pointer to the Variable Header.\r
+\r
+Returns:\r
+\r
+  UINT8*              Pointer to Variable Data\r
+\r
+--*/\r
+{\r
+  //\r
+  // Be careful about pad size for alignment\r
+  //\r
+  return (UINT8 *) ((UINTN) GET_VARIABLE_NAME_PTR (Variable) + Variable->NameSize + GET_PAD_SIZE (Variable->NameSize));\r
+}\r
+\r
+STATIC\r
+VARIABLE_HEADER *\r
+GetNextVariablePtr (\r
+  IN  VARIABLE_HEADER   *Variable\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This code gets the pointer to the next variable header.\r
+\r
+Arguments:\r
+\r
+  Variable              Pointer to the Variable Header.\r
+\r
+Returns:\r
+\r
+  VARIABLE_HEADER*      Pointer to next variable header.\r
+\r
+--*/\r
+{\r
+  if (!IsValidVariableHeader (Variable)) {\r
+    return NULL;\r
+  }\r
+  //\r
+  // Be careful about pad size for alignment\r
+  //\r
+  return (VARIABLE_HEADER *) ((UINTN) GetVariableDataPtr (Variable) + Variable->DataSize + GET_PAD_SIZE (Variable->DataSize));\r
+}\r
+\r
+STATIC\r
+VARIABLE_HEADER *\r
+GetEndPointer (\r
+  IN VARIABLE_STORE_HEADER       *VarStoreHeader\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This code gets the pointer to the last variable memory pointer byte\r
+\r
+Arguments:\r
+\r
+  VarStoreHeader        Pointer to the Variable Store Header.\r
+\r
+Returns:\r
+\r
+  VARIABLE_HEADER*      Pointer to last unavailable Variable Header\r
+\r
+--*/\r
+{\r
+  //\r
+  // The end of variable store\r
+  //\r
+  return (VARIABLE_HEADER *) ((UINTN) VarStoreHeader + VarStoreHeader->Size);\r
+}\r
+\r
+BOOLEAN\r
+ExistNewerVariable (\r
+  IN  VARIABLE_HEADER         *Variable\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Check if exist newer variable when doing reclaim\r
+\r
+Arguments:\r
+\r
+  Variable                    Pointer to start position\r
+\r
+Returns:\r
+\r
+  TRUE - Exists another variable, which is newer than the current one\r
+  FALSE  - Doesn't exist another vairable which is newer than the current one\r
+\r
+--*/\r
+{\r
+  VARIABLE_HEADER       *NextVariable;\r
+  CHAR16                *VariableName;\r
+  EFI_GUID              *VendorGuid;\r
+  \r
+  VendorGuid   = &Variable->VendorGuid;\r
+  VariableName = GET_VARIABLE_NAME_PTR(Variable);\r
+  \r
+  NextVariable = GetNextVariablePtr (Variable);\r
+  while (IsValidVariableHeader (NextVariable)) {\r
+    if ((NextVariable->State == VAR_ADDED) || (NextVariable->State == (VAR_ADDED & VAR_IN_DELETED_TRANSITION))) {\r
+      //\r
+      // If match Guid and Name\r
+      //\r
+      if (CompareGuid (VendorGuid, &NextVariable->VendorGuid)) {\r
+         if (CompareMem (VariableName, GET_VARIABLE_NAME_PTR (NextVariable), StrSize (VariableName)) == 0) {\r
+           return TRUE;\r
+         }\r
+       }\r
+    }\r
+    NextVariable = GetNextVariablePtr (NextVariable);\r
+  }\r
+  return FALSE;\r
+}\r
+\r
+STATIC\r
+EFI_STATUS\r
+Reclaim (\r
+  IN  VARIABLE_STORAGE_TYPE StorageType,\r
+  IN  VARIABLE_HEADER       *CurrentVariable OPTIONAL\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Variable store garbage collection and reclaim operation\r
+\r
+Arguments:\r
+\r
+  IsVolatile                  The variable store is volatile or not,\r
+                              if it is non-volatile, need FTW\r
+  CurrentVairable             If it is not NULL, it means not to process\r
+                              current variable for Reclaim.\r
+\r
+Returns:\r
+\r
+  EFI STATUS\r
+\r
+--*/\r
+{\r
+  VARIABLE_HEADER       *Variable;\r
+  VARIABLE_HEADER       *NextVariable;\r
+  VARIABLE_STORE_HEADER *VariableStoreHeader;\r
+  UINT8                 *ValidBuffer;\r
+  UINTN                 ValidBufferSize;\r
+  UINTN                 VariableSize;\r
+  UINT8                 *CurrPtr;\r
+  EFI_STATUS            Status;\r
+\r
+  VariableStoreHeader = (VARIABLE_STORE_HEADER *) mGlobal->VariableBase[StorageType];\r
+\r
+  //\r
+  // Start Pointers for the variable.\r
+  //\r
+  Variable        = (VARIABLE_HEADER *) (VariableStoreHeader + 1);\r
+\r
+  \r
+  //\r
+  // To make the reclaim, here we just allocate a memory that equal to the original memory\r
+  //\r
+  ValidBufferSize = sizeof (VARIABLE_STORE_HEADER) + VariableStoreHeader->Size;\r
+\r
+  Status = gBS->AllocatePool (\r
+                  EfiBootServicesData,\r
+                  ValidBufferSize,\r
+                  &ValidBuffer\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  CurrPtr = ValidBuffer;\r
+\r
+  //\r
+  // Copy variable store header\r
+  //\r
+  CopyMem (CurrPtr, VariableStoreHeader, sizeof (VARIABLE_STORE_HEADER));\r
+  CurrPtr += sizeof (VARIABLE_STORE_HEADER);\r
+\r
+  //\r
+  // Start Pointers for the variable.\r
+  //\r
+  Variable = (VARIABLE_HEADER *) (VariableStoreHeader + 1);\r
+\r
+  \r
+  ValidBufferSize = sizeof (VARIABLE_STORE_HEADER);\r
+  while (IsValidVariableHeader (Variable)) {\r
+    NextVariable = GetNextVariablePtr (Variable);\r
+    //\r
+    // State VAR_ADDED or VAR_IN_DELETED_TRANSITION are to kept,\r
+    // The CurrentVariable, is also saved, as SetVariable may fail due to lack of space\r
+    //\r
+    if (Variable->State == VAR_ADDED) {\r
+      VariableSize = (UINTN) NextVariable - (UINTN) Variable;\r
+      CopyMem (CurrPtr, (UINT8 *) Variable, VariableSize);\r
+      ValidBufferSize += VariableSize;\r
+      CurrPtr += VariableSize;\r
+    } else if (Variable->State == (VAR_ADDED & VAR_IN_DELETED_TRANSITION)) {\r
+      //\r
+      // As variables that with the same guid and name may exist in NV due to power failure during SetVariable,\r
+      // we will only save the latest valid one\r
+      //\r
+      if (!ExistNewerVariable(Variable)) {\r
+        VariableSize = (UINTN) NextVariable - (UINTN) Variable;\r
+        CopyMem (CurrPtr, (UINT8 *) Variable, VariableSize);\r
+        //\r
+        // If CurrentVariable == Variable, mark as VAR_IN_DELETED_TRANSITION\r
+        //\r
+        if (Variable != CurrentVariable){\r
+          ((VARIABLE_HEADER *)CurrPtr)->State = VAR_ADDED;\r
+        }\r
+        CurrPtr += VariableSize;\r
+        ValidBufferSize += VariableSize;\r
+      }\r
+    }\r
+    Variable = NextVariable;\r
+  }\r
+\r
+  //\r
+  // TODO: cannot restore to original state, basic FTW needed\r
+  //\r
+  Status = mGlobal->VariableStore[StorageType]->Erase (\r
+                                                  mGlobal->VariableStore[StorageType]\r
+                                                  );\r
+  Status = mGlobal->VariableStore[StorageType]->Write (\r
+                                                    mGlobal->VariableStore[StorageType],\r
+                                                    0,\r
+                                                    ValidBufferSize,\r
+                                                    ValidBuffer\r
+                                                    );\r
+\r
+  // ASSERT_EFI_ERROR (Status);\r
+\r
+  mGlobal->LastVariableOffset[StorageType] = ValidBufferSize;\r
+  gBS->FreePool (ValidBuffer);\r
+\r
+  return Status;\r
+}\r
+\r
+STATIC\r
+EFI_STATUS\r
+FindVariable (\r
+  IN  CHAR16                  *VariableName,\r
+  IN  EFI_GUID                *VendorGuid,\r
+  OUT VARIABLE_POINTER_TRACK  *PtrTrack\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This code finds variable in storage blocks (Volatile or Non-Volatile)\r
+\r
+Arguments:\r
+\r
+  VariableName                Name of the variable to be found\r
+  VendorGuid                  Vendor GUID to be found.\r
+  PtrTrack                    Variable Track Pointer structure that contains\r
+                              Variable Information.\r
+                              Contains the pointer of Variable header.\r
+\r
+Returns:\r
+\r
+  EFI_INVALID_PARAMETER       - Invalid parameter\r
+  EFI_SUCCESS                 - Find the specified variable\r
+  EFI_NOT_FOUND               - Not found\r
+\r
+--*/\r
+{\r
+  VARIABLE_HEADER         *Variable;\r
+  VARIABLE_STORE_HEADER   *VariableStoreHeader;\r
+  UINTN                   Index;\r
+  VARIABLE_HEADER         *InDeleteVariable;\r
+  UINTN                   InDeleteIndex;\r
+  VARIABLE_HEADER         *InDeleteStartPtr;\r
+  VARIABLE_HEADER         *InDeleteEndPtr;\r
+\r
+  if (VariableName[0] != 0 && VendorGuid == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  InDeleteVariable = NULL;\r
+  InDeleteIndex    = (UINTN)-1;\r
+  InDeleteStartPtr = NULL;\r
+  InDeleteEndPtr   = NULL;\r
+\r
+  for (Index = 0; Index < MaxType; Index ++) {\r
+    //\r
+    // 0: Non-Volatile, 1: Volatile\r
+    //\r
+    VariableStoreHeader = (VARIABLE_STORE_HEADER *) mGlobal->VariableBase[Index];\r
+\r
+    //\r
+    // Start Pointers for the variable.\r
+    // Actual Data Pointer where data can be written.\r
+    //\r
+    Variable = (VARIABLE_HEADER *) (VariableStoreHeader + 1);\r
+\r
+    //\r
+    // Find the variable by walk through non-volatile and volatile variable store\r
+    //\r
+    PtrTrack->StartPtr = Variable;\r
+    PtrTrack->EndPtr   = GetEndPointer (VariableStoreHeader);\r
+\r
+    while (IsValidVariableHeader (Variable) && (Variable < PtrTrack->EndPtr)) {\r
+      if (Variable->State == VAR_ADDED) {\r
+        if (!EfiAtRuntime () || (Variable->Attributes & EFI_VARIABLE_RUNTIME_ACCESS)) {\r
+          if (VariableName[0] == 0) {\r
+            PtrTrack->CurrPtr = Variable;\r
+            PtrTrack->Type    = (VARIABLE_STORAGE_TYPE) Index;\r
+            return EFI_SUCCESS;\r
+          } else {\r
+            if (CompareGuid (VendorGuid, &Variable->VendorGuid)) {\r
+              if (!CompareMem (VariableName, GET_VARIABLE_NAME_PTR (Variable), StrSize (VariableName))) {\r
+                PtrTrack->CurrPtr = Variable;\r
+                PtrTrack->Type    = (VARIABLE_STORAGE_TYPE) Index;\r
+                return EFI_SUCCESS;\r
+              }\r
+            }\r
+          }\r
+        }\r
+      } else if (Variable->State == (VAR_ADDED & VAR_IN_DELETED_TRANSITION)) {\r
+        //\r
+        // VAR_IN_DELETED_TRANSITION should also be checked.\r
+        //\r
+        if (!EfiAtRuntime () || (Variable->Attributes & EFI_VARIABLE_RUNTIME_ACCESS)) {\r
+          if (VariableName[0] == 0) {\r
+            InDeleteVariable = Variable;\r
+            InDeleteIndex    = Index;\r
+            InDeleteStartPtr = PtrTrack->StartPtr;\r
+            InDeleteEndPtr   = PtrTrack->EndPtr;\r
+          } else {\r
+            if (CompareGuid (VendorGuid, &Variable->VendorGuid)) {\r
+              if (!CompareMem (VariableName, GET_VARIABLE_NAME_PTR (Variable), StrSize (VariableName))) {\r
+                InDeleteVariable = Variable;\r
+                InDeleteIndex    = Index;\r
+                InDeleteStartPtr = PtrTrack->StartPtr;\r
+                InDeleteEndPtr   = PtrTrack->EndPtr;\r
+              }\r
+            }\r
+          }\r
+        }\r
+      }\r
+\r
+      Variable = GetNextVariablePtr (Variable);\r
+    }\r
+    //\r
+    // While (...)\r
+    //\r
+  }\r
+  //\r
+  // for (...)\r
+  //\r
+\r
+  //\r
+  // if VAR_IN_DELETED_TRANSITION found, and VAR_ADDED not found,\r
+  // we return it.\r
+  //\r
+  if (InDeleteVariable != NULL) {\r
+    PtrTrack->CurrPtr  = InDeleteVariable;\r
+    PtrTrack->Type     = (VARIABLE_STORAGE_TYPE) InDeleteIndex;\r
+    PtrTrack->StartPtr = InDeleteStartPtr;\r
+    PtrTrack->EndPtr   = InDeleteEndPtr;\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  PtrTrack->CurrPtr = NULL;\r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+GetVariable (\r
+  IN      CHAR16            *VariableName,\r
+  IN      EFI_GUID          *VendorGuid,\r
+  OUT     UINT32            *Attributes OPTIONAL,\r
+  IN OUT  UINTN             *DataSize,\r
+  OUT     VOID              *Data\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This code finds variable in storage blocks (Volatile or Non-Volatile)\r
+\r
+Arguments:\r
+\r
+  VariableName                    Name of Variable to be found\r
+  VendorGuid                      Variable vendor GUID\r
+  Attributes OPTIONAL             Attribute value of the variable found\r
+  DataSize                        Size of Data found. If size is less than the\r
+                                  data, this value contains the required size.\r
+  Data                            Data pointer\r
+\r
+Returns:\r
+\r
+  EFI STATUS\r
+\r
+--*/\r
+{\r
+  VARIABLE_POINTER_TRACK  Variable;\r
+  UINTN                   VarDataSize;\r
+  EFI_STATUS              Status;\r
+\r
+  if (VariableName == NULL || VendorGuid == NULL || DataSize == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // Find existing variable\r
+  //\r
+  Status = FindVariable (VariableName, VendorGuid, &Variable);\r
+\r
+  if (Variable.CurrPtr == NULL || EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  //\r
+  // Get data size\r
+  //\r
+  VarDataSize = Variable.CurrPtr->DataSize;\r
+  if (*DataSize >= VarDataSize) {\r
+    if (Data == NULL) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+    CopyMem (Data, GetVariableDataPtr (Variable.CurrPtr), VarDataSize);\r
+\r
+    if (Attributes != NULL) {\r
+      *Attributes = Variable.CurrPtr->Attributes;\r
+    }\r
+\r
+    *DataSize = VarDataSize;\r
+\r
+    return EFI_SUCCESS;\r
+  } else {\r
+    *DataSize = VarDataSize;\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  }\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+GetNextVariableName (\r
+  IN OUT  UINTN             *VariableNameSize,\r
+  IN OUT  CHAR16            *VariableName,\r
+  IN OUT  EFI_GUID          *VendorGuid\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This code Finds the Next available variable\r
+\r
+Arguments:\r
+\r
+  VariableNameSize            Size of the variable\r
+  VariableName                Pointer to variable name\r
+  VendorGuid                  Variable Vendor Guid\r
+\r
+Returns:\r
+\r
+  EFI STATUS\r
+\r
+--*/\r
+{\r
+  VARIABLE_POINTER_TRACK  Variable;\r
+  UINTN                   VarNameSize;\r
+  EFI_STATUS              Status;\r
+\r
+  if (VariableNameSize == NULL || VariableName == NULL || VendorGuid == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Status = FindVariable (VariableName, VendorGuid, &Variable);\r
+\r
+  if (Variable.CurrPtr == NULL || EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  if (VariableName[0] != 0) {\r
+    //\r
+    // If variable name is not NULL, get next variable\r
+    //\r
+    Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);\r
+  }\r
+\r
+  while (TRUE) {\r
+    //\r
+    // The order we find variable is: 1). NonVolatile; 2). Volatile\r
+    // If both volatile and non-volatile variable store are parsed,\r
+    // return not found\r
+    //\r
+    if (Variable.CurrPtr >= Variable.EndPtr || Variable.CurrPtr == NULL) {\r
+      if (Variable.Type == Volatile) {\r
+        //\r
+        // Since we met the end of Volatile storage, we have parsed all the stores.\r
+        //\r
+        return EFI_NOT_FOUND;\r
+      }\r
+\r
+      //\r
+      // End of NonVolatile, continue to parse Volatile\r
+      //\r
+      Variable.Type = Volatile;\r
+      Variable.StartPtr = (VARIABLE_HEADER *) ((VARIABLE_STORE_HEADER *) mGlobal->VariableBase[Volatile] + 1);\r
+      Variable.EndPtr   = (VARIABLE_HEADER *) GetEndPointer ((VARIABLE_STORE_HEADER *) mGlobal->VariableBase[Volatile]);\r
+\r
+      Variable.CurrPtr = Variable.StartPtr;\r
+      if (!IsValidVariableHeader (Variable.CurrPtr)) {\r
+        continue;\r
+      }\r
+    }\r
+    //\r
+    // Variable is found\r
+    //\r
+    if (IsValidVariableHeader (Variable.CurrPtr) &&\r
+        ((Variable.CurrPtr->State == VAR_ADDED) ||\r
+         (Variable.CurrPtr->State == (VAR_ADDED & VAR_IN_DELETED_TRANSITION)))) {\r
+      if (!EfiAtRuntime () || (Variable.CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS)) {\r
+        VarNameSize = Variable.CurrPtr->NameSize;\r
+        if (VarNameSize <= *VariableNameSize) {\r
+          CopyMem (\r
+            VariableName,\r
+            GET_VARIABLE_NAME_PTR (Variable.CurrPtr),\r
+            VarNameSize\r
+            );\r
+          CopyMem (\r
+            VendorGuid,\r
+            &Variable.CurrPtr->VendorGuid,\r
+            sizeof (EFI_GUID)\r
+            );\r
+          Status = EFI_SUCCESS;\r
+        } else {\r
+          Status = EFI_BUFFER_TOO_SMALL;\r
+        }\r
+\r
+        *VariableNameSize = VarNameSize;\r
+        return Status;\r
+      }\r
+    }\r
+\r
+    Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);\r
+  }\r
+\r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+SetVariable (\r
+  IN CHAR16                  *VariableName,\r
+  IN EFI_GUID                *VendorGuid,\r
+  IN UINT32                  Attributes,\r
+  IN UINTN                   DataSize,\r
+  IN VOID                    *Data\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This code sets variable in storage blocks (Volatile or Non-Volatile)\r
+\r
+Arguments:\r
+\r
+  VariableName                    Name of Variable to be found\r
+  VendorGuid                      Variable vendor GUID\r
+  Attributes                      Attribute value of the variable found\r
+  DataSize                        Size of Data found. If size is less than the\r
+                                  data, this value contains the required size.\r
+  Data                            Data pointer\r
+\r
+Returns:\r
+  \r
+  EFI_INVALID_PARAMETER           - Invalid parameter\r
+  EFI_SUCCESS                     - Set successfully\r
+  EFI_OUT_OF_RESOURCES            - Resource not enough to set variable\r
+  EFI_NOT_FOUND                   - Not found\r
+  EFI_DEVICE_ERROR                - Variable can not be saved due to hardware failure\r
+  EFI_WRITE_PROTECTED             - Variable is read-only\r
+\r
+--*/\r
+{\r
+  VARIABLE_POINTER_TRACK  Variable;\r
+  EFI_STATUS              Status;\r
+  VARIABLE_HEADER         *NextVariable;\r
+  UINTN                   VarNameSize;\r
+  UINTN                   VarNameOffset;\r
+  UINTN                   VarDataOffset;\r
+  UINTN                   VarSize;\r
+  UINT8                   State;\r
+  BOOLEAN                 Reclaimed;\r
+  VARIABLE_STORAGE_TYPE   StorageType;\r
+\r
+  Reclaimed = FALSE;\r
+  \r
+  //\r
+  // Check input parameters\r
+  // \r
+\r
+  if (VariableName == NULL || VariableName[0] == 0 || VendorGuid == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  \r
+  //\r
+  //  Make sure if runtime bit is set, boot service bit is set also\r
+  //\r
+  if ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == EFI_VARIABLE_RUNTIME_ACCESS) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  \r
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)\r
+  //\r
+  //  The size of the VariableName, including the Unicode Null in bytes plus\r
+  //  the DataSize is limited to maximum size of MAX_HARDWARE_ERROR_VARIABLE_SIZE (32K)\r
+  //  bytes for HwErrRec, and MAX_VARIABLE_SIZE (1024) bytes for the others.\r
+  //\r
+  if ((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) {\r
+    if ((DataSize > MAX_HARDWARE_ERROR_VARIABLE_SIZE) ||                                                       \r
+        (sizeof (VARIABLE_HEADER) + StrSize (VariableName) + DataSize > MAX_HARDWARE_ERROR_VARIABLE_SIZE)) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }    \r
+  } else {\r
+    if ((DataSize > MAX_VARIABLE_SIZE) ||\r
+        (sizeof (VARIABLE_HEADER) + StrSize (VariableName) + DataSize > MAX_VARIABLE_SIZE)) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }  \r
+  }  \r
+#else  \r
+  //\r
+  //  The size of the VariableName, including the Unicode Null in bytes plus\r
+  //  the DataSize is limited to maximum size of MAX_VARIABLE_SIZE (1024) bytes.\r
+  //\r
+  if ((DataSize > MAX_VARIABLE_SIZE) ||\r
+      (sizeof (VARIABLE_HEADER) + StrSize (VariableName) + DataSize > MAX_VARIABLE_SIZE)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }  \r
+#endif\r
+  //\r
+  // Check whether the input variable is already existed\r
+  //\r
+\r
+  Status = FindVariable (VariableName, VendorGuid, &Variable);\r
+\r
+  if (Status == EFI_SUCCESS && Variable.CurrPtr != NULL) {  \r
+    //\r
+    // Update/Delete existing variable\r
+    //\r
+    \r
+    if (EfiAtRuntime ()) {              \r
+      //\r
+      // If EfiAtRuntime and the variable is Volatile and Runtime Access,  \r
+      // the volatile is ReadOnly, and SetVariable should be aborted and \r
+      // return EFI_WRITE_PROTECTED.\r
+      //\r
+      if (Variable.Type == Volatile) {\r
+        return EFI_WRITE_PROTECTED;\r
+      }\r
+      //\r
+      // Only variable have NV attribute can be updated/deleted in Runtime\r
+      //\r
+      if (!(Variable.CurrPtr->Attributes & EFI_VARIABLE_NON_VOLATILE)) {\r
+        return EFI_INVALID_PARAMETER;      \r
+      }\r
+    }\r
+    \r
+    //\r
+    // Setting a data variable with no access, or zero DataSize attributes\r
+    // specified causes it to be deleted.\r
+    //\r
+    if (DataSize == 0 || (Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == 0) {\r
+      //\r
+      // Found this variable in storage\r
+      //\r
+      State = Variable.CurrPtr->State;\r
+      State &= VAR_DELETED;\r
+\r
+      Status = mGlobal->VariableStore[Variable.Type]->Write (\r
+                                                        mGlobal->VariableStore[Variable.Type],\r
+                                                        VARIABLE_MEMBER_OFFSET (State, (UINTN) Variable.CurrPtr - (UINTN) Variable.StartPtr),\r
+                                                        sizeof (Variable.CurrPtr->State),\r
+                                                        &State\r
+                                                        );\r
+      //\r
+      // NOTE: Write operation at least can write data to memory cache\r
+      //       Discard file writing failure here.\r
+      //\r
+      return EFI_SUCCESS;\r
+    }\r
+    \r
+    //\r
+    // Found this variable in storage\r
+    // If the variable is marked valid and the same data has been passed in\r
+    // then return to the caller immediately.\r
+    //\r
+    if ((Variable.CurrPtr->DataSize == DataSize) &&\r
+        (CompareMem (Data, GetVariableDataPtr (Variable.CurrPtr), DataSize) == 0)\r
+          ) {\r
+      return EFI_SUCCESS;\r
+    } else if ((Variable.CurrPtr->State == VAR_ADDED) ||\r
+               (Variable.CurrPtr->State == (VAR_ADDED & VAR_IN_DELETED_TRANSITION))) {\r
+      //\r
+      // Mark the old variable as in delete transition\r
+      //\r
+      State = Variable.CurrPtr->State;\r
+      State &= VAR_IN_DELETED_TRANSITION;\r
+\r
+      Status = mGlobal->VariableStore[Variable.Type]->Write (\r
+                                                        mGlobal->VariableStore[Variable.Type],\r
+                                                        VARIABLE_MEMBER_OFFSET (State, (UINTN) Variable.CurrPtr - (UINTN) Variable.StartPtr),\r
+                                                        sizeof (Variable.CurrPtr->State),\r
+                                                        &State\r
+                                                        );\r
+      //\r
+      // NOTE: Write operation at least can write data to memory cache\r
+      //       Discard file writing failure here.\r
+      //\r
+    }\r
+  } else if (Status == EFI_NOT_FOUND) {\r
+    //\r
+    // Create a new variable\r
+    //  \r
+    \r
+    //\r
+    // Make sure we are trying to create a new variable.\r
+    // Setting a data variable with no access, or zero DataSize attributes means to delete it.    \r
+    //\r
+    if (DataSize == 0 || (Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == 0) {\r
+      return EFI_NOT_FOUND;\r
+    }    \r
+    //\r
+    // Only variable have NV|RT attribute can be created in Runtime\r
+    //\r
+    if (EfiAtRuntime () &&\r
+        (!(Attributes & EFI_VARIABLE_RUNTIME_ACCESS) || !(Attributes & EFI_VARIABLE_NON_VOLATILE))) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }        \r
+    \r
+  } else {\r
+    //\r
+    // Status should be EFI_INVALID_PARAMETER here according to return status of FindVariable().\r
+    //\r
+    return Status;\r
+  } \r
+\r
+  //\r
+  // Function part - create a new variable and copy the data.\r
+  // Both update a variable and create a variable will come here.  \r
+  // We can firstly write all the data in memory, then write them to file\r
+  // This can reduce the times of write operation\r
+  //\r
+  \r
+  NextVariable = (VARIABLE_HEADER *) mGlobal->Scratch;\r
+\r
+  NextVariable->StartId     = VARIABLE_DATA;\r
+  NextVariable->Attributes  = Attributes;\r
+  NextVariable->State       = VAR_ADDED;\r
+  NextVariable->Reserved    = 0;\r
+  VarNameOffset             = sizeof (VARIABLE_HEADER);\r
+  VarNameSize               = StrSize (VariableName);\r
+  CopyMem (\r
+    (UINT8 *) ((UINTN) NextVariable + VarNameOffset),\r
+    VariableName,\r
+    VarNameSize\r
+    );\r
+  VarDataOffset = VarNameOffset + VarNameSize + GET_PAD_SIZE (VarNameSize);\r
+  CopyMem (\r
+    (UINT8 *) ((UINTN) NextVariable + VarDataOffset),\r
+    Data,\r
+    DataSize\r
+    );\r
+  CopyMem (&NextVariable->VendorGuid, VendorGuid, sizeof (EFI_GUID));\r
+  //\r
+  // There will be pad bytes after Data, the NextVariable->NameSize and\r
+  // NextVariable->DataSize should not include pad size so that variable\r
+  // service can get actual size in GetVariable\r
+  //\r
+  NextVariable->NameSize  = (UINT32)VarNameSize;\r
+  NextVariable->DataSize  = (UINT32)DataSize;\r
+\r
+  //\r
+  // The actual size of the variable that stores in storage should\r
+  // include pad size.\r
+  // VarDataOffset: offset from begin of current variable header\r
+  //\r
+  VarSize = VarDataOffset + DataSize + GET_PAD_SIZE (DataSize);\r
+\r
+  StorageType = (Attributes & EFI_VARIABLE_NON_VOLATILE) ? NonVolatile : Volatile;\r
+\r
+  if ((UINT32) (VarSize + mGlobal->LastVariableOffset[StorageType]) >\r
+      ((VARIABLE_STORE_HEADER *) mGlobal->VariableBase[StorageType])->Size\r
+      ) {\r
+    if ((StorageType == NonVolatile) && EfiAtRuntime ()) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    //\r
+    // Perform garbage collection & reclaim operation\r
+    //\r
+    Status = Reclaim (StorageType, Variable.CurrPtr);\r
+    if (EFI_ERROR (Status)) {\r
+      //\r
+      // Reclaim error\r
+      // we cannot restore to original state, fetal error, report to user\r
+      //\r
+      DEBUG ((EFI_D_ERROR, "FSVariable: Recalim error (fetal error) - %r\n", Status));\r
+      return Status;\r
+    }\r
+    //\r
+    // If still no enough space, return out of resources\r
+    //\r
+    if ((UINT32) (VarSize + mGlobal->LastVariableOffset[StorageType]) >\r
+        ((VARIABLE_STORE_HEADER *) mGlobal->VariableBase[StorageType])->Size\r
+       ) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    Reclaimed = TRUE;\r
+  }\r
+  Status = mGlobal->VariableStore[StorageType]->Write (\r
+                                                  mGlobal->VariableStore[StorageType],\r
+                                                  mGlobal->LastVariableOffset[StorageType],\r
+                                                  VarSize,\r
+                                                  NextVariable\r
+                                                  );\r
+  //\r
+  // NOTE: Write operation at least can write data to memory cache\r
+  //       Discard file writing failure here.\r
+  //\r
+  mGlobal->LastVariableOffset[StorageType] += VarSize;\r
+\r
+  //\r
+  // Mark the old variable as deleted\r
+  //\r
+  if (!Reclaimed && !EFI_ERROR (Status) && Variable.CurrPtr != NULL) {\r
+    State = Variable.CurrPtr->State;\r
+    State &= VAR_DELETED;\r
+\r
+    Status = mGlobal->VariableStore[StorageType]->Write (\r
+                                                    mGlobal->VariableStore[StorageType],\r
+                                                    VARIABLE_MEMBER_OFFSET (State, (UINTN) Variable.CurrPtr - (UINTN) Variable.StartPtr),\r
+                                                    sizeof (Variable.CurrPtr->State),\r
+                                                    &State\r
+                                                    );\r
+    //\r
+    // NOTE: Write operation at least can write data to memory cache\r
+    //       Discard file writing failure here.\r
+    //\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+#if (EFI_SPECIFICATION_VERSION >= 0x00020000)\r
+EFI_STATUS\r
+EFIAPI\r
+QueryVariableInfo (\r
+  IN  UINT32                 Attributes,\r
+  OUT UINT64                 *MaximumVariableStorageSize,\r
+  OUT UINT64                 *RemainingVariableStorageSize,\r
+  OUT UINT64                 *MaximumVariableSize\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This code returns information about the EFI variables.\r
+\r
+Arguments:\r
+\r
+  Attributes                      Attributes bitmask to specify the type of variables\r
+                                  on which to return information.\r
+  MaximumVariableStorageSize      Pointer to the maximum size of the storage space available\r
+                                  for the EFI variables associated with the attributes specified.\r
+  RemainingVariableStorageSize    Pointer to the remaining size of the storage space available\r
+                                  for the EFI variables associated with the attributes specified.\r
+  MaximumVariableSize             Pointer to the maximum size of the individual EFI variables\r
+                                  associated with the attributes specified.\r
+\r
+Returns:\r
+\r
+  EFI STATUS\r
+  EFI_INVALID_PARAMETER           - An invalid combination of attribute bits was supplied.\r
+  EFI_SUCCESS                     - Query successfully.\r
+  EFI_UNSUPPORTED                 - The attribute is not supported on this platform.\r
+\r
+--*/\r
+{\r
+  VARIABLE_HEADER        *Variable;\r
+  VARIABLE_HEADER        *NextVariable;\r
+  UINT64                 VariableSize;\r
+  VARIABLE_STORE_HEADER  *VariableStoreHeader;\r
+\r
+  if(MaximumVariableStorageSize == NULL || RemainingVariableStorageSize == NULL || MaximumVariableSize == NULL || Attributes == 0) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  \r
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)  \r
+  if((Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) == 0) {\r
+    //\r
+    // Make sure the Attributes combination is supported by the platform.\r
+    //\r
+    return EFI_UNSUPPORTED;  \r
+  }  \r
+#else\r
+  if((Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS)) == 0) {\r
+    //\r
+    // Make sure the Attributes combination is supported by the platform.\r
+    //\r
+    return EFI_UNSUPPORTED;  \r
+  } \r
+#endif  \r
+  else if ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == EFI_VARIABLE_RUNTIME_ACCESS) {\r
+    //\r
+    // Make sure if runtime bit is set, boot service bit is set also.\r
+    //\r
+    return EFI_INVALID_PARAMETER;\r
+  } else if (EfiAtRuntime () && !(Attributes & EFI_VARIABLE_RUNTIME_ACCESS)) {\r
+    //\r
+    // Make sure RT Attribute is set if we are in Runtime phase.\r
+    //\r
+    return EFI_INVALID_PARAMETER;\r
+  } \r
+  \r
+  VariableStoreHeader = (VARIABLE_STORE_HEADER *) mGlobal->VariableBase[\r
+                                (Attributes & EFI_VARIABLE_NON_VOLATILE) ? NonVolatile : Volatile\r
+                                ];\r
+  //\r
+  // Now let's fill *MaximumVariableStorageSize *RemainingVariableStorageSize\r
+  // with the storage size (excluding the storage header size).\r
+  //\r
+  *MaximumVariableStorageSize   = VariableStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER);\r
+  *RemainingVariableStorageSize = VariableStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER);\r
+\r
+  //\r
+  // Let *MaximumVariableSize be MAX_VARIABLE_SIZE with the exception of the variable header size.\r
+  //\r
+  *MaximumVariableSize = MAX_VARIABLE_SIZE - sizeof (VARIABLE_HEADER);\r
+\r
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)\r
+  //\r
+  // Harware error record variable needs larger size.\r
+  //\r
+  if ((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) {\r
+    *MaximumVariableSize = MAX_HARDWARE_ERROR_VARIABLE_SIZE - sizeof (VARIABLE_HEADER);\r
+  }\r
+#endif\r
+  \r
+  //\r
+  // Point to the starting address of the variables.\r
+  //\r
+  Variable = (VARIABLE_HEADER *) (VariableStoreHeader + 1);\r
+\r
+  //\r
+  // Now walk through the related variable store.\r
+  //\r
+  while (IsValidVariableHeader (Variable) && (Variable < GetEndPointer (VariableStoreHeader))) {\r
+    NextVariable = GetNextVariablePtr (Variable);\r
+    VariableSize = (UINT64) (UINTN) NextVariable - (UINT64) (UINTN) Variable;\r
+\r
+    if (EfiAtRuntime ()) {\r
+      //\r
+      // we don't take the state of the variables in mind\r
+      // when calculating RemainingVariableStorageSize,\r
+      // since the space occupied by variables not marked with\r
+      // VAR_ADDED is not allowed to be reclaimed in Runtime.\r
+      //\r
+      *RemainingVariableStorageSize -= VariableSize;\r
+    } else {\r
+      //\r
+      // Only care about Variables with State VAR_ADDED,because\r
+      // the space not marked as VAR_ADDED is reclaimable now.\r
+      //\r
+      if ((Variable->State == VAR_ADDED) ||\r
+          (Variable->State == (VAR_ADDED & VAR_IN_DELETED_TRANSITION))) {\r
+        *RemainingVariableStorageSize -= VariableSize;\r
+      }\r
+    }\r
+\r
+    //\r
+    // Go to the next one\r
+    //\r
+    Variable = NextVariable;\r
+  }\r
+  \r
+  if (*RemainingVariableStorageSize < sizeof (VARIABLE_HEADER)) {\r
+    *MaximumVariableSize = 0;\r
+  } else if ((*RemainingVariableStorageSize - sizeof (VARIABLE_HEADER)) < *MaximumVariableSize) {\r
+    *MaximumVariableSize = *RemainingVariableStorageSize - sizeof (VARIABLE_HEADER);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+#endif\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+VariableServiceInitialize (\r
+  IN EFI_HANDLE         ImageHandle,\r
+  IN EFI_SYSTEM_TABLE   *SystemTable\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  This function does initialization for variable services\r
+\r
+Arguments:\r
+\r
+  ImageHandle   - The firmware allocated handle for the EFI image.\r
+  SystemTable   - A pointer to the EFI System Table.\r
+\r
+Returns:\r
+\r
+  Status code.\r
+\r
+  EFI_NOT_FOUND     - Variable store area not found.\r
+  EFI_SUCCESS       - Variable services successfully initialized.\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                      Status;\r
+  EFI_HANDLE                      NewHandle;\r
+  VS_DEV                          *Dev;\r
+  VOID                            *HobList;\r
+  VARIABLE_HEADER                 *NextVariable;\r
+  VARIABLE_STORE_HEADER           *VariableStoreHeader;\r
+  EFI_FLASH_MAP_FS_ENTRY_DATA     *FlashMapEntryData;\r
+  EFI_FLASH_SUBAREA_ENTRY         VariableStoreEntry;\r
+  VOID                            *Buffer;\r
+  UINT64                          BaseAddress;\r
+  UINT64                          Length;\r
+  EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor;\r
+\r
+  Status = gBS->AllocatePool (\r
+                  EfiRuntimeServicesData,\r
+                  (UINTN) sizeof (VARIABLE_GLOBAL),\r
+                  &mGlobal\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = EfiGetSystemConfigurationTable (&gEfiHobListGuid, &HobList);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  \r
+  for (FlashMapEntryData = NULL; ;) {\r
+    Buffer = GetNextGuidHob (&gEfiFlashMapHobGuid, &HobList);\r
+\r
+    FlashMapEntryData = (EFI_FLASH_MAP_FS_ENTRY_DATA *) Buffer;\r
+\r
+    //\r
+    // Get the variable store area\r
+    //\r
+    if (FlashMapEntryData->AreaType == EFI_FLASH_AREA_EFI_VARIABLES) {\r
+      break;\r
+    }\r
+  }\r
+\r
+  if (EFI_ERROR (Status) || FlashMapEntryData == NULL) {\r
+    Status = EFI_NOT_FOUND;\r
+    return Status;\r
+  }\r
+\r
+  VariableStoreEntry = FlashMapEntryData->Entries[0];\r
+\r
+  //\r
+  // Mark the variable storage region of the FLASH as RUNTIME\r
+  //\r
+  BaseAddress = VariableStoreEntry.Base & (~EFI_PAGE_MASK);\r
+  Length      = VariableStoreEntry.Length + (VariableStoreEntry.Base - BaseAddress);\r
+  Length      = (Length + EFI_PAGE_SIZE - 1) & (~EFI_PAGE_MASK);\r
+  Status      = gDS->GetMemorySpaceDescriptor (BaseAddress, &GcdDescriptor);\r
+  if (EFI_ERROR (Status)) {\r
+    Status = EFI_UNSUPPORTED;\r
+    return Status;\r
+  }\r
+  Status = gDS->SetMemorySpaceAttributes (\r
+                  BaseAddress,\r
+                  Length,\r
+                  GcdDescriptor.Attributes | EFI_MEMORY_RUNTIME\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    Status = EFI_UNSUPPORTED;\r
+    return Status;\r
+  }\r
+  \r
+  Status = FileStorageConstructor (\r
+             &mGlobal->VariableStore[NonVolatile], \r
+             &mGlobal->GoVirtualChildEvent[NonVolatile],\r
+             VariableStoreEntry.Base,\r
+             (UINT32) VariableStoreEntry.Length,\r
+             FlashMapEntryData->VolumeId,\r
+             FlashMapEntryData->FilePath\r
+             );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Volatile Storage\r
+  //\r
+  Status = MemStorageConstructor (\r
+             &mGlobal->VariableStore[Volatile],\r
+             &mGlobal->GoVirtualChildEvent[Volatile],\r
+             VOLATILE_VARIABLE_STORE_SIZE\r
+             );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Scratch\r
+  //\r
+  Status = gBS->AllocatePool (\r
+                  EfiRuntimeServicesData,\r
+                  VARIABLE_SCRATCH_SIZE,\r
+                  &mGlobal->Scratch\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // 1. NV Storage\r
+  //\r
+  Dev = DEV_FROM_THIS (mGlobal->VariableStore[NonVolatile]);\r
+  VariableStoreHeader = (VARIABLE_STORE_HEADER *) VAR_DATA_PTR (Dev);\r
+  if (GetVariableStoreStatus (VariableStoreHeader) == EfiValid) {\r
+    if (~VariableStoreHeader->Size == 0) {\r
+      VariableStoreHeader->Size = (UINT32) VariableStoreEntry.Length;\r
+    }\r
+  }\r
+  //\r
+  // Calculate LastVariableOffset\r
+  //\r
+  NextVariable = (VARIABLE_HEADER *) (VariableStoreHeader + 1);\r
+  while (IsValidVariableHeader (NextVariable)) {\r
+    NextVariable = GetNextVariablePtr (NextVariable);\r
+  }\r
+  mGlobal->LastVariableOffset[NonVolatile] = (UINTN) NextVariable - (UINTN) VariableStoreHeader;\r
+  mGlobal->VariableBase[NonVolatile] = VariableStoreHeader;\r
+\r
+  //\r
+  // Reclaim if remaining space is too small\r
+  //\r
+  if ((VariableStoreHeader->Size - mGlobal->LastVariableOffset[NonVolatile]) < VARIABLE_RECLAIM_THRESHOLD) {\r
+    Status = Reclaim (NonVolatile, NULL);\r
+    if (EFI_ERROR (Status)) {\r
+      //\r
+      // Reclaim error\r
+      // we cannot restore to original state\r
+      //\r
+      DEBUG ((EFI_D_ERROR, "FSVariable: Recalim error (fetal error) - %r\n", Status));\r
+      ASSERT_EFI_ERROR (Status);\r
+    }\r
+  }\r
+  \r
+  //\r
+  // 2. Volatile Storage\r
+  //\r
+  Dev = DEV_FROM_THIS (mGlobal->VariableStore[Volatile]);\r
+  VariableStoreHeader = (VARIABLE_STORE_HEADER *) VAR_DATA_PTR (Dev);\r
+  mGlobal->VariableBase[Volatile] = VAR_DATA_PTR (Dev);  \r
+  mGlobal->LastVariableOffset[Volatile] = sizeof (VARIABLE_STORE_HEADER);\r
+  //\r
+  // init store_header & body in memory.\r
+  //\r
+  mGlobal->VariableStore[Volatile]->Erase (mGlobal->VariableStore[Volatile]);\r
+  mGlobal->VariableStore[Volatile]->Write (\r
+                                   mGlobal->VariableStore[Volatile],\r
+                                   0,\r
+                                   sizeof (VARIABLE_STORE_HEADER),\r
+                                   &mStoreHeaderTemplate\r
+                                   );\r
+\r
+\r
+  SystemTable->RuntimeServices->GetVariable         = GetVariable;\r
+  SystemTable->RuntimeServices->GetNextVariableName = GetNextVariableName;\r
+  SystemTable->RuntimeServices->SetVariable         = SetVariable;\r
+\r
+#if (EFI_SPECIFICATION_VERSION >= 0x00020000)\r
+  SystemTable->RuntimeServices->QueryVariableInfo   = QueryVariableInfo;\r
+#endif\r
+\r
+  //\r
+  // Now install the Variable Runtime Architectural Protocol on a new handle\r
+  //\r
+  NewHandle = NULL;\r
+  Status = gBS->InstallMultipleProtocolInterfaces (\r
+                  &NewHandle,\r
+                  &gEfiVariableArchProtocolGuid,\r
+                  NULL,\r
+                  &gEfiVariableWriteArchProtocolGuid,\r
+                  NULL,\r
+                  NULL\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  return Status;\r
+\r
+//Shutdown:\r
+//  EfiShutdownRuntimeDriverLib ();\r
+//  return Status;\r
+}\r
+\r
+\r
+\r
+STATIC\r
+VOID\r
+EFIAPI\r
+OnVirtualAddressChange (\r
+  IN EFI_EVENT        Event,\r
+  IN VOID             *Context\r
+  )\r
+{\r
+  UINTN Index;\r
+\r
+  for (Index = 0; Index < MaxType; Index++) {\r
+    mGlobal->GoVirtualChildEvent[Index] (Event, mGlobal->VariableStore[Index]);\r
+    EfiConvertPointer (0, &mGlobal->VariableStore[Index]);\r
+    EfiConvertPointer (0, &mGlobal->VariableBase[Index]);\r
+  }\r
+  EfiConvertPointer (0, &mGlobal->Scratch);\r
+  EfiConvertPointer (0, &mGlobal);\r
+}\r
diff --git a/DuetPkg/FSVariable/FSVariable.dxs b/DuetPkg/FSVariable/FSVariable.dxs
new file mode 100644 (file)
index 0000000..e3707da
--- /dev/null
@@ -0,0 +1,26 @@
+/*++\r
+\r
+Copyright (c) 2006, Intel Corporation                                                         \r
+All rights reserved. This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
+                                                                                          \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+\r
+Module Name:\r
+\r
+  FSVariable.dxs\r
+\r
+Abstract:\r
+\r
+  Dependency expression source file.\r
+  \r
+--*/  \r
+#include "EfiDepex.h"\r
+#include EFI_ARCH_PROTOCOL_DEFINITION (StatusCode)\r
+\r
+DEPENDENCY_START\r
+  EFI_STATUS_CODE_RUNTIME_PROTOCOL_GUID\r
+DEPENDENCY_END\r
diff --git a/DuetPkg/FSVariable/FSVariable.h b/DuetPkg/FSVariable/FSVariable.h
new file mode 100644 (file)
index 0000000..434c302
--- /dev/null
@@ -0,0 +1,162 @@
+/*++\r
+\r
+Copyright (c) 2006 - 2007, Intel Corporation                                                         \r
+All rights reserved. This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
+                                                                                          \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+\r
+Module Name:\r
+\r
+  FSVariable.h\r
+  \r
+Abstract:\r
+\r
+--*/\r
+\r
+#ifndef _FS_VARIABLE_H\r
+#define _FS_VARIABLE_H\r
+\r
+//\r
+// Statements that include other header files\r
+//\r
+#include <PiDxe.h>\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiRuntimeLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/HobLib.h>\r
+#include <Library/DxeServicesTableLib.h>\r
+#include <Library/DevicePathLib.h>\r
+\r
+#include <Guid/HobList.h>\r
+#include <Guid/FlashMapHob.h>\r
+\r
+#include <Protocol/Variable.h>\r
+#include <Protocol/VariableWrite.h>\r
+#include <Protocol/SimpleFileSystem.h>\r
+#include <Protocol/BlockIo.h>\r
+\r
+\r
+#include "EfiFlashMap.h"\r
+#include "VariableFormat.h"\r
+#include "VariableStorage.h"\r
+\r
+#define VOLATILE_VARIABLE_STORE_SIZE  (64 * 1024)\r
+#define VARIABLE_SCRATCH_SIZE         (4 * 1024)\r
+#define VARIABLE_RECLAIM_THRESHOLD    (1024)\r
+\r
+//\r
+// Define GET_PAD_SIZE to optimize compiler\r
+//\r
+#if ((ALIGNMENT == 0) || (ALIGNMENT == 1))\r
+#define GET_PAD_SIZE(a) (0)\r
+#else\r
+#define GET_PAD_SIZE(a) (((~a) + 1) & (ALIGNMENT - 1))\r
+#endif\r
+\r
+#define GET_VARIABLE_NAME_PTR(a)  (CHAR16 *) ((UINTN) (a) + sizeof (VARIABLE_HEADER))\r
+\r
+typedef enum {\r
+  Physical,\r
+  Virtual\r
+} VARIABLE_POINTER_TYPE;\r
+\r
+typedef enum {\r
+  NonVolatile,\r
+  Volatile,\r
+  MaxType\r
+} VARIABLE_STORAGE_TYPE;\r
+\r
+typedef struct {\r
+  VARIABLE_HEADER         *CurrPtr;\r
+  VARIABLE_HEADER         *EndPtr;\r
+  VARIABLE_HEADER         *StartPtr;\r
+  VARIABLE_STORAGE_TYPE   Type;\r
+} VARIABLE_POINTER_TRACK;\r
+\r
+#define VARIABLE_MEMBER_OFFSET(Member, StartOffset) \\r
+        ( sizeof (VARIABLE_STORE_HEADER) + (StartOffset) + \\r
+          (UINTN) ((UINT8 *) &((VARIABLE_HEADER*) 0)->Member - (UINT8 *) &((VARIABLE_HEADER*) 0)->StartId) \\r
+        )\r
+\r
+\r
+typedef struct {\r
+  EFI_EVENT_NOTIFY   GoVirtualChildEvent[MaxType];\r
+  VARIABLE_STORAGE   *VariableStore[MaxType];       // Instance of VariableStorage\r
+  VOID               *VariableBase[MaxType];        // Start address of variable storage\r
+  UINTN              LastVariableOffset[MaxType];   // The position to write new variable to (index from VariableBase)\r
+  VOID               *Scratch;                      // Buffer used during reclaim\r
+} VARIABLE_GLOBAL;\r
+\r
+//\r
+// Functions\r
+//\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+VariableServiceInitialize (\r
+  IN EFI_HANDLE         ImageHandle,\r
+  IN EFI_SYSTEM_TABLE   *SystemTable\r
+  )\r
+;\r
+\r
+VOID\r
+EFIAPI\r
+VariableClassAddressChangeEvent (\r
+  IN EFI_EVENT        Event,\r
+  IN VOID             *Context\r
+  )\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+GetVariable (\r
+  IN      CHAR16            *VariableName,\r
+  IN      EFI_GUID          *VendorGuid,\r
+  OUT     UINT32            *Attributes OPTIONAL,\r
+  IN OUT  UINTN             *DataSize,\r
+  OUT     VOID              *Data\r
+  )\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+GetNextVariableName (\r
+  IN OUT  UINTN             *VariableNameSize,\r
+  IN OUT  CHAR16            *VariableName,\r
+  IN OUT  EFI_GUID          *VendorGuid\r
+  )\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+SetVariable (\r
+  IN CHAR16                  *VariableName,\r
+  IN EFI_GUID                *VendorGuid,\r
+  IN UINT32                  Attributes,\r
+  IN UINTN                   DataSize,\r
+  IN VOID                    *Data\r
+  )\r
+;\r
+\r
+#if (EFI_SPECIFICATION_VERSION >= 0x00020000)\r
+EFI_STATUS\r
+EFIAPI\r
+QueryVariableInfo (\r
+  IN  UINT32                 Attributes,\r
+  OUT UINT64                 *MaximumVariableStorageSize,\r
+  OUT UINT64                 *RemainingVariableStorageSize,\r
+  OUT UINT64                 *MaximumVariableSize\r
+  )\r
+;\r
+#endif // EFI_SPECIFICATION_VERSION >= 0x00020000\r
+\r
+#endif\r
diff --git a/DuetPkg/FSVariable/FSVariable.inf b/DuetPkg/FSVariable/FSVariable.inf
new file mode 100644 (file)
index 0000000..9a9ff7f
--- /dev/null
@@ -0,0 +1,69 @@
+#/*++\r
+#\r
+# Copyright (c) 2006 - 2007, Intel Corporation                                                         \r
+# All rights reserved. This program and the accompanying materials                          \r
+# are licensed and made available under the terms and conditions of the BSD License         \r
+# which accompanies this distribution.  The full text of the license may be found at        \r
+# http://opensource.org/licenses/bsd-license.php                                            \r
+#                                                                                           \r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+# \r
+#  Module Name:\r
+#\r
+#   FSVariable.inf\r
+#\r
+#  Abstract:\r
+#\r
+#    Component description file for variable module\r
+#\r
+#--*/\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = FSVariable\r
+  FILE_GUID                      = A36495C1-C205-414e-B71F-4BE3476D699C\r
+  MODULE_TYPE                    = DXE_RUNTIME_DRIVER\r
+  VERSION_STRING                 = 1.0\r
+  EDK_RELEASE_VERSION            = 0x00020000\r
+  EFI_SPECIFICATION_VERSION      = 0x00020000\r
+  ENTRY_POINT                    = VariableServiceInitialize\r
+  \r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  DuetPkg/DuetPkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+\r
+[Sources.common]\r
+  FSVariable.h\r
+  VariableStorage.h\r
+  FSVariable.c\r
+  FileStorage.c\r
+  MemStorage.c\r
+\r
+[LibraryClasses.common]\r
+  PcdLib\r
+  BaseMemoryLib\r
+  BaseLib\r
+  UefiBootServicesTableLib\r
+  UefiRuntimeLib\r
+  DebugLib\r
+  UefiLib\r
+  HobLib\r
+  DxeServicesTableLib\r
+  DevicePathLib\r
+  UefiDriverEntryPoint\r
+\r
+[Guids]\r
+  gEfiHobListGuid\r
+  gEfiFlashMapHobGuid\r
+\r
+[Protocols]\r
+  gEfiVariableArchProtocolGuid\r
+  gEfiVariableWriteArchProtocolGuid\r
+  gEfiSimpleFileSystemProtocolGuid\r
+  gEfiBlockIoProtocolGuid\r
+\r
+[Pcd]\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize\r
+\r
diff --git a/DuetPkg/FSVariable/FileStorage.c b/DuetPkg/FSVariable/FileStorage.c
new file mode 100644 (file)
index 0000000..4e366de
--- /dev/null
@@ -0,0 +1,441 @@
+/*++\r
+\r
+Copyright (c) 2006 - 2007, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+    FileStorage.c\r
+\r
+Abstract:\r
+\r
+    handles variable store/reads on file\r
+\r
+Revision History\r
+\r
+--*/\r
+#include "FSVariable.h"\r
+\r
+VOID             *mSFSRegistration;\r
+\r
+//\r
+// Prototypes\r
+//\r
+\r
+STATIC\r
+VOID\r
+EFIAPI\r
+OnVirtualAddressChange (\r
+  IN EFI_EVENT            Event,\r
+  IN VOID                 *Context\r
+  );\r
+\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+FileEraseStore(\r
+  IN VARIABLE_STORAGE     *This\r
+  );\r
+\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+FileWriteStore (\r
+  IN VARIABLE_STORAGE     *This,\r
+  IN UINTN                Offset,\r
+  IN UINTN                BufferSize,\r
+  IN VOID                 *Buffer\r
+  );\r
+\r
+STATIC\r
+EFI_STATUS\r
+OpenStore (\r
+  IN  EFI_DEVICE_PATH_PROTOCOL  *Device,\r
+  IN  CHAR16                    *FilePathName,\r
+  IN  UINT64                    OpenMode,\r
+  OUT EFI_FILE                  **File\r
+  );\r
+\r
+//\r
+// Implementation below:\r
+//\r
+STATIC\r
+VOID\r
+FileClose (\r
+  IN  EFI_FILE                   *File\r
+  )\r
+{\r
+  EFI_STATUS Status;\r
+\r
+  Status = File->Flush (File);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  Status = File->Close (File);\r
+  ASSERT_EFI_ERROR (Status);\r
+}\r
+\r
+EFI_STATUS\r
+CheckStore (\r
+  IN  EFI_HANDLE                 SimpleFileSystemHandle,\r
+  IN  UINT32                     VolumeId,\r
+  OUT EFI_DEVICE_PATH_PROTOCOL   **Device\r
+  )\r
+{\r
+#define BLOCK_SIZE              0x200\r
+#define FAT16_VOLUME_ID_OFFSET  39\r
+#define FAT32_VOLUME_ID_OFFSET  67\r
+  EFI_STATUS                      Status;\r
+  EFI_BLOCK_IO_PROTOCOL           *BlkIo;\r
+  UINT8                           BootSector[BLOCK_SIZE];\r
+\r
+  *Device = NULL;\r
+  Status  = gBS->HandleProtocol (\r
+                   SimpleFileSystemHandle,\r
+                   &gEfiBlockIoProtocolGuid, // BlockIo should be supported if it supports SimpleFileSystem\r
+                   (VOID*)&BlkIo\r
+                   );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    goto ErrHandle;\r
+  }\r
+  if (!BlkIo->Media->MediaPresent) {\r
+    DEBUG ((EFI_D_ERROR, "FileStorage: Media not present!\n"));\r
+    Status = EFI_NO_MEDIA;\r
+    goto ErrHandle;\r
+  }\r
+  if (BlkIo->Media->ReadOnly) {\r
+    DEBUG ((EFI_D_ERROR, "FileStorage: Media is read-only!\n"));\r
+    Status = EFI_ACCESS_DENIED;\r
+    goto ErrHandle;\r
+  }\r
+\r
+  Status = BlkIo->ReadBlocks(\r
+                    BlkIo,\r
+                    BlkIo->Media->MediaId,\r
+                    0,\r
+                    BLOCK_SIZE,\r
+                    BootSector\r
+                    );\r
+  ASSERT_EFI_ERROR (Status);\r
+  if ((*(UINT32 *) &BootSector[FAT16_VOLUME_ID_OFFSET] != VolumeId) &&\r
+      (*(UINT32 *) &BootSector[FAT32_VOLUME_ID_OFFSET] != VolumeId)\r
+      ) {\r
+    Status = EFI_NOT_FOUND;\r
+    goto ErrHandle;\r
+  }\r
+\r
+  *Device = DuplicateDevicePath (DevicePathFromHandle (SimpleFileSystemHandle));\r
+  ASSERT (*Device != NULL);\r
+\r
+ErrHandle:\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+CheckStoreExists (\r
+  IN  EFI_DEVICE_PATH_PROTOCOL   *Device\r
+  )\r
+{\r
+  EFI_HANDLE                        Handle;\r
+  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Volume;\r
+  EFI_STATUS                        Status;\r
+\r
+  Status = gBS->LocateDevicePath (\r
+                  &gEfiSimpleFileSystemProtocolGuid,\r
+                  &Device, \r
+                  &Handle\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = gBS->HandleProtocol (\r
+                  Handle,\r
+                  &gEfiSimpleFileSystemProtocolGuid,\r
+                  &Volume\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+// this routine is still running in BS period, no limitation\r
+// call FileInitStorage(), which load variable content file to memory\r
+// read the store_header, init store_header if it has not been inited (read sth. about format/heathy)\r
+// reclaim space using scratch memory\r
+\r
+STATIC\r
+VOID\r
+EFIAPI\r
+OnSimpleFileSystemInstall (\r
+  IN EFI_EVENT        Event,\r
+  IN VOID             *Context\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  UINTN                     HandleSize;\r
+  EFI_HANDLE                Handle;\r
+  EFI_DEVICE_PATH_PROTOCOL  *Device;\r
+  VS_DEV                    *Dev;\r
+  EFI_FILE                  *File;\r
+  UINTN                     NumBytes;\r
+\r
+  Dev = (VS_DEV *) Context;\r
+  \r
+  if (VAR_FILE_DEVICEPATH (Dev) != NULL &&\r
+      !EFI_ERROR (CheckStoreExists (VAR_FILE_DEVICEPATH (Dev)))\r
+     ) {\r
+    DEBUG ((EFI_D_ERROR, "FileStorage: Already mapped!\n"));\r
+    return ;\r
+  }\r
+\r
+  while (TRUE) {\r
+    HandleSize = sizeof (EFI_HANDLE);\r
+    Status = gBS->LocateHandle (\r
+                    ByRegisterNotify,\r
+                    NULL,\r
+                    mSFSRegistration,\r
+                    &HandleSize,\r
+                    &Handle\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      return ;\r
+    }\r
+    \r
+    Status = CheckStore (Handle, VAR_FILE_VOLUMEID (Dev), &Device);\r
+    if (!EFI_ERROR (Status)) {\r
+      break;\r
+    }\r
+  }\r
+\r
+  VAR_FILE_DEVICEPATH (Dev) = Device;\r
+  Status = OpenStore (\r
+             VAR_FILE_DEVICEPATH (Dev), \r
+             VAR_FILE_FILEPATH (Dev), \r
+             EFI_FILE_MODE_WRITE | EFI_FILE_MODE_READ | EFI_FILE_MODE_CREATE,\r
+             &File\r
+             );\r
+  ASSERT_EFI_ERROR (Status);\r
+  \r
+  NumBytes = Dev->Size;\r
+  Status = File->Write (File, &NumBytes, VAR_DATA_PTR (Dev));\r
+  ASSERT_EFI_ERROR (Status);\r
+  FileClose (File);\r
+  DEBUG ((EFI_D_ERROR, "FileStorage: Mapped to file!\n"));\r
+}\r
+\r
+EFI_STATUS\r
+FileStorageConstructor (\r
+  OUT VARIABLE_STORAGE      **VarStore,\r
+  OUT EFI_EVENT_NOTIFY      *GoVirtualEvent,\r
+  IN  EFI_PHYSICAL_ADDRESS  NvStorageBase,\r
+  IN  UINTN                 Size,\r
+  IN  UINT32                VolumeId,\r
+  IN  CHAR16                *FilePath\r
+  )\r
+{\r
+  VS_DEV                    *Dev;\r
+  EFI_STATUS                Status;\r
+  EFI_EVENT                 Event;\r
+\r
+  Status = gBS->AllocatePool (EfiRuntimeServicesData, sizeof(VS_DEV), &Dev);\r
+  ASSERT_EFI_ERROR (Status);\r
+  ZeroMem (Dev, sizeof(VS_DEV));\r
+\r
+  Dev->Signature          = VARIABLE_STORE_SIGNATURE;\r
+  Dev->Size               = Size;\r
+  VAR_DATA_PTR (Dev)      = (UINT8 *) (UINTN) NvStorageBase;\r
+  VAR_FILE_VOLUMEID (Dev) = VolumeId;\r
+  StrCpy (VAR_FILE_FILEPATH (Dev), FilePath);\r
+  Dev->VarStore.Erase     = FileEraseStore;\r
+  Dev->VarStore.Write     = FileWriteStore;\r
+\r
+  DEBUG ((EFI_D_ERROR, "FileStorageConstructor(0x%0x:0x%0x): added!\n", NvStorageBase, Size));\r
+\r
+  // add notify on SFS's installation.\r
+\r
+  Status = gBS->CreateEvent (\r
+                  EFI_EVENT_NOTIFY_SIGNAL,\r
+                  TPL_CALLBACK,\r
+                  OnSimpleFileSystemInstall,\r
+                  Dev,\r
+                  &Event\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  Status = gBS->RegisterProtocolNotify (\r
+                  &gEfiSimpleFileSystemProtocolGuid,\r
+                  Event,\r
+                  &mSFSRegistration\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  *VarStore       = &Dev->VarStore;\r
+  *GoVirtualEvent = OnVirtualAddressChange;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+FileEraseStore(\r
+  IN VARIABLE_STORAGE   *This\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  VS_DEV                  *Dev;\r
+  EFI_FILE                *File;\r
+  UINTN                   NumBytes;\r
+\r
+  Status = EFI_SUCCESS;\r
+  Dev    = DEV_FROM_THIS(This);\r
+\r
+  SetMem (VAR_DATA_PTR (Dev), Dev->Size, VAR_DEFAULT_VALUE);\r
+\r
+  if (!EfiAtRuntime () && VAR_FILE_DEVICEPATH (Dev) != NULL) {\r
+    Status = OpenStore (\r
+               VAR_FILE_DEVICEPATH (Dev), \r
+               VAR_FILE_FILEPATH (Dev), \r
+               EFI_FILE_MODE_WRITE | EFI_FILE_MODE_READ,\r
+               &File\r
+               );\r
+    ASSERT_EFI_ERROR (Status);\r
+    NumBytes = Dev->Size;\r
+    Status = File->Write (File, &NumBytes, VAR_DATA_PTR (Dev));\r
+    ASSERT_EFI_ERROR (Status);\r
+    FileClose (File);\r
+  }\r
+  \r
+  return Status;\r
+}\r
+\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+FileWriteStore (\r
+  IN VARIABLE_STORAGE     *This,\r
+  IN UINTN                Offset,\r
+  IN UINTN                BufferSize,\r
+  IN VOID                 *Buffer\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  VS_DEV                  *Dev;\r
+  EFI_FILE                *File;\r
+\r
+  Status = EFI_SUCCESS;\r
+  Dev    = DEV_FROM_THIS(This);\r
+\r
+  ASSERT (Buffer != NULL);\r
+  ASSERT (Offset + BufferSize <= Dev->Size);\r
+\r
+  CopyMem (VAR_DATA_PTR (Dev) + Offset, Buffer, BufferSize);\r
+  \r
+  if (!EfiAtRuntime () && VAR_FILE_DEVICEPATH (Dev) != NULL) {\r
+    Status = OpenStore (\r
+               VAR_FILE_DEVICEPATH (Dev), \r
+               VAR_FILE_FILEPATH (Dev), \r
+               EFI_FILE_MODE_WRITE | EFI_FILE_MODE_READ,\r
+               &File\r
+               );\r
+    Status = File->SetPosition (File, Offset);\r
+    ASSERT_EFI_ERROR (Status);\r
+    Status = File->Write (File, &BufferSize, Buffer);\r
+    ASSERT_EFI_ERROR (Status);\r
+    FileClose (File);\r
+  }\r
+  return Status;\r
+}\r
+\r
+STATIC\r
+VOID\r
+EFIAPI\r
+OnVirtualAddressChange (\r
+  IN EFI_EVENT            Event,\r
+  IN VOID                 *Context\r
+  )\r
+{\r
+  VS_DEV  *Dev;\r
+\r
+  Dev = DEV_FROM_THIS (Context);\r
+\r
+  EfiConvertPointer (0, &VAR_DATA_PTR (Dev));\r
+  EfiConvertPointer (0, (VOID **) &Dev->VarStore.Erase);\r
+  EfiConvertPointer (0, (VOID **) &Dev->VarStore.Write);\r
+}\r
+\r
+STATIC\r
+EFI_STATUS\r
+OpenStore (\r
+  IN  EFI_DEVICE_PATH_PROTOCOL  *Device,\r
+  IN  CHAR16                    *FilePathName,\r
+  IN  UINT64                    OpenMode,\r
+  OUT EFI_FILE                  **File\r
+  )\r
+{\r
+  EFI_HANDLE                        Handle;\r
+  EFI_FILE_HANDLE                   Root;\r
+  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Volume;\r
+  EFI_STATUS                        Status;\r
+\r
+  *File = NULL;\r
+\r
+  Status = gBS->LocateDevicePath (\r
+                  &gEfiSimpleFileSystemProtocolGuid,\r
+                  &Device, \r
+                  &Handle\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = gBS->HandleProtocol (\r
+                  Handle,\r
+                  &gEfiSimpleFileSystemProtocolGuid,\r
+                  &Volume\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  \r
+  //\r
+  // Open the root directory of the volume\r
+  //\r
+  Root = NULL;\r
+  Status = Volume->OpenVolume (\r
+                     Volume,\r
+                     &Root\r
+                     );\r
+  ASSERT_EFI_ERROR (Status);\r
+  ASSERT (Root != NULL);\r
+\r
+  //\r
+  // Open file\r
+  //\r
+  Status = Root->Open (\r
+                   Root,\r
+                   File,\r
+                   FilePathName,\r
+                   OpenMode,\r
+                   0\r
+                   );\r
+  if (EFI_ERROR (Status)) {\r
+    *File = NULL;\r
+  }\r
+\r
+  //\r
+  // Close the Root directory\r
+  //\r
+  Root->Close (Root);\r
+  return Status;\r
+}\r
diff --git a/DuetPkg/FSVariable/MemStorage.c b/DuetPkg/FSVariable/MemStorage.c
new file mode 100644 (file)
index 0000000..ed72b89
--- /dev/null
@@ -0,0 +1,135 @@
+/*++\r
+\r
+Copyright (c) 2006 - 2007, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+    MemStorage.c\r
+\r
+Abstract:\r
+\r
+    handles variable store/reads with emulated memory\r
+\r
+Revision History\r
+\r
+--*/\r
+#include "FSVariable.h"\r
+\r
+STATIC\r
+VOID\r
+EFIAPI\r
+OnVirtualAddressChange (\r
+  IN EFI_EVENT            Event,\r
+  IN VOID                 *Context\r
+  );\r
+\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+MemEraseStore(\r
+  IN VARIABLE_STORAGE   *This\r
+  );\r
+\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+MemWriteStore (\r
+  IN VARIABLE_STORAGE   *This,\r
+  IN UINTN                Offset,\r
+  IN UINTN                BufferSize,\r
+  IN VOID                 *Buffer\r
+  );\r
+\r
+EFI_STATUS\r
+MemStorageConstructor (\r
+  OUT VARIABLE_STORAGE          **VarStore,\r
+  OUT EFI_EVENT_NOTIFY          *GoVirtualEvent,\r
+  IN  UINTN                     Size\r
+  )\r
+{\r
+  EFI_STATUS                  Status;\r
+  VS_DEV                      *Dev;\r
+\r
+  Status = gBS->AllocatePool (EfiRuntimeServicesData, sizeof(VS_DEV), &Dev);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  ZeroMem (Dev, sizeof(VS_DEV));\r
+\r
+  Dev->Signature   = VARIABLE_STORE_SIGNATURE;\r
+  Dev->Size        = Size;\r
+\r
+  Dev->VarStore.Erase    = MemEraseStore;\r
+  Dev->VarStore.Write    = MemWriteStore;\r
+\r
+  Status = gBS->AllocatePool (EfiRuntimeServicesData, Size, &VAR_DATA_PTR (Dev));\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  DEBUG ((EFI_D_ERROR, "VStorage: Size = 0x%x\n", Size));\r
+  \r
+  *VarStore       = &Dev->VarStore;\r
+  *GoVirtualEvent = OnVirtualAddressChange;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+STATIC\r
+VOID\r
+EFIAPI\r
+OnVirtualAddressChange (\r
+  IN EFI_EVENT            Event,\r
+  IN VOID                 *Context\r
+  )\r
+{\r
+  VS_DEV                  *Dev;\r
+\r
+  Dev = DEV_FROM_THIS (Context);\r
+\r
+  EfiConvertPointer (0, &VAR_DATA_PTR (Dev));\r
+  EfiConvertPointer (0, (VOID**)&Dev->VarStore.Erase);\r
+  EfiConvertPointer (0, (VOID**)&Dev->VarStore.Write);\r
+}\r
+\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+MemEraseStore(\r
+  IN VARIABLE_STORAGE   *This\r
+  )\r
+{\r
+  VS_DEV              *Dev;\r
+\r
+  Dev = DEV_FROM_THIS(This);\r
+  SetMem (VAR_DATA_PTR (Dev), Dev->Size, VAR_DEFAULT_VALUE);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+MemWriteStore (\r
+  IN VARIABLE_STORAGE     *This,\r
+  IN UINTN                Offset,\r
+  IN UINTN                BufferSize,\r
+  IN VOID                 *UserBuffer\r
+  )\r
+{\r
+  VS_DEV              *Dev;\r
+\r
+  Dev = DEV_FROM_THIS(This);\r
+\r
+  ASSERT (Offset + BufferSize < Dev->Size);\r
+\r
+  // For better performance\r
+  if (VAR_DATA_PTR (Dev) + Offset != UserBuffer) {\r
+    CopyMem (VAR_DATA_PTR (Dev) + Offset, UserBuffer, BufferSize);\r
+  }\r
+  return EFI_SUCCESS;\r
+}\r
diff --git a/DuetPkg/FSVariable/VariableStorage.h b/DuetPkg/FSVariable/VariableStorage.h
new file mode 100644 (file)
index 0000000..3ebfaeb
--- /dev/null
@@ -0,0 +1,111 @@
+/*++\r
+\r
+Copyright (c) 2006 - 2007, Intel Corporation                                                         \r
+All rights reserved. This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
+                                                                                          \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+\r
+Module Name:\r
+\r
+    VariableStorage.h\r
+\r
+Abstract:\r
+\r
+    handles variable store/reads with memory and file\r
+\r
+Revision History\r
+\r
+--*/\r
+#ifndef _VARIABLE_STORAGE_H_\r
+#define _VARIABLE_STORAGE_H_\r
+\r
+#define VAR_DEFAULT_VALUE           (0xff)\r
+#define VAR_DEFAULT_VALUE_16        EFI_SIGNATURE_16 (VAR_DEFAULT_VALUE, VAR_DEFAULT_VALUE)\r
+#define VAR_DEFAULT_VALUE_32        EFI_SIGNATURE_32 (VAR_DEFAULT_VALUE, VAR_DEFAULT_VALUE, \\r
+                                                      VAR_DEFAULT_VALUE, VAR_DEFAULT_VALUE)\r
+\r
+typedef struct _VARIABLE_STORAGE VARIABLE_STORAGE;\r
+\r
+EFI_STATUS\r
+FileStorageConstructor (\r
+  OUT VARIABLE_STORAGE      **VarStore,\r
+  OUT EFI_EVENT_NOTIFY      *GoVirtualEvent,\r
+  IN  EFI_PHYSICAL_ADDRESS  NvStorageBase,\r
+  IN  UINTN                 Size,\r
+  IN  UINT32                VolumeId,\r
+  IN  CHAR16                *FilePath\r
+  );\r
+\r
+EFI_STATUS\r
+MemStorageConstructor (\r
+  OUT VARIABLE_STORAGE          **VarStore,\r
+  OUT EFI_EVENT_NOTIFY          *GoVirtualEvent,\r
+  IN  UINTN                     Size\r
+  );\r
+\r
+typedef\r
+EFI_STATUS\r
+(EFIAPI *ERASE_STORE) (\r
+  IN VARIABLE_STORAGE   *This\r
+  );\r
+\r
+typedef\r
+EFI_STATUS\r
+(EFIAPI *WRITE_STORE) (\r
+  IN VARIABLE_STORAGE   *This,\r
+  IN UINTN              Offset,\r
+  IN UINTN              BufferSize,\r
+  IN VOID               *Buffer\r
+  );\r
+\r
+struct _VARIABLE_STORAGE {\r
+\r
+  //\r
+  // Functions to access the storage\r
+  //\r
+  ERASE_STORE           Erase;\r
+  WRITE_STORE           Write;\r
+};\r
+\r
+typedef struct _VS_FILE_INFO {\r
+  UINT8                     *FileData;      // local buffer for reading acceleration\r
+\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;    // device having storage file\r
+  UINT32                    VolumeId;\r
+  CHAR16                    FilePath[256];\r
+} VS_FILE_INFO;\r
+\r
+typedef struct _VS_MEM_INFO {\r
+  UINT8                     *MemData;\r
+} VS_MEM_INFO;\r
+\r
+typedef struct _VS_DEV {\r
+  UINT32             Signature;\r
+  VARIABLE_STORAGE   VarStore;\r
+  UINTN              Size;\r
+  \r
+  union {\r
+    //\r
+    // finally visit FileInfo.FileData or MemInfo.MemData\r
+    //\r
+    UINT8            *Data;\r
+    \r
+    VS_FILE_INFO     FileInfo;\r
+    VS_MEM_INFO      MemInfo;\r
+  } Info;\r
+\r
+} VS_DEV;\r
+\r
+#define DEV_FROM_THIS(a)        CR (a, VS_DEV, VarStore, VARIABLE_STORE_SIGNATURE)\r
+\r
+#define VAR_DATA_PTR(a)         ((a)->Info.Data)\r
+#define VAR_FILE_DEVICEPATH(a)  ((a)->Info.FileInfo.DevicePath)\r
+#define VAR_FILE_VOLUMEID(a)    ((a)->Info.FileInfo.VolumeId)\r
+#define VAR_FILE_FILEPATH(a)    ((a)->Info.FileInfo.FilePath)\r
+\r
+\r
+#endif\r
diff --git a/DuetPkg/FvbRuntimeService/DUETFwh.dxs b/DuetPkg/FvbRuntimeService/DUETFwh.dxs
new file mode 100644 (file)
index 0000000..8895c36
--- /dev/null
@@ -0,0 +1,26 @@
+#/*++\r
+#\r
+# Copyright (c) 2007, Intel Corporation                                                         \r
+# All rights reserved. This program and the accompanying materials                          \r
+# are licensed and made available under the terms and conditions of the BSD License         \r
+# which accompanies this distribution.  The full text of the license may be found at        \r
+# http://opensource.org/licenses/bsd-license.php                                            \r
+#                                                                                           \r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+# \r
+#  Module Name:\r
+#\r
+#   Nt32Fwh.inf\r
+#\r
+#  Abstract:\r
+#\r
+#    Component description file for Nt32 Module\r
+#\r
+#--*/  \r
+#include "EfiDepex.h"\r
+\r
+\r
+DEPENDENCY_START\r
+  TRUE\r
+DEPENDENCY_END\r
diff --git a/DuetPkg/FvbRuntimeService/DUETFwh.inf b/DuetPkg/FvbRuntimeService/DUETFwh.inf
new file mode 100644 (file)
index 0000000..90d73ec
--- /dev/null
@@ -0,0 +1,62 @@
+#/*++\r
+#\r
+# Copyright (c) 2007, Intel Corporation                                                         \r
+# All rights reserved. This program and the accompanying materials                          \r
+# are licensed and made available under the terms and conditions of the BSD License         \r
+# which accompanies this distribution.  The full text of the license may be found at        \r
+# http://opensource.org/licenses/bsd-license.php                                            \r
+#                                                                                           \r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+# \r
+#  Module Name:\r
+#\r
+#   DUETFwh.inf\r
+#\r
+#  Abstract:\r
+#\r
+#    Component description file for DUET Module\r
+#\r
+#--*/\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = DuetFwh\r
+  FILE_GUID                      = BDFE5FAA-2A35-44bb-B17A-8084D4E2B9E9\r
+  MODULE_TYPE                    = DXE_RUNTIME_DRIVER\r
+  VERSION_STRING                 = 1.0\r
+  EDK_RELEASE_VERSION            = 0x00020000\r
+  EFI_SPECIFICATION_VERSION      = 0x00020000\r
+  ENTRY_POINT                    = FvbInitialize\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+  DuetPkg/DuetPkg.dec\r
+  #TianoModulePkg/TianoModulePkg.dec\r
+\r
+[Sources.common]\r
+  FwBlockService.c\r
+  FwBlockService.h\r
+  FvbInfo.c\r
+  FileIo.c\r
+  FileIo.h\r
+\r
+[LibraryClasses]\r
+  DevicePathLib\r
+  UefiLib\r
+  UefiDriverEntryPoint\r
+  UefiRuntimeLib\r
+  HobLib\r
+\r
+[Guids]\r
+  gEfiFlashMapHobGuid\r
+  gEfiHobListGuid\r
+  gEfiAlternateFvBlockGuid\r
+\r
+[Protocols]\r
+  gEfiFvbExtensionProtocolGuid\r
+  gEfiSimpleFileSystemProtocolGuid\r
+  gEfiFirmwareVolumeBlockProtocolGuid\r
+  gEfiBlockIoProtocolGuid\r
+\r
diff --git a/DuetPkg/FvbRuntimeService/FWBlockService.c b/DuetPkg/FvbRuntimeService/FWBlockService.c
new file mode 100644 (file)
index 0000000..ab1ef25
--- /dev/null
@@ -0,0 +1,1822 @@
+/**@file\r
+Copyright (c) 2007, Intel Corporation                                                         \r
+All rights reserved. This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
+                                                                                          \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+\r
+Module Name:\r
+\r
+  FWBlockService.c\r
+    \r
+Abstract:\r
+\r
+Revision History\r
+\r
+**/\r
+#include "FWBlockService.h"\r
+#include "EfiFlashMap.h"\r
+#include "FileIo.h"\r
+#include "FlashLayout.h"\r
+\r
+ESAL_FWB_GLOBAL       *mFvbModuleGlobal;\r
+VOID                  *mSFSRegistration;\r
+#define TRY_ASSIGN(var, value)  if(var != NULL) {*var = value;}\r
+\r
+EFI_FW_VOL_BLOCK_DEVICE mFvbDeviceTemplate = {\r
+  FVB_DEVICE_SIGNATURE,\r
+  {\r
+    {\r
+      {\r
+        HARDWARE_DEVICE_PATH,\r
+        HW_MEMMAP_DP,\r
+        {\r
+          sizeof (MEMMAP_DEVICE_PATH),\r
+          0\r
+        }\r
+      },\r
+      EfiMemoryMappedIO,\r
+      0,\r
+      0,\r
+    },\r
+    {\r
+      END_DEVICE_PATH_TYPE,\r
+      END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
+      {\r
+        sizeof (EFI_DEVICE_PATH_PROTOCOL),\r
+        0\r
+      }\r
+    }\r
+  },\r
+  0,\r
+  {\r
+    FvbProtocolGetAttributes,\r
+    FvbProtocolSetAttributes,\r
+    FvbProtocolGetPhysicalAddress,\r
+    FvbProtocolGetBlockSize,\r
+    FvbProtocolRead,\r
+    FvbProtocolWrite,\r
+    FvbProtocolEraseBlocks,\r
+    NULL\r
+  },\r
+  {\r
+    FvbExtendProtocolEraseCustomBlockRange\r
+  }\r
+};\r
+\r
+\r
+EFI_STATUS\r
+FlashFdWrite (\r
+  IN     UINTN                            Address,\r
+  IN     EFI_FW_VOL_INSTANCE              *FwhInstance,\r
+  IN OUT UINTN                            *NumBytes,\r
+  IN     UINT8                            *Buffer\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Writes specified number of bytes from the input buffer to the address\r
+\r
+Arguments:\r
+\r
+Returns: \r
+\r
+--*/\r
+{\r
+  EFI_STATUS  Status;\r
+  EFI_FILE    *File;\r
+  UINTN       FileOffset;\r
+  UINTN       BufferForFile;\r
+  UINTN       Length;\r
+\r
+  Status = EFI_SUCCESS;\r
+  CopyMem ((VOID *) Address, Buffer, *NumBytes);\r
+\r
+  if (!EfiAtRuntime () && (FwhInstance->Device != NULL)) {\r
+    Status = FileOpen (FwhInstance->Device, FwhInstance->MappedFile, &File, EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE);\r
+    ASSERT_EFI_ERROR (Status);\r
+    if (!EFI_ERROR (Status)) {\r
+      if (Address - FwhInstance->FvBase[FVB_PHYSICAL] < FwhInstance->Offset) {\r
+        FileOffset = 0;\r
+        BufferForFile = FwhInstance->FvBase[FVB_PHYSICAL] + FwhInstance->Offset;\r
+        Length = *NumBytes - (FwhInstance->Offset - (Address - FwhInstance->FvBase[FVB_PHYSICAL]));\r
+      } else {\r
+        FileOffset = Address - FwhInstance->FvBase[FVB_PHYSICAL] - FwhInstance->Offset;\r
+        BufferForFile = Address;\r
+        Length = *NumBytes;\r
+      }\r
+      \r
+      Status = FileWrite (File, FileOffset, BufferForFile, Length);\r
+      ASSERT_EFI_ERROR (Status);\r
+      FileClose (File);\r
+    }\r
+  }\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+FlashFdErase (\r
+  IN UINTN                                Address,\r
+  IN EFI_FW_VOL_INSTANCE                  *FwhInstance,\r
+  IN UINTN                                LbaLength\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Erase a certain block from address LbaWriteAddress\r
+\r
+Arguments:\r
+\r
+Returns: \r
+\r
+--*/\r
+{\r
+  EFI_STATUS  Status;\r
+  EFI_FILE    *File;\r
+  UINTN       FileOffset;\r
+  UINTN       BufferForFile;\r
+  UINTN       Length;\r
+\r
+  Status = EFI_SUCCESS;\r
+\r
+  SetMem ((VOID *)Address, LbaLength, 0xff);\r
+\r
+  if (!EfiAtRuntime () && (FwhInstance->Device != NULL)) {\r
+    Status = FileOpen (FwhInstance->Device, FwhInstance->MappedFile, &File, EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE);\r
+    ASSERT_EFI_ERROR (Status);\r
+    if (!EFI_ERROR (Status)) {\r
+      if (Address - FwhInstance->FvBase[FVB_PHYSICAL] < FwhInstance->Offset) {\r
+        FileOffset = 0;\r
+        BufferForFile = FwhInstance->FvBase[FVB_PHYSICAL] + FwhInstance->Offset;\r
+        Length = LbaLength - (FwhInstance->Offset - (Address - FwhInstance->FvBase[FVB_PHYSICAL]));\r
+      } else {\r
+        FileOffset = Address - FwhInstance->FvBase[FVB_PHYSICAL] - FwhInstance->Offset;\r
+        BufferForFile = Address;\r
+        Length = LbaLength;\r
+      }\r
+      \r
+      Status = FileWrite (File, FileOffset, BufferForFile, Length);\r
+      ASSERT_EFI_ERROR (Status);\r
+      FileClose (File);\r
+    }\r
+  }\r
+  return Status;\r
+}\r
+\r
+VOID\r
+EFIAPI\r
+FvbVirtualddressChangeEvent (\r
+  IN EFI_EVENT        Event,\r
+  IN VOID             *Context\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Fixup internal data so that EFI and SAL can be call in virtual mode.\r
+  Call the passed in Child Notify event and convert the mFvbModuleGlobal\r
+  date items to there virtual address.\r
+\r
+  mFvbModuleGlobal->FvInstance[FVB_PHYSICAL]  - Physical copy of instance data\r
+  mFvbModuleGlobal->FvInstance[FVB_VIRTUAL]   - Virtual pointer to common \r
+                                                instance data.\r
+\r
+Arguments:\r
+\r
+  (Standard EFI notify event - EFI_EVENT_NOTIFY)\r
+\r
+Returns: \r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  EFI_FW_VOL_INSTANCE *FwhInstance;\r
+  UINTN               Index;\r
+\r
+  EfiConvertPointer (0, (VOID **) &mFvbModuleGlobal->FvInstance[FVB_VIRTUAL]);\r
+\r
+  //\r
+  // Convert the base address of all the instances\r
+  //\r
+  Index       = 0;\r
+  FwhInstance = mFvbModuleGlobal->FvInstance[FVB_PHYSICAL];\r
+  while (Index < mFvbModuleGlobal->NumFv) {\r
+    EfiConvertPointer (0, (VOID **) &FwhInstance->FvBase[FVB_VIRTUAL]);\r
+    FwhInstance = (EFI_FW_VOL_INSTANCE *) ((UINTN)((UINT8 *)FwhInstance) + FwhInstance->VolumeHeader.HeaderLength\r
+                    + (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER)));\r
+    Index++;\r
+  }\r
+\r
+  EfiConvertPointer (0, (VOID **) &mFvbModuleGlobal->FvbScratchSpace[FVB_VIRTUAL]);\r
+  EfiConvertPointer (0, (VOID **) &mFvbModuleGlobal);\r
+}\r
+\r
+EFI_STATUS\r
+GetFvbInstance (\r
+  IN  UINTN                               Instance,\r
+  IN  ESAL_FWB_GLOBAL                     *Global,\r
+  OUT EFI_FW_VOL_INSTANCE                 **FwhInstance,\r
+  IN BOOLEAN                              Virtual\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Retrieves the physical address of a memory mapped FV\r
+\r
+Arguments:\r
+  Instance              - The FV instance whose base address is going to be\r
+                          returned\r
+  Global                - Pointer to ESAL_FWB_GLOBAL that contains all\r
+                          instance data\r
+  FwhInstance           - The EFI_FW_VOL_INSTANCE fimrware instance structure\r
+  Virtual               - Whether CPU is in virtual or physical mode\r
+\r
+Returns: \r
+  EFI_SUCCESS           - Successfully returns\r
+  EFI_INVALID_PARAMETER - Instance not found\r
+\r
+--*/\r
+{\r
+  EFI_FW_VOL_INSTANCE *FwhRecord;\r
+\r
+  if (Instance >= Global->NumFv) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  //\r
+  // Find the right instance of the FVB private data\r
+  //\r
+  FwhRecord = Global->FvInstance[Virtual];\r
+  while (Instance > 0) {\r
+    FwhRecord = (EFI_FW_VOL_INSTANCE *) ((UINTN)((UINT8 *)FwhRecord) + FwhRecord->VolumeHeader.HeaderLength \r
+                     + (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER)));\r
+    Instance--;\r
+  }\r
+\r
+  *FwhInstance = FwhRecord;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+FvbGetPhysicalAddress (\r
+  IN UINTN                                Instance,\r
+  OUT EFI_PHYSICAL_ADDRESS                *Address,\r
+  IN ESAL_FWB_GLOBAL                      *Global,\r
+  IN BOOLEAN                              Virtual\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Retrieves the physical address of a memory mapped FV\r
+\r
+Arguments:\r
+  Instance              - The FV instance whose base address is going to be\r
+                          returned\r
+  Address               - Pointer to a caller allocated EFI_PHYSICAL_ADDRESS \r
+                          that on successful return, contains the base address\r
+                          of the firmware volume. \r
+  Global                - Pointer to ESAL_FWB_GLOBAL that contains all\r
+                          instance data\r
+  Virtual               - Whether CPU is in virtual or physical mode\r
+\r
+Returns: \r
+  EFI_SUCCESS           - Successfully returns\r
+  EFI_INVALID_PARAMETER - Instance not found\r
+\r
+--*/\r
+{\r
+  EFI_FW_VOL_INSTANCE *FwhInstance;\r
+  EFI_STATUS          Status;\r
+\r
+  //\r
+  // Find the right instance of the FVB private data\r
+  //\r
+  Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual);\r
+  ASSERT_EFI_ERROR (Status);\r
+  *Address = FwhInstance->FvBase[Virtual];\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+FvbGetVolumeAttributes (\r
+  IN UINTN                                Instance,\r
+  OUT EFI_FVB_ATTRIBUTES                  *Attributes,\r
+  IN ESAL_FWB_GLOBAL                      *Global,\r
+  IN BOOLEAN                              Virtual\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Retrieves attributes, insures positive polarity of attribute bits, returns\r
+  resulting attributes in output parameter\r
+\r
+Arguments:\r
+  Instance              - The FV instance whose attributes is going to be \r
+                          returned\r
+  Attributes            - Output buffer which contains attributes\r
+  Global                - Pointer to ESAL_FWB_GLOBAL that contains all\r
+                          instance data\r
+  Virtual               - Whether CPU is in virtual or physical mode\r
+\r
+Returns: \r
+  EFI_SUCCESS           - Successfully returns\r
+  EFI_INVALID_PARAMETER - Instance not found\r
+\r
+--*/\r
+{\r
+  EFI_FW_VOL_INSTANCE *FwhInstance;\r
+  EFI_STATUS          Status;\r
+\r
+  //\r
+  // Find the right instance of the FVB private data\r
+  //\r
+  Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual);\r
+  ASSERT_EFI_ERROR (Status);\r
+  *Attributes = FwhInstance->VolumeHeader.Attributes;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+FvbGetLbaAddress (\r
+  IN  UINTN                               Instance,\r
+  IN  EFI_LBA                             Lba,\r
+  OUT UINTN                               *LbaAddress  OPTIONAL,\r
+  OUT UINTN                               *LbaLength   OPTIONAL,\r
+  OUT UINTN                               *NumOfBlocks OPTIONAL,\r
+  IN  ESAL_FWB_GLOBAL                     *Global,\r
+  IN  BOOLEAN                             Virtual\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Retrieves the starting address of an LBA in an FV\r
+\r
+Arguments:\r
+  Instance              - The FV instance which the Lba belongs to\r
+  Lba                   - The logical block address\r
+  LbaAddress            - On output, contains the physical starting address\r
+                          of the Lba for writing\r
+  LbaLength             - On output, contains the length of the block\r
+  NumOfBlocks           - A pointer to a caller allocated UINTN in which the\r
+                          number of consecutive blocks starting with Lba is\r
+                          returned. All blocks in this range have a size of\r
+                          BlockSize\r
+  Global                - Pointer to ESAL_FWB_GLOBAL that contains all\r
+                          instance data\r
+  Virtual               - Whether CPU is in virtual or physical mode\r
+\r
+Returns: \r
+  EFI_SUCCESS           - Successfully returns\r
+  EFI_INVALID_PARAMETER - Instance not found\r
+\r
+--*/\r
+{\r
+  UINT32                  NumBlocks;\r
+  UINT32                  BlockLength;\r
+  UINTN                   Offset;\r
+  EFI_LBA                 StartLba;\r
+  EFI_LBA                 NextLba;\r
+  EFI_FW_VOL_INSTANCE     *FwhInstance;\r
+  EFI_FV_BLOCK_MAP_ENTRY  *BlockMap;\r
+  EFI_STATUS              Status;\r
+\r
+  //\r
+  // Find the right instance of the FVB private data\r
+  //\r
+  Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  StartLba  = 0;\r
+  Offset    = 0;\r
+  BlockMap  = &(FwhInstance->VolumeHeader.BlockMap[0]);\r
+\r
+  //\r
+  // Parse the blockmap of the FV to find which map entry the Lba belongs to\r
+  //\r
+  while (TRUE) {\r
+    NumBlocks   = BlockMap->NumBlocks;\r
+    BlockLength = BlockMap->Length;\r
+\r
+    if (NumBlocks == 0 || BlockLength == 0) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+\r
+    NextLba = StartLba + NumBlocks;\r
+\r
+    //\r
+    // The map entry found\r
+    //\r
+    if (Lba >= StartLba && Lba < NextLba) {\r
+      Offset = Offset + (UINTN) MultU64x32 ((Lba - StartLba), BlockLength);\r
+\r
+      if (LbaAddress) {\r
+        *LbaAddress = FwhInstance->FvBase[Virtual] + Offset;\r
+      }\r
+\r
+      if (LbaLength) {\r
+        *LbaLength = BlockLength;\r
+      }\r
+\r
+      if (NumOfBlocks) {\r
+        *NumOfBlocks = (UINTN) (NextLba - Lba);\r
+      }\r
+\r
+      return EFI_SUCCESS;\r
+    }\r
+\r
+    StartLba  = NextLba;\r
+    Offset    = Offset + NumBlocks * BlockLength;\r
+    BlockMap++;\r
+  }\r
+}\r
+\r
+EFI_STATUS\r
+FvbReadBlock (\r
+  IN UINTN                                Instance,\r
+  IN EFI_LBA                              Lba,\r
+  IN UINTN                                BlockOffset,\r
+  IN OUT UINTN                            *NumBytes,\r
+  IN UINT8                                *Buffer,\r
+  IN ESAL_FWB_GLOBAL                      *Global,\r
+  IN BOOLEAN                              Virtual\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Reads specified number of bytes into a buffer from the specified block\r
+\r
+Arguments:\r
+  Instance              - The FV instance to be read from\r
+  Lba                   - The logical block address to be read from\r
+  BlockOffset           - Offset into the block at which to begin reading\r
+  NumBytes              - Pointer that on input contains the total size of\r
+                          the buffer. On output, it contains the total number\r
+                          of bytes read\r
+  Buffer                - Pointer to a caller allocated buffer that will be\r
+                          used to hold the data read\r
+  Global                - Pointer to ESAL_FWB_GLOBAL that contains all\r
+                          instance data\r
+  Virtual               - Whether CPU is in virtual or physical mode\r
+\r
+Returns: \r
+  EFI_SUCCESS           - The firmware volume was read successfully and \r
+                          contents are in Buffer\r
+  EFI_BAD_BUFFER_SIZE   - Read attempted across a LBA boundary. On output,\r
+                          NumBytes contains the total number of bytes returned\r
+                          in Buffer\r
+  EFI_ACCESS_DENIED     - The firmware volume is in the ReadDisabled state\r
+  EFI_DEVICE_ERROR      - The block device is not functioning correctly and \r
+                          could not be read\r
+  EFI_INVALID_PARAMETER - Instance not found, or NumBytes, Buffer are NULL\r
+\r
+--*/\r
+{\r
+  EFI_FVB_ATTRIBUTES  Attributes;\r
+  UINTN               LbaAddress;\r
+  UINTN               LbaLength;\r
+  EFI_STATUS          Status;\r
+\r
+  //\r
+  // Check for invalid conditions\r
+  //\r
+  if ((NumBytes == NULL) || (Buffer == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (*NumBytes == 0) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Status = FvbGetLbaAddress (Instance, Lba, &LbaAddress, &LbaLength, NULL, Global, Virtual);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  //\r
+  // Check if the FV is read enabled\r
+  //\r
+  FvbGetVolumeAttributes (Instance, &Attributes, Global, Virtual);\r
+\r
+  if ((Attributes & EFI_FVB2_READ_STATUS) == 0) {\r
+    return EFI_ACCESS_DENIED;\r
+  }\r
+  //\r
+  // Perform boundary checks and adjust NumBytes\r
+  //\r
+  if (BlockOffset > LbaLength) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (LbaLength < (*NumBytes + BlockOffset)) {\r
+    *NumBytes = (UINT32) (LbaLength - BlockOffset);\r
+    Status    = EFI_BAD_BUFFER_SIZE;\r
+  }\r
+\r
+  CopyMem (Buffer, (VOID *) (LbaAddress + BlockOffset), (UINTN) *NumBytes);\r
+\r
+  return Status;\r
+}\r
+EFI_STATUS\r
+FvbWriteBlock (\r
+  IN UINTN                                Instance,\r
+  IN EFI_LBA                              Lba,\r
+  IN UINTN                                BlockOffset,\r
+  IN OUT UINTN                            *NumBytes,\r
+  IN UINT8                                *Buffer,\r
+  IN ESAL_FWB_GLOBAL                      *Global,\r
+  IN BOOLEAN                              Virtual\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Writes specified number of bytes from the input buffer to the block\r
+\r
+Arguments:\r
+  Instance              - The FV instance to be written to\r
+  Lba                   - The starting logical block index to write to\r
+  BlockOffset           - Offset into the block at which to begin writing\r
+  NumBytes              - Pointer that on input contains the total size of\r
+                          the buffer. On output, it contains the total number\r
+                          of bytes actually written\r
+  Buffer                - Pointer to a caller allocated buffer that contains\r
+                          the source for the write\r
+  Global                - Pointer to ESAL_FWB_GLOBAL that contains all\r
+                          instance data\r
+  Virtual               - Whether CPU is in virtual or physical mode\r
+\r
+Returns: \r
+  EFI_SUCCESS           - The firmware volume was written successfully\r
+  EFI_BAD_BUFFER_SIZE   - Write attempted across a LBA boundary. On output,\r
+                          NumBytes contains the total number of bytes\r
+                          actually written\r
+  EFI_ACCESS_DENIED     - The firmware volume is in the WriteDisabled state\r
+  EFI_DEVICE_ERROR      - The block device is not functioning correctly and \r
+                          could not be written\r
+  EFI_INVALID_PARAMETER - Instance not found, or NumBytes, Buffer are NULL\r
+\r
+--*/\r
+{\r
+  EFI_FVB_ATTRIBUTES  Attributes;\r
+  UINTN               LbaAddress;\r
+  UINTN               LbaLength;\r
+  EFI_FW_VOL_INSTANCE *FwhInstance;\r
+  EFI_STATUS          Status;\r
+  EFI_STATUS          ReturnStatus;\r
+\r
+  //\r
+  // Find the right instance of the FVB private data\r
+  //\r
+  Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Writes are enabled in the init routine itself\r
+  //\r
+  if (!FwhInstance->WriteEnabled) {\r
+    return EFI_ACCESS_DENIED;\r
+  }\r
+  //\r
+  // Check for invalid conditions\r
+  //\r
+  if ((NumBytes == NULL) || (Buffer == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (*NumBytes == 0) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Status = FvbGetLbaAddress (Instance, Lba, &LbaAddress, &LbaLength, NULL, Global, Virtual);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  //\r
+  // Check if the FV is write enabled\r
+  //\r
+  FvbGetVolumeAttributes (Instance, &Attributes, Global, Virtual);\r
+\r
+  if ((Attributes & EFI_FVB2_WRITE_STATUS) == 0) {\r
+    return EFI_ACCESS_DENIED;\r
+  }\r
+  //\r
+  // Perform boundary checks and adjust NumBytes\r
+  //\r
+  if (BlockOffset > LbaLength) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (LbaLength < (*NumBytes + BlockOffset)) {\r
+    *NumBytes = (UINT32) (LbaLength - BlockOffset);\r
+    Status    = EFI_BAD_BUFFER_SIZE;\r
+  }\r
+\r
+  ReturnStatus = FlashFdWrite (\r
+                  LbaAddress + BlockOffset,\r
+                  FwhInstance,\r
+                  NumBytes,\r
+                  Buffer\r
+                  );\r
+  if (EFI_ERROR (ReturnStatus)) {\r
+    return ReturnStatus;\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+FvbEraseBlock (\r
+  IN UINTN                                Instance,\r
+  IN EFI_LBA                              Lba,\r
+  IN ESAL_FWB_GLOBAL                      *Global,\r
+  IN BOOLEAN                              Virtual\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Erases and initializes a firmware volume block\r
+\r
+Arguments:\r
+  Instance              - The FV instance to be erased\r
+  Lba                   - The logical block index to be erased\r
+  Global                - Pointer to ESAL_FWB_GLOBAL that contains all\r
+                          instance data\r
+  Virtual               - Whether CPU is in virtual or physical mode\r
+\r
+Returns: \r
+  EFI_SUCCESS           - The erase request was successfully completed\r
+  EFI_ACCESS_DENIED     - The firmware volume is in the WriteDisabled state\r
+  EFI_DEVICE_ERROR      - The block device is not functioning correctly and \r
+                          could not be written. Firmware device may have been\r
+                          partially erased\r
+  EFI_INVALID_PARAMETER - Instance not found\r
+\r
+--*/\r
+{\r
+\r
+  EFI_FVB_ATTRIBUTES  Attributes;\r
+  UINTN               LbaAddress;\r
+  EFI_FW_VOL_INSTANCE *FwhInstance;\r
+  UINTN               LbaLength;\r
+  EFI_STATUS          Status;\r
+\r
+  //\r
+  // Find the right instance of the FVB private data\r
+  //\r
+  Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Writes are enabled in the init routine itself\r
+  //\r
+  if (!FwhInstance->WriteEnabled) {\r
+    return EFI_ACCESS_DENIED;\r
+  }\r
+  //\r
+  // Check if the FV is write enabled\r
+  //\r
+  FvbGetVolumeAttributes (Instance, &Attributes, Global, Virtual);\r
+\r
+  if ((Attributes & EFI_FVB2_WRITE_STATUS) == 0) {\r
+    return EFI_ACCESS_DENIED;\r
+  }\r
+  //\r
+  // Get the starting address of the block for erase. For debug reasons,\r
+  // LbaWriteAddress may not be the same as LbaAddress.\r
+  //\r
+  Status = FvbGetLbaAddress (Instance, Lba, &LbaAddress, &LbaLength, NULL, Global, Virtual);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  return FlashFdErase (\r
+          LbaAddress,\r
+          FwhInstance,\r
+          LbaLength\r
+          );\r
+}\r
+\r
+EFI_STATUS\r
+FvbEraseCustomBlockRange (\r
+  IN UINTN                                Instance,\r
+  IN EFI_LBA                              StartLba,\r
+  IN UINTN                                OffsetStartLba,\r
+  IN EFI_LBA                              LastLba,\r
+  IN UINTN                                OffsetLastLba,\r
+  IN ESAL_FWB_GLOBAL                      *Global,\r
+  IN BOOLEAN                              Virtual\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Erases and initializes a specified range of a firmware volume\r
+\r
+Arguments:\r
+  Instance              - The FV instance to be erased\r
+  StartLba              - The starting logical block index to be erased\r
+  OffsetStartLba        - Offset into the starting block at which to \r
+                          begin erasing\r
+  LastLba               - The last logical block index to be erased\r
+  OffsetStartLba        - Offset into the last block at which to end erasing\r
+  Global                - Pointer to ESAL_FWB_GLOBAL that contains all\r
+                          instance data\r
+  Virtual               - Whether CPU is in virtual or physical mode\r
+\r
+Returns: \r
+  EFI_SUCCESS           - The firmware volume was erased successfully\r
+  EFI_ACCESS_DENIED     - The firmware volume is in the WriteDisabled state\r
+  EFI_DEVICE_ERROR      - The block device is not functioning correctly and \r
+                          could not be written. Firmware device may have been\r
+                          partially erased\r
+  EFI_INVALID_PARAMETER - Instance not found\r
+\r
+--*/\r
+{\r
+  EFI_LBA Index;\r
+  UINTN   LbaSize;\r
+  UINTN   ScratchLbaSizeData;\r
+\r
+  //\r
+  // First LBA.\r
+  //\r
+  FvbGetLbaAddress (Instance, StartLba, NULL, &LbaSize, NULL, Global, Virtual);\r
+\r
+  //\r
+  // Use the scratch space as the intermediate buffer to transfer data\r
+  // Back up the first LBA in scratch space.\r
+  //\r
+  FvbReadBlock (Instance, StartLba, 0, &LbaSize, Global->FvbScratchSpace[Virtual], Global, Virtual);\r
+\r
+  //\r
+  // erase now\r
+  //\r
+  FvbEraseBlock (Instance, StartLba, Global, Virtual);\r
+  ScratchLbaSizeData = OffsetStartLba;\r
+\r
+  //\r
+  // write the data back to the first block\r
+  //\r
+  if (ScratchLbaSizeData > 0) {\r
+    FvbWriteBlock (Instance, StartLba, 0, &ScratchLbaSizeData, Global->FvbScratchSpace[Virtual], Global, Virtual);\r
+  }\r
+  //\r
+  // Middle LBAs\r
+  //\r
+  if (LastLba > (StartLba + 1)) {\r
+    for (Index = (StartLba + 1); Index <= (LastLba - 1); Index++) {\r
+      FvbEraseBlock (Instance, Index, Global, Virtual);\r
+    }\r
+  }\r
+  //\r
+  // Last LBAs, the same as first LBAs\r
+  //\r
+  if (LastLba > StartLba) {\r
+    FvbGetLbaAddress (Instance, LastLba, NULL, &LbaSize, NULL, Global, Virtual);\r
+    FvbReadBlock (Instance, LastLba, 0, &LbaSize, Global->FvbScratchSpace[Virtual], Global, Virtual);\r
+    FvbEraseBlock (Instance, LastLba, Global, Virtual);\r
+  }\r
+\r
+  ScratchLbaSizeData = LbaSize - (OffsetStartLba + 1);\r
+\r
+  return FvbWriteBlock (\r
+          Instance,\r
+          LastLba,\r
+          (OffsetLastLba + 1),\r
+          &ScratchLbaSizeData,\r
+          Global->FvbScratchSpace[Virtual],\r
+          Global,\r
+          Virtual\r
+          );\r
+}\r
+\r
+EFI_STATUS\r
+FvbSetVolumeAttributes (\r
+  IN UINTN                                Instance,\r
+  IN OUT EFI_FVB_ATTRIBUTES               *Attributes,\r
+  IN ESAL_FWB_GLOBAL                      *Global,\r
+  IN BOOLEAN                              Virtual\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Modifies the current settings of the firmware volume according to the \r
+  input parameter, and returns the new setting of the volume\r
+\r
+Arguments:\r
+  Instance              - The FV instance whose attributes is going to be \r
+                          modified\r
+  Attributes            - On input, it is a pointer to EFI_FVB_ATTRIBUTES \r
+                          containing the desired firmware volume settings.\r
+                          On successful return, it contains the new settings\r
+                          of the firmware volume\r
+  Global                - Pointer to ESAL_FWB_GLOBAL that contains all\r
+                          instance data\r
+  Virtual               - Whether CPU is in virtual or physical mode\r
+\r
+Returns: \r
+  EFI_SUCCESS           - Successfully returns\r
+  EFI_ACCESS_DENIED     - The volume setting is locked and cannot be modified\r
+  EFI_INVALID_PARAMETER - Instance not found, or The attributes requested are\r
+                          in conflict with the capabilities as declared in the\r
+                          firmware volume header\r
+\r
+--*/\r
+{\r
+  EFI_FW_VOL_INSTANCE *FwhInstance;\r
+  EFI_FVB_ATTRIBUTES  OldAttributes;\r
+  EFI_FVB_ATTRIBUTES  *AttribPtr;\r
+  UINT32              Capabilities;\r
+  UINT32              OldStatus;\r
+  UINT32              NewStatus;\r
+  EFI_STATUS          Status;\r
+\r
+  //\r
+  // Find the right instance of the FVB private data\r
+  //\r
+  Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  AttribPtr     = (EFI_FVB_ATTRIBUTES *) &(FwhInstance->VolumeHeader.Attributes);\r
+  OldAttributes = *AttribPtr;\r
+  Capabilities  = OldAttributes & EFI_FVB2_CAPABILITIES;\r
+  OldStatus     = OldAttributes & EFI_FVB2_STATUS;\r
+  NewStatus     = *Attributes & EFI_FVB2_STATUS;\r
+\r
+  //\r
+  // If firmware volume is locked, no status bit can be updated\r
+  //\r
+  if (OldAttributes & EFI_FVB2_LOCK_STATUS) {\r
+    if (OldStatus ^ NewStatus) {\r
+      return EFI_ACCESS_DENIED;\r
+    }\r
+  }\r
+  //\r
+  // Test read disable\r
+  //\r
+  if ((Capabilities & EFI_FVB2_READ_DISABLED_CAP) == 0) {\r
+    if ((NewStatus & EFI_FVB2_READ_STATUS) == 0) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+  }\r
+  //\r
+  // Test read enable\r
+  //\r
+  if ((Capabilities & EFI_FVB2_READ_ENABLED_CAP) == 0) {\r
+    if (NewStatus & EFI_FVB2_READ_STATUS) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+  }\r
+  //\r
+  // Test write disable\r
+  //\r
+  if ((Capabilities & EFI_FVB2_WRITE_DISABLED_CAP) == 0) {\r
+    if ((NewStatus & EFI_FVB2_WRITE_STATUS) == 0) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+  }\r
+  //\r
+  // Test write enable\r
+  //\r
+  if ((Capabilities & EFI_FVB2_WRITE_ENABLED_CAP) == 0) {\r
+    if (NewStatus & EFI_FVB2_WRITE_STATUS) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+  }\r
+  //\r
+  // Test lock\r
+  //\r
+  if ((Capabilities & EFI_FVB2_LOCK_CAP) == 0) {\r
+    if (NewStatus & EFI_FVB2_LOCK_STATUS) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+  }\r
+\r
+  *AttribPtr  = (*AttribPtr) & (0xFFFFFFFF & (~EFI_FVB2_STATUS));\r
+  *AttribPtr  = (*AttribPtr) | NewStatus;\r
+  *Attributes = *AttribPtr;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+//\r
+// FVB protocol APIs\r
+//\r
+EFI_STATUS\r
+EFIAPI\r
+FvbProtocolGetPhysicalAddress (\r
+  IN  CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL          *This,\r
+  OUT       EFI_PHYSICAL_ADDRESS                        *Address\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Retrieves the physical address of the device.\r
+\r
+Arguments:\r
+\r
+  This                  - Calling context\r
+  Address               - Output buffer containing the address.\r
+\r
+Returns:\r
+\r
+Returns: \r
+  EFI_SUCCESS           - Successfully returns\r
+\r
+--*/\r
+{\r
+  EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;\r
+\r
+  FvbDevice = FVB_DEVICE_FROM_THIS (This);\r
+\r
+  return FvbGetPhysicalAddress (FvbDevice->Instance, Address, mFvbModuleGlobal, EfiGoneVirtual ());\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+FvbProtocolGetBlockSize (\r
+  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL           *This,\r
+  IN  EFI_LBA                                     Lba,\r
+  OUT UINTN                                       *BlockSize,\r
+  OUT UINTN                                       *NumOfBlocks\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Retrieve the size of a logical block\r
+\r
+Arguments:\r
+  This                  - Calling context\r
+  Lba                   - Indicates which block to return the size for.\r
+  BlockSize             - A pointer to a caller allocated UINTN in which\r
+                          the size of the block is returned\r
+  NumOfBlocks           - a pointer to a caller allocated UINTN in which the\r
+                          number of consecutive blocks starting with Lba is\r
+                          returned. All blocks in this range have a size of\r
+                          BlockSize\r
+\r
+Returns: \r
+  EFI_SUCCESS           - The firmware volume was read successfully and \r
+                          contents are in Buffer\r
+\r
+--*/\r
+{\r
+  EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;\r
+\r
+  FvbDevice = FVB_DEVICE_FROM_THIS (This);\r
+\r
+  return FvbGetLbaAddress (\r
+          FvbDevice->Instance,\r
+          Lba,\r
+          NULL,\r
+          BlockSize,\r
+          NumOfBlocks,\r
+          mFvbModuleGlobal,\r
+          EfiGoneVirtual ()\r
+          );\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+FvbProtocolGetAttributes (\r
+  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL          *This,\r
+  OUT      EFI_FVB_ATTRIBUTES                          *Attributes\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+    Retrieves Volume attributes.  No polarity translations are done.\r
+\r
+Arguments:\r
+    This                - Calling context\r
+    Attributes          - output buffer which contains attributes\r
+\r
+Returns: \r
+  EFI_SUCCESS           - Successfully returns\r
+\r
+--*/\r
+{\r
+  EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;\r
+\r
+  FvbDevice = FVB_DEVICE_FROM_THIS (This);\r
+\r
+  return FvbGetVolumeAttributes (FvbDevice->Instance, Attributes, mFvbModuleGlobal, EfiGoneVirtual ());\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+FvbProtocolSetAttributes (\r
+  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL       *This,\r
+  IN OUT   EFI_FVB_ATTRIBUTES                       *Attributes\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Sets Volume attributes. No polarity translations are done.\r
+\r
+Arguments:\r
+  This                  - Calling context\r
+  Attributes            - output buffer which contains attributes\r
+\r
+Returns: \r
+  EFI_SUCCESS           - Successfully returns\r
+\r
+--*/\r
+{\r
+  EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;\r
+\r
+  FvbDevice = FVB_DEVICE_FROM_THIS (This);\r
+\r
+  return FvbSetVolumeAttributes (FvbDevice->Instance, Attributes, mFvbModuleGlobal, EfiGoneVirtual ());\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+FvbProtocolEraseBlocks (\r
+  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL    *This,\r
+  ...  \r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  The EraseBlock() function erases one or more blocks as denoted by the \r
+  variable argument list. The entire parameter list of blocks must be verified\r
+  prior to erasing any blocks.  If a block is requested that does not exist \r
+  within the associated firmware volume (it has a larger index than the last \r
+  block of the firmware volume), the EraseBlock() function must return\r
+  EFI_INVALID_PARAMETER without modifying the contents of the firmware volume.\r
+\r
+Arguments:\r
+  This                  - Calling context\r
+  ...                   - Starting LBA followed by Number of Lba to erase. \r
+                          a -1 to terminate the list.\r
+\r
+Returns: \r
+  EFI_SUCCESS           - The erase request was successfully completed\r
+  EFI_ACCESS_DENIED     - The firmware volume is in the WriteDisabled state\r
+  EFI_DEVICE_ERROR      - The block device is not functioning correctly and \r
+                          could not be written. Firmware device may have been\r
+                          partially erased\r
+\r
+--*/\r
+{\r
+  EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;\r
+  EFI_FW_VOL_INSTANCE     *FwhInstance;\r
+  UINTN                   NumOfBlocks;\r
+  VA_LIST                 args;\r
+  EFI_LBA                 StartingLba;\r
+  UINTN                   NumOfLba;\r
+  EFI_STATUS              Status;\r
+\r
+  FvbDevice = FVB_DEVICE_FROM_THIS (This);\r
+\r
+  Status    = GetFvbInstance (FvbDevice->Instance, mFvbModuleGlobal, &FwhInstance, EfiGoneVirtual ());\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  NumOfBlocks = FwhInstance->NumOfBlocks;\r
+\r
+  VA_START (args, This);\r
+\r
+  do {\r
+    StartingLba = VA_ARG (args, EFI_LBA);\r
+    if (StartingLba == EFI_LBA_LIST_TERMINATOR) {\r
+      break;\r
+    }\r
+\r
+    NumOfLba = VA_ARG (args, UINT32);\r
+\r
+    //\r
+    // Check input parameters\r
+    //\r
+    if ((NumOfLba == 0) || ((StartingLba + NumOfLba) > NumOfBlocks)) {\r
+      VA_END (args);\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+  } while (1);\r
+\r
+  VA_END (args);\r
+\r
+  VA_START (args, This);\r
+  do {\r
+    StartingLba = VA_ARG (args, EFI_LBA);\r
+    if (StartingLba == EFI_LBA_LIST_TERMINATOR) {\r
+      break;\r
+    }\r
+\r
+    NumOfLba = VA_ARG (args, UINT32);\r
+\r
+    while (NumOfLba > 0) {\r
+      Status = FvbEraseBlock (FvbDevice->Instance, StartingLba, mFvbModuleGlobal, EfiGoneVirtual ());\r
+      if (EFI_ERROR (Status)) {\r
+        VA_END (args);\r
+        return Status;\r
+      }\r
+\r
+      StartingLba++;\r
+      NumOfLba--;\r
+    }\r
+\r
+  } while (1);\r
+\r
+  VA_END (args);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+FvbProtocolWrite (\r
+  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL     *This,\r
+  IN EFI_LBA                                      Lba,\r
+  IN UINTN                                        Offset,\r
+  IN OUT UINTN                                    *NumBytes,\r
+  IN UINT8                                        *Buffer\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Writes data beginning at Lba:Offset from FV. The write terminates either\r
+  when *NumBytes of data have been written, or when a block boundary is\r
+  reached.  *NumBytes is updated to reflect the actual number of bytes\r
+  written. The write opertion does not include erase. This routine will\r
+  attempt to write only the specified bytes. If the writes do not stick,\r
+  it will return an error.\r
+\r
+Arguments:\r
+  This                  - Calling context\r
+  Lba                   - Block in which to begin write\r
+  Offset                - Offset in the block at which to begin write\r
+  NumBytes              - On input, indicates the requested write size. On\r
+                          output, indicates the actual number of bytes written\r
+  Buffer                - Buffer containing source data for the write.\r
+\r
+Returns: \r
+  EFI_SUCCESS           - The firmware volume was written successfully\r
+  EFI_BAD_BUFFER_SIZE   - Write attempted across a LBA boundary. On output,\r
+                          NumBytes contains the total number of bytes\r
+                          actually written\r
+  EFI_ACCESS_DENIED     - The firmware volume is in the WriteDisabled state\r
+  EFI_DEVICE_ERROR      - The block device is not functioning correctly and \r
+                          could not be written\r
+  EFI_INVALID_PARAMETER - NumBytes or Buffer are NULL\r
+\r
+--*/\r
+{\r
+\r
+  EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;\r
+\r
+  FvbDevice = FVB_DEVICE_FROM_THIS (This);\r
+\r
+  return FvbWriteBlock (FvbDevice->Instance, Lba, Offset, NumBytes, Buffer, mFvbModuleGlobal, EfiGoneVirtual ());\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+FvbProtocolRead (\r
+  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL     *This,\r
+  IN EFI_LBA                                      Lba,\r
+  IN UINTN                                        Offset,\r
+  IN OUT UINTN                                    *NumBytes,\r
+  IN UINT8                                        *Buffer\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Reads data beginning at Lba:Offset from FV. The Read terminates either\r
+  when *NumBytes of data have been read, or when a block boundary is\r
+  reached.  *NumBytes is updated to reflect the actual number of bytes\r
+  written. The write opertion does not include erase. This routine will\r
+  attempt to write only the specified bytes. If the writes do not stick,\r
+  it will return an error.\r
+\r
+Arguments:\r
+  This                  - Calling context\r
+  Lba                   - Block in which to begin Read\r
+  Offset                - Offset in the block at which to begin Read\r
+  NumBytes              - On input, indicates the requested write size. On\r
+                          output, indicates the actual number of bytes Read\r
+  Buffer                - Buffer containing source data for the Read.\r
+\r
+Returns: \r
+  EFI_SUCCESS           - The firmware volume was read successfully and \r
+                          contents are in Buffer\r
+  EFI_BAD_BUFFER_SIZE   - Read attempted across a LBA boundary. On output,\r
+                          NumBytes contains the total number of bytes returned\r
+                          in Buffer\r
+  EFI_ACCESS_DENIED     - The firmware volume is in the ReadDisabled state\r
+  EFI_DEVICE_ERROR      - The block device is not functioning correctly and \r
+                          could not be read\r
+  EFI_INVALID_PARAMETER - NumBytes or Buffer are NULL\r
+\r
+--*/\r
+{\r
+\r
+  EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;\r
+\r
+  FvbDevice = FVB_DEVICE_FROM_THIS (This);\r
+\r
+  return FvbReadBlock (FvbDevice->Instance, Lba, Offset, NumBytes, Buffer, mFvbModuleGlobal, EfiGoneVirtual ());\r
+}\r
+//\r
+// FVB Extension Protocols\r
+//\r
+EFI_STATUS\r
+EFIAPI\r
+FvbExtendProtocolEraseCustomBlockRange (\r
+  IN EFI_FVB_EXTENSION_PROTOCOL           *This,\r
+  IN EFI_LBA                              StartLba,\r
+  IN UINTN                                OffsetStartLba,\r
+  IN EFI_LBA                              LastLba,\r
+  IN UINTN                                OffsetLastLba\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Erases and initializes a specified range of a firmware volume\r
+\r
+Arguments:\r
+  This                  - Calling context\r
+  StartLba              - The starting logical block index to be erased\r
+  OffsetStartLba        - Offset into the starting block at which to \r
+                          begin erasing\r
+  LastLba               - The last logical block index to be erased\r
+  OffsetStartLba        - Offset into the last block at which to end erasing\r
+\r
+Returns: \r
+  EFI_SUCCESS           - The firmware volume was erased successfully\r
+  EFI_ACCESS_DENIED     - The firmware volume is in the WriteDisabled state\r
+  EFI_DEVICE_ERROR      - The block device is not functioning correctly and \r
+                          could not be written. Firmware device may have been\r
+                          partially erased\r
+\r
+--*/\r
+{\r
+  EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;\r
+\r
+  FvbDevice = FVB_EXTEND_DEVICE_FROM_THIS (This);\r
+\r
+  return FvbEraseCustomBlockRange (\r
+          FvbDevice->Instance,\r
+          StartLba,\r
+          OffsetStartLba,\r
+          LastLba,\r
+          OffsetLastLba,\r
+          mFvbModuleGlobal,\r
+          EfiGoneVirtual ()\r
+          );\r
+}\r
+\r
+STATIC\r
+EFI_STATUS\r
+ValidateFvHeader (\r
+  EFI_FIRMWARE_VOLUME_HEADER            *FwVolHeader\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Check the integrity of firmware volume header\r
+\r
+Arguments:\r
+  FwVolHeader           - A pointer to a firmware volume header\r
+\r
+Returns: \r
+  EFI_SUCCESS           - The firmware volume is consistent\r
+  EFI_NOT_FOUND         - The firmware volume has corrupted. So it is not an FV\r
+\r
+--*/\r
+{\r
+  UINT16  *Ptr;\r
+  UINT16  HeaderLength;\r
+  UINT16  Checksum;\r
+\r
+  //\r
+  // Verify the header revision, header signature, length\r
+  // Length of FvBlock cannot be 2**64-1\r
+  // HeaderLength cannot be an odd number\r
+  //\r
+  if ((FwVolHeader->Revision != EFI_FVH_REVISION) ||\r
+      (FwVolHeader->Signature != EFI_FVH_SIGNATURE) ||\r
+      (FwVolHeader->FvLength == ((UINTN) -1)) ||\r
+      ((FwVolHeader->HeaderLength & 0x01) != 0)\r
+      ) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+  //\r
+  // Verify the header checksum\r
+  //\r
+  HeaderLength  = (UINT16) (FwVolHeader->HeaderLength / 2);\r
+  Ptr           = (UINT16 *) FwVolHeader;\r
+  Checksum      = 0;\r
+  while (HeaderLength > 0) {\r
+    Checksum = Checksum + (*Ptr);\r
+    HeaderLength--;\r
+    Ptr++;\r
+  }\r
+\r
+  if (Checksum != 0) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+GetFvbHeader (\r
+  IN OUT VOID                           **HobList,\r
+  OUT    EFI_FIRMWARE_VOLUME_HEADER     **FwVolHeader,\r
+  OUT    EFI_PHYSICAL_ADDRESS           *BaseAddress     OPTIONAL,\r
+  OUT    UINT32                         *VolumeId        OPTIONAL,\r
+  OUT    CHAR16                         **MappedFile     OPTIONAL,\r
+  OUT    UINT32                         *ActuralSize     OPTIONAL,\r
+  OUT    UINT32                         *Offset          OPTIONAL,\r
+  OUT    BOOLEAN                        *WriteBack       OPTIONAL\r
+  )\r
+{\r
+  EFI_STATUS                  Status;\r
+  VOID                        *Buffer;\r
+  EFI_FLASH_MAP_FS_ENTRY_DATA *FlashMapEntry;\r
+  EFI_FLASH_SUBAREA_ENTRY     *FlashMapSubEntry;\r
+\r
+  Status        = EFI_SUCCESS;\r
+  *FwVolHeader  = NULL;\r
+  TRY_ASSIGN (WriteBack, FALSE);\r
+\r
+  Buffer        = GetNextGuidHob (&gEfiFlashMapHobGuid, HobList);\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  FlashMapEntry     = (EFI_FLASH_MAP_FS_ENTRY_DATA *) Buffer;\r
+  FlashMapSubEntry  = &FlashMapEntry->Entries[0];\r
+  //\r
+  // Check if it is a "FVB" area\r
+  //\r
+  if (!CompareGuid (&FlashMapSubEntry->FileSystem, &gEfiFirmwareVolumeBlockProtocolGuid)) {\r
+    return Status;\r
+  }\r
+  //\r
+  // Check if it is a "real" flash\r
+  //\r
+  if (FlashMapSubEntry->Attributes != (EFI_FLASH_AREA_FV | EFI_FLASH_AREA_MEMMAPPED_FV)) {\r
+    return Status;\r
+  }\r
+\r
+  TRY_ASSIGN (BaseAddress, FlashMapSubEntry->Base);\r
+\r
+  //\r
+  // Cast buffer to FLASH_AREA_INFO to get extra information related to the special FVB driver\r
+  //\r
+  TRY_ASSIGN (VolumeId,    FlashMapEntry->VolumeId);\r
+  TRY_ASSIGN (ActuralSize, FlashMapEntry->ActuralSize);\r
+  TRY_ASSIGN (MappedFile, ((CHAR16 *) FlashMapEntry->FilePath));\r
+  TRY_ASSIGN (Offset,      FlashMapEntry->Offset);\r
+\r
+  DEBUG ((\r
+    EFI_D_ERROR, \r
+    "FlashMap HOB: BaseAddress = 0x%x, Length = 0x%x, ActuralLength = 0x%x, Offset = 0x%x\n", \r
+    (UINTN) FlashMapSubEntry->Base, (UINTN) FlashMapSubEntry->Length, \r
+    (UINTN) FlashMapEntry->ActuralSize, (UINTN) FlashMapEntry->Offset\r
+  ));\r
+  DEBUG ((\r
+    EFI_D_ERROR,\r
+    "FlashMap HOB: VolumeId = 0x%lx, MappedFile = %s\n",\r
+    (UINTN) FlashMapEntry->VolumeId, (UINTN) FlashMapEntry->FilePath\r
+  ));\r
+  *FwVolHeader  = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) (FlashMapSubEntry->Base);\r
+  Status        = ValidateFvHeader (*FwVolHeader);\r
+  if (EFI_ERROR (Status)) {\r
+    //\r
+    // Get FvbInfo\r
+    //\r
+    TRY_ASSIGN (WriteBack, TRUE);\r
+    Status = GetFvbInfo (FlashMapSubEntry->Length, FwVolHeader);\r
+    DEBUG ((EFI_D_ERROR, "Fvb: FV header invalid, GetFvbInfo - %r\n", Status));\r
+    ASSERT_EFI_ERROR (Status);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+STATIC\r
+VOID\r
+EFIAPI\r
+OnSimpleFileSystemInstall (\r
+  IN EFI_EVENT        Event,\r
+  IN VOID             *Context\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  UINTN                     HandleSize;\r
+  EFI_HANDLE                Handle;\r
+  UINTN                     Instance;\r
+  EFI_DEVICE_PATH_PROTOCOL  *Device;\r
+  EFI_FILE                  *File;\r
+  EFI_FW_VOL_INSTANCE       *FwhInstance;\r
+  while (TRUE) {\r
+    HandleSize = sizeof (EFI_HANDLE);\r
+    Status = gBS->LocateHandle (\r
+                    ByRegisterNotify,\r
+                    NULL,\r
+                    mSFSRegistration,\r
+                    &HandleSize,\r
+                    &Handle\r
+                    );\r
+    if (Status == EFI_NOT_FOUND) {\r
+      break;\r
+    }\r
+    DEBUG ((EFI_D_ERROR, "Fwh: New FileSystem Installed!\n"));\r
+    ASSERT_EFI_ERROR (Status);\r
+    //\r
+    // Check if this is the storage we care about, and store it in FwhInstance\r
+    //\r
+    for (Instance = 0; Instance < mFvbModuleGlobal->NumFv; ++Instance) {\r
+      Status = GetFvbInstance (Instance, mFvbModuleGlobal, &FwhInstance, FALSE);\r
+      ASSERT_EFI_ERROR (Status);\r
+\r
+      if (FwhInstance->MappedFile[0] == L'\0') {\r
+        //\r
+        // The instance of FVB isn't mapped to file.\r
+        //\r
+        continue;\r
+      }\r
+\r
+      if ((FwhInstance->Device != NULL) && \r
+          !EFI_ERROR (CheckStoreExists (FwhInstance->Device))\r
+          ) {\r
+        //\r
+        // The instance of FVB has already associated to a device\r
+        //  and the device is not removed from system.\r
+        //\r
+        DEBUG ((\r
+              EFI_D_ERROR, "Fwh: MappedFile FVB (0x%x:0x%x) - Already mapped, Skip!\n", \r
+              (UINTN) FwhInstance->FvBase[FVB_PHYSICAL],\r
+              (UINTN) FwhInstance->Offset\r
+              ));\r
+        continue;\r
+      }\r
+\r
+      Status = CheckStore (Handle, FwhInstance->VolumeId, &Device);\r
+      if (!EFI_ERROR (Status)) {\r
+        //\r
+        // Write back memory content to file\r
+        //\r
+        Status = FileOpen (Device, FwhInstance->MappedFile, &File, EFI_FILE_MODE_WRITE | EFI_FILE_MODE_READ | EFI_FILE_MODE_CREATE);\r
+        ASSERT_EFI_ERROR (Status); \r
+        if (!EFI_ERROR (Status)) {\r
+          DEBUG ((\r
+                EFI_D_ERROR, "Fwh: MappedFile FVB (0x%x:0x%x) - Write back to mapped file!\n", \r
+                (UINTN) FwhInstance->FvBase[FVB_PHYSICAL],\r
+                (UINTN) FwhInstance->Offset\r
+                ));\r
+          Status = FileWrite (\r
+                     File, \r
+                     0, \r
+                     FwhInstance->FvBase[FVB_PHYSICAL] + FwhInstance->Offset, \r
+                     FwhInstance->ActuralSize - FwhInstance->Offset\r
+                     );\r
+          ASSERT_EFI_ERROR (Status); \r
+          if (!EFI_ERROR (Status)) {\r
+            if (FwhInstance->Device != NULL) {\r
+              gBS->FreePool (FwhInstance->Device);\r
+            }\r
+            FwhInstance->Device = Device;\r
+            DEBUG ((\r
+                  EFI_D_ERROR, "Fwh: MappedFile FVB (0x%x:0x%x) - Mapped!\n",\r
+                  (UINTN) FwhInstance->FvBase[FVB_PHYSICAL],\r
+                  (UINTN) FwhInstance->Offset\r
+                  ));\r
+          }\r
+          FileClose (File);\r
+        }\r
+      }\r
+    }\r
+  }\r
+}\r
+\r
+STATIC\r
+VOID\r
+FvbInstallSfsNotify (\r
+  VOID\r
+)\r
+{\r
+  EFI_STATUS Status;\r
+  EFI_EVENT  Event;\r
+\r
+  Status = gBS->CreateEvent (\r
+                  EFI_EVENT_NOTIFY_SIGNAL,\r
+                  TPL_CALLBACK,\r
+                  OnSimpleFileSystemInstall,\r
+                  NULL,\r
+                  &Event\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  Status = gBS->RegisterProtocolNotify (\r
+                  &gEfiSimpleFileSystemProtocolGuid,\r
+                  Event,\r
+                  &mSFSRegistration\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+}\r
+\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+FvbInitialize (\r
+  IN EFI_HANDLE         ImageHandle,\r
+  IN EFI_SYSTEM_TABLE   *SystemTable\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  This function does common initialization for FVB services\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                          Status;\r
+  EFI_FW_VOL_INSTANCE                 *FwhInstance;\r
+  EFI_FIRMWARE_VOLUME_HEADER          *FwVolHeader;\r
+  VOID                                *HobList;\r
+  VOID                                *FirmwareVolumeHobList;\r
+  UINT32                              BufferSize;\r
+  EFI_FV_BLOCK_MAP_ENTRY              *PtrBlockMapEntry;\r
+  UINTN                               LbaAddress;\r
+  EFI_HANDLE                          FwbHandle;\r
+  EFI_FW_VOL_BLOCK_DEVICE             *FvbDevice;\r
+  EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *OldFwbInterface;\r
+  EFI_DEVICE_PATH_PROTOCOL            *TempFwbDevicePath;\r
+  FV_DEVICE_PATH                      TempFvbDevicePathData;\r
+  UINT32                              MaxLbaSize;\r
+  EFI_PHYSICAL_ADDRESS                BaseAddress;\r
+  UINT32                              VolumeId;\r
+  CHAR16                              *MappedFile;\r
+  UINT32                              ActuralSize;\r
+  UINT32                              Offset;\r
+  BOOLEAN                             WriteBack;\r
+  UINTN                               NumOfBlocks;\r
+  UINTN                               HeaderLength;\r
+  BOOLEAN                             InstallSfsNotify;\r
+\r
+  Status = EfiGetSystemConfigurationTable (&gEfiHobListGuid, &HobList);\r
+  //\r
+  // No FV HOBs found\r
+  //\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  HeaderLength     = 0;\r
+  InstallSfsNotify = FALSE;\r
+\r
+  //\r
+  // Allocate runtime services data for global variable, which contains\r
+  // the private data of all firmware volume block instances\r
+  //\r
+  Status = gBS->AllocatePool (\r
+                  EfiRuntimeServicesData,\r
+                  sizeof (ESAL_FWB_GLOBAL),\r
+                  &mFvbModuleGlobal\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+  //\r
+  // Calculate the total size for all firmware volume block instances\r
+  //\r
+  BufferSize            = 0;\r
+  FirmwareVolumeHobList = HobList;\r
+  do {\r
+    Status = GetFvbHeader (&FirmwareVolumeHobList, &FwVolHeader, NULL, NULL, NULL, NULL, NULL, NULL);\r
+    if (EFI_ERROR (Status)) {\r
+      break;\r
+    }\r
+\r
+    if (FwVolHeader) {\r
+      BufferSize += (FwVolHeader->HeaderLength + sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER));\r
+    }\r
+  } while (TRUE);\r
+\r
+  //\r
+  // Only need to allocate once. There is only one copy of physical memory for\r
+  // the private data of each FV instance. But in virtual mode or in physical\r
+  // mode, the address of the the physical memory may be different.\r
+  //\r
+  Status = gBS->AllocatePool (\r
+                  EfiRuntimeServicesData,\r
+                  BufferSize,\r
+                  &mFvbModuleGlobal->FvInstance[FVB_PHYSICAL]\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Make a virtual copy of the FvInstance pointer.\r
+  //\r
+  FwhInstance = mFvbModuleGlobal->FvInstance[FVB_PHYSICAL];\r
+  mFvbModuleGlobal->FvInstance[FVB_VIRTUAL] = FwhInstance;\r
+\r
+  mFvbModuleGlobal->NumFv = 0;\r
+  FirmwareVolumeHobList   = HobList;\r
+  MaxLbaSize              = 0;\r
+\r
+  //\r
+  // Fill in the private data of each firmware volume block instance\r
+  //\r
+  do {\r
+    Status = GetFvbHeader (\r
+               &FirmwareVolumeHobList, &FwVolHeader, \r
+               &BaseAddress, &VolumeId, &MappedFile, &ActuralSize, &Offset,\r
+               &WriteBack\r
+             );\r
+    if (EFI_ERROR (Status)) {\r
+      break;\r
+    }\r
+\r
+    if (!FwVolHeader) {\r
+      continue;\r
+    }\r
+\r
+    CopyMem ((UINTN *) &(FwhInstance->VolumeHeader), (UINTN *) FwVolHeader, FwVolHeader->HeaderLength);\r
+    FwVolHeader                       = &(FwhInstance->VolumeHeader);\r
+\r
+    FwhInstance->FvBase[FVB_PHYSICAL] = (UINTN) BaseAddress;\r
+    FwhInstance->FvBase[FVB_VIRTUAL]  = (UINTN) BaseAddress;\r
+    FwhInstance->Device               = NULL;\r
+    FwhInstance->Offset               = Offset;\r
+\r
+    if (*MappedFile != '\0') {\r
+      FwhInstance->VolumeId             = VolumeId;\r
+      FwhInstance->ActuralSize          = ActuralSize;\r
+      StrCpy (FwhInstance->MappedFile, MappedFile);\r
+\r
+      InstallSfsNotify = TRUE;\r
+    } else {\r
+      FwhInstance->VolumeId             = (UINT32) -1;\r
+      FwhInstance->ActuralSize          = (UINT32) -1;\r
+      FwhInstance->MappedFile[0]        = L'\0';\r
+    }\r
+    \r
+\r
+    //\r
+    // We may expose readonly FVB in future.\r
+    //\r
+    FwhInstance->WriteEnabled         = TRUE;\r
+    EfiInitializeLock (&(FwhInstance->FvbDevLock), TPL_HIGH_LEVEL);\r
+\r
+    LbaAddress  = (UINTN) FwhInstance->FvBase[0];\r
+    NumOfBlocks = 0;\r
+\r
+    if (FwhInstance->WriteEnabled) {\r
+      for (PtrBlockMapEntry = FwVolHeader->BlockMap; PtrBlockMapEntry->NumBlocks != 0; PtrBlockMapEntry++) {\r
+\r
+        LbaAddress += PtrBlockMapEntry->NumBlocks * PtrBlockMapEntry->Length;\r
+        //\r
+        // Get the maximum size of a block. The size will be used to allocate\r
+        // buffer for Scratch space, the intermediate buffer for FVB extension\r
+        // protocol\r
+        //\r
+        if (MaxLbaSize < PtrBlockMapEntry->Length) {\r
+          MaxLbaSize = PtrBlockMapEntry->Length;\r
+        }\r
+\r
+        NumOfBlocks += PtrBlockMapEntry->NumBlocks;\r
+      }\r
+      //\r
+      //  Write back a healthy FV header\r
+      //\r
+      if (WriteBack) {\r
+        Status = FlashFdErase (\r
+                  (UINTN) FwhInstance->FvBase[0],\r
+                  FwhInstance,\r
+                  FwVolHeader->BlockMap->Length\r
+                  );\r
+\r
+        HeaderLength = (UINTN) FwVolHeader->HeaderLength;\r
+\r
+        Status = FlashFdWrite (\r
+                  (UINTN) FwhInstance->FvBase[0],\r
+                  FwhInstance,\r
+                  (UINTN *) &HeaderLength,\r
+                  (UINT8 *) FwVolHeader\r
+                  );\r
+\r
+        FwVolHeader->HeaderLength = (UINT16) HeaderLength;\r
+\r
+        DEBUG ((EFI_D_ERROR, "Fvb (0x%x): FV header invalid, write back - %r\n", (UINTN) FwhInstance->FvBase[0], Status));\r
+      }\r
+    }\r
+    //\r
+    // The total number of blocks in the FV.\r
+    //\r
+    FwhInstance->NumOfBlocks = NumOfBlocks;\r
+\r
+    //\r
+    // Add a FVB Protocol Instance\r
+    //\r
+    Status = gBS->AllocatePool (\r
+                    EfiRuntimeServicesData,\r
+                    sizeof (EFI_FW_VOL_BLOCK_DEVICE),\r
+                    &FvbDevice\r
+                    );\r
+    ASSERT_EFI_ERROR (Status);\r
+\r
+    CopyMem (FvbDevice, &mFvbDeviceTemplate, sizeof (EFI_FW_VOL_BLOCK_DEVICE));\r
+\r
+    FvbDevice->Instance = mFvbModuleGlobal->NumFv;\r
+    mFvbModuleGlobal->NumFv++;\r
+\r
+    //\r
+    // Set up the devicepath\r
+    //\r
+    FvbDevice->DevicePath.MemMapDevPath.StartingAddress = BaseAddress;\r
+    FvbDevice->DevicePath.MemMapDevPath.EndingAddress   = BaseAddress + (FwVolHeader->FvLength - 1);\r
+\r
+    //\r
+    // Find a handle with a matching device path that has supports FW Block protocol\r
+    //\r
+    TempFwbDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) &TempFvbDevicePathData;\r
+    CopyMem (TempFwbDevicePath, &FvbDevice->DevicePath, sizeof (FV_DEVICE_PATH));\r
+    Status = gBS->LocateDevicePath (&gEfiFirmwareVolumeBlockProtocolGuid, &TempFwbDevicePath, &FwbHandle);\r
+    if (EFI_ERROR (Status)) {\r
+      //\r
+      // LocateDevicePath fails so install a new interface and device path\r
+      //\r
+      FwbHandle = NULL;\r
+      Status = gBS->InstallMultipleProtocolInterfaces (\r
+                      &FwbHandle,\r
+                      &gEfiFirmwareVolumeBlockProtocolGuid,\r
+                      &FvbDevice->FwVolBlockInstance,\r
+                      &gEfiDevicePathProtocolGuid,\r
+                      &FvbDevice->DevicePath,\r
+                      NULL\r
+                      );\r
+      ASSERT_EFI_ERROR (Status);\r
+    } else if (EfiIsDevicePathEnd (TempFwbDevicePath)) {\r
+      //\r
+      // Device allready exists, so reinstall the FVB protocol\r
+      //\r
+      Status = gBS->HandleProtocol (\r
+                      FwbHandle,\r
+                      &gEfiFirmwareVolumeBlockProtocolGuid,\r
+                      &OldFwbInterface\r
+                      );\r
+      ASSERT_EFI_ERROR (Status);\r
+\r
+      Status = gBS->ReinstallProtocolInterface (\r
+                      FwbHandle,\r
+                      &gEfiFirmwareVolumeBlockProtocolGuid,\r
+                      OldFwbInterface,\r
+                      &FvbDevice->FwVolBlockInstance\r
+                      );\r
+      ASSERT_EFI_ERROR (Status);\r
+\r
+    } else {\r
+      //\r
+      // There was a FVB protocol on an End Device Path node\r
+      //\r
+      ASSERT (FALSE);\r
+    }\r
+    //\r
+    // Install FVB Extension Protocol on the same handle\r
+    //\r
+    Status = gBS->InstallMultipleProtocolInterfaces (\r
+                    &FwbHandle,\r
+                    &gEfiFvbExtensionProtocolGuid,\r
+                    &FvbDevice->FvbExtension,\r
+                    &gEfiAlternateFvBlockGuid,\r
+                    NULL,\r
+                    NULL\r
+                    );\r
+\r
+    ASSERT_EFI_ERROR (Status);\r
+\r
+    FwhInstance = (EFI_FW_VOL_INSTANCE *)\r
+      (\r
+        (UINTN) ((UINT8 *) FwhInstance) + FwVolHeader->HeaderLength +\r
+          (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER))\r
+      );\r
+  } while (TRUE);\r
+\r
+  //\r
+  // Allocate for scratch space, an intermediate buffer for FVB extention\r
+  //\r
+  Status = gBS->AllocatePool (\r
+                  EfiRuntimeServicesData,\r
+                  MaxLbaSize,\r
+                  &mFvbModuleGlobal->FvbScratchSpace[FVB_PHYSICAL]\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  mFvbModuleGlobal->FvbScratchSpace[FVB_VIRTUAL] = mFvbModuleGlobal->FvbScratchSpace[FVB_PHYSICAL];\r
+\r
+  if (InstallSfsNotify) {\r
+    FvbInstallSfsNotify ();\r
+  }\r
+  return EFI_SUCCESS;\r
+}\r
diff --git a/DuetPkg/FvbRuntimeService/FileIo.c b/DuetPkg/FvbRuntimeService/FileIo.c
new file mode 100644 (file)
index 0000000..0162b15
--- /dev/null
@@ -0,0 +1,210 @@
+/**@file\r
+Copyright (c) 2007, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+    FileIo.c\r
+\r
+Abstract:\r
+\r
+  File operation for Firmware volume block driver\r
+\r
+**/\r
+#include "FileIo.h"\r
+\r
+//\r
+// Variable storage hot plug is supported but there are still some restrictions:\r
+// After plugging the storage back,\r
+// 1. Still use memory as NV if newly plugged storage is not same as the original one\r
+// 2. Still use memory as NV if there are some update operation during storage is unplugged.\r
+//\r
+\r
+\r
+EFI_STATUS\r
+FileWrite (\r
+  IN EFI_FILE  *File,\r
+  IN UINTN     Offset,\r
+  IN UINTN     Buffer,\r
+  IN UINTN     Size\r
+  )\r
+{\r
+  EFI_STATUS Status;\r
+\r
+  Status = File->SetPosition (File, Offset);\r
+  ASSERT_EFI_ERROR (Status);\r
+  if (!EFI_ERROR (Status)) {\r
+    Status = File->Write (File, &Size, (VOID *) Buffer);\r
+    ASSERT_EFI_ERROR (Status);\r
+  }\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+CheckStore (\r
+  IN  EFI_HANDLE                 SimpleFileSystemHandle,\r
+  IN  UINT32                     VolumeId,\r
+  OUT EFI_DEVICE_PATH_PROTOCOL   **Device\r
+  )\r
+{\r
+#define BLOCK_SIZE              0x200\r
+#define FAT16_VOLUME_ID_OFFSET  39\r
+#define FAT32_VOLUME_ID_OFFSET  67\r
+  EFI_STATUS                      Status;\r
+  EFI_BLOCK_IO_PROTOCOL           *BlkIo;\r
+  UINT8                           BootSector[BLOCK_SIZE];\r
+\r
+  *Device = NULL;\r
+  Status  = gBS->HandleProtocol (\r
+                   SimpleFileSystemHandle,\r
+                   &gEfiBlockIoProtocolGuid, // BlockIo should be supported if it supports SimpleFileSystem\r
+                   (VOID*)&BlkIo\r
+                   );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    goto ErrHandle;\r
+  }\r
+  if (!BlkIo->Media->MediaPresent) {\r
+    DEBUG ((EFI_D_ERROR, "FwhMappedFile: Media not present!\n"));\r
+    Status = EFI_NO_MEDIA;\r
+    goto ErrHandle;\r
+  }\r
+  if (BlkIo->Media->ReadOnly) {\r
+    DEBUG ((EFI_D_ERROR, "FwhMappedFile: Media is read-only!\n"));\r
+    Status = EFI_ACCESS_DENIED;\r
+    goto ErrHandle;\r
+  }\r
+\r
+  Status = BlkIo->ReadBlocks(\r
+                    BlkIo,\r
+                    BlkIo->Media->MediaId,\r
+                    0,\r
+                    BLOCK_SIZE,\r
+                    BootSector\r
+                    );\r
+  ASSERT_EFI_ERROR (Status);\r
+  if ((*(UINT32 *) &BootSector[FAT16_VOLUME_ID_OFFSET] != VolumeId) &&\r
+      (*(UINT32 *) &BootSector[FAT32_VOLUME_ID_OFFSET] != VolumeId)\r
+      ) {\r
+    Status = EFI_NOT_FOUND;\r
+    goto ErrHandle;\r
+  }\r
+\r
+  *Device = DuplicateDevicePath (DevicePathFromHandle (SimpleFileSystemHandle));\r
+  ASSERT (*Device != NULL);\r
+\r
+ErrHandle:\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+CheckStoreExists (\r
+  IN  EFI_DEVICE_PATH_PROTOCOL   *Device\r
+  )\r
+{\r
+  EFI_HANDLE                        Handle;\r
+  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Volume;\r
+  EFI_STATUS                        Status;\r
+\r
+  Status = gBS->LocateDevicePath (\r
+                  &gEfiSimpleFileSystemProtocolGuid,\r
+                  &Device, \r
+                  &Handle\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = gBS->HandleProtocol (\r
+                  Handle,\r
+                  &gEfiSimpleFileSystemProtocolGuid,\r
+                  &Volume\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+VOID\r
+FileClose (\r
+  IN  EFI_FILE                   *File\r
+  )\r
+{\r
+  File->Flush (File);\r
+  File->Close (File);\r
+}\r
+EFI_STATUS\r
+FileOpen (\r
+  IN  EFI_DEVICE_PATH_PROTOCOL   *Device,\r
+  IN  CHAR16                     *MappedFile,\r
+  OUT EFI_FILE                   **File,\r
+  IN  UINT64                     OpenMode\r
+  )\r
+{  \r
+  EFI_HANDLE                        Handle;\r
+  EFI_FILE_HANDLE                   Root;\r
+  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Volume;\r
+  EFI_STATUS                        Status;\r
+\r
+  *File = NULL;\r
+\r
+  Status = gBS->LocateDevicePath (\r
+                  &gEfiSimpleFileSystemProtocolGuid,\r
+                  &Device, \r
+                  &Handle\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = gBS->HandleProtocol (\r
+                  Handle,\r
+                  &gEfiSimpleFileSystemProtocolGuid,\r
+                  &Volume\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  \r
+  //\r
+  // Open the root directory of the volume\r
+  //\r
+  Root = NULL;\r
+  Status = Volume->OpenVolume (\r
+                     Volume,\r
+                     &Root\r
+                     );\r
+  ASSERT_EFI_ERROR (Status);\r
+  ASSERT (Root != NULL);\r
+\r
+  //\r
+  // Open file\r
+  //\r
+  Status = Root->Open (\r
+                   Root,\r
+                   File,\r
+                   MappedFile,\r
+                   OpenMode,\r
+                   0\r
+                   );\r
+  if (EFI_ERROR (Status)) {\r
+    *File = NULL;\r
+  }\r
+\r
+  //\r
+  // Close the Root directory\r
+  //\r
+  Root->Close (Root);\r
+  return Status;\r
+}\r
diff --git a/DuetPkg/FvbRuntimeService/FileIo.h b/DuetPkg/FvbRuntimeService/FileIo.h
new file mode 100644 (file)
index 0000000..67068bf
--- /dev/null
@@ -0,0 +1,58 @@
+/**@file\r
+Copyright (c) 2007, Intel Corporation                                                         \r
+All rights reserved. This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
+                                                                                          \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+\r
+Module Name:\r
+\r
+  FileIo.h\r
+  \r
+Abstract:\r
+\r
+  File operation for Firmware volume block driver\r
+\r
+**/\r
+#ifndef _FW_BLOCK_SERVICE_FILE_IO_H\r
+#define _FW_BLOCK_SERVICE_FILE_IO_H\r
+\r
+#include "FwBlockService.h"\r
+\r
+EFI_STATUS\r
+FileWrite (\r
+  IN EFI_FILE  *File,\r
+  IN UINTN     Offset,\r
+  IN UINTN     Buffer,\r
+  IN UINTN     Size\r
+  );\r
+\r
+EFI_STATUS\r
+CheckStore (\r
+  IN  EFI_HANDLE                 SimpleFileSystemHandle,\r
+  IN  UINT32                     VolumeId,\r
+  OUT EFI_DEVICE_PATH_PROTOCOL   **Device\r
+  );\r
+\r
+EFI_STATUS\r
+CheckStoreExists (\r
+  IN  EFI_DEVICE_PATH_PROTOCOL   *Device\r
+  );\r
+\r
+EFI_STATUS\r
+FileOpen (\r
+  IN  EFI_DEVICE_PATH_PROTOCOL   *Device,\r
+  IN  CHAR16                     *MappedFile,\r
+  OUT EFI_FILE                   **File,\r
+  IN  UINT64                     OpenMode\r
+  );\r
+\r
+VOID\r
+FileClose (\r
+  IN  EFI_FILE                   *File\r
+  );\r
+\r
+#endif // _FW_BLOCK_SERVICE_FILE_IO_H\r
diff --git a/DuetPkg/FvbRuntimeService/FvbInfo.c b/DuetPkg/FvbRuntimeService/FvbInfo.c
new file mode 100644 (file)
index 0000000..2642e59
--- /dev/null
@@ -0,0 +1,121 @@
+/**@file\r
+Copyright (c) 2007, Intel Corporation                                                         \r
+All rights reserved. This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
+                                                                                          \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+\r
+Module Name:\r
+\r
+  FvbInfo.c\r
+\r
+Abstract:\r
+\r
+  Defines data structure that is the volume header found.These data is intent\r
+  to decouple FVB driver with FV header.\r
+\r
+**/\r
+#include "FileIo.h"\r
+#include "FlashLayout.h"\r
+\r
+typedef struct {\r
+  UINT64                      FvLength;\r
+  EFI_FIRMWARE_VOLUME_HEADER  FvbInfo;\r
+  EFI_FV_BLOCK_MAP_ENTRY      End;\r
+} EFI_FVB_MEDIA_INFO;\r
+\r
+#define FVB_MEDIA_BLOCK_SIZE    FIRMWARE_BLOCK_SIZE\r
+#define RECOVERY_BOIS_BLOCK_NUM FIRMWARE_BLOCK_NUMBER\r
+#define SYSTEM_NV_BLOCK_NUM     2\r
+\r
+EFI_FVB_MEDIA_INFO  mPlatformFvbMediaInfo[] = {\r
+  //\r
+  // Systen NvStorage FVB\r
+  //\r
+  {\r
+    NV_STORAGE_FVB_SIZE,\r
+    {\r
+      {\r
+        0,\r
+      },  // ZeroVector[16]\r
+      EFI_SYSTEM_NV_DATA_FV_GUID,\r
+      NV_STORAGE_FVB_SIZE,\r
+      EFI_FVH_SIGNATURE,\r
+      EFI_FVB2_READ_ENABLED_CAP |\r
+        EFI_FVB2_READ_STATUS |\r
+        EFI_FVB2_WRITE_ENABLED_CAP |\r
+        EFI_FVB2_WRITE_STATUS |\r
+        EFI_FVB2_ERASE_POLARITY,\r
+      sizeof (EFI_FIRMWARE_VOLUME_HEADER) + sizeof (EFI_FV_BLOCK_MAP_ENTRY),\r
+      0,  // CheckSum\r
+      0,  // ExtHeaderOffset\r
+      {\r
+        0,\r
+      },  // Reserved[1]\r
+      1,  // Revision\r
+      {\r
+        NV_STORAGE_FVB_BLOCK_NUM,\r
+        FV_BLOCK_SIZE,\r
+      }\r
+    },\r
+    {\r
+      0,\r
+      0\r
+    }\r
+  },\r
+  //\r
+  // System FTW FVB\r
+  //\r
+  {\r
+    NV_FTW_FVB_SIZE,\r
+    {\r
+      {\r
+        0,\r
+      },  // ZeroVector[16]\r
+      EFI_SYSTEM_NV_DATA_FV_GUID,\r
+      NV_FTW_FVB_SIZE,\r
+      EFI_FVH_SIGNATURE,\r
+      EFI_FVB2_READ_ENABLED_CAP |\r
+        EFI_FVB2_READ_STATUS |\r
+        EFI_FVB2_WRITE_ENABLED_CAP |\r
+        EFI_FVB2_WRITE_STATUS |\r
+        EFI_FVB2_ERASE_POLARITY,\r
+      sizeof (EFI_FIRMWARE_VOLUME_HEADER) + sizeof (EFI_FV_BLOCK_MAP_ENTRY),\r
+      0,  // CheckSum\r
+      0,  // ExtHeaderOffset\r
+      {\r
+        0,\r
+      },  // Reserved[1]\r
+      1,  // Revision\r
+      {\r
+        NV_FTW_FVB_BLOCK_NUM,\r
+        FV_BLOCK_SIZE,\r
+      }\r
+    },\r
+    {\r
+      0,\r
+      0\r
+    }\r
+  }\r
+};\r
+\r
+EFI_STATUS\r
+GetFvbInfo (\r
+  IN  UINT64                        FvLength,\r
+  OUT EFI_FIRMWARE_VOLUME_HEADER    **FvbInfo\r
+  )\r
+{\r
+  UINTN Index;\r
+\r
+  for (Index = 0; Index < sizeof (mPlatformFvbMediaInfo) / sizeof (EFI_FVB_MEDIA_INFO); Index += 1) {\r
+    if (mPlatformFvbMediaInfo[Index].FvLength == FvLength) {\r
+      *FvbInfo = &mPlatformFvbMediaInfo[Index].FvbInfo;\r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
+\r
+  return EFI_NOT_FOUND;\r
+}\r
diff --git a/DuetPkg/FvbRuntimeService/FwBlockService.h b/DuetPkg/FvbRuntimeService/FwBlockService.h
new file mode 100644 (file)
index 0000000..c3fe7d5
--- /dev/null
@@ -0,0 +1,348 @@
+/**@file\r
+Copyright (c) 2007, Intel Corporation                                                         \r
+All rights reserved. This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
+                                                                                          \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+\r
+Module Name:\r
+\r
+  FwBlockService.h\r
+  \r
+Abstract:\r
+\r
+  Firmware volume block driver for Intel Firmware Hub (FWH) device\r
+\r
+**/\r
+#ifndef _FW_BLOCK_SERVICE_H\r
+#define _FW_BLOCK_SERVICE_H\r
+\r
+//\r
+// The package level header files this module uses\r
+//\r
+#include <PiDxe.h>\r
+\r
+//\r
+// The protocols, PPI and GUID defintions for this module\r
+//\r
+#include <Guid/EventGroup.h>\r
+#include <Guid/FirmwareFileSystem2.h>\r
+#include <Protocol/FvbExtension.h>\r
+#include <Protocol/FirmwareVolumeBlock.h>\r
+#include <Guid/AlternateFvBlock.h>\r
+#include <Protocol/DevicePath.h>\r
+#include <Protocol/SimpleFileSystem.h>\r
+#include <Protocol/BlockIo.h>\r
+#include <Library/DevicePathLib.h>\r
+#include <Guid/SystemNvDataGuid.h>\r
+#include <Guid/FlashMapHob.h>\r
+#include <Guid/HobList.h>\r
+#include <Guid/AlternateFvBlock.h>\r
+#include <Protocol/FvbExtension.h>\r
+\r
+//\r
+// The Library classes this module consumes\r
+//\r
+#include <Library/UefiLib.h>\r
+#include <Library/UefiDriverEntryPoint.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/DxeServicesTableLib.h>\r
+#include <Library/UefiRuntimeLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/HobLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/PcdLib.h>\r
+\r
+\r
+#define FWH_READ_LOCK                   (1 << 2)\r
+#define FWH_LOCK_DOWN                   (1 << 1)\r
+#define FWH_WRITE_LOCK                  1\r
+#define FWH_WRITE_STATE_STATUS          (1 << 7)\r
+#define FWH_ERASE_STATUS                (1 << 5)\r
+#define FWH_PROGRAM_STATUS              (1 << 4)\r
+#define FWH_VPP_STATUS                  (1 << 3)\r
+#define STALL_TIME                      5\r
+#define FWH_ERASE_STATUS_BITS           (FWH_ERASE_STATUS || FWH_VPP_STATUS)\r
+#define FWH_WRITE_STATUS_BITS           (FWH_WRITE_STATUS || FWH_VPP_STATUS)\r
+\r
+//\r
+// BugBug: Add documentation here for data structure!!!!\r
+//\r
+#define FVB_PHYSICAL  0\r
+#define FVB_VIRTUAL   1\r
+\r
+#define EFI_FVB2_CAPABILITIES (EFI_FVB2_READ_DISABLED_CAP | \\r
+                              EFI_FVB2_READ_ENABLED_CAP | \\r
+                              EFI_FVB2_WRITE_DISABLED_CAP | \\r
+                              EFI_FVB2_WRITE_ENABLED_CAP | \\r
+                              EFI_FVB2_LOCK_CAP \\r
+                              )\r
+#define EFI_FVB2_STATUS (EFI_FVB2_READ_STATUS | EFI_FVB2_WRITE_STATUS | EFI_FVB2_LOCK_STATUS)\r
+\r
+typedef struct {\r
+  EFI_LOCK                    FvbDevLock;\r
+  UINTN                       FvBase[2];\r
+  //\r
+  // We can treat VolumeSignature combined with MappedFile \r
+  //  as a unique key to locate the mapped file.\r
+#define MAX_PATH 256\r
+  UINT32                      VolumeId;\r
+  CHAR16                      MappedFile[MAX_PATH];\r
+  UINT32                      ActuralSize;\r
+  UINT32                      Offset;\r
+  \r
+  EFI_DEVICE_PATH_PROTOCOL    *Device; // only used in BS period, won't use after memory map changed\r
+  UINTN                       NumOfBlocks;\r
+  BOOLEAN                     WriteEnabled;\r
+  EFI_FIRMWARE_VOLUME_HEADER  VolumeHeader;\r
+} EFI_FW_VOL_INSTANCE;\r
+\r
+typedef struct {\r
+  UINT32              NumFv;\r
+  EFI_FW_VOL_INSTANCE *FvInstance[2];\r
+  UINT8               *FvbScratchSpace[2];\r
+} ESAL_FWB_GLOBAL;\r
+\r
+//\r
+// Fvb Protocol instance data\r
+//\r
+#define FVB_DEVICE_FROM_THIS(a)         CR (a, EFI_FW_VOL_BLOCK_DEVICE, FwVolBlockInstance, FVB_DEVICE_SIGNATURE)\r
+#define FVB_EXTEND_DEVICE_FROM_THIS(a)  CR (a, EFI_FW_VOL_BLOCK_DEVICE, FvbExtension, FVB_DEVICE_SIGNATURE)\r
+#define FVB_DEVICE_SIGNATURE            EFI_SIGNATURE_32 ('F', 'V', 'B', 'C')\r
+\r
+typedef struct {\r
+  MEMMAP_DEVICE_PATH        MemMapDevPath;\r
+  EFI_DEVICE_PATH_PROTOCOL  EndDevPath;\r
+} FV_DEVICE_PATH;\r
+\r
+typedef struct {\r
+  UINTN                               Signature;\r
+  FV_DEVICE_PATH                      DevicePath;\r
+  UINTN                               Instance;\r
+  EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  FwVolBlockInstance;\r
+  EFI_FVB_EXTENSION_PROTOCOL          FvbExtension;\r
+} EFI_FW_VOL_BLOCK_DEVICE;\r
+\r
+EFI_STATUS\r
+GetFvbInfo (\r
+  IN  EFI_PHYSICAL_ADDRESS              FvBaseAddress,\r
+  OUT EFI_FIRMWARE_VOLUME_HEADER        **FvbInfo\r
+  )\r
+;\r
+\r
+EFI_STATUS\r
+EnableFvbWrites (\r
+  IN  BOOLEAN   EnableWrites\r
+  )\r
+;\r
+\r
+EFI_STATUS\r
+PlatformGetFvbWriteBase (\r
+  IN  UINTN     CurrentBaseAddress,\r
+  IN  UINTN     *NewBaseAddress,\r
+  IN  BOOLEAN   *WriteEnabled\r
+  )\r
+;\r
+\r
+EFI_STATUS\r
+EnablePlatformFvb (\r
+  VOID\r
+  )\r
+;\r
+\r
+BOOLEAN\r
+SetPlatformFvbLock (\r
+  IN UINTN  LbaAddress\r
+  )\r
+;\r
+\r
+EFI_STATUS\r
+FvbReadBlock (\r
+  IN UINTN                                Instance,\r
+  IN EFI_LBA                              Lba,\r
+  IN UINTN                                BlockOffset,\r
+  IN OUT UINTN                            *NumBytes,\r
+  IN UINT8                                *Buffer,\r
+  IN ESAL_FWB_GLOBAL                      *Global,\r
+  IN BOOLEAN                              Virtual\r
+  )\r
+;\r
+\r
+EFI_STATUS\r
+FvbWriteBlock (\r
+  IN UINTN                                Instance,\r
+  IN EFI_LBA                              Lba,\r
+  IN UINTN                                BlockOffset,\r
+  IN OUT UINTN                            *NumBytes,\r
+  IN UINT8                                *Buffer,\r
+  IN ESAL_FWB_GLOBAL                      *Global,\r
+  IN BOOLEAN                              Virtual\r
+  )\r
+;\r
+\r
+EFI_STATUS\r
+FvbEraseBlock (\r
+  IN UINTN                                Instance,\r
+  IN EFI_LBA                              Lba,\r
+  IN ESAL_FWB_GLOBAL                      *Global,\r
+  IN BOOLEAN                              Virtual\r
+  )\r
+;\r
+\r
+EFI_STATUS\r
+FvbSetVolumeAttributes (\r
+  IN UINTN                                Instance,\r
+  IN OUT EFI_FVB_ATTRIBUTES               *Attributes,\r
+  IN ESAL_FWB_GLOBAL                      *Global,\r
+  IN BOOLEAN                              Virtual\r
+  )\r
+;\r
+\r
+EFI_STATUS\r
+FvbGetVolumeAttributes (\r
+  IN UINTN                                Instance,\r
+  OUT EFI_FVB_ATTRIBUTES                  *Attributes,\r
+  IN ESAL_FWB_GLOBAL                      *Global,\r
+  IN BOOLEAN                              Virtual\r
+  )\r
+;\r
+\r
+EFI_STATUS\r
+FvbGetPhysicalAddress (\r
+  IN UINTN                                Instance,\r
+  OUT EFI_PHYSICAL_ADDRESS                *Address,\r
+  IN ESAL_FWB_GLOBAL                      *Global,\r
+  IN BOOLEAN                              Virtual\r
+  )\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+FvbInitialize (\r
+  IN EFI_HANDLE         ImageHandle,\r
+  IN EFI_SYSTEM_TABLE   *SystemTable\r
+  )\r
+;\r
+\r
+VOID\r
+EFIAPI\r
+FvbClassAddressChangeEvent (\r
+  IN EFI_EVENT        Event,\r
+  IN VOID             *Context\r
+  )\r
+;\r
+\r
+EFI_STATUS\r
+FvbSpecificInitialize (\r
+  IN  ESAL_FWB_GLOBAL   *mFvbModuleGlobal\r
+  )\r
+;\r
+\r
+EFI_STATUS\r
+FvbGetLbaAddress (\r
+  IN  UINTN                               Instance,\r
+  IN  EFI_LBA                             Lba,\r
+  OUT UINTN                               *LbaAddress,\r
+  OUT UINTN                               *LbaLength,\r
+  OUT UINTN                               *NumOfBlocks,\r
+  IN  ESAL_FWB_GLOBAL                     *Global,\r
+  IN  BOOLEAN                             Virtual\r
+  )\r
+;\r
+\r
+EFI_STATUS\r
+FvbEraseCustomBlockRange (\r
+  IN UINTN                                Instance,\r
+  IN EFI_LBA                              StartLba,\r
+  IN UINTN                                OffsetStartLba,\r
+  IN EFI_LBA                              LastLba,\r
+  IN UINTN                                OffsetLastLba,\r
+  IN ESAL_FWB_GLOBAL                      *Global,\r
+  IN BOOLEAN                              Virtual\r
+  )\r
+;\r
+\r
+//\r
+// Protocol APIs\r
+//\r
+EFI_STATUS\r
+EFIAPI\r
+FvbProtocolGetAttributes (\r
+  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL          *This,\r
+  OUT      EFI_FVB_ATTRIBUTES                          *Attributes\r
+  )\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+FvbProtocolSetAttributes (\r
+  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL       *This,\r
+  IN OUT   EFI_FVB_ATTRIBUTES                       *Attributes\r
+  )\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+FvbProtocolGetPhysicalAddress (\r
+  IN  CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL          *This,\r
+  OUT       EFI_PHYSICAL_ADDRESS                        *Address\r
+  )\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+FvbProtocolGetBlockSize (\r
+  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL           *This,\r
+  IN  EFI_LBA                                     Lba,\r
+  OUT UINTN                                       *BlockSize,\r
+  OUT UINTN                                       *NumOfBlocks\r
+  )\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+FvbProtocolRead (\r
+  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL     *This,\r
+  IN EFI_LBA                                      Lba,\r
+  IN UINTN                                        Offset,\r
+  IN OUT UINTN                                    *NumBytes,\r
+  IN UINT8                                        *Buffer\r
+  )\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+FvbProtocolWrite (\r
+  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL     *This,\r
+  IN EFI_LBA                                      Lba,\r
+  IN UINTN                                        Offset,\r
+  IN OUT UINTN                                    *NumBytes,\r
+  IN UINT8                                        *Buffer\r
+  )\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+FvbProtocolEraseBlocks (\r
+  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL    *This,\r
+  ...  \r
+  )\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+FvbExtendProtocolEraseCustomBlockRange (\r
+  IN EFI_FVB_EXTENSION_PROTOCOL           *This,\r
+  IN EFI_LBA                              StartLba,\r
+  IN UINTN                                OffsetStartLba,\r
+  IN EFI_LBA                              LastLba,\r
+  IN UINTN                                OffsetLastLba\r
+  )\r
+;\r
+\r
+#endif\r