/** @file\r
\r
-Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2006 - 2013, 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
+\r
/**\r
Do an AllocatePages () of type AllocateMaxAddress for EfiBootServicesCode\r
memory.\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)) {\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 < (UINTN) EFI_SIZE_TO_PAGES (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
Install Driver to produce Legacy BIOS protocol.\r
\r
EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor;\r
UINT64 Length;\r
UINT8 *SecureBoot;\r
+ EFI_EVENT InstallSmbiosEvent;\r
\r
//\r
// Load this driver's image to memory\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
// Make a new handle and install the protocol\r
#\r
# This driver installs Legacy Bios Protocol to support CSM module work in EFI system.\r
#\r
-# Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>\r
+# Copyright (c) 2006 - 2013, 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
[Guids]\r
gEfiDiskInfoIdeInterfaceGuid # ALWAYS_CONSUMED\r
+ gEfiSmbiosTableGuid # ALWAYS_CONSUMED\r
gEfiLegacyBiosGuid # ALWAYS_PRODUCED\r
\r
[Guids.IA32]\r
\r
#include <FrameworkDxe.h>\r
#include <IndustryStandard/Pci.h>\r
+#include <IndustryStandard/SmBios.h>\r
\r
#include <Guid/SmBios.h>\r
#include <Guid/Acpi.h>\r
/** @file\r
\r
-Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2006 - 2013, 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
extern BBS_TABLE *mBbsTable;\r
\r
+extern VOID *mRuntimeSmbiosEntryPoint;\r
+extern EFI_PHYSICAL_ADDRESS mReserveSmbiosEntryPoint;\r
+extern EFI_PHYSICAL_ADDRESS mStructureTableAddress;\r
+\r
/**\r
Print the BBS Table.\r
\r
return EFI_SUCCESS;\r
}\r
\r
+/**\r
+ Copy SMBIOS table to EfiReservedMemoryType of memory for legacy boot.\r
+\r
+**/\r
+VOID\r
+CreateSmbiosTableInReservedMemory (\r
+ VOID\r
+ )\r
+{\r
+ SMBIOS_TABLE_ENTRY_POINT *EntryPointStructure;\r
+ \r
+ if ((mRuntimeSmbiosEntryPoint == NULL) || \r
+ (mReserveSmbiosEntryPoint == 0) || \r
+ (mStructureTableAddress == 0)) {\r
+ return;\r
+ }\r
+ \r
+ EntryPointStructure = (SMBIOS_TABLE_ENTRY_POINT *) mRuntimeSmbiosEntryPoint;\r
+ \r
+ //\r
+ // Copy SMBIOS Entry Point Structure\r
+ //\r
+ CopyMem (\r
+ (VOID *)(UINTN) mReserveSmbiosEntryPoint,\r
+ EntryPointStructure,\r
+ EntryPointStructure->EntryPointLength\r
+ );\r
+ \r
+ //\r
+ // Copy SMBIOS Structure Table into EfiReservedMemoryType memory\r
+ //\r
+ CopyMem (\r
+ (VOID *)(UINTN) mStructureTableAddress,\r
+ (VOID *)(UINTN) EntryPointStructure->TableAddress,\r
+ EntryPointStructure->TableLength\r
+ );\r
+ \r
+ //\r
+ // Update TableAddress in Entry Point Structure\r
+ //\r
+ EntryPointStructure = (SMBIOS_TABLE_ENTRY_POINT *)(UINTN) mReserveSmbiosEntryPoint;\r
+ EntryPointStructure->TableAddress = (UINT32)(UINTN) mStructureTableAddress;\r
+ \r
+ //\r
+ // Fixup checksums in the Entry Point Structure\r
+ //\r
+ EntryPointStructure->IntermediateChecksum = 0;\r
+ EntryPointStructure->EntryPointStructureChecksum = 0;\r
+\r
+ EntryPointStructure->IntermediateChecksum = \r
+ CalculateCheckSum8 (\r
+ (UINT8 *) EntryPointStructure + OFFSET_OF (SMBIOS_TABLE_ENTRY_POINT, IntermediateAnchorString), \r
+ EntryPointStructure->EntryPointLength - OFFSET_OF (SMBIOS_TABLE_ENTRY_POINT, IntermediateAnchorString)\r
+ );\r
+ EntryPointStructure->EntryPointStructureChecksum =\r
+ CalculateCheckSum8 ((UINT8 *) EntryPointStructure, EntryPointStructure->EntryPointLength);\r
+}\r
\r
/**\r
Assign drive number to legacy HDD drives prior to booting an EFI\r
EFI_HANDLE IdeController;\r
UINTN HandleCount;\r
EFI_HANDLE *HandleBuffer;\r
- VOID *SmbiosTable;\r
VOID *AcpiTable;\r
UINTN ShadowAddress;\r
UINT32 Granularity;\r
);\r
Private->Legacy16Table->E820Length = (UINT32) CopySize;\r
}\r
- //\r
- // Get SMBIOS and ACPI table pointers\r
- //\r
- SmbiosTable = NULL;\r
- EfiGetSystemConfigurationTable (\r
- &gEfiSmbiosTableGuid,\r
- &SmbiosTable\r
- );\r
+\r
//\r
// We do not ASSERT if SmbiosTable not found. It is possbile that a platform does not produce SmbiosTable.\r
//\r
- if (SmbiosTable == NULL) {\r
+ if (mReserveSmbiosEntryPoint == 0) {\r
DEBUG ((EFI_D_INFO, "Smbios table is not found!\n"));\r
}\r
- EfiToLegacy16BootTable->SmbiosTable = (UINT32)(UINTN)SmbiosTable;\r
+ CreateSmbiosTableInReservedMemory ();\r
+ EfiToLegacy16BootTable->SmbiosTable = (UINT32)(UINTN)mReserveSmbiosEntryPoint;\r
\r
AcpiTable = NULL;\r
Status = EfiGetSystemConfigurationTable (\r
PhysicalAddress = 0xffffffff;\r
Status = gBS->AllocatePages (\r
AllocateMaxAddress,\r
- EfiReservedMemoryType,\r
+ EfiRuntimeServicesData,\r
EFI_SIZE_TO_PAGES (EntryPointStructure->TableLength),\r
&PhysicalAddress\r
);\r
PhysicalAddress = 0xffffffff;\r
Status = gBS->AllocatePages (\r
AllocateMaxAddress,\r
- EfiReservedMemoryType,\r
+ EfiRuntimeServicesData,\r
EFI_SIZE_TO_PAGES (sizeof (SMBIOS_TABLE_ENTRY_POINT)),\r
&PhysicalAddress\r
);\r
DEBUG ((EFI_D_ERROR, "SmbiosDriverEntryPoint() could not allocate EntryPointStructure < 4GB\n"));\r
Status = gBS->AllocatePages (\r
AllocateAnyPages,\r
- EfiReservedMemoryType,\r
+ EfiRuntimeServicesData,\r
EFI_SIZE_TO_PAGES (sizeof (SMBIOS_TABLE_ENTRY_POINT)),\r
&PhysicalAddress\r
);\r
PhysicalAddress = 0xffffffff;\r
Status = gBS->AllocatePages (\r
AllocateMaxAddress,\r
- EfiReservedMemoryType,\r
+ EfiRuntimeServicesData,\r
1,\r
&PhysicalAddress\r
);\r