2 Collect IDE information from Native EFI Driver
4 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include "LegacyBiosInterface.h"
12 BOOLEAN mIdeDataBuiltFlag
= FALSE
;
15 Collect IDE Inquiry data from the IDE disks
17 @param Private Legacy BIOS Instance data
18 @param HddInfo Hdd Information
19 @param Flag Reconnect IdeController or not
21 @retval EFI_SUCCESS It should always work.
25 LegacyBiosBuildIdeData (
26 IN LEGACY_BIOS_INSTANCE
*Private
,
27 IN HDD_INFO
**HddInfo
,
32 EFI_HANDLE IdeController
;
34 EFI_HANDLE
*HandleBuffer
;
36 EFI_DISK_INFO_PROTOCOL
*DiskInfo
;
41 UINT32 InquiryDataSize
;
42 HDD_INFO
*LocalHddInfo
;
44 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
45 EFI_DEVICE_PATH_PROTOCOL
*DevicePathNode
;
46 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePathNode
;
47 PCI_DEVICE_PATH
*PciDevicePath
;
50 // Only build data once
51 // We have a problem with GetBbsInfo in that it can be invoked two
52 // places. Once in BDS, when all EFI drivers are connected and once in
53 // LegacyBoot after all EFI drivers are disconnected causing this routine
54 // to hang. In LegacyBoot this function is also called before EFI drivers
57 // GetBbsInfo invoked in BDS. Both invocations in LegacyBoot ignored.
58 // GetBbsInfo not invoked in BDS. First invocation of this function
59 // proceeds normally and second via GetBbsInfo ignored.
62 LocalHddInfo
= *HddInfo
;
63 Status
= Private
->LegacyBiosPlatform
->GetPlatformHandle (
64 Private
->LegacyBiosPlatform
,
65 EfiGetPlatformIdeHandle
,
71 if (!EFI_ERROR (Status
)) {
72 IdeController
= HandleBuffer
[0];
74 // Force IDE drive spin up!
77 gBS
->DisconnectController (
84 gBS
->ConnectController (IdeController
, NULL
, NULL
, FALSE
);
87 // Do GetIdeHandle twice since disconnect/reconnect will switch to native mode
88 // And GetIdeHandle will switch to Legacy mode, if required.
90 Private
->LegacyBiosPlatform
->GetPlatformHandle (
91 Private
->LegacyBiosPlatform
,
92 EfiGetPlatformIdeHandle
,
100 mIdeDataBuiltFlag
= TRUE
;
103 // Get Identity command from all drives
105 gBS
->LocateHandleBuffer (
107 &gEfiDiskInfoProtocolGuid
,
113 Private
->IdeDriveCount
= (UINT8
)HandleCount
;
114 for (Index
= 0; Index
< HandleCount
; Index
++) {
115 Status
= gBS
->HandleProtocol (
117 &gEfiDiskInfoProtocolGuid
,
120 ASSERT_EFI_ERROR (Status
);
122 if (CompareGuid (&DiskInfo
->Interface
, &gEfiDiskInfoIdeInterfaceGuid
)) {
124 // Locate which PCI device
126 Status
= gBS
->HandleProtocol (
128 &gEfiDevicePathProtocolGuid
,
131 ASSERT_EFI_ERROR (Status
);
133 DevicePathNode
= DevicePath
;
134 while (!IsDevicePathEnd (DevicePathNode
)) {
135 TempDevicePathNode
= NextDevicePathNode (DevicePathNode
);
136 if ((DevicePathType (DevicePathNode
) == HARDWARE_DEVICE_PATH
) &&
137 (DevicePathSubType (DevicePathNode
) == HW_PCI_DP
) &&
138 (DevicePathType (TempDevicePathNode
) == MESSAGING_DEVICE_PATH
) &&
139 (DevicePathSubType (TempDevicePathNode
) == MSG_ATAPI_DP
))
141 PciDevicePath
= (PCI_DEVICE_PATH
*)DevicePathNode
;
145 DevicePathNode
= NextDevicePathNode (DevicePathNode
);
148 if (PciDevicePath
== NULL
) {
153 // Find start of PCI device in HddInfo. The assumption of the data
154 // structure is 2 controllers(channels) per PCI device and each
155 // controller can have 2 drives(devices).
156 // HddInfo[PciIndex+0].[0] = Channel[0].Device[0] Primary Master
157 // HddInfo[PciIndex+0].[1] = Channel[0].Device[1] Primary Slave
158 // HddInfo[PciIndex+1].[0] = Channel[1].Device[0] Secondary Master
159 // HddInfo[PciIndex+1].[1] = Channel[1].Device[1] Secondary Slave
160 // @bug eventually need to pass in max number of entries
161 // for end of for loop
163 for (PciIndex
= 0; PciIndex
< 8; PciIndex
++) {
164 if ((PciDevicePath
->Device
== LocalHddInfo
[PciIndex
].Device
) &&
165 (PciDevicePath
->Function
== LocalHddInfo
[PciIndex
].Function
)
176 Status
= DiskInfo
->WhichIde (DiskInfo
, &IdeChannel
, &IdeDevice
);
177 if (!EFI_ERROR (Status
)) {
178 Size
= sizeof (ATAPI_IDENTIFY
);
181 &LocalHddInfo
[PciIndex
+ IdeChannel
].IdentifyDrive
[IdeDevice
],
184 if (IdeChannel
== 0) {
185 LocalHddInfo
[PciIndex
+ IdeChannel
].Status
|= HDD_PRIMARY
;
186 } else if (IdeChannel
== 1) {
187 LocalHddInfo
[PciIndex
+ IdeChannel
].Status
|= HDD_SECONDARY
;
192 Status
= DiskInfo
->Inquiry (
197 if (Status
== EFI_BUFFER_TOO_SMALL
) {
198 InquiryData
= (UINT8
*)AllocatePool (
201 if (InquiryData
!= NULL
) {
202 Status
= DiskInfo
->Inquiry (
209 Status
= EFI_DEVICE_ERROR
;
213 // If ATAPI device then Inquiry will pass and ATA fail.
215 if (!EFI_ERROR (Status
)) {
216 ASSERT (InquiryData
!= NULL
);
218 // If IdeDevice = 0 then set master bit, else slave bit
220 if (IdeDevice
== 0) {
221 if ((InquiryData
[0] & 0x1f) == 0x05) {
222 LocalHddInfo
[PciIndex
+ IdeChannel
].Status
|= HDD_MASTER_ATAPI_CDROM
;
223 } else if ((InquiryData
[0] & 0x1f) == 0x00) {
224 LocalHddInfo
[PciIndex
+ IdeChannel
].Status
|= HDD_MASTER_ATAPI_ZIPDISK
;
227 if ((InquiryData
[0] & 0x1f) == 0x05) {
228 LocalHddInfo
[PciIndex
+ IdeChannel
].Status
|= HDD_SLAVE_ATAPI_CDROM
;
229 } else if ((InquiryData
[0] & 0x1f) == 0x00) {
230 LocalHddInfo
[PciIndex
+ IdeChannel
].Status
|= HDD_SLAVE_ATAPI_ZIPDISK
;
234 FreePool (InquiryData
);
236 if (IdeDevice
== 0) {
237 LocalHddInfo
[PciIndex
+ IdeChannel
].Status
|= HDD_MASTER_IDE
;
239 LocalHddInfo
[PciIndex
+ IdeChannel
].Status
|= HDD_SLAVE_IDE
;
246 if (HandleBuffer
!= NULL
) {
247 FreePool (HandleBuffer
);
254 If the IDE channel is in compatibility (legacy) mode, remove all
255 PCI I/O BAR addresses from the controller.
257 @param IdeController The handle of target IDE controller
262 InitLegacyIdeController (
263 IN EFI_HANDLE IdeController
266 EFI_PCI_IO_PROTOCOL
*PciIo
;
272 // If the IDE channel is in compatibility (legacy) mode, remove all
273 // PCI I/O BAR addresses from the controller. Some software gets
274 // confused if an IDE controller is in compatibility (legacy) mode
275 // and has PCI I/O resources allocated
277 Status
= gBS
->HandleProtocol (
279 &gEfiPciIoProtocolGuid
,
282 if (EFI_ERROR (Status
)) {
286 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint8
, 0, sizeof (PciData
), &PciData
);
287 if (EFI_ERROR (Status
)) {
292 // Check whether this is IDE
294 if ((PciData
.Hdr
.ClassCode
[2] != PCI_CLASS_MASS_STORAGE
) ||
295 (PciData
.Hdr
.ClassCode
[1] != PCI_CLASS_MASS_STORAGE_IDE
))
301 // Clear bar for legacy IDE
304 if ((PciData
.Hdr
.ClassCode
[0] & IDE_PI_REGISTER_PNE
) == 0) {
305 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x10, 1, &IOBarClear
);
306 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x14, 1, &IOBarClear
);
309 if ((PciData
.Hdr
.ClassCode
[0] & IDE_PI_REGISTER_SNE
) == 0) {
310 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x18, 1, &IOBarClear
);
311 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x1C, 1, &IOBarClear
);