]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c
OvmfPkg PlatformBdsLib: Set SCI_EN bit of PMCNTRL
[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 STATIC
77 VOID
78 LoadVideoRom (
79 VOID
80 );
81
82 STATIC
83 EFI_STATUS
84 PciRomLoadEfiDriversFromRomImage (
85 IN EFI_PHYSICAL_ADDRESS Rom,
86 IN UINTN RomSize
87 );
88
89 //
90 // BDS Platform Functions
91 //
92 VOID
93 EFIAPI
94 PlatformBdsInit (
95 VOID
96 )
97 /*++
98
99 Routine Description:
100
101 Platform Bds init. Incude the platform firmware vendor, revision
102 and so crc check.
103
104 Arguments:
105
106 Returns:
107
108 None.
109
110 --*/
111 {
112 DEBUG ((EFI_D_INFO, "PlatformBdsInit\n"));
113 InstallDevicePathCallback ();
114 LoadVideoRom ();
115 }
116
117
118 EFI_STATUS
119 ConnectRootBridge (
120 VOID
121 )
122 /*++
123
124 Routine Description:
125
126 Connect RootBridge
127
128 Arguments:
129
130 None.
131
132 Returns:
133
134 EFI_SUCCESS - Connect RootBridge successfully.
135 EFI_STATUS - Connect RootBridge fail.
136
137 --*/
138 {
139 EFI_STATUS Status;
140 EFI_HANDLE RootHandle;
141
142 //
143 // Make all the PCI_IO protocols on PCI Seg 0 show up
144 //
145 BdsLibConnectDevicePath (gPlatformRootBridges[0]);
146
147 Status = gBS->LocateDevicePath (
148 &gEfiDevicePathProtocolGuid,
149 &gPlatformRootBridges[0],
150 &RootHandle
151 );
152 if (EFI_ERROR (Status)) {
153 return Status;
154 }
155
156 Status = gBS->ConnectController (RootHandle, NULL, NULL, FALSE);
157 if (EFI_ERROR (Status)) {
158 return Status;
159 }
160
161 return EFI_SUCCESS;
162 }
163
164
165 EFI_STATUS
166 PrepareLpcBridgeDevicePath (
167 IN EFI_HANDLE DeviceHandle
168 )
169 /*++
170
171 Routine Description:
172
173 Add IsaKeyboard to ConIn,
174 add IsaSerial to ConOut, ConIn, ErrOut.
175 LPC Bridge: 06 01 00
176
177 Arguments:
178
179 DeviceHandle - Handle of PCIIO protocol.
180
181 Returns:
182
183 EFI_SUCCESS - LPC bridge is added to ConOut, ConIn, and ErrOut.
184 EFI_STATUS - No LPC bridge is added.
185
186 --*/
187 {
188 EFI_STATUS Status;
189 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
190 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
191 CHAR16 *DevPathStr;
192
193 DevicePath = NULL;
194 Status = gBS->HandleProtocol (
195 DeviceHandle,
196 &gEfiDevicePathProtocolGuid,
197 (VOID*)&DevicePath
198 );
199 if (EFI_ERROR (Status)) {
200 return Status;
201 }
202 TempDevicePath = DevicePath;
203
204 //
205 // Register Keyboard
206 //
207 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnpPs2KeyboardDeviceNode);
208
209 BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL);
210
211 //
212 // Register COM1
213 //
214 DevicePath = TempDevicePath;
215 gPnp16550ComPortDeviceNode.UID = 0;
216
217 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode);
218 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);
219 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);
220
221 //
222 // Print Device Path
223 //
224 DevPathStr = DevicePathToStr(DevicePath);
225 DEBUG((
226 EFI_D_INFO,
227 "BdsPlatform.c+%d: COM%d DevPath: %s\n",
228 __LINE__,
229 gPnp16550ComPortDeviceNode.UID + 1,
230 DevPathStr
231 ));
232 FreePool(DevPathStr);
233
234 BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);
235 BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL);
236 BdsLibUpdateConsoleVariable (VarErrorOut, DevicePath, NULL);
237
238 //
239 // Register COM2
240 //
241 DevicePath = TempDevicePath;
242 gPnp16550ComPortDeviceNode.UID = 1;
243
244 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode);
245 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);
246 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);
247
248 //
249 // Print Device Path
250 //
251 DevPathStr = DevicePathToStr(DevicePath);
252 DEBUG((
253 EFI_D_INFO,
254 "BdsPlatform.c+%d: COM%d DevPath: %s\n",
255 __LINE__,
256 gPnp16550ComPortDeviceNode.UID + 1,
257 DevPathStr
258 ));
259 FreePool(DevPathStr);
260
261 BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);
262 BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL);
263 BdsLibUpdateConsoleVariable (VarErrorOut, DevicePath, NULL);
264
265 return EFI_SUCCESS;
266 }
267
268 EFI_STATUS
269 GetGopDevicePath (
270 IN EFI_DEVICE_PATH_PROTOCOL *PciDevicePath,
271 OUT EFI_DEVICE_PATH_PROTOCOL **GopDevicePath
272 )
273 {
274 UINTN Index;
275 EFI_STATUS Status;
276 EFI_HANDLE PciDeviceHandle;
277 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
278 EFI_DEVICE_PATH_PROTOCOL *TempPciDevicePath;
279 UINTN GopHandleCount;
280 EFI_HANDLE *GopHandleBuffer;
281
282 if (PciDevicePath == NULL || GopDevicePath == NULL) {
283 return EFI_INVALID_PARAMETER;
284 }
285
286 //
287 // Initialize the GopDevicePath to be PciDevicePath
288 //
289 *GopDevicePath = PciDevicePath;
290 TempPciDevicePath = PciDevicePath;
291
292 Status = gBS->LocateDevicePath (
293 &gEfiDevicePathProtocolGuid,
294 &TempPciDevicePath,
295 &PciDeviceHandle
296 );
297 if (EFI_ERROR (Status)) {
298 return Status;
299 }
300
301 //
302 // Try to connect this handle, so that GOP dirver could start on this
303 // device and create child handles with GraphicsOutput Protocol installed
304 // on them, then we get device paths of these child handles and select
305 // them as possible console device.
306 //
307 gBS->ConnectController (PciDeviceHandle, NULL, NULL, FALSE);
308
309 Status = gBS->LocateHandleBuffer (
310 ByProtocol,
311 &gEfiGraphicsOutputProtocolGuid,
312 NULL,
313 &GopHandleCount,
314 &GopHandleBuffer
315 );
316 if (!EFI_ERROR (Status)) {
317 //
318 // Add all the child handles as possible Console Device
319 //
320 for (Index = 0; Index < GopHandleCount; Index++) {
321 Status = gBS->HandleProtocol (GopHandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID*)&TempDevicePath);
322 if (EFI_ERROR (Status)) {
323 continue;
324 }
325 if (CompareMem (
326 PciDevicePath,
327 TempDevicePath,
328 GetDevicePathSize (PciDevicePath) - END_DEVICE_PATH_LENGTH
329 ) == 0) {
330 //
331 // In current implementation, we only enable one of the child handles
332 // as console device, i.e. sotre one of the child handle's device
333 // path to variable "ConOut"
334 // In futhure, we could select all child handles to be console device
335 //
336
337 *GopDevicePath = TempDevicePath;
338
339 //
340 // Delete the PCI device's path that added by GetPlugInPciVgaDevicePath()
341 // Add the integrity GOP device path.
342 //
343 BdsLibUpdateConsoleVariable (VarConsoleOutDev, NULL, PciDevicePath);
344 BdsLibUpdateConsoleVariable (VarConsoleOutDev, TempDevicePath, NULL);
345 }
346 }
347 gBS->FreePool (GopHandleBuffer);
348 }
349
350 return EFI_SUCCESS;
351 }
352
353 EFI_STATUS
354 PreparePciVgaDevicePath (
355 IN EFI_HANDLE DeviceHandle
356 )
357 /*++
358
359 Routine Description:
360
361 Add PCI VGA to ConOut.
362 PCI VGA: 03 00 00
363
364 Arguments:
365
366 DeviceHandle - Handle of PCIIO protocol.
367
368 Returns:
369
370 EFI_SUCCESS - PCI VGA is added to ConOut.
371 EFI_STATUS - No PCI VGA device is added.
372
373 --*/
374 {
375 EFI_STATUS Status;
376 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
377 EFI_DEVICE_PATH_PROTOCOL *GopDevicePath;
378
379 DevicePath = NULL;
380 Status = gBS->HandleProtocol (
381 DeviceHandle,
382 &gEfiDevicePathProtocolGuid,
383 (VOID*)&DevicePath
384 );
385 if (EFI_ERROR (Status)) {
386 return Status;
387 }
388
389 GetGopDevicePath (DevicePath, &GopDevicePath);
390 DevicePath = GopDevicePath;
391
392 BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);
393
394 return EFI_SUCCESS;
395 }
396
397 EFI_STATUS
398 PreparePciSerialDevicePath (
399 IN EFI_HANDLE DeviceHandle
400 )
401 /*++
402
403 Routine Description:
404
405 Add PCI Serial to ConOut, ConIn, ErrOut.
406 PCI Serial: 07 00 02
407
408 Arguments:
409
410 DeviceHandle - Handle of PCIIO protocol.
411
412 Returns:
413
414 EFI_SUCCESS - PCI Serial is added to ConOut, ConIn, and ErrOut.
415 EFI_STATUS - No PCI Serial device is added.
416
417 --*/
418 {
419 EFI_STATUS Status;
420 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
421
422 DevicePath = NULL;
423 Status = gBS->HandleProtocol (
424 DeviceHandle,
425 &gEfiDevicePathProtocolGuid,
426 (VOID*)&DevicePath
427 );
428 if (EFI_ERROR (Status)) {
429 return Status;
430 }
431
432 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);
433 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);
434
435 BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);
436 BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL);
437 BdsLibUpdateConsoleVariable (VarErrorOut, DevicePath, NULL);
438
439 return EFI_SUCCESS;
440 }
441
442 EFI_STATUS
443 VisitAllInstancesOfProtocol (
444 IN EFI_GUID *Id,
445 IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction,
446 IN VOID *Context
447 )
448 {
449 EFI_STATUS Status;
450 UINTN HandleCount;
451 EFI_HANDLE *HandleBuffer;
452 UINTN Index;
453 VOID *Instance;
454
455 //
456 // Start to check all the PciIo to find all possible device
457 //
458 HandleCount = 0;
459 HandleBuffer = NULL;
460 Status = gBS->LocateHandleBuffer (
461 ByProtocol,
462 Id,
463 NULL,
464 &HandleCount,
465 &HandleBuffer
466 );
467 if (EFI_ERROR (Status)) {
468 return Status;
469 }
470
471 for (Index = 0; Index < HandleCount; Index++) {
472 Status = gBS->HandleProtocol (HandleBuffer[Index], Id, &Instance);
473 if (EFI_ERROR (Status)) {
474 continue;
475 }
476
477 Status = (*CallBackFunction) (
478 HandleBuffer[Index],
479 Instance,
480 Context
481 );
482 }
483
484 gBS->FreePool (HandleBuffer);
485
486 return EFI_SUCCESS;
487 }
488
489
490 EFI_STATUS
491 EFIAPI
492 VisitingAPciInstance (
493 IN EFI_HANDLE Handle,
494 IN VOID *Instance,
495 IN VOID *Context
496 )
497 {
498 EFI_STATUS Status;
499 EFI_PCI_IO_PROTOCOL *PciIo;
500 PCI_TYPE00 Pci;
501
502 PciIo = (EFI_PCI_IO_PROTOCOL*) Instance;
503
504 //
505 // Check for all PCI device
506 //
507 Status = PciIo->Pci.Read (
508 PciIo,
509 EfiPciIoWidthUint32,
510 0,
511 sizeof (Pci) / sizeof (UINT32),
512 &Pci
513 );
514 if (EFI_ERROR (Status)) {
515 return Status;
516 }
517
518 return (*(VISIT_PCI_INSTANCE_CALLBACK)(UINTN) Context) (
519 Handle,
520 PciIo,
521 &Pci
522 );
523
524 }
525
526
527
528 EFI_STATUS
529 VisitAllPciInstances (
530 IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
531 )
532 {
533 return VisitAllInstancesOfProtocol (
534 &gEfiPciIoProtocolGuid,
535 VisitingAPciInstance,
536 (VOID*)(UINTN) CallBackFunction
537 );
538 }
539
540
541 /**
542 Do platform specific PCI Device check and add them to
543 ConOut, ConIn, ErrOut.
544
545 @param[in] Handle - Handle of PCI device instance
546 @param[in] PciIo - PCI IO protocol instance
547 @param[in] Pci - PCI Header register block
548
549 @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.
550 @retval EFI_STATUS - PCI Device check or Console variable update fail.
551
552 **/
553 EFI_STATUS
554 EFIAPI
555 DetectAndPreparePlatformPciDevicePath (
556 IN EFI_HANDLE Handle,
557 IN EFI_PCI_IO_PROTOCOL *PciIo,
558 IN PCI_TYPE00 *Pci
559 )
560 {
561 EFI_STATUS Status;
562
563 Status = PciIo->Attributes (
564 PciIo,
565 EfiPciIoAttributeOperationEnable,
566 EFI_PCI_DEVICE_ENABLE,
567 NULL
568 );
569 ASSERT_EFI_ERROR (Status);
570
571 if (!mDetectVgaOnly) {
572 //
573 // Here we decide whether it is LPC Bridge
574 //
575 if ((IS_PCI_LPC (Pci)) ||
576 ((IS_PCI_ISA_PDECODE (Pci)) &&
577 (Pci->Hdr.VendorId == 0x8086) &&
578 (Pci->Hdr.DeviceId == 0x7000)
579 )
580 ) {
581 //
582 // Add IsaKeyboard to ConIn,
583 // add IsaSerial to ConOut, ConIn, ErrOut
584 //
585 DEBUG ((EFI_D_INFO, "Found LPC Bridge device\n"));
586 PrepareLpcBridgeDevicePath (Handle);
587 return EFI_SUCCESS;
588 }
589 //
590 // Here we decide which Serial device to enable in PCI bus
591 //
592 if (IS_PCI_16550SERIAL (Pci)) {
593 //
594 // Add them to ConOut, ConIn, ErrOut.
595 //
596 DEBUG ((EFI_D_INFO, "Found PCI 16550 SERIAL device\n"));
597 PreparePciSerialDevicePath (Handle);
598 return EFI_SUCCESS;
599 }
600 }
601
602 //
603 // Here we decide which VGA device to enable in PCI bus
604 //
605 if (IS_PCI_VGA (Pci)) {
606 //
607 // Add them to ConOut.
608 //
609 DEBUG ((EFI_D_INFO, "Found PCI VGA device\n"));
610 PreparePciVgaDevicePath (Handle);
611 return EFI_SUCCESS;
612 }
613
614 return Status;
615 }
616
617
618 /**
619 Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
620
621 @param[in] DetectVgaOnly - Only detect VGA device if it's TRUE.
622
623 @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.
624 @retval EFI_STATUS - PCI Device check or Console variable update fail.
625
626 **/
627 EFI_STATUS
628 DetectAndPreparePlatformPciDevicePaths (
629 BOOLEAN DetectVgaOnly
630 )
631 {
632 mDetectVgaOnly = DetectVgaOnly;
633 return VisitAllPciInstances (DetectAndPreparePlatformPciDevicePath);
634 }
635
636
637 EFI_STATUS
638 PlatformBdsConnectConsole (
639 IN BDS_CONSOLE_CONNECT_ENTRY *PlatformConsole
640 )
641 /*++
642
643 Routine Description:
644
645 Connect the predefined platform default console device. Always try to find
646 and enable the vga device if have.
647
648 Arguments:
649
650 PlatformConsole - Predfined platform default console device array.
651
652 Returns:
653
654 EFI_SUCCESS - Success connect at least one ConIn and ConOut
655 device, there must have one ConOut device is
656 active vga device.
657
658 EFI_STATUS - Return the status of
659 BdsLibConnectAllDefaultConsoles ()
660
661 --*/
662 {
663 EFI_STATUS Status;
664 UINTN Index;
665 EFI_DEVICE_PATH_PROTOCOL *VarConout;
666 EFI_DEVICE_PATH_PROTOCOL *VarConin;
667 UINTN DevicePathSize;
668
669 //
670 // Connect RootBridge
671 //
672 VarConout = BdsLibGetVariableAndSize (
673 VarConsoleOut,
674 &gEfiGlobalVariableGuid,
675 &DevicePathSize
676 );
677 VarConin = BdsLibGetVariableAndSize (
678 VarConsoleInp,
679 &gEfiGlobalVariableGuid,
680 &DevicePathSize
681 );
682
683 if (VarConout == NULL || VarConin == NULL) {
684 //
685 // Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
686 //
687 DetectAndPreparePlatformPciDevicePaths (FALSE);
688
689 //
690 // Have chance to connect the platform default console,
691 // the platform default console is the minimue device group
692 // the platform should support
693 //
694 for (Index = 0; PlatformConsole[Index].DevicePath != NULL; ++Index) {
695 //
696 // Update the console variable with the connect type
697 //
698 if ((PlatformConsole[Index].ConnectType & CONSOLE_IN) == CONSOLE_IN) {
699 BdsLibUpdateConsoleVariable (VarConsoleInp, PlatformConsole[Index].DevicePath, NULL);
700 }
701 if ((PlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) {
702 BdsLibUpdateConsoleVariable (VarConsoleOut, PlatformConsole[Index].DevicePath, NULL);
703 }
704 if ((PlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) {
705 BdsLibUpdateConsoleVariable (VarErrorOut, PlatformConsole[Index].DevicePath, NULL);
706 }
707 }
708 } else {
709 //
710 // Only detect VGA device and add them to ConOut
711 //
712 DetectAndPreparePlatformPciDevicePaths (TRUE);
713 }
714
715 //
716 // Connect the all the default console with current cosole variable
717 //
718 Status = BdsLibConnectAllDefaultConsoles ();
719 if (EFI_ERROR (Status)) {
720 return Status;
721 }
722
723 return EFI_SUCCESS;
724 }
725
726
727 VOID
728 PciInitialization (
729 )
730 {
731 //
732 // Bus 0, Device 0, Function 0 - Host to PCI Bridge
733 //
734 PciWrite8 (PCI_LIB_ADDRESS (0, 0, 0, 0x3c), 0x00);
735
736 //
737 // Bus 0, Device 1, Function 0 - PCI to ISA Bridge
738 //
739 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x3c), 0x00);
740 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x60), 0x0b);
741 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x61), 0x09);
742 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x62), 0x0b);
743 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x63), 0x09);
744
745 //
746 // Bus 0, Device 1, Function 1 - IDE Controller
747 //
748 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 1, 0x3c), 0x00);
749 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 1, 0x0d), 0x40);
750
751 //
752 // Bus 0, Device 1, Function 3 - Power Managment Controller
753 //
754 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 3, 0x3c), 0x0b);
755 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 3, 0x3d), 0x01);
756
757 //
758 // Bus 0, Device 2, Function 0 - Video Controller
759 //
760 PciWrite8 (PCI_LIB_ADDRESS (0, 2, 0, 0x3c), 0x00);
761
762 //
763 // Bus 0, Device 3, Function 0 - Network Controller
764 //
765 PciWrite8 (PCI_LIB_ADDRESS (0, 3, 0, 0x3c), 0x0b);
766 PciWrite8 (PCI_LIB_ADDRESS (0, 3, 0, 0x3d), 0x01);
767
768 //
769 // Bus 0, Device 4, Function 0 - RAM Memory
770 //
771 PciWrite8 (PCI_LIB_ADDRESS (0, 4, 0, 0x3c), 0x09);
772 PciWrite8 (PCI_LIB_ADDRESS (0, 4, 0, 0x3d), 0x01);
773 }
774
775
776 VOID
777 AcpiInitialization (
778 VOID
779 )
780 {
781 //
782 // Set ACPI SCI_EN bit in PMCNTRL
783 //
784 IoOr16 ((PciRead32 (PCI_LIB_ADDRESS (0, 1, 3, 0x40)) & ~BIT0) + 4, BIT0);
785 }
786
787
788 EFI_STATUS
789 EFIAPI
790 ConnectRecursivelyIfPciMassStorage (
791 IN EFI_HANDLE Handle,
792 IN EFI_PCI_IO_PROTOCOL *Instance,
793 IN PCI_TYPE00 *PciHeader
794 )
795 {
796 EFI_STATUS Status;
797 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
798 CHAR16 *DevPathStr;
799
800 if (IS_CLASS1 (PciHeader, PCI_CLASS_MASS_STORAGE)) {
801 DevicePath = NULL;
802 Status = gBS->HandleProtocol (
803 Handle,
804 &gEfiDevicePathProtocolGuid,
805 (VOID*)&DevicePath
806 );
807 if (EFI_ERROR (Status)) {
808 return Status;
809 }
810
811 //
812 // Print Device Path
813 //
814 DevPathStr = DevicePathToStr (DevicePath);
815 DEBUG((
816 EFI_D_INFO,
817 "Found Mass Storage device: %s\n",
818 DevPathStr
819 ));
820 FreePool(DevPathStr);
821
822 Status = gBS->ConnectController (Handle, NULL, NULL, TRUE);
823 if (EFI_ERROR (Status)) {
824 return Status;
825 }
826
827 }
828
829 return EFI_SUCCESS;
830 }
831
832
833 /**
834 This notification function is invoked when the
835 EMU Variable FVB has been changed.
836
837 @param Event The event that occured
838 @param Context For EFI compatiblity. Not used.
839
840 **/
841 VOID
842 EFIAPI
843 EmuVariablesUpdatedCallback (
844 IN EFI_EVENT Event,
845 IN VOID *Context
846 )
847 {
848 DEBUG ((EFI_D_INFO, "EmuVariablesUpdatedCallback\n"));
849 UpdateNvVarsOnFileSystem ();
850 }
851
852
853 EFI_STATUS
854 EFIAPI
855 VisitingFileSystemInstance (
856 IN EFI_HANDLE Handle,
857 IN VOID *Instance,
858 IN VOID *Context
859 )
860 {
861 EFI_STATUS Status;
862 STATIC BOOLEAN ConnectedToFileSystem = FALSE;
863
864 if (ConnectedToFileSystem) {
865 return EFI_ALREADY_STARTED;
866 }
867
868 Status = ConnectNvVarsToFileSystem (Handle);
869 if (EFI_ERROR (Status)) {
870 return Status;
871 }
872
873 ConnectedToFileSystem = TRUE;
874 mEmuVariableEvent =
875 EfiCreateProtocolNotifyEvent (
876 &gEfiDevicePathProtocolGuid,
877 TPL_CALLBACK,
878 EmuVariablesUpdatedCallback,
879 NULL,
880 &mEmuVariableEventReg
881 );
882 PcdSet64 (PcdEmuVariableEvent, (UINT64)(UINTN) mEmuVariableEvent);
883
884 return EFI_SUCCESS;
885 }
886
887
888 VOID
889 PlatformBdsRestoreNvVarsFromHardDisk (
890 )
891 {
892 VisitAllPciInstances (ConnectRecursivelyIfPciMassStorage);
893 VisitAllInstancesOfProtocol (
894 &gEfiSimpleFileSystemProtocolGuid,
895 VisitingFileSystemInstance,
896 NULL
897 );
898
899 }
900
901
902 VOID
903 PlatformBdsConnectSequence (
904 VOID
905 )
906 /*++
907
908 Routine Description:
909
910 Connect with predeined platform connect sequence,
911 the OEM/IBV can customize with their own connect sequence.
912
913 Arguments:
914
915 None.
916
917 Returns:
918
919 None.
920
921 --*/
922 {
923 UINTN Index;
924
925 DEBUG ((EFI_D_INFO, "PlatformBdsConnectSequence\n"));
926
927 Index = 0;
928
929 //
930 // Here we can get the customized platform connect sequence
931 // Notes: we can connect with new variable which record the
932 // last time boots connect device path sequence
933 //
934 while (gPlatformConnectSequence[Index] != NULL) {
935 //
936 // Build the platform boot option
937 //
938 BdsLibConnectDevicePath (gPlatformConnectSequence[Index]);
939 Index++;
940 }
941
942 //
943 // Just use the simple policy to connect all devices
944 //
945 BdsLibConnectAll ();
946
947 PciInitialization ();
948 AcpiInitialization ();
949
950 //
951 // Clear the logo after all devices are connected.
952 //
953 gST->ConOut->ClearScreen (gST->ConOut);
954 }
955
956 VOID
957 PlatformBdsGetDriverOption (
958 IN OUT LIST_ENTRY *BdsDriverLists
959 )
960 /*++
961
962 Routine Description:
963
964 Load the predefined driver option, OEM/IBV can customize this
965 to load their own drivers
966
967 Arguments:
968
969 BdsDriverLists - The header of the driver option link list.
970
971 Returns:
972
973 None.
974
975 --*/
976 {
977 DEBUG ((EFI_D_INFO, "PlatformBdsGetDriverOption\n"));
978 return;
979 }
980
981 VOID
982 PlatformBdsDiagnostics (
983 IN EXTENDMEM_COVERAGE_LEVEL MemoryTestLevel,
984 IN BOOLEAN QuietBoot,
985 IN BASEM_MEMORY_TEST BaseMemoryTest
986 )
987 /*++
988
989 Routine Description:
990
991 Perform the platform diagnostic, such like test memory. OEM/IBV also
992 can customize this fuction to support specific platform diagnostic.
993
994 Arguments:
995
996 MemoryTestLevel - The memory test intensive level
997
998 QuietBoot - Indicate if need to enable the quiet boot
999
1000 BaseMemoryTest - A pointer to BaseMemoryTest()
1001
1002 Returns:
1003
1004 None.
1005
1006 --*/
1007 {
1008 EFI_STATUS Status;
1009
1010 DEBUG ((EFI_D_INFO, "PlatformBdsDiagnostics\n"));
1011
1012 //
1013 // Here we can decide if we need to show
1014 // the diagnostics screen
1015 // Notes: this quiet boot code should be remove
1016 // from the graphic lib
1017 //
1018 if (QuietBoot) {
1019 EnableQuietBoot (PcdGetPtr(PcdLogoFile));
1020 //
1021 // Perform system diagnostic
1022 //
1023 Status = BaseMemoryTest (MemoryTestLevel);
1024 if (EFI_ERROR (Status)) {
1025 DisableQuietBoot ();
1026 }
1027
1028 return ;
1029 }
1030 //
1031 // Perform system diagnostic
1032 //
1033 Status = BaseMemoryTest (MemoryTestLevel);
1034 }
1035
1036
1037 VOID
1038 EFIAPI
1039 PlatformBdsPolicyBehavior (
1040 IN OUT LIST_ENTRY *DriverOptionList,
1041 IN OUT LIST_ENTRY *BootOptionList,
1042 IN PROCESS_CAPSULES ProcessCapsules,
1043 IN BASEM_MEMORY_TEST BaseMemoryTest
1044 )
1045 /*++
1046
1047 Routine Description:
1048
1049 The function will excute with as the platform policy, current policy
1050 is driven by boot mode. IBV/OEM can customize this code for their specific
1051 policy action.
1052
1053 Arguments:
1054
1055 DriverOptionList - The header of the driver option link list
1056
1057 BootOptionList - The header of the boot option link list
1058
1059 ProcessCapsules - A pointer to ProcessCapsules()
1060
1061 BaseMemoryTest - A pointer to BaseMemoryTest()
1062
1063 Returns:
1064
1065 None.
1066
1067 --*/
1068 {
1069 EFI_STATUS Status;
1070 UINT16 Timeout;
1071 EFI_EVENT UserInputDurationTime;
1072 LIST_ENTRY *Link;
1073 BDS_COMMON_OPTION *BootOption;
1074 UINTN Index;
1075 EFI_INPUT_KEY Key;
1076 EFI_TPL OldTpl;
1077 EFI_BOOT_MODE BootMode;
1078
1079 DEBUG ((EFI_D_INFO, "PlatformBdsPolicyBehavior\n"));
1080
1081 ConnectRootBridge ();
1082
1083 //
1084 // Try to restore variables from the hard disk early so
1085 // they can be used for the other BDS connect operations.
1086 //
1087 PlatformBdsRestoreNvVarsFromHardDisk ();
1088
1089 //
1090 // Init the time out value
1091 //
1092 Timeout = PcdGet16 (PcdPlatformBootTimeOut);
1093
1094 //
1095 // Load the driver option as the driver option list
1096 //
1097 PlatformBdsGetDriverOption (DriverOptionList);
1098
1099 //
1100 // Get current Boot Mode
1101 //
1102 Status = BdsLibGetBootMode (&BootMode);
1103 DEBUG ((EFI_D_ERROR, "Boot Mode:%x\n", BootMode));
1104
1105 //
1106 // Go the different platform policy with different boot mode
1107 // Notes: this part code can be change with the table policy
1108 //
1109 ASSERT (BootMode == BOOT_WITH_FULL_CONFIGURATION);
1110 //
1111 // Connect platform console
1112 //
1113 Status = PlatformBdsConnectConsole (gPlatformConsole);
1114 if (EFI_ERROR (Status)) {
1115 //
1116 // Here OEM/IBV can customize with defined action
1117 //
1118 PlatformBdsNoConsoleAction ();
1119 }
1120 //
1121 // Create a 300ms duration event to ensure user has enough input time to enter Setup
1122 //
1123 Status = gBS->CreateEvent (
1124 EVT_TIMER,
1125 0,
1126 NULL,
1127 NULL,
1128 &UserInputDurationTime
1129 );
1130 ASSERT (Status == EFI_SUCCESS);
1131 Status = gBS->SetTimer (UserInputDurationTime, TimerRelative, 3000000);
1132 ASSERT (Status == EFI_SUCCESS);
1133 //
1134 // Memory test and Logo show
1135 //
1136 PlatformBdsDiagnostics (IGNORE, TRUE, BaseMemoryTest);
1137
1138 //
1139 // Perform some platform specific connect sequence
1140 //
1141 PlatformBdsConnectSequence ();
1142
1143 //
1144 // Give one chance to enter the setup if we
1145 // have the time out
1146 //
1147 if (Timeout != 0) {
1148 //PlatformBdsEnterFrontPage (Timeout, FALSE);
1149 }
1150
1151 DEBUG ((EFI_D_INFO, "BdsLibConnectAll\n"));
1152 BdsLibConnectAll ();
1153 BdsLibEnumerateAllBootOption (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
1458
1459 STATIC
1460 VOID
1461 LoadVideoRom (
1462 VOID
1463 )
1464 {
1465 PCI_DATA_STRUCTURE *Pcir;
1466 UINTN RomSize;
1467
1468 //
1469 // The virtual machines sometimes load the video rom image
1470 // directly at the legacy video BIOS location of C000:0000,
1471 // and do not implement the PCI expansion ROM feature.
1472 //
1473 Pcir = (PCI_DATA_STRUCTURE *) (UINTN) 0xc0000;
1474 RomSize = Pcir->ImageLength * 512;
1475 PciRomLoadEfiDriversFromRomImage (0xc0000, RomSize);
1476 }
1477
1478
1479 STATIC
1480 EFI_STATUS
1481 PciRomLoadEfiDriversFromRomImage (
1482 IN EFI_PHYSICAL_ADDRESS Rom,
1483 IN UINTN RomSize
1484 )
1485 {
1486 CHAR16 *FileName;
1487 EFI_PCI_EXPANSION_ROM_HEADER *EfiRomHeader;
1488 PCI_DATA_STRUCTURE *Pcir;
1489 UINTN ImageIndex;
1490 UINTN RomOffset;
1491 UINT32 ImageSize;
1492 UINT16 ImageOffset;
1493 EFI_HANDLE ImageHandle;
1494 EFI_STATUS Status;
1495 EFI_STATUS retStatus;
1496 EFI_DEVICE_PATH_PROTOCOL *FilePath;
1497 BOOLEAN SkipImage;
1498 UINT32 DestinationSize;
1499 UINT32 ScratchSize;
1500 UINT8 *Scratch;
1501 VOID *ImageBuffer;
1502 VOID *DecompressedImageBuffer;
1503 UINT32 ImageLength;
1504 EFI_DECOMPRESS_PROTOCOL *Decompress;
1505 UINT32 InitializationSize;
1506
1507 FileName = L"PciRomInMemory";
1508
1509 //FileName = L"PciRom Addr=0000000000000000";
1510 //HexToString (&FileName[12], Rom, 16);
1511
1512 ImageIndex = 0;
1513 retStatus = EFI_NOT_FOUND;
1514 RomOffset = (UINTN) Rom;
1515
1516 do {
1517
1518 EfiRomHeader = (EFI_PCI_EXPANSION_ROM_HEADER *) (UINTN) RomOffset;
1519
1520 if (EfiRomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {
1521 return retStatus;
1522 }
1523
1524 //
1525 // If the pointer to the PCI Data Structure is invalid, no further images can be located.
1526 // The PCI Data Structure must be DWORD aligned.
1527 //
1528 if (EfiRomHeader->PcirOffset == 0 ||
1529 (EfiRomHeader->PcirOffset & 3) != 0 ||
1530 RomOffset - (UINTN)Rom + EfiRomHeader->PcirOffset + sizeof (PCI_DATA_STRUCTURE) > RomSize) {
1531 break;
1532 }
1533 Pcir = (PCI_DATA_STRUCTURE *) (UINTN) (RomOffset + EfiRomHeader->PcirOffset);
1534 //
1535 // If a valid signature is not present in the PCI Data Structure, no further images can be located.
1536 //
1537 if (Pcir->Signature != PCI_DATA_STRUCTURE_SIGNATURE) {
1538 break;
1539 }
1540 ImageSize = Pcir->ImageLength * 512;
1541 if (RomOffset - (UINTN)Rom + ImageSize > RomSize) {
1542 break;
1543 }
1544
1545 if ((Pcir->CodeType == PCI_CODE_TYPE_EFI_IMAGE) &&
1546 (EfiRomHeader->EfiSignature == EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE) &&
1547 ((EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) ||
1548 (EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER))) {
1549
1550 ImageOffset = EfiRomHeader->EfiImageHeaderOffset;
1551 InitializationSize = EfiRomHeader->InitializationSize * 512;
1552
1553 if (InitializationSize <= ImageSize && ImageOffset < InitializationSize) {
1554
1555 ImageBuffer = (VOID *) (UINTN) (RomOffset + ImageOffset);
1556 ImageLength = InitializationSize - ImageOffset;
1557 DecompressedImageBuffer = NULL;
1558
1559 //
1560 // decompress here if needed
1561 //
1562 SkipImage = FALSE;
1563 if (EfiRomHeader->CompressionType > EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {
1564 SkipImage = TRUE;
1565 }
1566
1567 if (EfiRomHeader->CompressionType == EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {
1568 Status = gBS->LocateProtocol (&gEfiDecompressProtocolGuid, NULL, (VOID **) &Decompress);
1569 if (EFI_ERROR (Status)) {
1570 SkipImage = TRUE;
1571 } else {
1572 SkipImage = TRUE;
1573 Status = Decompress->GetInfo (
1574 Decompress,
1575 ImageBuffer,
1576 ImageLength,
1577 &DestinationSize,
1578 &ScratchSize
1579 );
1580 if (!EFI_ERROR (Status)) {
1581 DecompressedImageBuffer = NULL;
1582 DecompressedImageBuffer = AllocatePool (DestinationSize);
1583 if (DecompressedImageBuffer != NULL) {
1584 Scratch = AllocatePool (ScratchSize);
1585 if (Scratch != NULL) {
1586 Status = Decompress->Decompress (
1587 Decompress,
1588 ImageBuffer,
1589 ImageLength,
1590 DecompressedImageBuffer,
1591 DestinationSize,
1592 Scratch,
1593 ScratchSize
1594 );
1595 if (!EFI_ERROR (Status)) {
1596 ImageBuffer = DecompressedImageBuffer;
1597 ImageLength = DestinationSize;
1598 SkipImage = FALSE;
1599 }
1600
1601 gBS->FreePool (Scratch);
1602 }
1603 }
1604 }
1605 }
1606 }
1607
1608 if (!SkipImage) {
1609
1610 //
1611 // load image and start image
1612 //
1613
1614 FilePath = FileDevicePath (NULL, FileName);
1615
1616 Status = gBS->LoadImage (
1617 FALSE,
1618 gImageHandle,
1619 FilePath,
1620 ImageBuffer,
1621 ImageLength,
1622 &ImageHandle
1623 );
1624 if (!EFI_ERROR (Status)) {
1625 Status = gBS->StartImage (ImageHandle, NULL, NULL);
1626 if (!EFI_ERROR (Status)) {
1627 retStatus = Status;
1628 }
1629 }
1630 if (FilePath != NULL) {
1631 gBS->FreePool (FilePath);
1632 }
1633 }
1634
1635 if (DecompressedImageBuffer != NULL) {
1636 gBS->FreePool (DecompressedImageBuffer);
1637 }
1638
1639 }
1640 }
1641
1642 RomOffset = RomOffset + ImageSize;
1643 ImageIndex++;
1644 } while (((Pcir->Indicator & 0x80) == 0x00) && ((RomOffset - (UINTN) Rom) < RomSize));
1645
1646 return retStatus;
1647 }
1648
1649