]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c
ProcessCapsule() and BdsMemoryTest() are implemented in the BdsDxe module, which...
[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 IN BASEM_MEMORY_TEST BaseMemoryTest
743 )
744 /*++
745
746 Routine Description:
747
748 Perform the platform diagnostic, such like test memory. OEM/IBV also
749 can customize this fuction to support specific platform diagnostic.
750
751 Arguments:
752
753 MemoryTestLevel - The memory test intensive level
754
755 QuietBoot - Indicate if need to enable the quiet boot
756
757 BaseMemoryTest - A pointer to BaseMemoryTest()
758
759 Returns:
760
761 None.
762
763 --*/
764 {
765 EFI_STATUS Status;
766
767 DEBUG ((EFI_D_INFO, "PlatformBdsDiagnostics\n"));
768
769 //
770 // Here we can decide if we need to show
771 // the diagnostics screen
772 // Notes: this quiet boot code should be remove
773 // from the graphic lib
774 //
775 if (QuietBoot) {
776 EnableQuietBoot (PcdGetPtr(PcdLogoFile));
777 //
778 // Perform system diagnostic
779 //
780 Status = BaseMemoryTest (MemoryTestLevel);
781 if (EFI_ERROR (Status)) {
782 DisableQuietBoot ();
783 }
784
785 return ;
786 }
787 //
788 // Perform system diagnostic
789 //
790 Status = BaseMemoryTest (MemoryTestLevel);
791 }
792
793
794 VOID
795 EFIAPI
796 PlatformBdsPolicyBehavior (
797 IN OUT LIST_ENTRY *DriverOptionList,
798 IN OUT LIST_ENTRY *BootOptionList,
799 IN PROCESS_CAPSULES ProcessCapsules,
800 IN BASEM_MEMORY_TEST BaseMemoryTest
801 )
802 /*++
803
804 Routine Description:
805
806 The function will excute with as the platform policy, current policy
807 is driven by boot mode. IBV/OEM can customize this code for their specific
808 policy action.
809
810 Arguments:
811
812 DriverOptionList - The header of the driver option link list
813
814 BootOptionList - The header of the boot option link list
815
816 ProcessCapsules - A pointer to ProcessCapsules()
817
818 BaseMemoryTest - A pointer to BaseMemoryTest()
819
820 Returns:
821
822 None.
823
824 --*/
825 {
826 EFI_STATUS Status;
827 UINT16 Timeout;
828 EFI_EVENT UserInputDurationTime;
829 LIST_ENTRY *Link;
830 BDS_COMMON_OPTION *BootOption;
831 UINTN Index;
832 EFI_INPUT_KEY Key;
833 EFI_TPL OldTpl;
834 EFI_BOOT_MODE BootMode;
835
836 DEBUG ((EFI_D_INFO, "PlatformBdsPolicyBehavior\n"));
837
838 //
839 // Init the time out value
840 //
841 Timeout = PcdGet16 (PcdPlatformBootTimeOut);
842
843 //
844 // Load the driver option as the driver option list
845 //
846 PlatformBdsGetDriverOption (DriverOptionList);
847
848 //
849 // Get current Boot Mode
850 //
851 Status = BdsLibGetBootMode (&BootMode);
852 DEBUG ((EFI_D_ERROR, "Boot Mode:%x\n", BootMode));
853
854 //
855 // Go the different platform policy with different boot mode
856 // Notes: this part code can be change with the table policy
857 //
858 ASSERT (BootMode == BOOT_WITH_FULL_CONFIGURATION);
859 //
860 // Connect platform console
861 //
862 Status = PlatformBdsConnectConsole (gPlatformConsole);
863 if (EFI_ERROR (Status)) {
864 //
865 // Here OEM/IBV can customize with defined action
866 //
867 PlatformBdsNoConsoleAction ();
868 }
869 //
870 // Create a 300ms duration event to ensure user has enough input time to enter Setup
871 //
872 Status = gBS->CreateEvent (
873 EVT_TIMER,
874 0,
875 NULL,
876 NULL,
877 &UserInputDurationTime
878 );
879 ASSERT (Status == EFI_SUCCESS);
880 Status = gBS->SetTimer (UserInputDurationTime, TimerRelative, 3000000);
881 ASSERT (Status == EFI_SUCCESS);
882 //
883 // Memory test and Logo show
884 //
885 PlatformBdsDiagnostics (IGNORE, TRUE, BaseMemoryTest);
886
887 //
888 // Perform some platform specific connect sequence
889 //
890 PlatformBdsConnectSequence ();
891
892 //
893 // Give one chance to enter the setup if we
894 // have the time out
895 //
896 if (Timeout != 0) {
897 //PlatformBdsEnterFrontPage (Timeout, FALSE);
898 }
899
900 DEBUG ((EFI_D_INFO, "BdsLibConnectAll\n"));
901 BdsLibConnectAll ();
902 BdsLibEnumerateAllBootOption (BootOptionList);
903
904 //
905 // Please uncomment above ConnectAll and EnumerateAll code and remove following first boot
906 // checking code in real production tip.
907 //
908 // In BOOT_WITH_FULL_CONFIGURATION boot mode, should always connect every device
909 // and do enumerate all the default boot options. But in development system board, the boot mode
910 // cannot be BOOT_ASSUMING_NO_CONFIGURATION_CHANGES because the machine box
911 // is always open. So the following code only do the ConnectAll and EnumerateAll at first boot.
912 //
913 Status = BdsLibBuildOptionFromVar (BootOptionList, L"BootOrder");
914 if (EFI_ERROR(Status)) {
915 //
916 // If cannot find "BootOrder" variable, it may be first boot.
917 // Try to connect all devices and enumerate all boot options here.
918 //
919 BdsLibConnectAll ();
920 BdsLibEnumerateAllBootOption (BootOptionList);
921 }
922
923 //
924 // To give the User a chance to enter Setup here, if user set TimeOut is 0.
925 // BDS should still give user a chance to enter Setup
926 //
927 // Connect first boot option, and then check user input before exit
928 //
929 for (Link = BootOptionList->ForwardLink; Link != BootOptionList;Link = Link->ForwardLink) {
930 BootOption = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);
931 if (!IS_LOAD_OPTION_TYPE (BootOption->Attribute, LOAD_OPTION_ACTIVE)) {
932 //
933 // skip the header of the link list, becuase it has no boot option
934 //
935 continue;
936 } else {
937 //
938 // Make sure the boot option device path connected, but ignore the BBS device path
939 //
940 if (DevicePathType (BootOption->DevicePath) != BBS_DEVICE_PATH) {
941 BdsLibConnectDevicePath (BootOption->DevicePath);
942 }
943 break;
944 }
945 }
946
947 //
948 // Check whether the user input after the duration time has expired
949 //
950 OldTpl = EfiGetCurrentTpl();
951 gBS->RestoreTPL (TPL_APPLICATION);
952 gBS->WaitForEvent (1, &UserInputDurationTime, &Index);
953 gBS->CloseEvent (UserInputDurationTime);
954 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
955 gBS->RaiseTPL (OldTpl);
956
957 if (!EFI_ERROR (Status)) {
958 //
959 // Enter Setup if user input
960 //
961 Timeout = 0xffff;
962 PlatformBdsEnterFrontPage (Timeout, FALSE);
963 }
964
965 return ;
966 }
967
968 VOID
969 EFIAPI
970 PlatformBdsBootSuccess (
971 IN BDS_COMMON_OPTION *Option
972 )
973 /*++
974
975 Routine Description:
976
977 Hook point after a boot attempt succeeds. We don't expect a boot option to
978 return, so the EFI 1.0 specification defines that you will default to an
979 interactive mode and stop processing the BootOrder list in this case. This
980 is alos a platform implementation and can be customized by IBV/OEM.
981
982 Arguments:
983
984 Option - Pointer to Boot Option that succeeded to boot.
985
986 Returns:
987
988 None.
989
990 --*/
991 {
992 CHAR16 *TmpStr;
993
994 DEBUG ((EFI_D_INFO, "PlatformBdsBootSuccess\n"));
995 //
996 // If Boot returned with EFI_SUCCESS and there is not in the boot device
997 // select loop then we need to pop up a UI and wait for user input.
998 //
999 TmpStr = Option->StatusString;
1000 if (TmpStr != NULL) {
1001 BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL);
1002 FreePool (TmpStr);
1003 }
1004 }
1005
1006 VOID
1007 EFIAPI
1008 PlatformBdsBootFail (
1009 IN BDS_COMMON_OPTION *Option,
1010 IN EFI_STATUS Status,
1011 IN CHAR16 *ExitData,
1012 IN UINTN ExitDataSize
1013 )
1014 /*++
1015
1016 Routine Description:
1017
1018 Hook point after a boot attempt fails.
1019
1020 Arguments:
1021
1022 Option - Pointer to Boot Option that failed to boot.
1023
1024 Status - Status returned from failed boot.
1025
1026 ExitData - Exit data returned from failed boot.
1027
1028 ExitDataSize - Exit data size returned from failed boot.
1029
1030 Returns:
1031
1032 None.
1033
1034 --*/
1035 {
1036 CHAR16 *TmpStr;
1037
1038 DEBUG ((EFI_D_INFO, "PlatformBdsBootFail\n"));
1039
1040 //
1041 // If Boot returned with failed status then we need to pop up a UI and wait
1042 // for user input.
1043 //
1044 TmpStr = Option->StatusString;
1045 if (TmpStr != NULL) {
1046 BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL);
1047 FreePool (TmpStr);
1048 }
1049 }
1050
1051 EFI_STATUS
1052 PlatformBdsNoConsoleAction (
1053 VOID
1054 )
1055 /*++
1056
1057 Routine Description:
1058
1059 This function is remained for IBV/OEM to do some platform action,
1060 if there no console device can be connected.
1061
1062 Arguments:
1063
1064 None.
1065
1066 Returns:
1067
1068 EFI_SUCCESS - Direct return success now.
1069
1070 --*/
1071 {
1072 DEBUG ((EFI_D_INFO, "PlatformBdsNoConsoleAction\n"));
1073 return EFI_SUCCESS;
1074 }
1075
1076 VOID
1077 EFIAPI
1078 PlatformBdsLockNonUpdatableFlash (
1079 VOID
1080 )
1081 {
1082 DEBUG ((EFI_D_INFO, "PlatformBdsLockNonUpdatableFlash\n"));
1083 return;
1084 }
1085
1086
1087 /**
1088 This notification function is invoked when an instance of the
1089 EFI_DEVICE_PATH_PROTOCOL is produced.
1090
1091 @param Event The event that occured
1092 @param Context For EFI compatiblity. Not used.
1093
1094 **/
1095 VOID
1096 EFIAPI
1097 NotifyDevPath (
1098 IN EFI_EVENT Event,
1099 IN VOID *Context
1100 )
1101 {
1102 EFI_HANDLE Handle;
1103 EFI_STATUS Status;
1104 UINTN BufferSize;
1105 EFI_DEVICE_PATH_PROTOCOL *DevPathNode;
1106 ATAPI_DEVICE_PATH *Atapi;
1107
1108 //
1109 // Examine all new handles
1110 //
1111 for (;;) {
1112 //
1113 // Get the next handle
1114 //
1115 BufferSize = sizeof (Handle);
1116 Status = gBS->LocateHandle (
1117 ByRegisterNotify,
1118 NULL,
1119 mEfiDevPathNotifyReg,
1120 &BufferSize,
1121 &Handle
1122 );
1123
1124 //
1125 // If not found, we're done
1126 //
1127 if (EFI_NOT_FOUND == Status) {
1128 break;
1129 }
1130
1131 if (EFI_ERROR (Status)) {
1132 continue;
1133 }
1134
1135 //
1136 // Get the DevicePath protocol on that handle
1137 //
1138 Status = gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **)&DevPathNode);
1139 ASSERT_EFI_ERROR (Status);
1140
1141 while (!IsDevicePathEnd (DevPathNode)) {
1142 //
1143 // Find the handler to dump this device path node
1144 //
1145 if (
1146 (DevicePathType(DevPathNode) == MESSAGING_DEVICE_PATH) &&
1147 (DevicePathSubType(DevPathNode) == MSG_ATAPI_DP)
1148 ) {
1149 Atapi = (ATAPI_DEVICE_PATH*) DevPathNode;
1150 PciOr16 (
1151 PCI_LIB_ADDRESS (
1152 0,
1153 1,
1154 1,
1155 (Atapi->PrimarySecondary == 1) ? 0x42: 0x40
1156 ),
1157 BIT15
1158 );
1159 }
1160
1161 //
1162 // Next device path node
1163 //
1164 DevPathNode = NextDevicePathNode (DevPathNode);
1165 }
1166 }
1167
1168 return;
1169 }
1170
1171
1172 VOID
1173 InstallDevicePathCallback (
1174 VOID
1175 )
1176 {
1177 DEBUG ((EFI_D_INFO, "Registered NotifyDevPath Event\n"));
1178 mEfiDevPathEvent = EfiCreateProtocolNotifyEvent (
1179 &gEfiDevicePathProtocolGuid,
1180 TPL_CALLBACK,
1181 NotifyDevPath,
1182 NULL,
1183 &mEfiDevPathNotifyReg
1184 );
1185 }
1186
1187 /**
1188 Lock the ConsoleIn device in system table. All key
1189 presses will be ignored until the Password is typed in. The only way to
1190 disable the password is to type it in to a ConIn device.
1191
1192 @param Password Password used to lock ConIn device.
1193
1194 @retval EFI_SUCCESS lock the Console In Spliter virtual handle successfully.
1195 @retval EFI_UNSUPPORTED Password not found
1196
1197 **/
1198 EFI_STATUS
1199 EFIAPI
1200 LockKeyboards (
1201 IN CHAR16 *Password
1202 )
1203 {
1204 return EFI_UNSUPPORTED;
1205 }