]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/Csm/CsmSupportLib/LegacyPlatform.c
OvmfPkg: Change OPTIONAL keyword usage style
[mirror_edk2.git] / OvmfPkg / Csm / CsmSupportLib / LegacyPlatform.c
CommitLineData
8016da21 1/** @file\r
2 Legacy BIOS Platform support\r
3\r
4 Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>\r
5\r
b26f0cf9 6 SPDX-License-Identifier: BSD-2-Clause-Patent\r
8016da21 7\r
8**/\r
9\r
10#include "LegacyPlatform.h"\r
11\r
12EFI_SETUP_BBS_MAP mSetupBbsMap[] = {\r
13 { 1, 2, 1, 1 }, // ATA HardDrive\r
14 { 2, 3, 1, 1 }, // ATAPI CDROM\r
15 { 3, 0x80, 2, 0 }, // PXE\r
16 { 4, 1, 0, 6 }, // USB Floppy\r
17 { 4, 2, 0, 6 }, // USB HDD\r
18 { 4, 3, 0, 6 }, // USB CD\r
19 { 4, 1, 0, 0 }, // USB ZIP Bugbug since Class/SubClass code is uninitialized\r
20 { 4, 2, 0, 0 } // USB ZIP Bugbug since Class/SubClass code is uninitialized\r
21};\r
22\r
23//\r
24// Global variables for System ROMs\r
25//\r
26#define SYSTEM_ROM_FILE_GUID \\r
f4a8ab28 27{ 0x1547B4F3, 0x3E8A, 0x4FEF, { 0x81, 0xC8, 0x32, 0x8E, 0xD6, 0x47, 0xAB, 0x1A } }\r
8016da21 28\r
29#define NULL_ROM_FILE_GUID \\r
f4a8ab28 30{ 0x00000000, 0x0000, 0x0000, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }\r
8016da21 31\r
32SYSTEM_ROM_TABLE mSystemRomTable[] = {\r
33 { SYSTEM_ROM_FILE_GUID, 1 },\r
34 { NULL_ROM_FILE_GUID, 0 }\r
35};\r
36\r
37EFI_HANDLE mVgaHandles[0x20];\r
38EFI_HANDLE mDiskHandles[0x20];\r
39EFI_HANDLE mIsaHandles[0x20];\r
40\r
41EFI_LEGACY_IRQ_PRIORITY_TABLE_ENTRY IrqPriorityTable[MAX_IRQ_PRIORITY_ENTRIES] = {\r
42 {0x0B,0},\r
43 {0x09,0},\r
44 {0x0A,0},\r
45 {0x05,0},\r
46 {0x07,0},\r
47 {0x00,0},\r
48 {0x00,0}\r
49};\r
50\r
51//\r
52// PIRQ Table\r
53// - Slot numbering will be used to update the bus number and determine bridge\r
54// to check to get bus number. The Slot number - 1 is an index into a decode\r
55// table to get the bridge information.\r
56//\r
57EFI_LEGACY_PIRQ_TABLE PirqTableHead = {\r
58 {\r
59 EFI_LEGACY_PIRQ_TABLE_SIGNATURE, // UINT32 Signature\r
60 0x00, // UINT8 MinorVersion\r
61 0x01, // UINT8 MajorVersion\r
62 0x0000, // UINT16 TableSize\r
63 0x00, // UINT8 Bus\r
64 0x08, // UINT8 DevFun\r
65 0x0000, // UINT16 PciOnlyIrq\r
66 0x8086, // UINT16 CompatibleVid\r
67 0x122e, // UINT16 CompatibleDid\r
68 0x00000000, // UINT32 Miniport\r
69 { // UINT8 Reserved[11]\r
70 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
71 0x00, 0x00, 0x00\r
72 },\r
73 0x00, // UINT8 Checksum\r
74 },\r
75 {\r
f4a8ab28
LE
76 // -- Pin 1 -- -- Pin 2 -- -- Pin 3 -- -- Pin 4 --\r
77 // Bus Dev Reg Map Reg Map Reg Map Reg Map\r
78 //\r
79 {0x00,0x08,{{0x60,0xDEB8},{0x61,0xDEB8},{0x62,0xDEB8},{0x63,0xDEB8}},0x00,0x00},\r
80 {0x00,0x10,{{0x61,0xDEB8},{0x62,0xDEB8},{0x63,0xDEB8},{0x60,0xDEB8}},0x01,0x00},\r
81 {0x00,0x18,{{0x62,0xDEB8},{0x63,0xDEB8},{0x60,0xDEB8},{0x61,0xDEB8}},0x02,0x00},\r
82 {0x00,0x20,{{0x63,0xDEB8},{0x60,0xDEB8},{0x61,0xDEB8},{0x62,0xDEB8}},0x03,0x00},\r
83 {0x00,0x28,{{0x60,0xDEB8},{0x61,0xDEB8},{0x62,0xDEB8},{0x63,0xDEB8}},0x04,0x00},\r
84 {0x00,0x30,{{0x61,0xDEB8},{0x62,0xDEB8},{0x63,0xDEB8},{0x60,0xDEB8}},0x05,0x00},\r
8016da21 85 }\r
86};\r
87\r
88LEGACY_BIOS_PLATFORM_INSTANCE mPrivateData;\r
89EFI_HANDLE mImageHandle = NULL;\r
90\r
91/**\r
92 Return the handles and assorted information for the specified PCI Class code\r
93\r
94 @param[in] PciClasses Array of PCI_CLASS_RECORD to find terminated with ClassCode 0xff\r
95 @param[in,out] DeviceTable Table to place handles etc in.\r
96 @param[in,out] DeviceIndex Number of devices found\r
97 @param[in] DeviceFlags FALSE if a valid legacy ROM is required, TRUE otherwise.\r
98\r
99 @retval EFI_SUCCESS One or more devices found\r
100 @retval EFI_NOT_FOUND No device found\r
101\r
102**/\r
103EFI_STATUS\r
104FindAllDeviceTypes (\r
105 IN PCI_CLASS_RECORD *PciClasses,\r
106 IN OUT DEVICE_STRUCTURE *DeviceTable,\r
107 IN OUT UINT16 *DeviceIndex,\r
108 IN BOOLEAN DeviceFlags\r
109 )\r
110{\r
111 UINTN HandleCount;\r
112 EFI_HANDLE *HandleBuffer;\r
113 UINTN Index;\r
114 UINTN StartIndex;\r
115 PCI_TYPE00 PciConfigHeader;\r
116 EFI_PCI_IO_PROTOCOL *PciIo;\r
117 EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
118 UINTN Flags;\r
119 EFI_STATUS Status;\r
120 UINTN Index2;\r
121\r
122 //\r
123 // Get legacy BIOS protocol as it is required to deal with Option ROMs.\r
124 //\r
125 StartIndex = *DeviceIndex;\r
126 Status = gBS->LocateProtocol (\r
127 &gEfiLegacyBiosProtocolGuid,\r
128 NULL,\r
129 (VOID**)&LegacyBios\r
130 );\r
131 ASSERT_EFI_ERROR (Status);\r
132\r
133 //\r
134 // Get all PCI handles and check them to generate a list of matching devices.\r
135 //\r
136 gBS->LocateHandleBuffer (\r
137 ByProtocol,\r
138 &gEfiPciIoProtocolGuid,\r
139 NULL,\r
140 &HandleCount,\r
141 &HandleBuffer\r
142 );\r
143 for (Index = 0; Index < HandleCount; Index++) {\r
144 gBS->HandleProtocol (\r
145 HandleBuffer[Index],\r
146 &gEfiPciIoProtocolGuid,\r
147 (VOID**)&PciIo\r
148 );\r
149 PciIo->Pci.Read (\r
150 PciIo,\r
151 EfiPciIoWidthUint32,\r
152 0,\r
153 sizeof (PciConfigHeader) / sizeof (UINT32),\r
154 &PciConfigHeader\r
155 );\r
156 for (Index2 = 0; PciClasses[Index2].Class != 0xff; Index2++) {\r
157 if ((PciConfigHeader.Hdr.ClassCode[2] == PciClasses[Index2].Class) &&\r
158 (PciConfigHeader.Hdr.ClassCode[1] == PciClasses[Index2].SubClass)) {\r
159 LegacyBios->CheckPciRom (\r
160 LegacyBios,\r
161 HandleBuffer[Index],\r
162 NULL,\r
163 NULL,\r
164 &Flags\r
165 );\r
166\r
167 //\r
168 // Verify that results of OPROM check match request.\r
169 // The two valid requests are:\r
170 // DeviceFlags = 0 require a valid legacy ROM\r
171 // DeviceFlags = 1 require either no ROM or a valid legacy ROM\r
172 //\r
173 if (\r
174 ((DeviceFlags != 0) && (Flags == NO_ROM)) ||\r
175 ((Flags & (ROM_FOUND | VALID_LEGACY_ROM)) == (ROM_FOUND | VALID_LEGACY_ROM))\r
176 ) {\r
177 DeviceTable->Handle = HandleBuffer[Index];\r
178 DeviceTable->Vid = PciConfigHeader.Hdr.VendorId;\r
179 DeviceTable->Did = PciConfigHeader.Hdr.DeviceId;\r
180 DeviceTable->SvId = PciConfigHeader.Device.SubsystemVendorID;\r
181 DeviceTable->SysId = PciConfigHeader.Device.SubsystemID;\r
182 ++ *DeviceIndex;\r
183 DeviceTable++;\r
184 }\r
185 }\r
186 }\r
187 }\r
188\r
189 //\r
190 // Free any allocated buffers\r
191 //\r
192 gBS->FreePool (HandleBuffer);\r
193\r
194 if (*DeviceIndex != StartIndex) {\r
195 return EFI_SUCCESS;\r
196 } else {\r
197 return EFI_NOT_FOUND;\r
198 }\r
199}\r
200\r
201/**\r
202 Load and initialize the Legacy BIOS SMM handler.\r
203\r
204 @param This The protocol instance pointer.\r
205 @param EfiToLegacy16BootTable A pointer to Legacy16 boot table.\r
206\r
207 @retval EFI_SUCCESS SMM code loaded.\r
208 @retval EFI_DEVICE_ERROR SMM code failed to load\r
209\r
210**/\r
211EFI_STATUS\r
212EFIAPI\r
213SmmInit (\r
214 IN EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *This,\r
215 IN VOID *EfiToLegacy16BootTable\r
216 )\r
217{\r
218 return EFI_SUCCESS;\r
219}\r
220\r
221/**\r
222 Finds the device path that should be used as the primary display adapter.\r
223\r
224 @param VgaHandle - The handle of the video device\r
225\r
226**/\r
227VOID\r
228GetSelectedVgaDeviceInfo (\r
229 OUT EFI_HANDLE *VgaHandle\r
230 )\r
231{\r
232 EFI_STATUS Status;\r
233 UINTN HandleCount;\r
234 EFI_HANDLE *HandleBuffer;\r
235 UINTN Index;\r
236 EFI_PCI_IO_PROTOCOL *PciIo;\r
237 PCI_TYPE00 Pci;\r
238 UINT8 MinBus;\r
239 UINT8 MaxBus;\r
240 UINTN Segment;\r
241 UINTN Bus;\r
242 UINTN Device;\r
243 UINTN Function;\r
244 UINTN SelectedAddress;\r
245 UINTN CurrentAddress;\r
246\r
247 //\r
248 // Initialize return to 'not found' state\r
249 //\r
250 *VgaHandle = NULL;\r
251\r
252 //\r
8c0b0b34
TH
253 // Initialize variable states. This is important for selecting the VGA\r
254 // device if multiple devices exist behind a single bridge.\r
8016da21 255 //\r
256 HandleCount = 0;\r
257 HandleBuffer = NULL;\r
258 SelectedAddress = PCI_LIB_ADDRESS(0xff, 0x1f, 0x7, 0);\r
259\r
260 //\r
261 // The bus range to search for a VGA device in.\r
262 //\r
263 MinBus = MaxBus = 0;\r
264\r
265 //\r
266 // Start to check all the pci io to find all possible VGA device\r
267 //\r
268 HandleCount = 0;\r
269 HandleBuffer = NULL;\r
270 Status = gBS->LocateHandleBuffer (\r
271 ByProtocol,\r
272 &gEfiPciIoProtocolGuid,\r
273 NULL,\r
274 &HandleCount,\r
275 &HandleBuffer\r
276 );\r
277 if (EFI_ERROR (Status)) {\r
278 return;\r
279 }\r
280\r
281 for (Index = 0; Index < HandleCount; Index++) {\r
282 Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiPciIoProtocolGuid, (VOID**)&PciIo);\r
283 if (!EFI_ERROR (Status)) {\r
284 //\r
48cf40b8 285 // Determine if this is in the correct bus range.\r
8016da21 286 //\r
287 Status = PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function);\r
288 if (EFI_ERROR(Status) || (Bus < MinBus || Bus > MaxBus)) {\r
289 continue;\r
290 }\r
291\r
292 //\r
293 // Read device information.\r
294 //\r
295 Status = PciIo->Pci.Read (\r
296 PciIo,\r
297 EfiPciIoWidthUint32,\r
298 0,\r
299 sizeof (Pci) / sizeof (UINT32),\r
300 &Pci\r
301 );\r
302 if (EFI_ERROR (Status)) {\r
303 continue;\r
304 }\r
305\r
306 //\r
307 // Make sure the device is a VGA device.\r
308 //\r
309 if (!IS_PCI_VGA (&Pci)) {\r
310 continue;\r
311 }\r
70d5086c 312 DEBUG ((DEBUG_INFO,\r
8016da21 313 "PCI VGA: 0x%04x:0x%04x\n",\r
314 Pci.Hdr.VendorId,\r
315 Pci.Hdr.DeviceId\r
316 ));\r
317\r
318 //\r
319 // Currently we use the lowest numbered bus/device/function if multiple\r
320 // devices are found in the target bus range.\r
321 //\r
322 CurrentAddress = PCI_LIB_ADDRESS(Bus, Device, Function, 0);\r
323 if (CurrentAddress < SelectedAddress) {\r
324 SelectedAddress = CurrentAddress;\r
325 *VgaHandle = HandleBuffer[Index];\r
326 }\r
327 }\r
328 }\r
329\r
330 FreePool (HandleBuffer);\r
331}\r
332\r
333\r
334/**\r
335 Returns a buffer of handles for the requested subfunction.\r
336\r
337 @param This The protocol instance pointer.\r
338 @param Mode Specifies what handle to return. See EFI_GET_PLATFORM_HANDLE_MODE enum.\r
339 @param Type Mode specific. See EFI_GET_PLATFORM_HANDLE_MODE enum.\r
340 @param HandleBuffer Mode specific. See EFI_GET_PLATFORM_HANDLE_MODE enum.\r
341 @param HandleCount Mode specific. See EFI_GET_PLATFORM_HANDLE_MODE enum.\r
342 @param AdditionalData Mode specific. See EFI_GET_PLATFORM_HANDLE_MODE enum.\r
343\r
344 @retval EFI_SUCCESS Handle is valid.\r
345 @retval EFI_UNSUPPORTED Mode is not supported on the platform.\r
346 @retval EFI_NOT_FOUND Handle is not known.\r
347\r
348**/\r
349EFI_STATUS\r
350EFIAPI\r
351GetPlatformHandle (\r
352 IN EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *This,\r
353 IN EFI_GET_PLATFORM_HANDLE_MODE Mode,\r
354 IN UINT16 Type,\r
355 OUT EFI_HANDLE **HandleBuffer,\r
356 OUT UINTN *HandleCount,\r
357 OUT VOID **AdditionalData OPTIONAL\r
358 )\r
359{\r
360 DEVICE_STRUCTURE LocalDevice[0x40];\r
361 UINT32 LocalIndex;\r
362 UINT32 Index;\r
363 DEVICE_STRUCTURE TempDevice;\r
364 EFI_STATUS Status;\r
365 EFI_PCI_IO_PROTOCOL *PciIo;\r
366 UINTN Segment;\r
367 UINTN Bus;\r
368 UINTN Device;\r
369 UINTN Function;\r
370 HDD_INFO *HddInfo;\r
371 PCI_TYPE00 PciConfigHeader;\r
372 UINT32 HddIndex;\r
373 EFI_HANDLE IdeHandle;\r
374 EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
375 PCI_CLASS_RECORD ClassLists[10];\r
376 UINTN PriorityIndex;\r
377\r
378 static BOOLEAN bConnected = FALSE;\r
379\r
380 LocalIndex = 0x00;\r
381 HddInfo = NULL;\r
382 HddIndex = 0;\r
383\r
384 Status = gBS->LocateProtocol (\r
385 &gEfiLegacyBiosProtocolGuid,\r
386 NULL,\r
387 (VOID**)&LegacyBios\r
388 );\r
389\r
390 //\r
391 // Process mode specific operations\r
392 //\r
393 switch (Mode) {\r
394 case EfiGetPlatformVgaHandle:\r
395 //\r
396 // Get the handle for the currently selected VGA device.\r
397 //\r
398 GetSelectedVgaDeviceInfo (&mVgaHandles[0]);\r
399 *HandleBuffer = &mVgaHandles[0];\r
400 *HandleCount = (mVgaHandles[0] != NULL) ? 1 : 0;\r
401 return EFI_SUCCESS;\r
402 case EfiGetPlatformIdeHandle:\r
403 IdeHandle = NULL;\r
404 if (AdditionalData != NULL) {\r
405 HddInfo = (HDD_INFO *) *AdditionalData;\r
406 }\r
407\r
408 //\r
409 // Locate all found block io devices\r
410 //\r
411 ClassLists[0].Class = PCI_CLASS_MASS_STORAGE;\r
412 ClassLists[0].SubClass = PCI_CLASS_MASS_STORAGE_SCSI;\r
413 ClassLists[1].Class = PCI_CLASS_MASS_STORAGE;\r
414 ClassLists[1].SubClass = PCI_CLASS_MASS_STORAGE_IDE;\r
415 ClassLists[2].Class = PCI_CLASS_MASS_STORAGE;\r
416 ClassLists[2].SubClass = PCI_CLASS_MASS_STORAGE_RAID;\r
417 ClassLists[3].Class = PCI_CLASS_MASS_STORAGE;\r
418 ClassLists[3].SubClass = PCI_CLASS_MASS_STORAGE_SATADPA;\r
419 ClassLists[4].Class = 0xff;\r
420 FindAllDeviceTypes (ClassLists, LocalDevice, (UINT16 *) &LocalIndex, TRUE);\r
421 if (LocalIndex == 0) {\r
422 return EFI_NOT_FOUND;\r
423 }\r
424\r
425 //\r
426 // Make sure all IDE controllers are connected. This is necessary\r
427 // in NO_CONFIG_CHANGE boot path to ensure IDE controller is correctly\r
428 // initialized and all IDE drives are enumerated\r
429 //\r
430 if (!bConnected) {\r
431 for (Index = 0; Index < LocalIndex; Index++) {\r
432 gBS->ConnectController (LocalDevice[Index].Handle, NULL, NULL, TRUE);\r
433 }\r
434 }\r
435\r
436 //\r
437 // Locate onboard controllers.\r
438 //\r
439 for (Index = 0; Index < LocalIndex; Index++) {\r
440 if (LocalDevice[Index].Vid == V_INTEL_VENDOR_ID) {\r
441 if (LocalDevice[Index].Did == V_PIIX4_IDE_DEVICE_ID) {\r
442 IdeHandle = LocalDevice[Index].Handle;\r
443 }\r
444 }\r
445 }\r
446\r
447 //\r
448 // Set the IDE contorller as primary devices.\r
449 //\r
450 PriorityIndex = 0;\r
451 for (Index = 0; Index < LocalIndex; Index++) {\r
452 if (LocalDevice[Index].Handle == IdeHandle && PriorityIndex == 0) {\r
453 TempDevice = LocalDevice[PriorityIndex];\r
454 LocalDevice[PriorityIndex] = LocalDevice[Index];\r
455 LocalDevice[Index] = TempDevice;\r
456 PriorityIndex++;\r
457 break;\r
458 }\r
459 }\r
460\r
461 //\r
462 // Copy over handles and update return values.\r
463 //\r
464 for (Index = 0; Index < LocalIndex; Index++) {\r
465 mDiskHandles[Index] = LocalDevice[Index].Handle;\r
466 }\r
467 *HandleBuffer = &mDiskHandles[0];\r
468 *HandleCount = LocalIndex;\r
469\r
470 //\r
471 // We have connected all IDE controllers once. No more needed\r
472 //\r
473 bConnected = TRUE;\r
474\r
475 //\r
476 // Log all onboard controllers.\r
477 //\r
478 for (Index = 0; (Index < LocalIndex) && (AdditionalData != NULL); Index++) {\r
479 if ((LocalDevice[Index].Handle != NULL) &&\r
480 (LocalDevice[Index].Handle == IdeHandle)) {\r
481 Status = gBS->HandleProtocol (\r
482 LocalDevice[Index].Handle,\r
483 &gEfiPciIoProtocolGuid,\r
484 (VOID **) &PciIo\r
485 );\r
486 PciIo->Pci.Read (\r
487 PciIo,\r
488 EfiPciIoWidthUint32,\r
489 0,\r
490 sizeof (PciConfigHeader) / sizeof (UINT32),\r
491 &PciConfigHeader\r
492 );\r
493 if (!EFI_ERROR (Status)) {\r
494 PciIo->GetLocation (\r
495 PciIo,\r
496 &Segment,\r
497 &Bus,\r
498 &Device,\r
499 &Function\r
500 );\r
501\r
502 //\r
503 // Be sure to only fill out correct information based on platform\r
48cf40b8 504 // configuration.\r
8016da21 505 //\r
506 HddInfo[HddIndex].Status |= HDD_PRIMARY;\r
507 HddInfo[HddIndex].Bus = (UINT32)Bus;\r
508 HddInfo[HddIndex].Device = (UINT32)Device;\r
509 HddInfo[HddIndex].Function = (UINT32)Function;\r
510 HddInfo[HddIndex + 1].Status |= HDD_SECONDARY;\r
511 HddInfo[HddIndex + 1].Bus = (UINT32)Bus;\r
512 HddInfo[HddIndex + 1].Device = (UINT32)Device;\r
513 HddInfo[HddIndex + 1].Function = (UINT32)Function;\r
514\r
515 //\r
516 // Primary controller data\r
517 //\r
518 if ((PciConfigHeader.Hdr.ClassCode[0] & 0x01) != 0) {\r
519 HddInfo[HddIndex].CommandBaseAddress =\r
520 (UINT16)(PciConfigHeader.Device.Bar[0] & 0xfffc);\r
521 HddInfo[HddIndex].ControlBaseAddress =\r
522 (UINT16)((PciConfigHeader.Device.Bar[1] & 0xfffc)+2);\r
523 HddInfo[HddIndex].BusMasterAddress =\r
524 (UINT16)(PciConfigHeader.Device.Bar[4] & 0xfffc);\r
525 HddInfo[HddIndex].HddIrq = PciConfigHeader.Device.InterruptLine;\r
526 } else {\r
527 HddInfo[HddIndex].HddIrq = 14;\r
528 HddInfo[HddIndex].CommandBaseAddress = 0x1f0;\r
529 HddInfo[HddIndex].ControlBaseAddress = 0x3f6;\r
530 HddInfo[HddIndex].BusMasterAddress = 0;\r
531 }\r
532 HddIndex++;\r
533\r
534 //\r
535 // Secondary controller data\r
536 //\r
537 if ((PciConfigHeader.Hdr.ClassCode[0] & 0x04) != 0) {\r
538 HddInfo[HddIndex].CommandBaseAddress =\r
539 (UINT16)(PciConfigHeader.Device.Bar[2] & 0xfffc);\r
540 HddInfo[HddIndex].ControlBaseAddress =\r
541 (UINT16)((PciConfigHeader.Device.Bar[3] & 0xfffc)+2);\r
542 HddInfo[HddIndex].BusMasterAddress =\r
543 (UINT16)(HddInfo[HddIndex].BusMasterAddress + 8);\r
544 HddInfo[HddIndex].HddIrq = PciConfigHeader.Device.InterruptLine;\r
545 } else {\r
546 HddInfo[HddIndex].HddIrq = 15;\r
547 HddInfo[HddIndex].CommandBaseAddress = 0x170;\r
548 HddInfo[HddIndex].ControlBaseAddress = 0x376;\r
549 HddInfo[HddIndex].BusMasterAddress = 0;\r
550 }\r
551 HddIndex++;\r
552 }\r
553 }\r
554 }\r
555 return EFI_SUCCESS;\r
556 case EfiGetPlatformIsaBusHandle:\r
557 ClassLists[0].Class = (UINT8) PCI_CLASS_BRIDGE;\r
558 ClassLists[0].SubClass = (UINT8) PCI_CLASS_BRIDGE_ISA_PDECODE;\r
559 ClassLists[1].Class = (UINT8) PCI_CLASS_BRIDGE;\r
560 ClassLists[1].SubClass = (UINT8) PCI_CLASS_BRIDGE_ISA;\r
561 ClassLists[2].Class = 0xff;\r
562\r
563 //\r
564 // Locate all found block io devices\r
565 //\r
566 FindAllDeviceTypes (ClassLists, LocalDevice, (UINT16 *) (&LocalIndex), TRUE);\r
567 if (LocalIndex == 0) {\r
568 return EFI_NOT_FOUND;\r
569 }\r
570\r
571 //\r
572 // Find our ISA bridge.\r
573 //\r
574 for (Index = 0; Index < LocalIndex; Index++) {\r
575 if (LocalDevice[Index].Vid == V_INTEL_VENDOR_ID) {\r
576 TempDevice = LocalDevice[0];\r
577 LocalDevice[0] = LocalDevice[Index];\r
578 LocalDevice[Index] = TempDevice;\r
579 }\r
580 }\r
581\r
582 //\r
583 // Perform copy and update return values.\r
584 //\r
585 for (Index = 0; Index < LocalIndex; Index++) {\r
586 mIsaHandles[Index] = LocalDevice[Index].Handle;\r
587 }\r
588 *HandleBuffer = &mIsaHandles[0];\r
589 *HandleCount = LocalIndex;\r
590 return EFI_SUCCESS;\r
591 case EfiGetPlatformUsbHandle:\r
592 default:\r
593 return EFI_UNSUPPORTED;\r
594 };\r
595}\r
596\r
597/**\r
598 Allows platform to perform any required action after a LegacyBios operation.\r
599 Invokes the specific sub function specified by Mode.\r
600\r
601 @param This The protocol instance pointer.\r
602 @param Mode Specifies what handle to return. See EFI_GET_PLATFORM_HOOK_MODE enum.\r
603 @param Type Mode specific. See EFI_GET_PLATFORM_HOOK_MODE enum.\r
604 @param DeviceHandle Mode specific. See EFI_GET_PLATFORM_HOOK_MODE enum.\r
605 @param ShadowAddress Mode specific. See EFI_GET_PLATFORM_HOOK_MODE enum.\r
606 @param Compatibility16Table Mode specific. See EFI_GET_PLATFORM_HOOK_MODE enum.\r
607 @param AdditionalData Mode specific. See EFI_GET_PLATFORM_HOOK_MODE enum.\r
608\r
609 @retval EFI_SUCCESS The operation performed successfully. Mode specific.\r
610 @retval EFI_UNSUPPORTED Mode is not supported on the platform.\r
611\r
612**/\r
613EFI_STATUS\r
614EFIAPI\r
615PlatformHooks (\r
616 IN EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *This,\r
617 IN EFI_GET_PLATFORM_HOOK_MODE Mode,\r
618 IN UINT16 Type,\r
79d49e16
MK
619 OUT EFI_HANDLE DeviceHandle OPTIONAL,\r
620 IN OUT UINTN *Shadowaddress OPTIONAL,\r
621 IN EFI_COMPATIBILITY16_TABLE *Compatibility16Table OPTIONAL,\r
8016da21 622 OUT VOID **AdditionalData OPTIONAL\r
623 )\r
624{\r
625 EFI_IA32_REGISTER_SET Regs;\r
626 EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
627 EFI_STATUS Status;\r
628\r
629 switch (Mode) {\r
630 case EfiPlatformHookPrepareToScanRom:\r
631 Status = gBS->LocateProtocol (\r
632 &gEfiLegacyBiosProtocolGuid,\r
633 NULL,\r
634 (VOID**)&LegacyBios\r
635 );\r
636\r
637 //\r
638 // Set the 80x25 Text VGA Mode\r
639 //\r
640 Regs.H.AH = 0x00;\r
641 Regs.H.AL = 0x03;\r
642 Status = LegacyBios->Int86 (LegacyBios, 0x10, &Regs);\r
643 return Status;\r
644 case EfiPlatformHookShadowServiceRoms:\r
645 return EFI_SUCCESS;\r
646 case EfiPlatformHookAfterRomInit:\r
647 default:\r
648 return EFI_UNSUPPORTED;\r
649 };\r
650}\r
651\r
652/**\r
653 Returns information associated with PCI IRQ routing.\r
654 This function returns the following information associated with PCI IRQ routing:\r
655 * An IRQ routing table and number of entries in the table.\r
656 * The $PIR table and its size.\r
657 * A list of PCI IRQs and the priority order to assign them.\r
658\r
659 @param This The protocol instance pointer.\r
660 @param RoutingTable The pointer to PCI IRQ Routing table.\r
661 This location is the $PIR table minus the header.\r
662 @param RoutingTableEntries The number of entries in table.\r
663 @param LocalPirqTable $PIR table.\r
664 @param PirqTableSize $PIR table size.\r
665 @param LocalIrqPriorityTable A list of interrupts in priority order to assign.\r
666 @param IrqPriorityTableEntries The number of entries in the priority table.\r
667\r
668 @retval EFI_SUCCESS Data was successfully returned.\r
669\r
670**/\r
671EFI_STATUS\r
672EFIAPI\r
673GetRoutingTable (\r
674 IN EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *This,\r
675 OUT VOID **RoutingTable,\r
676 OUT UINTN *RoutingTableEntries,\r
79d49e16
MK
677 OUT VOID **LocalPirqTable OPTIONAL,\r
678 OUT UINTN *PirqTableSize OPTIONAL,\r
679 OUT VOID **LocalIrqPriorityTable OPTIONAL,\r
8016da21 680 OUT UINTN *IrqPriorityTableEntries OPTIONAL\r
681 )\r
682{\r
683 UINT16 PTableSize;\r
684 UINT32 Index;\r
685 UINT8 Bus;\r
686 UINT8 Device;\r
687 UINT8 Function;\r
688 UINT8 Checksum;\r
689 UINT8 *Ptr;\r
690 EFI_STATUS Status;\r
691 EFI_LEGACY_INTERRUPT_PROTOCOL *LegacyInterrupt;\r
692\r
693 Checksum = 0;\r
694\r
695 if (LocalPirqTable != NULL) {\r
696 PTableSize = sizeof (EFI_LEGACY_PIRQ_TABLE_HEADER) +\r
697 sizeof (EFI_LEGACY_IRQ_ROUTING_ENTRY) * MAX_IRQ_ROUTING_ENTRIES;\r
698\r
699 Status = gBS->LocateProtocol (\r
700 &gEfiLegacyInterruptProtocolGuid,\r
701 NULL,\r
702 (VOID**)&LegacyInterrupt\r
703 );\r
704 ASSERT_EFI_ERROR (Status);\r
705 LegacyInterrupt->GetLocation (\r
706 LegacyInterrupt,\r
707 &Bus,\r
708 &Device,\r
709 &Function\r
710 );\r
711\r
712 //\r
713 // Update fields in $PIR table header\r
714 //\r
715 PirqTableHead.PirqTable.TableSize = PTableSize;\r
716 PirqTableHead.PirqTable.Bus = Bus;\r
717 PirqTableHead.PirqTable.DevFun = (UINT8) ((Device << 3) + Function);\r
718 Ptr = (UINT8 *) (&PirqTableHead);\r
719\r
720 //\r
721 // Calculate checksum.\r
722 //\r
723 for (Index = 0; Index < PTableSize; Index++) {\r
724 Checksum = (UINT8) (Checksum + (UINT8) *Ptr);\r
725 Ptr += 1;\r
726 }\r
727 Checksum = (UINT8) (0x00 - Checksum);\r
728 PirqTableHead.PirqTable.Checksum = Checksum;\r
729\r
730 //\r
731 // Update return values.\r
732 //\r
733 *LocalPirqTable = (VOID *) (&PirqTableHead);\r
734 *PirqTableSize = PTableSize;\r
735 }\r
736\r
737 //\r
738 // More items to return.\r
739 //\r
740 *RoutingTable = PirqTableHead.IrqRoutingEntry;\r
741 *RoutingTableEntries = MAX_IRQ_ROUTING_ENTRIES;\r
742 if (LocalIrqPriorityTable != NULL) {\r
743 *LocalIrqPriorityTable = IrqPriorityTable;\r
744 *IrqPriorityTableEntries = MAX_IRQ_PRIORITY_ENTRIES;\r
745 }\r
746\r
747 return EFI_SUCCESS;\r
748}\r
749\r
750/**\r
751 Finds the binary data or other platform information.\r
752\r
753 @param This The protocol instance pointer.\r
754 @param Mode Specifies what data to return. See See EFI_GET_PLATFORM_INFO_MODE enum.\r
755 @param Table Mode specific. See EFI_GET_PLATFORM_INFO_MODE enum.\r
756 @param TableSize Mode specific. See EFI_GET_PLATFORM_INFO_MODE enum.\r
757 @param Location Mode specific. See EFI_GET_PLATFORM_INFO_MODE enum.\r
758 @param Alignment Mode specific. See EFI_GET_PLATFORM_INFO_MODE enum.\r
759 @param LegacySegment Mode specific. See EFI_GET_PLATFORM_INFO_MODE enum.\r
760 @param LegacyOffset Mode specific. See EFI_GET_PLATFORM_INFO_MODE enum.\r
761\r
762 @retval EFI_SUCCESS Data returned successfully.\r
763 @retval EFI_UNSUPPORTED Mode is not supported on the platform.\r
764 @retval EFI_NOT_FOUND Binary image or table not found.\r
765\r
766**/\r
767EFI_STATUS\r
768EFIAPI\r
769GetPlatformInfo (\r
770 IN EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *This,\r
771 IN EFI_GET_PLATFORM_INFO_MODE Mode,\r
772 OUT VOID **Table,\r
773 OUT UINTN *TableSize,\r
774 OUT UINTN *Location,\r
775 OUT UINTN *Alignment,\r
776 IN UINT16 LegacySegment,\r
777 IN UINT16 LegacyOffset\r
778 )\r
779{\r
780 EFI_STATUS Status;\r
781 UINTN Index;\r
782\r
783 switch (Mode) {\r
784 case EfiGetPlatformBinarySystemRom:\r
785 //\r
786 // Loop through table of System rom descriptions\r
787 //\r
788 for (Index = 0; mSystemRomTable[Index].Valid != 0; Index++) {\r
789 Status = GetSectionFromFv (\r
790 &mSystemRomTable[Index].FileName,\r
791 EFI_SECTION_RAW,\r
792 0,\r
793 Table,\r
794 (UINTN *) TableSize\r
795 );\r
796 if (EFI_ERROR (Status)) {\r
797 continue;\r
798 }\r
799 return EFI_SUCCESS;\r
800 }\r
801\r
802 return EFI_NOT_FOUND;\r
803 case EfiGetPlatformBinaryOem16Data:\r
804 case EfiGetPlatformBinaryMpTable:\r
805 case EfiGetPlatformBinaryOemIntData:\r
806 case EfiGetPlatformBinaryOem32Data:\r
807 case EfiGetPlatformBinaryTpmBinary:\r
808 case EfiGetPlatformPciExpressBase:\r
809 default:\r
810 return EFI_UNSUPPORTED;\r
811 };\r
812}\r
813\r
814/**\r
815 Translates the given PIRQ accounting for bridge.\r
816 This function translates the given PIRQ back through all buses, if required,\r
817 and returns the true PIRQ and associated IRQ.\r
818\r
819 @param This The protocol instance pointer.\r
820 @param PciBus The PCI bus number for this device.\r
821 @param PciDevice The PCI device number for this device.\r
822 @param PciFunction The PCI function number for this device.\r
823 @param Pirq Input is PIRQ reported by device, and output is true PIRQ.\r
824 @param PciIrq The IRQ already assigned to the PIRQ, or the IRQ to be\r
825 assigned to the PIRQ.\r
826\r
827 @retval EFI_SUCCESS The PIRQ was translated.\r
828\r
829**/\r
830EFI_STATUS\r
831EFIAPI\r
832TranslatePirq (\r
833 IN EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *This,\r
834 IN UINTN PciBus,\r
835 IN UINTN PciDevice,\r
836 IN UINTN PciFunction,\r
837 IN OUT UINT8 *Pirq,\r
838 OUT UINT8 *PciIrq\r
839 )\r
840{\r
841 EFI_LEGACY_INTERRUPT_PROTOCOL *LegacyInterrupt;\r
842 EFI_STATUS Status;\r
843 UINTN Index;\r
844 UINTN Index1;\r
845 UINT8 LocalPirq;\r
846 UINT8 PirqData;\r
847 UINT8 MatchData;\r
848\r
849 Status = gBS->LocateProtocol (\r
850 &gEfiLegacyInterruptProtocolGuid,\r
851 NULL,\r
852 (VOID**)&LegacyInterrupt\r
853 );\r
854 ASSERT_EFI_ERROR (Status);\r
855 LocalPirq = (UINT8) (*Pirq);\r
856\r
857 for (Index = 0; Index < MAX_IRQ_ROUTING_ENTRIES; Index++) {\r
858 if ((PirqTableHead.IrqRoutingEntry[Index].Bus == PciBus) &&\r
859 (PirqTableHead.IrqRoutingEntry[Index].Device == PciDevice)) {\r
860 LocalPirq = (UINT8) (PirqTableHead.IrqRoutingEntry[Index].PirqEntry[LocalPirq].Pirq & 0x0f);\r
861 if (LocalPirq > 4) {\r
862 LocalPirq -= 4;\r
863 }\r
864\r
865 LegacyInterrupt->ReadPirq (LegacyInterrupt, LocalPirq, &PirqData);\r
866 MatchData = PCI_UNUSED;\r
867 while (PirqData == 0) {\r
868 for (Index1 = 0; Index1 < MAX_IRQ_PRIORITY_ENTRIES; Index1++) {\r
869 if ((IrqPriorityTable[Index1].Used == MatchData) &&\r
870 (IrqPriorityTable[Index1].Irq != 0)) {\r
871 PirqData = IrqPriorityTable[Index1].Irq;\r
872 IrqPriorityTable[Index1].Used = 0xff;\r
873 LegacyInterrupt->WritePirq (\r
874 LegacyInterrupt,\r
875 LocalPirq,\r
876 PirqData\r
877 );\r
878 break;\r
879 }\r
880 }\r
881\r
882 if (PirqData == 0) {\r
883\r
884 //\r
48cf40b8 885 // No unused interrupts, so start reusing them.\r
8016da21 886 //\r
887 MatchData = (UINT8) (~MatchData);\r
888 }\r
889 }\r
890\r
891 *PciIrq = PirqData;\r
892 *Pirq = LocalPirq;\r
893 }\r
894 }\r
895\r
896 return EFI_SUCCESS;\r
897}\r
898\r
899\r
900/**\r
901 Attempt to legacy boot the BootOption. If the EFI contexted has been\r
902 compromised this function will not return.\r
903\r
904 @param This The protocol instance pointer.\r
905 @param BbsDevicePath The EFI Device Path from BootXXXX variable.\r
906 @param BbsTable The Internal BBS table.\r
907 @param LoadOptionSize The size of LoadOption in size.\r
908 @param LoadOption The LoadOption from BootXXXX variable\r
909 @param EfiToLegacy16BootTable A pointer to BootTable structure\r
910\r
911 @retval EFI_SUCCESS Ready to boot.\r
912\r
913**/\r
914EFI_STATUS\r
915EFIAPI\r
916PrepareToBoot (\r
917 IN EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *This,\r
918 IN BBS_BBS_DEVICE_PATH *BbsDevicePath,\r
919 IN VOID *BbsTable,\r
920 IN UINT32 LoadOptionsSize,\r
921 IN VOID *LoadOptions,\r
922 IN VOID *EfiToLegacy16BootTable\r
923 )\r
924{\r
925 BBS_TABLE *LocalBbsTable;\r
926 EFI_TO_COMPATIBILITY16_BOOT_TABLE *Legacy16BootTable;\r
927 DEVICE_PRODUCER_DATA_HEADER *SioPtr;\r
928 UINT16 DevicePathType;\r
929 UINT16 Index;\r
930 UINT16 Priority;\r
931\r
932 //\r
933 // Initialize values\r
934 //\r
935 Priority = 0;\r
936 Legacy16BootTable = (EFI_TO_COMPATIBILITY16_BOOT_TABLE*) EfiToLegacy16BootTable;\r
937\r
938 //\r
939 // Set how Gate A20 is gated by hardware\r
940 //\r
941 SioPtr = &Legacy16BootTable->SioData;\r
942 SioPtr->Flags.A20Kybd = 1;\r
943 SioPtr->Flags.A20Port90 = 1;\r
944 SioPtr->MousePresent = 1;\r
945\r
946 LocalBbsTable = BbsTable;\r
947\r
948 //\r
949 // There are 2 cases that must be covered.\r
950 // Case 1: Booting to a legacy OS - BbsDevicePath is non-NULL.\r
951 // Case 2: Booting to an EFI aware OS - BbsDevicePath is NULL.\r
952 // We need to perform the PrepareToBoot function to assign\r
953 // drive numbers to HDD devices to allow the shell or EFI\r
954 // to access them.\r
955 //\r
956 if (BbsDevicePath != NULL) {\r
957 DevicePathType = BbsDevicePath->DeviceType;\r
958 } else {\r
959 DevicePathType = BBS_HARDDISK;\r
960 }\r
961\r
962 //\r
963 // Skip the boot devices where priority is set by BDS and set the next one\r
964 //\r
965 for (Index = 0; Index < Legacy16BootTable->NumberBbsEntries; Index++) {\r
966 if ((LocalBbsTable[Index].BootPriority != BBS_UNPRIORITIZED_ENTRY) &&\r
967 (LocalBbsTable[Index].BootPriority != BBS_IGNORE_ENTRY) &&\r
968 (LocalBbsTable[Index].BootPriority != BBS_LOWEST_PRIORITY) &&\r
969 (Priority <= LocalBbsTable[Index].BootPriority)) {\r
970 Priority = (UINT16) (LocalBbsTable[Index].BootPriority + 1);\r
971 }\r
972 }\r
973\r
974 switch (DevicePathType) {\r
975 case BBS_FLOPPY:\r
976 case BBS_HARDDISK:\r
977 case BBS_CDROM:\r
978 case BBS_EMBED_NETWORK:\r
979 for (Index = 0; Index < Legacy16BootTable->NumberBbsEntries; Index++) {\r
980 if ((LocalBbsTable[Index].BootPriority == BBS_UNPRIORITIZED_ENTRY) &&\r
981 (LocalBbsTable[Index].DeviceType == DevicePathType)) {\r
982 LocalBbsTable[Index].BootPriority = Priority;\r
983 ++Priority;\r
984 }\r
985 }\r
986 break;\r
987 case BBS_BEV_DEVICE:\r
988 for (Index = 0; Index < Legacy16BootTable->NumberBbsEntries; Index++) {\r
989 if ((LocalBbsTable[Index].BootPriority == BBS_UNPRIORITIZED_ENTRY) &&\r
990 (LocalBbsTable[Index].Class == 01) &&\r
991 (LocalBbsTable[Index].SubClass == 01)) {\r
992 LocalBbsTable[Index].BootPriority = Priority;\r
993 ++Priority;\r
994 }\r
995 }\r
996 break;\r
997 case BBS_USB:\r
998 case BBS_PCMCIA:\r
999 case BBS_UNKNOWN:\r
1000 default:\r
1001 break;\r
1002 };\r
1003\r
1004 //\r
1005 // Set priority for rest of devices\r
1006 //\r
1007 for (Index = 0; Index < Legacy16BootTable->NumberBbsEntries; Index++) {\r
1008 if (LocalBbsTable[Index].BootPriority == BBS_UNPRIORITIZED_ENTRY) {\r
1009 LocalBbsTable[Index].BootPriority = Priority;\r
1010 ++Priority;\r
1011 }\r
1012 }\r
1013\r
1014 return EFI_SUCCESS;\r
1015}\r
1016\r
1017\r
1018/**\r
1019 Initialize Legacy Platform support\r
1020\r
1021 @retval EFI_SUCCESS Successfully initialized\r
1022\r
1023**/\r
1024EFI_STATUS\r
1025LegacyBiosPlatformInstall (\r
1026 VOID\r
1027 )\r
1028{\r
1029 EFI_STATUS Status;\r
1030 LEGACY_BIOS_PLATFORM_INSTANCE *Private;\r
1031\r
1032 mImageHandle = gImageHandle;\r
1033 Private = &mPrivateData;\r
1034\r
1035 //\r
1036 // Grab a copy of all the protocols we depend on.\r
1037 //\r
1038 Private->Signature = LEGACY_BIOS_PLATFORM_INSTANCE_SIGNATURE;\r
1039 Private->LegacyBiosPlatform.GetPlatformInfo = GetPlatformInfo;\r
1040 Private->LegacyBiosPlatform.GetPlatformHandle = GetPlatformHandle;\r
1041 Private->LegacyBiosPlatform.SmmInit = SmmInit;\r
1042 Private->LegacyBiosPlatform.PlatformHooks = PlatformHooks;\r
1043 Private->LegacyBiosPlatform.GetRoutingTable = GetRoutingTable;\r
1044 Private->LegacyBiosPlatform.TranslatePirq = TranslatePirq;\r
1045 Private->LegacyBiosPlatform.PrepareToBoot = PrepareToBoot;\r
1046 Private->ImageHandle = gImageHandle;\r
1047\r
1048 //\r
1049 // Make a new handle and install the protocol\r
1050 //\r
1051 Private->Handle = NULL;\r
1052 Status = gBS->InstallProtocolInterface (\r
1053 &Private->Handle,\r
1054 &gEfiLegacyBiosPlatformProtocolGuid,\r
1055 EFI_NATIVE_INTERFACE,\r
1056 &Private->LegacyBiosPlatform\r
1057 );\r
1058 return Status;\r
1059}\r