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