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