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