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
,
69 (VOID
*) &LocalHddInfo
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
,
96 (VOID
*) &LocalHddInfo
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
) ) {
140 PciDevicePath
= (PCI_DEVICE_PATH
*) DevicePathNode
;
143 DevicePathNode
= NextDevicePathNode (DevicePathNode
);
146 if (PciDevicePath
== NULL
) {
151 // Find start of PCI device in HddInfo. The assumption of the data
152 // structure is 2 controllers(channels) per PCI device and each
153 // controller can have 2 drives(devices).
154 // HddInfo[PciIndex+0].[0] = Channel[0].Device[0] Primary Master
155 // HddInfo[PciIndex+0].[1] = Channel[0].Device[1] Primary Slave
156 // HddInfo[PciIndex+1].[0] = Channel[1].Device[0] Secondary Master
157 // HddInfo[PciIndex+1].[1] = Channel[1].Device[1] Secondary Slave
158 // @bug eventually need to pass in max number of entries
159 // for end of for loop
161 for (PciIndex
= 0; PciIndex
< 8; PciIndex
++) {
162 if ((PciDevicePath
->Device
== LocalHddInfo
[PciIndex
].Device
) &&
163 (PciDevicePath
->Function
== LocalHddInfo
[PciIndex
].Function
)
173 Status
= DiskInfo
->WhichIde (DiskInfo
, &IdeChannel
, &IdeDevice
);
174 if (!EFI_ERROR (Status
)) {
175 Size
= sizeof (ATAPI_IDENTIFY
);
178 &LocalHddInfo
[PciIndex
+ IdeChannel
].IdentifyDrive
[IdeDevice
],
181 if (IdeChannel
== 0) {
182 LocalHddInfo
[PciIndex
+ IdeChannel
].Status
|= HDD_PRIMARY
;
183 } else if (IdeChannel
== 1) {
184 LocalHddInfo
[PciIndex
+ IdeChannel
].Status
|= HDD_SECONDARY
;
189 Status
= DiskInfo
->Inquiry (
194 if (Status
== EFI_BUFFER_TOO_SMALL
) {
195 InquiryData
= (UINT8
*) AllocatePool (
198 if (InquiryData
!= NULL
) {
199 Status
= DiskInfo
->Inquiry (
206 Status
= EFI_DEVICE_ERROR
;
210 // If ATAPI device then Inquiry will pass and ATA fail.
212 if (!EFI_ERROR (Status
)) {
213 ASSERT (InquiryData
!= NULL
);
215 // If IdeDevice = 0 then set master bit, else slave bit
217 if (IdeDevice
== 0) {
218 if ((InquiryData
[0] & 0x1f) == 0x05) {
219 LocalHddInfo
[PciIndex
+ IdeChannel
].Status
|= HDD_MASTER_ATAPI_CDROM
;
220 } else if ((InquiryData
[0] & 0x1f) == 0x00) {
221 LocalHddInfo
[PciIndex
+ IdeChannel
].Status
|= HDD_MASTER_ATAPI_ZIPDISK
;
224 if ((InquiryData
[0] & 0x1f) == 0x05) {
225 LocalHddInfo
[PciIndex
+ IdeChannel
].Status
|= HDD_SLAVE_ATAPI_CDROM
;
226 } else if ((InquiryData
[0] & 0x1f) == 0x00) {
227 LocalHddInfo
[PciIndex
+ IdeChannel
].Status
|= HDD_SLAVE_ATAPI_ZIPDISK
;
230 FreePool (InquiryData
);
232 if (IdeDevice
== 0) {
233 LocalHddInfo
[PciIndex
+ IdeChannel
].Status
|= HDD_MASTER_IDE
;
235 LocalHddInfo
[PciIndex
+ IdeChannel
].Status
|= HDD_SLAVE_IDE
;
242 if (HandleBuffer
!= NULL
) {
243 FreePool (HandleBuffer
);
251 If the IDE channel is in compatibility (legacy) mode, remove all
252 PCI I/O BAR addresses from the controller.
254 @param IdeController The handle of target IDE controller
259 InitLegacyIdeController (
260 IN EFI_HANDLE IdeController
263 EFI_PCI_IO_PROTOCOL
*PciIo
;
269 // If the IDE channel is in compatibility (legacy) mode, remove all
270 // PCI I/O BAR addresses from the controller. Some software gets
271 // confused if an IDE controller is in compatibility (legacy) mode
272 // and has PCI I/O resources allocated
274 Status
= gBS
->HandleProtocol (
276 &gEfiPciIoProtocolGuid
,
279 if (EFI_ERROR (Status
)) {
283 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint8
, 0, sizeof (PciData
), &PciData
);
284 if (EFI_ERROR (Status
)) {
289 // Check whether this is IDE
291 if ((PciData
.Hdr
.ClassCode
[2] != PCI_CLASS_MASS_STORAGE
) ||
292 (PciData
.Hdr
.ClassCode
[1] != PCI_CLASS_MASS_STORAGE_IDE
)) {
297 // Clear bar for legacy IDE
300 if ((PciData
.Hdr
.ClassCode
[0] & IDE_PI_REGISTER_PNE
) == 0) {
301 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x10, 1, &IOBarClear
);
302 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x14, 1, &IOBarClear
);
304 if ((PciData
.Hdr
.ClassCode
[0] & IDE_PI_REGISTER_SNE
) == 0) {
305 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x18, 1, &IOBarClear
);
306 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x1C, 1, &IOBarClear
);