]> git.proxmox.com Git - mirror_edk2.git/blobdiff - IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyPci.c
IntelFrameworkModulePkg/KeyboardDxe: Use macro to enable/disable page 0
[mirror_edk2.git] / IntelFrameworkModulePkg / Csm / LegacyBiosDxe / LegacyPci.c
index a53b57a681d0365563b6e748bc511aeae230ac89..b10a9dcef6aa34be854f4f3a22a9761bb95b0ae5 100644 (file)
@@ -1,6 +1,6 @@
 /** @file\r
 \r
 /** @file\r
 \r
-Copyright (c) 2006 - 2011, 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
@@ -41,7 +41,7 @@ BOOLEAN                             mIgnoreBbsUpdateFlag;
 BOOLEAN                             mVgaInstallationInProgress  = FALSE;\r
 UINT32                              mRomCount                   = 0x00;\r
 ROM_INSTANCE_ENTRY                  mRomEntry[ROM_MAX_ENTRIES];\r
 BOOLEAN                             mVgaInstallationInProgress  = FALSE;\r
 UINT32                              mRomCount                   = 0x00;\r
 ROM_INSTANCE_ENTRY                  mRomEntry[ROM_MAX_ENTRIES];\r
-\r
+EDKII_IOMMU_PROTOCOL                *mIoMmu;\r
 \r
 /**\r
   Query shadowed legacy ROM parameters registered by RomShadow() previously.\r
 \r
 /**\r
   Query shadowed legacy ROM parameters registered by RomShadow() previously.\r
@@ -304,14 +304,24 @@ GetPciLegacyRom (
   BackupImage   = NULL;\r
   RomHeader.Raw = *Rom;\r
   while (RomHeader.Generic->Signature == PCI_EXPANSION_ROM_HEADER_SIGNATURE) {\r
   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
 \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
 \r
+    if (((UINTN)RomHeader.Raw - (UINTN)*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
     if (Pcir->CodeType == PCI_CODE_TYPE_PCAT_IMAGE) {\r
       Match = FALSE;\r
       if (Pcir->VendorId == VendorId) {\r
@@ -1188,7 +1198,7 @@ PciProgramAllInterruptLineRegisters (
                       &Supports\r
                       );\r
     if (!EFI_ERROR (Status)) {\r
                       &Supports\r
                       );\r
     if (!EFI_ERROR (Status)) {\r
-      Supports &= EFI_PCI_DEVICE_ENABLE;\r
+      Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;\r
       Status = PciIo->Attributes (\r
                         PciIo,\r
                         EfiPciIoAttributeOperationEnable,\r
       Status = PciIo->Attributes (\r
                         PciIo,\r
                         EfiPciIoAttributeOperationEnable,\r
@@ -1490,54 +1500,52 @@ UpdateBevBcvTable (
     }\r
   }\r
 \r
     }\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
 \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
 \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
     }\r
   }\r
 \r
@@ -1707,6 +1715,20 @@ PciShadowRoms (
     if (!EFI_ERROR (Status)) {\r
       continue;\r
     }\r
     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
     //\r
     // Install legacy ROM\r
     //\r
@@ -1750,7 +1772,7 @@ PciShadowRoms (
                           &Supports\r
                           );\r
         if (!EFI_ERROR (Status)) {\r
                           &Supports\r
                           );\r
         if (!EFI_ERROR (Status)) {\r
-          Supports &= EFI_PCI_DEVICE_ENABLE;\r
+          Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;\r
           Status = PciIo->Attributes (\r
                             PciIo,\r
                             EfiPciIoAttributeOperationEnable,\r
           Status = PciIo->Attributes (\r
                             PciIo,\r
                             EfiPciIoAttributeOperationEnable,\r
@@ -1790,7 +1812,7 @@ PciShadowRoms (
   @param  RomSize                Size of ROM Image\r
   @param  Flags                  Indicates if ROM found and if PC-AT.\r
 \r
   @param  RomSize                Size of ROM Image\r
   @param  Flags                  Indicates if ROM found and if PC-AT.\r
 \r
-  @retval EFI_SUCCESS            Legacy Option ROM availible for this device\r
+  @retval EFI_SUCCESS            Legacy Option ROM available for this device\r
   @retval EFI_UNSUPPORTED        Legacy Option ROM not supported.\r
 \r
 **/\r
   @retval EFI_UNSUPPORTED        Legacy Option ROM not supported.\r
 \r
 **/\r
