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