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