/** @file\r
Capsule update PEIM for UEFI2.0\r
\r
-Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>\r
\r
This program and the accompanying materials\r
are licensed and made available under the terms and conditions\r
\r
#include "Capsule.h"\r
\r
+#ifdef MDE_CPU_IA32\r
//\r
// Global Descriptor Table (GDT)\r
//\r
VOID\r
)\r
{\r
+ UINT32 RegEax;\r
+ UINT32 RegEdx;\r
UINTN TotalPagesNum;\r
UINT8 PhysicalAddressBits;\r
VOID *Hob;\r
UINT32 NumberOfPml4EntriesNeeded;\r
UINT32 NumberOfPdpEntriesNeeded;\r
+ BOOLEAN Page1GSupport;\r
+\r
+ Page1GSupport = FALSE;\r
+ if (PcdGetBool(PcdUse1GPageTable)) {\r
+ AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);\r
+ if (RegEax >= 0x80000001) {\r
+ AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx);\r
+ if ((RegEdx & BIT26) != 0) {\r
+ Page1GSupport = TRUE;\r
+ }\r
+ }\r
+ }\r
\r
//\r
- // Get physical address bits supported from CPU HOB.\r
+ // Get physical address bits supported.\r
//\r
- PhysicalAddressBits = 36;\r
- \r
Hob = GetFirstHob (EFI_HOB_TYPE_CPU);\r
if (Hob != NULL) {\r
PhysicalAddressBits = ((EFI_HOB_CPU *) Hob)->SizeOfMemorySpace;\r
+ } else {\r
+ AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);\r
+ if (RegEax >= 0x80000008) {\r
+ AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);\r
+ PhysicalAddressBits = (UINT8) RegEax;\r
+ } else {\r
+ PhysicalAddressBits = 36;\r
+ }\r
}\r
\r
//\r
//\r
if (PhysicalAddressBits <= 39 ) {\r
NumberOfPml4EntriesNeeded = 1;\r
- NumberOfPdpEntriesNeeded = 1 << (PhysicalAddressBits - 30);\r
+ NumberOfPdpEntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits - 30));\r
} else {\r
- NumberOfPml4EntriesNeeded = 1 << (PhysicalAddressBits - 39);\r
+ NumberOfPml4EntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits - 39));\r
NumberOfPdpEntriesNeeded = 512;\r
}\r
\r
- TotalPagesNum = (NumberOfPdpEntriesNeeded + 1) * NumberOfPml4EntriesNeeded + 1;\r
+ if (!Page1GSupport) {\r
+ TotalPagesNum = (NumberOfPdpEntriesNeeded + 1) * NumberOfPml4EntriesNeeded + 1;\r
+ } else {\r
+ TotalPagesNum = NumberOfPml4EntriesNeeded + 1;\r
+ }\r
\r
return EFI_PAGES_TO_SIZE (TotalPagesNum);\r
}\r
IN EFI_PHYSICAL_ADDRESS PageTablesAddress\r
)\r
{ \r
+ UINT32 RegEax;\r
+ UINT32 RegEdx;\r
UINT8 PhysicalAddressBits;\r
EFI_PHYSICAL_ADDRESS PageAddress;\r
UINTN IndexOfPml4Entries;\r
PAGE_TABLE_ENTRY *PageDirectoryEntry;\r
UINTN BigPageAddress;\r
VOID *Hob;\r
+ BOOLEAN Page1GSupport;\r
+ PAGE_TABLE_1G_ENTRY *PageDirectory1GEntry;\r
+\r
+ Page1GSupport = FALSE;\r
+ AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);\r
+ if (RegEax >= 0x80000001) {\r
+ AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx);\r
+ if ((RegEdx & BIT26) != 0) {\r
+ Page1GSupport = TRUE;\r
+ }\r
+ }\r
\r
//\r
- // Get physical address bits supported from CPU HOB.\r
+ // Get physical address bits supported.\r
//\r
- PhysicalAddressBits = 36;\r
- \r
Hob = GetFirstHob (EFI_HOB_TYPE_CPU);\r
if (Hob != NULL) {\r
PhysicalAddressBits = ((EFI_HOB_CPU *) Hob)->SizeOfMemorySpace;\r
+ } else {\r
+ AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);\r
+ if (RegEax >= 0x80000008) {\r
+ AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);\r
+ PhysicalAddressBits = (UINT8) RegEax;\r
+ } else {\r
+ PhysicalAddressBits = 36;\r
+ }\r
}\r
\r
//\r
//\r
if (PhysicalAddressBits <= 39 ) {\r
NumberOfPml4EntriesNeeded = 1;\r
- NumberOfPdpEntriesNeeded = 1 << (PhysicalAddressBits - 30);\r
+ NumberOfPdpEntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits - 30));\r
} else {\r
- NumberOfPml4EntriesNeeded = 1 << (PhysicalAddressBits - 39);\r
+ NumberOfPml4EntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits - 39));\r
NumberOfPdpEntriesNeeded = 512;\r
}\r
\r
// By architecture only one PageMapLevel4 exists - so lets allocate storage for it.\r
//\r
PageMap = (VOID *) BigPageAddress;\r
- BigPageAddress += EFI_PAGE_SIZE;\r
+ BigPageAddress += SIZE_4KB;\r
\r
PageMapLevel4Entry = PageMap;\r
PageAddress = 0;\r
// So lets allocate space for them and fill them in in the IndexOfPdpEntries loop.\r
//\r
PageDirectoryPointerEntry = (VOID *) BigPageAddress;\r
- BigPageAddress += EFI_PAGE_SIZE;\r
+ BigPageAddress += SIZE_4KB;\r
\r
//\r
// Make a PML4 Entry\r
PageMapLevel4Entry->Bits.ReadWrite = 1;\r
PageMapLevel4Entry->Bits.Present = 1;\r
\r
- for (IndexOfPdpEntries = 0; IndexOfPdpEntries < NumberOfPdpEntriesNeeded; IndexOfPdpEntries++, PageDirectoryPointerEntry++) {\r
- //\r
- // Each Directory Pointer entries points to a page of Page Directory entires.\r
- // So allocate space for them and fill them in in the IndexOfPageDirectoryEntries loop.\r
- // \r
- PageDirectoryEntry = (VOID *) BigPageAddress;\r
- BigPageAddress += EFI_PAGE_SIZE;\r
-\r
- //\r
- // Fill in a Page Directory Pointer Entries\r
- //\r
- PageDirectoryPointerEntry->Uint64 = (UINT64)(UINTN)PageDirectoryEntry;\r
- PageDirectoryPointerEntry->Bits.ReadWrite = 1;\r
- PageDirectoryPointerEntry->Bits.Present = 1;\r
-\r
- for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PageAddress += 0x200000) {\r
+ if (Page1GSupport) {\r
+ PageDirectory1GEntry = (VOID *) PageDirectoryPointerEntry;\r
+ \r
+ for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectory1GEntry++, PageAddress += SIZE_1GB) {\r
//\r
// Fill in the Page Directory entries\r
//\r
- PageDirectoryEntry->Uint64 = (UINT64)PageAddress;\r
- PageDirectoryEntry->Bits.ReadWrite = 1;\r
- PageDirectoryEntry->Bits.Present = 1;\r
- PageDirectoryEntry->Bits.MustBe1 = 1;\r
+ PageDirectory1GEntry->Uint64 = (UINT64)PageAddress;\r
+ PageDirectory1GEntry->Bits.ReadWrite = 1;\r
+ PageDirectory1GEntry->Bits.Present = 1;\r
+ PageDirectory1GEntry->Bits.MustBe1 = 1;\r
+ }\r
+ } else {\r
+ for (IndexOfPdpEntries = 0; IndexOfPdpEntries < NumberOfPdpEntriesNeeded; IndexOfPdpEntries++, PageDirectoryPointerEntry++) {\r
+ //\r
+ // Each Directory Pointer entries points to a page of Page Directory entires.\r
+ // So allocate space for them and fill them in in the IndexOfPageDirectoryEntries loop.\r
+ // \r
+ PageDirectoryEntry = (VOID *) BigPageAddress;\r
+ BigPageAddress += SIZE_4KB;\r
+\r
+ //\r
+ // Fill in a Page Directory Pointer Entries\r
+ //\r
+ PageDirectoryPointerEntry->Uint64 = (UINT64)(UINTN)PageDirectoryEntry;\r
+ PageDirectoryPointerEntry->Bits.ReadWrite = 1;\r
+ PageDirectoryPointerEntry->Bits.Present = 1;\r
+\r
+ for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PageAddress += SIZE_2MB) {\r
+ //\r
+ // Fill in the Page Directory entries\r
+ //\r
+ PageDirectoryEntry->Uint64 = (UINT64)PageAddress;\r
+ PageDirectoryEntry->Bits.ReadWrite = 1;\r
+ PageDirectoryEntry->Bits.Present = 1;\r
+ PageDirectoryEntry->Bits.MustBe1 = 1;\r
+ }\r
+ }\r
\r
+ for (; IndexOfPdpEntries < 512; IndexOfPdpEntries++, PageDirectoryPointerEntry++) {\r
+ ZeroMem (\r
+ PageDirectoryPointerEntry,\r
+ sizeof(PAGE_MAP_AND_DIRECTORY_POINTER)\r
+ );\r
}\r
}\r
}\r
\r
//\r
// For the PML4 entries we are not using fill in a null entry.\r
- // For now we just copy the first entry.\r
//\r
for (; IndexOfPml4Entries < 512; IndexOfPml4Entries++, PageMapLevel4Entry++) {\r
- CopyMem (\r
- PageMapLevel4Entry,\r
- PageMap,\r
- sizeof (PAGE_MAP_AND_DIRECTORY_POINTER)\r
- );\r
+ ZeroMem (\r
+ PageMapLevel4Entry,\r
+ sizeof (PAGE_MAP_AND_DIRECTORY_POINTER)\r
+ );\r
}\r
}\r
\r
//\r
AsmWriteCr3 ((UINTN) PageTableAddress);\r
\r
+ //\r
+ // Disable interrupt of Debug timer, since the IDT table cannot work in long mode\r
+ //\r
+ SaveAndSetDebugTimerInterrupt (FALSE);\r
//\r
// Transfer to long mode\r
//\r
\r
}\r
\r
+/**\r
+ Locates the coalesce image entry point, and detects its machine type.\r
+\r
+ @param CoalesceImageEntryPoint Pointer to coalesce image entry point for output.\r
+ @param CoalesceImageMachineType Pointer to machine type of coalesce image.\r
+\r
+ @retval EFI_SUCCESS Coalesce image successfully located.\r
+ @retval Others Failed to locate the coalesce image.\r
+\r
+**/\r
+EFI_STATUS\r
+FindCapsuleCoalesceImage (\r
+ OUT EFI_PHYSICAL_ADDRESS *CoalesceImageEntryPoint,\r
+ OUT UINT16 *CoalesceImageMachineType\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN Instance;\r
+ EFI_PEI_LOAD_FILE_PPI *LoadFile;\r
+ EFI_PEI_FV_HANDLE VolumeHandle;\r
+ EFI_PEI_FILE_HANDLE FileHandle;\r
+ EFI_PHYSICAL_ADDRESS CoalesceImageAddress;\r
+ UINT64 CoalesceImageSize;\r
+ UINT32 AuthenticationState;\r
+\r
+ Instance = 0;\r
+\r
+ while (TRUE) {\r
+ Status = PeiServicesFfsFindNextVolume (Instance++, &VolumeHandle);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ Status = PeiServicesFfsFindFileByName (PcdGetPtr(PcdCapsuleCoalesceFile), VolumeHandle, &FileHandle);\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = PeiServicesLocatePpi (&gEfiPeiLoadFilePpiGuid, 0, NULL, (VOID **) &LoadFile);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ Status = LoadFile->LoadFile (\r
+ LoadFile,\r
+ FileHandle,\r
+ &CoalesceImageAddress,\r
+ &CoalesceImageSize,\r
+ CoalesceImageEntryPoint,\r
+ &AuthenticationState\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "Unable to find PE32 section in CapsuleRelocate image ffs %r!\n", Status));\r
+ return Status;\r
+ }\r
+ *CoalesceImageMachineType = PeCoffLoaderGetMachineType ((VOID *) (UINTN) CoalesceImageAddress);\r
+ break;\r
+ } else {\r
+ continue;\r
+ }\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+#endif\r
+\r
/**\r
Checks for the presence of capsule descriptors.\r
Get capsule descriptors from variable CapsuleUpdateData, CapsuleUpdateData1, CapsuleUpdateData2...\r
return EFI_SUCCESS;\r
}\r
\r
-/**\r
- Locates the coalesce image entry point, and detects its machine type.\r
-\r
- @param CoalesceImageEntryPoint Pointer to coalesce image entry point for output.\r
- @param CoalesceImageMachineType Pointer to machine type of coalesce image.\r
-\r
- @retval EFI_SUCCESS Coalesce image successfully located.\r
- @retval Others Failed to locate the coalesce image.\r
-\r
-**/\r
-EFI_STATUS\r
-FindCapsuleCoalesceImage (\r
- OUT EFI_PHYSICAL_ADDRESS *CoalesceImageEntryPoint,\r
- OUT UINT16 *CoalesceImageMachineType\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINTN Instance;\r
- EFI_PEI_LOAD_FILE_PPI *LoadFile;\r
- EFI_PEI_FV_HANDLE VolumeHandle;\r
- EFI_PEI_FILE_HANDLE FileHandle;\r
- EFI_PHYSICAL_ADDRESS CoalesceImageAddress;\r
- UINT64 CoalesceImageSize;\r
- UINT32 AuthenticationState;\r
-\r
- Instance = 0;\r
-\r
- while (TRUE) {\r
- Status = PeiServicesFfsFindNextVolume (Instance++, &VolumeHandle);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
- Status = PeiServicesFfsFindFileByName (PcdGetPtr(PcdCapsuleCoalesceFile), VolumeHandle, &FileHandle);\r
- if (!EFI_ERROR (Status)) {\r
- Status = PeiServicesLocatePpi (&gEfiPeiLoadFilePpiGuid, 0, NULL, (VOID **) &LoadFile);\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- Status = LoadFile->LoadFile (\r
- LoadFile,\r
- FileHandle,\r
- &CoalesceImageAddress,\r
- &CoalesceImageSize,\r
- CoalesceImageEntryPoint,\r
- &AuthenticationState\r
- );\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_ERROR, "Unable to find PE32 section in CapsuleRelocate image ffs %r!\n", Status));\r
- return Status;\r
- }\r
- *CoalesceImageMachineType = PeCoffLoaderGetMachineType ((VOID *) (UINTN) CoalesceImageAddress);\r
- break;\r
- } else {\r
- continue;\r
- }\r
- }\r
-\r
- return Status;\r
-}\r
-\r
/**\r
Gets the reserved long mode buffer.\r
\r
EFI_CAPSULE_PEIM_PRIVATE_DATA *PrivateData;\r
UINTN Size;\r
EFI_PHYSICAL_ADDRESS NewBuffer;\r
- UINT32 *DataPtr;\r
- UINT32 CapsuleNumber;\r
+ UINTN CapsuleNumber;\r
UINT32 Index;\r
EFI_PHYSICAL_ADDRESS BaseAddress;\r
UINT64 Length;\r
\r
- DataPtr = NULL;\r
- CapsuleNumber = 0;\r
PrivateData = (EFI_CAPSULE_PEIM_PRIVATE_DATA *) CapsuleBase;\r
if (PrivateData->Signature != EFI_CAPSULE_PEIM_PRIVATE_DATA_SIGNATURE) {\r
return EFI_VOLUME_CORRUPTED;\r
}\r
+ if (PrivateData->CapsuleAllImageSize >= MAX_ADDRESS) {\r
+ DEBUG ((EFI_D_ERROR, "CapsuleAllImageSize too big - 0x%lx\n", PrivateData->CapsuleAllImageSize));\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ if (PrivateData->CapsuleNumber >= MAX_ADDRESS) {\r
+ DEBUG ((EFI_D_ERROR, "CapsuleNumber too big - 0x%lx\n", PrivateData->CapsuleNumber));\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
//\r
// Capsule Number and Capsule Offset is in the tail of Capsule data.\r
//\r
- Size = (UINTN) PrivateData->CapsuleSize;\r
- DataPtr = (UINT32*)((UINTN)CapsuleBase + (UINTN)sizeof(EFI_CAPSULE_PEIM_PRIVATE_DATA)+ Size);\r
- DataPtr = (UINT32*)(((UINTN) DataPtr + sizeof(UINT32) - 1) & ~(sizeof (UINT32) - 1));\r
- CapsuleNumber = *DataPtr++;\r
+ Size = (UINTN)PrivateData->CapsuleAllImageSize;\r
+ CapsuleNumber = (UINTN)PrivateData->CapsuleNumber;\r
//\r
// Allocate the memory so that it gets preserved into DXE\r
//\r
//\r
// Copy to our new buffer for DXE\r
//\r
- DEBUG ((EFI_D_INFO, "Capsule copy from 0x%8X to 0x%8X with size 0x%8X\n", (UINTN) (PrivateData + 1), (UINTN) NewBuffer, Size));\r
- CopyMem ((VOID *) (UINTN) NewBuffer, (VOID *) (UINTN) (PrivateData + 1), Size);\r
+ DEBUG ((EFI_D_INFO, "Capsule copy from 0x%8X to 0x%8X with size 0x%8X\n", (UINTN)((UINT8 *)PrivateData + sizeof(EFI_CAPSULE_PEIM_PRIVATE_DATA) + (CapsuleNumber - 1) * sizeof(UINT64)), (UINTN) NewBuffer, Size));\r
+ CopyMem ((VOID *) (UINTN) NewBuffer, (VOID *) (UINTN) ((UINT8 *)PrivateData + sizeof(EFI_CAPSULE_PEIM_PRIVATE_DATA) + (CapsuleNumber - 1) * sizeof(UINT64)), Size);\r
//\r
// Check for test data pattern. If it is the test pattern, then we'll\r
// test it ans still create the HOB so that it can be used to verify\r
// Build the UEFI Capsule Hob for each capsule image.\r
//\r
for (Index = 0; Index < CapsuleNumber; Index ++) {\r
- BaseAddress = NewBuffer + DataPtr[Index];\r
+ BaseAddress = NewBuffer + PrivateData->CapsuleOffset[Index];\r
Length = ((EFI_CAPSULE_HEADER *)((UINTN) BaseAddress))->CapsuleImageSize;\r
\r
BuildCvHob (BaseAddress, Length);\r