/** @file\r
\r
-Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2006 - 2018, 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
LEGACY_BIOS_INSTANCE mPrivateData;\r
\r
+//\r
+// The SMBIOS table in EfiRuntimeServicesData memory\r
+//\r
+VOID *mRuntimeSmbiosEntryPoint = NULL;\r
+\r
+//\r
+// The SMBIOS table in EfiReservedMemoryType memory\r
+//\r
+EFI_PHYSICAL_ADDRESS mReserveSmbiosEntryPoint = 0;\r
+EFI_PHYSICAL_ADDRESS mStructureTableAddress = 0;\r
+UINTN mStructureTablePages = 0;\r
+BOOLEAN mEndOfDxe = FALSE;\r
+\r
/**\r
- Do an AllocatePages () of type AllocateMaxAddress for EfiBootServicesCode\r
- memory.\r
+ Allocate memory for legacy usage.\r
\r
- @param AllocateType Allocated Legacy Memory Type\r
+ @param AllocateType The type of allocation to perform.\r
+ @param MemoryType The type of memory to allocate.\r
@param StartPageAddress Start address of range\r
@param Pages Number of pages to allocate\r
@param Result Result of allocation\r
EFI_STATUS\r
AllocateLegacyMemory (\r
IN EFI_ALLOCATE_TYPE AllocateType,\r
+ IN EFI_MEMORY_TYPE MemoryType,\r
IN EFI_PHYSICAL_ADDRESS StartPageAddress,\r
IN UINTN Pages,\r
OUT EFI_PHYSICAL_ADDRESS *Result\r
MemPage = (EFI_PHYSICAL_ADDRESS) (UINTN) StartPageAddress;\r
Status = gBS->AllocatePages (\r
AllocateType,\r
- EfiBootServicesCode,\r
+ MemoryType,\r
Pages,\r
&MemPage\r
);\r
);\r
\r
if (Regs.X.AX == 0) {\r
- *LegacyMemoryAddress = (VOID *) (UINTN) ((Regs.X.DS << 4) + Regs.X.BX);\r
+ *LegacyMemoryAddress = (VOID *) (((UINTN) Regs.X.DS << 4) + Regs.X.BX);\r
Status = EFI_SUCCESS;\r
} else {\r
Status = EFI_OUT_OF_RESOURCES;\r
return PciInterfaceVersion;\r
}\r
\r
+/**\r
+ Callback function to calculate SMBIOS table size, and allocate memory for SMBIOS table.\r
+ SMBIOS table will be copied into EfiReservedMemoryType memory in legacy boot path.\r
+\r
+ @param Event Event whose notification function is being invoked.\r
+ @param Context The pointer to the notification function's context,\r
+ which is implementation-dependent.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+InstallSmbiosEventCallback (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ SMBIOS_TABLE_ENTRY_POINT *EntryPointStructure;\r
+ \r
+ //\r
+ // Get SMBIOS table from EFI configuration table\r
+ //\r
+ Status = EfiGetSystemConfigurationTable (\r
+ &gEfiSmbiosTableGuid,\r
+ &mRuntimeSmbiosEntryPoint\r
+ );\r
+ if ((EFI_ERROR (Status)) || (mRuntimeSmbiosEntryPoint == NULL)) {\r
+ return;\r
+ }\r
+ \r
+ EntryPointStructure = (SMBIOS_TABLE_ENTRY_POINT *) mRuntimeSmbiosEntryPoint;\r
+\r
+ //\r
+ // Allocate memory for SMBIOS Entry Point Structure.\r
+ // CSM framework spec requires SMBIOS table below 4GB in EFI_TO_COMPATIBILITY16_BOOT_TABLE.\r
+ //\r
+ if (mReserveSmbiosEntryPoint == 0) {\r
+ //\r
+ // Entrypoint structure with fixed size is allocated only once.\r
+ //\r
+ mReserveSmbiosEntryPoint = SIZE_4GB - 1;\r
+ Status = gBS->AllocatePages (\r
+ AllocateMaxAddress,\r
+ EfiReservedMemoryType,\r
+ EFI_SIZE_TO_PAGES ((UINTN) (EntryPointStructure->EntryPointLength)),\r
+ &mReserveSmbiosEntryPoint\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ mReserveSmbiosEntryPoint = 0;\r
+ return;\r
+ }\r
+ DEBUG ((EFI_D_INFO, "Allocate memory for Smbios Entry Point Structure\n"));\r
+ }\r
+ \r
+ if ((mStructureTableAddress != 0) && \r
+ (mStructureTablePages < EFI_SIZE_TO_PAGES ((UINT32)EntryPointStructure->TableLength))) {\r
+ //\r
+ // If original buffer is not enough for the new SMBIOS table, free original buffer and re-allocate\r
+ //\r
+ gBS->FreePages (mStructureTableAddress, mStructureTablePages);\r
+ mStructureTableAddress = 0;\r
+ mStructureTablePages = 0;\r
+ DEBUG ((EFI_D_INFO, "Original size is not enough. Re-allocate the memory.\n"));\r
+ }\r
+ \r
+ if (mStructureTableAddress == 0) {\r
+ //\r
+ // Allocate reserved memory below 4GB.\r
+ // Smbios spec requires the structure table is below 4GB.\r
+ //\r
+ mStructureTableAddress = SIZE_4GB - 1;\r
+ mStructureTablePages = EFI_SIZE_TO_PAGES (EntryPointStructure->TableLength);\r
+ Status = gBS->AllocatePages (\r
+ AllocateMaxAddress,\r
+ EfiReservedMemoryType,\r
+ mStructureTablePages,\r
+ &mStructureTableAddress\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ gBS->FreePages (\r
+ mReserveSmbiosEntryPoint, \r
+ EFI_SIZE_TO_PAGES ((UINTN) (EntryPointStructure->EntryPointLength))\r
+ );\r
+ mReserveSmbiosEntryPoint = 0;\r
+ mStructureTableAddress = 0;\r
+ mStructureTablePages = 0;\r
+ return;\r
+ }\r
+ DEBUG ((EFI_D_INFO, "Allocate memory for Smbios Structure Table\n"));\r
+ }\r
+}\r
+\r
+/**\r
+ Callback function to toggle EndOfDxe status. NULL pointer detection needs\r
+ this status to decide if it's necessary to change attributes of page 0.\r
+\r
+ @param Event Event whose notification function is being invoked.\r
+ @param Context The pointer to the notification function's context,\r
+ which is implementation-dependent.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+ToggleEndOfDxeStatus (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ mEndOfDxe = TRUE;\r
+ return;\r
+}\r
+\r
/**\r
Install Driver to produce Legacy BIOS protocol.\r
\r
LEGACY_BIOS_INSTANCE *Private;\r
EFI_TO_COMPATIBILITY16_INIT_TABLE *EfiToLegacy16InitTable;\r
EFI_PHYSICAL_ADDRESS MemoryAddress;\r
+ EFI_PHYSICAL_ADDRESS EbdaReservedBaseAddress;\r
VOID *MemoryPtr;\r
EFI_PHYSICAL_ADDRESS MemoryAddressUnder1MB;\r
UINTN Index;\r
EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor;\r
UINT64 Length;\r
UINT8 *SecureBoot;\r
+ EFI_EVENT InstallSmbiosEvent;\r
+ EFI_EVENT EndOfDxeEvent;\r
\r
//\r
// Load this driver's image to memory\r
//\r
AllocateLegacyMemory (\r
AllocateAddress,\r
+ EfiReservedMemoryType,\r
0,\r
1,\r
&MemoryAddress\r
// Initialize region from 0x0000 to 4k. This initializes interrupt vector\r
// range.\r
//\r
- gBS->SetMem ((VOID *) ClearPtr, 0x400, INITIAL_VALUE_BELOW_1K);\r
- ZeroMem ((VOID *) ((UINTN)ClearPtr + 0x400), 0xC00);\r
+ ACCESS_PAGE0_CODE (\r
+ gBS->SetMem ((VOID *) ClearPtr, 0x400, INITIAL_VALUE_BELOW_1K);\r
+ ZeroMem ((VOID *) ((UINTN)ClearPtr + 0x400), 0xC00);\r
+ );\r
\r
//\r
// Allocate pages for OPROM usage\r
\r
Status = AllocateLegacyMemory (\r
AllocateAddress,\r
+ EfiReservedMemoryType,\r
CONVENTIONAL_MEMORY_TOP - MemorySize,\r
EFI_SIZE_TO_PAGES (MemorySize),\r
&MemoryAddress\r
//\r
// Allocate all 32k chunks from 0x60000 ~ 0x88000 for Legacy OPROMs that\r
// don't use PMM but look for zeroed memory. Note that various non-BBS\r
- // SCSIs expect different areas to be free\r
+ // OpROMs expect different areas to be free\r
+ //\r
+ EbdaReservedBaseAddress = MemoryAddress;\r
+ MemoryAddress = PcdGet32 (PcdOpromReservedMemoryBase);\r
+ MemorySize = PcdGet32 (PcdOpromReservedMemorySize);\r
+ //\r
+ // Check if base address and size for reserved memory are 4KB aligned.\r
+ //\r
+ ASSERT ((MemoryAddress & 0xFFF) == 0);\r
+ ASSERT ((MemorySize & 0xFFF) == 0);\r
+ //\r
+ // Check if the reserved memory is below EBDA reserved range.\r
//\r
- for (MemStart = 0x60000; MemStart < 0x88000; MemStart += 0x1000) {\r
+ ASSERT ((MemoryAddress < EbdaReservedBaseAddress) && ((MemoryAddress + MemorySize - 1) < EbdaReservedBaseAddress));\r
+ for (MemStart = MemoryAddress; MemStart < MemoryAddress + MemorySize; MemStart += 0x1000) {\r
Status = AllocateLegacyMemory (\r
AllocateAddress,\r
+ EfiBootServicesCode,\r
MemStart,\r
1,\r
- &MemoryAddress\r
+ &StartAddress\r
);\r
if (!EFI_ERROR (Status)) {\r
- MemoryPtr = (VOID *) ((UINTN) MemoryAddress);\r
+ MemoryPtr = (VOID *) ((UINTN) StartAddress);\r
ZeroMem (MemoryPtr, 0x1000);\r
} else {\r
DEBUG ((EFI_D_ERROR, "WARNING: Allocate legacy memory fail for SCSI card - %x\n", MemStart));\r
ASSERT ((MemorySize & 0xFFF) == 0); \r
Status = AllocateLegacyMemory (\r
AllocateMaxAddress,\r
+ EfiBootServicesCode,\r
CONVENTIONAL_MEMORY_TOP,\r
EFI_SIZE_TO_PAGES (MemorySize),\r
&MemoryAddressUnder1MB\r
//\r
Status = AllocateLegacyMemory (\r
AllocateMaxAddress,\r
+ EfiReservedMemoryType,\r
CONVENTIONAL_MEMORY_TOP,\r
(sizeof (LOW_MEMORY_THUNK) / EFI_PAGE_SIZE) + 2,\r
&MemoryAddress\r
// \r
Status = AllocateLegacyMemory (\r
AllocateMaxAddress,\r
+ EfiBootServicesCode,\r
0x1000000,\r
EFI_SIZE_TO_PAGES (MemorySize),\r
&MemoryAddress\r
// \r
Status = AllocateLegacyMemory (\r
AllocateMaxAddress,\r
+ EfiBootServicesCode,\r
0xFFFFFFFF,\r
EFI_SIZE_TO_PAGES (MemorySize),\r
&MemoryAddress\r
//\r
// Save Unexpected interrupt vector so can restore it just prior to boot\r
//\r
- BaseVectorMaster = (UINT32 *) (sizeof (UINT32) * PROTECTED_MODE_BASE_VECTOR_MASTER);\r
- Private->BiosUnexpectedInt = BaseVectorMaster[0];\r
- IntRedirCode = (UINT32) (UINTN) Private->IntThunk->InterruptRedirectionCode;\r
- for (Index = 0; Index < 8; Index++) {\r
- BaseVectorMaster[Index] = (EFI_SEGMENT (IntRedirCode + Index * 4) << 16) | EFI_OFFSET (IntRedirCode + Index * 4);\r
- }\r
+ ACCESS_PAGE0_CODE (\r
+ BaseVectorMaster = (UINT32 *) (sizeof (UINT32) * PROTECTED_MODE_BASE_VECTOR_MASTER);\r
+ Private->BiosUnexpectedInt = BaseVectorMaster[0];\r
+ IntRedirCode = (UINT32) (UINTN) Private->IntThunk->InterruptRedirectionCode;\r
+ for (Index = 0; Index < 8; Index++) {\r
+ BaseVectorMaster[Index] = (EFI_SEGMENT (IntRedirCode + Index * 4) << 16) | EFI_OFFSET (IntRedirCode + Index * 4);\r
+ }\r
+ );\r
+\r
//\r
// Save EFI value\r
//\r
Private->ThunkSeg = (UINT16) (EFI_SEGMENT (IntRedirCode));\r
+ \r
+ //\r
+ // Allocate reserved memory for SMBIOS table used in legacy boot if SMBIOS table exists\r
+ //\r
+ InstallSmbiosEventCallback (NULL, NULL);\r
+\r
+ //\r
+ // Create callback function to update the size of reserved memory after LegacyBiosDxe starts\r
+ //\r
+ Status = gBS->CreateEventEx (\r
+ EVT_NOTIFY_SIGNAL,\r
+ TPL_NOTIFY,\r
+ InstallSmbiosEventCallback,\r
+ NULL,\r
+ &gEfiSmbiosTableGuid,\r
+ &InstallSmbiosEvent\r
+ );\r
+ ASSERT_EFI_ERROR (Status); \r
+\r
+ //\r
+ // Create callback to update status of EndOfDxe, which is needed by NULL\r
+ // pointer detection\r
+ //\r
+ Status = gBS->CreateEventEx (\r
+ EVT_NOTIFY_SIGNAL,\r
+ TPL_NOTIFY,\r
+ ToggleEndOfDxeStatus,\r
+ NULL,\r
+ &gEfiEndOfDxeEventGroupGuid,\r
+ &EndOfDxeEvent\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
\r
//\r
// Make a new handle and install the protocol\r