]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c
OvmfPkg: PlatformBdsLib: Platform dependent PCI/IRQ initialization
[mirror_edk2.git] / OvmfPkg / Library / PlatformBdsLib / BdsPlatform.c
1 /** @file
2 Platform BDS customizations.
3
4 Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "BdsPlatform.h"
16 #include "QemuBootOrder.h"
17
18
19 //
20 // Global data
21 //
22
23 VOID *mEfiDevPathNotifyReg;
24 EFI_EVENT mEfiDevPathEvent;
25 VOID *mEmuVariableEventReg;
26 EFI_EVENT mEmuVariableEvent;
27 BOOLEAN mDetectVgaOnly;
28
29
30 //
31 // Type definitions
32 //
33
34 typedef
35 EFI_STATUS
36 (EFIAPI *PROTOCOL_INSTANCE_CALLBACK)(
37 IN EFI_HANDLE Handle,
38 IN VOID *Instance,
39 IN VOID *Context
40 );
41
42 /**
43 @param[in] Handle - Handle of PCI device instance
44 @param[in] PciIo - PCI IO protocol instance
45 @param[in] Pci - PCI Header register block
46 **/
47 typedef
48 EFI_STATUS
49 (EFIAPI *VISIT_PCI_INSTANCE_CALLBACK)(
50 IN EFI_HANDLE Handle,
51 IN EFI_PCI_IO_PROTOCOL *PciIo,
52 IN PCI_TYPE00 *Pci
53 );
54
55
56 //
57 // Function prototypes
58 //
59
60 EFI_STATUS
61 VisitAllInstancesOfProtocol (
62 IN EFI_GUID *Id,
63 IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction,
64 IN VOID *Context
65 );
66
67 EFI_STATUS
68 VisitAllPciInstancesOfProtocol (
69 IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
70 );
71
72 VOID
73 InstallDevicePathCallback (
74 VOID
75 );
76
77 //
78 // BDS Platform Functions
79 //
80 VOID
81 EFIAPI
82 PlatformBdsInit (
83 VOID
84 )
85 /*++
86
87 Routine Description:
88
89 Platform Bds init. Incude the platform firmware vendor, revision
90 and so crc check.
91
92 Arguments:
93
94 Returns:
95
96 None.
97
98 --*/
99 {
100 DEBUG ((EFI_D_INFO, "PlatformBdsInit\n"));
101 InstallDevicePathCallback ();
102 }
103
104
105 EFI_STATUS
106 ConnectRootBridge (
107 VOID
108 )
109 /*++
110
111 Routine Description:
112
113 Connect RootBridge
114
115 Arguments:
116
117 None.
118
119 Returns:
120
121 EFI_SUCCESS - Connect RootBridge successfully.
122 EFI_STATUS - Connect RootBridge fail.
123
124 --*/
125 {
126 EFI_STATUS Status;
127 EFI_HANDLE RootHandle;
128
129 //
130 // Make all the PCI_IO protocols on PCI Seg 0 show up
131 //
132 BdsLibConnectDevicePath (gPlatformRootBridges[0]);
133
134 Status = gBS->LocateDevicePath (
135 &gEfiDevicePathProtocolGuid,
136 &gPlatformRootBridges[0],
137 &RootHandle
138 );
139 if (EFI_ERROR (Status)) {
140 return Status;
141 }
142
143 Status = gBS->ConnectController (RootHandle, NULL, NULL, FALSE);
144 if (EFI_ERROR (Status)) {
145 return Status;
146 }
147
148 return EFI_SUCCESS;
149 }
150
151
152 EFI_STATUS
153 PrepareLpcBridgeDevicePath (
154 IN EFI_HANDLE DeviceHandle
155 )
156 /*++
157
158 Routine Description:
159
160 Add IsaKeyboard to ConIn,
161 add IsaSerial to ConOut, ConIn, ErrOut.
162 LPC Bridge: 06 01 00
163
164 Arguments:
165
166 DeviceHandle - Handle of PCIIO protocol.
167
168 Returns:
169
170 EFI_SUCCESS - LPC bridge is added to ConOut, ConIn, and ErrOut.
171 EFI_STATUS - No LPC bridge is added.
172
173 --*/
174 {
175 EFI_STATUS Status;
176 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
177 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
178 CHAR16 *DevPathStr;
179
180 DevicePath = NULL;
181 Status = gBS->HandleProtocol (
182 DeviceHandle,
183 &gEfiDevicePathProtocolGuid,
184 (VOID*)&DevicePath
185 );
186 if (EFI_ERROR (Status)) {
187 return Status;
188 }
189 TempDevicePath = DevicePath;
190
191 //
192 // Register Keyboard
193 //
194 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnpPs2KeyboardDeviceNode);
195
196 BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL);
197
198 //
199 // Register COM1
200 //
201 DevicePath = TempDevicePath;
202 gPnp16550ComPortDeviceNode.UID = 0;
203
204 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode);
205 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);
206 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);
207
208 //
209 // Print Device Path
210 //
211 DevPathStr = DevicePathToStr(DevicePath);
212 if (DevPathStr != NULL) {
213 DEBUG((
214 EFI_D_INFO,
215 "BdsPlatform.c+%d: COM%d DevPath: %s\n",
216 __LINE__,
217 gPnp16550ComPortDeviceNode.UID + 1,
218 DevPathStr
219 ));
220 FreePool(DevPathStr);
221 }
222
223 BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);
224 BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL);
225 BdsLibUpdateConsoleVariable (VarErrorOut, DevicePath, NULL);
226
227 //
228 // Register COM2
229 //
230 DevicePath = TempDevicePath;
231 gPnp16550ComPortDeviceNode.UID = 1;
232
233 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode);
234 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);
235 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);
236
237 //
238 // Print Device Path
239 //
240 DevPathStr = DevicePathToStr(DevicePath);
241 if (DevPathStr != NULL) {
242 DEBUG((
243 EFI_D_INFO,
244 "BdsPlatform.c+%d: COM%d DevPath: %s\n",
245 __LINE__,
246 gPnp16550ComPortDeviceNode.UID + 1,
247 DevPathStr
248 ));
249 FreePool(DevPathStr);
250 }
251
252 BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);
253 BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL);
254 BdsLibUpdateConsoleVariable (VarErrorOut, DevicePath, NULL);
255
256 return EFI_SUCCESS;
257 }
258
259 EFI_STATUS
260 GetGopDevicePath (
261 IN EFI_DEVICE_PATH_PROTOCOL *PciDevicePath,
262 OUT EFI_DEVICE_PATH_PROTOCOL **GopDevicePath
263 )
264 {
265 UINTN Index;
266 EFI_STATUS Status;
267 EFI_HANDLE PciDeviceHandle;
268 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
269 EFI_DEVICE_PATH_PROTOCOL *TempPciDevicePath;
270 UINTN GopHandleCount;
271 EFI_HANDLE *GopHandleBuffer;
272
273 if (PciDevicePath == NULL || GopDevicePath == NULL) {
274 return EFI_INVALID_PARAMETER;
275 }
276
277 //
278 // Initialize the GopDevicePath to be PciDevicePath
279 //
280 *GopDevicePath = PciDevicePath;
281 TempPciDevicePath = PciDevicePath;
282
283 Status = gBS->LocateDevicePath (
284 &gEfiDevicePathProtocolGuid,
285 &TempPciDevicePath,
286 &PciDeviceHandle
287 );
288 if (EFI_ERROR (Status)) {
289 return Status;
290 }
291
292 //
293 // Try to connect this handle, so that GOP dirver could start on this
294 // device and create child handles with GraphicsOutput Protocol installed
295 // on them, then we get device paths of these child handles and select
296 // them as possible console device.
297 //
298 gBS->ConnectController (PciDeviceHandle, NULL, NULL, FALSE);
299
300 Status = gBS->LocateHandleBuffer (
301 ByProtocol,
302 &gEfiGraphicsOutputProtocolGuid,
303 NULL,
304 &GopHandleCount,
305 &GopHandleBuffer
306 );
307 if (!EFI_ERROR (Status)) {
308 //
309 // Add all the child handles as possible Console Device
310 //
311 for (Index = 0; Index < GopHandleCount; Index++) {
312 Status = gBS->HandleProtocol (GopHandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID*)&TempDevicePath);
313 if (EFI_ERROR (Status)) {
314 continue;
315 }
316 if (CompareMem (
317 PciDevicePath,
318 TempDevicePath,
319 GetDevicePathSize (PciDevicePath) - END_DEVICE_PATH_LENGTH
320 ) == 0) {
321 //
322 // In current implementation, we only enable one of the child handles
323 // as console device, i.e. sotre one of the child handle's device
324 // path to variable "ConOut"
325 // In futhure, we could select all child handles to be console device
326 //
327
328 *GopDevicePath = TempDevicePath;
329
330 //
331 // Delete the PCI device's path that added by GetPlugInPciVgaDevicePath()
332 // Add the integrity GOP device path.
333 //
334 BdsLibUpdateConsoleVariable (VarConsoleOutDev, NULL, PciDevicePath);
335 BdsLibUpdateConsoleVariable (VarConsoleOutDev, TempDevicePath, NULL);
336 }
337 }
338 gBS->FreePool (GopHandleBuffer);
339 }
340
341 return EFI_SUCCESS;
342 }
343
344 EFI_STATUS
345 PreparePciVgaDevicePath (
346 IN EFI_HANDLE DeviceHandle
347 )
348 /*++
349
350 Routine Description:
351
352 Add PCI VGA to ConOut.
353 PCI VGA: 03 00 00
354
355 Arguments:
356
357 DeviceHandle - Handle of PCIIO protocol.
358
359 Returns:
360
361 EFI_SUCCESS - PCI VGA is added to ConOut.
362 EFI_STATUS - No PCI VGA device is added.
363
364 --*/
365 {
366 EFI_STATUS Status;
367 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
368 EFI_DEVICE_PATH_PROTOCOL *GopDevicePath;
369
370 DevicePath = NULL;
371 GopDevicePath = NULL;
372 Status = gBS->HandleProtocol (
373 DeviceHandle,
374 &gEfiDevicePathProtocolGuid,
375 (VOID*)&DevicePath
376 );
377 if (EFI_ERROR (Status)) {
378 return Status;
379 }
380
381 GetGopDevicePath (DevicePath, &GopDevicePath);
382 DevicePath = GopDevicePath;
383
384 BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);
385
386 return EFI_SUCCESS;
387 }
388
389 EFI_STATUS
390 PreparePciSerialDevicePath (
391 IN EFI_HANDLE DeviceHandle
392 )
393 /*++
394
395 Routine Description:
396
397 Add PCI Serial to ConOut, ConIn, ErrOut.
398 PCI Serial: 07 00 02
399
400 Arguments:
401
402 DeviceHandle - Handle of PCIIO protocol.
403
404 Returns:
405
406 EFI_SUCCESS - PCI Serial is added to ConOut, ConIn, and ErrOut.
407 EFI_STATUS - No PCI Serial device is added.
408
409 --*/
410 {
411 EFI_STATUS Status;
412 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
413
414 DevicePath = NULL;
415 Status = gBS->HandleProtocol (
416 DeviceHandle,
417 &gEfiDevicePathProtocolGuid,
418 (VOID*)&DevicePath
419 );
420 if (EFI_ERROR (Status)) {
421 return Status;
422 }
423
424 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);
425 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);
426
427 BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);
428 BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL);
429 BdsLibUpdateConsoleVariable (VarErrorOut, DevicePath, NULL);
430
431 return EFI_SUCCESS;
432 }
433
434 EFI_STATUS
435 VisitAllInstancesOfProtocol (
436 IN EFI_GUID *Id,
437 IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction,
438 IN VOID *Context
439 )
440 {
441 EFI_STATUS Status;
442 UINTN HandleCount;
443 EFI_HANDLE *HandleBuffer;
444 UINTN Index;
445 VOID *Instance;
446
447 //
448 // Start to check all the PciIo to find all possible device
449 //
450 HandleCount = 0;
451 HandleBuffer = NULL;
452 Status = gBS->LocateHandleBuffer (
453 ByProtocol,
454 Id,
455 NULL,
456 &HandleCount,
457 &HandleBuffer
458 );
459 if (EFI_ERROR (Status)) {
460 return Status;
461 }
462
463 for (Index = 0; Index < HandleCount; Index++) {
464 Status = gBS->HandleProtocol (HandleBuffer[Index], Id, &Instance);
465 if (EFI_ERROR (Status)) {
466 continue;
467 }
468
469 Status = (*CallBackFunction) (
470 HandleBuffer[Index],
471 Instance,
472 Context
473 );
474 }
475
476 gBS->FreePool (HandleBuffer);
477
478 return EFI_SUCCESS;
479 }
480
481
482 EFI_STATUS
483 EFIAPI
484 VisitingAPciInstance (
485 IN EFI_HANDLE Handle,
486 IN VOID *Instance,
487 IN VOID *Context
488 )
489 {
490 EFI_STATUS Status;
491 EFI_PCI_IO_PROTOCOL *PciIo;
492 PCI_TYPE00 Pci;
493
494 PciIo = (EFI_PCI_IO_PROTOCOL*) Instance;
495
496 //
497 // Check for all PCI device
498 //
499 Status = PciIo->Pci.Read (
500 PciIo,
501 EfiPciIoWidthUint32,
502 0,
503 sizeof (Pci) / sizeof (UINT32),
504 &Pci
505 );
506 if (EFI_ERROR (Status)) {
507 return Status;
508 }
509
510 return (*(VISIT_PCI_INSTANCE_CALLBACK)(UINTN) Context) (
511 Handle,
512 PciIo,
513 &Pci
514 );
515
516 }
517
518
519
520 EFI_STATUS
521 VisitAllPciInstances (
522 IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
523 )
524 {
525 return VisitAllInstancesOfProtocol (
526 &gEfiPciIoProtocolGuid,
527 VisitingAPciInstance,
528 (VOID*)(UINTN) CallBackFunction
529 );
530 }
531
532
533 /**
534 Do platform specific PCI Device check and add them to
535 ConOut, ConIn, ErrOut.
536
537 @param[in] Handle - Handle of PCI device instance
538 @param[in] PciIo - PCI IO protocol instance
539 @param[in] Pci - PCI Header register block
540
541 @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.
542 @retval EFI_STATUS - PCI Device check or Console variable update fail.
543
544 **/
545 EFI_STATUS
546 EFIAPI
547 DetectAndPreparePlatformPciDevicePath (
548 IN EFI_HANDLE Handle,
549 IN EFI_PCI_IO_PROTOCOL *PciIo,
550 IN PCI_TYPE00 *Pci
551 )
552 {
553 EFI_STATUS Status;
554
555 Status = PciIo->Attributes (
556 PciIo,
557 EfiPciIoAttributeOperationEnable,
558 EFI_PCI_DEVICE_ENABLE,
559 NULL
560 );
561 ASSERT_EFI_ERROR (Status);
562
563 if (!mDetectVgaOnly) {
564 //
565 // Here we decide whether it is LPC Bridge
566 //
567 if ((IS_PCI_LPC (Pci)) ||
568 ((IS_PCI_ISA_PDECODE (Pci)) &&
569 (Pci->Hdr.VendorId == 0x8086) &&
570 (Pci->Hdr.DeviceId == 0x7000)
571 )
572 ) {
573 //
574 // Add IsaKeyboard to ConIn,
575 // add IsaSerial to ConOut, ConIn, ErrOut
576 //
577 DEBUG ((EFI_D_INFO, "Found LPC Bridge device\n"));
578 PrepareLpcBridgeDevicePath (Handle);
579 return EFI_SUCCESS;
580 }
581 //
582 // Here we decide which Serial device to enable in PCI bus
583 //
584 if (IS_PCI_16550SERIAL (Pci)) {
585 //
586 // Add them to ConOut, ConIn, ErrOut.
587 //
588 DEBUG ((EFI_D_INFO, "Found PCI 16550 SERIAL device\n"));
589 PreparePciSerialDevicePath (Handle);
590 return EFI_SUCCESS;
591 }
592 }
593
594 //
595 // Here we decide which VGA device to enable in PCI bus
596 //
597 if (IS_PCI_VGA (Pci)) {
598 //
599 // Add them to ConOut.
600 //
601 DEBUG ((EFI_D_INFO, "Found PCI VGA device\n"));
602 PreparePciVgaDevicePath (Handle);
603 return EFI_SUCCESS;
604 }
605
606 return Status;
607 }
608
609
610 /**
611 Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
612
613 @param[in] DetectVgaOnly - Only detect VGA device if it's TRUE.
614
615 @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.
616 @retval EFI_STATUS - PCI Device check or Console variable update fail.
617
618 **/
619 EFI_STATUS
620 DetectAndPreparePlatformPciDevicePaths (
621 BOOLEAN DetectVgaOnly
622 )
623 {
624 mDetectVgaOnly = DetectVgaOnly;
625 return VisitAllPciInstances (DetectAndPreparePlatformPciDevicePath);
626 }
627
628
629 EFI_STATUS
630 PlatformBdsConnectConsole (
631 IN BDS_CONSOLE_CONNECT_ENTRY *PlatformConsole
632 )
633 /*++
634
635 Routine Description:
636
637 Connect the predefined platform default console device. Always try to find
638 and enable the vga device if have.
639
640 Arguments:
641
642 PlatformConsole - Predfined platform default console device array.
643
644 Returns:
645
646 EFI_SUCCESS - Success connect at least one ConIn and ConOut
647 device, there must have one ConOut device is
648 active vga device.
649
650 EFI_STATUS - Return the status of
651 BdsLibConnectAllDefaultConsoles ()
652
653 --*/
654 {
655 EFI_STATUS Status;
656 UINTN Index;
657 EFI_DEVICE_PATH_PROTOCOL *VarConout;
658 EFI_DEVICE_PATH_PROTOCOL *VarConin;
659 UINTN DevicePathSize;
660
661 //
662 // Connect RootBridge
663 //
664 VarConout = BdsLibGetVariableAndSize (
665 VarConsoleOut,
666 &gEfiGlobalVariableGuid,
667 &DevicePathSize
668 );
669 VarConin = BdsLibGetVariableAndSize (
670 VarConsoleInp,
671 &gEfiGlobalVariableGuid,
672 &DevicePathSize
673 );
674
675 if (VarConout == NULL || VarConin == NULL) {
676 //
677 // Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
678 //
679 DetectAndPreparePlatformPciDevicePaths (FALSE);
680
681 //
682 // Have chance to connect the platform default console,
683 // the platform default console is the minimue device group
684 // the platform should support
685 //
686 for (Index = 0; PlatformConsole[Index].DevicePath != NULL; ++Index) {
687 //
688 // Update the console variable with the connect type
689 //
690 if ((PlatformConsole[Index].ConnectType & CONSOLE_IN) == CONSOLE_IN) {
691 BdsLibUpdateConsoleVariable (VarConsoleInp, PlatformConsole[Index].DevicePath, NULL);
692 }
693 if ((PlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) {
694 BdsLibUpdateConsoleVariable (VarConsoleOut, PlatformConsole[Index].DevicePath, NULL);
695 }
696 if ((PlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) {
697 BdsLibUpdateConsoleVariable (VarErrorOut, PlatformConsole[Index].DevicePath, NULL);
698 }
699 }
700 } else {
701 //
702 // Only detect VGA device and add them to ConOut
703 //
704 DetectAndPreparePlatformPciDevicePaths (TRUE);
705 }
706
707 //
708 // Connect the all the default console with current cosole variable
709 //
710 Status = BdsLibConnectAllDefaultConsoles ();
711 if (EFI_ERROR (Status)) {
712 return Status;
713 }
714
715 return EFI_SUCCESS;
716 }
717
718
719 VOID
720 PciAcpiInitialization (
721 )
722 {
723 UINT16 HostBridgeDevId;
724 UINTN Pmba;
725
726 //
727 // Query Host Bridge DID to determine platform type
728 //
729 HostBridgeDevId = PcdGet16 (PcdOvmfHostBridgePciDevId);
730 switch (HostBridgeDevId) {
731 case INTEL_82441_DEVICE_ID:
732 Pmba = POWER_MGMT_REGISTER_PIIX4 (0x40);
733 //
734 // 00:01.0 ISA Bridge (PIIX4) LNK routing targets
735 //
736 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x60), 0x0b); // A
737 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x61), 0x0b); // B
738 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x62), 0x0a); // C
739 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x63), 0x0a); // D
740 break;
741 case INTEL_Q35_MCH_DEVICE_ID:
742 Pmba = POWER_MGMT_REGISTER_Q35 (0x40);
743 //
744 // 00:1f.0 LPC Bridge (Q35) LNK routing targets
745 //
746 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x60), 0x0a); // A
747 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x61), 0x0a); // B
748 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x62), 0x0b); // C
749 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x63), 0x0b); // D
750 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x68), 0x0a); // E
751 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x69), 0x0a); // F
752 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6a), 0x0b); // G
753 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6b), 0x0b); // H
754 break;
755 default:
756 DEBUG ((EFI_D_ERROR, "%a: Unknown Host Bridge Device ID: 0x%04x\n",
757 __FUNCTION__, HostBridgeDevId));
758 ASSERT (FALSE);
759 return;
760 }
761
762 //
763 // Set ACPI SCI_EN bit in PMCNTRL
764 //
765 IoOr16 ((PciRead32 (Pmba) & ~BIT0) + 4, BIT0);
766
767 //
768 // Initialize PCI_INTERRUPT_LINE for commonly encountered devices and slots
769 //
770 // FIXME: This should instead be accomplished programmatically by
771 // ennumerating all PCI devices present in the system and
772 // computing PCI_INTERRUPT_LINE from PCI_INTERRUPT_PIN, the
773 // slot/position of the device, and the available host IRQs
774 // (for an example, see SeaBIOS pci_bios_init_devices() in
775 // src/fw/pciinit.c)
776 //
777 switch (HostBridgeDevId) {
778 case INTEL_82441_DEVICE_ID:
779 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 2, 0x3c), 0x0b); // usb (northbr.)
780 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 3, 0x3c), 0x0a); // acpi (northbr.)
781 PciWrite8 (PCI_LIB_ADDRESS (0, 3, 0, 0x3c), 0x0b);
782 PciWrite8 (PCI_LIB_ADDRESS (0, 4, 0, 0x3c), 0x0b);
783 PciWrite8 (PCI_LIB_ADDRESS (0, 5, 0, 0x3c), 0x0a);
784 PciWrite8 (PCI_LIB_ADDRESS (0, 6, 0, 0x3c), 0x0a);
785 PciWrite8 (PCI_LIB_ADDRESS (0, 7, 0, 0x3c), 0x0b);
786 PciWrite8 (PCI_LIB_ADDRESS (0, 8, 0, 0x3c), 0x0b);
787 break;
788 case INTEL_Q35_MCH_DEVICE_ID:
789 PciWrite8 (PCI_LIB_ADDRESS (0, 2, 0, 0x3c), 0x0b);
790 PciWrite8 (PCI_LIB_ADDRESS (0, 3, 0, 0x3c), 0x0b);
791 PciWrite8 (PCI_LIB_ADDRESS (0, 4, 0, 0x3c), 0x0a);
792 PciWrite8 (PCI_LIB_ADDRESS (0, 5, 0, 0x3c), 0x0a);
793 PciWrite8 (PCI_LIB_ADDRESS (0, 6, 0, 0x3c), 0x0b);
794 PciWrite8 (PCI_LIB_ADDRESS (0, 7, 0, 0x3c), 0x0b);
795 PciWrite8 (PCI_LIB_ADDRESS (0, 8, 0, 0x3c), 0x0a);
796 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1d, 0, 0x3c), 0x0a); // uhci1
797 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1d, 1, 0x3c), 0x0a); // uhci2
798 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1d, 2, 0x3c), 0x0b); // uhci3
799 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1d, 7, 0x3c), 0x0b); // ehci1
800 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 2, 0x3c), 0x0a); // ahci (northbr.)
801 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 3, 0x3c), 0x0a); // smbus (northbr.)
802 break;
803 default:
804 ASSERT (FALSE); // should never be reached
805 }
806 }
807
808
809 EFI_STATUS
810 EFIAPI
811 ConnectRecursivelyIfPciMassStorage (
812 IN EFI_HANDLE Handle,
813 IN EFI_PCI_IO_PROTOCOL *Instance,
814 IN PCI_TYPE00 *PciHeader
815 )
816 {
817 EFI_STATUS Status;
818 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
819 CHAR16 *DevPathStr;
820
821 if (IS_CLASS1 (PciHeader, PCI_CLASS_MASS_STORAGE)) {
822 DevicePath = NULL;
823 Status = gBS->HandleProtocol (
824 Handle,
825 &gEfiDevicePathProtocolGuid,
826 (VOID*)&DevicePath
827 );
828 if (EFI_ERROR (Status)) {
829 return Status;
830 }
831
832 //
833 // Print Device Path
834 //
835 DevPathStr = DevicePathToStr (DevicePath);
836 if (DevPathStr != NULL) {
837 DEBUG((
838 EFI_D_INFO,
839 "Found Mass Storage device: %s\n",
840 DevPathStr
841 ));
842 FreePool(DevPathStr);
843 }
844
845 Status = gBS->ConnectController (Handle, NULL, NULL, TRUE);
846 if (EFI_ERROR (Status)) {
847 return Status;
848 }
849
850 }
851
852 return EFI_SUCCESS;
853 }
854
855
856 /**
857 This notification function is invoked when the
858 EMU Variable FVB has been changed.
859
860 @param Event The event that occured
861 @param Context For EFI compatiblity. Not used.
862
863 **/
864 VOID
865 EFIAPI
866 EmuVariablesUpdatedCallback (
867 IN EFI_EVENT Event,
868 IN VOID *Context
869 )
870 {
871 DEBUG ((EFI_D_INFO, "EmuVariablesUpdatedCallback\n"));
872 UpdateNvVarsOnFileSystem ();
873 }
874
875
876 EFI_STATUS
877 EFIAPI
878 VisitingFileSystemInstance (
879 IN EFI_HANDLE Handle,
880 IN VOID *Instance,
881 IN VOID *Context
882 )
883 {
884 EFI_STATUS Status;
885 STATIC BOOLEAN ConnectedToFileSystem = FALSE;
886
887 if (ConnectedToFileSystem) {
888 return EFI_ALREADY_STARTED;
889 }
890
891 Status = ConnectNvVarsToFileSystem (Handle);
892 if (EFI_ERROR (Status)) {
893 return Status;
894 }
895
896 ConnectedToFileSystem = TRUE;
897 mEmuVariableEvent =
898 EfiCreateProtocolNotifyEvent (
899 &gEfiDevicePathProtocolGuid,
900 TPL_CALLBACK,
901 EmuVariablesUpdatedCallback,
902 NULL,
903 &mEmuVariableEventReg
904 );
905 PcdSet64 (PcdEmuVariableEvent, (UINT64)(UINTN) mEmuVariableEvent);
906
907 return EFI_SUCCESS;
908 }
909
910
911 VOID
912 PlatformBdsRestoreNvVarsFromHardDisk (
913 )
914 {
915 VisitAllPciInstances (ConnectRecursivelyIfPciMassStorage);
916 VisitAllInstancesOfProtocol (
917 &gEfiSimpleFileSystemProtocolGuid,
918 VisitingFileSystemInstance,
919 NULL
920 );
921
922 }
923
924
925 VOID
926 PlatformBdsConnectSequence (
927 VOID
928 )
929 /*++
930
931 Routine Description:
932
933 Connect with predeined platform connect sequence,
934 the OEM/IBV can customize with their own connect sequence.
935
936 Arguments:
937
938 None.
939
940 Returns:
941
942 None.
943
944 --*/
945 {
946 UINTN Index;
947
948 DEBUG ((EFI_D_INFO, "PlatformBdsConnectSequence\n"));
949
950 Index = 0;
951
952 //
953 // Here we can get the customized platform connect sequence
954 // Notes: we can connect with new variable which record the
955 // last time boots connect device path sequence
956 //
957 while (gPlatformConnectSequence[Index] != NULL) {
958 //
959 // Build the platform boot option
960 //
961 BdsLibConnectDevicePath (gPlatformConnectSequence[Index]);
962 Index++;
963 }
964
965 //
966 // Just use the simple policy to connect all devices
967 //
968 BdsLibConnectAll ();
969
970 PciAcpiInitialization ();
971
972 //
973 // Clear the logo after all devices are connected.
974 //
975 gST->ConOut->ClearScreen (gST->ConOut);
976 }
977
978 VOID
979 PlatformBdsGetDriverOption (
980 IN OUT LIST_ENTRY *BdsDriverLists
981 )
982 /*++
983
984 Routine Description:
985
986 Load the predefined driver option, OEM/IBV can customize this
987 to load their own drivers
988
989 Arguments:
990
991 BdsDriverLists - The header of the driver option link list.
992
993 Returns:
994
995 None.
996
997 --*/
998 {
999 DEBUG ((EFI_D_INFO, "PlatformBdsGetDriverOption\n"));
1000 return;
1001 }
1002
1003 VOID
1004 PlatformBdsDiagnostics (
1005 IN EXTENDMEM_COVERAGE_LEVEL MemoryTestLevel,
1006 IN BOOLEAN QuietBoot,
1007 IN BASEM_MEMORY_TEST BaseMemoryTest
1008 )
1009 /*++
1010
1011 Routine Description:
1012
1013 Perform the platform diagnostic, such like test memory. OEM/IBV also
1014 can customize this fuction to support specific platform diagnostic.
1015
1016 Arguments:
1017
1018 MemoryTestLevel - The memory test intensive level
1019
1020 QuietBoot - Indicate if need to enable the quiet boot
1021
1022 BaseMemoryTest - A pointer to BaseMemoryTest()
1023
1024 Returns:
1025
1026 None.
1027
1028 --*/
1029 {
1030 EFI_STATUS Status;
1031
1032 DEBUG ((EFI_D_INFO, "PlatformBdsDiagnostics\n"));
1033
1034 //
1035 // Here we can decide if we need to show
1036 // the diagnostics screen
1037 // Notes: this quiet boot code should be remove
1038 // from the graphic lib
1039 //
1040 if (QuietBoot) {
1041 EnableQuietBoot (PcdGetPtr(PcdLogoFile));
1042 //
1043 // Perform system diagnostic
1044 //
1045 Status = BaseMemoryTest (MemoryTestLevel);
1046 if (EFI_ERROR (Status)) {
1047 DisableQuietBoot ();
1048 }
1049
1050 return ;
1051 }
1052 //
1053 // Perform system diagnostic
1054 //
1055 Status = BaseMemoryTest (MemoryTestLevel);
1056 }
1057
1058
1059 VOID
1060 EFIAPI
1061 PlatformBdsPolicyBehavior (
1062 IN OUT LIST_ENTRY *DriverOptionList,
1063 IN OUT LIST_ENTRY *BootOptionList,
1064 IN PROCESS_CAPSULES ProcessCapsules,
1065 IN BASEM_MEMORY_TEST BaseMemoryTest
1066 )
1067 /*++
1068
1069 Routine Description:
1070
1071 The function will excute with as the platform policy, current policy
1072 is driven by boot mode. IBV/OEM can customize this code for their specific
1073 policy action.
1074
1075 Arguments:
1076
1077 DriverOptionList - The header of the driver option link list
1078
1079 BootOptionList - The header of the boot option link list
1080
1081 ProcessCapsules - A pointer to ProcessCapsules()
1082
1083 BaseMemoryTest - A pointer to BaseMemoryTest()
1084
1085 Returns:
1086
1087 None.
1088
1089 --*/
1090 {
1091 EFI_STATUS Status;
1092 UINT16 Timeout;
1093 EFI_BOOT_MODE BootMode;
1094
1095 DEBUG ((EFI_D_INFO, "PlatformBdsPolicyBehavior\n"));
1096
1097 ConnectRootBridge ();
1098
1099 if (PcdGetBool (PcdOvmfFlashVariablesEnable)) {
1100 DEBUG ((EFI_D_INFO, "PlatformBdsPolicyBehavior: not restoring NvVars "
1101 "from disk since flash variables appear to be supported.\n"));
1102 } else {
1103 //
1104 // Try to restore variables from the hard disk early so
1105 // they can be used for the other BDS connect operations.
1106 //
1107 PlatformBdsRestoreNvVarsFromHardDisk ();
1108 }
1109
1110 //
1111 // Init the time out value
1112 //
1113 Timeout = PcdGet16 (PcdPlatformBootTimeOut);
1114
1115 //
1116 // Load the driver option as the driver option list
1117 //
1118 PlatformBdsGetDriverOption (DriverOptionList);
1119
1120 //
1121 // Get current Boot Mode
1122 //
1123 Status = BdsLibGetBootMode (&BootMode);
1124 DEBUG ((EFI_D_ERROR, "Boot Mode:%x\n", BootMode));
1125
1126 //
1127 // Go the different platform policy with different boot mode
1128 // Notes: this part code can be change with the table policy
1129 //
1130 ASSERT (BootMode == BOOT_WITH_FULL_CONFIGURATION);
1131 //
1132 // Connect platform console
1133 //
1134 Status = PlatformBdsConnectConsole (gPlatformConsole);
1135 if (EFI_ERROR (Status)) {
1136 //
1137 // Here OEM/IBV can customize with defined action
1138 //
1139 PlatformBdsNoConsoleAction ();
1140 }
1141
1142 //
1143 // Memory test and Logo show
1144 //
1145 PlatformBdsDiagnostics (IGNORE, TRUE, BaseMemoryTest);
1146
1147 //
1148 // Perform some platform specific connect sequence
1149 //
1150 PlatformBdsConnectSequence ();
1151
1152 //
1153 // Process QEMU's -kernel command line option
1154 //
1155 TryRunningQemuKernel ();
1156
1157 DEBUG ((EFI_D_INFO, "BdsLibConnectAll\n"));
1158 BdsLibConnectAll ();
1159 BdsLibEnumerateAllBootOption (BootOptionList);
1160
1161 SetBootOrderFromQemu (BootOptionList);
1162 //
1163 // The BootOrder variable may have changed, reload the in-memory list with
1164 // it.
1165 //
1166 BdsLibBuildOptionFromVar (BootOptionList, L"BootOrder");
1167
1168 PlatformBdsEnterFrontPage (Timeout, TRUE);
1169 }
1170
1171 VOID
1172 EFIAPI
1173 PlatformBdsBootSuccess (
1174 IN BDS_COMMON_OPTION *Option
1175 )
1176 /*++
1177
1178 Routine Description:
1179
1180 Hook point after a boot attempt succeeds. We don't expect a boot option to
1181 return, so the EFI 1.0 specification defines that you will default to an
1182 interactive mode and stop processing the BootOrder list in this case. This
1183 is alos a platform implementation and can be customized by IBV/OEM.
1184
1185 Arguments:
1186
1187 Option - Pointer to Boot Option that succeeded to boot.
1188
1189 Returns:
1190
1191 None.
1192
1193 --*/
1194 {
1195 CHAR16 *TmpStr;
1196
1197 DEBUG ((EFI_D_INFO, "PlatformBdsBootSuccess\n"));
1198 //
1199 // If Boot returned with EFI_SUCCESS and there is not in the boot device
1200 // select loop then we need to pop up a UI and wait for user input.
1201 //
1202 TmpStr = Option->StatusString;
1203 if (TmpStr != NULL) {
1204 BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL);
1205 FreePool (TmpStr);
1206 }
1207 }
1208
1209 VOID
1210 EFIAPI
1211 PlatformBdsBootFail (
1212 IN BDS_COMMON_OPTION *Option,
1213 IN EFI_STATUS Status,
1214 IN CHAR16 *ExitData,
1215 IN UINTN ExitDataSize
1216 )
1217 /*++
1218
1219 Routine Description:
1220
1221 Hook point after a boot attempt fails.
1222
1223 Arguments:
1224
1225 Option - Pointer to Boot Option that failed to boot.
1226
1227 Status - Status returned from failed boot.
1228
1229 ExitData - Exit data returned from failed boot.
1230
1231 ExitDataSize - Exit data size returned from failed boot.
1232
1233 Returns:
1234
1235 None.
1236
1237 --*/
1238 {
1239 CHAR16 *TmpStr;
1240
1241 DEBUG ((EFI_D_INFO, "PlatformBdsBootFail\n"));
1242
1243 //
1244 // If Boot returned with failed status then we need to pop up a UI and wait
1245 // for user input.
1246 //
1247 TmpStr = Option->StatusString;
1248 if (TmpStr != NULL) {
1249 BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL);
1250 FreePool (TmpStr);
1251 }
1252 }
1253
1254 EFI_STATUS
1255 PlatformBdsNoConsoleAction (
1256 VOID
1257 )
1258 /*++
1259
1260 Routine Description:
1261
1262 This function is remained for IBV/OEM to do some platform action,
1263 if there no console device can be connected.
1264
1265 Arguments:
1266
1267 None.
1268
1269 Returns:
1270
1271 EFI_SUCCESS - Direct return success now.
1272
1273 --*/
1274 {
1275 DEBUG ((EFI_D_INFO, "PlatformBdsNoConsoleAction\n"));
1276 return EFI_SUCCESS;
1277 }
1278
1279 VOID
1280 EFIAPI
1281 PlatformBdsLockNonUpdatableFlash (
1282 VOID
1283 )
1284 {
1285 DEBUG ((EFI_D_INFO, "PlatformBdsLockNonUpdatableFlash\n"));
1286 return;
1287 }
1288
1289
1290 /**
1291 This notification function is invoked when an instance of the
1292 EFI_DEVICE_PATH_PROTOCOL is produced.
1293
1294 @param Event The event that occured
1295 @param Context For EFI compatiblity. Not used.
1296
1297 **/
1298 VOID
1299 EFIAPI
1300 NotifyDevPath (
1301 IN EFI_EVENT Event,
1302 IN VOID *Context
1303 )
1304 {
1305 EFI_HANDLE Handle;
1306 EFI_STATUS Status;
1307 UINTN BufferSize;
1308 EFI_DEVICE_PATH_PROTOCOL *DevPathNode;
1309 ATAPI_DEVICE_PATH *Atapi;
1310
1311 //
1312 // Examine all new handles
1313 //
1314 for (;;) {
1315 //
1316 // Get the next handle
1317 //
1318 BufferSize = sizeof (Handle);
1319 Status = gBS->LocateHandle (
1320 ByRegisterNotify,
1321 NULL,
1322 mEfiDevPathNotifyReg,
1323 &BufferSize,
1324 &Handle
1325 );
1326
1327 //
1328 // If not found, we're done
1329 //
1330 if (EFI_NOT_FOUND == Status) {
1331 break;
1332 }
1333
1334 if (EFI_ERROR (Status)) {
1335 continue;
1336 }
1337
1338 //
1339 // Get the DevicePath protocol on that handle
1340 //
1341 Status = gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **)&DevPathNode);
1342 ASSERT_EFI_ERROR (Status);
1343
1344 while (!IsDevicePathEnd (DevPathNode)) {
1345 //
1346 // Find the handler to dump this device path node
1347 //
1348 if (
1349 (DevicePathType(DevPathNode) == MESSAGING_DEVICE_PATH) &&
1350 (DevicePathSubType(DevPathNode) == MSG_ATAPI_DP)
1351 ) {
1352 Atapi = (ATAPI_DEVICE_PATH*) DevPathNode;
1353 PciOr16 (
1354 PCI_LIB_ADDRESS (
1355 0,
1356 1,
1357 1,
1358 (Atapi->PrimarySecondary == 1) ? 0x42: 0x40
1359 ),
1360 BIT15
1361 );
1362 }
1363
1364 //
1365 // Next device path node
1366 //
1367 DevPathNode = NextDevicePathNode (DevPathNode);
1368 }
1369 }
1370
1371 return;
1372 }
1373
1374
1375 VOID
1376 InstallDevicePathCallback (
1377 VOID
1378 )
1379 {
1380 DEBUG ((EFI_D_INFO, "Registered NotifyDevPath Event\n"));
1381 mEfiDevPathEvent = EfiCreateProtocolNotifyEvent (
1382 &gEfiDevicePathProtocolGuid,
1383 TPL_CALLBACK,
1384 NotifyDevPath,
1385 NULL,
1386 &mEfiDevPathNotifyReg
1387 );
1388 }
1389
1390 /**
1391 Lock the ConsoleIn device in system table. All key
1392 presses will be ignored until the Password is typed in. The only way to
1393 disable the password is to type it in to a ConIn device.
1394
1395 @param Password Password used to lock ConIn device.
1396
1397 @retval EFI_SUCCESS lock the Console In Spliter virtual handle successfully.
1398 @retval EFI_UNSUPPORTED Password not found
1399
1400 **/
1401 EFI_STATUS
1402 EFIAPI
1403 LockKeyboards (
1404 IN CHAR16 *Password
1405 )
1406 {
1407 return EFI_UNSUPPORTED;
1408 }
1409