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