]> git.proxmox.com Git - mirror_edk2.git/blobdiff - IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyPci.c
Call LegacyBiosInstallVgaRom to shadow Legacy VBIOS instead of LegacyBiosInstallPciRo...
[mirror_edk2.git] / IntelFrameworkModulePkg / Csm / LegacyBiosDxe / LegacyPci.c
index a53b57a681d0365563b6e748bc511aeae230ac89..5b1117eb1b42ad03d2f0b32f5d9889638391ca14 100644 (file)
@@ -1,6 +1,6 @@
 /** @file\r
 \r
-Copyright (c) 2006 - 2011, 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
@@ -304,14 +304,24 @@ GetPciLegacyRom (
   BackupImage   = NULL;\r
   RomHeader.Raw = *Rom;\r
   while (RomHeader.Generic->Signature == PCI_EXPANSION_ROM_HEADER_SIGNATURE) {\r
-    if (*ImageSize < \r
-        RomHeader.Raw - (UINT8 *) *Rom + RomHeader.Generic->PcirOffset + sizeof (PCI_DATA_STRUCTURE)\r
-        ) {\r
-      return EFI_NOT_FOUND;\r
+    if (RomHeader.Generic->PcirOffset == 0 ||\r
+        (RomHeader.Generic->PcirOffset & 3) !=0 ||\r
+        *ImageSize < RomHeader.Raw - (UINT8 *) *Rom + RomHeader.Generic->PcirOffset + sizeof (PCI_DATA_STRUCTURE)) {\r
+      break;\r
     }\r
 \r
     Pcir = (PCI_3_0_DATA_STRUCTURE *) (RomHeader.Raw + RomHeader.Generic->PcirOffset);\r
+    //\r
+    // Check signature in the PCI Data Structure.\r
+    //\r
+    if (Pcir->Signature != PCI_DATA_STRUCTURE_SIGNATURE) {\r
+      break;\r
+    }\r
 \r
+    if ((UINTN)(RomHeader.Raw - (UINT8 *) *Rom) + Pcir->ImageLength * 512 > *ImageSize) {\r
+      break;\r
+    }\r
+    \r
     if (Pcir->CodeType == PCI_CODE_TYPE_PCAT_IMAGE) {\r
       Match = FALSE;\r
       if (Pcir->VendorId == VendorId) {\r
@@ -1490,54 +1500,52 @@ UpdateBevBcvTable (
     }\r
   }\r
 \r
-  if (PciPtr >= (EFI_LEGACY_EXPANSION_ROM_HEADER *) ((UINTN) 0xc8000)) {\r
-    while (TRUE) {\r
-      Status    = FindNextPnpExpansionHeader (Private, Instance, &PnpPtr);\r
-      Instance  = NOT_FIRST_INSTANCE;\r
-      if (EFI_ERROR (Status)) {\r
-        break;\r
-      }\r
-      //\r
-      // There can be additional $PnP headers within the OPROM.\r
-      // Example: SCSI can have one per drive.\r
-      //\r
-      BbsTable[BbsIndex].BootPriority             = BBS_UNPRIORITIZED_ENTRY;\r
-      BbsTable[BbsIndex].DeviceType               = DeviceType;\r
-      BbsTable[BbsIndex].Bus                      = (UINT32) Bus;\r
-      BbsTable[BbsIndex].Device                   = (UINT32) Device;\r
-      BbsTable[BbsIndex].Function                 = (UINT32) Function;\r
-      BbsTable[BbsIndex].StatusFlags.OldPosition  = 0;\r
-      BbsTable[BbsIndex].StatusFlags.Reserved1    = 0;\r
-      BbsTable[BbsIndex].StatusFlags.Enabled      = 0;\r
-      BbsTable[BbsIndex].StatusFlags.Failed       = 0;\r
-      BbsTable[BbsIndex].StatusFlags.MediaPresent = 0;\r
-      BbsTable[BbsIndex].StatusFlags.Reserved2    = 0;\r
-      BbsTable[BbsIndex].Class                    = PnpPtr->Class;\r
-      BbsTable[BbsIndex].SubClass                 = PnpPtr->SubClass;\r
-      BbsTable[BbsIndex].DescStringOffset         = PnpPtr->ProductNamePointer;\r
-      BbsTable[BbsIndex].DescStringSegment        = mBbsRomSegment;\r
-      BbsTable[BbsIndex].MfgStringOffset          = PnpPtr->MfgPointer;\r
-      BbsTable[BbsIndex].MfgStringSegment         = mBbsRomSegment;\r
-      BbsTable[BbsIndex].BootHandlerSegment       = mBbsRomSegment;\r
-\r
-      //\r
-      // Have seen case where PXE base code have PnP expansion ROM\r
-      // header but no Bcv or Bev vectors.\r
-      //\r
-      if (PnpPtr->Bcv != 0) {\r
-        BbsTable[BbsIndex].BootHandlerOffset = PnpPtr->Bcv;\r
-        ++BbsIndex;\r
-      }\r
+  while (TRUE) {\r
+    Status    = FindNextPnpExpansionHeader (Private, Instance, &PnpPtr);\r
+    Instance  = NOT_FIRST_INSTANCE;\r
+    if (EFI_ERROR (Status)) {\r
+      break;\r
+    }\r
+    //\r
+    // There can be additional $PnP headers within the OPROM.\r
+    // Example: SCSI can have one per drive.\r
+    //\r
+    BbsTable[BbsIndex].BootPriority             = BBS_UNPRIORITIZED_ENTRY;\r
+    BbsTable[BbsIndex].DeviceType               = DeviceType;\r
+    BbsTable[BbsIndex].Bus                      = (UINT32) Bus;\r
+    BbsTable[BbsIndex].Device                   = (UINT32) Device;\r
+    BbsTable[BbsIndex].Function                 = (UINT32) Function;\r
+    BbsTable[BbsIndex].StatusFlags.OldPosition  = 0;\r
+    BbsTable[BbsIndex].StatusFlags.Reserved1    = 0;\r
+    BbsTable[BbsIndex].StatusFlags.Enabled      = 0;\r
+    BbsTable[BbsIndex].StatusFlags.Failed       = 0;\r
+    BbsTable[BbsIndex].StatusFlags.MediaPresent = 0;\r
+    BbsTable[BbsIndex].StatusFlags.Reserved2    = 0;\r
+    BbsTable[BbsIndex].Class                    = PnpPtr->Class;\r
+    BbsTable[BbsIndex].SubClass                 = PnpPtr->SubClass;\r
+    BbsTable[BbsIndex].DescStringOffset         = PnpPtr->ProductNamePointer;\r
+    BbsTable[BbsIndex].DescStringSegment        = mBbsRomSegment;\r
+    BbsTable[BbsIndex].MfgStringOffset          = PnpPtr->MfgPointer;\r
+    BbsTable[BbsIndex].MfgStringSegment         = mBbsRomSegment;\r
+    BbsTable[BbsIndex].BootHandlerSegment       = mBbsRomSegment;\r
+\r
+    //\r
+    // Have seen case where PXE base code have PnP expansion ROM\r
+    // header but no Bcv or Bev vectors.\r
+    //\r
+    if (PnpPtr->Bcv != 0) {\r
+      BbsTable[BbsIndex].BootHandlerOffset = PnpPtr->Bcv;\r
+      ++BbsIndex;\r
+    }\r
 \r
-      if (PnpPtr->Bev != 0) {\r
-        BbsTable[BbsIndex].BootHandlerOffset  = PnpPtr->Bev;\r
-        BbsTable[BbsIndex].DeviceType         = BBS_BEV_DEVICE;\r
-        ++BbsIndex;\r
-      }\r
+    if (PnpPtr->Bev != 0) {\r
+      BbsTable[BbsIndex].BootHandlerOffset  = PnpPtr->Bev;\r
+      BbsTable[BbsIndex].DeviceType         = BBS_BEV_DEVICE;\r
+      ++BbsIndex;\r
+    }\r
 \r
-      if ((PnpPtr == (LEGACY_PNP_EXPANSION_HEADER *) PciPtr) || (PnpPtr > (LEGACY_PNP_EXPANSION_HEADER *) RomEnd)) {\r
-        break;\r
-      }\r
+    if ((PnpPtr == (LEGACY_PNP_EXPANSION_HEADER *) PciPtr) || (PnpPtr > (LEGACY_PNP_EXPANSION_HEADER *) RomEnd)) {\r
+      break;\r
     }\r
   }\r
 \r
@@ -1707,6 +1715,20 @@ PciShadowRoms (
     if (!EFI_ERROR (Status)) {\r
       continue;\r
     }\r
+    \r
+    //\r
+    // If legacy VBIOS Oprom has not been dispatched before, install legacy VBIOS here.\r
+    //\r
+    if (IS_PCI_DISPLAY (&Pci) && Index == 0) {    \r
+      Status = LegacyBiosInstallVgaRom (Private);\r
+      //\r
+      // A return status of EFI_NOT_FOUND is considered valid (No EFI\r
+      // driver is controlling video).\r
+      //\r
+      ASSERT ((Status == EFI_SUCCESS) || (Status == EFI_NOT_FOUND));\r
+      continue;\r
+    }\r
+\r
     //\r
     // Install legacy ROM\r
     //\r
@@ -2294,6 +2316,13 @@ LegacyBiosInstallRom (
         \r
     if (EFI_ERROR (Status)) {\r
       DEBUG ((EFI_D_ERROR, "return LegacyBiosInstallRom(%d): EFI_OUT_OF_RESOURCES (no more space for OpROM)\n", __LINE__));\r
+      //\r
+      // Report Status Code to indicate that there is no enough space for OpROM\r
+      //\r
+      REPORT_STATUS_CODE (\r
+        EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
+        (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_EC_LEGACY_OPROM_NO_SPACE)\r
+        );\r
       return EFI_OUT_OF_RESOURCES;\r
     }\r
     InitAddress = (UINTN) PhysicalAddress;\r
@@ -2301,9 +2330,16 @@ LegacyBiosInstallRom (
     //   then test if there is enough space for its RT code\r
     //\r
     RuntimeAddress = Private->OptionRom;\r
-    if (RuntimeAddress + *RuntimeImageLength > mEndOpromShadowAddress) {\r
+    if (RuntimeAddress + *RuntimeImageLength > PcdGet32 (PcdEndOpromShadowAddress)) {\r
       DEBUG ((EFI_D_ERROR, "return LegacyBiosInstallRom(%d): EFI_OUT_OF_RESOURCES (no more space for OpROM)\n", __LINE__));\r
       gBS->FreePages (PhysicalAddress, EFI_SIZE_TO_PAGES (ImageSize));\r
+      //\r
+      // Report Status Code to indicate that there is no enough space for OpROM\r
+      //\r
+      REPORT_STATUS_CODE (\r
+        EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
+        (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_EC_LEGACY_OPROM_NO_SPACE)\r
+        );\r
       return EFI_OUT_OF_RESOURCES;\r
     }\r
   } else {\r
@@ -2312,8 +2348,15 @@ LegacyBiosInstallRom (
     //   test if there is enough space for its INIT code\r
     //\r
     InitAddress    = PCI_START_ADDRESS (Private->OptionRom);\r
-    if (InitAddress + ImageSize > mEndOpromShadowAddress) {\r
+    if (InitAddress + ImageSize > PcdGet32 (PcdEndOpromShadowAddress)) {\r
       DEBUG ((EFI_D_ERROR, "return LegacyBiosInstallRom(%d): EFI_OUT_OF_RESOURCES (no more space for OpROM)\n", __LINE__));\r
+      //\r
+      // Report Status Code to indicate that there is no enough space for OpROM\r
+      //\r
+      REPORT_STATUS_CODE (\r
+        EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
+        (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_EC_LEGACY_OPROM_NO_SPACE)\r
+        );\r
       return EFI_OUT_OF_RESOURCES;\r
     }\r
 \r
@@ -2370,7 +2413,7 @@ LegacyBiosInstallRom (
     //\r
     // Store current mode settings since PrepareToScanRom may change mode.\r
     //\r
-    VideoMode = *(UINT8 *) ((UINTN) 0x449);\r
+    VideoMode = *(UINT8 *) ((UINTN) (0x400 + BDA_VIDEO_MODE));\r
   }\r
   //\r
   // Notify the platform that we are about to scan the ROM\r
@@ -2510,9 +2553,14 @@ LegacyBiosInstallRom (
     //\r
     // Set mode settings since PrepareToScanRom may change mode\r
     //\r
-    Regs.H.AH = 0x00;\r
-    Regs.H.AL = VideoMode;\r
-    Private->LegacyBios.Int86 (&Private->LegacyBios, 0x10, &Regs);\r
+    if (VideoMode != *(UINT8 *) ((UINTN) (0x400 + BDA_VIDEO_MODE))) {\r
+      //\r
+      // The active video mode is changed, restore it to original mode.\r
+      //\r
+      Regs.H.AH = 0x00;\r
+      Regs.H.AL = VideoMode;\r
+      Private->LegacyBios.Int86 (&Private->LegacyBios, 0x10, &Regs);\r
+    }\r
   }\r
   //\r
   // Regs.X.AX from the adapter initializion is ignored since some adapters\r
@@ -2521,7 +2569,16 @@ LegacyBiosInstallRom (
   //\r
   // The ROM could have updated it's size so we need to read again.\r
   //\r
-  *RuntimeImageLength = ((EFI_LEGACY_EXPANSION_ROM_HEADER *) (RuntimeAddress))->Size512 * 512;\r
+  if (((EFI_LEGACY_EXPANSION_ROM_HEADER *) RuntimeAddress)->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {\r
+    //\r
+    // Now we check the signature (0xaa55) to judge whether the run-time code is truly generated by INIT function.\r
+    // If signature is not valid, that means the INIT function didn't copy the run-time code to RuntimeAddress.\r
+    //\r
+    *RuntimeImageLength = 0;\r
+  } else {\r
+    *RuntimeImageLength = ((EFI_LEGACY_EXPANSION_ROM_HEADER *) RuntimeAddress)->Size512 * 512;\r
+  }\r
+\r
   DEBUG ((EFI_D_INFO, " fsize = %x\n", *RuntimeImageLength));\r
 \r
   //\r
@@ -2849,7 +2906,7 @@ LegacyBiosInstallPciRom (
       return EFI_UNSUPPORTED;\r
     }\r
   } else {\r
-    if (*RomImage == NULL) {\r
+    if ((RomImage == NULL) || (*RomImage == NULL)) {\r
       //\r
       // If PciHandle is NULL, and no OpRom is to be associated\r
       //\r
@@ -2857,9 +2914,39 @@ LegacyBiosInstallPciRom (
       return EFI_UNSUPPORTED;\r
     }\r
 \r
+    if (!Private->VgaInstalled) {\r
+      //\r
+      // A return status of EFI_NOT_FOUND is considered valid (No EFI\r
+      // driver is controlling video.\r
+      //\r
+      mVgaInstallationInProgress  = TRUE;\r
+      Status                      = LegacyBiosInstallVgaRom (Private);\r
+      if (EFI_ERROR (Status)) {\r
+        if (Status != EFI_NOT_FOUND) {\r
+          mVgaInstallationInProgress = FALSE;\r
+          return Status;\r
+        }\r
+      } else {\r
+        mVgaInstallationInProgress = FALSE;\r
+      }\r
+    }\r
+\r
     LocalRomImage = *RomImage;\r
+    if (((PCI_EXPANSION_ROM_HEADER *) LocalRomImage)->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE ||\r
+        ((PCI_EXPANSION_ROM_HEADER *) LocalRomImage)->PcirOffset == 0 ||\r
+        (((PCI_EXPANSION_ROM_HEADER *) LocalRomImage)->PcirOffset & 3 ) != 0) {\r
+      mVgaInstallationInProgress = FALSE;\r
+      return EFI_UNSUPPORTED;\r
+    }\r
+    \r
     Pcir = (PCI_3_0_DATA_STRUCTURE *)\r
            ((UINT8 *) LocalRomImage + ((PCI_EXPANSION_ROM_HEADER *) LocalRomImage)->PcirOffset);\r
+\r
+    if (Pcir->Signature != PCI_DATA_STRUCTURE_SIGNATURE) {\r
+      mVgaInstallationInProgress = FALSE;\r
+      return EFI_UNSUPPORTED;\r
+    }\r
+\r
     ImageSize = Pcir->ImageLength * 512;\r
     if (Pcir->Length >= 0x1C) {\r
       OpromRevision = Pcir->Revision;\r