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);