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