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)) {
89 // Update blockio in case the floppy is inserted in during BdsTimeout
91 Status
= gBS
->DisconnectController (HandleBuffer
[Index
], NULL
, NULL
);
93 if (EFI_ERROR (Status
)) {
97 Status
= gBS
->ConnectController (HandleBuffer
[Index
], NULL
, NULL
, TRUE
);
99 if (EFI_ERROR (Status
)) {
103 Status
= gBS
->HandleProtocol (
105 &gEfiBlockIoProtocolGuid
,
108 if (EFI_ERROR (Status
)) {
112 if (BlkIo
->Media
->MediaPresent
) {
113 FreePool (HandleBuffer
);
114 return FLOPPY_PRESENT_WITH_MEDIA
;
116 FreePool (HandleBuffer
);
117 return FLOPPY_PRESENT_NO_MEDIA
;
121 FreePool (HandleBuffer
);
123 return FLOPPY_NOT_PRESENT
;
129 Complete build of BBS TABLE.
131 @param Private Legacy BIOS Instance data
132 @param BbsTable BBS Table passed to 16-bit code
134 @retval EFI_SUCCESS Removable media not present
139 IN LEGACY_BIOS_INSTANCE
*Private
,
140 IN BBS_TABLE
*BbsTable
147 EFI_HANDLE
*BlockIoHandles
;
148 UINTN NumberBlockIoHandles
;
153 // First entry is floppy.
154 // Next 2*MAX_IDE_CONTROLLER entries are for onboard IDE.
155 // Next n entries are filled in after each ROM is dispatched.
156 // Entry filled in if follow BBS spec. See LegacyPci.c
157 // Next entries are for non-BBS compliant ROMS. They are filled in by
158 // 16-bit code during Legacy16UpdateBbs invocation. Final BootPriority
159 // occurs after that invocation.
162 // Set default state.
164 IsHaveMediaInFloppy
= HasMediaInFloppy ();
165 if (IsHaveMediaInFloppy
== FLOPPY_PRESENT_WITH_MEDIA
) {
166 BbsTable
[0].BootPriority
= BBS_UNPRIORITIZED_ENTRY
;
168 if (IsHaveMediaInFloppy
== FLOPPY_PRESENT_NO_MEDIA
) {
169 BbsTable
[0].BootPriority
= BBS_LOWEST_PRIORITY
;
171 BbsTable
[0].BootPriority
= BBS_IGNORE_ENTRY
;
175 BbsTable
[0].Bus
= 0xff;
176 BbsTable
[0].Device
= 0xff;
177 BbsTable
[0].Function
= 0xff;
178 BbsTable
[0].DeviceType
= BBS_FLOPPY
;
179 BbsTable
[0].Class
= 01;
180 BbsTable
[0].SubClass
= 02;
181 BbsTable
[0].StatusFlags
.OldPosition
= 0;
182 BbsTable
[0].StatusFlags
.Reserved1
= 0;
183 BbsTable
[0].StatusFlags
.Enabled
= 0;
184 BbsTable
[0].StatusFlags
.Failed
= 0;
185 BbsTable
[0].StatusFlags
.MediaPresent
= 0;
186 BbsTable
[0].StatusFlags
.Reserved2
= 0;
189 // Onboard HDD - Note Each HDD controller controls 2 drives
192 HddInfo
= &Private
->IntThunk
->EfiToLegacy16BootTable
.HddInfo
[0];
194 // Get IDE Drive Info
196 LegacyBiosBuildIdeData (Private
, &HddInfo
, 0);
198 for (HddIndex
= 0; HddIndex
< MAX_IDE_CONTROLLER
; HddIndex
++) {
200 BbsIndex
= HddIndex
* 2 + 1;
201 for (Index
= 0; Index
< 2; ++Index
) {
203 BbsTable
[BbsIndex
+ Index
].Bus
= HddInfo
[HddIndex
].Bus
;
204 BbsTable
[BbsIndex
+ Index
].Device
= HddInfo
[HddIndex
].Device
;
205 BbsTable
[BbsIndex
+ Index
].Function
= HddInfo
[HddIndex
].Function
;
206 BbsTable
[BbsIndex
+ Index
].Class
= 01;
207 BbsTable
[BbsIndex
+ Index
].SubClass
= 01;
208 BbsTable
[BbsIndex
+ Index
].StatusFlags
.OldPosition
= 0;
209 BbsTable
[BbsIndex
+ Index
].StatusFlags
.Reserved1
= 0;
210 BbsTable
[BbsIndex
+ Index
].StatusFlags
.Enabled
= 0;
211 BbsTable
[BbsIndex
+ Index
].StatusFlags
.Failed
= 0;
212 BbsTable
[BbsIndex
+ Index
].StatusFlags
.MediaPresent
= 0;
213 BbsTable
[BbsIndex
+ Index
].StatusFlags
.Reserved2
= 0;
216 // If no controller found or no device found set to ignore
217 // else set to unprioritized and set device type
219 if (HddInfo
[HddIndex
].CommandBaseAddress
== 0) {
220 BbsTable
[BbsIndex
+ Index
].BootPriority
= BBS_IGNORE_ENTRY
;
223 if ((HddInfo
[HddIndex
].Status
& (HDD_MASTER_IDE
| HDD_MASTER_ATAPI_CDROM
| HDD_MASTER_ATAPI_ZIPDISK
)) != 0) {
224 BbsTable
[BbsIndex
+ Index
].BootPriority
= BBS_UNPRIORITIZED_ENTRY
;
225 if ((HddInfo
[HddIndex
].Status
& HDD_MASTER_IDE
) != 0) {
226 BbsTable
[BbsIndex
+ Index
].DeviceType
= BBS_HARDDISK
;
227 } else if ((HddInfo
[HddIndex
].Status
& HDD_MASTER_ATAPI_CDROM
) != 0) {
228 BbsTable
[BbsIndex
+ Index
].DeviceType
= BBS_CDROM
;
233 BbsTable
[BbsIndex
+ Index
].DeviceType
= BBS_HARDDISK
;
236 BbsTable
[BbsIndex
+ Index
].BootPriority
= BBS_IGNORE_ENTRY
;
239 if ((HddInfo
[HddIndex
].Status
& (HDD_SLAVE_IDE
| HDD_SLAVE_ATAPI_CDROM
| HDD_SLAVE_ATAPI_ZIPDISK
)) != 0) {
240 BbsTable
[BbsIndex
+ Index
].BootPriority
= BBS_UNPRIORITIZED_ENTRY
;
241 if ((HddInfo
[HddIndex
].Status
& HDD_SLAVE_IDE
) != 0) {
242 BbsTable
[BbsIndex
+ Index
].DeviceType
= BBS_HARDDISK
;
243 } else if ((HddInfo
[HddIndex
].Status
& HDD_SLAVE_ATAPI_CDROM
) != 0) {
244 BbsTable
[BbsIndex
+ Index
].DeviceType
= BBS_CDROM
;
249 BbsTable
[BbsIndex
+ Index
].DeviceType
= BBS_HARDDISK
;
252 BbsTable
[BbsIndex
+ Index
].BootPriority
= BBS_IGNORE_ENTRY
;
260 // Add non-IDE block devices
262 BbsIndex
= HddIndex
* 2 + 1;
264 Status
= gBS
->LocateHandleBuffer (
266 &gEfiBlockIoProtocolGuid
,
268 &NumberBlockIoHandles
,
272 if (!EFI_ERROR (Status
)) {
274 EFI_BLOCK_IO_PROTOCOL
*BlkIo
;
275 EFI_PCI_IO_PROTOCOL
*PciIo
;
276 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
277 EFI_DEVICE_PATH_PROTOCOL
*DevicePathNode
;
278 EFI_HANDLE PciHandle
;
284 for (Removable
= 0; Removable
< 2; Removable
++) {
285 for (BlockIndex
= 0; BlockIndex
< NumberBlockIoHandles
; BlockIndex
++) {
286 Status
= gBS
->HandleProtocol (
287 BlockIoHandles
[BlockIndex
],
288 &gEfiBlockIoProtocolGuid
,
292 if (EFI_ERROR (Status
)) {
297 // Skip the logical partitions
299 if (BlkIo
->Media
->LogicalPartition
) {
304 // Skip the fixed block io then the removable block io
306 if (BlkIo
->Media
->RemovableMedia
== ((Removable
== 0) ? FALSE
: TRUE
)) {
313 Status
= gBS
->HandleProtocol (
314 BlockIoHandles
[BlockIndex
],
315 &gEfiDevicePathProtocolGuid
,
316 (VOID
**) &DevicePath
318 if (EFI_ERROR (Status
)) {
323 // Skip ATA devices as they have already been handled
325 DevicePathNode
= DevicePath
;
326 while (!IsDevicePathEnd (DevicePathNode
)) {
327 if (DevicePathType (DevicePathNode
) == MESSAGING_DEVICE_PATH
&&
328 DevicePathSubType (DevicePathNode
) == MSG_ATAPI_DP
) {
331 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
)) {
370 DEBUG ((DEBUG_WARN
, "CSM cannot use PCI devices in segment %Lu\n",
375 DEBUG ((DEBUG_INFO
, "Add Legacy Bbs entry for PCI %d/%d/%d\n",
376 BusNum
, DevNum
, FuncNum
));
378 BbsTable
[BbsIndex
].Bus
= BusNum
;
379 BbsTable
[BbsIndex
].Device
= DevNum
;
380 BbsTable
[BbsIndex
].Function
= FuncNum
;
381 BbsTable
[BbsIndex
].Class
= 1;
382 BbsTable
[BbsIndex
].SubClass
= 0x80;
383 BbsTable
[BbsIndex
].StatusFlags
.OldPosition
= 0;
384 BbsTable
[BbsIndex
].StatusFlags
.Reserved1
= 0;
385 BbsTable
[BbsIndex
].StatusFlags
.Enabled
= 0;
386 BbsTable
[BbsIndex
].StatusFlags
.Failed
= 0;
387 BbsTable
[BbsIndex
].StatusFlags
.MediaPresent
= 0;
388 BbsTable
[BbsIndex
].StatusFlags
.Reserved2
= 0;
389 BbsTable
[BbsIndex
].DeviceType
= BBS_HARDDISK
;
390 BbsTable
[BbsIndex
].BootPriority
= BBS_UNPRIORITIZED_ENTRY
;
393 if (BbsIndex
== MAX_BBS_ENTRIES
) {
400 FreePool (BlockIoHandles
);
410 @param This Protocol instance pointer.
411 @param HddCount Number of HDD_INFO structures
412 @param HddInfo Onboard IDE controller information
413 @param BbsCount Number of BBS_TABLE structures
414 @param BbsTable List BBS entries
416 @retval EFI_SUCCESS Tables returned
417 @retval EFI_NOT_FOUND resource not found
418 @retval EFI_DEVICE_ERROR can not get BBS table
423 LegacyBiosGetBbsInfo (
424 IN EFI_LEGACY_BIOS_PROTOCOL
*This
,
425 OUT UINT16
*HddCount
,
426 OUT HDD_INFO
**HddInfo
,
427 OUT UINT16
*BbsCount
,
428 OUT BBS_TABLE
**BbsTable
431 LEGACY_BIOS_INSTANCE
*Private
;
432 EFI_IA32_REGISTER_SET Regs
;
433 EFI_TO_COMPATIBILITY16_BOOT_TABLE
*EfiToLegacy16BootTable
;
434 // HDD_INFO *LocalHddInfo;
435 // IN BBS_TABLE *LocalBbsTable;
437 EFI_HANDLE
*HandleBuffer
;
444 Private
= LEGACY_BIOS_INSTANCE_FROM_THIS (This
);
445 EfiToLegacy16BootTable
= &Private
->IntThunk
->EfiToLegacy16BootTable
;
446 // LocalHddInfo = EfiToLegacy16BootTable->HddInfo;
447 // LocalBbsTable = (BBS_TABLE*)(UINTN)EfiToLegacy16BootTable->BbsTable;
449 if (!mBbsTableDoneFlag
) {
450 mBbsTable
= Private
->BbsTablePtr
;
453 // Always enable disk controllers so 16-bit CSM code has valid information for all
457 // Get PciRootBridgeIO protocol
459 gBS
->LocateHandleBuffer (
461 &gEfiPciRootBridgeIoProtocolGuid
,
467 if (NumHandles
== 0) {
468 return EFI_NOT_FOUND
;
471 mBbsTableDoneFlag
= TRUE
;
472 for (Index
= 0; Index
< NumHandles
; Index
++) {
474 // Connect PciRootBridgeIO protocol handle with FALSE parameter to let
475 // PCI bus driver enumerate all subsequent handles
477 gBS
->ConnectController (HandleBuffer
[Index
], NULL
, NULL
, FALSE
);
481 LegacyBiosBuildBbs (Private
, mBbsTable
);
483 Private
->LegacyRegion
->UnLock (Private
->LegacyRegion
, 0xe0000, 0x20000, &Granularity
);
486 // Call into Legacy16 code to add to BBS table for non BBS compliant OPROMs.
488 ZeroMem (&Regs
, sizeof (EFI_IA32_REGISTER_SET
));
489 Regs
.X
.AX
= Legacy16UpdateBbs
;
492 // Pass in handoff data
494 TempData
= (UINTN
) EfiToLegacy16BootTable
;
495 Regs
.X
.ES
= NORMALIZE_EFI_SEGMENT ((UINT32
) TempData
);
496 Regs
.X
.BX
= NORMALIZE_EFI_OFFSET ((UINT32
) TempData
);
498 Private
->LegacyBios
.FarCall86 (
500 Private
->Legacy16CallSegment
,
501 Private
->Legacy16CallOffset
,
507 Private
->Cpu
->FlushDataCache (Private
->Cpu
, 0xE0000, 0x20000, EfiCpuFlushTypeWriteBackInvalidate
);
508 Private
->LegacyRegion
->Lock (Private
->LegacyRegion
, 0xe0000, 0x20000, &Granularity
);
510 if (Regs
.X
.AX
!= 0) {
511 return EFI_DEVICE_ERROR
;
515 if (HandleBuffer
!= NULL
) {
516 FreePool (HandleBuffer
);
519 *HddCount
= MAX_IDE_CONTROLLER
;
520 *HddInfo
= EfiToLegacy16BootTable
->HddInfo
;
521 *BbsTable
= (BBS_TABLE
*)(UINTN
)EfiToLegacy16BootTable
->BbsTable
;
522 *BbsCount
= (UINT16
) (sizeof (Private
->IntThunk
->BbsTable
) / sizeof (BBS_TABLE
));