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