mirror of https://github.com/acidanthera/audk.git
525 lines
16 KiB
C
525 lines
16 KiB
C
/** @file
|
|
|
|
Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
|
|
|
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
|
|
**/
|
|
|
|
#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;
|
|
EFI_HANDLE *BlockIoHandles;
|
|
UINTN NumberBlockIoHandles;
|
|
UINTN BlockIndex;
|
|
EFI_STATUS Status;
|
|
|
|
//
|
|
// 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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Add non-IDE block devices
|
|
//
|
|
BbsIndex = HddIndex * 2 + 1;
|
|
|
|
Status = gBS->LocateHandleBuffer (
|
|
ByProtocol,
|
|
&gEfiBlockIoProtocolGuid,
|
|
NULL,
|
|
&NumberBlockIoHandles,
|
|
&BlockIoHandles
|
|
);
|
|
|
|
if (!EFI_ERROR (Status)) {
|
|
UINTN Removable;
|
|
EFI_BLOCK_IO_PROTOCOL *BlkIo;
|
|
EFI_PCI_IO_PROTOCOL *PciIo;
|
|
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
|
|
EFI_DEVICE_PATH_PROTOCOL *DevicePathNode;
|
|
EFI_HANDLE PciHandle;
|
|
UINTN SegNum;
|
|
UINTN BusNum;
|
|
UINTN DevNum;
|
|
UINTN FuncNum;
|
|
|
|
for (Removable = 0; Removable < 2; Removable++) {
|
|
for (BlockIndex = 0; BlockIndex < NumberBlockIoHandles; BlockIndex++) {
|
|
Status = gBS->HandleProtocol (
|
|
BlockIoHandles[BlockIndex],
|
|
&gEfiBlockIoProtocolGuid,
|
|
(VOID **) &BlkIo
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Skip the logical partitions
|
|
//
|
|
if (BlkIo->Media->LogicalPartition) {
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Skip the fixed block io then the removable block io
|
|
//
|
|
if (BlkIo->Media->RemovableMedia == ((Removable == 0) ? FALSE : TRUE)) {
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Get Device Path
|
|
//
|
|
Status = gBS->HandleProtocol (
|
|
BlockIoHandles[BlockIndex],
|
|
&gEfiDevicePathProtocolGuid,
|
|
(VOID **) &DevicePath
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Skip ATA devices as they have already been handled
|
|
//
|
|
DevicePathNode = DevicePath;
|
|
while (!IsDevicePathEnd (DevicePathNode)) {
|
|
if (DevicePathType (DevicePathNode) == MESSAGING_DEVICE_PATH &&
|
|
DevicePathSubType (DevicePathNode) == MSG_ATAPI_DP) {
|
|
break;
|
|
}
|
|
DevicePathNode = NextDevicePathNode (DevicePathNode);
|
|
}
|
|
if (!IsDevicePathEnd (DevicePathNode)) {
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Locate which PCI device
|
|
//
|
|
Status = gBS->LocateDevicePath (
|
|
&gEfiPciIoProtocolGuid,
|
|
&DevicePath,
|
|
&PciHandle
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
continue;
|
|
}
|
|
|
|
Status = gBS->HandleProtocol (
|
|
PciHandle,
|
|
&gEfiPciIoProtocolGuid,
|
|
(VOID **) &PciIo
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
continue;
|
|
}
|
|
|
|
Status = PciIo->GetLocation (
|
|
PciIo,
|
|
&SegNum,
|
|
&BusNum,
|
|
&DevNum,
|
|
&FuncNum
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
continue;
|
|
}
|
|
|
|
if (SegNum != 0) {
|
|
DEBUG ((DEBUG_WARN, "CSM cannot use PCI devices in segment %Lu\n",
|
|
(UINT64) SegNum));
|
|
continue;
|
|
}
|
|
|
|
DEBUG ((DEBUG_INFO, "Add Legacy Bbs entry for PCI %d/%d/%d\n",
|
|
BusNum, DevNum, FuncNum));
|
|
|
|
BbsTable[BbsIndex].Bus = BusNum;
|
|
BbsTable[BbsIndex].Device = DevNum;
|
|
BbsTable[BbsIndex].Function = FuncNum;
|
|
BbsTable[BbsIndex].Class = 1;
|
|
BbsTable[BbsIndex].SubClass = 0x80;
|
|
BbsTable[BbsIndex].StatusFlags.OldPosition = 0;
|
|
BbsTable[BbsIndex].StatusFlags.Reserved1 = 0;
|
|
BbsTable[BbsIndex].StatusFlags.Enabled = 0;
|
|
BbsTable[BbsIndex].StatusFlags.Failed = 0;
|
|
BbsTable[BbsIndex].StatusFlags.MediaPresent = 0;
|
|
BbsTable[BbsIndex].StatusFlags.Reserved2 = 0;
|
|
BbsTable[BbsIndex].DeviceType = BBS_HARDDISK;
|
|
BbsTable[BbsIndex].BootPriority = BBS_UNPRIORITIZED_ENTRY;
|
|
BbsIndex++;
|
|
|
|
if (BbsIndex == MAX_BBS_ENTRIES) {
|
|
Removable = 2;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
FreePool (BlockIoHandles);
|
|
}
|
|
|
|
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;
|
|
}
|