summaryrefslogtreecommitdiff
path: root/Core/CORE_DXE/BDS.c
diff options
context:
space:
mode:
Diffstat (limited to 'Core/CORE_DXE/BDS.c')
-rw-r--r--Core/CORE_DXE/BDS.c1607
1 files changed, 1607 insertions, 0 deletions
diff --git a/Core/CORE_DXE/BDS.c b/Core/CORE_DXE/BDS.c
new file mode 100644
index 0000000..f3302c2
--- /dev/null
+++ b/Core/CORE_DXE/BDS.c
@@ -0,0 +1,1607 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2010, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/CORE_DXE/BDS.c 3 7/15/14 9:54p Chienhsieh $
+//
+// $Revision: 3 $
+//
+// $Date: 7/15/14 9:54p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/CORE_DXE/BDS.c $
+//
+// 3 7/15/14 9:54p Chienhsieh
+// Update rev.125 for EIP172950, Core updates for UEFI Variable Technical
+// Advisory implement.
+//
+// 125 5/09/14 2:44p Artems
+// [TAG] EIP166565
+// [Category] Improvement
+// [Description] Removed runtime-access attribute from the variables
+// MemoryTypeInformation
+// and PreviousMemoryTypeInformation
+// [Files] BDS.c
+//
+// 2 11/21/12 4:21a Wesleychen
+// Update for SCT test (EIP104956).
+//
+// 117 10/29/12 4:03p Artems
+// [TAG] EIP104956
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] UEFI 2.3.1 SCT test failed in Generic\EfiCompliant case.
+// The VariableAttribute of ErrOut is not correct.
+// [RootCause] System variable ErrOut was saved without EFI_NON_VOLATILE
+// attribute
+// [Solution] Added missing attribute
+// [Files] Bds.c
+//
+// 116 10/08/12 6:56p Artems
+// [TAG] EIP N/A
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] build error with message invalid Code page
+// [RootCause] Presence of special characters in debug comment
+// [Solution] Removed special characters
+// [Files] BDS.c
+//
+// 115 7/20/12 10:33a Artems
+// [TAG] EIP N/A
+// [Category] Improvement
+// [Description] Improved debug output for SaveMemoryInformation
+// function
+// [Files] BDS.c
+//
+// 114 5/30/12 4:59p Felixp
+// SaveMemoryTypeInformation is updated to never decrease the memory type
+// usage values
+// to workaround Windows 7 and Windows 8 bug.
+//
+// 113 5/30/12 3:12p Felixp
+// [TAG] EIP90941
+// [Category] Bug Fix
+// [Symptom] "System resume from S4 would have problem when iRST
+// setting changed and system did S4.
+// [RootCause] SaveMemoryTypeInformation has been called twice.
+// [Solution] The function is updated to perform processing only during
+// the first call.
+//
+// 112 5/23/12 11:42a Artems
+// [TAG] EIP N/A
+// [Category] Spec Update
+// [Description] Replaced FirmwareVolume protocol with FirmwareVolume2
+// protocol
+// [Files] bootoptions.h BDS.c
+//
+// 111 4/12/12 11:12a Felixp
+// [TAG] EIP85611
+// [Category] Improvement
+// [Description] Memory map is not consistent between
+// second and third boots if system has been reset from the Setup
+// during the very first boot.
+// [Files] Bds.c, CORE_DXE.sdl
+//
+// 110 12/05/11 2:18p Felixp
+// // 109 11/21/11 11:03a Felixp
+// // [TAG] EIP69841
+// // [Category] Improvement
+// // [Description] Improvements in the Memory Type Information
+// processing
+// // to properly handle first boot.
+//
+// 109 11/21/11 11:03a Felixp
+// [TAG] EIP69841
+// [Category] Improvement
+// [Description] Improvements in the Memory Type Information processing
+// to properly handle S4 resume during the fast boot.
+//
+// 108 11/09/11 3:19p Oleksiyy
+// [TAG] EIP64296
+// [Category] New Feature
+// [Description] Creation and filling of Firmware Performance Data Table
+// is added.
+// [Files] AcpiCore.c, AmiDxeLib.h, BDS.c, DxeMain.c, EfiLib.c,
+// Image.c, S3Resume.c and FirmPerfDataTab.h
+//
+// 107 11/01/11 1:55p Felixp
+// [TAG] EIP 69841 and 71719
+// [Category] Improvement
+// [Description] The AMI customizations are removed from the DXE memory
+// manager.
+// They are replaced with the Memory Type Information HOB used in Tiano
+// projects.
+// This is done to reduces number of descriptors in the memory map
+// and to workaround Windows bug (Windows can't handle memory allocations
+// that happen after the start of the OS loader).
+// [Files] CORE_DXE.sdl, Page.c, BDS.c, DxeIpl.c
+//
+// 106 11/01/11 1:42p Felixp
+// Improvement: Support for logging of the performance information during
+// legacy boot.
+//
+// 105 10/20/11 6:59p Artems
+// Function ConnectConsoles moved to FastBoot module
+//
+// 104 3/16/11 11:41p Felixp
+// Editorial: Several spelling errors in the comments are fixed
+//
+// 103 2/25/11 12:51p Artems
+// EIP 53767 - Velocity boot time above 5 seconds. Added provision to skip
+// USB keyboard initialization
+//
+// 102 2/15/11 6:52p Artems
+// Add possibility to modify ConnectConsoles function list with SDL tokens
+//
+// 101 12/03/10 10:26a Felixp
+//
+// 100 12/03/10 10:23a Felixp
+//
+// 99 12/03/10 10:23a Felixp
+// Bug fix in InitConVars: console-related fields of the systems table
+// were not initialized on headless systems.
+//
+// 98 10/15/10 12:02p Felixp
+// Bug fix in ConnectConsoles function
+//
+// 97 10/01/10 8:02a Felixp
+// ThisImageHandle variabled added (for compatibility with existing
+// modules)
+// Clean up
+//
+// 96 9/29/10 9:21a Felixp
+// Enhancement(EIP 39464) : Implementation of the BdsEntry function is
+// changed.
+// The BdsEntry is now a dispatching function that calls a collection of
+// functions
+// formed by the BDS_CONTROL_FLOW eLink.
+//
+// 95 6/29/10 11:06p Felixp
+// New Boot Options Maintenance Infrastructure.
+// See AMI_Aptio_4.x_Boot_Options_Maintenance_Infrastructure_Porting_Guide
+// _NDA.doc for details.
+//
+// 94 5/07/10 6:00p Felixp
+// Improvement in ConnectDevicePath (EIP 38132): Null pointer check of the
+// input parameter is added
+//
+// 93 3/22/10 10:20a Artems
+// EIP 35562 Fixed boot variable name - hex digits should be in upper case
+//
+// 92 2/03/10 4:34p Oleksiyy
+// Minor bug fix (typecasting)
+//
+// 91 2/02/10 5:45p Felixp
+// Fast Boot related code is removed from BDS. It is now part of the stand
+// alone FastBoot eModule.
+//
+// 90 10/28/09 12:19p Felixp
+// Minor bug fix: check for a NULL pointer is added to the
+// CreateLegacyBootOption function(EIP 28577).
+//
+// 89 10/09/09 6:06p Felixp
+// UEFI 2.1 - related changes (suppot Framework and UEFI HII).
+//
+// 88 10/09/09 11:58a Felixp
+// Code that sets ConOutDev variable is removed. It is not needed. The
+// variable is set by the ConSplitter driver.
+//
+// 87 8/04/09 1:28p Felixp
+// Bug fix: in BuildBootOptionName function.
+// Symptoms: Systems with several boot devices where occasionally handing
+// towards the end of the BDS phase.
+//
+// 86 7/10/09 5:58p Felixp
+// New Boot Option Maintenance Ifrastructure is added
+//
+// 85 7/08/09 8:36a Felixp
+// Bug fix (EIP 23027): Update NVRAM instance of LegacyDevOrder variable
+// when it's modified by the AdjustLegacyDevOrder function.
+//
+// 84 6/26/09 3:08p Felixp
+// ConnectDefaultConOut updated:
+// 1. AGP support is removed
+// 2. Improved on-board device detection logic
+// (EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE attribut is used).
+//
+// 83 5/22/09 9:52a Felixp
+// Minor improvements in AdjustLegacyDevOrder function
+//
+// 82 5/21/09 5:20p Felixp
+// Bug fix in BuildBootOptionName function
+//
+// 81 1/20/09 10:57p Felixp
+//
+// 80 1/20/09 3:30p Felixp
+// Bug fix. EIP 16566. Order of legacy devices within BBS group is reset
+// when configuration changes.
+// Symptoms: Order of legacy devices within BBS group is sometimes reset
+// when bootable devices are added (enabled) or removed (disabled).
+// Here is one of the ways to reproduce the problem:
+// 1. Make sure the following bootable devices are plugged into the
+// system:
+// - Bootable network device (onboard or offboard)
+// - USB flash drive emulated as hard drive
+// - IDE or SATA hard drive
+// 2. Boot to setup.
+// 3. Enable PXE boot using "Lunch PXE OpRom" option on the "Advanced"
+// page.
+// 4. Save the settings, reboot the system, and enter the setup.
+// 5. On the "Boot" page, update "Hard Driver BBS Priorities" to set USB
+// drive as a first boot device.
+// 6. Disable PXE boot using "Lunch PXE OpRom" option on the "Advanced"
+// page.
+// 7. Save the settings, reboot the system, and enter the setup.
+// 8. Enter "Hard Driver BBS Priorities" menu on the "Boot" page.
+// USB drive priority has been reset( it is no longer the first boot
+// device).
+// Details: BDS used index within BBS table to match saved priorities with
+// available boot devices.
+// However, when list of boot devices changes, BBS index may also change.
+// For example, when network boot is enabled, boot option for a network
+// device
+// is inserted into the BBS table prior to the USB drive boot option.
+// As a result, index of the USB drive boot option increases by one
+// and matching against saved boor priority fails.
+// BDS code is updated to save more information about legacy boot devices.
+// For every legacy boot device BDS saves
+// checksum of the device name into the NVRAM (along with device index).
+// When index matching fails, BDS uses saved checksum to find updated BBS
+// index
+// of the boot option.
+//
+// 79 1/14/09 3:52p Felixp
+// BDS updated to signal beginning of the driver connection cycle by
+// installing the protocol.
+//
+// 78 1/05/09 3:02p Felixp
+// Bug fix. EIP 17217
+// Problems during video card switching.
+// Symptoms: Some systems were hanging during after replacement
+// of the video card.
+//
+// 77 11/03/08 5:21p Felixp
+// Do no re-create boot option for the built-in Shell, if Shell is not
+// included into the ROM
+//
+// 76 10/29/08 12:52p Felixp
+// RunDrivers updates: ignore non-active driver options; perform reconnect
+// once
+//
+// 74 10/22/08 4:24p Felixp
+//
+// 73 10/22/08 11:35a Felixp
+// 1. Code to recreate deleted boot option for the built-in Shell is
+// added(EIP 15524).
+// 2. Processing of the DriverOrder list is added
+// 3. Clean up
+//
+// 72 10/21/08 5:56p Felixp
+// Multi-language support added to UEFI boot options implementation
+//
+// 71 10/21/08 3:30p Felixp
+// BuildBootOptionName function improvements and bug fixes
+//
+// 70 10/17/08 3:46p Yakovlevs
+// Support for UEFI boot options added
+//
+// 69 10/10/08 4:25p Felixp
+// - Improved handling of console devices
+// - Clean up
+//
+// 68 10/09/08 5:07p Felixp
+// Bug fixes:
+// - Support for systems with no console devices.
+// If no console input or output devices are available,
+// system table is populated with the fake ConIn/ConOut handles
+// and protocol interface pointers.
+// This prevents potential failures caused by the NULL pointers in the
+// system table.
+// - Early Console device initialization during the first boot(EIP 13459).
+// During the very first boot after the firmware update,
+// console devices were initialized towards the end of the boot.
+// The logic has been updated to initialize default console devices
+// at the beginning of the BDS connection cycle.
+// - Serial Redirection could not be enabled, if
+// it was disabled by default(EIP 15565)
+//
+// 67 9/30/08 11:07p Felixp
+// Performance measurement support: callback to publish performance data
+// for OS usage added (the callback is generated by TSE).
+//
+// 66 6/06/08 11:00a Felixp
+// 1. Performance measurement support is added
+// 2. Support for boot with minimal configuration is added
+// 3. Code is reformatted in accordance with the coding standards
+//
+// 65 5/06/08 10:07a Felixp
+//
+// 64 12/17/07 4:07p Felixp
+// Signal protocol event before handing control over to TSE
+//
+// 63 11/08/07 4:51p Felixp
+// Code updated to compile and work without CSM.
+//
+// 62 10/26/07 2:36p Felixp
+// New FW based load file protocl is added.
+// This protocol is used to load FW based EFI applications such as built
+// in Shell.
+//
+// 61 10/17/07 11:28a Felixp
+// Update in InitBbs routine: Delete LegacyDevOrder when no legacy devices
+// are found.
+// This fixes hang in AMITSE when no bootable devices are present.
+//
+// 60 8/31/07 1:55p Felixp
+// Updated to support new location of AMIPostMgr.h. It is moved from
+// Core/em/AMITSE into Include/Protocol
+//
+// 59 8/07/07 2:36p Felixp
+// Additionanal Status Codes added
+//
+// 58 4/10/07 9:34a Felixp
+//
+// 55 3/18/07 2:30p Felixp
+// Initialization of Lang & LangCodes variables removed
+// (it is done in Setup now)
+//
+// 54 2/28/07 7:32p Felixp
+//
+// 52 2/26/07 6:12p Felixp
+// Bug fix in SetBbsPriorities.
+//
+// 51 2/13/07 9:18a Felixp
+// MRE Handshake protocol renamed to AMI POST Manager protocol
+// (MreHandshake.h removed from Core Protocols and added to AMITSE module
+// as AMIPostMgr.h)
+//
+// 50 2/12/07 1:45p Felixp
+// 1. Correct handling of disabled legacy BBS options
+// 2. Name of the legacy device removed from legacy boot option because it
+// is not needed (AMITSE does not use it)
+// 3. Clean up in ConnectDevicePath
+//
+// 49 12/29/06 3:00p Felixp
+// Console initialization logic changed
+//
+// 48 10/30/06 6:03p Felixp
+// Updated to be complient with HII Spec. 0.92 (used to be 0.91)
+//
+// 47 10/13/06 4:43p Felixp
+// Beep when ConIn available
+//
+// 46 10/13/06 9:27a Felixp
+// Patch for disconnected FDD moved to a proper place
+//
+// 45 10/12/06 9:42a Felixp
+// UEFI2.0 compliance: use CreateReadyToBootEvent instead of CreateEvent
+//
+// 44 9/29/06 3:52p Pavell
+// Added processing and dispatching capsule
+//
+// 42 5/23/06 4:17a Felixp
+// Patch for disconnection of the Floppy Controller added
+//
+// 41 5/19/06 10:45p Felixp
+// Device Path code updated to use NEXT_NODE/NODE_LENGTH/SET_NODE_LENGTH
+// macros to remove direct access to the Length field
+//
+// 40 3/13/06 10:07a Felixp
+//
+// 39 12/22/05 11:25a Felixp
+//
+// 38 11/08/05 4:07a Felixp
+// Support for TSE notifications added
+//
+// 37 11/07/05 10:34a Felixp
+// Boot with minimum configuration suuport
+//
+// 36 9/29/05 4:36p Robert
+//
+// 35 8/25/05 11:47a Felixp
+// Code added to start Standard ConIn devices (PS2, USB) early
+//
+// 34 8/25/05 11:41a Felixp
+//
+// 33 8/22/05 5:29p Felixp
+// Invoke dispatcher before boot
+//
+// 32 7/29/05 6:52p Felixp
+// improvement in InitBbs: correct handling of LegacyDevOrder shorter then
+// 6 bytes
+//
+// 3 7/20/05 8:03p Felixp
+// workaround for password support
+//
+// 28 7/15/05 7:16p Felixp
+// CONSOLE_DEVICES_STARTED_PROTOCOL_GUID added.
+// BDS uses it to notify Splitter that Console Devices have been started.
+// Once Splitter receives notification, it will install ConIn and ConOut
+// in System Table
+//
+// 27 7/14/05 12:10a Felixp
+// BBS support
+//
+// 25 5/24/05 2:55p Felixp
+// Boot menu logic moved to SetupEngine.
+// Now BDS just gives control to MREHandshake
+//
+// 24 4/28/05 1:06p Felixp
+// bug fix in InitConVars
+//
+// 23 4/25/05 12:12p Felixp
+// AddBootOption - loader options can now be passed
+//
+// 21 4/08/05 3:02p Felixp
+// SignalReadyToBoot added
+//
+// 20 4/08/05 7:39a Felixp
+// Boot Menu implemented
+//
+// 19 4/02/05 3:24p Felixp
+//
+// 18 3/28/05 7:03p Felixp
+// DrawBmp function added
+//
+// 15 3/17/05 7:51p Felixp
+// pBootScript->CloseTable commented out
+//
+// 14 3/15/05 2:55p Felixp
+// 1. Code to initialize global EFI variables added
+// 2. Code to Close boot script table and save the address to NVRAM added
+//
+// 13 2/14/05 10:40a Felixp
+// Off-board video started before on-board
+//
+// 12 2/11/05 6:05p Felixp
+// Code optimized by using DPAddNode instead of DPAdd
+// Logic to set video card priorities added(from hi ti lo):
+// AGP->on board PCI ->off board PCI
+//
+// 11 2/07/05 5:21p Felixp
+// function GetEfiVariable moved to AmiDxeLib
+//
+// 10 2/03/05 8:07p Felixp
+// ConnectDevicePath change: now last node connected recursively
+//
+// 9 2/03/05 7:58p Felixp
+//
+// 8 2/03/05 7:45p Felixp
+// Logic to initialize Console variables added
+//
+// 7 2/01/05 4:24p Felixp
+// 1 .ConnectDevicePath fixed (before it didn't connect last node in the
+// device path)
+// 2. REAY to BOOT event signaled
+//
+// 6 1/25/05 3:27p Felixp
+// if GSE absent restart shell if it returns
+//
+// 5 1/19/05 7:01p Felixp
+//
+// 3 1/18/05 3:21p Felixp
+// PrintDebugMessage renamed to Trace
+//
+// 2 1/10/05 5:10p Felixp
+// Patches for Intel CSM and Intel Terminal driver disabled
+//
+// 28 12/23/04 9:29a Felixp
+// ArchProtocols moved to Include\Protocols
+//
+// 27 12/21/04 4:53p Markw
+// Modified device path defines for consistency.
+//
+// 26 12/21/04 4:21p Markw
+// Renamed hardware device path definition for consistency.
+//
+// 21 12/01/04 3:24p Felixp
+// GSE support added
+//
+// 20 8/03/04 6:46p Felixp
+// SetVariable for "Lang" and "LangCodes" moved to do it before all
+// drivers are connected
+//
+// 15 7/16/04 3:57p Felixp
+// Changes to support both 7f and ff values for the device path end type
+//
+// 1 3/30/04 3:26p Felixp
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: BDS.c
+//
+// Description: Implementation of the BDS architectural protocol
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+#include "BootOptions.h"
+#include <Protocol/BDS.h>
+#include <Protocol/PciRootBridgeIo.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/SimpleTextIn.h>
+#include <Protocol/SimpleTextOut.h >
+#include <Protocol/LoadedImage.h>
+#include <Protocol/ConsoleControl.h>
+#include <Protocol/AMIPostMgr.h>
+#include <Protocol/LoadFile.h>
+#include <DXE.h>
+#include <HOB.h>
+#include <Guid/MemoryTypeInformation.h>
+
+/**************************** TYPES ***********************************/
+
+/***************** FUNCTION DECLARATIONS *****************************/
+//this funciton is created from InitList.c template file during build process
+VOID InitParts2(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable);
+
+//Local functions
+VOID BdsEntry (IN EFI_BDS_ARCH_PROTOCOL *This);
+
+EFI_STATUS FwLoadFile (
+ IN EFI_LOAD_FILE_PROTOCOL *This, IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
+ IN BOOLEAN BootPolicy, IN OUT UINTN *BufferSize,
+ IN VOID *Buffer OPTIONAL
+);
+
+/**************************** CONSTANTS *******************************/
+#define BDS_ALL_DRIVERS_CONNECTED_PROTOCOL_GUID \
+ {0xdbc9fd21, 0xfad8, 0x45b0, 0x9e, 0x78, 0x27, 0x15, 0x88, 0x67, 0xcc, 0x93}
+// {3AA83745-9454-4f7a-A7C0-90DBD02FAB8E}
+#define BDS_CONNECT_DRIVERS_PROTOCOL_GUID \
+ { 0x3aa83745, 0x9454, 0x4f7a, { 0xa7, 0xc0, 0x90, 0xdb, 0xd0, 0x2f, 0xab, 0x8e } }
+// {8DB699CC-BC81-41e2-AAC6-D81D5300D759}
+#define PARTITION_VARIABLE_GUID\
+ { 0x8db699cc, 0xbc81, 0x41e2, { 0xaa, 0xc6, 0xd8, 0x1d, 0x53, 0x0, 0xd7, 0x59 } }
+// {5023B95C-DB26-429b-A648-BD47664C8012}
+#define AMI_MEDIA_DEVICE_PATH_GUID \
+ { 0x5023b95c, 0xdb26, 0x429b, { 0xa6, 0x48, 0xbd, 0x47, 0x66, 0x4c, 0x80, 0x12 } }
+
+extern EFI_GUID gEfiBdsArchProtocolGuid; // = EFI_BDS_ARCH_PROTOCOL_GUID;
+extern EFI_GUID gEfiDevicePathProtocolGuid ;//= EFI_DEVICE_PATH_PROTOCOL_GUID;
+extern EFI_GUID gEfiFirmwareVolume2ProtocolGuid; // = EFI_FIRMWARE_VOLUME_PROTOCOL_GUID;
+extern EFI_GUID gEfiLoadedImageProtocolGuid; //=EFI_LOADED_IMAGE_PROTOCOL_GUID;
+extern EFI_GUID gEfiPciIoProtocolGuid; // = EFI_PCI_IO_PROTOCOL_GUID;
+extern EFI_GUID gEfiBlockIoProtocolGuid;
+extern EFI_GUID gEfiLoadFileProtocolGuid;
+extern EFI_GUID gEfiSimpleFileSystemProtocolGuid;
+//defined in BdsBoard.c
+extern EFI_GUID SetupEnterProtocolGuid;
+extern EFI_GUID SecondBootOptionProtocolGuid;
+extern EFI_GUID BeforeBootProtocolGuid;
+extern EFI_GUID BeforeLegacyBootProtocolGuid;
+extern EFI_GUID *DefaultAppFfsGuidPtr;
+
+extern BDS_CONTROL_FLOW_FUNCTION *BdsControlFlowFunctions[];
+extern CHAR8 *BdsControlFlowFunctionNames[];
+
+EFI_GUID EfiVariableGuid = EFI_GLOBAL_VARIABLE;
+EFI_GUID AmiPostMgrProtocolGuid=AMI_POST_MANAGER_PROTOCOL_GUID;
+EFI_GUID ConInStartedProtocolGuid = CONSOLE_IN_DEVICES_STARTED_PROTOCOL_GUID;
+EFI_GUID ConOutStartedProtocolGuid = CONSOLE_OUT_DEVICES_STARTED_PROTOCOL_GUID;
+EFI_GUID BdsAllDriversConnectedProtocolGuid = BDS_ALL_DRIVERS_CONNECTED_PROTOCOL_GUID;
+EFI_GUID BdsConnectDriversProtocolGuid = BDS_CONNECT_DRIVERS_PROTOCOL_GUID;
+EFI_GUID PartitionVariableGuid = PARTITION_VARIABLE_GUID;
+
+EFI_BDS_ARCH_PROTOCOL BDS = {&BdsEntry};
+
+/**************************** VARIABLES *******************************/
+//externals defined in BdsBoard.c
+extern UINT16 DefaultTimeout;
+extern BOOLEAN QuietBoot;
+extern STRING_REF StrToken[];
+
+// Global Variables
+EFI_LOAD_FILE_PROTOCOL FwLoadFileInterface = {FwLoadFile};
+
+struct {
+ VENDOR_DEVICE_PATH Media;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} FwLoadFileDp = {
+ {
+ {
+ MEDIA_DEVICE_PATH, MEDIA_VENDOR_DP,
+ sizeof(VENDOR_DEVICE_PATH)
+ },
+ AMI_MEDIA_DEVICE_PATH_GUID
+ },
+ {
+ END_DEVICE_PATH, END_ENTIRE_SUBTYPE,
+ sizeof(EFI_DEVICE_PATH_PROTOCOL)
+ }
+};
+
+EFI_HANDLE LpcHandle = NULL;
+EFI_DEVICE_PATH_PROTOCOL *LpcDevicePath = NULL;
+
+VOID ConnectDevicePath(IN EFI_DEVICE_PATH_PROTOCOL *pPath)
+{
+ EFI_HANDLE Handle;
+ EFI_STATUS Status;
+
+ if (pPath == NULL) return;
+ while (TRUE)
+ {
+ EFI_DEVICE_PATH_PROTOCOL *pLastPath=NULL, *pFirstNode = pPath;
+ if (isEndNode(pPath))
+ {
+ if (pPath->SubType == END_ENTIRE_SUBTYPE) break;
+ pPath++;
+ continue;
+ }
+ while(TRUE){
+ EFI_DEVICE_PATH_PROTOCOL *Dp;
+ UINT8 SubType;
+
+ pPath = pFirstNode;
+
+ //LocateDevicePath can not work with multi-instance device paths.
+ //Prepare single instance device path and call LocateDevicePath
+ Dp = DPGetEndNode(pPath);
+ SubType = Dp->SubType;
+ Dp->SubType=END_ENTIRE_SUBTYPE;
+ Status = pBS->LocateDevicePath(&gEfiDevicePathProtocolGuid, &pPath, &Handle);
+ Dp->SubType=SubType;
+ if (EFI_ERROR(Status)) break;
+
+ if (isEndNode(pPath))
+ {
+ //Last time let's do it recursively
+ pBS->ConnectController(Handle,NULL,NULL,TRUE);
+ break;
+ }
+ if (pPath==pLastPath) break;
+ pLastPath = pPath;
+ if (EFI_ERROR(pBS->ConnectController(Handle,NULL,pPath,FALSE))) break;
+ }
+ while (!isEndNode(pPath))
+ pPath = NEXT_NODE(pPath);
+ }
+}
+
+EFI_DEVICE_PATH_PROTOCOL* AddDevicePath(EFI_DEVICE_PATH_PROTOCOL *pDp1, EFI_DEVICE_PATH_PROTOCOL *pDp2)
+{
+ if (!pDp2) return pDp1;
+ if (!pDp1)
+ {
+ return DPCopy(pDp2);
+ }
+ else
+ {
+ pDp2 = DPAddInstance(pDp1,pDp2);
+ pBS->FreePool(pDp1);
+ return pDp2;
+ }
+}
+
+EFI_STATUS GetPciHandlesByClass(
+ UINT8 Class, UINT8 SubClass, UINTN *NumberOfHandles, EFI_HANDLE **HandleBuffer
+){
+ EFI_STATUS Status;
+ EFI_HANDLE *Handle;
+ UINTN Number,i;
+
+ if (!NumberOfHandles || !HandleBuffer) return EFI_INVALID_PARAMETER;
+ //Get a list of all PCI devices
+ Status = pBS->LocateHandleBuffer(
+ ByProtocol,&gEfiPciIoProtocolGuid, NULL, &Number, &Handle
+ );
+ if (EFI_ERROR(Status)) return Status;
+ *NumberOfHandles = 0;
+ for(i=0; i<Number; i++)
+ {
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT8 PciClass[4];
+ Status=pBS->HandleProtocol(Handle[i],&gEfiPciIoProtocolGuid,&PciIo);
+ if (EFI_ERROR(Status)) continue;
+ Status=PciIo->Pci.Read(PciIo, EfiPciIoWidthUint32, PCI_REV_ID_OFFSET, 1, &PciClass);
+ if( PciClass[3]==Class && PciClass[2]==SubClass)
+ Handle[(*NumberOfHandles)++] = Handle[i];
+ }
+ if (*NumberOfHandles == 0){
+ pBS->FreePool(Handle);
+ return EFI_NOT_FOUND;
+ }
+ *HandleBuffer = Handle;
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS InitSystemVariable(
+ IN CHAR16 *NameStr, IN UINTN DataSize, IN VOID *Data
+)
+{
+ UINTN Size = 0;
+ EFI_STATUS Status;
+ Status = pRS->GetVariable(NameStr, &EfiVariableGuid, NULL, &Size, NULL);
+ if (Status==EFI_NOT_FOUND)
+ {
+ return pRS->SetVariable(
+ NameStr, &EfiVariableGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ DataSize, Data);
+ }
+ return EFI_SUCCESS;
+}
+
+static EFI_HANDLE *RootHandles;
+static UINTN NumberOfHandles;
+VOID ConnectEverything()
+{
+ UINTN i;
+ for(i=0; i<NumberOfHandles; i++) pBS->ConnectController(RootHandles[i],NULL,NULL,TRUE);
+/////////////////////////////////////////
+//TODO: Ugly patch for the Floppy Controller. Find the better place for it!
+// It is necessary to Disconnect Floppy Device Handle when Floppy Drive is not connected.
+// This is necessary to disable Floppy Device in the Super I/O
+// and eliminate BBS Floppy boot option.
+// It was previously done (In Core 4.0) by the Floppy Controller driver.
+// However, EDK DXE Core (DxeMain) crashes during the
+// DisconnectController operation performed from within the Start function.
+// Because of that, the Floppy Controller driver code is commented out
+// and this patch is created.
+// If you remove this code, you should also remove
+// LpcHandle & LpcDevicePath global variables.
+// They are only used to implement this patch.
+ if (LpcDevicePath)
+ {
+ EFI_HANDLE Handle;
+ ACPI_HID_DEVICE_PATH FloppyCtrl = {
+ {ACPI_DEVICE_PATH,ACPI_DP,sizeof(ACPI_HID_DEVICE_PATH)},
+ EISA_PNP_ID(0x0604),0
+ };
+ EFI_DEVICE_PATH_PROTOCOL *ChildDp=DPAddNode(LpcDevicePath, &FloppyCtrl.Header);
+ EFI_STATUS Status=pBS->LocateDevicePath(&gEfiDevicePathProtocolGuid, &ChildDp, &Handle);
+ if (!EFI_ERROR(Status) && isEndNode(ChildDp))
+ {
+ VOID* pDummy;
+ Status = pBS->HandleProtocol(Handle,&gEfiBlockIoProtocolGuid,&pDummy);
+ if (EFI_ERROR(Status)) pBS->DisconnectController(LpcHandle,NULL,Handle);
+ }
+ }
+}
+VOID DisconnectEverything()
+{
+ UINTN i;
+ for(i=0; i<NumberOfHandles; i++) pBS->DisconnectController(RootHandles[i],NULL,NULL);
+}
+
+VOID ReadyToBoot(UINT16 OptionNumber)
+{
+ //signal EFI_EVENT_SIGNAL_READY_TO_BOOT
+ EFI_EVENT ReadToBootEvent;
+ EFI_STATUS Status;
+ if (OptionNumber!= (UINT16)-1)
+ pRS->SetVariable(
+ L"BootCurrent", &EfiVariableGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ sizeof(OptionNumber), &OptionNumber
+ );
+ Status = CreateReadyToBootEvent(
+ TPL_CALLBACK, NULL, NULL, &ReadToBootEvent
+ );
+ if (!EFI_ERROR(Status)) {
+ pBS->SignalEvent(ReadToBootEvent);
+ pBS->CloseEvent(ReadToBootEvent);
+ }
+}
+
+#if CSM_SUPPORT
+EFI_STATUS BootLegacy(EFI_DEVICE_PATH_PROTOCOL *Dp, UINT16 Number)
+{
+ UINTN i, Old=-1, New, Priority=-1;
+ BBS_BBS_DEVICE_PATH *BbsEntry = (BBS_BBS_DEVICE_PATH*)Dp;
+ EFI_STATUS Status;
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
+ UINT16 HddCount;
+ UINT16 BbsCount;
+ HDD_INFO *HddInfo;
+ BBS_TABLE *BbsTable;
+
+ // Legacy Boot
+ Status = pBS->LocateProtocol(&gEfiLegacyBiosProtocolGuid, NULL, &LegacyBios);
+ if(EFI_ERROR(Status)) return Status;
+ LegacyBios->GetBbsInfo(LegacyBios, &HddCount, &HddInfo, &BbsCount, &BbsTable);
+ if (!BbsCount) return EFI_NOT_FOUND;
+ for(i=0; i<BbsCount; i++)
+ {
+ if ( // !BbsTable[i].StatusFlags.Enabled
+ /*||*/ BbsTable[i].BootPriority==BBS_IGNORE_ENTRY
+ || BbsTable[i].BootPriority==BBS_DO_NOT_BOOT_FROM
+ ) continue;
+ if (!BbsTable[i].BootPriority && Old==-1) Old=i;
+ if ( BbsTable[i].DeviceType==BbsEntry->DeviceType
+ && BbsTable[i].BootPriority < Priority
+ )
+ {
+ Priority = BbsTable[i].BootPriority;
+ New = i;
+ }
+ }
+ if (Old!=-1) BbsTable[Old].BootPriority=BbsTable[New].BootPriority;
+ BbsTable[New].BootPriority=0;
+ ReadyToBoot(Number);
+ return LegacyBios->LegacyBoot(LegacyBios,(BBS_BBS_DEVICE_PATH*)Dp,0,0);
+}
+#endif
+
+EFI_STATUS BootEfi(EFI_DEVICE_PATH_PROTOCOL *Dp, UINT16 Number, VOID *pOptions, UINT32 Size)
+{
+ EFI_STATUS Status;
+ EFI_HANDLE Handle;
+ EFI_LOADED_IMAGE_PROTOCOL *Image;
+ Status=pBS->LoadImage(TRUE, TheImageHandle, Dp, NULL, 0, &Handle);
+ if (EFI_ERROR(Status)) return Status;
+ Status=pBS->HandleProtocol(Handle,&gEfiLoadedImageProtocolGuid,&Image);
+ if (!EFI_ERROR(Status) && Size)
+ {
+ Image->LoadOptionsSize = Size;
+ Image->LoadOptions = pOptions;
+ }
+ ReadyToBoot(Number);
+ return pBS->StartImage(Handle, NULL, NULL);
+}
+
+EFI_STATUS Boot(EFI_LOAD_OPTION *BootOption, UINT16 Number, UINTN Size)
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *Dp;
+ Dp = (EFI_DEVICE_PATH_PROTOCOL*)
+ ( //skip the header
+ (UINT8*)(BootOption+1)
+ //skip the string
+ +(Wcslen((CHAR16*)(BootOption+1))+1)*sizeof(CHAR16)
+ );
+ if (Dp->Type!=BBS_DEVICE_PATH)
+ {
+ UINT8 *pOptions = (UINT8*)Dp+BootOption->FilePathListLength;
+ Status=BootEfi(Dp,Number,pOptions, (UINT32)((UINT8*)BootOption+Size-pOptions));
+ }
+#if CSM_SUPPORT
+ else
+ {
+ Status=BootLegacy(Dp,Number);
+ }
+#endif
+ return Status;
+}
+
+VOID RunDrivers(){
+ EFI_LOAD_OPTION *DriverOption = NULL; //buffer for DriverXXX variables
+ UINT16 *DriverOrder = NULL; //old(saved) Driver Order
+ UINTN DriverOrderSize = 0; //size of DriverOrder Variable
+ EFI_STATUS Status;
+ UINTN Size,i;
+ BOOLEAN ReconnectAll = FALSE;
+
+ //================== Init Driver Order buffers ========================//
+ Status = GetEfiVariable(L"DriverOrder", &EfiVariableGuid, NULL, &DriverOrderSize, &DriverOrder);
+ if (EFI_ERROR(Status)) return;
+ //===================================================================//
+ // Start drivers refered to by DriverXXXX //
+ //===================================================================//
+ for(i=0; i<DriverOrderSize/sizeof(UINT16); i++){
+ CHAR16 DriverStr[9];
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_HANDLE Handle;
+ EFI_LOADED_IMAGE_PROTOCOL *Image;
+ UINT32 SizeOfOptions;
+ UINT8 *Options;
+
+ // Get Driver Option
+ Swprintf(DriverStr,L"Driver%04X",DriverOrder[i]);
+ Status=GetEfiVariable(DriverStr, &EfiVariableGuid, NULL, &Size, &DriverOption);
+ if ( EFI_ERROR(Status)
+ || (DriverOption->Attributes & LOAD_OPTION_ACTIVE)==0
+ ) continue;
+
+ DevicePath = (EFI_DEVICE_PATH_PROTOCOL*)
+ ( //skip the header
+ (UINT8*)(DriverOption+1)
+ //skip the string
+ +(Wcslen((CHAR16*)(DriverOption+1))+1)*sizeof(CHAR16)
+ );
+ Status=pBS->LoadImage(
+ TRUE, TheImageHandle, DevicePath, NULL, 0, &Handle
+ );
+ if (EFI_ERROR(Status)) continue;
+ Status=pBS->HandleProtocol(
+ Handle,&gEfiLoadedImageProtocolGuid,&Image
+ );
+ Options = (UINT8*)DevicePath+DriverOption->FilePathListLength;
+ SizeOfOptions=(UINT32)((UINT8*)DriverOption+Size-Options);
+ if (!EFI_ERROR(Status)&& SizeOfOptions!=0){
+ Image->LoadOptionsSize = SizeOfOptions;
+ Image->LoadOptions = Options;
+ }
+ Status=pBS->StartImage(Handle, NULL, NULL);
+ if ( !EFI_ERROR(Status)
+ && (DriverOption->Attributes & LOAD_OPTION_FORCE_RECONNECT)!=0
+ ) ReconnectAll=TRUE;
+ }
+ pBS->FreePool(DriverOption);
+ pBS->FreePool(DriverOrder);
+ if (ReconnectAll){
+ DisconnectEverything();
+ ConnectEverything();
+ }
+}
+
+EFI_DEVICE_PATH_PROTOCOL* DiscoverPartition(
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+){
+ UINTN Count,i;
+ EFI_HANDLE *Handle;
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *PartDevicePath=NULL;
+ HARDDRIVE_DEVICE_PATH* BootParitionDevicePath = (HARDDRIVE_DEVICE_PATH*)DevicePath;
+ //get list of available Block I/O devices
+ Status=pBS->LocateHandleBuffer(ByProtocol,&gEfiBlockIoProtocolGuid,NULL,&Count,&Handle);
+ if (EFI_ERROR(Status)) return NULL;
+
+ for(i=0;i<Count;i++){
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+ EFI_DEVICE_PATH_PROTOCOL *PartitionDevicePath;
+ HARDDRIVE_DEVICE_PATH* PartitionNode;
+ Status = pBS->HandleProtocol(Handle[i],&gEfiBlockIoProtocolGuid,&BlockIo);
+ if (EFI_ERROR(Status)) continue;
+ // if this is not partition, continue
+ if (!BlockIo->Media->LogicalPartition) continue;
+ Status = pBS->HandleProtocol(Handle[i],&gEfiDevicePathProtocolGuid,&PartitionDevicePath);
+ if (EFI_ERROR(Status)) continue;
+ // Get last node of the device path. It should be partition node
+ PartitionNode = (HARDDRIVE_DEVICE_PATH*)DPGetLastNode(PartitionDevicePath);
+ //Check if our partition matches Boot partition
+ if ( PartitionNode->Header.Type!=MEDIA_DEVICE_PATH
+ || PartitionNode->Header.SubType!=MEDIA_HARDDRIVE_DP
+ ) continue;
+ if ( PartitionNode->PartitionNumber==BootParitionDevicePath->PartitionNumber
+ && PartitionNode->SignatureType==BootParitionDevicePath->SignatureType
+ && !MemCmp(PartitionNode->Signature,BootParitionDevicePath->Signature,16)
+ ){
+ //Match found
+ PartDevicePath = PartitionDevicePath;
+ break;
+ }
+ }
+ pBS->FreePool(Handle);
+ return PartDevicePath;
+}
+
+EFI_STATUS FwLoadFile (
+ IN EFI_LOAD_FILE_PROTOCOL *This, IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
+ IN BOOLEAN BootPolicy, IN OUT UINTN *BufferSize,
+ IN VOID *Buffer OPTIONAL
+){
+ EFI_GUID *FileGuid;
+ UINTN FvCount,i;
+ EFI_HANDLE *FvHandle;
+ EFI_STATUS Status;
+
+ if (!BufferSize || *BufferSize && !Buffer)
+ return EFI_INVALID_PARAMETER;
+ if (!FilePath || isEndNode(FilePath)){
+ if (BootPolicy){
+ if (DefaultAppFfsGuidPtr==NULL) return EFI_UNSUPPORTED;
+ else FileGuid = DefaultAppFfsGuidPtr;
+ }else{
+ return EFI_INVALID_PARAMETER;
+ }
+ }else{
+ if ( FilePath->Type!=MEDIA_DEVICE_PATH
+ || FilePath->SubType!=MEDIA_FV_FILEPATH_DP
+ ) return EFI_INVALID_PARAMETER;
+ FileGuid = &((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH*)FilePath)->NameGuid;
+ }
+ //If Buffer is NULL, ReadSection will allocate the memory.
+ //That's not what we need.
+ //Initialize Buffer with some value.
+ //We don't care what value is that because *BufferSize is 0 anyway,
+ //so nothing will be copied into the buffer.
+ //We know that *BufferSize is always 0 for NULL buffer because we checked that
+ //at the beginning of the routine.
+ if (!Buffer) Buffer = (VOID*)1;
+ Status=pBS->LocateHandleBuffer(ByProtocol, &gEfiFirmwareVolume2ProtocolGuid, NULL, &FvCount, &FvHandle);
+ if (EFI_ERROR(Status)) return Status;
+ Status=EFI_NOT_FOUND;
+ for(i=0; i<FvCount; i++)
+ {
+ EFI_FIRMWARE_VOLUME_PROTOCOL *Fv;
+ UINT32 AuthStatus;
+ Status = pBS->HandleProtocol(FvHandle[i], &gEfiFirmwareVolume2ProtocolGuid, &Fv);
+ if (EFI_ERROR(Status)) continue;
+ Status = Fv->ReadSection(
+ Fv, FileGuid, EFI_SECTION_PE32,
+ 0, &Buffer, BufferSize, &AuthStatus
+ );
+ if (!EFI_ERROR(Status)){
+ if (Status==EFI_WARN_BUFFER_TOO_SMALL) Status=EFI_BUFFER_TOO_SMALL;
+ break;
+ }
+ }
+ pBS->FreePool(FvHandle);
+ return Status;
+}
+
+VOID InstallFwLoadFile(){
+ EFI_HANDLE Handle=NULL;
+ pBS->InstallMultipleProtocolInterfaces(
+ &Handle,
+ &gEfiLoadFileProtocolGuid, &FwLoadFileInterface,
+ &gEfiDevicePathProtocolGuid, &FwLoadFileDp,
+ NULL
+ );
+}
+
+//----------------------------------------------------------------------------
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SignalProtocolEvent
+//
+// Description: Internal function that installs/uninstall protocol
+// with a specified GUID and NULL interface.
+// Such protocols can be used as event signaling mechanism.
+//
+// Input: ProtocolGuid Pointer to the protocol GUID
+//
+// Output: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID SignalProtocolEvent(IN EFI_GUID *ProtocolGuid){
+ EFI_HANDLE Handle = NULL;
+ pBS->InstallProtocolInterface (
+ &Handle, ProtocolGuid, EFI_NATIVE_INTERFACE,NULL
+ );
+ pBS->UninstallProtocolInterface (
+ Handle, ProtocolGuid, NULL
+ );
+}
+
+#ifdef EFI_DXE_PERFORMANCE
+VOID SavePerformanceData(IN EFI_EVENT Event, IN VOID *Context){
+ PERF_END (0, BDS_TOK, NULL, 0) ;
+ WriteBootToOsPerformanceData();
+}
+#endif
+
+VOID SaveFpdtDataOnLegacyBoot(IN EFI_EVENT Event, IN VOID *Context){
+ AmiFillFpdt (FillOsLoaderStartImageStart); // Fill OsLoaderStartImageStart field in FPDT
+}
+
+VOID SignalConnectDriversEvent(){
+ PROGRESS_CODE(DXE_BDS_CONNECT_DRIVERS);
+ SignalProtocolEvent(&BdsConnectDriversProtocolGuid);
+}
+
+VOID ConnectRootBridgeHandles(){
+ EFI_HANDLE *Handle;
+ UINTN NumberOfHandles;
+ EFI_STATUS Status;
+ UINTN i;
+
+ //Enumerate PCI Bus and Create handles for all PCI devices
+ Status = pBS->LocateHandleBuffer(
+ ByProtocol,&gEfiPciRootBridgeIoProtocolGuid, NULL,
+ &NumberOfHandles, &Handle
+ );
+ if (EFI_ERROR(Status)) return;
+ for(i=0; i<NumberOfHandles; i++)
+ pBS->ConnectController(Handle[i],NULL,NULL,FALSE);
+ pBS->FreePool(Handle);
+}
+
+VOID ReportConnectConOutProgressCode(){
+ PROGRESS_CODE(DXE_CON_OUT_CONNECT);
+}
+
+VOID ConnectVgaConOut(){
+ EFI_STATUS Status;
+ EFI_HANDLE *Handle;
+ UINTN Number,i;
+ EFI_DEVICE_PATH_PROTOCOL *OnBoard=NULL, *OffBoard=NULL;
+ UINT64 PciAttributes;
+
+ //Get a list of all PCI devices
+ Status = pBS->LocateHandleBuffer(
+ ByProtocol,&gEfiPciIoProtocolGuid, NULL, &Number, &Handle
+ );
+ if (EFI_ERROR(Status)) return;
+ for(i=0; i<Number; i++)
+ {
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_DEVICE_PATH_PROTOCOL *Dp;
+ UINT8 PciClass;
+ Status=pBS->HandleProtocol(Handle[i],&gEfiPciIoProtocolGuid,&PciIo);
+ if (EFI_ERROR(Status)) continue;
+ Status=PciIo->Pci.Read(PciIo, EfiPciIoWidthUint8, 0xB, 1, &PciClass);
+ if (EFI_ERROR(Status)) continue;
+ if (PciClass!=PCI_CL_DISPLAY) continue;
+ Status=pBS->HandleProtocol(Handle[i],&gEfiDevicePathProtocolGuid,&Dp);
+ if (EFI_ERROR(Status)) continue;
+ //We found Display adapter
+ // Check if this is on-board device
+ //(EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE is set).
+ Status = PciIo->Attributes(
+ PciIo, EfiPciIoAttributeOperationGet, 0, &PciAttributes
+ );
+ if ( !EFI_ERROR(Status)
+ && (PciAttributes & EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE)
+ ) OnBoard = AddDevicePath(OnBoard,Dp);
+ else OffBoard = AddDevicePath(OffBoard,Dp);
+ }
+ pBS->FreePool(Handle);
+ //Offboard has a higher priority
+ OffBoard = AddDevicePath(OffBoard,OnBoard);
+ if (OffBoard)
+ {
+ ConnectDevicePath(OffBoard);
+ pBS->FreePool(OffBoard);
+ }
+}
+
+VOID ConnecConsoleVariable(CHAR16* ConVar){
+ EFI_DEVICE_PATH_PROTOCOL *ConPath=NULL;
+ UINTN Size = 0;
+
+ if (EFI_ERROR(
+ GetEfiVariable(ConVar, &EfiVariableGuid, NULL, &Size, &ConPath)
+ )) return;
+
+ //Connect all active console devices
+ ConnectDevicePath(ConPath);
+ pBS->FreePool(ConPath);
+}
+
+VOID InstallConsoleStartedProtocol(
+ CHAR16* ConDevVar, EFI_GUID* ProtocolGuid
+){
+ UINTN Size = 0;
+ VOID *Interface;
+
+ //Signal to Console Splitter that all console devices have been started
+ //if at least one console device exists (ConDev variable exists)
+ if (ConDevVar!=NULL && pRS->GetVariable(
+ ConDevVar, &EfiVariableGuid, NULL, &Size, NULL
+ ) == EFI_NOT_FOUND
+ ) return;
+ //if the protocol is already installed, return
+ if (!EFI_ERROR(pBS->LocateProtocol(ProtocolGuid, NULL, &Interface)))
+ return;
+ pBS->InstallProtocolInterface(
+ &TheImageHandle, ProtocolGuid, EFI_NATIVE_INTERFACE, NULL
+ );
+}
+
+VOID ConnectConOutVariable(){
+ ConnecConsoleVariable(L"ConOut");
+}
+
+VOID InstallConOutStartedProtocol(){
+ InstallConsoleStartedProtocol(L"ConOutDev", &ConOutStartedProtocolGuid);
+}
+
+VOID ReportConnectConInProgressCode(){
+ PROGRESS_CODE(DXE_CON_IN_CONNECT);
+}
+
+VOID ConnectPs2ConIn(){
+ EFI_STATUS Status;
+ EFI_HANDLE *Handle;
+ UINTN Number,i;
+
+ //Get a list of all PCI to ISA Bridges
+ Status = GetPciHandlesByClass(
+ PCI_CL_BRIDGE, PCI_CL_BRIDGE_SCL_ISA, &Number, &Handle
+ );
+ if (EFI_ERROR(Status)) return;
+ for(i=0; i<Number; i++)
+ {
+ EFI_DEVICE_PATH_PROTOCOL *Dp, *ChildDp;
+ ACPI_HID_DEVICE_PATH Ps2Kbd = {
+ {ACPI_DEVICE_PATH,ACPI_DP,sizeof(ACPI_HID_DEVICE_PATH)},
+ EISA_PNP_ID(0x303),0
+ };
+ ACPI_HID_DEVICE_PATH Ps2Mouse = {
+ {ACPI_DEVICE_PATH,ACPI_DP,sizeof(ACPI_HID_DEVICE_PATH)},
+ EISA_PNP_ID(0xF03),0
+ };
+ Status=pBS->HandleProtocol(Handle[i],&gEfiDevicePathProtocolGuid,&Dp);
+ if (EFI_ERROR(Status)) continue;
+ pBS->ConnectController(Handle[i],NULL,NULL,FALSE);
+ ChildDp=DPAddNode(Dp, &Ps2Kbd.Header);
+ ConnectDevicePath(ChildDp);
+ pBS->FreePool(ChildDp);
+ ChildDp=DPAddNode(Dp, &Ps2Mouse.Header);
+ ConnectDevicePath(ChildDp);
+ pBS->FreePool(ChildDp);
+ LpcHandle = Handle[i];
+ LpcDevicePath = Dp;
+ }
+ pBS->FreePool(Handle);
+
+}
+
+VOID ConnectUsbConIn(){
+ EFI_STATUS Status;
+ EFI_HANDLE *Handle;
+ UINTN Number,i;
+ //Get a list of all USB Controllers
+ Status = GetPciHandlesByClass(
+ PCI_CL_SER_BUS, PCI_CL_SER_BUS_SCL_USB, &Number, &Handle
+ );
+ if (EFI_ERROR(Status)) return;
+ for(i=0; i<Number; i++)
+ {
+ pBS->ConnectController(Handle[i],NULL,NULL,TRUE);
+ }
+ pBS->FreePool(Handle);
+}
+
+VOID ConnectConInVariable(){
+ ConnecConsoleVariable(L"ConIn");
+}
+
+VOID InstallConInStartedProtocol(){
+ InstallConsoleStartedProtocol(L"ConInDev", &ConInStartedProtocolGuid);
+}
+
+VOID ConInAvailabilityBeep(){
+ LibReportStatusCode(EFI_PROGRESS_CODE, AMI_STATUS_CODE_BEEP_CLASS|1, 0, NULL, NULL);
+}
+
+VOID InitConVars()
+{
+ UINTN i;
+ UINTN Size = 0;
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *ConPath=NULL;
+
+ static CHAR16* ConVar[] = {L"ConOut", L"ConIn"};
+ static CHAR16* ConDev[] = {L"ConOutDev", L"ConInDev"};
+
+ // Install Console Stared Protocols
+ // ConSplitter will process notification by populating
+ // corresponding fields of the system table.
+ // At this point the protocol need to be installed
+ // even if no actual console devices are available
+ // to prevent problems on headless systems
+ // caused by NULL console pointers in the system table.
+ // The functions will not install the protocol if it has already been installed
+ InstallConsoleStartedProtocol(NULL, &ConOutStartedProtocolGuid);
+ InstallConsoleStartedProtocol(NULL, &ConInStartedProtocolGuid);
+
+ //Create non-existent ConVar variables for ConIn and ConOut
+ //ErrOut will be treated differently
+ for( i=0; i<2; i++){
+ if (EFI_ERROR(
+ GetEfiVariable(ConDev[i], &EfiVariableGuid, NULL, &Size, &ConPath)
+ )
+ ) continue;
+ //Set ConVar[i] equal to the ConDev[i]
+ pRS->SetVariable(
+ ConVar[i], &EfiVariableGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ Size, ConPath
+ );
+ }
+ //Let's take care about ErrOut
+ Status = GetEfiVariable(
+ L"ErrOutDev", &EfiVariableGuid, NULL, &Size, &ConPath
+ );
+ if ( Status == EFI_NOT_FOUND ){
+ Status = GetEfiVariable(
+ L"ConOutDev", &EfiVariableGuid, NULL, &Size, &ConPath
+ );
+ if (!EFI_ERROR(Status))
+ //Set ConErrDev equal to the ConOutDev
+ pRS->SetVariable(
+ L"ErrOutDev", &EfiVariableGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ Size, ConPath
+ );
+ }
+ if (!EFI_ERROR(Status)){
+ //Set ErrOut
+ pRS->SetVariable(
+ L"ErrOut", &EfiVariableGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ Size, ConPath
+ );
+ }
+ if (ConPath) pBS->FreePool(ConPath);
+}
+
+#define IsRuntimeMemoryType(MemoryType) \
+ ((MemoryType) == EfiACPIReclaimMemory || \
+ (MemoryType) == EfiACPIMemoryNVS || \
+ (MemoryType) == EfiRuntimeServicesCode || \
+ (MemoryType) == EfiRuntimeServicesData || \
+ (MemoryType) == EfiReservedMemoryType )
+
+VOID SaveMemoryTypeInformation (
+ IN EFI_EVENT Event, IN VOID *Context
+){
+#ifdef EFI_DEBUG
+ CONST CHAR8* EfiMemTypeStr[] = {
+ "Reserved ",
+ "LoaderCode ",
+ "LoaderData ",
+ "BSCode ",
+ "BSData ",
+ "RSCode ",
+ "RSData ",
+ "Free ",
+ "Unusable ",
+ "ACPIReclaim",
+ "ACPINVS ",
+ "MMIO ",
+ "MMIOIOPort ",
+ "PalCode "
+ };
+ struct{
+ UINT32 Previous,Current,Next;
+ } MemoryInfoHistory[EfiMaxMemoryType];
+#endif
+ static EFI_GUID HobListGuid = HOB_LIST_GUID;
+ EFI_STATUS Status;
+ EFI_HOB_GUID_TYPE *MemoryInformationHob;
+ EFI_MEMORY_TYPE_INFORMATION *MemoryTypeInformation = NULL;
+ UINTN MemoryTypeInformationSize = 0;
+ BOOLEAN IsFirstBoot = FALSE;
+ EFI_MEMORY_TYPE_INFORMATION *CurrentMemoryTypeInformation;
+ UINTN i, j;
+ BOOLEAN MemoryTypeInformationModified;
+ BOOLEAN RtMemoryQuotasIncreased = FALSE;
+ UINT32 Current, Next;
+
+ static BOOLEAN MemoryTypeInformationIsSaved = FALSE;
+
+ // Make sure the processing is performed only once.
+ // (we are registering callback on multiple events in RegisterMemoryTypeInformationUpdateCallback)
+ if (MemoryTypeInformationIsSaved){
+ pBS->CloseEvent(Event);
+ return;
+ }
+
+ // Get the Memory Type Information settings from Hob if they exist,
+ // PEI is responsible for getting them from variable and building a Hob to save them.
+ MemoryInformationHob = GetEfiConfigurationTable(pST, &HobListGuid);
+ if (MemoryInformationHob == NULL) return;
+ if (EFI_ERROR(
+ FindNextHobByGuid(&gEfiMemoryTypeInformationGuid, &MemoryInformationHob)
+ )) return;
+
+ Status = pRS->GetVariable(
+ L"PreviousMemoryTypeInformation", &gEfiMemoryTypeInformationGuid, NULL,
+ &MemoryTypeInformationSize, NULL
+ );
+ IsFirstBoot = Status==EFI_NOT_FOUND;
+
+ MemoryTypeInformation = (EFI_MEMORY_TYPE_INFORMATION*)(MemoryInformationHob+1);
+ MemoryTypeInformationSize = MemoryInformationHob->Header.HobLength
+ - sizeof (EFI_HOB_GUID_TYPE);
+ // Save memory information for the current boot.
+ // It will be used if next boot is S4 resume.
+ Status = pRS->SetVariable (
+ L"PreviousMemoryTypeInformation", &gEfiMemoryTypeInformationGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ MemoryTypeInformationSize, MemoryTypeInformation
+ );
+ ASSERT_EFI_ERROR(Status);
+
+ // Retrieve the current memory usage statistics. If they are not found, then
+ // no adjustments can be made to the Memory Type Information variable.
+ CurrentMemoryTypeInformation = GetEfiConfigurationTable(
+ pST, &gEfiMemoryTypeInformationGuid
+ );
+ if (CurrentMemoryTypeInformation == NULL) return;
+ MemoryTypeInformationModified = FALSE;
+ TRACE((TRACE_DXE_CORE, "BDS.%s(%X)\n",
+ "SaveMemoryTypeInformation", SaveMemoryTypeInformation
+ ));
+ // Adjust the Memory Type Information for the next boot
+ for (i = 0; MemoryTypeInformation[i].Type != EfiMaxMemoryType; i++) {
+ Current = 0;
+ for (j = 0; CurrentMemoryTypeInformation[j].Type != EfiMaxMemoryType; j++) {
+ if (MemoryTypeInformation[i].Type == CurrentMemoryTypeInformation[j].Type) {
+ Current = CurrentMemoryTypeInformation[j].NumberOfPages;
+ break;
+ }
+ }
+
+ // Set next value to 125% of the current
+ Next = Current + (Current >> 2);
+#ifdef EFI_DEBUG
+ MemoryInfoHistory[i].Previous = MemoryTypeInformation[i].NumberOfPages;
+ MemoryInfoHistory[i].Current = Current;
+ MemoryInfoHistory[i].Next = (Next > MemoryTypeInformation[i].NumberOfPages) ? Next : MemoryTypeInformation[i].NumberOfPages;
+#endif
+ // We are never decreasing the memory type usage values.
+ // It would've been more fair to check for inequality (!=) here to
+ // keep memory type information consistent with the actual memory usage.
+ // We are not doing it to workaround UEFI Windows 7 and Windows 8 bug.
+ // Windows loader can't properly handle (it crashes)
+ // memory map changes that happen after OS load has been launched
+ // and before the ExitBootServices call.
+ // It's very difficult to predict how much memory will be used during
+ // the execution of the Windows loader because in certain cases Windows loader
+ // is pretty active. For example, it sometimes calls
+ // ConnectController for all the devices.
+ // By never decreasing the memory type usage values, we are avoiding the problem
+ // by always assuming the worst case scenario (the heaviest memory usage).
+ // The drawback is, we are stealing more memory than is actually used from the user.
+ if (Next > MemoryTypeInformation[i].NumberOfPages){
+ if ( IsRuntimeMemoryType(MemoryTypeInformation[i].Type) )
+ RtMemoryQuotasIncreased = TRUE;
+ MemoryTypeInformation[i].NumberOfPages = Next;
+ MemoryTypeInformationModified = TRUE;
+ }
+ }
+
+ // If any changes were made to the Memory Type Information settings,
+ // set the new variable value;
+ if ( MemoryTypeInformationModified ){
+ TRACE((TRACE_DXE_CORE, " Memory Previous Current Next \n"));
+ TRACE((TRACE_DXE_CORE, " Type Pages Pages Pages \n"));
+ TRACE((TRACE_DXE_CORE, "=========== ======== ======== ========\n"));
+ for (i = 0; MemoryTypeInformation[i].Type != EfiMaxMemoryType; i++) {
+ TRACE((
+ TRACE_DXE_CORE, "%s %8X %8X %8X\n",
+ EfiMemTypeStr[MemoryTypeInformation[i].Type],
+ MemoryInfoHistory[i].Previous,
+ MemoryInfoHistory[i].Current,
+ MemoryInfoHistory[i].Next
+ ));
+ }
+ Status = pRS->SetVariable(
+ EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME, &gEfiMemoryTypeInformationGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ MemoryTypeInformationSize, MemoryTypeInformation
+ );
+ ASSERT_EFI_ERROR(Status);
+ if (IsFirstBoot && RtMemoryQuotasIncreased){
+ TRACE((
+ TRACE_DXE_CORE,
+ "Default RT memory quotas have been increased. Resetting the system...\n"
+ ));
+ pRS->ResetSystem(EfiResetCold, EFI_SUCCESS, 0, NULL);
+ }
+ }
+ pBS->CloseEvent(Event);
+ MemoryTypeInformationIsSaved = TRUE;
+}
+
+VOID RegisterMemoryTypeInformationUpdateCallback(){
+ EFI_EVENT Event;
+ VOID *Registration;
+
+ EFI_BOOT_MODE BootMode = GetBootMode();
+ if ( BootMode == BOOT_ON_S4_RESUME
+ || BootMode == BOOT_ON_FLASH_UPDATE
+ || BootMode == BOOT_IN_RECOVERY_MODE
+ ) return;
+
+ // We really want to get control.
+ // That's why we are registering callbacks for multiple boot events hoping that
+ // at least one of them will be triggered.
+ // If multiple events are signaled, only the first one is handled
+ RegisterProtocolCallback(
+ &BeforeBootProtocolGuid,
+ SaveMemoryTypeInformation,
+ NULL, &Event, &Registration
+ );
+ RegisterProtocolCallback(
+ &BeforeLegacyBootProtocolGuid,
+ SaveMemoryTypeInformation,
+ NULL, &Event, &Registration
+ );
+ CreateLegacyBootEvent(TPL_CALLBACK, &SaveMemoryTypeInformation, NULL, &Event);
+ pBS->CreateEvent(
+ EVT_SIGNAL_EXIT_BOOT_SERVICES,TPL_CALLBACK,
+ &SaveMemoryTypeInformation, NULL, &Event
+ );
+}
+
+VOID CallTheDispatcher(){
+ DXE_SERVICES *pDxe;
+
+ if (EFI_ERROR(LibGetDxeSvcTbl(&pDxe)))
+ return;
+ if (pDxe) pDxe->Dispatch();
+}
+
+VOID SignalAllDriversConnectedEvent(){
+ SignalProtocolEvent(&BdsAllDriversConnectedProtocolGuid);
+}
+
+VOID HandoffToTse(){
+ AMI_POST_MANAGER_PROTOCOL *AmiPostMgr=NULL;
+
+ if (!EFI_ERROR(pBS->LocateProtocol(
+ &AmiPostMgrProtocolGuid, NULL, &AmiPostMgr
+ ))) AmiPostMgr->Handshake();
+
+}
+
+VOID BdsEntry (IN EFI_BDS_ARCH_PROTOCOL *This)
+{
+
+ UINTN i;
+
+ PERF_END(0, DXE_TOK, NULL, 0);
+ PERF_START(0, BDS_TOK, NULL, 0);
+ InitParts2(TheImageHandle, pST);
+ //Lang & LangCodes are initialized by Setup driver
+ InitSystemVariable(L"Timeout", sizeof(UINT16), &DefaultTimeout);
+
+{
+ EFI_EVENT Event;
+ VOID *Registration;
+#ifdef EFI_DXE_PERFORMANCE
+ RegisterProtocolCallback(
+ &BeforeBootProtocolGuid,
+ SavePerformanceData,
+ NULL, &Event, &Registration
+ );
+ RegisterProtocolCallback(
+ &BeforeLegacyBootProtocolGuid,
+ SavePerformanceData,
+ NULL, &Event, &Registration
+ );
+
+#endif
+ RegisterProtocolCallback(
+ &BeforeLegacyBootProtocolGuid,
+ SaveFpdtDataOnLegacyBoot,
+ NULL, &Event, &Registration
+ );
+
+}
+ pBS->LocateHandleBuffer(AllHandles, NULL, NULL, &NumberOfHandles, &RootHandles);
+
+ for(i=0; BdsControlFlowFunctions[i]!=NULL; i++){
+ TRACE((TRACE_DXE_CORE, "BDS.%s(%X)\n",
+ BdsControlFlowFunctionNames[i], BdsControlFlowFunctions[i]
+ ));
+ BdsControlFlowFunctions[i]();
+ }
+}
+
+// Deprecated Variable.
+// Use TheImageHandle instead.
+EFI_HANDLE ThisImageHandle = NULL;
+
+EFI_STATUS BdsInit (IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
+{
+ EFI_HANDLE Handle = NULL;
+ InitAmiLib(ImageHandle, SystemTable);
+ ThisImageHandle = ImageHandle;
+ return pBS->InstallProtocolInterface(&Handle, &gEfiBdsArchProtocolGuid, EFI_NATIVE_INTERFACE, &BDS);
+}
+
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2010, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************