Fix VS2013 build failure.
[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 PciInitialization (
721 )
722 {
723 //
724 // Bus 0, Device 0, Function 0 - Host to PCI Bridge
725 //
726 PciWrite8 (PCI_LIB_ADDRESS (0, 0, 0, 0x3c), 0x00);
727
728 //
729 // Bus 0, Device 1, Function 0 - PCI to ISA Bridge
730 //
731 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x3c), 0x00);
732 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x60), 0x0b); // LNKA routing target
733 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x61), 0x0b); // LNKB routing target
734 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x62), 0x0a); // LNKC routing target
735 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x63), 0x0a); // LNKD routing target
736
737 //
738 // Bus 0, Device 1, Function 1 - IDE Controller
739 //
740 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 1, 0x3c), 0x00);
741 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 1, 0x0d), 0x40);
742
743 //
744 // Bus 0, Device 1, Function 3 - Power Managment Controller
745 //
746 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 3, 0x3c), 0x09);
747 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 3, 0x3d), 0x01); // INTA
748
749 //
750 // Bus 0, Device 2, Function 0 - Video Controller
751 //
752 PciWrite8 (PCI_LIB_ADDRESS (0, 2, 0, 0x3c), 0x00);
753
754 //
755 // Bus 0, Device 3, Function 0 - Network Controller
756 //
757 PciWrite8 (PCI_LIB_ADDRESS (0, 3, 0, 0x3c), 0x0a);
758 PciWrite8 (PCI_LIB_ADDRESS (0, 3, 0, 0x3d), 0x01); // INTA (-> LNKC)
759
760 //
761 // Bus 0, Device 5, Function 0 - RAM Memory
762 //
763 PciWrite8 (PCI_LIB_ADDRESS (0, 5, 0, 0x3c), 0x0b);
764 PciWrite8 (PCI_LIB_ADDRESS (0, 5, 0, 0x3d), 0x01); // INTA (-> LNKA)
765 }
766
767
768 VOID
769 AcpiInitialization (
770 VOID
771 )
772 {
773 //
774 // Set ACPI SCI_EN bit in PMCNTRL
775 //
776 IoOr16 ((PciRead32 (PCI_LIB_ADDRESS (0, 1, 3, 0x40)) & ~BIT0) + 4, BIT0);
777 }
778
779
780 EFI_STATUS
781 EFIAPI
782 ConnectRecursivelyIfPciMassStorage (
783 IN EFI_HANDLE Handle,
784 IN EFI_PCI_IO_PROTOCOL *Instance,
785 IN PCI_TYPE00 *PciHeader
786 )
787 {
788 EFI_STATUS Status;
789 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
790 CHAR16 *DevPathStr;
791
792 if (IS_CLASS1 (PciHeader, PCI_CLASS_MASS_STORAGE)) {
793 DevicePath = NULL;
794 Status = gBS->HandleProtocol (
795 Handle,
796 &gEfiDevicePathProtocolGuid,
797 (VOID*)&DevicePath
798 );
799 if (EFI_ERROR (Status)) {
800 return Status;
801 }
802
803 //
804 // Print Device Path
805 //
806 DevPathStr = DevicePathToStr (DevicePath);
807 if (DevPathStr != NULL) {
808 DEBUG((
809 EFI_D_INFO,
810 "Found Mass Storage device: %s\n",
811 DevPathStr
812 ));
813 FreePool(DevPathStr);
814 }
815
816 Status = gBS->ConnectController (Handle, NULL, NULL, TRUE);
817 if (EFI_ERROR (Status)) {
818 return Status;
819 }
820
821 }
822
823 return EFI_SUCCESS;
824 }
825
826
827 /**
828 This notification function is invoked when the
829 EMU Variable FVB has been changed.
830
831 @param Event The event that occured
832 @param Context For EFI compatiblity. Not used.
833
834 **/
835 VOID
836 EFIAPI
837 EmuVariablesUpdatedCallback (
838 IN EFI_EVENT Event,
839 IN VOID *Context
840 )
841 {
842 DEBUG ((EFI_D_INFO, "EmuVariablesUpdatedCallback\n"));
843 UpdateNvVarsOnFileSystem ();
844 }
845
846
847 EFI_STATUS
848 EFIAPI
849 VisitingFileSystemInstance (
850 IN EFI_HANDLE Handle,
851 IN VOID *Instance,
852 IN VOID *Context
853 )
854 {
855 EFI_STATUS Status;
856 STATIC BOOLEAN ConnectedToFileSystem = FALSE;
857
858 if (ConnectedToFileSystem) {
859 return EFI_ALREADY_STARTED;
860 }
861
862 Status = ConnectNvVarsToFileSystem (Handle);
863 if (EFI_ERROR (Status)) {
864 return Status;
865 }
866
867 ConnectedToFileSystem = TRUE;
868 mEmuVariableEvent =
869 EfiCreateProtocolNotifyEvent (
870 &gEfiDevicePathProtocolGuid,
871 TPL_CALLBACK,
872 EmuVariablesUpdatedCallback,
873 NULL,
874 &mEmuVariableEventReg
875 );
876 PcdSet64 (PcdEmuVariableEvent, (UINT64)(UINTN) mEmuVariableEvent);
877
878 return EFI_SUCCESS;
879 }
880
881
882 VOID
883 PlatformBdsRestoreNvVarsFromHardDisk (
884 )
885 {
886 VisitAllPciInstances (ConnectRecursivelyIfPciMassStorage);
887 VisitAllInstancesOfProtocol (
888 &gEfiSimpleFileSystemProtocolGuid,
889 VisitingFileSystemInstance,
890 NULL
891 );
892
893 }
894
895
896 VOID
897 PlatformBdsConnectSequence (
898 VOID
899 )
900 /*++
901
902 Routine Description:
903
904 Connect with predeined platform connect sequence,
905 the OEM/IBV can customize with their own connect sequence.
906
907 Arguments:
908
909 None.
910
911 Returns:
912
913 None.
914
915 --*/
916 {
917 UINTN Index;
918
919 DEBUG ((EFI_D_INFO, "PlatformBdsConnectSequence\n"));
920
921 Index = 0;
922
923 //
924 // Here we can get the customized platform connect sequence
925 // Notes: we can connect with new variable which record the
926 // last time boots connect device path sequence
927 //
928 while (gPlatformConnectSequence[Index] != NULL) {
929 //
930 // Build the platform boot option
931 //
932 BdsLibConnectDevicePath (gPlatformConnectSequence[Index]);
933 Index++;
934 }
935
936 //
937 // Just use the simple policy to connect all devices
938 //
939 BdsLibConnectAll ();
940
941 PciInitialization ();
942 AcpiInitialization ();
943
944 //
945 // Clear the logo after all devices are connected.
946 //
947 gST->ConOut->ClearScreen (gST->ConOut);
948 }
949
950 VOID
951 PlatformBdsGetDriverOption (
952 IN OUT LIST_ENTRY *BdsDriverLists
953 )
954 /*++
955
956 Routine Description:
957
958 Load the predefined driver option, OEM/IBV can customize this
959 to load their own drivers
960
961 Arguments:
962
963 BdsDriverLists - The header of the driver option link list.
964
965 Returns:
966
967 None.
968
969 --*/
970 {
971 DEBUG ((EFI_D_INFO, "PlatformBdsGetDriverOption\n"));
972 return;
973 }
974
975 VOID
976 PlatformBdsDiagnostics (
977 IN EXTENDMEM_COVERAGE_LEVEL MemoryTestLevel,
978 IN BOOLEAN QuietBoot,
979 IN BASEM_MEMORY_TEST BaseMemoryTest
980 )
981 /*++
982
983 Routine Description:
984
985 Perform the platform diagnostic, such like test memory. OEM/IBV also
986 can customize this fuction to support specific platform diagnostic.
987
988 Arguments:
989
990 MemoryTestLevel - The memory test intensive level
991
992 QuietBoot - Indicate if need to enable the quiet boot
993
994 BaseMemoryTest - A pointer to BaseMemoryTest()
995
996 Returns:
997
998 None.
999
1000 --*/
1001 {
1002 EFI_STATUS Status;
1003
1004 DEBUG ((EFI_D_INFO, "PlatformBdsDiagnostics\n"));
1005
1006 //
1007 // Here we can decide if we need to show
1008 // the diagnostics screen
1009 // Notes: this quiet boot code should be remove
1010 // from the graphic lib
1011 //
1012 if (QuietBoot) {
1013 EnableQuietBoot (PcdGetPtr(PcdLogoFile));
1014 //
1015 // Perform system diagnostic
1016 //
1017 Status = BaseMemoryTest (MemoryTestLevel);
1018 if (EFI_ERROR (Status)) {
1019 DisableQuietBoot ();
1020 }
1021
1022 return ;
1023 }
1024 //
1025 // Perform system diagnostic
1026 //
1027 Status = BaseMemoryTest (MemoryTestLevel);
1028 }
1029
1030
1031 VOID
1032 EFIAPI
1033 PlatformBdsPolicyBehavior (
1034 IN OUT LIST_ENTRY *DriverOptionList,
1035 IN OUT LIST_ENTRY *BootOptionList,
1036 IN PROCESS_CAPSULES ProcessCapsules,
1037 IN BASEM_MEMORY_TEST BaseMemoryTest
1038 )
1039 /*++
1040
1041 Routine Description:
1042
1043 The function will excute with as the platform policy, current policy
1044 is driven by boot mode. IBV/OEM can customize this code for their specific
1045 policy action.
1046
1047 Arguments:
1048
1049 DriverOptionList - The header of the driver option link list
1050
1051 BootOptionList - The header of the boot option link list
1052
1053 ProcessCapsules - A pointer to ProcessCapsules()
1054
1055 BaseMemoryTest - A pointer to BaseMemoryTest()
1056
1057 Returns:
1058
1059 None.
1060
1061 --*/
1062 {
1063 EFI_STATUS Status;
1064 UINT16 Timeout;
1065 EFI_EVENT UserInputDurationTime;
1066 LIST_ENTRY *Link;
1067 BDS_COMMON_OPTION *BootOption;
1068 UINTN Index;
1069 EFI_INPUT_KEY Key;
1070 EFI_TPL OldTpl;
1071 EFI_BOOT_MODE BootMode;
1072
1073 DEBUG ((EFI_D_INFO, "PlatformBdsPolicyBehavior\n"));
1074
1075 ConnectRootBridge ();
1076
1077 if (PcdGetBool (PcdOvmfFlashVariablesEnable)) {
1078 DEBUG ((EFI_D_INFO, "PlatformBdsPolicyBehavior: not restoring NvVars "
1079 "from disk since flash variables appear to be supported.\n"));
1080 } else {
1081 //
1082 // Try to restore variables from the hard disk early so
1083 // they can be used for the other BDS connect operations.
1084 //
1085 PlatformBdsRestoreNvVarsFromHardDisk ();
1086 }
1087
1088 //
1089 // Init the time out value
1090 //
1091 Timeout = PcdGet16 (PcdPlatformBootTimeOut);
1092
1093 //
1094 // Load the driver option as the driver option list
1095 //
1096 PlatformBdsGetDriverOption (DriverOptionList);
1097
1098 //
1099 // Get current Boot Mode
1100 //
1101 Status = BdsLibGetBootMode (&BootMode);
1102 DEBUG ((EFI_D_ERROR, "Boot Mode:%x\n", BootMode));
1103
1104 //
1105 // Go the different platform policy with different boot mode
1106 // Notes: this part code can be change with the table policy
1107 //
1108 ASSERT (BootMode == BOOT_WITH_FULL_CONFIGURATION);
1109 //
1110 // Connect platform console
1111 //
1112 Status = PlatformBdsConnectConsole (gPlatformConsole);
1113 if (EFI_ERROR (Status)) {
1114 //
1115 // Here OEM/IBV can customize with defined action
1116 //
1117 PlatformBdsNoConsoleAction ();
1118 }
1119 //
1120 // Create a 300ms duration event to ensure user has enough input time to enter Setup
1121 //
1122 Status = gBS->CreateEvent (
1123 EVT_TIMER,
1124 0,
1125 NULL,
1126 NULL,
1127 &UserInputDurationTime
1128 );
1129 ASSERT (Status == EFI_SUCCESS);
1130 Status = gBS->SetTimer (UserInputDurationTime, TimerRelative, 3000000);
1131 ASSERT (Status == EFI_SUCCESS);
1132 //
1133 // Memory test and Logo show
1134 //
1135 PlatformBdsDiagnostics (IGNORE, TRUE, BaseMemoryTest);
1136
1137 //
1138 // Perform some platform specific connect sequence
1139 //
1140 PlatformBdsConnectSequence ();
1141
1142 //
1143 // Process QEMU's -kernel command line option
1144 //
1145 TryRunningQemuKernel ();
1146
1147 //
1148 // Give one chance to enter the setup if we
1149 // have the time out
1150 //
1151 if (Timeout != 0) {
1152 //PlatformBdsEnterFrontPage (Timeout, FALSE);
1153 }
1154
1155 DEBUG ((EFI_D_INFO, "BdsLibConnectAll\n"));
1156 BdsLibConnectAll ();
1157 BdsLibEnumerateAllBootOption (BootOptionList);
1158
1159 SetBootOrderFromQemu (BootOptionList);
1160 //
1161 // The BootOrder variable may have changed, reload the in-memory list with
1162 // it.
1163 //
1164 BdsLibBuildOptionFromVar (BootOptionList, L"BootOrder");
1165
1166 //
1167 // To give the User a chance to enter Setup here, if user set TimeOut is 0.
1168 // BDS should still give user a chance to enter Setup
1169 //
1170 // Connect first boot option, and then check user input before exit
1171 //
1172 for (Link = BootOptionList->ForwardLink; Link != BootOptionList;Link = Link->ForwardLink) {
1173 BootOption = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);
1174 if (!IS_LOAD_OPTION_TYPE (BootOption->Attribute, LOAD_OPTION_ACTIVE)) {
1175 //
1176 // skip the header of the link list, becuase it has no boot option
1177 //
1178 continue;
1179 } else {
1180 //
1181 // Make sure the boot option device path connected, but ignore the BBS device path
1182 //
1183 if (DevicePathType (BootOption->DevicePath) != BBS_DEVICE_PATH) {
1184 BdsLibConnectDevicePath (BootOption->DevicePath);
1185 }
1186 break;
1187 }
1188 }
1189
1190 //
1191 // Check whether the user input after the duration time has expired
1192 //
1193 OldTpl = EfiGetCurrentTpl();
1194 gBS->RestoreTPL (TPL_APPLICATION);
1195 gBS->WaitForEvent (1, &UserInputDurationTime, &Index);
1196 gBS->CloseEvent (UserInputDurationTime);
1197 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
1198 gBS->RaiseTPL (OldTpl);
1199
1200 if (!EFI_ERROR (Status)) {
1201 //
1202 // Enter Setup if user input
1203 //
1204 Timeout = 0xffff;
1205 PlatformBdsEnterFrontPage (Timeout, FALSE);
1206 }
1207
1208 return ;
1209 }
1210
1211 VOID
1212 EFIAPI
1213 PlatformBdsBootSuccess (
1214 IN BDS_COMMON_OPTION *Option
1215 )
1216 /*++
1217
1218 Routine Description:
1219
1220 Hook point after a boot attempt succeeds. We don't expect a boot option to
1221 return, so the EFI 1.0 specification defines that you will default to an
1222 interactive mode and stop processing the BootOrder list in this case. This
1223 is alos a platform implementation and can be customized by IBV/OEM.
1224
1225 Arguments:
1226
1227 Option - Pointer to Boot Option that succeeded to boot.
1228
1229 Returns:
1230
1231 None.
1232
1233 --*/
1234 {
1235 CHAR16 *TmpStr;
1236
1237 DEBUG ((EFI_D_INFO, "PlatformBdsBootSuccess\n"));
1238 //
1239 // If Boot returned with EFI_SUCCESS and there is not in the boot device
1240 // select loop then we need to pop up a UI and wait for user input.
1241 //
1242 TmpStr = Option->StatusString;
1243 if (TmpStr != NULL) {
1244 BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL);
1245 FreePool (TmpStr);
1246 }
1247 }
1248
1249 VOID
1250 EFIAPI
1251 PlatformBdsBootFail (
1252 IN BDS_COMMON_OPTION *Option,
1253 IN EFI_STATUS Status,
1254 IN CHAR16 *ExitData,
1255 IN UINTN ExitDataSize
1256 )
1257 /*++
1258
1259 Routine Description:
1260
1261 Hook point after a boot attempt fails.
1262
1263 Arguments:
1264
1265 Option - Pointer to Boot Option that failed to boot.
1266
1267 Status - Status returned from failed boot.
1268
1269 ExitData - Exit data returned from failed boot.
1270
1271 ExitDataSize - Exit data size returned from failed boot.
1272
1273 Returns:
1274
1275 None.
1276
1277 --*/
1278 {
1279 CHAR16 *TmpStr;
1280
1281 DEBUG ((EFI_D_INFO, "PlatformBdsBootFail\n"));
1282
1283 //
1284 // If Boot returned with failed status then we need to pop up a UI and wait
1285 // for user input.
1286 //
1287 TmpStr = Option->StatusString;
1288 if (TmpStr != NULL) {
1289 BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL);
1290 FreePool (TmpStr);
1291 }
1292 }
1293
1294 EFI_STATUS
1295 PlatformBdsNoConsoleAction (
1296 VOID
1297 )
1298 /*++
1299
1300 Routine Description:
1301
1302 This function is remained for IBV/OEM to do some platform action,
1303 if there no console device can be connected.
1304
1305 Arguments:
1306
1307 None.
1308
1309 Returns:
1310
1311 EFI_SUCCESS - Direct return success now.
1312
1313 --*/
1314 {
1315 DEBUG ((EFI_D_INFO, "PlatformBdsNoConsoleAction\n"));
1316 return EFI_SUCCESS;
1317 }
1318
1319 VOID
1320 EFIAPI
1321 PlatformBdsLockNonUpdatableFlash (
1322 VOID
1323 )
1324 {
1325 DEBUG ((EFI_D_INFO, "PlatformBdsLockNonUpdatableFlash\n"));
1326 return;
1327 }
1328
1329
1330 /**
1331 This notification function is invoked when an instance of the
1332 EFI_DEVICE_PATH_PROTOCOL is produced.
1333
1334 @param Event The event that occured
1335 @param Context For EFI compatiblity. Not used.
1336
1337 **/
1338 VOID
1339 EFIAPI
1340 NotifyDevPath (
1341 IN EFI_EVENT Event,
1342 IN VOID *Context
1343 )
1344 {
1345 EFI_HANDLE Handle;
1346 EFI_STATUS Status;
1347 UINTN BufferSize;
1348 EFI_DEVICE_PATH_PROTOCOL *DevPathNode;
1349 ATAPI_DEVICE_PATH *Atapi;
1350
1351 //
1352 // Examine all new handles
1353 //
1354 for (;;) {
1355 //
1356 // Get the next handle
1357 //
1358 BufferSize = sizeof (Handle);
1359 Status = gBS->LocateHandle (
1360 ByRegisterNotify,
1361 NULL,
1362 mEfiDevPathNotifyReg,
1363 &BufferSize,
1364 &Handle
1365 );
1366
1367 //
1368 // If not found, we're done
1369 //
1370 if (EFI_NOT_FOUND == Status) {
1371 break;
1372 }
1373
1374 if (EFI_ERROR (Status)) {
1375 continue;
1376 }
1377
1378 //
1379 // Get the DevicePath protocol on that handle
1380 //
1381 Status = gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **)&DevPathNode);
1382 ASSERT_EFI_ERROR (Status);
1383
1384 while (!IsDevicePathEnd (DevPathNode)) {
1385 //
1386 // Find the handler to dump this device path node
1387 //
1388 if (
1389 (DevicePathType(DevPathNode) == MESSAGING_DEVICE_PATH) &&
1390 (DevicePathSubType(DevPathNode) == MSG_ATAPI_DP)
1391 ) {
1392 Atapi = (ATAPI_DEVICE_PATH*) DevPathNode;
1393 PciOr16 (
1394 PCI_LIB_ADDRESS (
1395 0,
1396 1,
1397 1,
1398 (Atapi->PrimarySecondary == 1) ? 0x42: 0x40
1399 ),
1400 BIT15
1401 );
1402 }
1403
1404 //
1405 // Next device path node
1406 //
1407 DevPathNode = NextDevicePathNode (DevPathNode);
1408 }
1409 }
1410
1411 return;
1412 }
1413
1414
1415 VOID
1416 InstallDevicePathCallback (
1417 VOID
1418 )
1419 {
1420 DEBUG ((EFI_D_INFO, "Registered NotifyDevPath Event\n"));
1421 mEfiDevPathEvent = EfiCreateProtocolNotifyEvent (
1422 &gEfiDevicePathProtocolGuid,
1423 TPL_CALLBACK,
1424 NotifyDevPath,
1425 NULL,
1426 &mEfiDevPathNotifyReg
1427 );
1428 }
1429
1430 /**
1431 Lock the ConsoleIn device in system table. All key
1432 presses will be ignored until the Password is typed in. The only way to
1433 disable the password is to type it in to a ConIn device.
1434
1435 @param Password Password used to lock ConIn device.
1436
1437 @retval EFI_SUCCESS lock the Console In Spliter virtual handle successfully.
1438 @retval EFI_UNSUPPORTED Password not found
1439
1440 **/
1441 EFI_STATUS
1442 EFIAPI
1443 LockKeyboards (
1444 IN CHAR16 *Password
1445 )
1446 {
1447 return EFI_UNSUPPORTED;
1448 }
1449