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