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