Signed-off-by: Li Elvin <elvin.li@intel.com> Reviewed-by: Yao Jiewen <jiewen.yao@intel.com> Reviewed-by: Ni Ruiyu <ruiyu.ni@intel.com> Reviewed-by: Gao Liming <liming.gao@intel.com> Reviewed-by: Tian Feng <feng.tian@intel.com> Reviewed-by: Fan Jeff <jeff.fan@intel.com> git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13889 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			2083 lines
		
	
	
		
			65 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			2083 lines
		
	
	
		
			65 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
| 
 | |
| Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
 | |
| 
 | |
| This program and the accompanying materials
 | |
| are licensed and made available under the terms and conditions
 | |
| of the BSD License which accompanies this distribution.  The
 | |
| full text of the license may be found at
 | |
| http://opensource.org/licenses/bsd-license.php
 | |
| 
 | |
| THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | |
| WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include "LegacyBiosInterface.h"
 | |
| #include <IndustryStandard/Pci.h>
 | |
| 
 | |
| #define BOOT_LEGACY_OS              0
 | |
| #define BOOT_EFI_OS                 1
 | |
| #define BOOT_UNCONVENTIONAL_DEVICE  2
 | |
| 
 | |
| UINT32              mLoadOptionsSize    = 0;
 | |
| UINTN               mBootMode           = BOOT_LEGACY_OS;
 | |
| VOID                *mLoadOptions       = NULL;
 | |
| BBS_BBS_DEVICE_PATH *mBbsDevicePathPtr  = NULL;
 | |
| BBS_BBS_DEVICE_PATH mBbsDevicePathNode;
 | |
| UDC_ATTRIBUTES      mAttributes         = { 0, 0, 0, 0 };
 | |
| UINTN               mBbsEntry           = 0;
 | |
| VOID                *mBeerData          = NULL;
 | |
| VOID                *mServiceAreaData   = NULL;
 | |
| UINT64              mLowWater           = 0xffffffffffffffffULL;
 | |
| 
 | |
| extern BBS_TABLE           *mBbsTable;
 | |
| 
 | |
| /**
 | |
|   Print the BBS Table.
 | |
| 
 | |
|   @param BbsTable   The BBS table.
 | |
| 
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| PrintBbsTable (
 | |
|   IN BBS_TABLE *BbsTable
 | |
|   )
 | |
| {
 | |
|   UINT16 Index;
 | |
|   UINT16 SubIndex;
 | |
|   CHAR8  *String;
 | |
| 
 | |
|   DEBUG ((EFI_D_INFO, "\n"));
 | |
|   DEBUG ((EFI_D_INFO, " NO  Prio bb/dd/ff cl/sc Type Stat segm:offs mfgs:mfgo dess:deso\n"));
 | |
|   DEBUG ((EFI_D_INFO, "=================================================================\n"));
 | |
|   for (Index = 0; Index < MAX_BBS_ENTRIES; Index++) {
 | |
|     //
 | |
|     // Filter
 | |
|     //
 | |
|     if (BbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) {
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     DEBUG ((
 | |
|       EFI_D_INFO,
 | |
|       " %02x: %04x %02x/%02x/%02x %02x/%02x %04x %04x",
 | |
|       (UINTN) Index,
 | |
|       (UINTN) BbsTable[Index].BootPriority,
 | |
|       (UINTN) BbsTable[Index].Bus,
 | |
|       (UINTN) BbsTable[Index].Device,
 | |
|       (UINTN) BbsTable[Index].Function,
 | |
|       (UINTN) BbsTable[Index].Class,
 | |
|       (UINTN) BbsTable[Index].SubClass,
 | |
|       (UINTN) BbsTable[Index].DeviceType,
 | |
|       (UINTN) * (UINT16 *) &BbsTable[Index].StatusFlags
 | |
|       ));
 | |
|     DEBUG ((
 | |
|       EFI_D_INFO,
 | |
|       " %04x:%04x %04x:%04x %04x:%04x",
 | |
|       (UINTN) BbsTable[Index].BootHandlerSegment,
 | |
|       (UINTN) BbsTable[Index].BootHandlerOffset,
 | |
|       (UINTN) BbsTable[Index].MfgStringSegment,
 | |
|       (UINTN) BbsTable[Index].MfgStringOffset,
 | |
|       (UINTN) BbsTable[Index].DescStringSegment,
 | |
|       (UINTN) BbsTable[Index].DescStringOffset
 | |
|       ));
 | |
| 
 | |
|     //
 | |
|     // Print DescString
 | |
|     //
 | |
|     String = (CHAR8 *)(UINTN)((BbsTable[Index].DescStringSegment << 4) + BbsTable[Index].DescStringOffset);
 | |
|     if (String != NULL) {
 | |
|       DEBUG ((EFI_D_INFO," ("));
 | |
|       for (SubIndex = 0; String[SubIndex] != 0; SubIndex++) {
 | |
|         DEBUG ((EFI_D_INFO, "%c", String[SubIndex]));
 | |
|       }
 | |
|       DEBUG ((EFI_D_INFO,")"));
 | |
|     }
 | |
|     DEBUG ((EFI_D_INFO,"\n"));
 | |
|   }
 | |
| 
 | |
|   DEBUG ((EFI_D_INFO, "\n"));
 | |
| 
 | |
|   return ;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Print the BBS Table.
 | |
| 
 | |
|   @param HddInfo   The HddInfo table.
 | |
| 
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| PrintHddInfo (
 | |
|   IN HDD_INFO *HddInfo
 | |
|   )
 | |
| {
 | |
|   UINTN Index;
 | |
| 
 | |
|   DEBUG ((EFI_D_INFO, "\n"));
 | |
|   for (Index = 0; Index < MAX_IDE_CONTROLLER; Index++) {
 | |
|     DEBUG ((EFI_D_INFO, "Index - %04x\n", Index));
 | |
|     DEBUG ((EFI_D_INFO, "  Status    - %04x\n", (UINTN)HddInfo[Index].Status));
 | |
|     DEBUG ((EFI_D_INFO, "  B/D/F     - %02x/%02x/%02x\n", (UINTN)HddInfo[Index].Bus, (UINTN)HddInfo[Index].Device, (UINTN)HddInfo[Index].Function));
 | |
|     DEBUG ((EFI_D_INFO, "  Command   - %04x\n", HddInfo[Index].CommandBaseAddress));
 | |
|     DEBUG ((EFI_D_INFO, "  Control   - %04x\n", HddInfo[Index].ControlBaseAddress));
 | |
|     DEBUG ((EFI_D_INFO, "  BusMaster - %04x\n", HddInfo[Index].BusMasterAddress));
 | |
|     DEBUG ((EFI_D_INFO, "  HddIrq    - %02x\n", HddInfo[Index].HddIrq));
 | |
|     DEBUG ((EFI_D_INFO, "  IdentifyDrive[0].Raw[0] - %x\n", HddInfo[Index].IdentifyDrive[0].Raw[0]));
 | |
|     DEBUG ((EFI_D_INFO, "  IdentifyDrive[1].Raw[0] - %x\n", HddInfo[Index].IdentifyDrive[1].Raw[0]));
 | |
|   }
 | |
| 
 | |
|   DEBUG ((EFI_D_INFO, "\n"));
 | |
| 
 | |
|   return ;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Print the PCI Interrupt Line and Interrupt Pin registers.
 | |
| **/
 | |
| VOID
 | |
