]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/Csm/LegacyBiosDxe/LegacyIde.c
OvmfPkg: Apply uncrustify changes
[mirror_edk2.git] / OvmfPkg / Csm / LegacyBiosDxe / LegacyIde.c
CommitLineData
b522c77b
HW
1/** @file\r
2 Collect IDE information from Native EFI Driver\r
3\r
4Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
5\r
6SPDX-License-Identifier: BSD-2-Clause-Patent\r
7\r
8**/\r
9\r
10#include "LegacyBiosInterface.h"\r
11\r
ac0a286f 12BOOLEAN mIdeDataBuiltFlag = FALSE;\r
b522c77b
HW
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
ac0a286f
MK
26 IN LEGACY_BIOS_INSTANCE *Private,\r
27 IN HDD_INFO **HddInfo,\r
28 IN UINT16 Flag\r
b522c77b
HW
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
ac0a286f
MK
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
b522c77b
HW
71 if (!EFI_ERROR (Status)) {\r
72 IdeController = HandleBuffer[0];\r
73 //\r
74 // Force IDE drive spin up!\r
75 //\r
76 if (Flag != 0) {\r
77 gBS->DisconnectController (\r
ac0a286f
MK
78 IdeController,\r
79 NULL,\r
80 NULL\r
81 );\r
b522c77b
HW
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
ac0a286f
MK
91 Private->LegacyBiosPlatform,\r
92 EfiGetPlatformIdeHandle,\r
93 0,\r
94 &HandleBuffer,\r
95 &HandleCount,\r
96 (VOID *)&LocalHddInfo\r
97 );\r
b522c77b
HW
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
ac0a286f
MK
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
b522c77b
HW
114 for (Index = 0; Index < HandleCount; Index++) {\r
115 Status = gBS->HandleProtocol (\r
116 HandleBuffer[Index],\r
117 &gEfiDiskInfoProtocolGuid,\r
ac0a286f 118 (VOID **)&DiskInfo\r
b522c77b
HW
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
ac0a286f 129 (VOID *)&DevicePath\r
b522c77b
HW
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
ac0a286f
MK
137 (DevicePathSubType (DevicePathNode) == HW_PCI_DP) &&\r
138 (DevicePathType (TempDevicePathNode) == MESSAGING_DEVICE_PATH) &&\r
139 (DevicePathSubType (TempDevicePathNode) == MSG_ATAPI_DP))\r
140 {\r
141 PciDevicePath = (PCI_DEVICE_PATH *)DevicePathNode;\r
b522c77b
HW
142 break;\r
143 }\r
ac0a286f 144\r
b522c77b
HW
145 DevicePathNode = NextDevicePathNode (DevicePathNode);\r
146 }\r
147\r
148 if (PciDevicePath == NULL) {\r
149 continue;\r
150 }\r
151\r
152 //\r
153 // Find start of PCI device in HddInfo. The assumption of the data\r
154 // structure is 2 controllers(channels) per PCI device and each\r
155 // controller can have 2 drives(devices).\r
156 // HddInfo[PciIndex+0].[0] = Channel[0].Device[0] Primary Master\r
157 // HddInfo[PciIndex+0].[1] = Channel[0].Device[1] Primary Slave\r
158 // HddInfo[PciIndex+1].[0] = Channel[1].Device[0] Secondary Master\r
159 // HddInfo[PciIndex+1].[1] = Channel[1].Device[1] Secondary Slave\r
160 // @bug eventually need to pass in max number of entries\r
161 // for end of for loop\r
162 //\r
163 for (PciIndex = 0; PciIndex < 8; PciIndex++) {\r
164 if ((PciDevicePath->Device == LocalHddInfo[PciIndex].Device) &&\r
165 (PciDevicePath->Function == LocalHddInfo[PciIndex].Function)\r
ac0a286f
MK
166 )\r
167 {\r
b522c77b
HW
168 break;\r
169 }\r
170 }\r
171\r
172 if (PciIndex == 8) {\r
173 continue;\r
174 }\r
175\r
176 Status = DiskInfo->WhichIde (DiskInfo, &IdeChannel, &IdeDevice);\r
177 if (!EFI_ERROR (Status)) {\r
178 Size = sizeof (ATAPI_IDENTIFY);\r
179 DiskInfo->Identify (\r
180 DiskInfo,\r
181 &LocalHddInfo[PciIndex + IdeChannel].IdentifyDrive[IdeDevice],\r
182 &Size\r
183 );\r
184 if (IdeChannel == 0) {\r
185 LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_PRIMARY;\r
186 } else if (IdeChannel == 1) {\r
187 LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_SECONDARY;\r
188 }\r
189\r
190 InquiryData = NULL;\r
191 InquiryDataSize = 0;\r
ac0a286f
MK
192 Status = DiskInfo->Inquiry (\r
193 DiskInfo,\r
194 NULL,\r
195 &InquiryDataSize\r
196 );\r
b522c77b 197 if (Status == EFI_BUFFER_TOO_SMALL) {\r
ac0a286f
MK
198 InquiryData = (UINT8 *)AllocatePool (\r
199 InquiryDataSize\r
200 );\r
b522c77b
HW
201 if (InquiryData != NULL) {\r
202 Status = DiskInfo->Inquiry (\r
203 DiskInfo,\r
204 InquiryData,\r
205 &InquiryDataSize\r
206 );\r
207 }\r
208 } else {\r
209 Status = EFI_DEVICE_ERROR;\r
210 }\r
211\r
212 //\r
213 // If ATAPI device then Inquiry will pass and ATA fail.\r
214 //\r
215 if (!EFI_ERROR (Status)) {\r
216 ASSERT (InquiryData != NULL);\r
217 //\r
218 // If IdeDevice = 0 then set master bit, else slave bit\r
219 //\r
220 if (IdeDevice == 0) {\r
221 if ((InquiryData[0] & 0x1f) == 0x05) {\r
222 LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_MASTER_ATAPI_CDROM;\r
223 } else if ((InquiryData[0] & 0x1f) == 0x00) {\r
224 LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_MASTER_ATAPI_ZIPDISK;\r
225 }\r
226 } else {\r
227 if ((InquiryData[0] & 0x1f) == 0x05) {\r
228 LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_SLAVE_ATAPI_CDROM;\r
229 } else if ((InquiryData[0] & 0x1f) == 0x00) {\r
230 LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_SLAVE_ATAPI_ZIPDISK;\r
231 }\r
232 }\r
ac0a286f 233\r
b522c77b
HW
234 FreePool (InquiryData);\r
235 } else {\r
236 if (IdeDevice == 0) {\r
237 LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_MASTER_IDE;\r
238 } else {\r
239 LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_SLAVE_IDE;\r
240 }\r
241 }\r
242 }\r
243 }\r
244 }\r
245\r
246 if (HandleBuffer != NULL) {\r
247 FreePool (HandleBuffer);\r
248 }\r
249\r
250 return EFI_SUCCESS;\r
251}\r
252\r
b522c77b
HW
253/**\r
254 If the IDE channel is in compatibility (legacy) mode, remove all\r
255 PCI I/O BAR addresses from the controller.\r
256\r
257 @param IdeController The handle of target IDE controller\r
258\r
259\r
260**/\r
261VOID\r
262InitLegacyIdeController (\r
ac0a286f 263 IN EFI_HANDLE IdeController\r
b522c77b
HW
264 )\r
265{\r
ac0a286f
MK
266 EFI_PCI_IO_PROTOCOL *PciIo;\r
267 UINT32 IOBarClear;\r
268 EFI_STATUS Status;\r
269 PCI_TYPE00 PciData;\r
b522c77b
HW
270\r
271 //\r
272 // If the IDE channel is in compatibility (legacy) mode, remove all\r
273 // PCI I/O BAR addresses from the controller. Some software gets\r
274 // confused if an IDE controller is in compatibility (legacy) mode\r
275 // and has PCI I/O resources allocated\r
276 //\r
277 Status = gBS->HandleProtocol (\r
278 IdeController,\r
279 &gEfiPciIoProtocolGuid,\r
280 (VOID **)&PciIo\r
281 );\r
282 if (EFI_ERROR (Status)) {\r
ac0a286f 283 return;\r
b522c77b
HW
284 }\r
285\r
286 Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0, sizeof (PciData), &PciData);\r
287 if (EFI_ERROR (Status)) {\r
ac0a286f 288 return;\r
b522c77b
HW
289 }\r
290\r
291 //\r
292 // Check whether this is IDE\r
293 //\r
294 if ((PciData.Hdr.ClassCode[2] != PCI_CLASS_MASS_STORAGE) ||\r
ac0a286f
MK
295 (PciData.Hdr.ClassCode[1] != PCI_CLASS_MASS_STORAGE_IDE))\r
296 {\r
297 return;\r
b522c77b
HW
298 }\r
299\r
300 //\r
301 // Clear bar for legacy IDE\r
302 //\r
303 IOBarClear = 0x00;\r
304 if ((PciData.Hdr.ClassCode[0] & IDE_PI_REGISTER_PNE) == 0) {\r
305 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x10, 1, &IOBarClear);\r
306 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x14, 1, &IOBarClear);\r
307 }\r
ac0a286f 308\r
b522c77b
HW
309 if ((PciData.Hdr.ClassCode[0] & IDE_PI_REGISTER_SNE) == 0) {\r
310 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x18, 1, &IOBarClear);\r
311 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x1C, 1, &IOBarClear);\r
312 }\r
313\r
ac0a286f 314 return;\r
b522c77b 315}\r