]> git.proxmox.com Git - mirror_edk2.git/blobdiff - IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBios.c
IntelFrameworkModulePkg/LegacyBios: Use macro to enable/disable page 0
[mirror_edk2.git] / IntelFrameworkModulePkg / Csm / LegacyBiosDxe / LegacyBios.c
index c90231af07dcd2bb35a410e6efee4aaccc0ae269..fca08a8fa26d4be275576f8b6156290f96a9e5fc 100644 (file)
@@ -1,6 +1,6 @@
 /** @file\r
 \r
 /** @file\r
 \r
-Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2006 - 2017, 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
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions\r
@@ -29,6 +29,19 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 //\r
 LEGACY_BIOS_INSTANCE  mPrivateData;\r
 \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
 /**\r
   Do an AllocatePages () of type AllocateMaxAddress for EfiBootServicesCode\r
   memory.\r
@@ -132,7 +145,7 @@ LegacyBiosGetLegacyRegion (
      );\r
 \r
   if (Regs.X.AX == 0) {\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
     Status = EFI_SUCCESS;\r
   } else {\r
     Status = EFI_OUT_OF_RESOURCES;\r
@@ -661,6 +674,118 @@ GetPciInterfaceVersion (
   return PciInterfaceVersion;\r
 }\r
 \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
 /**\r
   Install Driver to produce Legacy BIOS protocol.\r
 \r
@@ -682,6 +807,7 @@ LegacyBiosInstall (
   LEGACY_BIOS_INSTANCE               *Private;\r
   EFI_TO_COMPATIBILITY16_INIT_TABLE  *EfiToLegacy16InitTable;\r
   EFI_PHYSICAL_ADDRESS               MemoryAddress;\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
   VOID                               *MemoryPtr;\r
   EFI_PHYSICAL_ADDRESS               MemoryAddressUnder1MB;\r
   UINTN                              Index;\r
@@ -695,6 +821,9 @@ LegacyBiosInstall (
   UINT32                             MemorySize;\r
   EFI_GCD_MEMORY_SPACE_DESCRIPTOR    Descriptor;\r
   UINT64                             Length;\r
   UINT32                             MemorySize;\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
   //\r
   // Load this driver's image to memory\r
@@ -704,6 +833,20 @@ LegacyBiosInstall (
     return Status;\r
   }\r
 \r
     return Status;\r
   }\r
 \r
+  //\r
+  // When UEFI Secure Boot is enabled, CSM module will not start any more.\r
+  //\r
+  SecureBoot = NULL;\r
+  GetEfiGlobalVariable2 (EFI_SECURE_BOOT_MODE_NAME, (VOID**)&SecureBoot, NULL);\r
+  if ((SecureBoot != NULL) && (*SecureBoot == SECURE_BOOT_MODE_ENABLE)) {\r
+    FreePool (SecureBoot);\r
+    return EFI_SECURITY_VIOLATION;\r
+  }\r
+  \r
+  if (SecureBoot != NULL) {\r
+    FreePool (SecureBoot);\r
+  }\r
+\r
   Private = &mPrivateData;\r
   ZeroMem (Private, sizeof (LEGACY_BIOS_INSTANCE));\r
 \r
   Private = &mPrivateData;\r
   ZeroMem (Private, sizeof (LEGACY_BIOS_INSTANCE));\r
 \r
@@ -843,8 +986,10 @@ LegacyBiosInstall (
   // Initialize region from 0x0000 to 4k. This initializes interrupt vector\r
   // range.\r
   //\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
   //\r
   // Allocate pages for OPROM usage\r
@@ -865,17 +1010,29 @@ LegacyBiosInstall (
   //\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
   //\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
   //\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
                MemStart,\r
                1,\r
     Status = AllocateLegacyMemory (\r
                AllocateAddress,\r
                MemStart,\r
                1,\r
-               &MemoryAddress\r
+               &StartAddress\r
                );\r
     if (!EFI_ERROR (Status)) {\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
       ZeroMem (MemoryPtr, 0x1000);\r
     } else {\r
       DEBUG ((EFI_D_ERROR, "WARNING: Allocate legacy memory fail for SCSI card - %x\n", MemStart));\r
@@ -971,16 +1128,51 @@ LegacyBiosInstall (
   //\r
   // Save Unexpected interrupt vector so can restore it just prior to boot\r
   //\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
   // 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
 \r
   //\r
   // Make a new handle and install the protocol\r