]> git.proxmox.com Git - mirror_edk2.git/blob - CorebootPayloadPkg/Library/PlatformBdsLib/BdsPlatform.c
44144853068a88c2141e8bf9f4ee9f138b4a713e
[mirror_edk2.git] / CorebootPayloadPkg / Library / PlatformBdsLib / BdsPlatform.c
1 /** @file
2 This file include all platform action which can be customized by IBV/OEM.
3
4 Copyright (c) 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
17 //
18 // Global data
19 //
20 BOOLEAN mDetectVgaOnly;
21
22
23 //
24 // Type definitions
25 //
26
27 typedef
28 EFI_STATUS
29 (EFIAPI *PROTOCOL_INSTANCE_CALLBACK)(
30 IN EFI_HANDLE Handle,
31 IN VOID *Instance,
32 IN VOID *Context
33 );
34
35 /**
36 @param[in] Handle - Handle of PCI device instance
37 @param[in] PciIo - PCI IO protocol instance
38 @param[in] Pci - PCI Header register block
39 **/
40 typedef
41 EFI_STATUS
42 (EFIAPI *VISIT_PCI_INSTANCE_CALLBACK)(
43 IN EFI_HANDLE Handle,
44 IN EFI_PCI_IO_PROTOCOL *PciIo,
45 IN PCI_TYPE00 *Pci
46 );
47
48
49 //
50 // Function prototypes
51 //
52
53 EFI_STATUS
54 VisitAllInstancesOfProtocol (
55 IN EFI_GUID *Id,
56 IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction,
57 IN VOID *Context
58 );
59
60 EFI_STATUS
61 VisitAllPciInstancesOfProtocol (
62 IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
63 );
64
65
66 //
67 // BDS Platform Functions
68 //
69
70 /**
71 Platform Bds init. Include the platform firmware vendor, revision
72 and so crc check.
73
74 **/
75 VOID
76 EFIAPI
77 PlatformBdsInit (
78 VOID
79 )
80 {
81 }
82
83
84 EFI_STATUS
85 PrepareLpcBridgeDevicePath (
86 IN EFI_HANDLE DeviceHandle
87 )
88 /*++
89
90 Routine Description:
91
92 Add IsaKeyboard to ConIn,
93 add IsaSerial to ConOut, ConIn, ErrOut.
94 LPC Bridge: 06 01 00
95
96 Arguments:
97
98 DeviceHandle - Handle of PCIIO protocol.
99
100 Returns:
101
102 EFI_SUCCESS - LPC bridge is added to ConOut, ConIn, and ErrOut.
103 EFI_STATUS - No LPC bridge is added.
104
105 --*/
106 {
107 EFI_STATUS Status;
108 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
109 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
110 CHAR16 *DevPathStr;
111
112 DevicePath = NULL;
113 Status = gBS->HandleProtocol (
114 DeviceHandle,
115 &gEfiDevicePathProtocolGuid,
116 (VOID*)&DevicePath
117 );
118 if (EFI_ERROR (Status)) {
119 return Status;
120 }
121 TempDevicePath = DevicePath;
122
123 //
124 // Register COM1
125 //
126 DevicePath = AppendDevicePathNode ((EFI_DEVICE_PATH_PROTOCOL *)NULL, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceVendorNode);
127 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);
128 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);
129
130 //
131 // Print Device Path
132 //
133 DevPathStr = DevicePathToStr(DevicePath);
134 DEBUG((
135 EFI_D_INFO,
136 "BdsPlatform.c+%d: COM%d DevPath: %s\n",
137 __LINE__,
138 gPnp16550ComPortDeviceNode.UID + 1,
139 DevPathStr
140 ));
141 FreePool(DevPathStr);
142
143 BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);
144 BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL);
145 BdsLibUpdateConsoleVariable (VarErrorOut, DevicePath, NULL);
146
147 return EFI_SUCCESS;
148 }
149
150 EFI_STATUS
151 GetGopDevicePath (
152 IN EFI_DEVICE_PATH_PROTOCOL *PciDevicePath,
153 OUT EFI_DEVICE_PATH_PROTOCOL **GopDevicePath
154 )
155 {
156 UINTN Index;
157 EFI_STATUS Status;
158 EFI_HANDLE PciDeviceHandle;
159 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
160 EFI_DEVICE_PATH_PROTOCOL *TempPciDevicePath;
161 UINTN GopHandleCount;
162 EFI_HANDLE *GopHandleBuffer;
163
164 if (PciDevicePath == NULL || GopDevicePath == NULL) {
165 return EFI_INVALID_PARAMETER;
166 }
167
168 //
169 // Initialize the GopDevicePath to be PciDevicePath
170 //
171 *GopDevicePath = PciDevicePath;
172 TempPciDevicePath = PciDevicePath;
173
174 Status = gBS->LocateDevicePath (
175 &gEfiDevicePathProtocolGuid,
176 &TempPciDevicePath,
177 &PciDeviceHandle
178 );
179 if (EFI_ERROR (Status)) {
180 return Status;
181 }
182
183 //
184 // Try to connect this handle, so that GOP dirver could start on this
185 // device and create child handles with GraphicsOutput Protocol installed
186 // on them, then we get device paths of these child handles and select
187 // them as possible console device.
188 //
189 #if 0
190 gBS->ConnectController (PciDeviceHandle, NULL, NULL, FALSE);
191 #else
192 {
193 ACPI_ADR_DEVICE_PATH AcpiAdr;
194 EFI_DEVICE_PATH_PROTOCOL *MyDevicePath = NULL;
195
196 AcpiAdr.Header.Type = ACPI_DEVICE_PATH;
197 AcpiAdr.Header.SubType = ACPI_ADR_DP;
198 //AcpiAdr.ADR= ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA, 6, 0); //on bayleybay, CRT Device
199 AcpiAdr.ADR= ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_INTERNAL_DIGITAL, 8, 0); ; // on rambi, eDP C
200
201 SetDevicePathNodeLength (&AcpiAdr.Header, sizeof (ACPI_ADR_DEVICE_PATH));
202
203 MyDevicePath = AppendDevicePathNode(MyDevicePath, (EFI_DEVICE_PATH_PROTOCOL*)&AcpiAdr);
204
205 gBS->ConnectController (PciDeviceHandle, NULL, MyDevicePath, FALSE);
206
207 FreePool(MyDevicePath);
208 }
209 #endif
210
211 Status = gBS->LocateHandleBuffer (
212 ByProtocol,
213 &gEfiGraphicsOutputProtocolGuid,
214 NULL,
215 &GopHandleCount,
216 &GopHandleBuffer
217 );
218 if (!EFI_ERROR (Status)) {
219 //
220 // Add all the child handles as possible Console Device
221 //
222 for (Index = 0; Index < GopHandleCount; Index++) {
223 Status = gBS->HandleProtocol (GopHandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID*)&TempDevicePath);
224 if (EFI_ERROR (Status)) {
225 continue;
226 }
227 if (CompareMem (
228 PciDevicePath,
229 TempDevicePath,
230 GetDevicePathSize (PciDevicePath) - END_DEVICE_PATH_LENGTH
231 ) == 0) {
232 //
233 // In current implementation, we only enable one of the child handles
234 // as console device, i.e. sotre one of the child handle's device
235 // path to variable "ConOut"
236 // In futhure, we could select all child handles to be console device
237 //
238
239 *GopDevicePath = TempDevicePath;
240
241 //
242 // Delete the PCI device's path that added by GetPlugInPciVgaDevicePath()
243 // Add the integrity GOP device path.
244 //
245 BdsLibUpdateConsoleVariable (VarConsoleOutDev, NULL, PciDevicePath);
246 BdsLibUpdateConsoleVariable (VarConsoleOutDev, TempDevicePath, NULL);
247 }
248 }
249 gBS->FreePool (GopHandleBuffer);
250 }
251
252 return EFI_SUCCESS;
253 }
254
255 EFI_STATUS
256 PreparePciVgaDevicePath (
257 IN EFI_HANDLE DeviceHandle
258 )
259 /*++
260
261 Routine Description:
262
263 Add PCI VGA to ConOut.
264 PCI VGA: 03 00 00
265
266 Arguments:
267
268 DeviceHandle - Handle of PCIIO protocol.
269
270 Returns:
271
272 EFI_SUCCESS - PCI VGA is added to ConOut.
273 EFI_STATUS - No PCI VGA device is added.
274
275 --*/
276 {
277 EFI_STATUS Status;
278 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
279 EFI_DEVICE_PATH_PROTOCOL *GopDevicePath;
280
281 DevicePath = NULL;
282 Status = gBS->HandleProtocol (
283 DeviceHandle,
284 &gEfiDevicePathProtocolGuid,
285 (VOID*)&DevicePath
286 );
287 if (EFI_ERROR (Status)) {
288 return Status;
289 }
290
291 GetGopDevicePath (DevicePath, &GopDevicePath);
292 DevicePath = GopDevicePath;
293
294 BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);
295
296 return EFI_SUCCESS;
297 }
298
299 EFI_STATUS
300 PreparePciSerialDevicePath (
301 IN EFI_HANDLE DeviceHandle
302 )
303 /*++
304
305 Routine Description:
306
307 Add PCI Serial to ConOut, ConIn, ErrOut.
308 PCI Serial: 07 00 02
309
310 Arguments:
311
312 DeviceHandle - Handle of PCIIO protocol.
313
314 Returns:
315
316 EFI_SUCCESS - PCI Serial is added to ConOut, ConIn, and ErrOut.
317 EFI_STATUS - No PCI Serial device is added.
318
319 --*/
320 {
321 EFI_STATUS Status;
322 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
323
324 DevicePath = NULL;
325 Status = gBS->HandleProtocol (
326 DeviceHandle,
327 &gEfiDevicePathProtocolGuid,
328 (VOID*)&DevicePath
329 );
330 if (EFI_ERROR (Status)) {
331 return Status;
332 }
333
334 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);
335 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);
336
337 BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);
338 BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL);
339 BdsLibUpdateConsoleVariable (VarErrorOut, DevicePath, NULL);
340
341 return EFI_SUCCESS;
342 }
343
344 EFI_STATUS
345 VisitAllInstancesOfProtocol (
346 IN EFI_GUID *Id,
347 IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction,
348 IN VOID *Context
349 )
350 {
351 EFI_STATUS Status;
352 UINTN HandleCount;
353 EFI_HANDLE *HandleBuffer;
354 UINTN Index;
355 VOID *Instance;
356
357 //
358 // Start to check all the PciIo to find all possible device
359 //
360 HandleCount = 0;
361 HandleBuffer = NULL;
362 Status = gBS->LocateHandleBuffer (
363 ByProtocol,
364 Id,
365 NULL,
366 &HandleCount,
367 &HandleBuffer
368 );
369 if (EFI_ERROR (Status)) {
370 return Status;
371 }
372
373 for (Index = 0; Index < HandleCount; Index++) {
374 Status = gBS->HandleProtocol (HandleBuffer[Index], Id, &Instance);
375 if (EFI_ERROR (Status)) {
376 continue;
377 }
378
379 Status = (*CallBackFunction) (
380 HandleBuffer[Index],
381 Instance,
382 Context
383 );
384 }
385
386 gBS->FreePool (HandleBuffer);
387
388 return EFI_SUCCESS;
389 }
390
391
392 EFI_STATUS
393 EFIAPI
394 VisitingAPciInstance (
395 IN EFI_HANDLE Handle,
396 IN VOID *Instance,
397 IN VOID *Context
398 )
399 {
400 EFI_STATUS Status;
401 EFI_PCI_IO_PROTOCOL *PciIo;
402 PCI_TYPE00 Pci;
403
404 PciIo = (EFI_PCI_IO_PROTOCOL*) Instance;
405
406 //
407 // Check for all PCI device
408 //
409 Status = PciIo->Pci.Read (
410 PciIo,
411 EfiPciIoWidthUint32,
412 0,
413 sizeof (Pci) / sizeof (UINT32),
414 &Pci
415 );
416 if (EFI_ERROR (Status)) {
417 return Status;
418 }
419
420 return (*(VISIT_PCI_INSTANCE_CALLBACK)(UINTN) Context) (
421 Handle,
422 PciIo,
423 &Pci
424 );
425
426 }
427
428
429
430 EFI_STATUS
431 VisitAllPciInstances (
432 IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
433 )
434 {
435 return VisitAllInstancesOfProtocol (
436 &gEfiPciIoProtocolGuid,
437 VisitingAPciInstance,
438 (VOID*)(UINTN) CallBackFunction
439 );
440 }
441
442
443 /**
444 Do platform specific PCI Device check and add them to
445 ConOut, ConIn, ErrOut.
446
447 @param[in] Handle - Handle of PCI device instance
448 @param[in] PciIo - PCI IO protocol instance
449 @param[in] Pci - PCI Header register block
450
451 @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.
452 @retval EFI_STATUS - PCI Device check or Console variable update fail.
453
454 **/
455 EFI_STATUS
456 EFIAPI
457 DetectAndPreparePlatformPciDevicePath (
458 IN EFI_HANDLE Handle,
459 IN EFI_PCI_IO_PROTOCOL *PciIo,
460 IN PCI_TYPE00 *Pci
461 )
462 {
463 EFI_STATUS Status;
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 (!mDetectVgaOnly) {
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 )
481 ) {
482 //
483 // Add IsaKeyboard to ConIn,
484 // add IsaSerial to ConOut, ConIn, ErrOut
485 //
486 DEBUG ((EFI_D_INFO, "Found LPC Bridge device\n"));
487 PrepareLpcBridgeDevicePath (Handle);
488 return EFI_SUCCESS;
489 }
490 //
491 // Here we decide which Serial device to enable in PCI bus
492 //
493 if (IS_PCI_16550SERIAL (Pci)) {
494 //
495 // Add them to ConOut, ConIn, ErrOut.
496 //
497 DEBUG ((EFI_D_INFO, "Found PCI 16550 SERIAL device\n"));
498 PreparePciSerialDevicePath (Handle);
499 return EFI_SUCCESS;
500 }
501 }
502
503 //
504 // Here we decide which VGA device to enable in PCI bus
505 //
506 if (IS_PCI_VGA (Pci)) {
507 //
508 // Add them to ConOut.
509 //
510 DEBUG ((EFI_D_INFO, "Found PCI VGA device\n"));
511 PreparePciVgaDevicePath (Handle);
512 return EFI_SUCCESS;
513 }
514
515 return Status;
516 }
517
518
519 /**
520 Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
521
522 @param[in] DetectVgaOnly - Only detect VGA device if it's TRUE.
523
524 @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.
525 @retval EFI_STATUS - PCI Device check or Console variable update fail.
526
527 **/
528 EFI_STATUS
529 DetectAndPreparePlatformPciDevicePaths (
530 BOOLEAN DetectVgaOnly
531 )
532 {
533 mDetectVgaOnly = DetectVgaOnly;
534 return VisitAllPciInstances (DetectAndPreparePlatformPciDevicePath);
535 }
536
537 /**
538 Connect the predefined platform default console device. Always try to find
539 and enable the vga device if have.
540
541 @param PlatformConsole Predefined platform default console device array.
542
543 @retval EFI_SUCCESS Success connect at least one ConIn and ConOut
544 device, there must have one ConOut device is
545 active vga device.
546 @return Return the status of BdsLibConnectAllDefaultConsoles ()
547
548 **/
549 EFI_STATUS
550 PlatformBdsConnectConsole (
551 IN BDS_CONSOLE_CONNECT_ENTRY *PlatformConsole
552 )
553 {
554 EFI_STATUS Status;
555 UINTN Index;
556 EFI_DEVICE_PATH_PROTOCOL *VarConout;
557 EFI_DEVICE_PATH_PROTOCOL *VarConin;
558 UINTN DevicePathSize;
559
560 //
561 // Connect RootBridge
562 //
563 VarConout = BdsLibGetVariableAndSize (
564 VarConsoleOut,
565 &gEfiGlobalVariableGuid,
566 &DevicePathSize
567 );
568 VarConin = BdsLibGetVariableAndSize (
569 VarConsoleInp,
570 &gEfiGlobalVariableGuid,
571 &DevicePathSize
572 );
573
574 if (VarConout == NULL || VarConin == NULL) {
575 //
576 // Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
577 //
578 DetectAndPreparePlatformPciDevicePaths (FALSE);
579
580 //
581 // Have chance to connect the platform default console,
582 // the platform default console is the minimue device group
583 // the platform should support
584 //
585 for (Index = 0; PlatformConsole[Index].DevicePath != NULL; ++Index) {
586 //
587 // Update the console variable with the connect type
588 //
589 if ((PlatformConsole[Index].ConnectType & CONSOLE_IN) == CONSOLE_IN) {
590 BdsLibUpdateConsoleVariable (VarConsoleInp, PlatformConsole[Index].DevicePath, NULL);
591 }
592 if ((PlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) {
593 BdsLibUpdateConsoleVariable (VarConsoleOut, PlatformConsole[Index].DevicePath, NULL);
594 }
595 if ((PlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) {
596 BdsLibUpdateConsoleVariable (VarErrorOut, PlatformConsole[Index].DevicePath, NULL);
597 }
598 }
599 } else {
600 //
601 // Only detect VGA device and add them to ConOut
602 //
603 DetectAndPreparePlatformPciDevicePaths (TRUE);
604 }
605
606 //
607 // Connect the all the default console with current cosole variable
608 //
609 Status = BdsLibConnectAllDefaultConsoles ();
610 if (EFI_ERROR (Status)) {
611 return Status;
612 }
613
614 return EFI_SUCCESS;
615 }
616
617 /**
618 Connect with predefined platform connect sequence,
619 the OEM/IBV can customize with their own connect sequence.
620 **/
621 VOID
622 PlatformBdsConnectSequence (
623 VOID
624 )
625 {
626 UINTN Index;
627
628 DEBUG ((EFI_D_INFO, "PlatformBdsConnectSequence\n"));
629 Index = 0;
630
631 //
632 // Here we can get the customized platform connect sequence
633 // Notes: we can connect with new variable which record the
634 // last time boots connect device path sequence
635 //
636 while (gPlatformConnectSequence[Index] != NULL) {
637 //
638 // Build the platform boot option
639 //
640 BdsLibConnectDevicePath (gPlatformConnectSequence[Index]);
641 Index++;
642 }
643 }
644
645 /**
646 Load the predefined driver option, OEM/IBV can customize this
647 to load their own drivers
648
649 @param BdsDriverLists - The header of the driver option link list.
650
651 **/
652 VOID
653 PlatformBdsGetDriverOption (
654 IN OUT LIST_ENTRY *BdsDriverLists
655 )
656 {
657 UINTN Index;
658
659 Index = 0;
660
661 DEBUG ((EFI_D_INFO, "PlatformBdsGetDriverOption\n"));
662
663
664 //
665 // Here we can get the customized platform driver option
666 //
667 while (gPlatformDriverOption[Index] != NULL) {
668
669 //
670 // Build the platform boot option
671 //
672 BdsLibRegisterNewOption (BdsDriverLists, gPlatformDriverOption[Index], NULL, L"DriverOrder");
673 Index ++;
674 }
675 }
676
677 /**
678 Perform the platform diagnostic, such like test memory. OEM/IBV also
679 can customize this function to support specific platform diagnostic.
680
681 @param MemoryTestLevel The memory test intensive level
682 @param QuietBoot Indicate if need to enable the quiet boot
683 @param BaseMemoryTest A pointer to BdsMemoryTest()
684
685 **/
686 VOID
687 PlatformBdsDiagnostics (
688 IN EXTENDMEM_COVERAGE_LEVEL MemoryTestLevel,
689 IN BOOLEAN QuietBoot,
690 IN BASEM_MEMORY_TEST BaseMemoryTest
691 )
692 {
693 EFI_STATUS Status;
694
695 DEBUG ((EFI_D_INFO, "PlatformBdsDiagnostics\n"));
696 //
697 // Here we can decide if we need to show
698 // the diagnostics screen
699 // Notes: this quiet boot code should be remove
700 // from the graphic lib
701 //
702 if (QuietBoot) {
703 EnableQuietBoot (PcdGetPtr(PcdLogoFile));
704
705 //
706 // Perform system diagnostic
707 //
708 Status = BaseMemoryTest (MemoryTestLevel);
709 if (EFI_ERROR (Status)) {
710 DisableQuietBoot ();
711 }
712
713 return;
714 }
715
716 //
717 // Perform system diagnostic
718 //
719 Status = BaseMemoryTest (MemoryTestLevel);
720 }
721
722
723 /**
724 The function will connect root bridge
725
726 @return EFI_SUCCESS Connect RootBridge successfully.
727
728 **/
729 EFI_STATUS
730 ConnectRootBridge (
731 VOID
732 )
733 {
734 EFI_STATUS Status;
735 EFI_HANDLE RootHandle;
736
737 //
738 // Make all the PCI_IO protocols on PCI Seg 0 show up
739 //
740 BdsLibConnectDevicePath (gPlatformRootBridges[0]);
741
742 Status = gBS->LocateDevicePath (
743 &gEfiDevicePathProtocolGuid,
744 &gPlatformRootBridges[0],
745 &RootHandle
746 );
747 if (EFI_ERROR (Status)) {
748 return Status;
749 }
750
751 Status = gBS->ConnectController (RootHandle, NULL, NULL, FALSE);
752 if (EFI_ERROR (Status)) {
753 return Status;
754 }
755
756 return EFI_SUCCESS;
757 }
758
759 /**
760 The function will execute with as the platform policy, current policy
761 is driven by boot mode. IBV/OEM can customize this code for their specific
762 policy action.
763
764 @param DriverOptionList The header of the driver option link list
765 @param BootOptionList The header of the boot option link list
766 @param ProcessCapsules A pointer to ProcessCapsules()
767 @param BaseMemoryTest A pointer to BaseMemoryTest()
768
769 **/
770 VOID
771 EFIAPI
772 PlatformBdsPolicyBehavior (
773 IN LIST_ENTRY *DriverOptionList,
774 IN LIST_ENTRY *BootOptionList,
775 IN PROCESS_CAPSULES ProcessCapsules,
776 IN BASEM_MEMORY_TEST BaseMemoryTest
777 )
778 {
779 EFI_STATUS Status;
780 UINT16 Timeout;
781 EFI_EVENT UserInputDurationTime;
782 LIST_ENTRY *Link;
783 BDS_COMMON_OPTION *BootOption;
784 UINTN Index;
785 EFI_INPUT_KEY Key;
786 EFI_TPL OldTpl;
787 EFI_BOOT_MODE BootMode;
788
789 DEBUG ((EFI_D_INFO, "PlatformBdsPolicyBehavior\n"));
790
791 ConnectRootBridge ();
792
793 //
794 // Init the time out value
795 //
796 Timeout = PcdGet16 (PcdPlatformBootTimeOut);
797
798 //
799 // Load the driver option as the driver option list
800 //
801 PlatformBdsGetDriverOption (DriverOptionList);
802
803 //
804 // Get current Boot Mode
805 //
806 Status = BdsLibGetBootMode (&BootMode);
807 DEBUG ((EFI_D_ERROR, "Boot Mode:%x\n", BootMode));
808
809 //
810 // Go the different platform policy with different boot mode
811 // Notes: this part code can be change with the table policy
812 //
813 ASSERT (BootMode == BOOT_WITH_FULL_CONFIGURATION);
814 //
815 // Connect platform console
816 //
817 Status = PlatformBdsConnectConsole (gPlatformConsole);
818 if (EFI_ERROR (Status)) {
819 //
820 // Here OEM/IBV can customize with defined action
821 //
822 PlatformBdsNoConsoleAction ();
823 }
824 //
825 // Create a 300ms duration event to ensure user has enough input time to enter Setup
826 //
827 Status = gBS->CreateEvent (
828 EVT_TIMER,
829 0,
830 NULL,
831 NULL,
832 &UserInputDurationTime
833 );
834 ASSERT (Status == EFI_SUCCESS);
835 Status = gBS->SetTimer (UserInputDurationTime, TimerRelative, 3000000);
836 ASSERT (Status == EFI_SUCCESS);
837 //
838 // Memory test and Logo show
839 //
840 PlatformBdsDiagnostics (IGNORE, TRUE, BaseMemoryTest);
841
842 //
843 // Perform some platform specific connect sequence
844 //
845 PlatformBdsConnectSequence ();
846
847 //
848 // In BOOT_WITH_FULL_CONFIGURATION boot mode, should always connect every device
849 // and do enumerate all the default boot options. But in development system board, the boot mode
850 // cannot be BOOT_ASSUMING_NO_CONFIGURATION_CHANGES because the machine box
851 // is always open. So the following code only do the ConnectAll and EnumerateAll at first boot.
852 //
853 Status = BdsLibBuildOptionFromVar (BootOptionList, L"BootOrder");
854 if (EFI_ERROR(Status)) {
855 //
856 // If cannot find "BootOrder" variable, it may be first boot.
857 // Try to connect all devices and enumerate all boot options here.
858 //
859 BdsLibConnectAll ();
860 BdsLibEnumerateAllBootOption (BootOptionList);
861 }
862
863 //
864 // To give the User a chance to enter Setup here, if user set TimeOut is 0.
865 // BDS should still give user a chance to enter Setup
866 //
867 // Connect first boot option, and then check user input before exit
868 //
869 for (Link = BootOptionList->ForwardLink; Link != BootOptionList;Link = Link->ForwardLink) {
870 BootOption = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);
871 if (!IS_LOAD_OPTION_TYPE (BootOption->Attribute, LOAD_OPTION_ACTIVE)) {
872 //
873 // skip the header of the link list, becuase it has no boot option
874 //
875 continue;
876 } else {
877 //
878 // Make sure the boot option device path connected, but ignore the BBS device path
879 //
880 if (DevicePathType (BootOption->DevicePath) != BBS_DEVICE_PATH) {
881 BdsLibConnectDevicePath (BootOption->DevicePath);
882 }
883 break;
884 }
885 }
886
887 //
888 // Check whether the user input after the duration time has expired
889 //
890 OldTpl = EfiGetCurrentTpl();
891 gBS->RestoreTPL (TPL_APPLICATION);
892 gBS->WaitForEvent (1, &UserInputDurationTime, &Index);
893 gBS->CloseEvent (UserInputDurationTime);
894 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
895 gBS->RaiseTPL (OldTpl);
896
897 if (!EFI_ERROR (Status)) {
898 //
899 // Enter Setup if user input
900 //
901 Timeout = 0xffff;
902 PlatformBdsEnterFrontPage (Timeout, FALSE);
903 }
904 }
905
906 /**
907 Hook point after a boot attempt succeeds. We don't expect a boot option to
908 return, so the UEFI 2.0 specification defines that you will default to an
909 interactive mode and stop processing the BootOrder list in this case. This
910 is also a platform implementation and can be customized by IBV/OEM.
911
912 @param Option Pointer to Boot Option that succeeded to boot.
913
914 **/
915 VOID
916 EFIAPI
917 PlatformBdsBootSuccess (
918 IN BDS_COMMON_OPTION *Option
919 )
920 {
921 CHAR16 *TmpStr;
922 DEBUG ((EFI_D_INFO, "PlatformBdsBootSuccess\n"));
923
924 //
925 // If Boot returned with EFI_SUCCESS and there is not in the boot device
926 // select loop then we need to pop up a UI and wait for user input.
927 //
928 TmpStr = Option->StatusString;
929 if (TmpStr != NULL) {
930 BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL);
931 FreePool (TmpStr);
932 }
933 }
934
935 /**
936 Hook point after a boot attempt fails.
937
938 @param Option Pointer to Boot Option that failed to boot.
939 @param Status Status returned from failed boot.
940 @param ExitData Exit data returned from failed boot.
941 @param ExitDataSize Exit data size returned from failed boot.
942
943 **/
944 VOID
945 EFIAPI
946 PlatformBdsBootFail (
947 IN BDS_COMMON_OPTION *Option,
948 IN EFI_STATUS Status,
949 IN CHAR16 *ExitData,
950 IN UINTN ExitDataSize
951 )
952 {
953 CHAR16 *TmpStr;
954 DEBUG ((EFI_D_INFO, "PlatformBdsBootFail\n"));
955
956 //
957 // If Boot returned with failed status then we need to pop up a UI and wait
958 // for user input.
959 //
960 TmpStr = Option->StatusString;
961 if (TmpStr != NULL) {
962 BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL);
963 FreePool (TmpStr);
964 }
965 }
966
967 /**
968 This function is remained for IBV/OEM to do some platform action,
969 if there no console device can be connected.
970
971 @return EFI_SUCCESS Direct return success now.
972
973 **/
974 EFI_STATUS
975 PlatformBdsNoConsoleAction (
976 VOID
977 )
978 {
979 DEBUG ((EFI_D_INFO, "PlatformBdsNoConsoleAction\n"));
980 return EFI_SUCCESS;
981 }
982
983 /**
984 This function locks platform flash that is not allowed to be updated during normal boot path.
985 The flash layout is platform specific.
986 **/
987 VOID
988 EFIAPI
989 PlatformBdsLockNonUpdatableFlash (
990 VOID
991 )
992 {
993 DEBUG ((EFI_D_INFO, "PlatformBdsLockNonUpdatableFlash\n"));
994 return ;
995 }
996
997
998 /**
999 Lock the ConsoleIn device in system table. All key
1000 presses will be ignored until the Password is typed in. The only way to
1001 disable the password is to type it in to a ConIn device.
1002
1003 @param Password Password used to lock ConIn device.
1004
1005 @retval EFI_SUCCESS lock the Console In Spliter virtual handle successfully.
1006 @retval EFI_UNSUPPORTED Password not found
1007
1008 **/
1009 EFI_STATUS
1010 EFIAPI
1011 LockKeyboards (
1012 IN CHAR16 *Password
1013 )
1014 {
1015 return EFI_UNSUPPORTED;
1016 }