]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c
Add missing EFIAPI instances on several functions.
[mirror_edk2.git] / OvmfPkg / Library / PlatformBdsLib / BdsPlatform.c
1 /** @file
2 Platform BDS customizations.
3
4 Copyright (c) 2004 - 2009, 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 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 EFI_STATUS
777 EFIAPI
778 ConnectRecursivelyIfPciMassStorage (
779 IN EFI_HANDLE Handle,
780 IN EFI_PCI_IO_PROTOCOL *Instance,
781 IN PCI_TYPE00 *PciHeader
782 )
783 {
784 EFI_STATUS Status;
785 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
786 CHAR16 *DevPathStr;
787
788 if (IS_CLASS1 (PciHeader, PCI_CLASS_MASS_STORAGE)) {
789 DevicePath = NULL;
790 Status = gBS->HandleProtocol (
791 Handle,
792 &gEfiDevicePathProtocolGuid,
793 (VOID*)&DevicePath
794 );
795 if (EFI_ERROR (Status)) {
796 return Status;
797 }
798
799 //
800 // Print Device Path
801 //
802 DevPathStr = DevicePathToStr (DevicePath);
803 DEBUG((
804 EFI_D_INFO,
805 "Found Mass Storage device: %s\n",
806 DevPathStr
807 ));
808 FreePool(DevPathStr);
809
810 Status = gBS->ConnectController (Handle, NULL, NULL, TRUE);
811 if (EFI_ERROR (Status)) {
812 return Status;
813 }
814
815 }
816
817 return EFI_SUCCESS;
818 }
819
820
821 /**
822 This notification function is invoked when the
823 EMU Variable FVB has been changed.
824
825 @param Event The event that occured
826 @param Context For EFI compatiblity. Not used.
827
828 **/
829 VOID
830 EFIAPI
831 EmuVariablesUpdatedCallback (
832 IN EFI_EVENT Event,
833 IN VOID *Context
834 )
835 {
836 DEBUG ((EFI_D_INFO, "EmuVariablesUpdatedCallback\n"));
837 UpdateNvVarsOnFileSystem ();
838 }
839
840
841 EFI_STATUS
842 EFIAPI
843 VisitingFileSystemInstance (
844 IN EFI_HANDLE Handle,
845 IN VOID *Instance,
846 IN VOID *Context
847 )
848 {
849 EFI_STATUS Status;
850 STATIC BOOLEAN ConnectedToFileSystem = FALSE;
851
852 if (ConnectedToFileSystem) {
853 return EFI_ALREADY_STARTED;
854 }
855
856 Status = ConnectNvVarsToFileSystem (Handle);
857 if (EFI_ERROR (Status)) {
858 return Status;
859 }
860
861 ConnectedToFileSystem = TRUE;
862 mEmuVariableEvent =
863 EfiCreateProtocolNotifyEvent (
864 &gEfiDevicePathProtocolGuid,
865 TPL_CALLBACK,
866 EmuVariablesUpdatedCallback,
867 NULL,
868 &mEmuVariableEventReg
869 );
870 PcdSet64 (PcdEmuVariableEvent, (UINT64)(UINTN) mEmuVariableEvent);
871
872 return EFI_SUCCESS;
873 }
874
875
876 VOID
877 PlatformBdsRestoreNvVarsFromHardDisk (
878 )
879 {
880 VisitAllPciInstances (ConnectRecursivelyIfPciMassStorage);
881 VisitAllInstancesOfProtocol (
882 &gEfiSimpleFileSystemProtocolGuid,
883 VisitingFileSystemInstance,
884 NULL
885 );
886
887 }
888
889
890 VOID
891 PlatformBdsConnectSequence (
892 VOID
893 )
894 /*++
895
896 Routine Description:
897
898 Connect with predeined platform connect sequence,
899 the OEM/IBV can customize with their own connect sequence.
900
901 Arguments:
902
903 None.
904
905 Returns:
906
907 None.
908
909 --*/
910 {
911 UINTN Index;
912
913 DEBUG ((EFI_D_INFO, "PlatformBdsConnectSequence\n"));
914
915 Index = 0;
916
917 //
918 // Here we can get the customized platform connect sequence
919 // Notes: we can connect with new variable which record the
920 // last time boots connect device path sequence
921 //
922 while (gPlatformConnectSequence[Index] != NULL) {
923 //
924 // Build the platform boot option
925 //
926 BdsLibConnectDevicePath (gPlatformConnectSequence[Index]);
927 Index++;
928 }
929
930 //
931 // Just use the simple policy to connect all devices
932 //
933 BdsLibConnectAll ();
934
935 PciInitialization ();
936
937 //
938 // Clear the logo after all devices are connected.
939 //
940 gST->ConOut->ClearScreen (gST->ConOut);
941 }
942
943 VOID
944 PlatformBdsGetDriverOption (
945 IN OUT LIST_ENTRY *BdsDriverLists
946 )
947 /*++
948
949 Routine Description:
950
951 Load the predefined driver option, OEM/IBV can customize this
952 to load their own drivers
953
954 Arguments:
955
956 BdsDriverLists - The header of the driver option link list.
957
958 Returns:
959
960 None.
961
962 --*/
963 {
964 DEBUG ((EFI_D_INFO, "PlatformBdsGetDriverOption\n"));
965 return;
966 }
967
968 VOID
969 PlatformBdsDiagnostics (
970 IN EXTENDMEM_COVERAGE_LEVEL MemoryTestLevel,
971 IN BOOLEAN QuietBoot,
972 IN BASEM_MEMORY_TEST BaseMemoryTest
973 )
974 /*++
975
976 Routine Description:
977
978 Perform the platform diagnostic, such like test memory. OEM/IBV also
979 can customize this fuction to support specific platform diagnostic.
980
981 Arguments:
982
983 MemoryTestLevel - The memory test intensive level
984
985 QuietBoot - Indicate if need to enable the quiet boot
986
987 BaseMemoryTest - A pointer to BaseMemoryTest()
988
989 Returns:
990
991 None.
992
993 --*/
994 {
995 EFI_STATUS Status;
996
997 DEBUG ((EFI_D_INFO, "PlatformBdsDiagnostics\n"));
998
999 //
1000 // Here we can decide if we need to show
1001 // the diagnostics screen
1002 // Notes: this quiet boot code should be remove
1003 // from the graphic lib
1004 //
1005 if (QuietBoot) {
1006 EnableQuietBoot (PcdGetPtr(PcdLogoFile));
1007 //
1008 // Perform system diagnostic
1009 //
1010 Status = BaseMemoryTest (MemoryTestLevel);
1011 if (EFI_ERROR (Status)) {
1012 DisableQuietBoot ();
1013 }
1014
1015 return ;
1016 }
1017 //
1018 // Perform system diagnostic
1019 //
1020 Status = BaseMemoryTest (MemoryTestLevel);
1021 }
1022
1023
1024 VOID
1025 EFIAPI
1026 PlatformBdsPolicyBehavior (
1027 IN OUT LIST_ENTRY *DriverOptionList,
1028 IN OUT LIST_ENTRY *BootOptionList,
1029 IN PROCESS_CAPSULES ProcessCapsules,
1030 IN BASEM_MEMORY_TEST BaseMemoryTest
1031 )
1032 /*++
1033
1034 Routine Description:
1035
1036 The function will excute with as the platform policy, current policy
1037 is driven by boot mode. IBV/OEM can customize this code for their specific
1038 policy action.
1039
1040 Arguments:
1041
1042 DriverOptionList - The header of the driver option link list
1043
1044 BootOptionList - The header of the boot option link list
1045
1046 ProcessCapsules - A pointer to ProcessCapsules()
1047
1048 BaseMemoryTest - A pointer to BaseMemoryTest()
1049
1050 Returns:
1051
1052 None.
1053
1054 --*/
1055 {
1056 EFI_STATUS Status;
1057 UINT16 Timeout;
1058 EFI_EVENT UserInputDurationTime;
1059 LIST_ENTRY *Link;
1060 BDS_COMMON_OPTION *BootOption;
1061 UINTN Index;
1062 EFI_INPUT_KEY Key;
1063 EFI_TPL OldTpl;
1064 EFI_BOOT_MODE BootMode;
1065
1066 DEBUG ((EFI_D_INFO, "PlatformBdsPolicyBehavior\n"));
1067
1068 ConnectRootBridge ();
1069
1070 //
1071 // Try to restore variables from the hard disk early so
1072 // they can be used for the other BDS connect operations.
1073 //
1074 PlatformBdsRestoreNvVarsFromHardDisk ();
1075
1076 //
1077 // Init the time out value
1078 //
1079 Timeout = PcdGet16 (PcdPlatformBootTimeOut);
1080
1081 //
1082 // Load the driver option as the driver option list
1083 //
1084 PlatformBdsGetDriverOption (DriverOptionList);
1085
1086 //
1087 // Get current Boot Mode
1088 //
1089 Status = BdsLibGetBootMode (&BootMode);
1090 DEBUG ((EFI_D_ERROR, "Boot Mode:%x\n", BootMode));
1091
1092 //
1093 // Go the different platform policy with different boot mode
1094 // Notes: this part code can be change with the table policy
1095 //
1096 ASSERT (BootMode == BOOT_WITH_FULL_CONFIGURATION);
1097 //
1098 // Connect platform console
1099 //
1100 Status = PlatformBdsConnectConsole (gPlatformConsole);
1101 if (EFI_ERROR (Status)) {
1102 //
1103 // Here OEM/IBV can customize with defined action
1104 //
1105 PlatformBdsNoConsoleAction ();
1106 }
1107 //
1108 // Create a 300ms duration event to ensure user has enough input time to enter Setup
1109 //
1110 Status = gBS->CreateEvent (
1111 EVT_TIMER,
1112 0,
1113 NULL,
1114 NULL,
1115 &UserInputDurationTime
1116 );
1117 ASSERT (Status == EFI_SUCCESS);
1118 Status = gBS->SetTimer (UserInputDurationTime, TimerRelative, 3000000);
1119 ASSERT (Status == EFI_SUCCESS);
1120 //
1121 // Memory test and Logo show
1122 //
1123 PlatformBdsDiagnostics (IGNORE, TRUE, BaseMemoryTest);
1124
1125 //
1126 // Perform some platform specific connect sequence
1127 //
1128 PlatformBdsConnectSequence ();
1129
1130 //
1131 // Give one chance to enter the setup if we
1132 // have the time out
1133 //
1134 if (Timeout != 0) {
1135 //PlatformBdsEnterFrontPage (Timeout, FALSE);
1136 }
1137
1138 DEBUG ((EFI_D_INFO, "BdsLibConnectAll\n"));
1139 BdsLibConnectAll ();
1140 BdsLibEnumerateAllBootOption (BootOptionList);
1141
1142 //
1143 // Please uncomment above ConnectAll and EnumerateAll code and remove following first boot
1144 // checking code in real production tip.
1145 //
1146 // In BOOT_WITH_FULL_CONFIGURATION boot mode, should always connect every device
1147 // and do enumerate all the default boot options. But in development system board, the boot mode
1148 // cannot be BOOT_ASSUMING_NO_CONFIGURATION_CHANGES because the machine box
1149 // is always open. So the following code only do the ConnectAll and EnumerateAll at first boot.
1150 //
1151 Status = BdsLibBuildOptionFromVar (BootOptionList, L"BootOrder");
1152 if (EFI_ERROR(Status)) {
1153 //
1154 // If cannot find "BootOrder" variable, it may be first boot.
1155 // Try to connect all devices and enumerate all boot options here.
1156 //
1157 BdsLibConnectAll ();
1158 BdsLibEnumerateAllBootOption (BootOptionList);
1159 }
1160
1161 //
1162 // To give the User a chance to enter Setup here, if user set TimeOut is 0.
1163 // BDS should still give user a chance to enter Setup
1164 //
1165 // Connect first boot option, and then check user input before exit
1166 //
1167 for (Link = BootOptionList->ForwardLink; Link != BootOptionList;Link = Link->ForwardLink) {
1168 BootOption = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);
1169 if (!IS_LOAD_OPTION_TYPE (BootOption->Attribute, LOAD_OPTION_ACTIVE)) {
1170 //
1171 // skip the header of the link list, becuase it has no boot option
1172 //
1173 continue;
1174 } else {
1175 //
1176 // Make sure the boot option device path connected, but ignore the BBS device path
1177 //
1178 if (DevicePathType (BootOption->DevicePath) != BBS_DEVICE_PATH) {
1179 BdsLibConnectDevicePath (BootOption->DevicePath);
1180 }
1181 break;
1182 }
1183 }
1184
1185 //
1186 // Check whether the user input after the duration time has expired
1187 //
1188 OldTpl = EfiGetCurrentTpl();
1189 gBS->RestoreTPL (TPL_APPLICATION);
1190 gBS->WaitForEvent (1, &UserInputDurationTime, &Index);
1191 gBS->CloseEvent (UserInputDurationTime);
1192 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
1193 gBS->RaiseTPL (OldTpl);
1194
1195 if (!EFI_ERROR (Status)) {
1196 //
1197 // Enter Setup if user input
1198 //
1199 Timeout = 0xffff;
1200 PlatformBdsEnterFrontPage (Timeout, FALSE);
1201 }
1202
1203 return ;
1204 }
1205
1206 VOID
1207 EFIAPI
1208 PlatformBdsBootSuccess (
1209 IN BDS_COMMON_OPTION *Option
1210 )
1211 /*++
1212
1213 Routine Description:
1214
1215 Hook point after a boot attempt succeeds. We don't expect a boot option to
1216 return, so the EFI 1.0 specification defines that you will default to an
1217 interactive mode and stop processing the BootOrder list in this case. This
1218 is alos a platform implementation and can be customized by IBV/OEM.
1219
1220 Arguments:
1221
1222 Option - Pointer to Boot Option that succeeded to boot.
1223
1224 Returns:
1225
1226 None.
1227
1228 --*/
1229 {
1230 CHAR16 *TmpStr;
1231
1232 DEBUG ((EFI_D_INFO, "PlatformBdsBootSuccess\n"));
1233 //
1234 // If Boot returned with EFI_SUCCESS and there is not in the boot device
1235 // select loop then we need to pop up a UI and wait for user input.
1236 //
1237 TmpStr = Option->StatusString;
1238 if (TmpStr != NULL) {
1239 BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL);
1240 FreePool (TmpStr);
1241 }
1242 }
1243
1244 VOID
1245 EFIAPI
1246 PlatformBdsBootFail (
1247 IN BDS_COMMON_OPTION *Option,
1248 IN EFI_STATUS Status,
1249 IN CHAR16 *ExitData,
1250 IN UINTN ExitDataSize
1251 )
1252 /*++
1253
1254 Routine Description:
1255
1256 Hook point after a boot attempt fails.
1257
1258 Arguments:
1259
1260 Option - Pointer to Boot Option that failed to boot.
1261
1262 Status - Status returned from failed boot.
1263
1264 ExitData - Exit data returned from failed boot.
1265
1266 ExitDataSize - Exit data size returned from failed boot.
1267
1268 Returns:
1269
1270 None.
1271
1272 --*/
1273 {
1274 CHAR16 *TmpStr;
1275
1276 DEBUG ((EFI_D_INFO, "PlatformBdsBootFail\n"));
1277
1278 //
1279 // If Boot returned with failed status then we need to pop up a UI and wait
1280 // for user input.
1281 //
1282 TmpStr = Option->StatusString;
1283 if (TmpStr != NULL) {
1284 BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL);
1285 FreePool (TmpStr);
1286 }
1287 }
1288
1289 EFI_STATUS
1290 PlatformBdsNoConsoleAction (
1291 VOID
1292 )
1293 /*++
1294
1295 Routine Description:
1296
1297 This function is remained for IBV/OEM to do some platform action,
1298 if there no console device can be connected.
1299
1300 Arguments:
1301
1302 None.
1303
1304 Returns:
1305
1306 EFI_SUCCESS - Direct return success now.
1307
1308 --*/
1309 {
1310 DEBUG ((EFI_D_INFO, "PlatformBdsNoConsoleAction\n"));
1311 return EFI_SUCCESS;
1312 }
1313
1314 VOID
1315 EFIAPI
1316 PlatformBdsLockNonUpdatableFlash (
1317 VOID
1318 )
1319 {
1320 DEBUG ((EFI_D_INFO, "PlatformBdsLockNonUpdatableFlash\n"));
1321 return;
1322 }
1323
1324
1325 /**
1326 This notification function is invoked when an instance of the
1327 EFI_DEVICE_PATH_PROTOCOL is produced.
1328
1329 @param Event The event that occured
1330 @param Context For EFI compatiblity. Not used.
1331
1332 **/
1333 VOID
1334 EFIAPI
1335 NotifyDevPath (
1336 IN EFI_EVENT Event,
1337 IN VOID *Context
1338 )
1339 {
1340 EFI_HANDLE Handle;
1341 EFI_STATUS Status;
1342 UINTN BufferSize;
1343 EFI_DEVICE_PATH_PROTOCOL *DevPathNode;
1344 ATAPI_DEVICE_PATH *Atapi;
1345
1346 //
1347 // Examine all new handles
1348 //
1349 for (;;) {
1350 //
1351 // Get the next handle
1352 //
1353 BufferSize = sizeof (Handle);
1354 Status = gBS->LocateHandle (
1355 ByRegisterNotify,
1356 NULL,
1357 mEfiDevPathNotifyReg,
1358 &BufferSize,
1359 &Handle
1360 );
1361
1362 //
1363 // If not found, we're done
1364 //
1365 if (EFI_NOT_FOUND == Status) {
1366 break;
1367 }
1368
1369 if (EFI_ERROR (Status)) {
1370 continue;
1371 }
1372
1373 //
1374 // Get the DevicePath protocol on that handle
1375 //
1376 Status = gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **)&DevPathNode);
1377 ASSERT_EFI_ERROR (Status);
1378
1379 while (!IsDevicePathEnd (DevPathNode)) {
1380 //
1381 // Find the handler to dump this device path node
1382 //
1383 if (
1384 (DevicePathType(DevPathNode) == MESSAGING_DEVICE_PATH) &&
1385 (DevicePathSubType(DevPathNode) == MSG_ATAPI_DP)
1386 ) {
1387 Atapi = (ATAPI_DEVICE_PATH*) DevPathNode;
1388 PciOr16 (
1389 PCI_LIB_ADDRESS (
1390 0,
1391 1,
1392 1,
1393 (Atapi->PrimarySecondary == 1) ? 0x42: 0x40
1394 ),
1395 BIT15
1396 );
1397 }
1398
1399 //
1400 // Next device path node
1401 //
1402 DevPathNode = NextDevicePathNode (DevPathNode);
1403 }
1404 }
1405
1406 return;
1407 }
1408
1409
1410 VOID
1411 InstallDevicePathCallback (
1412 VOID
1413 )
1414 {
1415 DEBUG ((EFI_D_INFO, "Registered NotifyDevPath Event\n"));
1416 mEfiDevPathEvent = EfiCreateProtocolNotifyEvent (
1417 &gEfiDevicePathProtocolGuid,
1418 TPL_CALLBACK,
1419 NotifyDevPath,
1420 NULL,
1421 &mEfiDevPathNotifyReg
1422 );
1423 }
1424
1425 /**
1426 Lock the ConsoleIn device in system table. All key
1427 presses will be ignored until the Password is typed in. The only way to
1428 disable the password is to type it in to a ConIn device.
1429
1430 @param Password Password used to lock ConIn device.
1431
1432 @retval EFI_SUCCESS lock the Console In Spliter virtual handle successfully.
1433 @retval EFI_UNSUPPORTED Password not found
1434
1435 **/
1436 EFI_STATUS
1437 EFIAPI
1438 LockKeyboards (
1439 IN CHAR16 *Password
1440 )
1441 {
1442 return EFI_UNSUPPORTED;
1443 }
1444
1445
1446 STATIC
1447 VOID
1448 LoadVideoRom (
1449 VOID
1450 )
1451 {
1452 PCI_DATA_STRUCTURE *Pcir;
1453 UINTN RomSize;
1454
1455 //
1456 // The virtual machines sometimes load the video rom image
1457 // directly at the legacy video BIOS location of C000:0000,
1458 // and do not implement the PCI expansion ROM feature.
1459 //
1460 Pcir = (PCI_DATA_STRUCTURE *) (UINTN) 0xc0000;
1461 RomSize = Pcir->ImageLength * 512;
1462 PciRomLoadEfiDriversFromRomImage (0xc0000, RomSize);
1463 }
1464
1465
1466 STATIC
1467 EFI_STATUS
1468 PciRomLoadEfiDriversFromRomImage (
1469 IN EFI_PHYSICAL_ADDRESS Rom,
1470 IN UINTN RomSize
1471 )
1472 {
1473 CHAR16 *FileName;
1474 EFI_PCI_EXPANSION_ROM_HEADER *EfiRomHeader;
1475 PCI_DATA_STRUCTURE *Pcir;
1476 UINTN ImageIndex;
1477 UINTN RomOffset;
1478 UINT32 ImageSize;
1479 UINT16 ImageOffset;
1480 EFI_HANDLE ImageHandle;
1481 EFI_STATUS Status;
1482 EFI_STATUS retStatus;
1483 EFI_DEVICE_PATH_PROTOCOL *FilePath;
1484 BOOLEAN SkipImage;
1485 UINT32 DestinationSize;
1486 UINT32 ScratchSize;
1487 UINT8 *Scratch;
1488 VOID *ImageBuffer;
1489 VOID *DecompressedImageBuffer;
1490 UINT32 ImageLength;
1491 EFI_DECOMPRESS_PROTOCOL *Decompress;
1492
1493 FileName = L"PciRomInMemory";
1494
1495 //FileName = L"PciRom Addr=0000000000000000";
1496 //HexToString (&FileName[12], Rom, 16);
1497
1498 ImageIndex = 0;
1499 retStatus = EFI_NOT_FOUND;
1500 RomOffset = (UINTN) Rom;
1501
1502 do {
1503
1504 EfiRomHeader = (EFI_PCI_EXPANSION_ROM_HEADER *) (UINTN) RomOffset;
1505
1506 if (EfiRomHeader->Signature != 0xaa55) {
1507 return retStatus;
1508 }
1509
1510 Pcir = (PCI_DATA_STRUCTURE *) (UINTN) (RomOffset + EfiRomHeader->PcirOffset);
1511 ImageSize = Pcir->ImageLength * 512;
1512
1513 if ((Pcir->CodeType == PCI_CODE_TYPE_EFI_IMAGE) &&
1514 (EfiRomHeader->EfiSignature == EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE) ) {
1515
1516 if ((EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) ||
1517 (EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) ) {
1518
1519 ImageOffset = EfiRomHeader->EfiImageHeaderOffset;
1520 ImageSize = EfiRomHeader->InitializationSize * 512;
1521
1522 ImageBuffer = (VOID *) (UINTN) (RomOffset + ImageOffset);
1523 ImageLength = ImageSize - ImageOffset;
1524 DecompressedImageBuffer = NULL;
1525
1526 //
1527 // decompress here if needed
1528 //
1529 SkipImage = FALSE;
1530 if (EfiRomHeader->CompressionType > EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {
1531 SkipImage = TRUE;
1532 }
1533
1534 if (EfiRomHeader->CompressionType == EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {
1535 Status = gBS->LocateProtocol (&gEfiDecompressProtocolGuid, NULL, (VOID **) &Decompress);
1536 if (EFI_ERROR (Status)) {
1537 SkipImage = TRUE;
1538 } else {
1539 SkipImage = TRUE;
1540 Status = Decompress->GetInfo (
1541 Decompress,
1542 ImageBuffer,
1543 ImageLength,
1544 &DestinationSize,
1545 &ScratchSize
1546 );
1547 if (!EFI_ERROR (Status)) {
1548 DecompressedImageBuffer = NULL;
1549 DecompressedImageBuffer = AllocatePool (DestinationSize);
1550 if (DecompressedImageBuffer != NULL) {
1551 Scratch = AllocatePool (ScratchSize);
1552 if (Scratch != NULL) {
1553 Status = Decompress->Decompress (
1554 Decompress,
1555 ImageBuffer,
1556 ImageLength,
1557 DecompressedImageBuffer,
1558 DestinationSize,
1559 Scratch,
1560 ScratchSize
1561 );
1562 if (!EFI_ERROR (Status)) {
1563 ImageBuffer = DecompressedImageBuffer;
1564 ImageLength = DestinationSize;
1565 SkipImage = FALSE;
1566 }
1567
1568 gBS->FreePool (Scratch);
1569 }
1570 }
1571 }
1572 }
1573 }
1574
1575 if (!SkipImage) {
1576
1577 //
1578 // load image and start image
1579 //
1580
1581 FilePath = FileDevicePath (NULL, FileName);
1582
1583 Status = gBS->LoadImage (
1584 FALSE,
1585 gImageHandle,
1586 FilePath,
1587 ImageBuffer,
1588 ImageLength,
1589 &ImageHandle
1590 );
1591 if (!EFI_ERROR (Status)) {
1592 Status = gBS->StartImage (ImageHandle, NULL, NULL);
1593 if (!EFI_ERROR (Status)) {
1594 retStatus = Status;
1595 }
1596 }
1597 if (FilePath != NULL) {
1598 gBS->FreePool (FilePath);
1599 }
1600 }
1601
1602 if (DecompressedImageBuffer != NULL) {
1603 gBS->FreePool (DecompressedImageBuffer);
1604 }
1605
1606 }
1607 }
1608
1609 RomOffset = RomOffset + ImageSize;
1610 ImageIndex++;
1611 } while (((Pcir->Indicator & 0x80) == 0x00) && ((RomOffset - (UINTN) Rom) < RomSize));
1612
1613 return retStatus;
1614 }
1615
1616