| PrintPciInterruptRegister (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                  Status;
 | |
|   UINTN                       Index;
 | |
|   EFI_HANDLE                  *Handles;
 | |
|   UINTN                       HandleNum;
 | |
|   EFI_PCI_IO_PROTOCOL         *PciIo;
 | |
|   UINT8                       Interrupt[2];
 | |
|   UINTN                       Segment;
 | |
|   UINTN                       Bus;
 | |
|   UINTN                       Device;
 | |
|   UINTN                       Function;
 | |
| 
 | |
|   gBS->LocateHandleBuffer (
 | |
|          ByProtocol,
 | |
|          &gEfiPciIoProtocolGuid,
 | |
|          NULL,
 | |
|          &HandleNum,
 | |
|          &Handles
 | |
|          );
 | |
| 
 | |
|   Bus      = 0;
 | |
|   Device   = 0;
 | |
|   Function = 0;
 | |
| 
 | |
|   DEBUG ((EFI_D_INFO, "\n"));
 | |
|   DEBUG ((EFI_D_INFO, " bb/dd/ff interrupt line interrupt pin\n"));
 | |
|   DEBUG ((EFI_D_INFO, "======================================\n"));
 | |
|   for (Index = 0; Index < HandleNum; Index++) {
 | |
|     Status = gBS->HandleProtocol (Handles[Index], &gEfiPciIoProtocolGuid, (VOID **) &PciIo);
 | |
|     if (!EFI_ERROR (Status)) {
 | |
|       Status = PciIo->Pci.Read (
 | |
|                             PciIo,
 | |
|                             EfiPciIoWidthUint8,
 | |
|                             PCI_INT_LINE_OFFSET,
 | |
|                             2,
 | |
|                             Interrupt
 | |
|                             );
 | |
|     }
 | |
|     if (!EFI_ERROR (Status)) {
 | |
|       Status = PciIo->GetLocation (
 | |
|                         PciIo,
 | |
|                         &Segment,
 | |
|                         &Bus,
 | |
|                         &Device,
 | |
|                         &Function
 | |
|                         );
 | |
|     }
 | |
|     if (!EFI_ERROR (Status)) {
 | |
|       DEBUG ((EFI_D_INFO, " %02x/%02x/%02x 0x%02x           0x%02x\n",
 | |
|               Bus, Device, Function, Interrupt[0], Interrupt[1]));
 | |
|     }
 | |
|   }
 | |
|   DEBUG ((EFI_D_INFO, "\n"));
 | |
| 
 | |
|   if (Handles != NULL) {
 | |
|     FreePool (Handles);
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Identify drive data must be updated to actual parameters before boot.
 | |
| 
 | |
|   @param  IdentifyDriveData       ATA Identify Data
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| UpdateIdentifyDriveData (
 | |
|   IN  UINT8     *IdentifyDriveData
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Update SIO data.
 | |
| 
 | |
|   @param  Private                 Legacy BIOS Instance data
 | |
| 
 | |
|   @retval EFI_SUCCESS             Removable media not present
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| UpdateSioData (
 | |
|   IN  LEGACY_BIOS_INSTANCE      *Private
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                          Status;
 | |
|   UINTN                               Index;
 | |
|   UINTN                               Index1;
 | |
|   UINT8                               LegacyInterrupts[16];
 | |
|   EFI_LEGACY_IRQ_ROUTING_ENTRY        *RoutingTable;
 | |
|   UINTN                               RoutingTableEntries;
 | |
|   EFI_LEGACY_IRQ_PRIORITY_TABLE_ENTRY *IrqPriorityTable;
 | |
|   UINTN                               NumberPriorityEntries;
 | |
|   EFI_TO_COMPATIBILITY16_BOOT_TABLE   *EfiToLegacy16BootTable;
 | |
|   UINT8                               HddIrq;
 | |
|   UINT16                              LegacyInt;
 | |
|   UINT16                              LegMask;
 | |
|   UINT32                              Register;
 | |
|   UINTN                               HandleCount;
 | |
|   EFI_HANDLE                          *HandleBuffer;
 | |
|   EFI_ISA_IO_PROTOCOL                 *IsaIo;
 | |
| 
 | |
|   LegacyInt               = 0;
 | |
|   HandleBuffer            = NULL;
 | |
| 
 | |
|   EfiToLegacy16BootTable  = &Private->IntThunk->EfiToLegacy16BootTable;
 | |
|   LegacyBiosBuildSioData (Private);
 | |
|   SetMem (LegacyInterrupts, sizeof (LegacyInterrupts), 0);
 | |
| 
 | |
|   //
 | |
|   // Create list of legacy interrupts.
 | |
|   //
 | |
|   for (Index = 0; Index < 4; Index++) {
 | |
|     LegacyInterrupts[Index] = EfiToLegacy16BootTable->SioData.Serial[Index].Irq;
 | |
|   }
 | |
| 
 | |
|   for (Index = 4; Index < 7; Index++) {
 | |
|     LegacyInterrupts[Index] = EfiToLegacy16BootTable->SioData.Parallel[Index - 4].Irq;
 | |
|   }
 | |
| 
 | |
|   LegacyInterrupts[7] = EfiToLegacy16BootTable->SioData.Floppy.Irq;
 | |
| 
 | |
|   //
 | |
|   // Get Legacy Hdd IRQs. If native mode treat as PCI
 | |
|   //
 | |
|   for (Index = 0; Index < 2; Index++) {
 | |
|     HddIrq = EfiToLegacy16BootTable->HddInfo[Index].HddIrq;
 | |
|     if ((HddIrq != 0) && ((HddIrq == 15) || (HddIrq == 14))) {
 | |
|       LegacyInterrupts[Index + 8] = HddIrq;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   Private->LegacyBiosPlatform->GetRoutingTable (
 | |
|                                 Private->LegacyBiosPlatform,
 | |
|                                 (VOID *) &RoutingTable,
 | |
|                                 &RoutingTableEntries,
 | |
|                                 NULL,
 | |
|                                 NULL,
 | |
|                                 (VOID **) &IrqPriorityTable,
 | |
|                                 &NumberPriorityEntries
 | |
|                                 );
 | |
|   //
 | |
|   // Remove legacy interrupts from the list of PCI interrupts available.
 | |
|   //
 | |
|   for (Index = 0; Index <= 0x0b; Index++) {
 | |
|     for (Index1 = 0; Index1 <= NumberPriorityEntries; Index1++) {
 | |
|       if (LegacyInterrupts[Index] != 0) {
 | |
|         LegacyInt = (UINT16) (LegacyInt | (1 << LegacyInterrupts[Index]));
 | |
|         if (LegacyInterrupts[Index] == IrqPriorityTable[Index1].Irq) {
 | |
|           IrqPriorityTable[Index1].Used = LEGACY_USED;
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   Private->Legacy8259->GetMask (
 | |
|                         Private->Legacy8259,
 | |
|                         &LegMask,
 | |
|                         NULL,
 | |
|                         NULL,
 | |
|                         NULL
 | |
|                         );
 | |
| 
 | |
|   //
 | |
|   // Set SIO interrupts and disable mouse. Let mouse driver
 | |
|   // re-enable it.
 | |
|   //
 | |
|   LegMask = (UINT16) ((LegMask &~LegacyInt) | 0x1000);
 | |
|   Private->Legacy8259->SetMask (
 | |
|                         Private->Legacy8259,
 | |
|                         &LegMask,
 | |
|                         NULL,
 | |
|                         NULL,
 | |
|                         NULL
 | |
|                         );
 | |
| 
 | |
|   //
 | |
|   // Disable mouse in keyboard controller
 | |
|   //
 | |
|   Register = 0xA7;
 | |
|   Status = gBS->LocateHandleBuffer (
 | |
|                   ByProtocol,
 | |
|                   &gEfiIsaIoProtocolGuid,
 | |
|                   NULL,
 | |
|                   &HandleCount,
 | |
|                   &HandleBuffer
 | |
|                   );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   for (Index = 0; Index < HandleCount; Index++) {
 | |
|     Status = gBS->HandleProtocol (
 | |
|                     HandleBuffer[Index],
 | |
|                     &gEfiIsaIoProtocolGuid,
 | |
|                     (VOID **) &IsaIo
 | |
|                     );
 | |
|     ASSERT_EFI_ERROR (Status);
 | |
|     IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUint8, 0x64, 1, &Register);
 | |
| 
 | |
|   }
 | |
| 
 | |
|   if (HandleBuffer != NULL) {
 | |
|     FreePool (HandleBuffer);
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| 
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Identify drive data must be updated to actual parameters before boot.
 | |
|   This requires updating the checksum, if it exists.
 | |
| 
 | |
|   @param  IdentifyDriveData       ATA Identify Data
 | |
|   @param  Checksum                checksum of the ATA Identify Data
 | |
| 
 | |
|   @retval EFI_SUCCESS             checksum calculated
 | |
|   @retval EFI_SECURITY_VIOLATION  IdentifyData invalid
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| CalculateIdentifyDriveChecksum (
 | |
|   IN  UINT8     *IdentifyDriveData,
 | |
|   OUT UINT8     *Checksum
 | |
|   )
 | |
| {
 | |
|   UINTN Index;
 | |
|   UINT8 LocalChecksum;
 | |
|   LocalChecksum = 0;
 | |
|   *Checksum     = 0;
 | |
|   if (IdentifyDriveData[510] != 0xA5) {
 | |
|     return EFI_SECURITY_VIOLATION;
 | |
|   }
 | |
| 
 | |
|   for (Index = 0; Index < 512; Index++) {
 | |
|     LocalChecksum = (UINT8) (LocalChecksum + IdentifyDriveData[Index]);
 | |
|   }
 | |
| 
 | |
|   *Checksum = LocalChecksum;
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Identify drive data must be updated to actual parameters before boot.
 | |
| 
 | |
|   @param  IdentifyDriveData       ATA Identify Data
 | |
| 
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| UpdateIdentifyDriveData (
 | |
|   IN  UINT8     *IdentifyDriveData
 | |
|   )
 | |
| {
 | |
|   UINT16          NumberCylinders;
 | |
|   UINT16          NumberHeads;
 | |
|   UINT16          NumberSectorsTrack;
 | |
|   UINT32          CapacityInSectors;
 | |
|   UINT8           OriginalChecksum;
 | |
|   UINT8           FinalChecksum;
 | |
|   EFI_STATUS      Status;
 | |
|   ATAPI_IDENTIFY  *ReadInfo;
 | |
| 
 | |
|   //
 | |
|   // Status indicates if Integrity byte is correct. Checksum should be
 | |
|   // 0 if valid.
 | |
|   //
 | |
|   ReadInfo  = (ATAPI_IDENTIFY *) IdentifyDriveData;
 | |
|   Status    = CalculateIdentifyDriveChecksum (IdentifyDriveData, &OriginalChecksum);
 | |
|   if (OriginalChecksum != 0) {
 | |
|     Status = EFI_SECURITY_VIOLATION;
 | |
|   }
 | |
|   //
 | |
|   // If NumberCylinders = 0 then do data(Controller present but don drive attached).
 | |
|   //
 | |
|   NumberCylinders = ReadInfo->Raw[1];
 | |
|   if (NumberCylinders != 0) {
 | |
|     ReadInfo->Raw[54]   = NumberCylinders;
 | |
| 
 | |
|     NumberHeads         = ReadInfo->Raw[3];
 | |
|     ReadInfo->Raw[55]   = NumberHeads;
 | |
| 
 | |
|     NumberSectorsTrack  = ReadInfo->Raw[6];
 | |
|     ReadInfo->Raw[56]   = NumberSectorsTrack;
 | |
| 
 | |
|     //
 | |
|     // Copy Multisector info and set valid bit.
 | |
|     //
 | |
|     ReadInfo->Raw[59] = (UINT16) (ReadInfo->Raw[47] + 0x100);
 | |
|     CapacityInSectors = (UINT32) ((UINT32) (NumberCylinders) * (UINT32) (NumberHeads) * (UINT32) (NumberSectorsTrack));
 | |
|     ReadInfo->Raw[57] = (UINT16) (CapacityInSectors >> 16);
 | |
|     ReadInfo->Raw[58] = (UINT16) (CapacityInSectors & 0xffff);
 | |
|     if (Status == EFI_SUCCESS) {
 | |
|       //
 | |
|       // Forece checksum byte to 0 and get new checksum.
 | |
|       //
 | |
|       ReadInfo->Raw[255] &= 0xff;
 | |
|       CalculateIdentifyDriveChecksum (IdentifyDriveData, &FinalChecksum);
 | |
| 
 | |
|       //
 | |
|       // Force new checksum such that sum is 0.
 | |
|       //
 | |
|       FinalChecksum = (UINT8) ((UINT8)0 - FinalChecksum);
 | |
|       ReadInfo->Raw[255] = (UINT16) (ReadInfo->Raw[255] | (FinalChecksum << 8));
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Identify drive data must be updated to actual parameters before boot.
 | |
|   Do for all drives.
 | |
| 
 | |
|   @param  Private                 Legacy BIOS Instance data
 | |
| 
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| UpdateAllIdentifyDriveData (
 | |
|   IN LEGACY_BIOS_INSTANCE                 *Private
 | |
|   )
 | |
| {
 | |
|   UINTN     Index;
 | |
|   HDD_INFO  *HddInfo;
 | |
| 
 | |
|   HddInfo = &Private->IntThunk->EfiToLegacy16BootTable.HddInfo[0];
 | |
| 
 | |
|   for (Index = 0; Index < MAX_IDE_CONTROLLER; Index++) {
 | |
|     //
 | |
|     // Each controller can have 2 devices. Update for each device
 | |
|     //
 | |
|     if ((HddInfo[Index].Status & HDD_MASTER_IDE) != 0) {
 | |
|       UpdateIdentifyDriveData ((UINT8 *) (&HddInfo[Index].IdentifyDrive[0].Raw[0]));
 | |
|     }
 | |
| 
 | |
|     if ((HddInfo[Index].Status & HDD_SLAVE_IDE) != 0) {
 | |
|       UpdateIdentifyDriveData ((UINT8 *) (&HddInfo[Index].IdentifyDrive[1].Raw[0]));
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Enable ide controller.  This gets disabled when LegacyBoot.c is about
 | |
|   to run the Option ROMs.
 | |
| 
 | |
|   @param  Private        Legacy BIOS Instance data
 | |
| 
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| EnableIdeController (
 | |
|   IN LEGACY_BIOS_INSTANCE              *Private
 | |
|   )
 | |
| {
 | |
|   EFI_PCI_IO_PROTOCOL *PciIo;
 | |
|   EFI_STATUS          Status;
 | |
|   EFI_HANDLE          IdeController;
 | |
|   UINT8               ByteBuffer;
 | |
|   UINTN               HandleCount;
 | |
|   EFI_HANDLE          *HandleBuffer;
 | |
| 
 | |
|   Status = Private->LegacyBiosPlatform->GetPlatformHandle (
 | |
|                                           Private->LegacyBiosPlatform,
 | |
|                                           EfiGetPlatformIdeHandle,
 | |
|                                           0,
 | |
|                                           &HandleBuffer,
 | |
|                                           &HandleCount,
 | |
|                                           NULL
 | |
|                                           );
 | |
|   if (!EFI_ERROR (Status)) {
 | |
|     IdeController = HandleBuffer[0];
 | |
|     Status = gBS->HandleProtocol (
 | |
|                     IdeController,
 | |
|                     &gEfiPciIoProtocolGuid,
 | |
|                     (VOID **) &PciIo
 | |
|                     );
 | |
|     ByteBuffer = 0x1f;
 | |
|     if (!EFI_ERROR (Status)) {
 | |
|       PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x04, 1, &ByteBuffer);
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Enable ide controller.  This gets disabled when LegacyBoot.c is about
 | |
|   to run the Option ROMs.
 | |
| 
 | |
|   @param  Private                 Legacy BIOS Instance data
 | |
| 
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| EnableAllControllers (
 | |
|   IN LEGACY_BIOS_INSTANCE              *Private
 | |
|   )
 | |
| {
 | |
|   UINTN               HandleCount;
 | |
|   EFI_HANDLE          *HandleBuffer;
 | |
|   UINTN               Index;
 | |
|   EFI_PCI_IO_PROTOCOL *PciIo;
 | |
|   PCI_TYPE01          PciConfigHeader;
 | |
|   EFI_STATUS          Status;
 | |
| 
 | |
|   //
 | |
|   //
 | |
|   //
 | |
|   EnableIdeController (Private);
 | |
| 
 | |
|   //
 | |
|   // Assumption is table is built from low bus to high bus numbers.
 | |
|   //
 | |
|   Status = gBS->LocateHandleBuffer (
 | |
|                   ByProtocol,
 | |
|                   &gEfiPciIoProtocolGuid,
 | |
|                   NULL,
 | |
|                   &HandleCount,
 | |
|                   &HandleBuffer
 | |
|                   );
 | |
|   ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|   for (Index = 0; Index < HandleCount; Index++) {
 | |
|     Status = gBS->HandleProtocol (
 | |
|                     HandleBuffer[Index],
 | |
|                     &gEfiPciIoProtocolGuid,
 | |
|                     (VOID **) &PciIo
 | |
|                     );
 | |
|     ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|     PciIo->Pci.Read (
 | |
|                 PciIo,
 | |
|                 EfiPciIoWidthUint32,
 | |
|                 0,
 | |
|                 sizeof (PciConfigHeader) / sizeof (UINT32),
 | |
|                 &PciConfigHeader
 | |
|                 );
 | |
| 
 | |
|     //
 | |
|     // We do not enable PPB here. This is for HotPlug Consideration.
 | |
|     // The Platform HotPlug Driver is responsible for Padding enough hot plug
 | |
|     // resources. It is also responsible for enable this bridge. If it
 | |
|     // does not pad it. It will cause some early Windows fail to installation.
 | |
|     // If the platform driver does not pad resource for PPB, PPB should be in
 | |
|     // un-enabled state to let Windows know that this PPB is not configured by
 | |
|     // BIOS. So Windows will allocate default resource for PPB.
 | |
|     //
 | |
|     // The reason for why we enable the command register is:
 | |
|     // The CSM will use the IO bar to detect some IRQ status, if the command
 | |
|     // is disabled, the IO resource will be out of scope.
 | |
|     // For example:
 | |
|     // We installed a legacy IRQ handle for a PCI IDE controller. When IRQ
 | |
|     // comes up, the handle will check the IO space to identify is the
 | |
|     // controller generated the IRQ source.
 | |
|     // If the IO command is not enabled, the IRQ handler will has wrong
 | |
|     // information. It will cause IRQ storm when the correctly IRQ handler fails
 | |
|     // to run.
 | |
|     //
 | |
|     if (!(IS_PCI_VGA (&PciConfigHeader)     ||
 | |
|           IS_PCI_OLD_VGA (&PciConfigHeader) ||
 | |
|           IS_PCI_IDE (&PciConfigHeader)     ||
 | |
|           IS_PCI_P2P (&PciConfigHeader)     ||
 | |
|           IS_PCI_P2P_SUB (&PciConfigHeader) ||
 | |
|           IS_PCI_LPC (&PciConfigHeader)     )) {
 | |
| 
 | |
|       PciConfigHeader.Hdr.Command |= 0x1f;
 | |
| 
 | |
|       PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 4, 1, &PciConfigHeader.Hdr.Command);
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   The following routines are identical in operation, so combine
 | |
|   for code compaction:
 | |
|   EfiGetPlatformBinaryGetMpTable
 | |
|   EfiGetPlatformBinaryGetOemIntData
 | |
|   EfiGetPlatformBinaryGetOem32Data
 | |
|   EfiGetPlatformBinaryGetOem16Data
 | |
| 
 | |
|   @param  This                    Protocol instance pointer.
 | |
|   @param  Id                      Table/Data identifier
 | |
| 
 | |
|   @retval EFI_SUCCESS             Success
 | |
|   @retval EFI_INVALID_PARAMETER   Invalid ID
 | |
|   @retval EFI_OUT_OF_RESOURCES    no resource to get data or table
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| LegacyGetDataOrTable (
 | |
|   IN EFI_LEGACY_BIOS_PROTOCOL         *This,
 | |
|   IN EFI_GET_PLATFORM_INFO_MODE       Id
 | |
|   )
 | |
| {
 | |
|   VOID                              *Table;
 | |
|   UINT32                            TablePtr;
 | |
|   UINTN                             TableSize;
 | |
|   UINTN                             Alignment;
 | |
|   UINTN                             Location;
 | |
|   EFI_STATUS                        Status;
 | |
|   EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *LegacyBiosPlatform;
 | |
|   EFI_COMPATIBILITY16_TABLE         *Legacy16Table;
 | |
|   EFI_IA32_REGISTER_SET             Regs;
 | |
|   LEGACY_BIOS_INSTANCE              *Private;
 | |
| 
 | |
|   Private             = LEGACY_BIOS_INSTANCE_FROM_THIS (This);
 | |
| 
 | |
|   LegacyBiosPlatform  = Private->LegacyBiosPlatform;
 | |
|   Legacy16Table       = Private->Legacy16Table;
 | |
| 
 | |
|   //
 | |
|   // Phase 1 - get an address allocated in 16-bit code
 | |
|   //
 | |
|   while (TRUE) {
 | |
|     switch (Id) {
 | |
|     case EfiGetPlatformBinaryMpTable:
 | |
|     case EfiGetPlatformBinaryOemIntData:
 | |
|     case EfiGetPlatformBinaryOem32Data:
 | |
|     case EfiGetPlatformBinaryOem16Data:
 | |
|       {
 | |
|         Status = LegacyBiosPlatform->GetPlatformInfo (
 | |
|                                       LegacyBiosPlatform,
 | |
|                                       Id,
 | |
|                                       (VOID *) &Table,
 | |
|                                       &TableSize,
 | |
|                                       &Location,
 | |
|                                       &Alignment,
 | |
|                                       0,
 | |
|                                       0
 | |
|                                       );
 | |
|         DEBUG ((EFI_D_INFO, "LegacyGetDataOrTable - ID: %x, %r\n", (UINTN)Id, Status));
 | |
|         DEBUG ((EFI_D_INFO, "  Table - %x, Size - %x, Location - %x, Alignment - %x\n", (UINTN)Table, (UINTN)TableSize, (UINTN)Location, (UINTN)Alignment));
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|     default:
 | |
|       {
 | |
|         return EFI_INVALID_PARAMETER;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       return Status;
 | |
|     }
 | |
| 
 | |
|     ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));
 | |
|     Regs.X.AX = Legacy16GetTableAddress;
 | |
|     Regs.X.CX = (UINT16) TableSize;
 | |
|     Regs.X.BX = (UINT16) Location;
 | |
|     Regs.X.DX = (UINT16) Alignment;
 | |
|     Private->LegacyBios.FarCall86 (
 | |
|       This,
 | |
|       Private->Legacy16CallSegment,
 | |
|       Private->Legacy16CallOffset,
 | |
|       &Regs,
 | |
|       NULL,
 | |
|       0
 | |
|       );
 | |
| 
 | |
|     if (Regs.X.AX != 0) {
 | |
|       DEBUG ((EFI_D_ERROR, "Table ID %x length insufficient\n", Id));
 | |
|       return EFI_OUT_OF_RESOURCES;
 | |
|     } else {
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
|   //
 | |
|   // Phase 2 Call routine second time with address to allow address adjustment
 | |
|   //
 | |
|   Status = LegacyBiosPlatform->GetPlatformInfo (
 | |
|                                 LegacyBiosPlatform,
 | |
|                                 Id,
 | |
|                                 (VOID *) &Table,
 | |
|                                 &TableSize,
 | |
|                                 &Location,
 | |
|                                 &Alignment,
 | |
|                                 Regs.X.DS,
 | |
|                                 Regs.X.BX
 | |
|                                 );
 | |
|   switch (Id) {
 | |
|   case EfiGetPlatformBinaryMpTable:
 | |
|     {
 | |
|       Legacy16Table->MpTablePtr     = (UINT32) (Regs.X.DS * 16 + Regs.X.BX);
 | |
|       Legacy16Table->MpTableLength  = (UINT32)TableSize;
 | |
|       DEBUG ((EFI_D_INFO, "MP table in legacy region - %x\n", (UINTN)Legacy16Table->MpTablePtr));
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|   case EfiGetPlatformBinaryOemIntData:
 | |
|     {
 | |
| 
 | |
|       Legacy16Table->OemIntSegment  = Regs.X.DS;
 | |
|       Legacy16Table->OemIntOffset   = Regs.X.BX;
 | |
|       DEBUG ((EFI_D_INFO, "OemInt table in legacy region - %04x:%04x\n", (UINTN)Legacy16Table->OemIntSegment, (UINTN)Legacy16Table->OemIntOffset));
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|   case EfiGetPlatformBinaryOem32Data:
 | |
|     {
 | |
|       Legacy16Table->Oem32Segment = Regs.X.DS;
 | |
|       Legacy16Table->Oem32Offset  = Regs.X.BX;
 | |
|       DEBUG ((EFI_D_INFO, "Oem32 table in legacy region - %04x:%04x\n", (UINTN)Legacy16Table->Oem32Segment, (UINTN)Legacy16Table->Oem32Offset));
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|   case EfiGetPlatformBinaryOem16Data:
 | |
|     {
 | |
|       //
 | |
|       //          Legacy16Table->Oem16Segment = Regs.X.DS;
 | |
|       //          Legacy16Table->Oem16Offset  = Regs.X.BX;
 | |
|       DEBUG ((EFI_D_INFO, "Oem16 table in legacy region - %04x:%04x\n", (UINTN)Legacy16Table->Oem16Segment, (UINTN)Legacy16Table->Oem16Offset));
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|   default:
 | |
|     {
 | |
|       return EFI_INVALID_PARAMETER;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
|   //
 | |
|   // Phase 3 Copy table to final location
 | |
|   //
 | |
|   TablePtr = (UINT32) (Regs.X.DS * 16 + Regs.X.BX);
 | |
| 
 | |
|   CopyMem (
 | |
|     (VOID *) (UINTN)TablePtr,
 | |
|     Table,
 | |
|     TableSize
 | |
|     );
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Assign drive number to legacy HDD drives prior to booting an EFI
 | |
|   aware OS so the OS can access drives without an EFI driver.
 | |
|   Note: BBS compliant drives ARE NOT available until this call by
 | |
|   either shell or EFI.
 | |
| 
 | |
|   @param  This                    Protocol instance pointer.
 | |
| 
 | |
|   @retval EFI_SUCCESS             Drive numbers assigned
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| GenericLegacyBoot (
 | |
|   IN EFI_LEGACY_BIOS_PROTOCOL           *This
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                        Status;
 | |
|   LEGACY_BIOS_INSTANCE              *Private;
 | |
|   EFI_IA32_REGISTER_SET             Regs;
 | |
|   EFI_TO_COMPATIBILITY16_BOOT_TABLE *EfiToLegacy16BootTable;
 | |
|   EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *LegacyBiosPlatform;
 | |
|   UINTN                             CopySize;
 | |
|   VOID                              *AcpiPtr;
 | |
|   HDD_INFO                          *HddInfo;
 | |
|   HDD_INFO                          *LocalHddInfo;
 | |
|   UINTN                             Index;
 | |
|   EFI_COMPATIBILITY16_TABLE         *Legacy16Table;
 | |
|   UINT32                            *BdaPtr;
 | |
|   UINT16                            HddCount;
 | |
|   UINT16                            BbsCount;
 | |
|   BBS_TABLE                         *LocalBbsTable;
 | |
|   UINT32                            *BaseVectorMaster;
 | |
|   EFI_TIME                          BootTime;
 | |
|   UINT32                            LocalTime;
 | |
|   EFI_HANDLE                        IdeController;
 | |
|   UINTN                             HandleCount;
 | |
|   EFI_HANDLE                        *HandleBuffer;
 | |
|   VOID                              *SmbiosTable;
 | |
|   VOID                              *AcpiTable;
 | |
|   UINTN                             ShadowAddress;
 | |
|   UINT32                            Granularity;
 | |
| 
 | |
|   LocalHddInfo  = NULL;
 | |
|   HddCount      = 0;
 | |
|   BbsCount      = 0;
 | |
|   LocalBbsTable = NULL;
 | |
| 
 | |
|   Private       = LEGACY_BIOS_INSTANCE_FROM_THIS (This);
 | |
|   DEBUG_CODE (
 | |
|     DEBUG ((EFI_D_ERROR, "Start of legacy boot\n"));
 | |
|   );
 | |
| 
 | |
|   Legacy16Table                         = Private->Legacy16Table;
 | |
|   EfiToLegacy16BootTable                = &Private->IntThunk->EfiToLegacy16BootTable;
 | |
|   HddInfo = &EfiToLegacy16BootTable->HddInfo[0];
 | |
| 
 | |
|   LegacyBiosPlatform = Private->LegacyBiosPlatform;
 | |
| 
 | |
|   EfiToLegacy16BootTable->MajorVersion = EFI_TO_LEGACY_MAJOR_VERSION;
 | |
|   EfiToLegacy16BootTable->MinorVersion = EFI_TO_LEGACY_MINOR_VERSION;
 | |
|   
 | |
|   //
 | |
|   // If booting to a legacy OS then force HDD drives to the appropriate
 | |
|   // boot mode by calling GetIdeHandle.
 | |
|   // A reconnect -r can force all HDDs back to native mode.
 | |
|   //
 | |
|   IdeController = NULL;
 | |
|   if ((mBootMode == BOOT_LEGACY_OS) || (mBootMode == BOOT_UNCONVENTIONAL_DEVICE)) {
 | |
|     Status = LegacyBiosPlatform->GetPlatformHandle (
 | |
|                                   Private->LegacyBiosPlatform,
 | |
|                                   EfiGetPlatformIdeHandle,
 | |
|                                   0,
 | |
|                                   &HandleBuffer,
 | |
|                                   &HandleCount,
 | |
|                                   NULL
 | |
|                                   );
 | |
|     if (!EFI_ERROR (Status)) {
 | |
|       IdeController = HandleBuffer[0];
 | |
|     }   
 | |
|   }
 | |
|   //
 | |
|   // Unlock the Legacy BIOS region
 | |
|   //
 | |
|   Private->LegacyRegion->UnLock (
 | |
|                            Private->LegacyRegion,
 | |
|                            0xE0000,
 | |
|                            0x20000,
 | |
|                            &Granularity
 | |
|                            );
 | |
| 
 | |
|   //
 | |
|   // Reconstruct the Legacy16 boot memory map
 | |
|   //
 | |
|   LegacyBiosBuildE820 (Private, &CopySize);
 | |
|   if (CopySize > Private->Legacy16Table->E820Length) {
 | |
|     ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));
 | |
|     Regs.X.AX = Legacy16GetTableAddress;
 | |
|     Regs.X.CX = (UINT16) CopySize;
 | |
|     Private->LegacyBios.FarCall86 (
 | |
|       &Private->LegacyBios,
 | |
|       Private->Legacy16Table->Compatibility16CallSegment,
 | |
|       Private->Legacy16Table->Compatibility16CallOffset,
 | |
|       &Regs,
 | |
|       NULL,
 | |
|       0
 | |
|       );
 | |
| 
 | |
|     Private->Legacy16Table->E820Pointer = (UINT32) (Regs.X.DS * 16 + Regs.X.BX);
 | |
|     Private->Legacy16Table->E820Length  = (UINT32) CopySize;
 | |
|     if (Regs.X.AX != 0) {
 | |
|       DEBUG ((EFI_D_ERROR, "Legacy16 E820 length insufficient\n"));
 | |
|     } else {
 | |
|       CopyMem (
 | |
|         (VOID *)(UINTN) Private->Legacy16Table->E820Pointer,
 | |
|         Private->E820Table,
 | |
|         CopySize
 | |
|         );
 | |
|     }
 | |
|   } else {
 | |
|     CopyMem (
 | |
|       (VOID *)(UINTN) Private->Legacy16Table->E820Pointer,
 | |
|       Private->E820Table,
 | |
|       CopySize
 | |
|       );
 | |
|     Private->Legacy16Table->E820Length = (UINT32) CopySize;
 | |
|   }
 | |
|   //
 | |
|   // Get SMBIOS and ACPI table pointers
 | |
|   //
 | |
|   SmbiosTable = NULL;
 | |
|   EfiGetSystemConfigurationTable (
 | |
|     &gEfiSmbiosTableGuid,
 | |
|     &SmbiosTable
 | |
|     );
 | |
|   //
 | |
|   // We do not ASSERT if SmbiosTable not found. It is possbile that a platform does not produce SmbiosTable.
 | |
|   //
 | |
|   if (SmbiosTable == NULL) {
 | |
|     DEBUG ((EFI_D_INFO, "Smbios table is not found!\n"));
 | |
|   }
 | |
|   EfiToLegacy16BootTable->SmbiosTable = (UINT32)(UINTN)SmbiosTable;
 | |
| 
 | |
|   AcpiTable = NULL;
 | |
|   Status = EfiGetSystemConfigurationTable (
 | |
|              &gEfiAcpi20TableGuid,
 | |
|              &AcpiTable
 | |
|              );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     Status = EfiGetSystemConfigurationTable (
 | |
|                &gEfiAcpi10TableGuid,
 | |
|                &AcpiTable
 | |
|                );
 | |
|   }
 | |
|   //
 | |
|   // We do not ASSERT if AcpiTable not found. It is possbile that a platform does not produce AcpiTable.
 | |
|   //
 | |
|   if (AcpiTable == NULL) {
 | |
|     DEBUG ((EFI_D_INFO, "ACPI table is not found!\n"));
 | |
|   }
 | |
|   EfiToLegacy16BootTable->AcpiTable = (UINT32)(UINTN)AcpiTable;
 | |
| 
 | |
|   //
 | |
|   // Get RSD Ptr table rev at offset 15 decimal
 | |
|   // Rev = 0 Length is 20 decimal
 | |
|   // Rev != 0 Length is UINT32 at offset 20 decimal
 | |
|   //
 | |
|   if (AcpiTable != NULL) {
 | |
| 
 | |
|     AcpiPtr = AcpiTable;
 | |
|     if (*((UINT8 *) AcpiPtr + 15) == 0) {
 | |
|       CopySize = 20;
 | |
|     } else {
 | |
|       AcpiPtr   = ((UINT8 *) AcpiPtr + 20);
 | |
|       CopySize  = (*(UINT32 *) AcpiPtr);
 | |
|     }
 | |
| 
 | |
|     CopyMem (
 | |
|       (VOID *)(UINTN) Private->Legacy16Table->AcpiRsdPtrPointer,
 | |
|       AcpiTable,
 | |
|       CopySize
 | |
|       );
 | |
|   }
 | |
|   //
 | |
|   // Make sure all PCI Interrupt Line register are programmed to match 8259
 | |
|   //
 | |
|   PciProgramAllInterruptLineRegisters (Private);
 | |
| 
 | |
|   //
 | |
|   // Unlock the Legacy BIOS region as PciProgramAllInterruptLineRegisters
 | |
|   // can lock it.
 | |
|   //
 | |
|   Private->LegacyRegion->UnLock (
 | |
|                            Private->LegacyRegion,
 | |
|                            Private->BiosStart,
 | |
|                            Private->LegacyBiosImageSize,
 | |
|                            &Granularity
 | |
|                            );
 | |
| 
 | |
|   //
 | |
|   // Configure Legacy Device Magic
 | |
|   //
 | |
|   // Only do this code if booting legacy OS
 | |
|   //
 | |
|   if ((mBootMode == BOOT_LEGACY_OS) || (mBootMode == BOOT_UNCONVENTIONAL_DEVICE)) {
 | |
|     UpdateSioData (Private);
 | |
|   }
 | |
|   //
 | |
|   // Setup BDA and EBDA standard areas before Legacy Boot
 | |
|   //
 | |
|   LegacyBiosCompleteBdaBeforeBoot (Private);
 | |
|   LegacyBiosCompleteStandardCmosBeforeBoot (Private);
 | |
| 
 | |
|   //
 | |
|   // We must build IDE data, if it hasn't been done, before PciShadowRoms
 | |
|   // to insure EFI drivers are connected.
 | |
|   //
 | |
|   LegacyBiosBuildIdeData (Private, &HddInfo, 1);
 | |
|   UpdateAllIdentifyDriveData (Private);
 | |
| 
 | |
|   //
 | |
|   // Clear IO BAR, if IDE controller in legacy mode.
 | |
|   //
 | |
|   InitLegacyIdeController (IdeController);
 | |
| 
 | |
|   //
 | |
|   // Generate number of ticks since midnight for BDA. DOS requires this
 | |
|   // for its time. We have to make assumptions as to how long following
 | |
|   // code takes since after PciShadowRoms PciIo is gone. Place result in
 | |
|   // 40:6C-6F
 | |
|   //
 | |
|   // Adjust value by 1 second.
 | |
|   //
 | |
|   gRT->GetTime (&BootTime, NULL);
 | |
|   LocalTime = BootTime.Hour * 3600 + BootTime.Minute * 60 + BootTime.Second;
 | |
|   LocalTime += 1;
 | |
| 
 | |
|   //
 | |
|   // Multiply result by 18.2 for number of ticks since midnight.
 | |
|   // Use 182/10 to avoid floating point math.
 | |
|   //
 | |
|   LocalTime = (LocalTime * 182) / 10;
 | |
|   BdaPtr    = (UINT32 *) (UINTN)0x46C;
 | |
|   *BdaPtr   = LocalTime;
 | |
| 
 | |
|   //
 | |
|   // Shadow PCI ROMs. We must do this near the end since this will kick
 | |
|   // of Native EFI drivers that may be needed to collect info for Legacy16
 | |
|   //
 | |
|   //  WARNING: PciIo is gone after this call.
 | |
|   //
 | |
|   PciShadowRoms (Private);
 | |
| 
 | |
|   //
 | |
|   // Shadow PXE base code, BIS etc.
 | |
|   //
 | |
|   Private->LegacyRegion->UnLock (Private->LegacyRegion, 0xc0000, 0x40000, &Granularity);
 | |
|   ShadowAddress = Private->OptionRom;
 | |
|   Private->LegacyBiosPlatform->PlatformHooks (
 | |
|                                  Private->LegacyBiosPlatform,
 | |
|                                  EfiPlatformHookShadowServiceRoms,
 | |
|                                  0,
 | |
|                                  0,
 | |
|                                  &ShadowAddress,
 | |
|                                  Legacy16Table,
 | |
|                                  NULL
 | |
|                                  );
 | |
|   Private->OptionRom = (UINT32)ShadowAddress;
 | |
|   //
 | |
|   // Register Legacy SMI Handler
 | |
|   //
 | |
|   LegacyBiosPlatform->SmmInit (
 | |
|                         LegacyBiosPlatform,
 | |
|                         EfiToLegacy16BootTable
 | |
|                         );
 | |
| 
 | |
|   //
 | |
|   // Let platform code know the boot options
 | |
|   //
 | |
|   LegacyBiosGetBbsInfo (
 | |
|     This,
 | |
|     &HddCount,
 | |
|     &LocalHddInfo,
 | |
|     &BbsCount,
 | |
|     &LocalBbsTable
 | |
|     );
 | |
| 
 | |
|   DEBUG_CODE (
 | |
|     PrintPciInterruptRegister ();
 | |
|     PrintBbsTable (LocalBbsTable);
 | |
|     PrintHddInfo (LocalHddInfo);
 | |
|     );
 | |
|   //
 | |
|   // If drive wasn't spun up then BuildIdeData may have found new drives.
 | |
|   // Need to update BBS boot priority.
 | |
|   //
 | |
|   for (Index = 0; Index < MAX_IDE_CONTROLLER; Index++) {
 | |
|     if ((LocalHddInfo[Index].IdentifyDrive[0].Raw[0] != 0) &&
 | |
|         (LocalBbsTable[2 * Index + 1].BootPriority == BBS_IGNORE_ENTRY)
 | |
|         ) {
 | |
|       LocalBbsTable[2 * Index + 1].BootPriority = BBS_UNPRIORITIZED_ENTRY;
 | |
|     }
 | |
| 
 | |
|     if ((LocalHddInfo[Index].IdentifyDrive[1].Raw[0] != 0) &&
 | |
|         (LocalBbsTable[2 * Index + 2].BootPriority == BBS_IGNORE_ENTRY)
 | |
|         ) {
 | |
|       LocalBbsTable[2 * Index + 2].BootPriority = BBS_UNPRIORITIZED_ENTRY;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   Private->LegacyRegion->UnLock (
 | |
|                            Private->LegacyRegion,
 | |
|                            0xc0000,
 | |
|                            0x40000,
 | |
|                            &Granularity
 | |
|                            );
 | |
| 
 | |
|   LegacyBiosPlatform->PrepareToBoot (
 | |
|                         LegacyBiosPlatform,
 | |
|                         mBbsDevicePathPtr,
 | |
|                         mBbsTable,
 | |
|                         mLoadOptionsSize,
 | |
|                         mLoadOptions,
 | |
|                         (VOID *) &Private->IntThunk->EfiToLegacy16BootTable
 | |
|                         );
 | |
| 
 | |
|   //
 | |
|   // If no boot device return to BDS
 | |
|   //
 | |
|   if ((mBootMode == BOOT_LEGACY_OS) || (mBootMode == BOOT_UNCONVENTIONAL_DEVICE)) {
 | |
|     for (Index = 0; Index < BbsCount; Index++){
 | |
|       if ((LocalBbsTable[Index].BootPriority != BBS_DO_NOT_BOOT_FROM) &&
 | |
|           (LocalBbsTable[Index].BootPriority != BBS_UNPRIORITIZED_ENTRY) &&
 | |
|           (LocalBbsTable[Index].BootPriority != BBS_IGNORE_ENTRY)) {
 | |
|         break;
 | |
|       }
 | |
|     }
 | |
|     if (Index == BbsCount) {
 | |
|       return EFI_DEVICE_ERROR;
 | |
|     }
 | |
|   }
 | |
|   //
 | |
|   // Let the Legacy16 code know the device path type for legacy boot
 | |
|   //
 | |
|   EfiToLegacy16BootTable->DevicePathType = mBbsDevicePathPtr->DeviceType;
 | |
| 
 | |
|   //
 | |
|   // Copy MP table, if it exists.
 | |
|   //
 | |
|   LegacyGetDataOrTable (This, EfiGetPlatformBinaryMpTable);
 | |
| 
 | |
|   if (!Private->LegacyBootEntered) {
 | |
|     //
 | |
|     // Copy OEM INT Data, if it exists. Note: This code treats any data
 | |
|     // as a bag of bits and knows nothing of the contents nor cares.
 | |
|     // Contents are IBV specific.
 | |
|     //
 | |
|     LegacyGetDataOrTable (This, EfiGetPlatformBinaryOemIntData);
 | |
| 
 | |
|     //
 | |
|     // Copy OEM16 Data, if it exists.Note: This code treats any data
 | |
|     // as a bag of bits and knows nothing of the contents nor cares.
 | |
|     // Contents are IBV specific.
 | |
|     //
 | |
|     LegacyGetDataOrTable (This, EfiGetPlatformBinaryOem16Data);
 | |
| 
 | |
|     //
 | |
|     // Copy OEM32 Data, if it exists.Note: This code treats any data
 | |
|     // as a bag of bits and knows nothing of the contents nor cares.
 | |
|     // Contents are IBV specific.
 | |
|     //
 | |
|     LegacyGetDataOrTable (This, EfiGetPlatformBinaryOem32Data);
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Call into Legacy16 code to prepare for INT 19h
 | |
|   //
 | |
|   ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));
 | |
|   Regs.X.AX = Legacy16PrepareToBoot;
 | |
| 
 | |
|   //
 | |
|   // Pass in handoff data
 | |
|   //
 | |
|   Regs.X.ES = NORMALIZE_EFI_SEGMENT ((UINTN)EfiToLegacy16BootTable);
 | |
|   Regs.X.BX = NORMALIZE_EFI_OFFSET ((UINTN)EfiToLegacy16BootTable);
 | |
| 
 | |
|   Private->LegacyBios.FarCall86 (
 | |
|     This,
 | |
|     Private->Legacy16CallSegment,
 | |
|     Private->Legacy16CallOffset,
 | |
|     &Regs,
 | |
|     NULL,
 | |
|     0
 | |
|     );
 | |
| 
 | |
|   if (Regs.X.AX != 0) {
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
|   //
 | |
|   // Lock the Legacy BIOS region
 | |
|   //
 | |
|   Private->LegacyRegion->Lock (
 | |
|                            Private->LegacyRegion,
 | |
|                            0xc0000,
 | |
|                            0x40000,
 | |
|                            &Granularity
 | |
|                            );
 | |
|   //
 | |
|   // Lock attributes of the Legacy Region if chipset supports
 | |
|   //
 | |
|   Private->LegacyRegion->BootLock (
 | |
|                            Private->LegacyRegion,
 | |
|                            0xc0000,
 | |
|                            0x40000,
 | |
|                            &Granularity
 | |
|                            );
 | |
| 
 | |
|   //
 | |
|   // Call into Legacy16 code to do the INT 19h
 | |
|   //
 | |
|   EnableAllControllers (Private);
 | |
|   if ((mBootMode == BOOT_LEGACY_OS) || (mBootMode == BOOT_UNCONVENTIONAL_DEVICE)) {
 | |
|     //
 | |
|     // Report Status Code to indicate legacy boot event will be signalled
 | |
|     //
 | |
|     REPORT_STATUS_CODE (
 | |
|       EFI_PROGRESS_CODE,
 | |
|       (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_PC_LEGACY_BOOT_EVENT)
 | |
|       );
 | |
| 
 | |
|     //
 | |
|     // Signal all the events that are waiting on EVT_SIGNAL_LEGACY_BOOT
 | |
|     //
 | |
|     EfiSignalEventLegacyBoot ();
 | |
|     DEBUG ((EFI_D_INFO, "Legacy INT19 Boot...\n"));
 | |
| 
 | |
|     //
 | |
|     // Disable DXE Timer while executing in real mode
 | |
|     //
 | |
|     Private->Timer->SetTimerPeriod (Private->Timer, 0);
 | |
|     
 | |
|     //
 | |
|     // Save and disable interrupt of debug timer
 | |
|     //
 | |
|     SaveAndSetDebugTimerInterrupt (FALSE);
 | |
| 
 | |
| 
 | |
|     //
 | |
|     // Put the 8259 into its legacy mode by reprogramming the vector bases
 | |
|     //
 | |
|     Private->Legacy8259->SetVectorBase (Private->Legacy8259, LEGACY_MODE_BASE_VECTOR_MASTER, LEGACY_MODE_BASE_VECTOR_SLAVE);
 | |
|     //
 | |
|     // PC History
 | |
|     //   The original PC used INT8-F for master PIC. Since these mapped over
 | |
|     //   processor exceptions TIANO moved the master PIC to INT68-6F.
 | |
|     // We need to set these back to the Legacy16 unexpected interrupt(saved
 | |
|     // in LegacyBios.c) since some OS see that these have values different from
 | |
|     // what is expected and invoke them. Since the legacy OS corrupts EFI
 | |
|     // memory, there is no handler for these interrupts and OS blows up.
 | |
|     //
 | |
|     // We need to save the TIANO values for the rare case that the Legacy16
 | |
|     // code cannot boot but knows memory hasn't been destroyed.
 | |
|     //
 | |
|     // To compound the problem, video takes over one of these INTS and must be
 | |
|     // be left.
 | |
|     // @bug - determine if video hooks INT(in which case we must find new
 | |
|     //          set of TIANO vectors) or takes it over.
 | |
|     //
 | |
|     //
 | |
|     BaseVectorMaster = (UINT32 *) (sizeof (UINT32) * PROTECTED_MODE_BASE_VECTOR_MASTER);
 | |
|     for (Index = 0; Index < 8; Index++) {
 | |
|       Private->ThunkSavedInt[Index] = BaseVectorMaster[Index];
 | |
|       if (Private->ThunkSeg == (UINT16) (BaseVectorMaster[Index] >> 16)) {
 | |
|         BaseVectorMaster[Index] = (UINT32) (Private->BiosUnexpectedInt);
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));
 | |
|     Regs.X.AX = Legacy16Boot;
 | |
| 
 | |
|     Private->LegacyBios.FarCall86 (
 | |
|       This,
 | |
|       Private->Legacy16CallSegment,
 | |
|       Private->Legacy16CallOffset,
 | |
|       &Regs,
 | |
|       NULL,
 | |
|       0
 | |
|       );
 | |
| 
 | |
|     BaseVectorMaster = (UINT32 *) (sizeof (UINT32) * PROTECTED_MODE_BASE_VECTOR_MASTER);
 | |
|     for (Index = 0; Index < 8; Index++) {
 | |
|       BaseVectorMaster[Index] = Private->ThunkSavedInt[Index];
 | |
|     }
 | |
|   }
 | |
|   Private->LegacyBootEntered = TRUE;
 | |
|   if ((mBootMode == BOOT_LEGACY_OS) || (mBootMode == BOOT_UNCONVENTIONAL_DEVICE)) {
 | |
|     //
 | |
|     // Should never return unless never passed control to 0:7c00(first stage
 | |
|     // OS loader) and only then if no bootable device found.
 | |
|     //
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   } else {
 | |
|     //
 | |
|     // If boot to EFI then expect to return to caller
 | |
|     //
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Assign drive number to legacy HDD drives prior to booting an EFI
 | |
|   aware OS so the OS can access drives without an EFI driver.
 | |
|   Note: BBS compliant drives ARE NOT available until this call by
 | |
|   either shell or EFI.
 | |
| 
 | |
|   @param  This                    Protocol instance pointer.
 | |
|   @param  BbsCount                Number of BBS_TABLE structures
 | |
|   @param  BbsTable                List BBS entries
 | |
| 
 | |
|   @retval EFI_SUCCESS             Drive numbers assigned
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| LegacyBiosPrepareToBootEfi (
 | |
|   IN EFI_LEGACY_BIOS_PROTOCOL         *This,
 | |
|   OUT UINT16                          *BbsCount,
 | |
|   OUT BBS_TABLE                       **BbsTable
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                        Status;
 | |
|   EFI_TO_COMPATIBILITY16_BOOT_TABLE *EfiToLegacy16BootTable;
 | |
|   LEGACY_BIOS_INSTANCE              *Private;
 | |
| 
 | |
|   Private                 = LEGACY_BIOS_INSTANCE_FROM_THIS (This);
 | |
|   EfiToLegacy16BootTable  = &Private->IntThunk->EfiToLegacy16BootTable;
 | |
|   mBootMode               = BOOT_EFI_OS;
 | |
|   mBbsDevicePathPtr       = NULL;
 | |
|   Status                  = GenericLegacyBoot (This);
 | |
|   *BbsTable               = (BBS_TABLE*)(UINTN)EfiToLegacy16BootTable->BbsTable;
 | |
|   *BbsCount               = (UINT16) (sizeof (Private->IntThunk->BbsTable) / sizeof (BBS_TABLE));
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   To boot from an unconventional device like parties and/or execute HDD diagnostics.
 | |
| 
 | |
|   @param  This            Protocol instance pointer.
 | |
|   @param  Attributes      How to interpret the other input parameters
 | |
|   @param  BbsEntry        The 0-based index into the BbsTable for the parent
 | |
|                           device.
 | |
|   @param  BeerData        Pointer to the 128 bytes of ram BEER data.
 | |
|   @param  ServiceAreaData Pointer to the 64 bytes of raw Service Area data. The
 | |
|                           caller must provide a pointer to the specific Service
 | |
|                           Area and not the start all Service Areas.
 | |
| 
 | |
|   @retval EFI_INVALID_PARAMETER if error. Does NOT return if no error.
 | |
| 
 | |
| ***/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| LegacyBiosBootUnconventionalDevice (
 | |
|   IN EFI_LEGACY_BIOS_PROTOCOL         *This,
 | |
|   IN UDC_ATTRIBUTES                   Attributes,
 | |
|   IN UINTN                            BbsEntry,
 | |
|   IN VOID                             *BeerData,
 | |
|   IN VOID                             *ServiceAreaData
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                        Status;
 | |
|   EFI_TO_COMPATIBILITY16_BOOT_TABLE *EfiToLegacy16BootTable;
 | |
|   LEGACY_BIOS_INSTANCE              *Private;
 | |
|   UD_TABLE                          *UcdTable;
 | |
|   UINTN                             Index;
 | |
|   UINT16                            BootPriority;
 | |
|   BBS_TABLE                         *BbsTable;
 | |
| 
 | |
|   BootPriority = 0;
 | |
|   Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This);
 | |
|   mBootMode = BOOT_UNCONVENTIONAL_DEVICE;
 | |
|   mBbsDevicePathPtr = &mBbsDevicePathNode;
 | |
|   mAttributes = Attributes;
 | |
|   mBbsEntry = BbsEntry;
 | |
|   mBeerData = BeerData, mServiceAreaData = ServiceAreaData;
 | |
| 
 | |
|   EfiToLegacy16BootTable = &Private->IntThunk->EfiToLegacy16BootTable;
 | |
| 
 | |
|   //
 | |
|   // Do input parameter checking
 | |
|   //
 | |
|   if ((Attributes.DirectoryServiceValidity == 0) &&
 | |
|       (Attributes.RabcaUsedFlag == 0) &&
 | |
|       (Attributes.ExecuteHddDiagnosticsFlag == 0)
 | |
|       ) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   if (((Attributes.DirectoryServiceValidity != 0) && (ServiceAreaData == NULL)) ||
 | |
|       (((Attributes.DirectoryServiceValidity | Attributes.RabcaUsedFlag) != 0) && (BeerData == NULL))
 | |
|       ) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   UcdTable = (UD_TABLE *) AllocatePool (
 | |
| 														sizeof (UD_TABLE)
 | |
| 														);
 | |
|   if (NULL == UcdTable) {
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   EfiToLegacy16BootTable->UnconventionalDeviceTable = (UINT32)(UINTN)UcdTable;
 | |
|   UcdTable->Attributes = Attributes;
 | |
|   UcdTable->BbsTableEntryNumberForParentDevice = (UINT8) BbsEntry;
 | |
|   //
 | |
|   // Force all existing BBS entries to DoNotBoot. This allows 16-bit CSM
 | |
|   // to assign drive numbers but bot boot from. Only newly created entries
 | |
|   // will be valid.
 | |
|   //
 | |
|   BbsTable = (BBS_TABLE*)(UINTN)EfiToLegacy16BootTable->BbsTable;
 | |
|   for (Index = 0; Index < EfiToLegacy16BootTable->NumberBbsEntries; Index++) {
 | |
|     BbsTable[Index].BootPriority = BBS_DO_NOT_BOOT_FROM;
 | |
|   }
 | |
|   //
 | |
|   // If parent is onboard IDE then assign controller & device number
 | |
|   // else they are 0.
 | |
|   //
 | |
|   if (BbsEntry < MAX_IDE_CONTROLLER * 2) {
 | |
|     UcdTable->DeviceNumber = (UINT8) ((BbsEntry - 1) % 2);
 | |
|   }
 | |
| 
 | |
|   if (BeerData != NULL) {
 | |
|     CopyMem (
 | |
|       (VOID *) UcdTable->BeerData,
 | |
|       BeerData,
 | |
|       (UINTN) 128
 | |
|       );
 | |
|   }
 | |
| 
 | |
|   if (ServiceAreaData != NULL) {
 | |
|     CopyMem (
 | |
|       (VOID *) UcdTable->ServiceAreaData,
 | |
|       ServiceAreaData,
 | |
|       (UINTN) 64
 | |
|       );
 | |
|   }
 | |
|   //
 | |
|   // For each new entry do the following:
 | |
|   //   1. Increment current number of BBS entries
 | |
|   //   2. Copy parent entry to new entry.
 | |
|   //   3. Zero out BootHandler Offset & segment
 | |
|   //   4. Set appropriate device type. BEV(0x80) for HDD diagnostics
 | |
|   //      and Floppy(0x01) for PARTIES boot.
 | |
|   //   5. Assign new priority.
 | |
|   //
 | |
|   if ((Attributes.ExecuteHddDiagnosticsFlag) != 0) {
 | |
|     EfiToLegacy16BootTable->NumberBbsEntries += 1;
 | |
| 
 | |
|     CopyMem (
 | |
|       (VOID *) &BbsTable[EfiToLegacy16BootTable->NumberBbsEntries].BootPriority,
 | |
|       (VOID *) &BbsTable[BbsEntry].BootPriority,
 | |
|       sizeof (BBS_TABLE)
 | |
|       );
 | |
| 
 | |
|     BbsTable[EfiToLegacy16BootTable->NumberBbsEntries].BootHandlerOffset  = 0;
 | |
|     BbsTable[EfiToLegacy16BootTable->NumberBbsEntries].BootHandlerSegment = 0;
 | |
|     BbsTable[EfiToLegacy16BootTable->NumberBbsEntries].DeviceType         = 0x80;
 | |
| 
 | |
|     UcdTable->BbsTableEntryNumberForHddDiag = (UINT8) (EfiToLegacy16BootTable->NumberBbsEntries - 1);
 | |
| 
 | |
|     BbsTable[EfiToLegacy16BootTable->NumberBbsEntries].BootPriority = BootPriority;
 | |
|     BootPriority += 1;
 | |
| 
 | |
|     //
 | |
|     // Set device type as BBS_TYPE_DEV for PARTIES diagnostic
 | |
|     //
 | |
|     mBbsDevicePathNode.DeviceType = BBS_TYPE_BEV;
 | |
|   }
 | |
| 
 | |
|   if (((Attributes.DirectoryServiceValidity | Attributes.RabcaUsedFlag)) != 0) {
 | |
|     EfiToLegacy16BootTable->NumberBbsEntries += 1;
 | |
|     CopyMem (
 | |
|       (VOID *) &BbsTable[EfiToLegacy16BootTable->NumberBbsEntries].BootPriority,
 | |
|       (VOID *) &BbsTable[BbsEntry].BootPriority,
 | |
|       sizeof (BBS_TABLE)
 | |
|       );
 | |
| 
 | |
|     BbsTable[EfiToLegacy16BootTable->NumberBbsEntries].BootHandlerOffset  = 0;
 | |
|     BbsTable[EfiToLegacy16BootTable->NumberBbsEntries].BootHandlerSegment = 0;
 | |
|     BbsTable[EfiToLegacy16BootTable->NumberBbsEntries].DeviceType         = 0x01;
 | |
|     UcdTable->BbsTableEntryNumberForBoot = (UINT8) (EfiToLegacy16BootTable->NumberBbsEntries - 1);
 | |
|     BbsTable[EfiToLegacy16BootTable->NumberBbsEntries].BootPriority = BootPriority;
 | |
| 
 | |
|     //
 | |
|     // Set device type as BBS_TYPE_FLOPPY for PARTIES boot as floppy
 | |
|     //
 | |
|     mBbsDevicePathNode.DeviceType = BBS_TYPE_FLOPPY;
 | |
|   }
 | |
|   //
 | |
|   // Build the BBS Device Path for this boot selection
 | |
|   //
 | |
|   mBbsDevicePathNode.Header.Type    = BBS_DEVICE_PATH;
 | |
|   mBbsDevicePathNode.Header.SubType = BBS_BBS_DP;
 | |
|   SetDevicePathNodeLength (&mBbsDevicePathNode.Header, sizeof (BBS_BBS_DEVICE_PATH));
 | |
|   mBbsDevicePathNode.StatusFlag = 0;
 | |
|   mBbsDevicePathNode.String[0]  = 0;
 | |
| 
 | |
|   Status                        = GenericLegacyBoot (This);
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Attempt to legacy boot the BootOption. If the EFI contexted has been
 | |
|   compromised this function will not return.
 | |
| 
 | |
|   @param  This             Protocol instance pointer.
 | |
|   @param  BbsDevicePath    EFI Device Path from BootXXXX variable.
 | |
|   @param  LoadOptionsSize  Size of LoadOption in size.
 | |
|   @param  LoadOptions      LoadOption from BootXXXX variable
 | |
| 
 | |
|   @retval EFI_SUCCESS      Removable media not present
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| LegacyBiosLegacyBoot (
 | |
|   IN EFI_LEGACY_BIOS_PROTOCOL           *This,
 | |
|   IN  BBS_BBS_DEVICE_PATH               *BbsDevicePath,
 | |
|   IN  UINT32                            LoadOptionsSize,
 | |
|   IN  VOID                              *LoadOptions
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
| 
 | |
|   mBbsDevicePathPtr = BbsDevicePath;
 | |
|   mLoadOptionsSize  = LoadOptionsSize;
 | |
|   mLoadOptions      = LoadOptions;
 | |
|   mBootMode         = BOOT_LEGACY_OS;
 | |
|   Status            = GenericLegacyBoot (This);
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Convert EFI Memory Type to E820 Memory Type.
 | |
| 
 | |
|   @param  Type  EFI Memory Type
 | |
| 
 | |
|   @return ACPI Memory Type for EFI Memory Type
 | |
| 
 | |
| **/
 | |
| EFI_ACPI_MEMORY_TYPE
 | |
| EfiMemoryTypeToE820Type (
 | |
|   IN  UINT32    Type
 | |
|   )
 | |
| {
 | |
|   switch (Type) {
 | |
|   case EfiLoaderCode:
 | |
|   case EfiLoaderData:
 | |
|   case EfiBootServicesCode:
 | |
|   case EfiBootServicesData:
 | |
|   case EfiConventionalMemory:
 | |
|   case EfiRuntimeServicesCode:
 | |
|   case EfiRuntimeServicesData:
 | |
|     return EfiAcpiAddressRangeMemory;
 | |
| 
 | |
|   case EfiACPIReclaimMemory:
 | |
|     return EfiAcpiAddressRangeACPI;
 | |
| 
 | |
|   case EfiACPIMemoryNVS:
 | |
|     return EfiAcpiAddressRangeNVS;
 | |
| 
 | |
|   //
 | |
|   // All other types map to reserved.
 | |
|   // Adding the code just waists FLASH space.
 | |
|   //
 | |
|   //  case  EfiReservedMemoryType:
 | |
|   //  case  EfiUnusableMemory:
 | |
|   //  case  EfiMemoryMappedIO:
 | |
|   //  case  EfiMemoryMappedIOPortSpace:
 | |
|   //  case  EfiPalCode:
 | |
|   //
 | |
|   default:
 | |
|     return EfiAcpiAddressRangeReserved;
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Build the E820 table.
 | |
| 
 | |
|   @param  Private  Legacy BIOS Instance data
 | |
|   @param  Size     Size of E820 Table
 | |
| 
 | |
|   @retval EFI_SUCCESS  It should always work.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| LegacyBiosBuildE820 (
 | |
|   IN  LEGACY_BIOS_INSTANCE    *Private,
 | |
|   OUT UINTN                   *Size
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                  Status;
 | |
|   EFI_E820_ENTRY64            *E820Table;
 | |
|   EFI_MEMORY_DESCRIPTOR       *EfiMemoryMap;
 | |
|   EFI_MEMORY_DESCRIPTOR       *EfiMemoryMapEnd;
 | |
|   EFI_MEMORY_DESCRIPTOR       *EfiEntry;
 | |
|   EFI_MEMORY_DESCRIPTOR       *NextEfiEntry;
 | |
|   EFI_MEMORY_DESCRIPTOR       TempEfiEntry;
 | |
|   UINTN                       EfiMemoryMapSize;
 | |
|   UINTN                       EfiMapKey;
 | |
|   UINTN                       EfiDescriptorSize;
 | |
|   UINT32                      EfiDescriptorVersion;
 | |
|   UINTN                       Index;
 | |
|   EFI_PEI_HOB_POINTERS        Hob;
 | |
|   EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;
 | |
|   UINTN                       TempIndex;
 | |
|   UINTN                       IndexSort;
 | |
|   UINTN                       TempNextIndex;
 | |
|   EFI_E820_ENTRY64            TempE820;
 | |
|   EFI_ACPI_MEMORY_TYPE        TempType;
 | |
|   BOOLEAN                     ChangedFlag;
 | |
|   UINTN                       Above1MIndex;
 | |
|   UINT64                      MemoryBlockLength;
 | |
| 
 | |
|   E820Table = (EFI_E820_ENTRY64 *) Private->E820Table;
 | |
| 
 | |
|   //
 | |
|   // Get the EFI memory map.
 | |
|   //
 | |
|   EfiMemoryMapSize  = 0;
 | |
|   EfiMemoryMap      = NULL;
 | |
|   Status = gBS->GetMemoryMap (
 | |
|                   &EfiMemoryMapSize,
 | |
|                   EfiMemoryMap,
 | |
|                   &EfiMapKey,
 | |
|                   &EfiDescriptorSize,
 | |
|                   &EfiDescriptorVersion
 | |
|                   );
 | |
|   ASSERT (Status == EFI_BUFFER_TOO_SMALL);
 | |
| 
 | |
|   do {
 | |
|     //
 | |
|     // Use size returned back plus 1 descriptor for the AllocatePool.
 | |
|     // We don't just multiply by 2 since the "for" loop below terminates on
 | |
|     // EfiMemoryMapEnd which is dependent upon EfiMemoryMapSize. Otherwize
 | |
|     // we process bogus entries and create bogus E820 entries.
 | |
|     //
 | |
|     EfiMemoryMap = (EFI_MEMORY_DESCRIPTOR *) AllocatePool (EfiMemoryMapSize);
 | |
|     ASSERT (EfiMemoryMap != NULL);
 | |
|     Status = gBS->GetMemoryMap (
 | |
|                     &EfiMemoryMapSize,
 | |
|                     EfiMemoryMap,
 | |
|                     &EfiMapKey,
 | |
|                     &EfiDescriptorSize,
 | |
|                     &EfiDescriptorVersion
 | |
|                     );
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       FreePool (EfiMemoryMap);
 | |
|     }
 | |
|   } while (Status == EFI_BUFFER_TOO_SMALL);
 | |
| 
 | |
|   ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|   //
 | |
|   // Punch in the E820 table for memory less than 1 MB.
 | |
|   // Assume ZeroMem () has been done on data structure.
 | |
|   //
 | |
|   //
 | |
|   // First entry is 0 to (640k - EBDA)
 | |
|   //
 | |
|   E820Table[0].BaseAddr  = 0;
 | |
|   E820Table[0].Length    = (UINT64) ((*(UINT16 *) (UINTN)0x40E) << 4);
 | |
|   E820Table[0].Type      = EfiAcpiAddressRangeMemory;
 | |
| 
 | |
|   //
 | |
|   // Second entry is (640k - EBDA) to 640k
 | |
|   //
 | |
|   E820Table[1].BaseAddr  = E820Table[0].Length;
 | |
|   E820Table[1].Length    = (UINT64) ((640 * 1024) - E820Table[0].Length);
 | |
|   E820Table[1].Type      = EfiAcpiAddressRangeReserved;
 | |
| 
 | |
|   //
 | |
|   // Third Entry is legacy BIOS
 | |
|   // DO NOT CLAIM region from 0xA0000-0xDFFFF. OS can use free areas
 | |
|   // to page in memory under 1MB.
 | |
|   // Omit region from 0xE0000 to start of BIOS, if any. This can be
 | |
|   // used for a multiple reasons including OPROMS.
 | |
|   //
 | |
| 
 | |
|   //
 | |
|   // The CSM binary image size is not the actually size that CSM binary used,
 | |
|   // to avoid memory corrupt, we declare the 0E0000 - 0FFFFF is used by CSM binary.
 | |
|   //
 | |
|   E820Table[2].BaseAddr  = 0xE0000;
 | |
|   E820Table[2].Length    = 0x20000;
 | |
|   E820Table[2].Type      = EfiAcpiAddressRangeReserved;
 | |
| 
 | |
|   Above1MIndex = 2;
 | |
| 
 | |
|   //
 | |
|   // Process the EFI map to produce E820 map;
 | |
|   //
 | |
| 
 | |
|   //
 | |
|   // Sort memory map from low to high
 | |
|   //
 | |
|   EfiEntry        = EfiMemoryMap;
 | |
|   NextEfiEntry    = NEXT_MEMORY_DESCRIPTOR (EfiEntry, EfiDescriptorSize);
 | |
|   EfiMemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) EfiMemoryMap + EfiMemoryMapSize);
 | |
|   while (EfiEntry < EfiMemoryMapEnd) {
 | |
|     while (NextEfiEntry < EfiMemoryMapEnd) {
 | |
|       if (EfiEntry->PhysicalStart > NextEfiEntry->PhysicalStart) {
 | |
|         CopyMem (&TempEfiEntry, EfiEntry, sizeof (EFI_MEMORY_DESCRIPTOR));
 | |
|         CopyMem (EfiEntry, NextEfiEntry, sizeof (EFI_MEMORY_DESCRIPTOR));
 | |
|         CopyMem (NextEfiEntry, &TempEfiEntry, sizeof (EFI_MEMORY_DESCRIPTOR));
 | |
|       }
 | |
| 
 | |
|       NextEfiEntry = NEXT_MEMORY_DESCRIPTOR (NextEfiEntry, EfiDescriptorSize);
 | |
|     }
 | |
| 
 | |
|     EfiEntry      = NEXT_MEMORY_DESCRIPTOR (EfiEntry, EfiDescriptorSize);
 | |
|     NextEfiEntry  = NEXT_MEMORY_DESCRIPTOR (EfiEntry, EfiDescriptorSize);
 | |
|   }
 | |
| 
 | |
|   EfiEntry        = EfiMemoryMap;
 | |
|   EfiMemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) EfiMemoryMap + EfiMemoryMapSize);
 | |
|   for (Index = Above1MIndex; (EfiEntry < EfiMemoryMapEnd) && (Index < EFI_MAX_E820_ENTRY - 1); ) {
 | |
|     MemoryBlockLength = (UINT64) (LShiftU64 (EfiEntry->NumberOfPages, 12));
 | |
|     if ((EfiEntry->PhysicalStart + MemoryBlockLength) < 0x100000) {
 | |
|       //
 | |
|       // Skip the memory block is under 1MB
 | |
|       //
 | |
|     } else {
 | |
|       if (EfiEntry->PhysicalStart < 0x100000) {
 | |
|         //
 | |
|         // When the memory block spans below 1MB, ensure the memory block start address is at least 1MB
 | |
|         //
 | |
|         MemoryBlockLength       -= 0x100000 - EfiEntry->PhysicalStart;
 | |
|         EfiEntry->PhysicalStart =  0x100000;
 | |
|       }
 | |
| 
 | |
|       //
 | |
|       // Convert memory type to E820 type
 | |
|       //
 | |
|       TempType = EfiMemoryTypeToE820Type (EfiEntry->Type);
 | |
| 
 | |
|       if ((E820Table[Index].Type == TempType) && (EfiEntry->PhysicalStart == (E820Table[Index].BaseAddr + E820Table[Index].Length))) {
 | |
|         //
 | |
|         // Grow an existing entry
 | |
|         //
 | |
|         E820Table[Index].Length += MemoryBlockLength;
 | |
|       } else {
 | |
|         //
 | |
|         // Make a new entry
 | |
|         //
 | |
|         ++Index;
 | |
|         E820Table[Index].BaseAddr  = EfiEntry->PhysicalStart;
 | |
|         E820Table[Index].Length    = MemoryBlockLength;
 | |
|         E820Table[Index].Type      = TempType;
 | |
|       }
 | |
|     }
 | |
|     EfiEntry = NEXT_MEMORY_DESCRIPTOR (EfiEntry, EfiDescriptorSize);
 | |
|   }
 | |
| 
 | |
|   FreePool (EfiMemoryMap);
 | |
| 
 | |
|   //
 | |
|   // Process the reserved memory map to produce E820 map ;
 | |
|   //
 | |
|   for (Hob.Raw = GetHobList (); !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {
 | |
|     if (Hob.Raw != NULL && GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
 | |
|       ResourceHob = Hob.ResourceDescriptor;
 | |
|       if (((ResourceHob->ResourceType == EFI_RESOURCE_MEMORY_MAPPED_IO) ||
 | |
|           (ResourceHob->ResourceType == EFI_RESOURCE_FIRMWARE_DEVICE)  ||
 | |
|           (ResourceHob->ResourceType == EFI_RESOURCE_MEMORY_RESERVED)    ) &&
 | |
|           (ResourceHob->PhysicalStart > 0x100000) &&
 | |
|           (Index < EFI_MAX_E820_ENTRY - 1)) {
 | |
|         ++Index;
 | |
|         E820Table[Index].BaseAddr  = ResourceHob->PhysicalStart;
 | |
|         E820Table[Index].Length    = ResourceHob->ResourceLength;
 | |
|         E820Table[Index].Type      = EfiAcpiAddressRangeReserved;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   Index ++;
 | |
|   Private->IntThunk->EfiToLegacy16InitTable.NumberE820Entries = (UINT32)Index;
 | |
|   Private->IntThunk->EfiToLegacy16BootTable.NumberE820Entries = (UINT32)Index;
 | |
|   Private->NumberE820Entries = (UINT32)Index;
 | |
|   *Size = (UINTN) (Index * sizeof (EFI_E820_ENTRY64));
 | |
| 
 | |
|   //
 | |
|   // Sort E820Table from low to high
 | |
|   //
 | |
|   for (TempIndex = 0; TempIndex < Index; TempIndex++) {
 | |
|     ChangedFlag = FALSE;
 | |
|     for (TempNextIndex = 1; TempNextIndex < Index - TempIndex; TempNextIndex++) {
 | |
|       if (E820Table[TempNextIndex - 1].BaseAddr > E820Table[TempNextIndex].BaseAddr) {
 | |
|         ChangedFlag                       = TRUE;
 | |
|         TempE820.BaseAddr                 = E820Table[TempNextIndex - 1].BaseAddr;
 | |
|         TempE820.Length                   = E820Table[TempNextIndex - 1].Length;
 | |
|         TempE820.Type                     = E820Table[TempNextIndex - 1].Type;
 | |
| 
 | |
|         E820Table[TempNextIndex - 1].BaseAddr  = E820Table[TempNextIndex].BaseAddr;
 | |
|         E820Table[TempNextIndex - 1].Length    = E820Table[TempNextIndex].Length;
 | |
|         E820Table[TempNextIndex - 1].Type      = E820Table[TempNextIndex].Type;
 | |
| 
 | |
|         E820Table[TempNextIndex].BaseAddr      = TempE820.BaseAddr;
 | |
|         E820Table[TempNextIndex].Length        = TempE820.Length;
 | |
|         E820Table[TempNextIndex].Type          = TempE820.Type;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     if (!ChangedFlag) {
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Remove the overlap range
 | |
|   //
 | |
|   for (TempIndex = 1; TempIndex < Index; TempIndex++) {
 | |
|     if (E820Table[TempIndex - 1].BaseAddr <= E820Table[TempIndex].BaseAddr &&
 | |
|         ((E820Table[TempIndex - 1].BaseAddr + E820Table[TempIndex - 1].Length) >=
 | |
|          (E820Table[TempIndex].BaseAddr +E820Table[TempIndex].Length))) {
 | |
|         //
 | |
|         //Overlap range is found
 | |
|         //
 | |
|         ASSERT (E820Table[TempIndex - 1].Type == E820Table[TempIndex].Type);
 | |
| 
 | |
|         if (TempIndex == Index - 1) {
 | |
|           E820Table[TempIndex].BaseAddr = 0;
 | |
|           E820Table[TempIndex].Length   = 0;
 | |
|           E820Table[TempIndex].Type     = (EFI_ACPI_MEMORY_TYPE) 0;
 | |
|           Index--;
 | |
|           break;
 | |
|         } else {
 | |
|           for (IndexSort = TempIndex; IndexSort < Index - 1; IndexSort ++) {
 | |
|             E820Table[IndexSort].BaseAddr = E820Table[IndexSort + 1].BaseAddr;
 | |
|             E820Table[IndexSort].Length   = E820Table[IndexSort + 1].Length;
 | |
|             E820Table[IndexSort].Type     = E820Table[IndexSort + 1].Type;
 | |
|           }
 | |
|           Index--;
 | |
|        }
 | |
|     }
 | |
|   }
 | |
| 
 | |
| 
 | |
| 
 | |
|   Private->IntThunk->EfiToLegacy16InitTable.NumberE820Entries = (UINT32)Index;
 | |
|   Private->IntThunk->EfiToLegacy16BootTable.NumberE820Entries = (UINT32)Index;
 | |
|   Private->NumberE820Entries = (UINT32)Index;
 | |
|   *Size = (UINTN) (Index * sizeof (EFI_E820_ENTRY64));
 | |
| 
 | |
|   //
 | |
|   // Determine OS usable memory above 1Mb
 | |
|   //
 | |
|   Private->IntThunk->EfiToLegacy16BootTable.OsMemoryAbove1Mb = 0x0000;
 | |
|   for (TempIndex = Above1MIndex; TempIndex < Index; TempIndex++) {
 | |
|     if (E820Table[TempIndex].BaseAddr >= 0x100000 && E820Table[TempIndex].BaseAddr < 0x100000000ULL) { // not include above 4G memory
 | |
|       //
 | |
|       // ACPIReclaimMemory is also usable memory for ACPI OS, after OS dumps all ACPI tables.
 | |
|       //
 | |
|       if ((E820Table[TempIndex].Type == EfiAcpiAddressRangeMemory) || (E820Table[TempIndex].Type == EfiAcpiAddressRangeACPI)) {
 | |
|         Private->IntThunk->EfiToLegacy16BootTable.OsMemoryAbove1Mb += (UINT32) (E820Table[TempIndex].Length);
 | |
|       } else {
 | |
|         break; // break at first not normal memory, because SMM may use reserved memory.
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   Private->IntThunk->EfiToLegacy16InitTable.OsMemoryAbove1Mb = Private->IntThunk->EfiToLegacy16BootTable.OsMemoryAbove1Mb;
 | |
| 
 | |
|   //
 | |
|   // Print DEBUG information
 | |
|   //
 | |
|   for (TempIndex = 0; TempIndex < Index; TempIndex++) {
 | |
|     DEBUG((EFI_D_INFO, "E820[%2d]: 0x%16lx ---- 0x%16lx, Type = 0x%x \n",
 | |
|       TempIndex,
 | |
|       E820Table[TempIndex].BaseAddr,
 | |
|       (E820Table[TempIndex].BaseAddr + E820Table[TempIndex].Length),
 | |
|       E820Table[TempIndex].Type
 | |
|       ));
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Fill in the standard BDA and EBDA stuff prior to legacy Boot
 | |
| 
 | |
|   @param  Private      Legacy BIOS Instance data
 | |
| 
 | |
|   @retval EFI_SUCCESS  It should always work.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| LegacyBiosCompleteBdaBeforeBoot (
 | |
|   IN  LEGACY_BIOS_INSTANCE    *Private
 | |
|   )
 | |
| {
 | |
|   BDA_STRUC                   *Bda;
 | |
|   UINT16                      MachineConfig;
 | |
|   DEVICE_PRODUCER_DATA_HEADER *SioPtr;
 | |
| 
 | |
|   Bda           = (BDA_STRUC *) ((UINTN) 0x400);
 | |
|   MachineConfig = 0;
 | |
| 
 | |
|   SioPtr        = &(Private->IntThunk->EfiToLegacy16BootTable.SioData);
 | |
|   Bda->Com1     = SioPtr->Serial[0].Address;
 | |
|   Bda->Com2     = SioPtr->Serial[1].Address;
 | |
|   Bda->Com3     = SioPtr->Serial[2].Address;
 | |
|   Bda->Com4     = SioPtr->Serial[3].Address;
 | |
| 
 | |
|   if (SioPtr->Serial[0].Address != 0x00) {
 | |
|     MachineConfig += 0x200;
 | |
|   }
 | |
| 
 | |
|   if (SioPtr->Serial[1].Address != 0x00) {
 | |
|     MachineConfig += 0x200;
 | |
|   }
 | |
| 
 | |
|   if (SioPtr->Serial[2].Address != 0x00) {
 | |
|     MachineConfig += 0x200;
 | |
|   }
 | |
| 
 | |
|   if (SioPtr->Serial[3].Address != 0x00) {
 | |
|     MachineConfig += 0x200;
 | |
|   }
 | |
| 
 | |
|   Bda->Lpt1 = SioPtr->Parallel[0].Address;
 | |
|   Bda->Lpt2 = SioPtr->Parallel[1].Address;
 | |
|   Bda->Lpt3 = SioPtr->Parallel[2].Address;
 | |
| 
 | |
|   if (SioPtr->Parallel[0].Address != 0x00) {
 | |
|     MachineConfig += 0x4000;
 | |
|   }
 | |
| 
 | |
|   if (SioPtr->Parallel[1].Address != 0x00) {
 | |
|     MachineConfig += 0x4000;
 | |
|   }
 | |
| 
 | |
|   if (SioPtr->Parallel[2].Address != 0x00) {
 | |
|     MachineConfig += 0x4000;
 | |
|   }
 | |
| 
 | |
|   Bda->NumberOfDrives = (UINT8) (Bda->NumberOfDrives + Private->IdeDriveCount);
 | |
|   if (SioPtr->Floppy.NumberOfFloppy != 0x00) {
 | |
|     MachineConfig     = (UINT16) (MachineConfig + 0x01 + (SioPtr->Floppy.NumberOfFloppy - 1) * 0x40);
 | |
|     Bda->FloppyXRate  = 0x07;
 | |
|   }
 | |
| 
 | |
|   Bda->Lpt1_2Timeout  = 0x1414;
 | |
|   Bda->Lpt3_4Timeout  = 0x1414;
 | |
|   Bda->Com1_2Timeout  = 0x0101;
 | |
|   Bda->Com3_4Timeout  = 0x0101;
 | |
| 
 | |
|   //
 | |
|   // Force VGA and Coprocessor, indicate 101/102 keyboard
 | |
|   //
 | |
|   MachineConfig       = (UINT16) (MachineConfig + 0x00 + 0x02 + (SioPtr->MousePresent * 0x04));
 | |
|   Bda->MachineConfig  = MachineConfig;
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Fill in the standard BDA for Keyboard LEDs
 | |
| 
 | |
|   @param  This         Protocol instance pointer.
 | |
|   @param  Leds         Current LED status
 | |
| 
 | |
|   @retval EFI_SUCCESS  It should always work.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| LegacyBiosUpdateKeyboardLedStatus (
 | |
|   IN EFI_LEGACY_BIOS_PROTOCOL           *This,
 | |
|   IN  UINT8                             Leds
 | |
|   )
 | |
| {
 | |
|   LEGACY_BIOS_INSTANCE  *Private;
 | |
|   BDA_STRUC             *Bda;
 | |
|   UINT8                 LocalLeds;
 | |
|   EFI_IA32_REGISTER_SET Regs;
 | |
| 
 | |
|   Bda                 = (BDA_STRUC *) ((UINTN) 0x400);
 | |
| 
 | |
|   Private             = LEGACY_BIOS_INSTANCE_FROM_THIS (This);
 | |
|   LocalLeds           = Leds;
 | |
|   Bda->LedStatus      = (UINT8) ((Bda->LedStatus &~0x07) | LocalLeds);
 | |
|   LocalLeds           = (UINT8) (LocalLeds << 4);
 | |
|   Bda->ShiftStatus    = (UINT8) ((Bda->ShiftStatus &~0x70) | LocalLeds);
 | |
|   LocalLeds           = (UINT8) (Leds & 0x20);
 | |
|   Bda->KeyboardStatus = (UINT8) ((Bda->KeyboardStatus &~0x20) | LocalLeds);
 | |
|   //
 | |
|   // Call into Legacy16 code to allow it to do any processing
 | |
|   //
 | |
|   ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));
 | |
|   Regs.X.AX = Legacy16SetKeyboardLeds;
 | |
|   Regs.H.CL = Leds;
 | |
| 
 | |
|   Private->LegacyBios.FarCall86 (
 | |
|     &Private->LegacyBios,
 | |
|     Private->Legacy16Table->Compatibility16CallSegment,
 | |
|     Private->Legacy16Table->Compatibility16CallOffset,
 | |
|     &Regs,
 | |
|     NULL,
 | |
|     0
 | |
|     );
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Fill in the standard CMOS stuff prior to legacy Boot
 | |
| 
 | |
|   @param  Private      Legacy BIOS Instance data
 | |
| 
 | |
|   @retval EFI_SUCCESS  It should always work.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| LegacyBiosCompleteStandardCmosBeforeBoot (
 | |
|   IN  LEGACY_BIOS_INSTANCE    *Private
 | |
|   )
 | |
| {
 | |
|   UINT8   Bda;
 | |
|   UINT8   Floppy;
 | |
|   UINT32  Size;
 | |
| 
 | |
|   //
 | |
|   // Update CMOS locations
 | |
|   // 10 floppy
 | |
|   // 12,19,1A - ignore as OS don't use them and there is no standard due
 | |
|   //            to large capacity drives
 | |
|   // CMOS 14 = BDA 40:10 plus bit 3(display enabled)
 | |
|   //
 | |
|   Bda = (UINT8)(*((UINT8 *)((UINTN)0x410)) | BIT3);
 | |
| 
 | |
|   //
 | |
|   // Force display enabled
 | |
|   //
 | |
|   Floppy = 0x00;
 | |
|   if ((Bda & BIT0) != 0) {
 | |
|     Floppy = BIT6;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Check if 2.88MB floppy set
 | |
|   //
 | |
|   if ((Bda & (BIT7 | BIT6)) != 0) {
 | |
|     Floppy = (UINT8)(Floppy | BIT1);
 | |
|   }
 | |
| 
 | |
|   LegacyWriteStandardCmos (CMOS_10, Floppy);
 | |
|   LegacyWriteStandardCmos (CMOS_14, Bda);
 | |
| 
 | |
|   //
 | |
|   // Force Status Register A to set rate selection bits and divider
 | |
|   //
 | |
|   LegacyWriteStandardCmos (CMOS_0A, 0x26);
 | |
| 
 | |
|   //
 | |
|   // redo memory size since it can change
 | |
|   //
 | |
|   Size = 15 * SIZE_1MB;
 | |
|   if (Private->IntThunk->EfiToLegacy16InitTable.OsMemoryAbove1Mb < (15 * SIZE_1MB)) {
 | |
|     Size  = Private->IntThunk->EfiToLegacy16InitTable.OsMemoryAbove1Mb >> 10;
 | |
|   }
 | |
| 
 | |
|   LegacyWriteStandardCmos (CMOS_17, (UINT8)(Size & 0xFF));
 | |
|   LegacyWriteStandardCmos (CMOS_30, (UINT8)(Size & 0xFF));
 | |
|   LegacyWriteStandardCmos (CMOS_18, (UINT8)(Size >> 8));
 | |
|   LegacyWriteStandardCmos (CMOS_31, (UINT8)(Size >> 8));
 | |
| 
 | |
|   LegacyCalculateWriteStandardCmosChecksum ();
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Relocate this image under 4G memory for IPF.
 | |
| 
 | |
|   @param  ImageHandle  Handle of driver image.
 | |
|   @param  SystemTable  Pointer to system table.
 | |
| 
 | |
|   @retval EFI_SUCCESS  Image successfully relocated.
 | |
|   @retval EFI_ABORTED  Failed to relocate image.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| RelocateImageUnder4GIfNeeded (
 | |
|   IN EFI_HANDLE           ImageHandle,
 | |
|   IN EFI_SYSTEM_TABLE     *SystemTable
 | |
|   )
 | |
| {
 | |
|   return EFI_SUCCESS;
 | |
| }
 |