2 Collect IDE information from Native EFI Driver
4 Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions
8 of the BSD License which accompanies this distribution. The
9 full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 #include "LegacyBiosInterface.h"
19 BOOLEAN mIdeDataBuiltFlag
= FALSE
;
22 Collect IDE Inquiry data from the IDE disks
24 @param Private Legacy BIOS Instance data
25 @param HddInfo Hdd Information
26 @param Flag Reconnect IdeController or not
28 @retval EFI_SUCCESS It should always work.
32 LegacyBiosBuildIdeData (
33 IN LEGACY_BIOS_INSTANCE
*Private
,
34 IN HDD_INFO
**HddInfo
,
39 EFI_HANDLE IdeController
;
41 EFI_HANDLE
*HandleBuffer
;
43 EFI_DISK_INFO_PROTOCOL
*DiskInfo
;
48 UINT32 InquiryDataSize
;
49 HDD_INFO
*LocalHddInfo
;
51 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
52 EFI_DEVICE_PATH_PROTOCOL
*DevicePathNode
;
53 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePathNode
;
54 PCI_DEVICE_PATH
*PciDevicePath
;
57 // Only build data once
58 // We have a problem with GetBbsInfo in that it can be invoked two
59 // places. Once in BDS, when all EFI drivers are connected and once in
60 // LegacyBoot after all EFI drivers are disconnected causing this routine
61 // to hang. In LegacyBoot this function is also called before EFI drivers
64 // GetBbsInfo invoked in BDS. Both invocations in LegacyBoot ignored.
65 // GetBbsInfo not invoked in BDS. First invocation of this function
66 // proceeds normally and second via GetBbsInfo ignored.
69 LocalHddInfo
= *HddInfo
;
70 Status
= Private
->LegacyBiosPlatform
->GetPlatformHandle (
71 Private
->LegacyBiosPlatform
,
72 EfiGetPlatformIdeHandle
,
76 (VOID
*) &LocalHddInfo
78 if (!EFI_ERROR (Status
)) {
79 IdeController
= HandleBuffer
[0];
81 // Force IDE drive spin up!
84 gBS
->DisconnectController (
91 gBS
->ConnectController (IdeController
, NULL
, NULL
, FALSE
);
94 // Do GetIdeHandle twice since disconnect/reconnect will switch to native mode
95 // And GetIdeHandle will switch to Legacy mode, if required.
97 Private
->LegacyBiosPlatform
->GetPlatformHandle (
98 Private
->LegacyBiosPlatform
,
99 EfiGetPlatformIdeHandle
,
103 (VOID
*) &LocalHddInfo
107 mIdeDataBuiltFlag
= TRUE
;
110 // Get Identity command from all drives
112 gBS
->LocateHandleBuffer (
114 &gEfiDiskInfoProtocolGuid
,
120 Private
->IdeDriveCount
= (UINT8
) HandleCount
;
121 for (Index
= 0; Index
< HandleCount
; Index
++) {
122 Status
= gBS
->HandleProtocol (
124 &gEfiDiskInfoProtocolGuid
,
127 ASSERT_EFI_ERROR (Status
);
129 if (CompareGuid (&DiskInfo
->Interface
, &gEfiDiskInfoIdeInterfaceGuid
)) {
131 // Locate which PCI device
133 Status
= gBS
->HandleProtocol (
135 &gEfiDevicePathProtocolGuid
,
138 ASSERT_EFI_ERROR (Status
);
140 DevicePathNode
= DevicePath
;
141 while (!IsDevicePathEnd (DevicePathNode
)) {
142 TempDevicePathNode
= NextDevicePathNode (DevicePathNode
);
143 if ((DevicePathType (DevicePathNode
) == HARDWARE_DEVICE_PATH
) &&
144 ( DevicePathSubType (DevicePathNode
) == HW_PCI_DP
) &&
145 ( DevicePathType(TempDevicePathNode
) == MESSAGING_DEVICE_PATH
) &&
146 ( DevicePathSubType(TempDevicePathNode
) == MSG_ATAPI_DP
) ) {
147 PciDevicePath
= (PCI_DEVICE_PATH
*) DevicePathNode
;
150 DevicePathNode
= NextDevicePathNode (DevicePathNode
);
153 if (PciDevicePath
== NULL
) {
158 // Find start of PCI device in HddInfo. The assumption of the data
159 // structure is 2 controllers(channels) per PCI device and each
160 // controller can have 2 drives(devices).
161 // HddInfo[PciIndex+0].[0] = Channel[0].Device[0] Primary Master
162 // HddInfo[PciIndex+0].[1] = Channel[0].Device[1] Primary Slave
163 // HddInfo[PciIndex+1].[0] = Channel[1].Device[0] Secondary Master
164 // HddInfo[PciIndex+1].[1] = Channel[1].Device[1] Secondary Slave
165 // @bug eventually need to pass in max number of entries
166 // for end of for loop
168 for (PciIndex
= 0; PciIndex
< 8; PciIndex
++) {
169 if ((PciDevicePath
->Device
== LocalHddInfo
[PciIndex
].Device
) &&
170 (PciDevicePath
->Function
== LocalHddInfo
[PciIndex
].Function
)
180 Status
= DiskInfo
->WhichIde (DiskInfo
, &IdeChannel
, &IdeDevice
);
181 if (!EFI_ERROR (Status
)) {
182 Size
= sizeof (ATAPI_IDENTIFY
);
185 &LocalHddInfo
[PciIndex
+ IdeChannel
].IdentifyDrive
[IdeDevice
],
188 if (IdeChannel
== 0) {
189 LocalHddInfo
[PciIndex
+ IdeChannel
].Status
|= HDD_PRIMARY
;
190 } else if (IdeChannel
== 1) {
191 LocalHddInfo
[PciIndex
+ IdeChannel
].Status
|= HDD_SECONDARY
;
196 Status
= DiskInfo
->Inquiry (
201 if (Status
== EFI_BUFFER_TOO_SMALL
) {
202 InquiryData
= (UINT8
*) AllocatePool (
205 if (InquiryData
!= NULL
) {
206 Status
= DiskInfo
->Inquiry (
213 Status
= EFI_DEVICE_ERROR
;
217 // If ATAPI device then Inquiry will pass and ATA fail.
219 if (!EFI_ERROR (Status
)) {
220 ASSERT (InquiryData
!= NULL
);
222 // If IdeDevice = 0 then set master bit, else slave bit
224 if (IdeDevice
== 0) {
225 if ((InquiryData
[0] & 0x1f) == 0x05) {
226 LocalHddInfo
[PciIndex
+ IdeChannel
].Status
|= HDD_MASTER_ATAPI_CDROM
;
227 } else if ((InquiryData
[0] & 0x1f) == 0x00) {
228 LocalHddInfo
[PciIndex
+ IdeChannel
].Status
|= HDD_MASTER_ATAPI_ZIPDISK
;
231 if ((InquiryData
[0] & 0x1f) == 0x05) {
232 LocalHddInfo
[PciIndex
+ IdeChannel
].Status
|= HDD_SLAVE_ATAPI_CDROM
;
233 } else if ((InquiryData
[0] & 0x1f) == 0x00) {
234 LocalHddInfo
[PciIndex
+ IdeChannel
].Status
|= HDD_SLAVE_ATAPI_ZIPDISK
;
237 FreePool (InquiryData
);
239 if (IdeDevice
== 0) {
240 LocalHddInfo
[PciIndex
+ IdeChannel
].Status
|= HDD_MASTER_IDE
;
242 LocalHddInfo
[PciIndex
+ IdeChannel
].Status
|= HDD_SLAVE_IDE
;
249 if (HandleBuffer
!= NULL
) {
250 FreePool (HandleBuffer
);
258 If the IDE channel is in compatibility (legacy) mode, remove all
259 PCI I/O BAR addresses from the controller.
261 @param IdeController The handle of target IDE controller
266 InitLegacyIdeController (
267 IN EFI_HANDLE IdeController
270 EFI_PCI_IO_PROTOCOL
*PciIo
;
276 // If the IDE channel is in compatibility (legacy) mode, remove all
277 // PCI I/O BAR addresses from the controller. Some software gets
278 // confused if an IDE controller is in compatibility (legacy) mode
279 // and has PCI I/O resources allocated
281 Status
= gBS
->HandleProtocol (
283 &gEfiPciIoProtocolGuid
,
286 if (!EFI_ERROR (Status
)) {
288 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint8
, 0x09, 1, &Pi
);
289 if ((Pi
& 0x01) == 0) {
290 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x10, 1, &IOBarClear
);
291 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x14, 1, &IOBarClear
);
293 if ((Pi
& 0x04) == 0) {
294 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x18, 1, &IOBarClear
);
295 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x1C, 1, &IOBarClear
);