@@ -1832,7 +1854,7 @@ LegacyBiosCheckPciRom (
     @param[out] OpromRevision          Revision of the PCI Rom\r
     @param[out] ConfigUtilityCodeHeaderPointer of Configuration Utility Code Header\r
 \r
     @param[out] OpromRevision          Revision of the PCI Rom\r
     @param[out] ConfigUtilityCodeHeaderPointer of Configuration Utility Code Header\r
 \r
-    @return EFI_SUCCESS            Legacy Option ROM availible for this device\r
+    @return EFI_SUCCESS            Legacy Option ROM available for this device\r
     @return EFI_ALREADY_STARTED    This device is already managed by its Oprom\r
     @return EFI_UNSUPPORTED        Legacy Option ROM not supported.\r
 \r
     @return EFI_ALREADY_STARTED    This device is already managed by its Oprom\r
     @return EFI_UNSUPPORTED        Legacy Option ROM not supported.\r
 \r
@@ -1857,6 +1879,7 @@ LegacyBiosCheckPciRomEx (
   PCI_TYPE00                      PciConfigHeader;\r
   VOID                            *LocalConfigUtilityCodeHeader;\r
 \r
   PCI_TYPE00                      PciConfigHeader;\r
   VOID                            *LocalConfigUtilityCodeHeader;\r
 \r
+  LocalConfigUtilityCodeHeader = NULL;\r
   *Flags = NO_ROM;\r
   Status = gBS->HandleProtocol (\r
                   PciHandle,\r
   *Flags = NO_ROM;\r
   Status = gBS->HandleProtocol (\r
                   PciHandle,\r
@@ -1872,7 +1895,7 @@ LegacyBiosCheckPciRomEx (
   //\r
   Status = IsLegacyRom (PciHandle);\r
   if (!EFI_ERROR (Status)) {\r
   //\r
   Status = IsLegacyRom (PciHandle);\r
   if (!EFI_ERROR (Status)) {\r
-    *Flags |= (ROM_FOUND | VALID_LEGACY_ROM);\r
+    *Flags |= (UINTN)(ROM_FOUND | VALID_LEGACY_ROM);\r
     return EFI_SUCCESS;\r
   }\r
   //\r
     return EFI_SUCCESS;\r
   }\r
   //\r
@@ -2164,8 +2187,8 @@ LegacyBiosInstallVgaRom (
                     &Supports\r
                     );\r
   if (!EFI_ERROR (Status)) {\r
                     &Supports\r
                     );\r
   if (!EFI_ERROR (Status)) {\r
-    Supports &= EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY | \\r
-                EFI_PCI_IO_ATTRIBUTE_VGA_IO | EFI_PCI_IO_ATTRIBUTE_VGA_IO_16;\r
+    Supports &= (UINT64)(EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY | \\r
+                         EFI_PCI_IO_ATTRIBUTE_VGA_IO | EFI_PCI_IO_ATTRIBUTE_VGA_IO_16);\r
     Status = PciIo->Attributes (\r
                       PciIo,\r
                       EfiPciIoAttributeOperationEnable,\r
     Status = PciIo->Attributes (\r
                       PciIo,\r
                       EfiPciIoAttributeOperationEnable,\r
@@ -2256,11 +2279,13 @@ LegacyBiosInstallRom (
   UINTN                 Function;\r
   EFI_IA32_REGISTER_SET Regs;\r
   UINT8                 VideoMode;\r
   UINTN                 Function;\r
   EFI_IA32_REGISTER_SET Regs;\r
   UINT8                 VideoMode;\r
+  UINT8                 OldVideoMode;\r
   EFI_TIME              BootTime;\r
   UINT32                *BdaPtr;\r
   UINT32                LocalTime;\r
   UINT32                StartBbsIndex;\r
   UINT32                EndBbsIndex;\r
   EFI_TIME              BootTime;\r
   UINT32                *BdaPtr;\r
   UINT32                LocalTime;\r
   UINT32                StartBbsIndex;\r
   UINT32                EndBbsIndex;\r
+  UINT32                MaxRomAddr;\r
   UINTN                 TempData;\r
   UINTN                 InitAddress;\r
   UINTN                 RuntimeAddress;\r
   UINTN                 TempData;\r
   UINTN                 InitAddress;\r
   UINTN                 RuntimeAddress;\r
@@ -2275,7 +2300,17 @@ LegacyBiosInstallRom (
   Device          = 0;\r
   Function        = 0;\r
   VideoMode       = 0;\r
   Device          = 0;\r
   Function        = 0;\r
   VideoMode       = 0;\r
+  OldVideoMode    = 0;\r
   PhysicalAddress = 0;\r
   PhysicalAddress = 0;\r
+  MaxRomAddr      = PcdGet32 (PcdEndOpromShadowAddress);\r
+\r
+  if ((Private->Legacy16Table->TableLength >= OFFSET_OF(EFI_COMPATIBILITY16_TABLE, HiPermanentMemoryAddress)) &&\r
+      (Private->Legacy16Table->UmaAddress != 0) && \r
+      (Private->Legacy16Table->UmaSize != 0) &&\r
+      (MaxRomAddr > (Private->Legacy16Table->UmaAddress))) {\r
+    MaxRomAddr = Private->Legacy16Table->UmaAddress;\r
+  }\r
+\r
 \r
   PciProgramAllInterruptLineRegisters (Private);\r
 \r
 \r
   PciProgramAllInterruptLineRegisters (Private);\r
 \r
@@ -2294,6 +2329,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
     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
       return EFI_OUT_OF_RESOURCES;\r
     }\r
     InitAddress = (UINTN) PhysicalAddress;\r
@@ -2301,9 +2343,16 @@ LegacyBiosInstallRom (
     //   then test if there is enough space for its RT code\r
     //\r
     RuntimeAddress = Private->OptionRom;\r
     //   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 > MaxRomAddr) {\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
       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
       return EFI_OUT_OF_RESOURCES;\r
     }\r
   } else {\r
@@ -2312,8 +2361,15 @@ LegacyBiosInstallRom (
     //   test if there is enough space for its INIT code\r
     //\r
     InitAddress    = PCI_START_ADDRESS (Private->OptionRom);\r
     //   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 > MaxRomAddr) {\r
       DEBUG ((EFI_D_ERROR, "return LegacyBiosInstallRom(%d): EFI_OUT_OF_RESOURCES (no more space for OpROM)\n", __LINE__));\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
       return EFI_OUT_OF_RESOURCES;\r
     }\r
 \r
@@ -2347,31 +2403,34 @@ LegacyBiosInstallRom (
   // 2. BBS compliants drives will not change 40:75 until boot time.\r
   // 3. Onboard IDE controllers will change 40:75\r
   //\r
   // 2. BBS compliants drives will not change 40:75 until boot time.\r
   // 3. Onboard IDE controllers will change 40:75\r
   //\r
-  LocalDiskStart = (UINT8) ((*(UINT8 *) ((UINTN) 0x475)) + 0x80);\r
-  if ((Private->Disk4075 + 0x80) < LocalDiskStart) {\r
-    //\r
-    // Update table since onboard IDE drives found\r
-    //\r
-    Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciSegment        = 0xff;\r
-    Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciBus            = 0xff;\r
-    Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciDevice         = 0xff;\r
-    Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciFunction       = 0xff;\r
-    Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].StartDriveNumber  = (UINT8) (Private->Disk4075 + 0x80);\r
-    Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].EndDriveNumber    = LocalDiskStart;\r
-    Private->LegacyEfiHddTableIndex ++;\r
-    Private->Disk4075 = (UINT8) (LocalDiskStart & 0x7f);\r
-    Private->DiskEnd  = LocalDiskStart;\r
-  }\r
+  ACCESS_PAGE0_CODE (\r
+    LocalDiskStart = (UINT8) ((*(UINT8 *) ((UINTN) 0x475)) + 0x80);\r
+    if ((Private->Disk4075 + 0x80) < LocalDiskStart) {\r
+      //\r
+      // Update table since onboard IDE drives found\r
+      //\r
+      Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciSegment        = 0xff;\r
+      Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciBus            = 0xff;\r
+      Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciDevice         = 0xff;\r
+      Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciFunction       = 0xff;\r
+      Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].StartDriveNumber  = (UINT8) (Private->Disk4075 + 0x80);\r
+      Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].EndDriveNumber    = LocalDiskStart;\r
+      Private->LegacyEfiHddTableIndex ++;\r
+      Private->Disk4075 = (UINT8) (LocalDiskStart & 0x7f);\r
+      Private->DiskEnd  = LocalDiskStart;\r
+    }\r
 \r
 \r
-  if (PciHandle != mVgaHandle) {\r
+    if (PciHandle != mVgaHandle) {\r
 \r
 \r
-    EnablePs2Keyboard ();\r
+      EnablePs2Keyboard ();\r
+\r
+      //\r
+      // Store current mode settings since PrepareToScanRom may change mode.\r
+      //\r
+      VideoMode = *(UINT8 *) ((UINTN) (0x400 + BDA_VIDEO_MODE));\r
+    }\r
+  );\r
 \r
 \r
-    //\r
-    // Store current mode settings since PrepareToScanRom may change mode.\r
-    //\r
-    VideoMode = *(UINT8 *) ((UINTN) 0x449);\r
-  }\r
   //\r
   // Notify the platform that we are about to scan the ROM\r
   //\r
   //\r
   // Notify the platform that we are about to scan the ROM\r
   //\r
@@ -2412,9 +2471,11 @@ LegacyBiosInstallRom (
   // Multiply result by 18.2 for number of ticks since midnight.\r
   // Use 182/10 to avoid floating point math.\r
   //\r
   // Multiply result by 18.2 for number of ticks since midnight.\r
   // Use 182/10 to avoid floating point math.\r
   //\r
-  LocalTime = (LocalTime * 182) / 10;\r
-  BdaPtr    = (UINT32 *) ((UINTN) 0x46C);\r
-  *BdaPtr   = LocalTime;\r
+  ACCESS_PAGE0_CODE (\r
+    LocalTime = (LocalTime * 182) / 10;\r
+    BdaPtr    = (UINT32 *) ((UINTN) 0x46C);\r
+    *BdaPtr   = LocalTime;\r
+  );\r
   \r
   //\r
   // Pass in handoff data\r
   \r
   //\r
   // Pass in handoff data\r
@@ -2510,9 +2571,18 @@ LegacyBiosInstallRom (
     //\r
     // Set mode settings since PrepareToScanRom may change mode\r
     //\r
     //\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
+    ACCESS_PAGE0_CODE ({\r
+      OldVideoMode = *(UINT8 *) ((UINTN) (0x400 + BDA_VIDEO_MODE));\r
+    });\r
+\r
+    if (VideoMode != OldVideoMode) {\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
   }\r
   //\r
   // Regs.X.AX from the adapter initializion is ignored since some adapters\r
@@ -2521,7 +2591,16 @@ LegacyBiosInstallRom (
   //\r
   // The ROM could have updated it's size so we need to read again.\r
   //\r
   //\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
   DEBUG ((EFI_D_INFO, " fsize = %x\n", *RuntimeImageLength));\r
 \r
   //\r
@@ -2536,7 +2615,9 @@ LegacyBiosInstallRom (
     }\r
   }\r
 \r
     }\r
   }\r
 \r
-  LocalDiskEnd = (UINT8) ((*(UINT8 *) ((UINTN) 0x475)) + 0x80);\r
+  ACCESS_PAGE0_CODE (\r
+    LocalDiskEnd = (UINT8) ((*(UINT8 *) ((UINTN) 0x475)) + 0x80);\r
+  );\r
   \r
   //\r
   // Allow platform to perform any required actions after the\r
   \r
   //\r
   // Allow platform to perform any required actions after the\r
@@ -2628,6 +2709,61 @@ Done:
   return Status;\r
 }\r
 \r
   return Status;\r
 }\r
 \r
+/**\r
+  Let IOMMU grant DMA access for the PCI device.\r
+\r
+  @param  PciHandle             The EFI handle for the PCI device.\r
+  @param  HostAddress           The system memory address to map to the PCI controller.\r
+  @param  NumberOfBytes         The number of bytes to map.\r
+\r
+  @retval EFI_SUCCESS  The DMA access is granted.\r
+**/\r
+EFI_STATUS\r
+IoMmuGrantAccess (\r
+  IN  EFI_HANDLE                        PciHandle,\r
+  IN  EFI_PHYSICAL_ADDRESS              HostAddress,\r
+  IN  UINTN                             NumberOfBytes\r
+  )\r
+{\r
+  EFI_PHYSICAL_ADDRESS            DeviceAddress;\r
+  VOID                            *Mapping;\r
+  EFI_STATUS                      Status;\r
+\r
+  if (PciHandle == NULL) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  Status = EFI_SUCCESS;\r
+  if (mIoMmu == NULL) {\r
+    gBS->LocateProtocol (&gEdkiiIoMmuProtocolGuid, NULL, (VOID **)&mIoMmu);\r
+  }\r
+  if (mIoMmu != NULL) {\r
+    Status = mIoMmu->Map (\r
+                       mIoMmu,\r
+                       EdkiiIoMmuOperationBusMasterCommonBuffer,\r
+                       (VOID *)(UINTN)HostAddress,\r
+                       &NumberOfBytes,\r
+                       &DeviceAddress,\r
+                       &Mapping\r
+                       );\r
+    if (EFI_ERROR(Status)) {\r
+      DEBUG ((DEBUG_ERROR, "LegacyPci - IoMmuMap - %r\n", Status));\r
+    } else {\r
+      ASSERT (DeviceAddress == HostAddress);\r
+      Status = mIoMmu->SetAttribute (\r
+                         mIoMmu,\r
+                         PciHandle,\r
+                         Mapping,\r
+                         EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE\r
+                         );\r
+      if (EFI_ERROR(Status)) {\r
+        DEBUG ((DEBUG_ERROR, "LegacyPci - IoMmuSetAttribute - %r\n", Status));\r
+      }\r
+    }\r
+  }\r
+  return Status;\r
+}\r
+\r
 /**\r
   Load a legacy PC-AT OPROM on the PciHandle device. Return information\r
   about how many disks were added by the OPROM and the shadow address and\r
 /**\r
   Load a legacy PC-AT OPROM on the PciHandle device. Return information\r
   about how many disks were added by the OPROM and the shadow address and\r
@@ -2849,7 +2985,7 @@ LegacyBiosInstallPciRom (
       return EFI_UNSUPPORTED;\r
     }\r
   } else {\r
       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
       //\r
       // If PciHandle is NULL, and no OpRom is to be associated\r
       //\r
@@ -2857,9 +2993,47 @@ LegacyBiosInstallPciRom (
       return EFI_UNSUPPORTED;\r
     }\r
 \r
       return EFI_UNSUPPORTED;\r
     }\r
 \r
+    Status = Private->LegacyBiosPlatform->GetPlatformHandle (\r
+                                            Private->LegacyBiosPlatform,\r
+                                            EfiGetPlatformVgaHandle,\r
+                                            0,\r
+                                            &HandleBuffer,\r
+                                            &HandleCount,\r
+                                            NULL\r
+                                            );\r
+    if ((!EFI_ERROR (Status)) && (!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
     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
     Pcir = (PCI_3_0_DATA_STRUCTURE *)\r
            ((UINT8 *) LocalRomImage + ((PCI_EXPANSION_ROM_HEADER *) LocalRomImage)->PcirOffset);\r
+\r
+    if ((Pcir->Signature != PCI_DATA_STRUCTURE_SIGNATURE) || (Pcir->CodeType != PCI_CODE_TYPE_PCAT_IMAGE)) {\r
+      mVgaInstallationInProgress = FALSE;\r
+      return EFI_UNSUPPORTED;\r
+    }\r
+\r
     ImageSize = Pcir->ImageLength * 512;\r
     if (Pcir->Length >= 0x1C) {\r
       OpromRevision = Pcir->Revision;\r
     ImageSize = Pcir->ImageLength * 512;\r
     if (Pcir->Length >= 0x1C) {\r
       OpromRevision = Pcir->Revision;\r
@@ -2872,6 +3046,21 @@ LegacyBiosInstallPciRom (
       RuntimeImageLength = Pcir->MaxRuntimeImageLength * 512;\r
     }\r
   }\r
       RuntimeImageLength = Pcir->MaxRuntimeImageLength * 512;\r
     }\r
   }\r
+\r
+  //\r
+  // Grant access for below 1M\r
+  // BDA/EBDA/LowPMM and scratch memory for OPROM.\r
+  //\r
+  IoMmuGrantAccess (PciHandle, 0, SIZE_1MB);\r
+  //\r
+  // Grant access for HiPmm\r
+  //\r
+  IoMmuGrantAccess (\r
+    PciHandle,\r
+    Private->IntThunk->EfiToLegacy16InitTable.HiPmmMemory,\r
+    Private->IntThunk->EfiToLegacy16InitTable.HiPmmMemorySizeInBytes\r
+    );\r
+\r
   //\r
   // Shadow and initialize the OpROM.\r
   //\r
   //\r
   // Shadow and initialize the OpROM.\r
   //\r