| /** @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> | |
| // Give floppy 3 states | |
| // FLOPPY_PRESENT_WITH_MEDIA = Floppy controller present and media is inserted | |
| // FLOPPY_NOT_PRESENT = No floppy controller present | |
| // FLOPPY_PRESENT_NO_MEDIA = Floppy controller present but no media inserted | |
| // | |
| #define FLOPPY_NOT_PRESENT 0 | |
| #define FLOPPY_PRESENT_WITH_MEDIA 1 | |
| #define FLOPPY_PRESENT_NO_MEDIA 2 | |
| BBS_TABLE *mBbsTable; | |
| BOOLEAN mBbsTableDoneFlag = FALSE; | |
| BOOLEAN IsHaveMediaInFloppy = TRUE; | |
| /** | |
| Checks the state of the floppy and if media is inserted. | |
| This routine checks the state of the floppy and if media is inserted. | |
| There are 3 cases: | |
| No floppy present - Set BBS entry to ignore | |
| Floppy present & no media - Set BBS entry to lowest priority. We cannot | |
| set it to ignore since 16-bit CSM will | |
| indicate no floppy and thus drive A: is | |
| unusable. CSM-16 will not try floppy since | |
| lowest priority and thus not incur boot | |
| time penality. | |
| Floppy present & media - Set BBS entry to some priority. | |
| @return State of floppy media | |
| **/ | |
| UINT8 | |
| HasMediaInFloppy ( | |
| VOID | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| UINTN HandleCount; | |
| EFI_HANDLE *HandleBuffer; | |
| UINTN Index; | |
| EFI_ISA_IO_PROTOCOL *IsaIo; | |
| EFI_BLOCK_IO_PROTOCOL *BlkIo; | |
| HandleBuffer = NULL; | |
| HandleCount = 0; | |
| gBS->LocateHandleBuffer ( | |
| ByProtocol, | |
| &gEfiIsaIoProtocolGuid, | |
| NULL, | |
| &HandleCount, | |
| &HandleBuffer | |
| ); | |
| // | |
| // If don't find any ISA/IO protocol assume no floppy. Need for floppy | |
| // free system | |
| // | |
| if (HandleCount == 0) { | |
| return FLOPPY_NOT_PRESENT; | |
| } | |
| ASSERT (HandleBuffer != NULL); | |
| for (Index = 0; Index < HandleCount; Index++) { | |
| Status = gBS->HandleProtocol ( | |
| HandleBuffer[Index], | |
| &gEfiIsaIoProtocolGuid, | |
| (VOID **) &IsaIo | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| continue; | |
| } | |
| if (IsaIo->ResourceList->Device.HID != EISA_PNP_ID (0x604)) { | |
| continue; | |
| } | |
| // | |
| // Update blockio in case the floppy is inserted in during BdsTimeout | |
| // | |
| Status = gBS->DisconnectController (HandleBuffer[Index], NULL, NULL); | |
| if (EFI_ERROR (Status)) { | |
| continue; | |
| } | |
| Status = gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE); | |
| if (EFI_ERROR (Status)) { | |
| continue; | |
| } | |
| Status = gBS->HandleProtocol ( | |
| HandleBuffer[Index], | |
| &gEfiBlockIoProtocolGuid, | |
| (VOID **) &BlkIo | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| continue; | |
| } | |
| if (BlkIo->Media->MediaPresent) { | |
| FreePool (HandleBuffer); | |
| return FLOPPY_PRESENT_WITH_MEDIA; | |
| } else { | |
| FreePool (HandleBuffer); | |
| return FLOPPY_PRESENT_NO_MEDIA; | |
| } | |
| } | |
| FreePool (HandleBuffer); | |
| return FLOPPY_NOT_PRESENT; | |
| } | |
| /** | |
| Complete build of BBS TABLE. | |
| @param Private Legacy BIOS Instance data | |
| @param BbsTable BBS Table passed to 16-bit code | |
| @retval EFI_SUCCESS Removable media not present | |
| **/ | |
| EFI_STATUS | |
| LegacyBiosBuildBbs ( | |
| IN LEGACY_BIOS_INSTANCE *Private, | |
| IN BBS_TABLE *BbsTable | |
| ) | |
| { | |
| UINTN BbsIndex; | |
| HDD_INFO *HddInfo; | |
| UINTN HddIndex; | |
| UINTN Index; | |
| // | |
| // First entry is floppy. | |
| // Next 2*MAX_IDE_CONTROLLER entries are for onboard IDE. | |
| // Next n entries are filled in after each ROM is dispatched. | |
| // Entry filled in if follow BBS spec. See LegacyPci.c | |
| // Next entries are for non-BBS compliant ROMS. They are filled in by | |
| // 16-bit code during Legacy16UpdateBbs invocation. Final BootPriority | |
| // occurs after that invocation. | |
| // | |
| // Floppy | |
| // Set default state. | |
| // | |
| IsHaveMediaInFloppy = HasMediaInFloppy (); | |
| if (IsHaveMediaInFloppy == FLOPPY_PRESENT_WITH_MEDIA) { | |
| BbsTable[0].BootPriority = BBS_UNPRIORITIZED_ENTRY; | |
| } else { | |
| if (IsHaveMediaInFloppy == FLOPPY_PRESENT_NO_MEDIA) { | |
| BbsTable[0].BootPriority = BBS_LOWEST_PRIORITY; | |
| } else { | |
| BbsTable[0].BootPriority = BBS_IGNORE_ENTRY; | |
| } | |
| } | |
| BbsTable[0].Bus = 0xff; | |
| BbsTable[0].Device = 0xff; | |
| BbsTable[0].Function = 0xff; | |
| BbsTable[0].DeviceType = BBS_FLOPPY; | |
| BbsTable[0].Class = 01; | |
| BbsTable[0].SubClass = 02; | |
| BbsTable[0].StatusFlags.OldPosition = 0; | |
| BbsTable[0].StatusFlags.Reserved1 = 0; | |
| BbsTable[0].StatusFlags.Enabled = 0; | |
| BbsTable[0].StatusFlags.Failed = 0; | |
| BbsTable[0].StatusFlags.MediaPresent = 0; | |
| BbsTable[0].StatusFlags.Reserved2 = 0; | |
| // | |
| // Onboard HDD - Note Each HDD controller controls 2 drives | |
| // Master & Slave | |
| // | |
| HddInfo = &Private->IntThunk->EfiToLegacy16BootTable.HddInfo[0]; | |
| // | |
| // Get IDE Drive Info | |
| // | |
| LegacyBiosBuildIdeData (Private, &HddInfo, 0); | |
| for (HddIndex = 0; HddIndex < MAX_IDE_CONTROLLER; HddIndex++) { | |
| BbsIndex = HddIndex * 2 + 1; | |
| for (Index = 0; Index < 2; ++Index) { | |
| BbsTable[BbsIndex + Index].Bus = HddInfo[HddIndex].Bus; | |
| BbsTable[BbsIndex + Index].Device = HddInfo[HddIndex].Device; | |
| BbsTable[BbsIndex + Index].Function = HddInfo[HddIndex].Function; | |
| BbsTable[BbsIndex + Index].Class = 01; | |
| BbsTable[BbsIndex + Index].SubClass = 01; | |
| BbsTable[BbsIndex + Index].StatusFlags.OldPosition = 0; | |
| BbsTable[BbsIndex + Index].StatusFlags.Reserved1 = 0; | |
| BbsTable[BbsIndex + Index].StatusFlags.Enabled = 0; | |
| BbsTable[BbsIndex + Index].StatusFlags.Failed = 0; | |
| BbsTable[BbsIndex + Index].StatusFlags.MediaPresent = 0; | |
| BbsTable[BbsIndex + Index].StatusFlags.Reserved2 = 0; | |
| // | |
| // If no controller found or no device found set to ignore | |
| // else set to unprioritized and set device type | |
| // | |
| if (HddInfo[HddIndex].CommandBaseAddress == 0) { | |
| BbsTable[BbsIndex + Index].BootPriority = BBS_IGNORE_ENTRY; | |
| } else { | |
| if (Index == 0) { | |
| if ((HddInfo[HddIndex].Status & (HDD_MASTER_IDE | HDD_MASTER_ATAPI_CDROM | HDD_MASTER_ATAPI_ZIPDISK)) != 0) { | |
| BbsTable[BbsIndex + Index].BootPriority = BBS_UNPRIORITIZED_ENTRY; | |
| if ((HddInfo[HddIndex].Status & HDD_MASTER_IDE) != 0) { | |
| BbsTable[BbsIndex + Index].DeviceType = BBS_HARDDISK; | |
| } else if ((HddInfo[HddIndex].Status & HDD_MASTER_ATAPI_CDROM) != 0) { | |
| BbsTable[BbsIndex + Index].DeviceType = BBS_CDROM; | |
| } else { | |
| // | |
| // for ZIPDISK | |
| // | |
| BbsTable[BbsIndex + Index].DeviceType = BBS_HARDDISK; | |
| } | |
| } else { | |
| BbsTable[BbsIndex + Index].BootPriority = BBS_IGNORE_ENTRY; | |
| } | |
| } else { | |
| if ((HddInfo[HddIndex].Status & (HDD_SLAVE_IDE | HDD_SLAVE_ATAPI_CDROM | HDD_SLAVE_ATAPI_ZIPDISK)) != 0) { | |
| BbsTable[BbsIndex + Index].BootPriority = BBS_UNPRIORITIZED_ENTRY; | |
| if ((HddInfo[HddIndex].Status & HDD_SLAVE_IDE) != 0) { | |
| BbsTable[BbsIndex + Index].DeviceType = BBS_HARDDISK; | |
| } else if ((HddInfo[HddIndex].Status & HDD_SLAVE_ATAPI_CDROM) != 0) { | |
| BbsTable[BbsIndex + Index].DeviceType = BBS_CDROM; | |
| } else { | |
| // | |
| // for ZIPDISK | |
| // | |
| BbsTable[BbsIndex + Index].DeviceType = BBS_HARDDISK; | |
| } | |
| } else { | |
| BbsTable[BbsIndex + Index].BootPriority = BBS_IGNORE_ENTRY; | |
| } | |
| } | |
| } | |
| } | |
| } | |
| return EFI_SUCCESS; | |
| } | |
| /** | |
| Get all BBS info | |
| @param This Protocol instance pointer. | |
| @param HddCount Number of HDD_INFO structures | |
| @param HddInfo Onboard IDE controller information | |
| @param BbsCount Number of BBS_TABLE structures | |
| @param BbsTable List BBS entries | |
| @retval EFI_SUCCESS Tables returned | |
| @retval EFI_NOT_FOUND resource not found | |
| @retval EFI_DEVICE_ERROR can not get BBS table | |
| **/ | |
| EFI_STATUS | |
| EFIAPI | |
| LegacyBiosGetBbsInfo ( | |
| IN EFI_LEGACY_BIOS_PROTOCOL *This, | |
| OUT UINT16 *HddCount, | |
| OUT HDD_INFO **HddInfo, | |
| OUT UINT16 *BbsCount, | |
| OUT BBS_TABLE **BbsTable | |
| ) | |
| { | |
| LEGACY_BIOS_INSTANCE *Private; | |
| EFI_IA32_REGISTER_SET Regs; | |
| EFI_TO_COMPATIBILITY16_BOOT_TABLE *EfiToLegacy16BootTable; | |
| // HDD_INFO *LocalHddInfo; | |
| // IN BBS_TABLE *LocalBbsTable; | |
| UINTN NumHandles; | |
| EFI_HANDLE *HandleBuffer; | |
| UINTN Index; | |
| UINTN TempData; | |
| UINT32 Granularity; | |
| HandleBuffer = NULL; | |
| Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This); | |
| EfiToLegacy16BootTable = &Private->IntThunk->EfiToLegacy16BootTable; | |
| // LocalHddInfo = EfiToLegacy16BootTable->HddInfo; | |
| // LocalBbsTable = (BBS_TABLE*)(UINTN)EfiToLegacy16BootTable->BbsTable; | |
| if (!mBbsTableDoneFlag) { | |
| mBbsTable = Private->BbsTablePtr; | |
| // | |
| // Always enable disk controllers so 16-bit CSM code has valid information for all | |
| // drives. | |
| // | |
| // | |
| // Get PciRootBridgeIO protocol | |
| // | |
| gBS->LocateHandleBuffer ( | |
| ByProtocol, | |
| &gEfiPciRootBridgeIoProtocolGuid, | |
| NULL, | |
| &NumHandles, | |
| &HandleBuffer | |
| ); | |
| if (NumHandles == 0) { | |
| return EFI_NOT_FOUND; | |
| } | |
| mBbsTableDoneFlag = TRUE; | |
| for (Index = 0; Index < NumHandles; Index++) { | |
| // | |
| // Connect PciRootBridgeIO protocol handle with FALSE parameter to let | |
| // PCI bus driver enumerate all subsequent handles | |
| // | |
| gBS->ConnectController (HandleBuffer[Index], NULL, NULL, FALSE); | |
| } | |
| LegacyBiosBuildBbs (Private, mBbsTable); | |
| Private->LegacyRegion->UnLock (Private->LegacyRegion, 0xe0000, 0x20000, &Granularity); | |
| // | |
| // Call into Legacy16 code to add to BBS table for non BBS compliant OPROMs. | |
| // | |
| ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); | |
| Regs.X.AX = Legacy16UpdateBbs; | |
| // | |
| // Pass in handoff data | |
| // | |
| TempData = (UINTN) EfiToLegacy16BootTable; | |
| Regs.X.ES = NORMALIZE_EFI_SEGMENT ((UINT32) TempData); | |
| Regs.X.BX = NORMALIZE_EFI_OFFSET ((UINT32) TempData); | |
| Private->LegacyBios.FarCall86 ( | |
| This, | |
| Private->Legacy16CallSegment, | |
| Private->Legacy16CallOffset, | |
| &Regs, | |
| NULL, | |
| 0 | |
| ); | |
| Private->Cpu->FlushDataCache (Private->Cpu, 0xE0000, 0x20000, EfiCpuFlushTypeWriteBackInvalidate); | |
| Private->LegacyRegion->Lock (Private->LegacyRegion, 0xe0000, 0x20000, &Granularity); | |
| if (Regs.X.AX != 0) { | |
| return EFI_DEVICE_ERROR; | |
| } | |
| } | |
| if (HandleBuffer != NULL) { | |
| FreePool (HandleBuffer); | |
| } | |
| *HddCount = MAX_IDE_CONTROLLER; | |
| *HddInfo = EfiToLegacy16BootTable->HddInfo; | |
| *BbsTable = (BBS_TABLE*)(UINTN)EfiToLegacy16BootTable->BbsTable; | |
| *BbsCount = (UINT16) (sizeof (Private->IntThunk->BbsTable) / sizeof (BBS_TABLE)); | |
| return EFI_SUCCESS; | |
| } |