3 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
9 #include "LegacyBiosInterface.h"
10 #include <IndustryStandard/Pci.h>
12 // Give floppy 3 states
13 // FLOPPY_PRESENT_WITH_MEDIA = Floppy controller present and media is inserted
14 // FLOPPY_NOT_PRESENT = No floppy controller present
15 // FLOPPY_PRESENT_NO_MEDIA = Floppy controller present but no media inserted
17 #define FLOPPY_NOT_PRESENT 0
18 #define FLOPPY_PRESENT_WITH_MEDIA 1
19 #define FLOPPY_PRESENT_NO_MEDIA 2
22 BOOLEAN mBbsTableDoneFlag
= FALSE
;
23 BOOLEAN IsHaveMediaInFloppy
= TRUE
;
26 Checks the state of the floppy and if media is inserted.
28 This routine checks the state of the floppy and if media is inserted.
30 No floppy present - Set BBS entry to ignore
31 Floppy present & no media - Set BBS entry to lowest priority. We cannot
32 set it to ignore since 16-bit CSM will
33 indicate no floppy and thus drive A: is
34 unusable. CSM-16 will not try floppy since
35 lowest priority and thus not incur boot
37 Floppy present & media - Set BBS entry to some priority.
39 @return State of floppy media
49 EFI_HANDLE
*HandleBuffer
;
51 EFI_ISA_IO_PROTOCOL
*IsaIo
;
52 EFI_BLOCK_IO_PROTOCOL
*BlkIo
;
57 gBS
->LocateHandleBuffer (
59 &gEfiIsaIoProtocolGuid
,
66 // If don't find any ISA/IO protocol assume no floppy. Need for floppy
69 if (HandleCount
== 0) {
70 return FLOPPY_NOT_PRESENT
;
73 ASSERT (HandleBuffer
!= NULL
);
75 for (Index
= 0; Index
< HandleCount
; Index
++) {
76 Status
= gBS
->HandleProtocol (
78 &gEfiIsaIoProtocolGuid
,
81 if (EFI_ERROR (Status
)) {
85 if (IsaIo
->ResourceList
->Device
.HID
!= EISA_PNP_ID (0x604)) {
90 // Update blockio in case the floppy is inserted in during BdsTimeout
92 Status
= gBS
->DisconnectController (HandleBuffer
[Index
], NULL
, NULL
);
94 if (EFI_ERROR (Status
)) {
98 Status
= gBS
->ConnectController (HandleBuffer
[Index
], NULL
, NULL
, TRUE
);
100 if (EFI_ERROR (Status
)) {
104 Status
= gBS
->HandleProtocol (
106 &gEfiBlockIoProtocolGuid
,
109 if (EFI_ERROR (Status
)) {
113 if (BlkIo
->Media
->MediaPresent
) {
114 FreePool (HandleBuffer
);
115 return FLOPPY_PRESENT_WITH_MEDIA
;
117 FreePool (HandleBuffer
);
118 return FLOPPY_PRESENT_NO_MEDIA
;
122 FreePool (HandleBuffer
);
124 return FLOPPY_NOT_PRESENT
;
128 Complete build of BBS TABLE.
130 @param Private Legacy BIOS Instance data
131 @param BbsTable BBS Table passed to 16-bit code
133 @retval EFI_SUCCESS Removable media not present
138 IN LEGACY_BIOS_INSTANCE
*Private
,
139 IN BBS_TABLE
*BbsTable
146 EFI_HANDLE
*BlockIoHandles
;
147 UINTN NumberBlockIoHandles
;
152 // First entry is floppy.
153 // Next 2*MAX_IDE_CONTROLLER entries are for onboard IDE.
154 // Next n entries are filled in after each ROM is dispatched.
155 // Entry filled in if follow BBS spec. See LegacyPci.c
156 // Next entries are for non-BBS compliant ROMS. They are filled in by
157 // 16-bit code during Legacy16UpdateBbs invocation. Final BootPriority
158 // occurs after that invocation.
161 // Set default state.
163 IsHaveMediaInFloppy
= HasMediaInFloppy ();
164 if (IsHaveMediaInFloppy
== FLOPPY_PRESENT_WITH_MEDIA
) {
165 BbsTable
[0].BootPriority
= BBS_UNPRIORITIZED_ENTRY
;
167 if (IsHaveMediaInFloppy
== FLOPPY_PRESENT_NO_MEDIA
) {
168 BbsTable
[0].BootPriority
= BBS_LOWEST_PRIORITY
;
170 BbsTable
[0].BootPriority
= BBS_IGNORE_ENTRY
;
174 BbsTable
[0].Bus
= 0xff;
175 BbsTable
[0].Device
= 0xff;
176 BbsTable
[0].Function
= 0xff;
177 BbsTable
[0].DeviceType
= BBS_FLOPPY
;
178 BbsTable
[0].Class
= 01;
179 BbsTable
[0].SubClass
= 02;
180 BbsTable
[0].StatusFlags
.OldPosition
= 0;
181 BbsTable
[0].StatusFlags
.Reserved1
= 0;
182 BbsTable
[0].StatusFlags
.Enabled
= 0;
183 BbsTable
[0].StatusFlags
.Failed
= 0;
184 BbsTable
[0].StatusFlags
.MediaPresent
= 0;
185 BbsTable
[0].StatusFlags
.Reserved2
= 0;
188 // Onboard HDD - Note Each HDD controller controls 2 drives
191 HddInfo
= &Private
->IntThunk
->EfiToLegacy16BootTable
.HddInfo
[0];
193 // Get IDE Drive Info
195 LegacyBiosBuildIdeData (Private
, &HddInfo
, 0);
197 for (HddIndex
= 0; HddIndex
< MAX_IDE_CONTROLLER
; HddIndex
++) {
198 BbsIndex
= HddIndex
* 2 + 1;
199 for (Index
= 0; Index
< 2; ++Index
) {
200 BbsTable
[BbsIndex
+ Index
].Bus
= HddInfo
[HddIndex
].Bus
;
201 BbsTable
[BbsIndex
+ Index
].Device
= HddInfo
[HddIndex
].Device
;
202 BbsTable
[BbsIndex
+ Index
].Function
= HddInfo
[HddIndex
].Function
;
203 BbsTable
[BbsIndex
+ Index
].Class
= 01;
204 BbsTable
[BbsIndex
+ Index
].SubClass
= 01;
205 BbsTable
[BbsIndex
+ Index
].StatusFlags
.OldPosition
= 0;
206 BbsTable
[BbsIndex
+ Index
].StatusFlags
.Reserved1
= 0;
207 BbsTable
[BbsIndex
+ Index
].StatusFlags
.Enabled
= 0;
208 BbsTable
[BbsIndex
+ Index
].StatusFlags
.Failed
= 0;
209 BbsTable
[BbsIndex
+ Index
].StatusFlags
.MediaPresent
= 0;
210 BbsTable
[BbsIndex
+ Index
].StatusFlags
.Reserved2
= 0;
213 // If no controller found or no device found set to ignore
214 // else set to unprioritized and set device type
216 if (HddInfo
[HddIndex
].CommandBaseAddress
== 0) {
217 BbsTable
[BbsIndex
+ Index
].BootPriority
= BBS_IGNORE_ENTRY
;
220 if ((HddInfo
[HddIndex
].Status
& (HDD_MASTER_IDE
| HDD_MASTER_ATAPI_CDROM
| HDD_MASTER_ATAPI_ZIPDISK
)) != 0) {
221 BbsTable
[BbsIndex
+ Index
].BootPriority
= BBS_UNPRIORITIZED_ENTRY
;
222 if ((HddInfo
[HddIndex
].Status
& HDD_MASTER_IDE
) != 0) {
223 BbsTable
[BbsIndex
+ Index
].DeviceType
= BBS_HARDDISK
;
224 } else if ((HddInfo
[HddIndex
].Status
& HDD_MASTER_ATAPI_CDROM
) != 0) {
225 BbsTable
[BbsIndex
+ Index
].DeviceType
= BBS_CDROM
;
230 BbsTable
[BbsIndex
+ Index
].DeviceType
= BBS_HARDDISK
;
233 BbsTable
[BbsIndex
+ Index
].BootPriority
= BBS_IGNORE_ENTRY
;
236 if ((HddInfo
[HddIndex
].Status
& (HDD_SLAVE_IDE
| HDD_SLAVE_ATAPI_CDROM
| HDD_SLAVE_ATAPI_ZIPDISK
)) != 0) {
237 BbsTable
[BbsIndex
+ Index
].BootPriority
= BBS_UNPRIORITIZED_ENTRY
;
238 if ((HddInfo
[HddIndex
].Status
& HDD_SLAVE_IDE
) != 0) {
239 BbsTable
[BbsIndex
+ Index
].DeviceType
= BBS_HARDDISK
;
240 } else if ((HddInfo
[HddIndex
].Status
& HDD_SLAVE_ATAPI_CDROM
) != 0) {
241 BbsTable
[BbsIndex
+ Index
].DeviceType
= BBS_CDROM
;
246 BbsTable
[BbsIndex
+ Index
].DeviceType
= BBS_HARDDISK
;
249 BbsTable
[BbsIndex
+ Index
].BootPriority
= BBS_IGNORE_ENTRY
;
257 // Add non-IDE block devices
259 BbsIndex
= HddIndex
* 2 + 1;
261 Status
= gBS
->LocateHandleBuffer (
263 &gEfiBlockIoProtocolGuid
,
265 &NumberBlockIoHandles
,
269 if (!EFI_ERROR (Status
)) {
271 EFI_BLOCK_IO_PROTOCOL
*BlkIo
;
272 EFI_PCI_IO_PROTOCOL
*PciIo
;
273 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
274 EFI_DEVICE_PATH_PROTOCOL
*DevicePathNode
;
275 EFI_HANDLE PciHandle
;
281 for (Removable
= 0; Removable
< 2; Removable
++) {
282 for (BlockIndex
= 0; BlockIndex
< NumberBlockIoHandles
; BlockIndex
++) {
283 Status
= gBS
->HandleProtocol (
284 BlockIoHandles
[BlockIndex
],
285 &gEfiBlockIoProtocolGuid
,
289 if (EFI_ERROR (Status
)) {
294 // Skip the logical partitions
296 if (BlkIo
->Media
->LogicalPartition
) {
301 // Skip the fixed block io then the removable block io
303 if (BlkIo
->Media
->RemovableMedia
== ((Removable
== 0) ? FALSE
: TRUE
)) {
310 Status
= gBS
->HandleProtocol (
311 BlockIoHandles
[BlockIndex
],
312 &gEfiDevicePathProtocolGuid
,
315 if (EFI_ERROR (Status
)) {
320 // Skip ATA devices as they have already been handled
322 DevicePathNode
= DevicePath
;
323 while (!IsDevicePathEnd (DevicePathNode
)) {
324 if ((DevicePathType (DevicePathNode
) == MESSAGING_DEVICE_PATH
) &&
325 (DevicePathSubType (DevicePathNode
) == MSG_ATAPI_DP
))
330 DevicePathNode
= NextDevicePathNode (DevicePathNode
);
333 if (!IsDevicePathEnd (DevicePathNode
)) {
338 // Locate which PCI device
340 Status
= gBS
->LocateDevicePath (
341 &gEfiPciIoProtocolGuid
,
345 if (EFI_ERROR (Status
)) {
349 Status
= gBS
->HandleProtocol (
351 &gEfiPciIoProtocolGuid
,
354 if (EFI_ERROR (Status
)) {
358 Status
= PciIo
->GetLocation (
365 if (EFI_ERROR (Status
)) {
372 "CSM cannot use PCI devices in segment %Lu\n",
380 "Add Legacy Bbs entry for PCI %d/%d/%d\n",
386 BbsTable
[BbsIndex
].Bus
= BusNum
;
387 BbsTable
[BbsIndex
].Device
= DevNum
;
388 BbsTable
[BbsIndex
].Function
= FuncNum
;
389 BbsTable
[BbsIndex
].Class
= 1;
390 BbsTable
[BbsIndex
].SubClass
= 0x80;
391 BbsTable
[BbsIndex
].StatusFlags
.OldPosition
= 0;
392 BbsTable
[BbsIndex
].StatusFlags
.Reserved1
= 0;
393 BbsTable
[BbsIndex
].StatusFlags
.Enabled
= 0;
394 BbsTable
[BbsIndex
].StatusFlags
.Failed
= 0;
395 BbsTable
[BbsIndex
].StatusFlags
.MediaPresent
= 0;
396 BbsTable
[BbsIndex
].StatusFlags
.Reserved2
= 0;
397 BbsTable
[BbsIndex
].DeviceType
= BBS_HARDDISK
;
398 BbsTable
[BbsIndex
].BootPriority
= BBS_UNPRIORITIZED_ENTRY
;
401 if (BbsIndex
== MAX_BBS_ENTRIES
) {
408 FreePool (BlockIoHandles
);
417 @param This Protocol instance pointer.
418 @param HddCount Number of HDD_INFO structures
419 @param HddInfo Onboard IDE controller information
420 @param BbsCount Number of BBS_TABLE structures
421 @param BbsTable List BBS entries
423 @retval EFI_SUCCESS Tables returned
424 @retval EFI_NOT_FOUND resource not found
425 @retval EFI_DEVICE_ERROR can not get BBS table
430 LegacyBiosGetBbsInfo (
431 IN EFI_LEGACY_BIOS_PROTOCOL
*This
,
432 OUT UINT16
*HddCount
,
433 OUT HDD_INFO
**HddInfo
,
434 OUT UINT16
*BbsCount
,
435 OUT BBS_TABLE
**BbsTable
438 LEGACY_BIOS_INSTANCE
*Private
;
439 EFI_IA32_REGISTER_SET Regs
;
440 EFI_TO_COMPATIBILITY16_BOOT_TABLE
*EfiToLegacy16BootTable
;
441 // HDD_INFO *LocalHddInfo;
442 // IN BBS_TABLE *LocalBbsTable;
444 EFI_HANDLE
*HandleBuffer
;
451 Private
= LEGACY_BIOS_INSTANCE_FROM_THIS (This
);
452 EfiToLegacy16BootTable
= &Private
->IntThunk
->EfiToLegacy16BootTable
;
453 // LocalHddInfo = EfiToLegacy16BootTable->HddInfo;
454 // LocalBbsTable = (BBS_TABLE*)(UINTN)EfiToLegacy16BootTable->BbsTable;
456 if (!mBbsTableDoneFlag
) {
457 mBbsTable
= Private
->BbsTablePtr
;
460 // Always enable disk controllers so 16-bit CSM code has valid information for all
464 // Get PciRootBridgeIO protocol
466 gBS
->LocateHandleBuffer (
468 &gEfiPciRootBridgeIoProtocolGuid
,
474 if (NumHandles
== 0) {
475 return EFI_NOT_FOUND
;
478 mBbsTableDoneFlag
= TRUE
;
479 for (Index
= 0; Index
< NumHandles
; Index
++) {
481 // Connect PciRootBridgeIO protocol handle with FALSE parameter to let
482 // PCI bus driver enumerate all subsequent handles
484 gBS
->ConnectController (HandleBuffer
[Index
], NULL
, NULL
, FALSE
);
487 LegacyBiosBuildBbs (Private
, mBbsTable
);
489 Private
->LegacyRegion
->UnLock (Private
->LegacyRegion
, 0xe0000, 0x20000, &Granularity
);
492 // Call into Legacy16 code to add to BBS table for non BBS compliant OPROMs.
494 ZeroMem (&Regs
, sizeof (EFI_IA32_REGISTER_SET
));
495 Regs
.X
.AX
= Legacy16UpdateBbs
;
498 // Pass in handoff data
500 TempData
= (UINTN
)EfiToLegacy16BootTable
;
501 Regs
.X
.ES
= NORMALIZE_EFI_SEGMENT ((UINT32
)TempData
);
502 Regs
.X
.BX
= NORMALIZE_EFI_OFFSET ((UINT32
)TempData
);
504 Private
->LegacyBios
.FarCall86 (
506 Private
->Legacy16CallSegment
,
507 Private
->Legacy16CallOffset
,
513 Private
->Cpu
->FlushDataCache (Private
->Cpu
, 0xE0000, 0x20000, EfiCpuFlushTypeWriteBackInvalidate
);
514 Private
->LegacyRegion
->Lock (Private
->LegacyRegion
, 0xe0000, 0x20000, &Granularity
);
516 if (Regs
.X
.AX
!= 0) {
517 return EFI_DEVICE_ERROR
;
521 if (HandleBuffer
!= NULL
) {
522 FreePool (HandleBuffer
);
525 *HddCount
= MAX_IDE_CONTROLLER
;
526 *HddInfo
= EfiToLegacy16BootTable
->HddInfo
;
527 *BbsTable
= (BBS_TABLE
*)(UINTN
)EfiToLegacy16BootTable
->BbsTable
;
528 *BbsCount
= (UINT16
)(sizeof (Private
->IntThunk
->BbsTable
) / sizeof (BBS_TABLE
));