]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c
fix ICC build issue.
[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 if (!DetectVgaOnly) {
466 //
467 // Here we decide whether it is LPC Bridge
468 //
469 if ((IS_PCI_LPC (&Pci)) ||
470 ((IS_PCI_ISA_PDECODE (&Pci)) &&
471 (Pci.Hdr.VendorId == 0x8086) &&
472 (Pci.Hdr.DeviceId == 0x7000)
473 )
474 ) {
475 Status = PciIo->Attributes (
476 PciIo,
477 EfiPciIoAttributeOperationEnable,
478 EFI_PCI_DEVICE_ENABLE,
479 NULL
480 );
481 //
482 // Add IsaKeyboard to ConIn,
483 // add IsaSerial to ConOut, ConIn, ErrOut
484 //
485 DEBUG ((EFI_D_INFO, "Find the LPC Bridge device\n"));
486 PrepareLpcBridgeDevicePath (HandleBuffer[Index]);
487 continue;
488 }
489 //
490 // Here we decide which Serial device to enable in PCI bus
491 //
492 if (IS_PCI_16550SERIAL (&Pci)) {
493 //
494 // Add them to ConOut, ConIn, ErrOut.
495 //
496 DEBUG ((EFI_D_INFO, "Find the 16550 SERIAL device\n"));
497 PreparePciSerialDevicePath (HandleBuffer[Index]);
498 continue;
499 }
500 }
501
502 if ((Pci.Hdr.VendorId == 0x8086) &&
503 (Pci.Hdr.DeviceId == 0x7010)
504 ) {
505 Status = PciIo->Attributes (
506 PciIo,
507 EfiPciIoAttributeOperationEnable,
508 EFI_PCI_DEVICE_ENABLE,
509 NULL
510 );
511 }
512
513 //
514 // Here we decide which VGA device to enable in PCI bus
515 //
516 if (IS_PCI_VGA (&Pci)) {
517 //
518 // Add them to ConOut.
519 //
520 DEBUG ((EFI_D_INFO, "Find the VGA device\n"));
521 PreparePciVgaDevicePath (HandleBuffer[Index]);
522 continue;
523 }
524 }
525
526 gBS->FreePool (HandleBuffer);
527
528 return EFI_SUCCESS;
529 }
530
531
532 EFI_STATUS
533 PlatformBdsConnectConsole (
534 IN BDS_CONSOLE_CONNECT_ENTRY *PlatformConsole
535 )
536 /*++
537
538 Routine Description:
539
540 Connect the predefined platform default console device. Always try to find
541 and enable the vga device if have.
542
543 Arguments:
544
545 PlatformConsole - Predfined platform default console device array.
546
547 Returns:
548
549 EFI_SUCCESS - Success connect at least one ConIn and ConOut
550 device, there must have one ConOut device is
551 active vga device.
552
553 EFI_STATUS - Return the status of
554 BdsLibConnectAllDefaultConsoles ()
555
556 --*/
557 {
558 EFI_STATUS Status;
559 UINTN Index;
560 EFI_DEVICE_PATH_PROTOCOL *VarConout;
561 EFI_DEVICE_PATH_PROTOCOL *VarConin;
562 UINTN DevicePathSize;
563
564 //
565 // Connect RootBridge
566 //
567 ConnectRootBridge ();
568
569 VarConout = BdsLibGetVariableAndSize (
570 VarConsoleOut,
571 &gEfiGlobalVariableGuid,
572 &DevicePathSize
573 );
574 VarConin = BdsLibGetVariableAndSize (
575 VarConsoleInp,
576 &gEfiGlobalVariableGuid,
577 &DevicePathSize
578 );
579
580 if (VarConout == NULL || VarConin == NULL) {
581 //
582 // Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
583 //
584 DetectAndPreparePlatformPciDevicePath (FALSE);
585
586 //
587 // Have chance to connect the platform default console,
588 // the platform default console is the minimue device group
589 // the platform should support
590 //
591 for (Index = 0; PlatformConsole[Index].DevicePath != NULL; ++Index) {
592 //
593 // Update the console variable with the connect type
594 //
595 if ((PlatformConsole[Index].ConnectType & CONSOLE_IN) == CONSOLE_IN) {
596 BdsLibUpdateConsoleVariable (VarConsoleInp, PlatformConsole[Index].DevicePath, NULL);
597 }
598 if ((PlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) {
599 BdsLibUpdateConsoleVariable (VarConsoleOut, PlatformConsole[Index].DevicePath, NULL);
600 }
601 if ((PlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) {
602 BdsLibUpdateConsoleVariable (VarErrorOut, PlatformConsole[Index].DevicePath, NULL);
603 }
604 }
605 } else {
606 //
607 // Only detect VGA device and add them to ConOut
608 //
609 DetectAndPreparePlatformPciDevicePath (TRUE);
610 }
611
612 //
613 // Connect the all the default console with current cosole variable
614 //
615 Status = BdsLibConnectAllDefaultConsoles ();
616 if (EFI_ERROR (Status)) {
617 return Status;
618 }
619
620 return EFI_SUCCESS;
621 }
622
623
624 VOID
625 PciInitialization (
626 )
627 {
628 //
629 // Bus 0, Device 0, Function 0 - Host to PCI Bridge
630 //
631 PciWrite8 (PCI_LIB_ADDRESS (0, 0, 0, 0x3c), 0x00);
632
633 //
634 // Bus 0, Device 1, Function 0 - PCI to ISA Bridge
635 //
636 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x3c), 0x00);
637 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x60), 0x0b);
638 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x61), 0x09);
639 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x62), 0x0b);
640 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x63), 0x09);
641
642 //
643 // Bus 0, Device 1, Function 1 - IDE Controller
644 //
645 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 1, 0x3c), 0x00);
646 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 1, 0x0d), 0x40);
647
648 //
649 // Bus 0, Device 1, Function 3 - Power Managment Controller
650 //
651 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 3, 0x3c), 0x0b);
652 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 3, 0x3d), 0x01);
653
654 //
655 // Bus 0, Device 2, Function 0 - Video Controller
656 //
657 PciWrite8 (PCI_LIB_ADDRESS (0, 2, 0, 0x3c), 0x00);
658
659 //
660 // Bus 0, Device 3, Function 0 - Network Controller
661 //
662 PciWrite8 (PCI_LIB_ADDRESS (0, 3, 0, 0x3c), 0x0b);
663 PciWrite8 (PCI_LIB_ADDRESS (0, 3, 0, 0x3d), 0x01);
664
665 //
666 // Bus 0, Device 4, Function 0 - RAM Memory
667 //
668 PciWrite8 (PCI_LIB_ADDRESS (0, 4, 0, 0x3c), 0x09);
669 PciWrite8 (PCI_LIB_ADDRESS (0, 4, 0, 0x3d), 0x01);
670 }
671
672
673 VOID
674 PlatformBdsConnectSequence (
675 VOID
676 )
677 /*++
678
679 Routine Description:
680
681 Connect with predeined platform connect sequence,
682 the OEM/IBV can customize with their own connect sequence.
683
684 Arguments:
685
686 None.
687
688 Returns:
689
690 None.
691
692 --*/
693 {
694 UINTN Index;
695
696 DEBUG ((EFI_D_INFO, "PlatformBdsConnectSequence\n"));
697
698 Index = 0;
699
700 //
701 // Here we can get the customized platform connect sequence
702 // Notes: we can connect with new variable which record the
703 // last time boots connect device path sequence
704 //
705 while (gPlatformConnectSequence[Index] != NULL) {
706 //
707 // Build the platform boot option
708 //
709 BdsLibConnectDevicePath (gPlatformConnectSequence[Index]);
710 Index++;
711 }
712
713 //
714 // Just use the simple policy to connect all devices
715 //
716 BdsLibConnectAll ();
717
718 PciInitialization ();
719
720 //
721 // Clear the logo after all devices are connected.
722 //
723 gST->ConOut->ClearScreen (gST->ConOut);
724 }
725
726 VOID
727 PlatformBdsGetDriverOption (
728 IN OUT LIST_ENTRY *BdsDriverLists
729 )
730 /*++
731
732 Routine Description:
733
734 Load the predefined driver option, OEM/IBV can customize this
735 to load their own drivers
736
737 Arguments:
738
739 BdsDriverLists - The header of the driver option link list.
740
741 Returns:
742
743 None.
744
745 --*/
746 {
747 DEBUG ((EFI_D_INFO, "PlatformBdsGetDriverOption\n"));
748 return;
749 }
750
751 VOID
752 PlatformBdsDiagnostics (
753 IN EXTENDMEM_COVERAGE_LEVEL MemoryTestLevel,
754 IN BOOLEAN QuietBoot,
755 IN BASEM_MEMORY_TEST BaseMemoryTest
756 )
757 /*++
758
759 Routine Description:
760
761 Perform the platform diagnostic, such like test memory. OEM/IBV also
762 can customize this fuction to support specific platform diagnostic.
763
764 Arguments:
765
766 MemoryTestLevel - The memory test intensive level
767
768 QuietBoot - Indicate if need to enable the quiet boot
769
770 BaseMemoryTest - A pointer to BaseMemoryTest()
771
772 Returns:
773
774 None.
775
776 --*/
777 {
778 EFI_STATUS Status;
779
780 DEBUG ((EFI_D_INFO, "PlatformBdsDiagnostics\n"));
781
782 //
783 // Here we can decide if we need to show
784 // the diagnostics screen
785 // Notes: this quiet boot code should be remove
786 // from the graphic lib
787 //
788 if (QuietBoot) {
789 EnableQuietBoot (PcdGetPtr(PcdLogoFile));
790 //
791 // Perform system diagnostic
792 //
793 Status = BaseMemoryTest (MemoryTestLevel);
794 if (EFI_ERROR (Status)) {
795 DisableQuietBoot ();
796 }
797
798 return ;
799 }
800 //
801 // Perform system diagnostic
802 //
803 Status = BaseMemoryTest (MemoryTestLevel);
804 }
805
806
807 VOID
808 EFIAPI
809 PlatformBdsPolicyBehavior (
810 IN OUT LIST_ENTRY *DriverOptionList,
811 IN OUT LIST_ENTRY *BootOptionList,
812 IN PROCESS_CAPSULES ProcessCapsules,
813 IN BASEM_MEMORY_TEST BaseMemoryTest
814 )
815 /*++
816
817 Routine Description:
818
819 The function will excute with as the platform policy, current policy
820 is driven by boot mode. IBV/OEM can customize this code for their specific
821 policy action.
822
823 Arguments:
824
825 DriverOptionList - The header of the driver option link list
826
827 BootOptionList - The header of the boot option link list
828
829 ProcessCapsules - A pointer to ProcessCapsules()
830
831 BaseMemoryTest - A pointer to BaseMemoryTest()
832
833 Returns:
834
835 None.
836
837 --*/
838 {
839 EFI_STATUS Status;
840 UINT16 Timeout;
841 EFI_EVENT UserInputDurationTime;
842 LIST_ENTRY *Link;
843 BDS_COMMON_OPTION *BootOption;
844 UINTN Index;
845 EFI_INPUT_KEY Key;
846 EFI_TPL OldTpl;
847 EFI_BOOT_MODE BootMode;
848
849 DEBUG ((EFI_D_INFO, "PlatformBdsPolicyBehavior\n"));
850
851 //
852 // Init the time out value
853 //
854 Timeout = PcdGet16 (PcdPlatformBootTimeOut);
855
856 //
857 // Load the driver option as the driver option list
858 //
859 PlatformBdsGetDriverOption (DriverOptionList);
860
861 //
862 // Get current Boot Mode
863 //
864 Status = BdsLibGetBootMode (&BootMode);
865 DEBUG ((EFI_D_ERROR, "Boot Mode:%x\n", BootMode));
866
867 //
868 // Go the different platform policy with different boot mode
869 // Notes: this part code can be change with the table policy
870 //
871 ASSERT (BootMode == BOOT_WITH_FULL_CONFIGURATION);
872 //
873 // Connect platform console
874 //
875 Status = PlatformBdsConnectConsole (gPlatformConsole);
876 if (EFI_ERROR (Status)) {
877 //
878 // Here OEM/IBV can customize with defined action
879 //
880 PlatformBdsNoConsoleAction ();
881 }
882 //
883 // Create a 300ms duration event to ensure user has enough input time to enter Setup
884 //
885 Status = gBS->CreateEvent (
886 EVT_TIMER,
887 0,
888 NULL,
889 NULL,
890 &UserInputDurationTime
891 );
892 ASSERT (Status == EFI_SUCCESS);
893 Status = gBS->SetTimer (UserInputDurationTime, TimerRelative, 3000000);
894 ASSERT (Status == EFI_SUCCESS);
895 //
896 // Memory test and Logo show
897 //
898 PlatformBdsDiagnostics (IGNORE, TRUE, BaseMemoryTest);
899
900 //
901 // Perform some platform specific connect sequence
902 //
903 PlatformBdsConnectSequence ();
904
905 //
906 // Give one chance to enter the setup if we
907 // have the time out
908 //
909 if (Timeout != 0) {
910 //PlatformBdsEnterFrontPage (Timeout, FALSE);
911 }
912
913 DEBUG ((EFI_D_INFO, "BdsLibConnectAll\n"));
914 BdsLibConnectAll ();
915 BdsLibEnumerateAllBootOption (BootOptionList);
916
917 //
918 // Please uncomment above ConnectAll and EnumerateAll code and remove following first boot
919 // checking code in real production tip.
920 //
921 // In BOOT_WITH_FULL_CONFIGURATION boot mode, should always connect every device
922 // and do enumerate all the default boot options. But in development system board, the boot mode
923 // cannot be BOOT_ASSUMING_NO_CONFIGURATION_CHANGES because the machine box
924 // is always open. So the following code only do the ConnectAll and EnumerateAll at first boot.
925 //
926 Status = BdsLibBuildOptionFromVar (BootOptionList, L"BootOrder");
927 if (EFI_ERROR(Status)) {
928 //
929 // If cannot find "BootOrder" variable, it may be first boot.
930 // Try to connect all devices and enumerate all boot options here.
931 //
932 BdsLibConnectAll ();
933 BdsLibEnumerateAllBootOption (BootOptionList);
934 }
935
936 //
937 // To give the User a chance to enter Setup here, if user set TimeOut is 0.
938 // BDS should still give user a chance to enter Setup
939 //
940 // Connect first boot option, and then check user input before exit
941 //
942 for (Link = BootOptionList->ForwardLink; Link != BootOptionList;Link = Link->ForwardLink) {
943 BootOption = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);
944 if (!IS_LOAD_OPTION_TYPE (BootOption->Attribute, LOAD_OPTION_ACTIVE)) {
945 //
946 // skip the header of the link list, becuase it has no boot option
947 //
948 continue;
949 } else {
950 //
951 // Make sure the boot option device path connected, but ignore the BBS device path
952 //
953 if (DevicePathType (BootOption->DevicePath) != BBS_DEVICE_PATH) {
954 BdsLibConnectDevicePath (BootOption->DevicePath);
955 }
956 break;
957 }
958 }
959
960 //
961 // Check whether the user input after the duration time has expired
962 //
963 OldTpl = EfiGetCurrentTpl();
964 gBS->RestoreTPL (TPL_APPLICATION);
965 gBS->WaitForEvent (1, &UserInputDurationTime, &Index);
966 gBS->CloseEvent (UserInputDurationTime);
967 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
968 gBS->RaiseTPL (OldTpl);
969
970 if (!EFI_ERROR (Status)) {
971 //
972 // Enter Setup if user input
973 //
974 Timeout = 0xffff;
975 PlatformBdsEnterFrontPage (Timeout, FALSE);
976 }
977
978 return ;
979 }
980
981 VOID
982 EFIAPI
983 PlatformBdsBootSuccess (
984 IN BDS_COMMON_OPTION *Option
985 )
986 /*++
987
988 Routine Description:
989
990 Hook point after a boot attempt succeeds. We don't expect a boot option to
991 return, so the EFI 1.0 specification defines that you will default to an
992 interactive mode and stop processing the BootOrder list in this case. This
993 is alos a platform implementation and can be customized by IBV/OEM.
994
995 Arguments:
996
997 Option - Pointer to Boot Option that succeeded to boot.
998
999 Returns:
1000
1001 None.
1002
1003 --*/
1004 {
1005 CHAR16 *TmpStr;
1006
1007 DEBUG ((EFI_D_INFO, "PlatformBdsBootSuccess\n"));
1008 //
1009 // If Boot returned with EFI_SUCCESS and there is not in the boot device
1010 // select loop then we need to pop up a UI and wait for user input.
1011 //
1012 TmpStr = Option->StatusString;
1013 if (TmpStr != NULL) {
1014 BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL);
1015 FreePool (TmpStr);
1016 }
1017 }
1018
1019 VOID
1020 EFIAPI
1021 PlatformBdsBootFail (
1022 IN BDS_COMMON_OPTION *Option,
1023 IN EFI_STATUS Status,
1024 IN CHAR16 *ExitData,
1025 IN UINTN ExitDataSize
1026 )
1027 /*++
1028
1029 Routine Description:
1030
1031 Hook point after a boot attempt fails.
1032
1033 Arguments:
1034
1035 Option - Pointer to Boot Option that failed to boot.
1036
1037 Status - Status returned from failed boot.
1038
1039 ExitData - Exit data returned from failed boot.
1040
1041 ExitDataSize - Exit data size returned from failed boot.
1042
1043 Returns:
1044
1045 None.
1046
1047 --*/
1048 {
1049 CHAR16 *TmpStr;
1050
1051 DEBUG ((EFI_D_INFO, "PlatformBdsBootFail\n"));
1052
1053 //
1054 // If Boot returned with failed status then we need to pop up a UI and wait
1055 // for user input.
1056 //
1057 TmpStr = Option->StatusString;
1058 if (TmpStr != NULL) {
1059 BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL);
1060 FreePool (TmpStr);
1061 }
1062 }
1063
1064 EFI_STATUS
1065 PlatformBdsNoConsoleAction (
1066 VOID
1067 )
1068 /*++
1069
1070 Routine Description:
1071
1072 This function is remained for IBV/OEM to do some platform action,
1073 if there no console device can be connected.
1074
1075 Arguments:
1076
1077 None.
1078
1079 Returns:
1080
1081 EFI_SUCCESS - Direct return success now.
1082
1083 --*/
1084 {
1085 DEBUG ((EFI_D_INFO, "PlatformBdsNoConsoleAction\n"));
1086 return EFI_SUCCESS;
1087 }
1088
1089 VOID
1090 EFIAPI
1091 PlatformBdsLockNonUpdatableFlash (
1092 VOID
1093 )
1094 {
1095 DEBUG ((EFI_D_INFO, "PlatformBdsLockNonUpdatableFlash\n"));
1096 return;
1097 }
1098
1099
1100 /**
1101 This notification function is invoked when an instance of the
1102 EFI_DEVICE_PATH_PROTOCOL is produced.
1103
1104 @param Event The event that occured
1105 @param Context For EFI compatiblity. Not used.
1106
1107 **/
1108 VOID
1109 EFIAPI
1110 NotifyDevPath (
1111 IN EFI_EVENT Event,
1112 IN VOID *Context
1113 )
1114 {
1115 EFI_HANDLE Handle;
1116 EFI_STATUS Status;
1117 UINTN BufferSize;
1118 EFI_DEVICE_PATH_PROTOCOL *DevPathNode;
1119 ATAPI_DEVICE_PATH *Atapi;
1120
1121 //
1122 // Examine all new handles
1123 //
1124 for (;;) {
1125 //
1126 // Get the next handle
1127 //
1128 BufferSize = sizeof (Handle);
1129 Status = gBS->LocateHandle (
1130 ByRegisterNotify,
1131 NULL,
1132 mEfiDevPathNotifyReg,
1133 &BufferSize,
1134 &Handle
1135 );
1136
1137 //
1138 // If not found, we're done
1139 //
1140 if (EFI_NOT_FOUND == Status) {
1141 break;
1142 }
1143
1144 if (EFI_ERROR (Status)) {
1145 continue;
1146 }
1147
1148 //
1149 // Get the DevicePath protocol on that handle
1150 //
1151 Status = gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **)&DevPathNode);
1152 ASSERT_EFI_ERROR (Status);
1153
1154 while (!IsDevicePathEnd (DevPathNode)) {
1155 //
1156 // Find the handler to dump this device path node
1157 //
1158 if (
1159 (DevicePathType(DevPathNode) == MESSAGING_DEVICE_PATH) &&
1160 (DevicePathSubType(DevPathNode) == MSG_ATAPI_DP)
1161 ) {
1162 Atapi = (ATAPI_DEVICE_PATH*) DevPathNode;
1163 PciOr16 (
1164 PCI_LIB_ADDRESS (
1165 0,
1166 1,
1167 1,
1168 (Atapi->PrimarySecondary == 1) ? 0x42: 0x40
1169 ),
1170 BIT15
1171 );
1172 }
1173
1174 //
1175 // Next device path node
1176 //
1177 DevPathNode = NextDevicePathNode (DevPathNode);
1178 }
1179 }
1180
1181 return;
1182 }
1183
1184
1185 VOID
1186 InstallDevicePathCallback (
1187 VOID
1188 )
1189 {
1190 DEBUG ((EFI_D_INFO, "Registered NotifyDevPath Event\n"));
1191 mEfiDevPathEvent = EfiCreateProtocolNotifyEvent (
1192 &gEfiDevicePathProtocolGuid,
1193 TPL_CALLBACK,
1194 NotifyDevPath,
1195 NULL,
1196 &mEfiDevPathNotifyReg
1197 );
1198 }
1199
1200 /**
1201 Lock the ConsoleIn device in system table. All key
1202 presses will be ignored until the Password is typed in. The only way to
1203 disable the password is to type it in to a ConIn device.
1204
1205 @param Password Password used to lock ConIn device.
1206
1207 @retval EFI_SUCCESS lock the Console In Spliter virtual handle successfully.
1208 @retval EFI_UNSUPPORTED Password not found
1209
1210 **/
1211 EFI_STATUS
1212 EFIAPI
1213 LockKeyboards (
1214 IN CHAR16 *Password
1215 )
1216 {
1217 return EFI_UNSUPPORTED;
1218 }
1219
1220
1221 STATIC
1222 VOID
1223 LoadVideoRom (
1224 VOID
1225 )
1226 {
1227 PCI_DATA_STRUCTURE *Pcir;
1228 UINTN RomSize;
1229
1230 //
1231 // The virtual machines sometimes load the video rom image
1232 // directly at the legacy video BIOS location of C000:0000,
1233 // and do not implement the PCI expansion ROM feature.
1234 //
1235 Pcir = (PCI_DATA_STRUCTURE *) (UINTN) 0xc0000;
1236 RomSize = Pcir->ImageLength * 512;
1237 PciRomLoadEfiDriversFromRomImage (0xc0000, RomSize);
1238 }
1239
1240
1241 STATIC
1242 EFI_STATUS
1243 PciRomLoadEfiDriversFromRomImage (
1244 IN EFI_PHYSICAL_ADDRESS Rom,
1245 IN UINTN RomSize
1246 )
1247 {
1248 CHAR16 *FileName;
1249 EFI_PCI_EXPANSION_ROM_HEADER *EfiRomHeader;
1250 PCI_DATA_STRUCTURE *Pcir;
1251 UINTN ImageIndex;
1252 UINTN RomOffset;
1253 UINT32 ImageSize;
1254 UINT16 ImageOffset;
1255 EFI_HANDLE ImageHandle;
1256 EFI_STATUS Status;
1257 EFI_STATUS retStatus;
1258 EFI_DEVICE_PATH_PROTOCOL *FilePath;
1259 BOOLEAN SkipImage;
1260 UINT32 DestinationSize;
1261 UINT32 ScratchSize;
1262 UINT8 *Scratch;
1263 VOID *ImageBuffer;
1264 VOID *DecompressedImageBuffer;
1265 UINT32 ImageLength;
1266 EFI_DECOMPRESS_PROTOCOL *Decompress;
1267
1268 FileName = L"PciRomInMemory";
1269
1270 //FileName = L"PciRom Addr=0000000000000000";
1271 //HexToString (&FileName[12], Rom, 16);
1272
1273 ImageIndex = 0;
1274 retStatus = EFI_NOT_FOUND;
1275 RomOffset = (UINTN) Rom;
1276
1277 do {
1278
1279 EfiRomHeader = (EFI_PCI_EXPANSION_ROM_HEADER *) (UINTN) RomOffset;
1280
1281 if (EfiRomHeader->Signature != 0xaa55) {
1282 return retStatus;
1283 }
1284
1285 Pcir = (PCI_DATA_STRUCTURE *) (UINTN) (RomOffset + EfiRomHeader->PcirOffset);
1286 ImageSize = Pcir->ImageLength * 512;
1287
1288 if ((Pcir->CodeType == PCI_CODE_TYPE_EFI_IMAGE) &&
1289 (EfiRomHeader->EfiSignature == EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE) ) {
1290
1291 if ((EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) ||
1292 (EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) ) {
1293
1294 ImageOffset = EfiRomHeader->EfiImageHeaderOffset;
1295 ImageSize = EfiRomHeader->InitializationSize * 512;
1296
1297 ImageBuffer = (VOID *) (UINTN) (RomOffset + ImageOffset);
1298 ImageLength = ImageSize - ImageOffset;
1299 DecompressedImageBuffer = NULL;
1300
1301 //
1302 // decompress here if needed
1303 //
1304 SkipImage = FALSE;
1305 if (EfiRomHeader->CompressionType > EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {
1306 SkipImage = TRUE;
1307 }
1308
1309 if (EfiRomHeader->CompressionType == EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {
1310 Status = gBS->LocateProtocol (&gEfiDecompressProtocolGuid, NULL, (VOID **) &Decompress);
1311 if (EFI_ERROR (Status)) {
1312 SkipImage = TRUE;
1313 } else {
1314 SkipImage = TRUE;
1315 Status = Decompress->GetInfo (
1316 Decompress,
1317 ImageBuffer,
1318 ImageLength,
1319 &DestinationSize,
1320 &ScratchSize
1321 );
1322 if (!EFI_ERROR (Status)) {
1323 DecompressedImageBuffer = NULL;
1324 DecompressedImageBuffer = AllocatePool (DestinationSize);
1325 if (DecompressedImageBuffer != NULL) {
1326 Scratch = AllocatePool (ScratchSize);
1327 if (Scratch != NULL) {
1328 Status = Decompress->Decompress (
1329 Decompress,
1330 ImageBuffer,
1331 ImageLength,
1332 DecompressedImageBuffer,
1333 DestinationSize,
1334 Scratch,
1335 ScratchSize
1336 );
1337 if (!EFI_ERROR (Status)) {
1338 ImageBuffer = DecompressedImageBuffer;
1339 ImageLength = DestinationSize;
1340 SkipImage = FALSE;
1341 }
1342
1343 gBS->FreePool (Scratch);
1344 }
1345 }
1346 }
1347 }
1348 }
1349
1350 if (!SkipImage) {
1351
1352 //
1353 // load image and start image
1354 //
1355
1356 FilePath = FileDevicePath (NULL, FileName);
1357
1358 Status = gBS->LoadImage (
1359 FALSE,
1360 gImageHandle,
1361 FilePath,
1362 ImageBuffer,
1363 ImageLength,
1364 &ImageHandle
1365 );
1366 if (!EFI_ERROR (Status)) {
1367 Status = gBS->StartImage (ImageHandle, NULL, NULL);
1368 if (!EFI_ERROR (Status)) {
1369 retStatus = Status;
1370 }
1371 }
1372 if (FilePath != NULL) {
1373 gBS->FreePool (FilePath);
1374 }
1375 }
1376
1377 if (DecompressedImageBuffer != NULL) {
1378 gBS->FreePool (DecompressedImageBuffer);
1379 }
1380
1381 }
1382 }
1383
1384 RomOffset = RomOffset + ImageSize;
1385 ImageIndex++;
1386 } while (((Pcir->Indicator & 0x80) == 0x00) && ((RomOffset - (UINTN) Rom) < RomSize));
1387
1388 return retStatus;
1389 }
1390
1391