]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c
OvmfPkg/BdsPlatform: don't restore NvVars from disk when flash is present
[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 //
1161 // Please uncomment above ConnectAll and EnumerateAll code and remove following first boot
1162 // checking code in real production tip.
1163 //
1164 // In BOOT_WITH_FULL_CONFIGURATION boot mode, should always connect every device
1165 // and do enumerate all the default boot options. But in development system board, the boot mode
1166 // cannot be BOOT_ASSUMING_NO_CONFIGURATION_CHANGES because the machine box
1167 // is always open. So the following code only do the ConnectAll and EnumerateAll at first boot.
1168 //
1169 Status = BdsLibBuildOptionFromVar (BootOptionList, L"BootOrder");
1170 if (EFI_ERROR(Status)) {
1171 //
1172 // If cannot find "BootOrder" variable, it may be first boot.
1173 // Try to connect all devices and enumerate all boot options here.
1174 //
1175 BdsLibConnectAll ();
1176 BdsLibEnumerateAllBootOption (BootOptionList);
1177 }
1178
1179 //
1180 // To give the User a chance to enter Setup here, if user set TimeOut is 0.
1181 // BDS should still give user a chance to enter Setup
1182 //
1183 // Connect first boot option, and then check user input before exit
1184 //
1185 for (Link = BootOptionList->ForwardLink; Link != BootOptionList;Link = Link->ForwardLink) {
1186 BootOption = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);
1187 if (!IS_LOAD_OPTION_TYPE (BootOption->Attribute, LOAD_OPTION_ACTIVE)) {
1188 //
1189 // skip the header of the link list, becuase it has no boot option
1190 //
1191 continue;
1192 } else {
1193 //
1194 // Make sure the boot option device path connected, but ignore the BBS device path
1195 //
1196 if (DevicePathType (BootOption->DevicePath) != BBS_DEVICE_PATH) {
1197 BdsLibConnectDevicePath (BootOption->DevicePath);
1198 }
1199 break;
1200 }
1201 }
1202
1203 //
1204 // Check whether the user input after the duration time has expired
1205 //
1206 OldTpl = EfiGetCurrentTpl();
1207 gBS->RestoreTPL (TPL_APPLICATION);
1208 gBS->WaitForEvent (1, &UserInputDurationTime, &Index);
1209 gBS->CloseEvent (UserInputDurationTime);
1210 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
1211 gBS->RaiseTPL (OldTpl);
1212
1213 if (!EFI_ERROR (Status)) {
1214 //
1215 // Enter Setup if user input
1216 //
1217 Timeout = 0xffff;
1218 PlatformBdsEnterFrontPage (Timeout, FALSE);
1219 }
1220
1221 return ;
1222 }
1223
1224 VOID
1225 EFIAPI
1226 PlatformBdsBootSuccess (
1227 IN BDS_COMMON_OPTION *Option
1228 )
1229 /*++
1230
1231 Routine Description:
1232
1233 Hook point after a boot attempt succeeds. We don't expect a boot option to
1234 return, so the EFI 1.0 specification defines that you will default to an
1235 interactive mode and stop processing the BootOrder list in this case. This
1236 is alos a platform implementation and can be customized by IBV/OEM.
1237
1238 Arguments:
1239
1240 Option - Pointer to Boot Option that succeeded to boot.
1241
1242 Returns:
1243
1244 None.
1245
1246 --*/
1247 {
1248 CHAR16 *TmpStr;
1249
1250 DEBUG ((EFI_D_INFO, "PlatformBdsBootSuccess\n"));
1251 //
1252 // If Boot returned with EFI_SUCCESS and there is not in the boot device
1253 // select loop then we need to pop up a UI and wait for user input.
1254 //
1255 TmpStr = Option->StatusString;
1256 if (TmpStr != NULL) {
1257 BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL);
1258 FreePool (TmpStr);
1259 }
1260 }
1261
1262 VOID
1263 EFIAPI
1264 PlatformBdsBootFail (
1265 IN BDS_COMMON_OPTION *Option,
1266 IN EFI_STATUS Status,
1267 IN CHAR16 *ExitData,
1268 IN UINTN ExitDataSize
1269 )
1270 /*++
1271
1272 Routine Description:
1273
1274 Hook point after a boot attempt fails.
1275
1276 Arguments:
1277
1278 Option - Pointer to Boot Option that failed to boot.
1279
1280 Status - Status returned from failed boot.
1281
1282 ExitData - Exit data returned from failed boot.
1283
1284 ExitDataSize - Exit data size returned from failed boot.
1285
1286 Returns:
1287
1288 None.
1289
1290 --*/
1291 {
1292 CHAR16 *TmpStr;
1293
1294 DEBUG ((EFI_D_INFO, "PlatformBdsBootFail\n"));
1295
1296 //
1297 // If Boot returned with failed status then we need to pop up a UI and wait
1298 // for user input.
1299 //
1300 TmpStr = Option->StatusString;
1301 if (TmpStr != NULL) {
1302 BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL);
1303 FreePool (TmpStr);
1304 }
1305 }
1306
1307 EFI_STATUS
1308 PlatformBdsNoConsoleAction (
1309 VOID
1310 )
1311 /*++
1312
1313 Routine Description:
1314
1315 This function is remained for IBV/OEM to do some platform action,
1316 if there no console device can be connected.
1317
1318 Arguments:
1319
1320 None.
1321
1322 Returns:
1323
1324 EFI_SUCCESS - Direct return success now.
1325
1326 --*/
1327 {
1328 DEBUG ((EFI_D_INFO, "PlatformBdsNoConsoleAction\n"));
1329 return EFI_SUCCESS;
1330 }
1331
1332 VOID
1333 EFIAPI
1334 PlatformBdsLockNonUpdatableFlash (
1335 VOID
1336 )
1337 {
1338 DEBUG ((EFI_D_INFO, "PlatformBdsLockNonUpdatableFlash\n"));
1339 return;
1340 }
1341
1342
1343 /**
1344 This notification function is invoked when an instance of the
1345 EFI_DEVICE_PATH_PROTOCOL is produced.
1346
1347 @param Event The event that occured
1348 @param Context For EFI compatiblity. Not used.
1349
1350 **/
1351 VOID
1352 EFIAPI
1353 NotifyDevPath (
1354 IN EFI_EVENT Event,
1355 IN VOID *Context
1356 )
1357 {
1358 EFI_HANDLE Handle;
1359 EFI_STATUS Status;
1360 UINTN BufferSize;
1361 EFI_DEVICE_PATH_PROTOCOL *DevPathNode;
1362 ATAPI_DEVICE_PATH *Atapi;
1363
1364 //
1365 // Examine all new handles
1366 //
1367 for (;;) {
1368 //
1369 // Get the next handle
1370 //
1371 BufferSize = sizeof (Handle);
1372 Status = gBS->LocateHandle (
1373 ByRegisterNotify,
1374 NULL,
1375 mEfiDevPathNotifyReg,
1376 &BufferSize,
1377 &Handle
1378 );
1379
1380 //
1381 // If not found, we're done
1382 //
1383 if (EFI_NOT_FOUND == Status) {
1384 break;
1385 }
1386
1387 if (EFI_ERROR (Status)) {
1388 continue;
1389 }
1390
1391 //
1392 // Get the DevicePath protocol on that handle
1393 //
1394 Status = gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **)&DevPathNode);
1395 ASSERT_EFI_ERROR (Status);
1396
1397 while (!IsDevicePathEnd (DevPathNode)) {
1398 //
1399 // Find the handler to dump this device path node
1400 //
1401 if (
1402 (DevicePathType(DevPathNode) == MESSAGING_DEVICE_PATH) &&
1403 (DevicePathSubType(DevPathNode) == MSG_ATAPI_DP)
1404 ) {
1405 Atapi = (ATAPI_DEVICE_PATH*) DevPathNode;
1406 PciOr16 (
1407 PCI_LIB_ADDRESS (
1408 0,
1409 1,
1410 1,
1411 (Atapi->PrimarySecondary == 1) ? 0x42: 0x40
1412 ),
1413 BIT15
1414 );
1415 }
1416
1417 //
1418 // Next device path node
1419 //
1420 DevPathNode = NextDevicePathNode (DevPathNode);
1421 }
1422 }
1423
1424 return;
1425 }
1426
1427
1428 VOID
1429 InstallDevicePathCallback (
1430 VOID
1431 )
1432 {
1433 DEBUG ((EFI_D_INFO, "Registered NotifyDevPath Event\n"));
1434 mEfiDevPathEvent = EfiCreateProtocolNotifyEvent (
1435 &gEfiDevicePathProtocolGuid,
1436 TPL_CALLBACK,
1437 NotifyDevPath,
1438 NULL,
1439 &mEfiDevPathNotifyReg
1440 );
1441 }
1442
1443 /**
1444 Lock the ConsoleIn device in system table. All key
1445 presses will be ignored until the Password is typed in. The only way to
1446 disable the password is to type it in to a ConIn device.
1447
1448 @param Password Password used to lock ConIn device.
1449
1450 @retval EFI_SUCCESS lock the Console In Spliter virtual handle successfully.
1451 @retval EFI_UNSUPPORTED Password not found
1452
1453 **/
1454 EFI_STATUS
1455 EFIAPI
1456 LockKeyboards (
1457 IN CHAR16 *Password
1458 )
1459 {
1460 return EFI_UNSUPPORTED;
1461 }
1462