--- /dev/null
+/*++\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
--- /dev/null
+/*++\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
--- /dev/null
+/*++\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
--- /dev/null
+#/*++\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
--- /dev/null
+/*++\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
--- /dev/null
+/*++\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
--- /dev/null
+#/*++\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
--- /dev/null
+#/*++\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
--- /dev/null
+/*++\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
--- /dev/null
+/*++\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
--- /dev/null
+/*++\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
--- /dev/null
+/*++\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
--- /dev/null
+#/*++\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
--- /dev/null
+#/*++\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
--- /dev/null
+/*++\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
--- /dev/null
+/*++\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
--- /dev/null
+/*++\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
--- /dev/null
+/*++\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
--- /dev/null
+#/*++\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
--- /dev/null
+/*++\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
--- /dev/null
+/*++\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
--- /dev/null
+/*++\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
--- /dev/null
+#/*++\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
--- /dev/null
+#/*++\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
--- /dev/null
+/**@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
--- /dev/null
+/**@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
--- /dev/null
+/**@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
--- /dev/null
+/**@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
--- /dev/null
+/**@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