]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c
9f953acf792ce37bddca6baca4974f0bc13659b7
[mirror_edk2.git] / OvmfPkg / Library / PlatformBdsLib / BdsPlatform.c
1 /** @file
2 Platform BDS customizations.
3
4 Copyright (c) 2004 - 2013, 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 Status = gBS->HandleProtocol (
372 DeviceHandle,
373 &gEfiDevicePathProtocolGuid,
374 (VOID*)&DevicePath
375 );
376 if (EFI_ERROR (Status)) {
377 return Status;
378 }
379
380 GetGopDevicePath (DevicePath, &GopDevicePath);
381 DevicePath = GopDevicePath;
382
383 BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);
384
385 return EFI_SUCCESS;
386 }
387
388 EFI_STATUS
389 PreparePciSerialDevicePath (
390 IN EFI_HANDLE DeviceHandle
391 )
392 /*++
393
394 Routine Description:
395
396 Add PCI Serial to ConOut, ConIn, ErrOut.
397 PCI Serial: 07 00 02
398
399 Arguments:
400
401 DeviceHandle - Handle of PCIIO protocol.
402
403 Returns:
404
405 EFI_SUCCESS - PCI Serial is added to ConOut, ConIn, and ErrOut.
406 EFI_STATUS - No PCI Serial device is added.
407
408 --*/
409 {
410 EFI_STATUS Status;
411 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
412
413 DevicePath = NULL;
414 Status = gBS->HandleProtocol (
415 DeviceHandle,
416 &gEfiDevicePathProtocolGuid,
417 (VOID*)&DevicePath
418 );
419 if (EFI_ERROR (Status)) {
420 return Status;
421 }
422
423 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);
424 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);
425
426 BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);
427 BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL);
428 BdsLibUpdateConsoleVariable (VarErrorOut, DevicePath, NULL);
429
430 return EFI_SUCCESS;
431 }
432
433 EFI_STATUS
434 VisitAllInstancesOfProtocol (
435 IN EFI_GUID *Id,
436 IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction,
437 IN VOID *Context
438 )
439 {
440 EFI_STATUS Status;
441 UINTN HandleCount;
442 EFI_HANDLE *HandleBuffer;
443 UINTN Index;
444 VOID *Instance;
445
446 //
447 // Start to check all the PciIo to find all possible device
448 //
449 HandleCount = 0;
450 HandleBuffer = NULL;
451 Status = gBS->LocateHandleBuffer (
452 ByProtocol,
453 Id,
454 NULL,
455 &HandleCount,
456 &HandleBuffer
457 );
458 if (EFI_ERROR (Status)) {
459 return Status;
460 }
461
462 for (Index = 0; Index < HandleCount; Index++) {
463 Status = gBS->HandleProtocol (HandleBuffer[Index], Id, &Instance);
464 if (EFI_ERROR (Status)) {
465 continue;
466 }
467
468 Status = (*CallBackFunction) (
469 HandleBuffer[Index],
470 Instance,
471 Context
472 );
473 }
474
475 gBS->FreePool (HandleBuffer);
476
477 return EFI_SUCCESS;
478 }
479
480
481 EFI_STATUS
482 EFIAPI
483 VisitingAPciInstance (
484 IN EFI_HANDLE Handle,
485 IN VOID *Instance,
486 IN VOID *Context
487 )
488 {
489 EFI_STATUS Status;
490 EFI_PCI_IO_PROTOCOL *PciIo;
491 PCI_TYPE00 Pci;
492
493 PciIo = (EFI_PCI_IO_PROTOCOL*) Instance;
494
495 //
496 // Check for all PCI device
497 //
498 Status = PciIo->Pci.Read (
499 PciIo,
500 EfiPciIoWidthUint32,
501 0,
502 sizeof (Pci) / sizeof (UINT32),
503 &Pci
504 );
505 if (EFI_ERROR (Status)) {
506 return Status;
507 }
508
509 return (*(VISIT_PCI_INSTANCE_CALLBACK)(UINTN) Context) (
510 Handle,
511 PciIo,
512 &Pci
513 );
514
515 }
516
517
518
519 EFI_STATUS
520 VisitAllPciInstances (
521 IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
522 )
523 {
524 return VisitAllInstancesOfProtocol (
525 &gEfiPciIoProtocolGuid,
526 VisitingAPciInstance,
527 (VOID*)(UINTN) CallBackFunction
528 );
529 }
530
531
532 /**
533 Do platform specific PCI Device check and add them to
534 ConOut, ConIn, ErrOut.
535
536 @param[in] Handle - Handle of PCI device instance
537 @param[in] PciIo - PCI IO protocol instance
538 @param[in] Pci - PCI Header register block
539
540 @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.
541 @retval EFI_STATUS - PCI Device check or Console variable update fail.
542
543 **/
544 EFI_STATUS
545 EFIAPI
546 DetectAndPreparePlatformPciDevicePath (
547 IN EFI_HANDLE Handle,
548 IN EFI_PCI_IO_PROTOCOL *PciIo,
549 IN PCI_TYPE00 *Pci
550 )
551 {
552 EFI_STATUS Status;
553
554 Status = PciIo->Attributes (
555 PciIo,
556 EfiPciIoAttributeOperationEnable,
557 EFI_PCI_DEVICE_ENABLE,
558 NULL
559 );
560 ASSERT_EFI_ERROR (Status);
561
562 if (!mDetectVgaOnly) {
563 //
564 // Here we decide whether it is LPC Bridge
565 //
566 if ((IS_PCI_LPC (Pci)) ||
567 ((IS_PCI_ISA_PDECODE (Pci)) &&
568 (Pci->Hdr.VendorId == 0x8086) &&
569 (Pci->Hdr.DeviceId == 0x7000)
570 )
571 ) {
572 //
573 // Add IsaKeyboard to ConIn,
574 // add IsaSerial to ConOut, ConIn, ErrOut
575 //
576 DEBUG ((EFI_D_INFO, "Found LPC Bridge device\n"));
577 PrepareLpcBridgeDevicePath (Handle);
578 return EFI_SUCCESS;
579 }
580 //
581 // Here we decide which Serial device to enable in PCI bus
582 //
583 if (IS_PCI_16550SERIAL (Pci)) {
584 //
585 // Add them to ConOut, ConIn, ErrOut.
586 //
587 DEBUG ((EFI_D_INFO, "Found PCI 16550 SERIAL device\n"));
588 PreparePciSerialDevicePath (Handle);
589 return EFI_SUCCESS;
590 }
591 }
592
593 //
594 // Here we decide which VGA device to enable in PCI bus
595 //
596 if (IS_PCI_VGA (Pci)) {
597 //
598 // Add them to ConOut.
599 //
600 DEBUG ((EFI_D_INFO, "Found PCI VGA device\n"));
601 PreparePciVgaDevicePath (Handle);
602 return EFI_SUCCESS;
603 }
604
605 return Status;
606 }
607
608
609 /**
610 Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
611
612 @param[in] DetectVgaOnly - Only detect VGA device if it's TRUE.
613
614 @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.
615 @retval EFI_STATUS - PCI Device check or Console variable update fail.
616
617 **/
618 EFI_STATUS
619 DetectAndPreparePlatformPciDevicePaths (
620 BOOLEAN DetectVgaOnly
621 )
622 {
623 mDetectVgaOnly = DetectVgaOnly;
624 return VisitAllPciInstances (DetectAndPreparePlatformPciDevicePath);
625 }
626
627
628 EFI_STATUS
629 PlatformBdsConnectConsole (
630 IN BDS_CONSOLE_CONNECT_ENTRY *PlatformConsole
631 )
632 /*++
633
634 Routine Description:
635
636 Connect the predefined platform default console device. Always try to find
637 and enable the vga device if have.
638
639 Arguments:
640
641 PlatformConsole - Predfined platform default console device array.
642
643 Returns:
644
645 EFI_SUCCESS - Success connect at least one ConIn and ConOut
646 device, there must have one ConOut device is
647 active vga device.
648
649 EFI_STATUS - Return the status of
650 BdsLibConnectAllDefaultConsoles ()
651
652 --*/
653 {
654 EFI_STATUS Status;
655 UINTN Index;
656 EFI_DEVICE_PATH_PROTOCOL *VarConout;
657 EFI_DEVICE_PATH_PROTOCOL *VarConin;
658 UINTN DevicePathSize;
659
660 //
661 // Connect RootBridge
662 //
663 VarConout = BdsLibGetVariableAndSize (
664 VarConsoleOut,
665 &gEfiGlobalVariableGuid,
666 &DevicePathSize
667 );
668 VarConin = BdsLibGetVariableAndSize (
669 VarConsoleInp,
670 &gEfiGlobalVariableGuid,
671 &DevicePathSize
672 );
673
674 if (VarConout == NULL || VarConin == NULL) {
675 //
676 // Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
677 //
678 DetectAndPreparePlatformPciDevicePaths (FALSE);
679
680 //
681 // Have chance to connect the platform default console,
682 // the platform default console is the minimue device group
683 // the platform should support
684 //
685 for (Index = 0; PlatformConsole[Index].DevicePath != NULL; ++Index) {
686 //
687 // Update the console variable with the connect type
688 //
689 if ((PlatformConsole[Index].ConnectType & CONSOLE_IN) == CONSOLE_IN) {
690 BdsLibUpdateConsoleVariable (VarConsoleInp, PlatformConsole[Index].DevicePath, NULL);
691 }
692 if ((PlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) {
693 BdsLibUpdateConsoleVariable (VarConsoleOut, PlatformConsole[Index].DevicePath, NULL);
694 }
695 if ((PlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) {
696 BdsLibUpdateConsoleVariable (VarErrorOut, PlatformConsole[Index].DevicePath, NULL);
697 }
698 }
699 } else {
700 //
701 // Only detect VGA device and add them to ConOut
702 //
703 DetectAndPreparePlatformPciDevicePaths (TRUE);
704 }
705
706 //
707 // Connect the all the default console with current cosole variable
708 //
709 Status = BdsLibConnectAllDefaultConsoles ();
710 if (EFI_ERROR (Status)) {
711 return Status;
712 }
713
714 return EFI_SUCCESS;
715 }
716
717
718 VOID
719 PciInitialization (
720 )
721 {
722 //
723 // Bus 0, Device 0, Function 0 - Host to PCI Bridge
724 //
725 PciWrite8 (PCI_LIB_ADDRESS (0, 0, 0, 0x3c), 0x00);
726
727 //
728 // Bus 0, Device 1, Function 0 - PCI to ISA Bridge
729 //
730 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x3c), 0x00);
731 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x60), 0x0b); // LNKA routing target
732 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x61), 0x0b); // LNKB routing target
733 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x62), 0x0a); // LNKC routing target
734 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x63), 0x0a); // LNKD routing target
735
736 //
737 // Bus 0, Device 1, Function 1 - IDE Controller
738 //
739 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 1, 0x3c), 0x00);
740 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 1, 0x0d), 0x40);
741
742 //
743 // Bus 0, Device 1, Function 3 - Power Managment Controller
744 //
745 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 3, 0x3c), 0x09);
746 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 3, 0x3d), 0x01); // INTA
747
748 //
749 // Bus 0, Device 2, Function 0 - Video Controller
750 //
751 PciWrite8 (PCI_LIB_ADDRESS (0, 2, 0, 0x3c), 0x00);
752
753 //
754 // Bus 0, Device 3, Function 0 - Network Controller
755 //
756 PciWrite8 (PCI_LIB_ADDRESS (0, 3, 0, 0x3c), 0x0a);
757 PciWrite8 (PCI_LIB_ADDRESS (0, 3, 0, 0x3d), 0x01); // INTA (-> LNKC)
758
759 //
760 // Bus 0, Device 5, Function 0 - RAM Memory
761 //
762 PciWrite8 (PCI_LIB_ADDRESS (0, 5, 0, 0x3c), 0x0b);
763 PciWrite8 (PCI_LIB_ADDRESS (0, 5, 0, 0x3d), 0x01); // INTA (-> LNKA)
764 }
765
766
767 VOID
768 AcpiInitialization (
769 VOID
770 )
771 {
772 //
773 // Set ACPI SCI_EN bit in PMCNTRL
774 //
775 IoOr16 ((PciRead32 (PCI_LIB_ADDRESS (0, 1, 3, 0x40)) & ~BIT0) + 4, BIT0);
776 }
777
778
779 EFI_STATUS
780 EFIAPI
781 ConnectRecursivelyIfPciMassStorage (
782 IN EFI_HANDLE Handle,
783 IN EFI_PCI_IO_PROTOCOL *Instance,
784 IN PCI_TYPE00 *PciHeader
785 )
786 {
787 EFI_STATUS Status;
788 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
789 CHAR16 *DevPathStr;
790
791 if (IS_CLASS1 (PciHeader, PCI_CLASS_MASS_STORAGE)) {
792 DevicePath = NULL;
793 Status = gBS->HandleProtocol (
794 Handle,
795 &gEfiDevicePathProtocolGuid,
796 (VOID*)&DevicePath
797 );
798 if (EFI_ERROR (Status)) {
799 return Status;
800 }
801
802 //
803 // Print Device Path
804 //
805 DevPathStr = DevicePathToStr (DevicePath);
806 if (DevPathStr != NULL) {
807 DEBUG((
808 EFI_D_INFO,
809 "Found Mass Storage device: %s\n",
810 DevPathStr
811 ));
812 FreePool(DevPathStr);
813 }
814
815 Status = gBS->ConnectController (Handle, NULL, NULL, TRUE);
816 if (EFI_ERROR (Status)) {
817 return Status;
818 }
819
820 }
821
822 return EFI_SUCCESS;
823 }
824
825
826 /**
827 This notification function is invoked when the
828 EMU Variable FVB has been changed.
829
830 @param Event The event that occured
831 @param Context For EFI compatiblity. Not used.
832
833 **/
834 VOID
835 EFIAPI
836 EmuVariablesUpdatedCallback (
837 IN EFI_EVENT Event,
838 IN VOID *Context
839 )
840 {
841 DEBUG ((EFI_D_INFO, "EmuVariablesUpdatedCallback\n"));
842 UpdateNvVarsOnFileSystem ();
843 }
844
845
846 EFI_STATUS
847 EFIAPI
848 VisitingFileSystemInstance (
849 IN EFI_HANDLE Handle,
850 IN VOID *Instance,
851 IN VOID *Context
852 )
853 {
854 EFI_STATUS Status;
855 STATIC BOOLEAN ConnectedToFileSystem = FALSE;
856
857 if (ConnectedToFileSystem) {
858 return EFI_ALREADY_STARTED;
859 }
860
861 Status = ConnectNvVarsToFileSystem (Handle);
862 if (EFI_ERROR (Status)) {
863 return Status;
864 }
865
866 ConnectedToFileSystem = TRUE;
867 mEmuVariableEvent =
868 EfiCreateProtocolNotifyEvent (
869 &gEfiDevicePathProtocolGuid,
870 TPL_CALLBACK,
871 EmuVariablesUpdatedCallback,
872 NULL,
873 &mEmuVariableEventReg
874 );
875 PcdSet64 (PcdEmuVariableEvent, (UINT64)(UINTN) mEmuVariableEvent);
876
877 return EFI_SUCCESS;
878 }
879
880
881 VOID
882 PlatformBdsRestoreNvVarsFromHardDisk (
883 )
884 {
885 VisitAllPciInstances (ConnectRecursivelyIfPciMassStorage);
886 VisitAllInstancesOfProtocol (
887 &gEfiSimpleFileSystemProtocolGuid,
888 VisitingFileSystemInstance,
889 NULL
890 );
891
892 }
893
894
895 VOID
896 PlatformBdsConnectSequence (
897 VOID
898 )
899 /*++
900
901 Routine Description:
902
903 Connect with predeined platform connect sequence,
904 the OEM/IBV can customize with their own connect sequence.
905
906 Arguments:
907
908 None.
909
910 Returns:
911
912 None.
913
914 --*/
915 {
916 UINTN Index;
917
918 DEBUG ((EFI_D_INFO, "PlatformBdsConnectSequence\n"));
919
920 Index = 0;
921
922 //
923 // Here we can get the customized platform connect sequence
924 // Notes: we can connect with new variable which record the
925 // last time boots connect device path sequence
926 //
927 while (gPlatformConnectSequence[Index] != NULL) {
928 //
929 // Build the platform boot option
930 //
931 BdsLibConnectDevicePath (gPlatformConnectSequence[Index]);
932 Index++;
933 }
934
935 //
936 // Just use the simple policy to connect all devices
937 //
938 BdsLibConnectAll ();
939
940 PciInitialization ();
941 AcpiInitialization ();
942
943 //
944 // Clear the logo after all devices are connected.
945 //
946 gST->ConOut->ClearScreen (gST->ConOut);
947 }
948
949 VOID
950 PlatformBdsGetDriverOption (
951 IN OUT LIST_ENTRY *BdsDriverLists
952 )
953 /*++
954
955 Routine Description:
956
957 Load the predefined driver option, OEM/IBV can customize this
958 to load their own drivers
959
960 Arguments:
961
962 BdsDriverLists - The header of the driver option link list.
963
964 Returns:
965
966 None.
967
968 --*/
969 {
970 DEBUG ((EFI_D_INFO, "PlatformBdsGetDriverOption\n"));
971 return;
972 }
973
974 VOID
975 PlatformBdsDiagnostics (
976 IN EXTENDMEM_COVERAGE_LEVEL MemoryTestLevel,
977 IN BOOLEAN QuietBoot,
978 IN BASEM_MEMORY_TEST BaseMemoryTest
979 )
980 /*++
981
982 Routine Description:
983
984 Perform the platform diagnostic, such like test memory. OEM/IBV also
985 can customize this fuction to support specific platform diagnostic.
986
987 Arguments:
988
989 MemoryTestLevel - The memory test intensive level
990
991 QuietBoot - Indicate if need to enable the quiet boot
992
993 BaseMemoryTest - A pointer to BaseMemoryTest()
994
995 Returns:
996
997 None.
998
999 --*/
1000 {
1001 EFI_STATUS Status;
1002
1003 DEBUG ((EFI_D_INFO, "PlatformBdsDiagnostics\n"));
1004
1005 //
1006 // Here we can decide if we need to show
1007 // the diagnostics screen
1008 // Notes: this quiet boot code should be remove
1009 // from the graphic lib
1010 //
1011 if (QuietBoot) {
1012 EnableQuietBoot (PcdGetPtr(PcdLogoFile));
1013 //
1014 // Perform system diagnostic
1015 //
1016 Status = BaseMemoryTest (MemoryTestLevel);
1017 if (EFI_ERROR (Status)) {
1018 DisableQuietBoot ();
1019 }
1020
1021 return ;
1022 }
1023 //
1024 // Perform system diagnostic
1025 //
1026 Status = BaseMemoryTest (MemoryTestLevel);
1027 }
1028
1029
1030 VOID
1031 EFIAPI
1032 PlatformBdsPolicyBehavior (
1033 IN OUT LIST_ENTRY *DriverOptionList,
1034 IN OUT LIST_ENTRY *BootOptionList,
1035 IN PROCESS_CAPSULES ProcessCapsules,
1036 IN BASEM_MEMORY_TEST BaseMemoryTest
1037 )
1038 /*++
1039
1040 Routine Description:
1041
1042 The function will excute with as the platform policy, current policy
1043 is driven by boot mode. IBV/OEM can customize this code for their specific
1044 policy action.
1045
1046 Arguments:
1047
1048 DriverOptionList - The header of the driver option link list
1049
1050 BootOptionList - The header of the boot option link list
1051
1052 ProcessCapsules - A pointer to ProcessCapsules()
1053
1054 BaseMemoryTest - A pointer to BaseMemoryTest()
1055
1056 Returns:
1057
1058 None.
1059
1060 --*/
1061 {
1062 EFI_STATUS Status;
1063 UINT16 Timeout;
1064 EFI_EVENT UserInputDurationTime;
1065 LIST_ENTRY *Link;
1066 BDS_COMMON_OPTION *BootOption;
1067 UINTN Index;
1068 EFI_INPUT_KEY Key;
1069 EFI_TPL OldTpl;
1070 EFI_BOOT_MODE BootMode;
1071
1072 DEBUG ((EFI_D_INFO, "PlatformBdsPolicyBehavior\n"));
1073
1074 ConnectRootBridge ();
1075
1076 if (PcdGetBool (PcdOvmfFlashVariablesEnable)) {
1077 DEBUG ((EFI_D_INFO, "PlatformBdsPolicyBehavior: not restoring NvVars "
1078 "from disk since flash variables appear to be supported.\n"));
1079 } else {
1080 //
1081 // Try to restore variables from the hard disk early so
1082 // they can be used for the other BDS connect operations.
1083 //
1084 PlatformBdsRestoreNvVarsFromHardDisk ();
1085 }
1086
1087 //
1088 // Init the time out value
1089 //
1090 Timeout = PcdGet16 (PcdPlatformBootTimeOut);
1091
1092 //
1093 // Load the driver option as the driver option list
1094 //
1095 PlatformBdsGetDriverOption (DriverOptionList);
1096
1097 //
1098 // Get current Boot Mode
1099 //
1100 Status = BdsLibGetBootMode (&BootMode);
1101 DEBUG ((EFI_D_ERROR, "Boot Mode:%x\n", BootMode));
1102
1103 //
1104 // Go the different platform policy with different boot mode
1105 // Notes: this part code can be change with the table policy
1106 //
1107 ASSERT (BootMode == BOOT_WITH_FULL_CONFIGURATION);
1108 //
1109 // Connect platform console
1110 //
1111 Status = PlatformBdsConnectConsole (gPlatformConsole);
1112 if (EFI_ERROR (Status)) {
1113 //
1114 // Here OEM/IBV can customize with defined action
1115 //
1116 PlatformBdsNoConsoleAction ();
1117 }
1118 //
1119 // Create a 300ms duration event to ensure user has enough input time to enter Setup
1120 //
1121 Status = gBS->CreateEvent (
1122 EVT_TIMER,
1123 0,
1124 NULL,
1125 NULL,
1126 &UserInputDurationTime
1127 );
1128 ASSERT (Status == EFI_SUCCESS);
1129 Status = gBS->SetTimer (UserInputDurationTime, TimerRelative, 3000000);
1130 ASSERT (Status == EFI_SUCCESS);
1131 //
1132 // Memory test and Logo show
1133 //
1134 PlatformBdsDiagnostics (IGNORE, TRUE, BaseMemoryTest);
1135
1136 //
1137 // Perform some platform specific connect sequence
1138 //
1139 PlatformBdsConnectSequence ();
1140
1141 //
1142 // Process QEMU's -kernel command line option
1143 //
1144 TryRunningQemuKernel ();
1145
1146 //
1147 // Give one chance to enter the setup if we
1148 // have the time out
1149 //
1150 if (Timeout != 0) {
1151 //PlatformBdsEnterFrontPage (Timeout, FALSE);
1152 }
1153
1154 DEBUG ((EFI_D_INFO, "BdsLibConnectAll\n"));
1155 BdsLibConnectAll ();
1156 BdsLibEnumerateAllBootOption (BootOptionList);
1157
1158 SetBootOrderFromQemu (BootOptionList);
1159 //
1160 // The BootOrder variable may have changed, reload the in-memory list with
1161 // it.
1162 //
1163 BdsLibBuildOptionFromVar (BootOptionList, L"BootOrder");
1164
1165 //
1166 // To give the User a chance to enter Setup here, if user set TimeOut is 0.
1167 // BDS should still give user a chance to enter Setup
1168 //
1169 // Connect first boot option, and then check user input before exit
1170 //
1171 for (Link = BootOptionList->ForwardLink; Link != BootOptionList;Link = Link->ForwardLink) {
1172 BootOption = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);
1173 if (!IS_LOAD_OPTION_TYPE (BootOption->Attribute, LOAD_OPTION_ACTIVE)) {
1174 //
1175 // skip the header of the link list, becuase it has no boot option
1176 //
1177 continue;
1178 } else {
1179 //
1180 // Make sure the boot option device path connected, but ignore the BBS device path
1181 //
1182 if (DevicePathType (BootOption->DevicePath) != BBS_DEVICE_PATH) {
1183 BdsLibConnectDevicePath (BootOption->DevicePath);
1184 }
1185 break;
1186 }
1187 }
1188
1189 //
1190 // Check whether the user input after the duration time has expired
1191 //
1192 OldTpl = EfiGetCurrentTpl();
1193 gBS->RestoreTPL (TPL_APPLICATION);
1194 gBS->WaitForEvent (1, &UserInputDurationTime, &Index);
1195 gBS->CloseEvent (UserInputDurationTime);
1196 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
1197 gBS->RaiseTPL (OldTpl);
1198
1199 if (!EFI_ERROR (Status)) {
1200 //
1201 // Enter Setup if user input
1202 //
1203 Timeout = 0xffff;
1204 PlatformBdsEnterFrontPage (Timeout, FALSE);
1205 }
1206
1207 return ;
1208 }
1209
1210 VOID
1211 EFIAPI
1212 PlatformBdsBootSuccess (
1213 IN BDS_COMMON_OPTION *Option
1214 )
1215 /*++
1216
1217 Routine Description:
1218
1219 Hook point after a boot attempt succeeds. We don't expect a boot option to
1220 return, so the EFI 1.0 specification defines that you will default to an
1221 interactive mode and stop processing the BootOrder list in this case. This
1222 is alos a platform implementation and can be customized by IBV/OEM.
1223
1224 Arguments:
1225
1226 Option - Pointer to Boot Option that succeeded to boot.
1227
1228 Returns:
1229
1230 None.
1231
1232 --*/
1233 {
1234 CHAR16 *TmpStr;
1235
1236 DEBUG ((EFI_D_INFO, "PlatformBdsBootSuccess\n"));
1237 //
1238 // If Boot returned with EFI_SUCCESS and there is not in the boot device
1239 // select loop then we need to pop up a UI and wait for user input.
1240 //
1241 TmpStr = Option->StatusString;
1242 if (TmpStr != NULL) {
1243 BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL);
1244 FreePool (TmpStr);
1245 }
1246 }
1247
1248 VOID
1249 EFIAPI
1250 PlatformBdsBootFail (
1251 IN BDS_COMMON_OPTION *Option,
1252 IN EFI_STATUS Status,
1253 IN CHAR16 *ExitData,
1254 IN UINTN ExitDataSize
1255 )
1256 /*++
1257
1258 Routine Description:
1259
1260 Hook point after a boot attempt fails.
1261
1262 Arguments:
1263
1264 Option - Pointer to Boot Option that failed to boot.
1265
1266 Status - Status returned from failed boot.
1267
1268 ExitData - Exit data returned from failed boot.
1269
1270 ExitDataSize - Exit data size returned from failed boot.
1271
1272 Returns:
1273
1274 None.
1275
1276 --*/
1277 {
1278 CHAR16 *TmpStr;
1279
1280 DEBUG ((EFI_D_INFO, "PlatformBdsBootFail\n"));
1281
1282 //
1283 // If Boot returned with failed status then we need to pop up a UI and wait
1284 // for user input.
1285 //
1286 TmpStr = Option->StatusString;
1287 if (TmpStr != NULL) {
1288 BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL);
1289 FreePool (TmpStr);
1290 }
1291 }
1292
1293 EFI_STATUS
1294 PlatformBdsNoConsoleAction (
1295 VOID
1296 )
1297 /*++
1298
1299 Routine Description:
1300
1301 This function is remained for IBV/OEM to do some platform action,
1302 if there no console device can be connected.
1303
1304 Arguments:
1305
1306 None.
1307
1308 Returns:
1309
1310 EFI_SUCCESS - Direct return success now.
1311
1312 --*/
1313 {
1314 DEBUG ((EFI_D_INFO, "PlatformBdsNoConsoleAction\n"));
1315 return EFI_SUCCESS;
1316 }
1317
1318 VOID
1319 EFIAPI
1320 PlatformBdsLockNonUpdatableFlash (
1321 VOID
1322 )
1323 {
1324 DEBUG ((EFI_D_INFO, "PlatformBdsLockNonUpdatableFlash\n"));
1325 return;
1326 }
1327
1328
1329 /**
1330 This notification function is invoked when an instance of the
1331 EFI_DEVICE_PATH_PROTOCOL is produced.
1332
1333 @param Event The event that occured
1334 @param Context For EFI compatiblity. Not used.
1335
1336 **/
1337 VOID
1338 EFIAPI
1339 NotifyDevPath (
1340 IN EFI_EVENT Event,
1341 IN VOID *Context
1342 )
1343 {
1344 EFI_HANDLE Handle;
1345 EFI_STATUS Status;
1346 UINTN BufferSize;
1347 EFI_DEVICE_PATH_PROTOCOL *DevPathNode;
1348 ATAPI_DEVICE_PATH *Atapi;
1349
1350 //
1351 // Examine all new handles
1352 //
1353 for (;;) {
1354 //
1355 // Get the next handle
1356 //
1357 BufferSize = sizeof (Handle);
1358 Status = gBS->LocateHandle (
1359 ByRegisterNotify,
1360 NULL,
1361 mEfiDevPathNotifyReg,
1362 &BufferSize,
1363 &Handle
1364 );
1365
1366 //
1367 // If not found, we're done
1368 //
1369 if (EFI_NOT_FOUND == Status) {
1370 break;
1371 }
1372
1373 if (EFI_ERROR (Status)) {
1374 continue;
1375 }
1376
1377 //
1378 // Get the DevicePath protocol on that handle
1379 //
1380 Status = gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **)&DevPathNode);
1381 ASSERT_EFI_ERROR (Status);
1382
1383 while (!IsDevicePathEnd (DevPathNode)) {
1384 //
1385 // Find the handler to dump this device path node
1386 //
1387 if (
1388 (DevicePathType(DevPathNode) == MESSAGING_DEVICE_PATH) &&
1389 (DevicePathSubType(DevPathNode) == MSG_ATAPI_DP)
1390 ) {
1391 Atapi = (ATAPI_DEVICE_PATH*) DevPathNode;
1392 PciOr16 (
1393 PCI_LIB_ADDRESS (
1394 0,
1395 1,
1396 1,
1397 (Atapi->PrimarySecondary == 1) ? 0x42: 0x40
1398 ),
1399 BIT15
1400 );
1401 }
1402
1403 //
1404 // Next device path node
1405 //
1406 DevPathNode = NextDevicePathNode (DevPathNode);
1407 }
1408 }
1409
1410 return;
1411 }
1412
1413
1414 VOID
1415 InstallDevicePathCallback (
1416 VOID
1417 )
1418 {
1419 DEBUG ((EFI_D_INFO, "Registered NotifyDevPath Event\n"));
1420 mEfiDevPathEvent = EfiCreateProtocolNotifyEvent (
1421 &gEfiDevicePathProtocolGuid,
1422 TPL_CALLBACK,
1423 NotifyDevPath,
1424 NULL,
1425 &mEfiDevPathNotifyReg
1426 );
1427 }
1428
1429 /**
1430 Lock the ConsoleIn device in system table. All key
1431 presses will be ignored until the Password is typed in. The only way to
1432 disable the password is to type it in to a ConIn device.
1433
1434 @param Password Password used to lock ConIn device.
1435
1436 @retval EFI_SUCCESS lock the Console In Spliter virtual handle successfully.
1437 @retval EFI_UNSUPPORTED Password not found
1438
1439 **/
1440 EFI_STATUS
1441 EFIAPI
1442 LockKeyboards (
1443 IN CHAR16 *Password
1444 )
1445 {
1446 return EFI_UNSUPPORTED;
1447 }
1448