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