]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyIde.c
IntelFrameworkModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / IntelFrameworkModulePkg / Csm / LegacyBiosDxe / LegacyIde.c
CommitLineData
bcecde14 1/** @file\r
2 Collect IDE information from Native EFI Driver\r
3\r
0a6f4824 4Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
bcecde14 5\r
c0a00b14 6SPDX-License-Identifier: BSD-2-Clause-Patent\r
bcecde14 7\r
8**/\r
9\r
10#include "LegacyBiosInterface.h"\r
11\r
12BOOLEAN mIdeDataBuiltFlag = FALSE;\r
13\r
14/**\r
15 Collect IDE Inquiry data from the IDE disks\r
16\r
17 @param Private Legacy BIOS Instance data\r
18 @param HddInfo Hdd Information\r
19 @param Flag Reconnect IdeController or not\r
20\r
21 @retval EFI_SUCCESS It should always work.\r
22\r
23**/\r
24EFI_STATUS\r
25LegacyBiosBuildIdeData (\r
26 IN LEGACY_BIOS_INSTANCE *Private,\r
27 IN HDD_INFO **HddInfo,\r
28 IN UINT16 Flag\r
29 )\r
30{\r
31 EFI_STATUS Status;\r
32 EFI_HANDLE IdeController;\r
33 UINTN HandleCount;\r
34 EFI_HANDLE *HandleBuffer;\r
35 UINTN Index;\r
36 EFI_DISK_INFO_PROTOCOL *DiskInfo;\r
37 UINT32 IdeChannel;\r
38 UINT32 IdeDevice;\r
39 UINT32 Size;\r
40 UINT8 *InquiryData;\r
41 UINT32 InquiryDataSize;\r
42 HDD_INFO *LocalHddInfo;\r
43 UINT32 PciIndex;\r
44 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
45 EFI_DEVICE_PATH_PROTOCOL *DevicePathNode;\r
46 EFI_DEVICE_PATH_PROTOCOL *TempDevicePathNode;\r
47 PCI_DEVICE_PATH *PciDevicePath;\r
48\r
49 //\r
50 // Only build data once\r
51 // We have a problem with GetBbsInfo in that it can be invoked two\r
52 // places. Once in BDS, when all EFI drivers are connected and once in\r
53 // LegacyBoot after all EFI drivers are disconnected causing this routine\r
54 // to hang. In LegacyBoot this function is also called before EFI drivers\r
55 // are disconnected.\r
56 // Cases covered\r
57 // GetBbsInfo invoked in BDS. Both invocations in LegacyBoot ignored.\r
58 // GetBbsInfo not invoked in BDS. First invocation of this function\r
59 // proceeds normally and second via GetBbsInfo ignored.\r
60 //\r
61 PciDevicePath = NULL;\r
62 LocalHddInfo = *HddInfo;\r
63 Status = Private->LegacyBiosPlatform->GetPlatformHandle (\r
64 Private->LegacyBiosPlatform,\r
65 EfiGetPlatformIdeHandle,\r
66 0,\r
67 &HandleBuffer,\r
68 &HandleCount,\r
69 (VOID *) &LocalHddInfo\r
70 );\r
71 if (!EFI_ERROR (Status)) {\r
0a6f4824 72 IdeController = HandleBuffer[0];\r
bcecde14 73 //\r
74 // Force IDE drive spin up!\r
75 //\r
76 if (Flag != 0) {\r
77 gBS->DisconnectController (\r
78 IdeController,\r
79 NULL,\r
80 NULL\r
81 );\r
82 }\r
83\r
84 gBS->ConnectController (IdeController, NULL, NULL, FALSE);\r
85\r
86 //\r
87 // Do GetIdeHandle twice since disconnect/reconnect will switch to native mode\r
88 // And GetIdeHandle will switch to Legacy mode, if required.\r
89 //\r
90 Private->LegacyBiosPlatform->GetPlatformHandle (\r
91 Private->LegacyBiosPlatform,\r
92 EfiGetPlatformIdeHandle,\r
93 0,\r
94 &HandleBuffer,\r
95 &HandleCount,\r
96 (VOID *) &LocalHddInfo\r
97 );\r
98 }\r
99\r
100 mIdeDataBuiltFlag = TRUE;\r
101\r
102 //\r
103 // Get Identity command from all drives\r
104 //\r
105 gBS->LocateHandleBuffer (\r
106 ByProtocol,\r
107 &gEfiDiskInfoProtocolGuid,\r
108 NULL,\r
109 &HandleCount,\r
110 &HandleBuffer\r
111 );\r
112\r
113 Private->IdeDriveCount = (UINT8) HandleCount;\r
114 for (Index = 0; Index < HandleCount; Index++) {\r
115 Status = gBS->HandleProtocol (\r
116 HandleBuffer[Index],\r
117 &gEfiDiskInfoProtocolGuid,\r
118 (VOID **) &DiskInfo\r
119 );\r
120 ASSERT_EFI_ERROR (Status);\r
121\r
122 if (CompareGuid (&DiskInfo->Interface, &gEfiDiskInfoIdeInterfaceGuid)) {\r
123 //\r
124 // Locate which PCI device\r
125 //\r
126 Status = gBS->HandleProtocol (\r
127 HandleBuffer[Index],\r
128 &gEfiDevicePathProtocolGuid,\r
129 (VOID *) &DevicePath\r
130 );\r
131 ASSERT_EFI_ERROR (Status);\r
132\r
133 DevicePathNode = DevicePath;\r
134 while (!IsDevicePathEnd (DevicePathNode)) {\r
135 TempDevicePathNode = NextDevicePathNode (DevicePathNode);\r
136 if ((DevicePathType (DevicePathNode) == HARDWARE_DEVICE_PATH) &&\r
137 ( DevicePathSubType (DevicePathNode) == HW_PCI_DP) &&\r
138 ( DevicePathType(TempDevicePathNode) == MESSAGING_DEVICE_PATH) &&\r
139 ( DevicePathSubType(TempDevicePathNode) == MSG_ATAPI_DP) ) {\r
140 PciDevicePath = (PCI_DEVICE_PATH *) DevicePathNode;\r
141 break;\r
142 }\r
143 DevicePathNode = NextDevicePathNode (DevicePathNode);\r
144 }\r
145\r
146 if (PciDevicePath == NULL) {\r
147 continue;\r
148 }\r
149\r
150 //\r
151 // Find start of PCI device in HddInfo. The assumption of the data\r
152 // structure is 2 controllers(channels) per PCI device and each\r
153 // controller can have 2 drives(devices).\r
154 // HddInfo[PciIndex+0].[0] = Channel[0].Device[0] Primary Master\r
155 // HddInfo[PciIndex+0].[1] = Channel[0].Device[1] Primary Slave\r
156 // HddInfo[PciIndex+1].[0] = Channel[1].Device[0] Secondary Master\r
157 // HddInfo[PciIndex+1].[1] = Channel[1].Device[1] Secondary Slave\r
158 // @bug eventually need to pass in max number of entries\r
159 // for end of for loop\r
160 //\r
161 for (PciIndex = 0; PciIndex < 8; PciIndex++) {\r
162 if ((PciDevicePath->Device == LocalHddInfo[PciIndex].Device) &&\r
163 (PciDevicePath->Function == LocalHddInfo[PciIndex].Function)\r
164 ) {\r
165 break;\r
166 }\r
167 }\r
168\r
169 if (PciIndex == 8) {\r
170 continue;\r
171 }\r
172\r
173 Status = DiskInfo->WhichIde (DiskInfo, &IdeChannel, &IdeDevice);\r
174 if (!EFI_ERROR (Status)) {\r
175 Size = sizeof (ATAPI_IDENTIFY);\r
176 DiskInfo->Identify (\r
177 DiskInfo,\r
178 &LocalHddInfo[PciIndex + IdeChannel].IdentifyDrive[IdeDevice],\r
179 &Size\r
180 );\r
181 if (IdeChannel == 0) {\r
182 LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_PRIMARY;\r
183 } else if (IdeChannel == 1) {\r
184 LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_SECONDARY;\r
185 }\r
186\r
187 InquiryData = NULL;\r
188 InquiryDataSize = 0;\r
189 Status = DiskInfo->Inquiry (\r
190 DiskInfo,\r
191 NULL,\r
192 &InquiryDataSize\r
193 );\r
194 if (Status == EFI_BUFFER_TOO_SMALL) {\r
195 InquiryData = (UINT8 *) AllocatePool (\r
196 InquiryDataSize\r
197 );\r
198 if (InquiryData != NULL) {\r
199 Status = DiskInfo->Inquiry (\r
200 DiskInfo,\r
201 InquiryData,\r
202 &InquiryDataSize\r
203 );\r
204 }\r
205 } else {\r
206 Status = EFI_DEVICE_ERROR;\r
207 }\r
208\r
209 //\r
210 // If ATAPI device then Inquiry will pass and ATA fail.\r
211 //\r
212 if (!EFI_ERROR (Status)) {\r
213 ASSERT (InquiryData != NULL);\r
214 //\r
215 // If IdeDevice = 0 then set master bit, else slave bit\r
216 //\r
217 if (IdeDevice == 0) {\r
218 if ((InquiryData[0] & 0x1f) == 0x05) {\r
219 LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_MASTER_ATAPI_CDROM;\r
220 } else if ((InquiryData[0] & 0x1f) == 0x00) {\r
221 LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_MASTER_ATAPI_ZIPDISK;\r
222 }\r
223 } else {\r
224 if ((InquiryData[0] & 0x1f) == 0x05) {\r
225 LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_SLAVE_ATAPI_CDROM;\r
226 } else if ((InquiryData[0] & 0x1f) == 0x00) {\r
227 LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_SLAVE_ATAPI_ZIPDISK;\r
228 }\r
229 }\r
230 FreePool (InquiryData);\r
231 } else {\r
232 if (IdeDevice == 0) {\r
233 LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_MASTER_IDE;\r
234 } else {\r
235 LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_SLAVE_IDE;\r
236 }\r
237 }\r
238 }\r
239 }\r
240 }\r
241\r
242 if (HandleBuffer != NULL) {\r
243 FreePool (HandleBuffer);\r
244 }\r
245\r
246 return EFI_SUCCESS;\r
247}\r
248\r
249\r
250/**\r
251 If the IDE channel is in compatibility (legacy) mode, remove all\r
252 PCI I/O BAR addresses from the controller.\r
253\r
254 @param IdeController The handle of target IDE controller\r
255\r
256\r
257**/\r
258VOID\r
259InitLegacyIdeController (\r
260 IN EFI_HANDLE IdeController\r
261 )\r
262{\r
263 EFI_PCI_IO_PROTOCOL *PciIo;\r
bcecde14 264 UINT32 IOBarClear;\r
265 EFI_STATUS Status;\r
6d55565d 266 PCI_TYPE00 PciData;\r
bcecde14 267\r
268 //\r
269 // If the IDE channel is in compatibility (legacy) mode, remove all\r
270 // PCI I/O BAR addresses from the controller. Some software gets\r
271 // confused if an IDE controller is in compatibility (legacy) mode\r
272 // and has PCI I/O resources allocated\r
273 //\r
274 Status = gBS->HandleProtocol (\r
0a6f4824
LG
275 IdeController,\r
276 &gEfiPciIoProtocolGuid,\r
d316f1dc 277 (VOID **)&PciIo\r
bcecde14 278 );\r
6d55565d 279 if (EFI_ERROR (Status)) {\r
280 return ;\r
281 }\r
282\r
283 Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0, sizeof (PciData), &PciData);\r
284 if (EFI_ERROR (Status)) {\r
285 return ;\r
286 }\r
287\r
288 //\r
289 // Check whether this is IDE\r
290 //\r
291 if ((PciData.Hdr.ClassCode[2] != PCI_CLASS_MASS_STORAGE) ||\r
292 (PciData.Hdr.ClassCode[1] != PCI_CLASS_MASS_STORAGE_IDE)) {\r
293 return ;\r
294 }\r
295\r
296 //\r
297 // Clear bar for legacy IDE\r
298 //\r
299 IOBarClear = 0x00;\r
300 if ((PciData.Hdr.ClassCode[0] & IDE_PI_REGISTER_PNE) == 0) {\r
301 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x10, 1, &IOBarClear);\r
302 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x14, 1, &IOBarClear);\r
303 }\r
304 if ((PciData.Hdr.ClassCode[0] & IDE_PI_REGISTER_SNE) == 0) {\r
305 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x18, 1, &IOBarClear);\r
306 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x1C, 1, &IOBarClear);\r
bcecde14 307 }\r
308\r
309 return ;\r
310}\r