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