diff options
author | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
---|---|---|
committer | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
commit | b7c51c9cf4864df6aabb99a1ae843becd577237c (patch) | |
tree | eebe9b0d0ca03062955223097e57da84dd618b9a /Core/EM/CSM/CSM.c | |
download | zprj-master.tar.xz |
Diffstat (limited to 'Core/EM/CSM/CSM.c')
-rw-r--r-- | Core/EM/CSM/CSM.c | 2926 |
1 files changed, 2926 insertions, 0 deletions
diff --git a/Core/EM/CSM/CSM.c b/Core/EM/CSM/CSM.c new file mode 100644 index 0000000..c3b5314 --- /dev/null +++ b/Core/EM/CSM/CSM.c @@ -0,0 +1,2926 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2013, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** + +//**************************************************************************** +// $Header: /Alaska/SOURCE/Modules/CSM/Generic/Core/csm.c 198 8/06/14 12:57p Fasihm $ +// +// $Revision: 198 $ +// +// $Date: 8/06/14 12:57p $ +// +//**************************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Modules/CSM/Generic/Core/csm.c $ +// +// 198 8/06/14 12:57p Fasihm +// [TAG] EIP180667 +// [Category] Bug Fix +// [Severity] Normal +// [Symptom] Aptio 4 CSM: CPU cache attributes need adjustment. +// [Solution] Changed the cache attributes to WriteProtect for all 4 +// regions. +// [Files] +// Core/EM/CSM/CSM.c +// +// 197 1/10/14 12:21p Olegi +// EIP149769: LegacyToEfi boot management +// Changed default setting, added new token to extend the functionality +// +// 196 10/18/13 12:36p Olegi +// EIP139866 +// Create interface to manage LegacyToEfi CSM feature +// +// 195 10/07/13 10:21a Olegi +// [TAG] EIP138427 +// [Category] New Feature +// [Description] Create interface to let OEM customers change CSM16 +// variables +// [Files] csm.c, csm.h, csmlib.c, legacybiosext.h +// +// 194 10/07/13 8:57a Olegi +// EIP135289 +// Legacy2Efi update +// +// 193 8/14/13 8:38a Olegi +// EIP132753: Legacy2Efi module support +// +// 192 7/24/13 11:46a Olegi +// [TAG] EIP121303 +// [Category] Improvement +// [Description] UEFI Win7 hibernation wake up may fail +// [Files] csm.c +// +// 191 5/03/13 2:38a Rameshr +// [TAG] EIP117874 +// [Category] Improvement +// [Description] Modified AllConnectedCallback function event is based +// on TPL_NOTIFY +// [Files] csm.c +// +// 190 4/29/13 12:31p Olegi +// [TAG] EIP120105 +// [Category] Improvement +// [Description] Incorrect 'CSM16LocationAttribute' passed to +// CopyLegacyTable(), in CSM.c +// +// 189 4/09/13 9:25a Olegi +// [TAG] EIP118727 +// [Category] New Feature +// [Description] Onboard PCI Option ROM loading is moved outside CSM +// [Files] CSM.mak +// CSM.dxs +// CSM.c +// PciInterrupts.c +// CsmBsp.c +// CsmLib.c +// +// 188 12/24/12 12:06p Olegi +// [TAG] EIP89376 +// [Category] Improvement +// [Description] [CSM] Support to return EFI_SECURITY_VIOLATION from +// EFI_Legacy_BIOS_Protocol.LegacyBoot when secure boot is on +// +// 187 12/18/12 1:44p Olegi +// [TAG] EIP108682 +// [Category] Bug Fix +// [Severity] Normal +// [Symptom] Invalid Error Code from CSM Functions +// [RootCause] BIT31 is used as error indication +// [Solution] use EFI_ERROR_BIT macro instead of BIT31 +// [Files] CSM.c +// CsmHwInfo.c +// +// 186 12/14/12 3:04p Olegi +// [TAG] EIP105734 +// [Category] Bug Fix +// [Symptom] PCI Resource Issue with PLX Bridges +// [RootCause] Bridge stays disabled on LegacyBoot +// [Solution] Enable the bridges on legacy boot along with the other PCI +// devices. +// +// 185 7/23/12 4:46p Olegi +// [TAG] EIP93685 +// [Category] Improvement +// [Description] Clear CSM used resources when it is disabled +// +// 184 7/23/12 12:10p Olegi +// [TAG] EIP92416 +// [Description] Testing request for Smbios (INT)a_4.6.5.1_SMBIOS_32 +// label +// LegacyBiosExt protocol is rearranged to match the one used by the +// SMBIOS. +// +// 183 6/25/12 3:59p Olegi +// [TAG] EIP90257 +// [Category] Improvement +// [Description] In CSM, don't clear allocated memory below 640K - added +// ClearFreeMemory function +// [Files] CsmOpROM.c +// CSM.c +// CsmHwInfo.c +// +// 182 6/13/12 9:12a Olegi +// [TAG] EIP90257 +// [Category] Improvement +// [Description] In CSM, don't clear allocated memory below 640K. +// +// 181 12/23/11 3:09p Olegi +// [TAG] EIP78921 +// [Category] Improvement +// [Description] CsmBlockIo should create device handle in BBS table +// [Files] CSM.h +// CSM.c +// CsmLib.c +// +// 180 12/23/11 2:47p Olegi +// [TAG] EIP79228 +// [Category] Improvement +// [Description] Implement CSM_INT19_TRAP_IMMEDIATE_ACTION functionality +// [Files] CsmOpROM.c +// CSM.c +// +// 179 11/14/11 11:59a Olegi +// +// 176 11/10/11 7:28p Olegi +// CSM_OPTOUT_SUPPORT is replaced with CsmOptOut_SUPPORT master token. +// +// 175 10/31/11 11:55a Olegi +// Installation of AMISCMStartedProtocolGuid is moved our of +// CSM_OPTOUT_IMPLEMENTED scope. +// +// 174 10/12/11 10:06p Olegi +// [TAG] EIP72331 +// [Category] Improvement +// [Description] Added CSM_INIT_LEGACY_MEMORY_FUNCTIONS eLink for custom +// memory initialization. +// [Files] CSM.mak +// CSM.c +// CsmBsp.c +// +// 173 10/12/11 2:56p Olegi +// [TAG] EIP72177 +// [Category] Improvement +// [Description] CheckPmmTable function suppressed. +// [Files] CsmOpROM.c +// CSM.c +// CsmBsp.c +// CSM.SDL +// +// 172 10/03/11 5:05p Olegi +// +// 171 10/03/11 3:22p Olegi +// [TAG] EIP71591 +// [Category] Improvement +// [Description] CSM opt-out changes +// +// 170 10/03/11 1:44p Olegi +// Modifications in HaltApsBeforeBoot function related to PI1.1 +// +// 169 8/29/11 2:23p Olegi +// [TAG] EIP56792 +// [Category] Improvement +// [Description] Original fix for this EIP checked in earlier does not +// work for the newer Core versions. FLEXBOOT has been depreciated for +// newer Cores, and it must be enabled for proper operation. +// [Files] csm.c +// +// 168 6/10/11 5:37p Olegi +// [TAG] EIP59263 +// [Category] New Feature +// [Description] High memory PMM area made dynamic. +// [Files] CSM.h +// CsmOpROM.c +// CSM.c +// CsmBsp.c +// csm.sdl +// +// 167 6/10/11 5:07p Olegi +// Undone check-ins #165 and #166 as EIP59263 is resolved differently. +// +// 164 3/24/11 9:39a Olegi +// [TAG] EIP56792 +// [Category] Improvement +// [Description] The value of FLEX_BOOT is depreciated for the newer +// Core. +// [Files] csm.c +// +// 163 3/15/11 3:50p Olegi +// [TAG] EIP55913 +// [Category] Improvement +// [Description] Remove LastOpromAddress from EFI_COMPATIBILITY16_TABLE +// structure +// [Files] Csm.c LegacyBios.h LegacyBiosExt.h +// +// 162 3/10/11 3:04a Rameshr +// [TAG]- EIP 54231 +// [Category]-IMPROVEMENT +// [Description]- Display the virus warning message when writting into MBR +// of HDD. This support added for IDE, AHCI and USB HD devices. +// [Files]- Csm.c, CsmOem.cif, Csm.uni, Csm.sdl, Csm.sd, Amilegacy16.bin, +// AI13.Bin, Ui13.bin, VirusProtect module +// +// 161 3/08/11 12:44p Olegi +// [TAG] EIP55496 +// [Category] Improvement +// [Description] Added ebdaOffset field to SAVED_PCI_ROM structure to +// ensure the correct EBDA saving/restoration. +// [Files] CSM.h +// CsmOpROM.c +// CSM.c +// +// 160 12/13/10 5:29p Olegi +// [TAG] EIP50206 +// [Category] Bug Fix +// [Severity] Important +// [Symptom] Calls to Get16BitFuncAddress() can hang the system when +// CSM_OEM_SUPPORT is disabled +// [RootCause] Disabling CSM_OEM_SUPPORT and calling +// Get16BitFuncAddress() will hang the system because gCsm16FuncAddress is +// NULL (uninitialized) and gCsm16FuncAddress is dereferenced. +// [Solution] Added validation of gCsm16FuncAddress variable in +// Get16BitFuncAddress function. +// [Files] CSM.C +// +// 159 11/15/10 12:04p Olegi +// [TAG] EIP47997 +// [Category] Improvement +// [Description] Project tag updated in F000:F4F0 +// [Files] CSM.C +// +// 158 10/13/10 12:43p Olegi +// Undoing the previous change related to InitCsmSimpleIn as it is not +// generic change. +// +// 157 10/12/10 5:43p Olegi +// Function call InitCsmSimpleIn made conditional; in the older BDS this +// call causes problem. EIP43050 +// +// 156 9/15/10 5:21p Olegi +// Added reverse thunk stack allocation. +// +// 155 7/16/10 12:47p Olegi +// +// 154 7/16/10 12:31p Olegi +// - EIP39395: Update CSM16 header checksum after LastPciBus field of it +// has been changed. +// - EIP39768: Modifications in the video mode switching policy +// - Isolated all AMI CSM16 specific programming into a separate function +// so that it can be skipped in case of non-AMI CSM16. +// +// 153 7/09/10 9:18a Olegi +// Changed the sequence of HaltApsBeforeBoot and SignalAmiLegacyBootEvent +// execution. EIP39089. +// +// 152 7/08/10 11:31a Olegi +// Added SignalAmiLegacyBootEvent call. EIP39089 +// +// 151 5/27/10 4:59p Olegi +// Modified UpdatePciLastBus function, made it a callback notification on +// PciIo, not on RootBridgeIo. EIP#39123. +// +// 150 5/14/10 4:16p Olegi +// +// 149 5/10/10 2:24p Olegi +// Update BIOS date/time/rev in CSM16 area. EIP#34791 +// +// 148 4/28/10 11:53a Olegi +// +// 147 3/26/10 9:36a Olegi +// Dynamic CSM16 location calculation. EIP36484 +// +// 146 3/02/10 5:13p Olegi +// Making use of AmiExtPciBusProtocol when PCI Bus driver version is 240 +// or newer. +// +// 145 2/19/10 3:13p Olegi +// +// 144 2/19/10 1:24p Olegi +// Changed the resolution of EIP34733 (>10s delay during boot). Root cause +// of the problem is one of the LEGACY_BOOT callback notification +// functions (BootNotify function in CpuDxe.c) is initializing IDT with +// the "iret", at the same time interrupts kept enabled. This is not +// suitable for the HW interrupt (IRQ1 from timer) - at least EOI must be +// sent to PIC before executing "iret". This was causing a timeout while +// reading the HDD in the PrepareToBoot function. The current solution is +// to mask timer interrupt after all callback notifications are complete. +// +// 143 2/17/10 1:50p Olegi +// Undo the final resolution for EIP32001: UpdatePciLastBus can not be +// called from AllConnectedCallback as the last PCI bus # may be needed +// earlier than that (Option ROMs). EIP35258. +// +// 142 2/05/10 7:14p Olegi +// +// 141 2/01/10 1:56p Olegi +// EIP33173: During LegacyBoot set video mode 3 only if it is not set +// already. +// +// 140 1/26/10 12:38p Olegi +// EIP32001: functionality of UpdatePciLastBus function is moved to +// AllConnectedCallback. +// +// 139 1/12/10 11:46a Olegi +// Copyright message updated. +// +// 138 12/28/09 8:48a Olegi +// RemoveDecodingForShadow call moved to LEGACYREGION.Lock +// +// 137 12/28/09 8:25a Olegi +// WinCE loader support. EIP#30803 +// +// 136 12/02/09 10:00a Olegi +// EIP#23106: added NMI information related call. +// +// 135 12/01/09 11:40a Olegi +// Changed the order of UpdateCmos-->EnableDisableNmi functions because +// UpdateCmos will unconditionally enable NMIs. +// +// 134 11/17/09 12:06p Olegi +// Changed the order of PrepareToBoot execution. It is moved after +// singaling LegacyBoot event. The reason is PrepareToBoot finalizes E820 +// table and LegacyBoot event callbacks may allocate some memory that must +// be reflected in E820 map. Example - S3 resume script memory. EIP#29087. +// +// 133 11/10/09 8:24a Olegi +// Added CSM SimpleTextIn support. EIP#27843 +// +// 132 10/27/09 8:08a Olegi +// EIP#29883: Bugfix in InitCompatibility16 function. +// +// 131 6/16/09 4:11p Olegi +// Generic modifications to update LastPciBus field in +// EFI_COMPATIBILITY16_TABLE. +// +// 130 4/02/09 2:14p Olegi +// Modification in EnablePciDevices: the counter of PCI devices was +// declared as UINT8 - some configurations have more than 256 devices. +// Changed to UINTN. +// +// 129 3/30/09 5:05p Olegi +// Change in OEM16 routines: fixups are done so that every routine is +// entered at a correct offset; no fixup is needed to access the local +// variables. EIP#16383. +// +// 128 12/16/08 10:47a Olegi +// Correction in the return value: 0 changed to NULL. EIP#17767 +// +// 126 12/11/08 3:00p Olegi +// Added shadow regions initialization. EIP#17763 +// +// 125 12/09/08 3:31p Olegi +// Added EfiGetPlatformGateA20Information function. +// +// 124 11/13/08 1:01p Olegi +// +// 123 11/12/08 4:59p Olegi +// Added board specific hooks. +// +// 122 10/10/08 3:35p Olegi +// +// 121 9/23/08 2:18p Olegi +// +// 120 9/02/08 10:54a Olegi +// Modification in EnablePciDevice function that will keep "unused" PCI +// bridges disabled after legacy boot. +// +// 119 7/23/08 9:57a Fasihm +// Fix EIP#: 14947: Added fix for CPU MTRR registers being inconsistent +// between cores. Moved the RemoveDecodingForShadow call from after to +// before the Signal_Legacy_Boot event. +// +// 118 6/30/08 3:50p Olegi +// +// 117 6/09/08 2:07p Olegi +// Added HaltApsBeforeBoot routine that halts the APs before legacy boot. +// +// 116 5/19/08 12:37p Olegi +// Removed EBDA size limitation. +// +// 115 4/14/08 2:45p Rameshraju +// Removed the decoding for the remaining Shadow region +// +// 114 3/20/08 4:44p Olegi +// FLEXBOOT initialization added. +// +// 113 3/12/08 11:59a Olegi +// Added progress status codes. +// +// 112 1/31/08 11:53a Olegi +// AllocateEbda call definition changed. +// +// 111 1/16/08 2:17p Olegi +// Modified AllocateEbda function. +// +// 110 12/17/07 4:22p Olegi +// KBC_SUPPORT dependency removed. +// +// 109 12/04/07 11:07a Olegi +// +// 108 10/24/07 12:27p Olegi +// Function AllocateEbda added to LegacyBiosExt protocol. +// +// 107 10/17/07 3:23p Olegi +// - modified PrepareToBoot to properly Unlock/Lock shadow regions. The +// problem was with the ROMs that are not in the SavedRom list (service +// ROMs or non-BBS compliant ROMs). After the final locking these ROMs +// areas were not decoded +// - modified GetBbsInfo to treat floppy with NO_FLOPPY_DISK and +// FLOPPY_INSERTED the same way +// +// 106 8/23/07 9:14a Olegi +// Reverted #105, it causes problems on MCP55 AMD projects. Instead, +// UninstallMemoryManagerEF call is removed from CSM16 PrepareToBoot. +// +// 105 8/21/07 11:07a Olegi +// CreateLegacyBootEvent moved before PrepareToBoot call so that legacy +// boot event callbacks have a chance to allocate E/F memory +// +// 104 8/10/07 11:05a Olegi +// +// 103 7/23/07 12:41p Olegi +// Change the order of PrepareToBoot and BspPrepareToBoot execution. +// +// 102 7/10/07 12:42p Olegi +// Added the initialization of kbd head and tail in PrepareToBoot +// function. +// +// 101 6/27/07 3:52p Olegi +// Workaround for OpROMs that use 40:13 to allocate memory, not EBDA. +// +// 100 6/21/07 10:32a Olegi +// +// 99 6/18/07 5:46p Olegi +// Added two new protocol functions GetEmbeddedRom and AddBbsEntry. +// +// 98 6/12/07 5:47p Olegi +// Removed the loop that initializes the priorities for the existing BBS +// devices. +// +// 97 6/12/07 2:59p Olegi +// +// 96 6/04/07 12:34p Olegi +// +// 95 6/04/07 10:45a Olegi +// +// 94 6/02/07 10:46a Olegi +// +// 93 6/02/07 10:25a Olegi +// Shadow size correction. +// +// 92 6/01/07 12:29p Olegi +// Fixed the return values while exiting the entry point. +// +// 91 5/29/07 12:21p Olegi +// The code to disable Shadow W/R for the unused shadow regions is moved +// to CsmOpROM.c +// +// 90 5/24/07 4:05p Olegi +// Added two setup questions - NumLock state at boot and OpROM display +// mode. +// +// 89 5/03/07 1:23p Olegi +// PCIE_BASE_ADDRESS token is changed to PCIEX_BASE_ADDRESS +// +// 88 4/27/07 5:28p Olegi +// PCIEX_BASE_ADDRESS is used instead of PCIE_BASE_ADDRESS. It is +// currently defined in NB.SDL +// +// 87 4/27/07 5:13p Olegi +// CSM.CHM file preparation. +// +// 86 4/20/07 11:31a Olegi +// Bugfix in OEM interrupts and OEM 16-bit function initialization. +// +// 85 4/19/07 10:21a Olegi +// Updated InitializeOem16 function. +// +// 84 4/12/07 1:28p Olegi +// +// 83 4/10/07 5:18p Olegi +// LastOpromAddress is passed from CSM32 to CSM16. +// +// 82 3/01/07 9:12a Olegi +// +// 81 12/13/06 4:12p Olegi +// +// 80 12/12/06 5:30p Olegi +// BBS table dump before PrepareToBoot. +// +// 79 10/13/06 12:30a Felixp +// UEFI2.0 compliance: use CreateLegacyBootEvent instead of +// CreateEvent(LEGACY_BOOT) +// +// 78 10/05/06 5:53p Olegi +// Added context to EFI_EVENT_SIGNAL_LEGACY_BOOT event. +// +// 77 9/22/06 6:13p Olegi +// +// 76 9/20/06 11:35a Felixp +// x64 warning fixed +// +// 75 8/24/06 6:49p Felixp +// x64 support (warnings/errors fixed) +// +// 74 8/16/06 2:38p Olegi +// Previous typecast changes undone. +// +// 72 8/11/06 4:44p Olegi +// +// 71 7/31/06 4:05p Olegi +// +// 70 7/28/06 4:43p Olegi +// +// 68 7/07/06 8:24a Olegi +// At entry point clear 0..640K, assuming no other driver allocated any +// memory within this range. This assumption implies the whole +// conventional memory directly and indirectly belongs to CSM. +// +// 67 7/05/06 3:42p Olegi +// LegacyBoot used to do INT10 first, then TxtOut->ClearScreen. This +// sequence needs to be reversed. +// +// 64 5/25/06 2:23p Olegi +// +// 63 5/16/06 1:57p Olegi +// +// 62 5/04/06 9:42a Olegi +// Removed the logic that fixes the location of PATA/SATA in BBS table. +// +// 61 4/24/06 9:27a Olegi +// Lock/UnLock shadow regions added before and after each CSM API call. +// +// 59 4/18/06 12:06p Olegi +// +// 58 4/18/06 10:38a Olegi +// SHADOWREGION_GRANULARITY token has been removed; shadow regions +// granularity is taken from Lock/Unlock routines. +// +// 57 4/17/06 4:27p Olegi +// +// 56 4/17/06 9:32a Olegi +// +// 55 3/31/06 4:44p Olegi +// +// 54 3/31/06 9:14a Olegi +// +// 53 3/30/06 1:20p Olegi +// +// 50 3/03/06 5:09p Olegi +// EFI System Table pointer is passed to CSM16. +// +// 49 3/01/06 3:10p Olegi +// +// 47 2/23/06 7:06p Olegi +// GetLegacyRegion and CopyLegacyRegion functions added. +// +// 46 12/16/05 2:59p Robert +// Clear the screen before PrepareToBoot function: some BCVs (Netcell PCI +// SATA RAID) attempt to output messages using INT10, this causes screen +// corruption. +// +// 45 12/14/05 4:16p Olegi +// NMI enable/disable changes. +// +// 44 12/12/05 12:13p Olegi +// +// 43 10/13/05 6:23p Olegi +// Interrupt save/restore correction. +// +// 42 10/11/05 2:57p Olegi +// +// 41 10/11/05 11:56a Olegi +// +// 40 10/10/05 7:27p Olegi +// +// 39 9/30/05 6:27p Olegi +// VC7.1 compatibility issues solved. +// +// 38 9/29/05 5:20p Olegi +// Clear TxtOut screens before booting. +// +// 37 9/28/05 8:29a Olegi +// Interrupt save/restore code is divided into SW and HW interrupts +// restoration. +// +// 36 9/21/05 3:55p Olegi +// +// 35 9/09/05 6:04p Olegi +// +// 34 9/09/05 11:22a Olegi +// +// 33 9/06/05 10:48a Olegi +// +// 32 9/02/05 2:57p Olegi +// Save/restore additional interrupts. +// +// 31 8/25/05 10:31a Olegi +// Previous change undone, issue with some VGA cards that hook int 6d +// (Matrox PCI) is solved different way: vector base for the master 8259 +// is changed from 0x68 to 0x58. +// +// 29 8/02/05 11:28a Olegi +// GetBbsInfo: device priorities are initialized for all entries with +// priority different from BBS_IGNORE. +// +// 28 6/22/05 8:35a Olegi +// +// 27 6/21/05 12:12p Olegi +// LegacyBios and LegacyBiosPlatform are combined into one FFS. +// +// 26 4/29/05 8:42a Olegi +// +// 25 4/25/05 5:32p Olegi +// +// 24 4/22/05 2:11p Olegi +// +// 24 4/21/05 9:04a Olegi +// - moved INT 13 vector manipulation here from BiosBlkIo +// - added ShadowPciRoms and EnablePciDevices functions +// - modified the sequence of signaling the boot event and locking shadow +// in LegacyBoot function +// +// 23 4/19/05 11:16a Olegi +// Signal legacy boot event code moved after the shadow memory is locked. +// +// 22 4/19/05 11:12a Olegi +// ShadowAllLegacyOproms call added. +// +// 21 4/12/05 12:20p Olegi +// +// 20 3/10/05 4:45p Olegi +// Removed ASSERT after allocation of shadow memory since it might be +// allocated already. +// +// 19 3/04/05 1:53p Mandal +// +//********************************************************************** + +//********************************************************************** +//<AMI_FHDR_START> +// +// Name: CSM.C +// Description: Compatibility Support Module entry point and interface functions. +// +//<AMI_FHDR_END> +//**************************************************************************** + +#include "token.h" +#include "csm.h" +#include <Protocol/cpu.h> +#include <Protocol/PciIo.h> +#include <AmiDxeLib.h> +#include "biosdata.h" +#include "pci.h" +#include "setup.h" +#include <Protocol/MPService.h> +#include <Protocol/PciRootBridgeIo.h> +#include <Protocol/Timer.h> +#include <Protocol/CsmPlatform.h> +#include "timestamp.h" +#include <ImageAuthentication.h> +#include <Protocol/AmiBoardInfo.h> + +#include <AmiCspLib.h> +#ifndef DEFAULT_TICK_DURATION +#define DEFAULT_TICK_DURATION ((65535 * 838 + 50) / 100) +#endif +#define LTEB_GUID \ + {0xC8BCA618, 0xBFC6, 0x46B7, 0x8D, 0x19, 0x83, 0x14, 0xE2, 0xE5, 0x6E, 0xC1} +EFI_GUID gLTEBGuid = LTEB_GUID; + +#define AMI_PCI_BUS_EXT_PROTOCOL_GUID \ +{ 0xf42a009d, 0x977f, 0x4f08, 0x94, 0x40, 0xbc, 0xa5, 0xa3, 0xbe, 0xd9, 0xaf }; + +#define BDS_ALL_DRIVERS_CONNECTED_PROTOCOL_GUID \ + {0xdbc9fd21, 0xfad8, 0x45b0, 0x9e, 0x78, 0x27, 0x15, 0x88, 0x67, 0xcc, 0x93} + +#define WINCE_GUID \ +{ 0xC184562C,0x6864,0x40a3,{0xA0,0x81,0xC8,0xD3,0x5E,0x82,0xB9,0x20 }} + +EFI_GUID WinceGuid=WINCE_GUID; + +EFI_GUID gEfiMpServicesProtocolGuid = EFI_MP_SERVICES_PROTOCOL_GUID; +EFI_GUID gBdsAllDriversConnectedProtocolGuid = BDS_ALL_DRIVERS_CONNECTED_PROTOCOL_GUID; + +BIOS_INFO *CoreBiosInfo = NULL; +SAVED_PCI_ROM *gSavedOprom; +BOOLEAN gServiceRomsExecuted = FALSE; + +UINT8 *gNextRomAddress; // PCI ROM address pointer, updated as ROMs are installed +UINTN gMaxOpRomAddress; // Highest available address for PCI ROM + +EXECUTED_PCI_ROM *gExecutedRomsPci; // List of PciIo's with installed OpROMs +VOID *mAllocatedOnceMemory = NULL; + +BOOLEAN gIsBootPrepared; +BOOLEAN gIsBbsInitialized; +BOOLEAN gIsMassStorageInstalled; + +UINT32 HwIrqRedirSav[8]; // hw interrupts redirected vectors - IRQ0..IRQ7 +UINT8 irq0; + +#define MAX_NUM_IRQS_SAVERESTORE 16 +IVT_SAVE_RESTORE gIrqSav[MAX_NUM_IRQS_SAVERESTORE]; + +// +// gSetTxtMode +// 0 - switching to text mode is needed (init value) +// 1 - switching is needed, restoration is not (set in ShadowOptionRoms) +// 2 - neither switching nor restoration is needed +// +UINT8 gSetTxtMode; + +EFI_GUID guidSetup = SETUP_GUID; +SETUP_DATA gSetup; + +OEMINT_FUNC *gCsm16IntStart = 0; +OEM16_FUNC *gCsm16FuncAddress = 0; +UINTN gCsm32DataAddress = 0; +VOID *gProtocolNotifyRegistration; + +extern EFI_HANDLE gVgaHandle; + +AMI_BOARD_INFO_PROTOCOL *gAmiBoardInfo = NULL; + +VOID ConnectSerialIO(); +VOID DisconnectSerialIO(); +VOID DummyFunction(EFI_EVENT Event, VOID *Context); +EFI_TPL gOldTplValue = NULL; +UINT16 gProtectedIrqMask = 0xffff; +BBS_TABLE *gOriginalBbsTable = NULL; + +VOID DumpBbsTable(UINT32); +#define BBS_LOWEST_ACTIVE_PRIORITY 0xfffb + +/*---------------------------------------------------*/ +/*--- ---*/ +/*--- AMI CSM Extensions Protocol functions ---*/ +/*--- ---*/ +/*---------------------------------------------------*/ + +EFI_LEGACY_BIOS_EXT_PROTOCOL gAmiCsmExtensionsProtocol = { + GetEmbeddedRom, + AddBbsEntry, + InsertBbsEntryAt, + RemoveBbsEntryAt, + AllocateEbda, + UnlockShadow, + LockShadow, + Get16BitFuncAddress, + CopyLegacyTable, + InstallIsaRom, + GetShadowRamAddress, + GetBbsTable, + Csm16Configuration +}; + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: GetEmbeddedRom +// +// Description: +// This function calls FindEmbeddedRom to search for onboard Option ROM. +// +// Output: +// EFI_SUCCESS or EFI_NOT_FOUND +// +// Referrals: +// FindEmbeddedRom +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +GetEmbeddedRom ( + IN UINT16 ModuleId, + IN UINT16 VendorId, + IN UINT16 DeviceId, + OUT VOID **ImageStart, + OUT UINTN *ImageSize +) +{ + return FindEmbeddedRom(ModuleId, VendorId, DeviceId, ImageStart, ImageSize); +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: InitializeCsm16MiscInfo +// +// Description: +// This function initialize AMI specific CSM16 data: POST/RT variables in +// CSM16 based on Setup settings, OEM porting overridesIt will be skipped +// in case of non-AMI CSM16 binary. +// +// +// Notes: +// Shadow regions are unlocked. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID +InitializeCsm16MiscInfo( + LEGACY16_TO_EFI_DATA_TABLE_STRUC *Csm16Data, + SETUP_DATA *Setup +) +{ + UINT8 KbcSupport; + UINTN Data; + EFI_STATUS Status; + + // + // Initialize misc_info + // + KbcSupport = IoRead8(0x64); + if (KbcSupport != 0xff) { + Csm16Configuration(Csm16FeatureReset, Csm16LegacyFree, NULL); + } + else { + Csm16Configuration(Csm16FeatureSet, Csm16LegacyFree, NULL); + } + + if (Setup->ZipEmulation) { + Csm16Configuration(Csm16FeatureSet, Csm16ZipHddEmulation, NULL); + } + + Csm16Configuration(Csm16FeatureSet, Csm16I19Trap, NULL); + Csm16Configuration(Csm16FeatureSet, Csm16Flexboot, NULL); + + // Set GA20 related information in misc_info and rt_cmos_byte + Status = CoreBiosInfo->iBiosPlatform->GetPlatformInfo(CoreBiosInfo->iBiosPlatform, + EfiGetPlatformGateA20Information, + NULL, NULL, NULL, + &Data, 0, 0); + if (!EFI_ERROR(Status)) { + if (Data & 1) { + Csm16Configuration(Csm16FeatureSet, Csm16GA20, NULL); + } else { + Csm16Configuration(Csm16FeatureReset, Csm16GA20, NULL); + } + if (Data & 2) { + Csm16Configuration(Csm16FeatureSet, Csm16SkipGA20Deactivation, NULL); + } else { + Csm16Configuration(Csm16FeatureReset, Csm16SkipGA20Deactivation, NULL); + } + } + // Set NMI related information in misc_info and rt_cmos_byte; if porting function is not + // implemented, enable NMI + Status = CoreBiosInfo->iBiosPlatform->GetPlatformInfo(CoreBiosInfo->iBiosPlatform, + EfiGetPlatformNmiInformation, + NULL, NULL, NULL, + &Data, 0, 0); + if (EFI_ERROR(Status) || (Data == 1)) { + Csm16Configuration(Csm16FeatureSet, Csm16Nmi, NULL); + } else { + Csm16Configuration(Csm16FeatureReset, Csm16Nmi, NULL); + } + + // Allocate stack for reverse thunk + { + EFI_PHYSICAL_ADDRESS RtStackPtr; + UINTN CsmRtStackPtrLocation; + + Status = pBS->AllocatePages(AllocateAnyPages, EfiReservedMemoryType, 16, &RtStackPtr); + ASSERT_EFI_ERROR(Status); + pBS->SetMem( (UINT8*)(UINTN)RtStackPtr, 0x10000, 0 ); + CsmRtStackPtrLocation = 0xf0000 + Csm16Data->ReverseThunkStackPtrOfs; + *(UINTN*)CsmRtStackPtrLocation = (UINTN)RtStackPtr + 0x10000; + } + { + // Update the E000 memory bounds + UINTN StartOfFreeE000Ptr = 0xf0000 + Csm16Data->StartOfFreeE000Ofs; + UINT16 StartOfFreeE000; + UINT16 SizeOfFreeE000; + + ASSERT(gMaxOpRomAddress >= 0xdffff); + ASSERT(gMaxOpRomAddress < 0xeffff); + + StartOfFreeE000 = (UINT16)((UINT32)gMaxOpRomAddress + 1); // Cut off upper word + SizeOfFreeE000 = ~StartOfFreeE000; + + *(UINT16*)StartOfFreeE000Ptr = StartOfFreeE000; + *(UINT16*)(StartOfFreeE000Ptr + 2) = SizeOfFreeE000; + } + { + // Allocate legacy boot context save buffer and pass the pointer and the size to CSM16 + UINTN NumberOfPages = EFI_SIZE_TO_PAGES(LEGACY_TO_EFI_BOOT_BUFFER_SIZE); + EFI_PHYSICAL_ADDRESS Address = 0xffffffff; + UINTN Csm16BufferPointer = 0xf0000 + Csm16Data->BootBufferPtrOfs; + + Status = pBS->AllocatePages ( + AllocateMaxAddress, + EfiACPIMemoryNVS, + NumberOfPages, + &Address + ); + ASSERT_EFI_ERROR(Status); + + TRACE((-1, "CSM LegacyBoot context save buffer: %x, size %x; pointer is updated at %x\n", + Address, LEGACY_TO_EFI_BOOT_BUFFER_SIZE, Csm16BufferPointer)); + + *(UINT32*)Csm16BufferPointer = (UINT32)Address; + *(UINT32*)(Csm16BufferPointer+4) = LEGACY_TO_EFI_BOOT_BUFFER_SIZE; + + Csm16Configuration(Csm16FeatureReset, Csm16LegacyToEfi, NULL); + Csm16Configuration(Csm16FeatureReset, Csm16LegacyToEfiPonr, NULL); + +#if LEGACY_TO_EFI_DEFAULT + Csm16Configuration(Csm16FeatureSet, Csm16LegacyToEfi, NULL); +#if LEGACY_TO_EFI_BOOTRECORD_RETURN + Csm16Configuration(Csm16FeatureSet, Csm16LegacyToEfiPonr, NULL); +#endif +#endif + } +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: EnablePciDevices +// +// Description: +// This function enables all PCI devices before legacy boot +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS EnablePciDevices(EFI_LEGACY_BIOS_PROTOCOL *Bios) +{ + EFI_PCI_IO_PROTOCOL *PciIo; + UINTN Count; + EFI_HANDLE *Buffer; + UINTN i; + EFI_STATUS Status; + UINT8 PciCfg[4]; + UINT64 Capabilities; + + Status = pBS->LocateHandleBuffer(ByProtocol, + &gEfiPciIoProtocolGuid, + NULL, + &Count, + &Buffer); + ASSERT_EFI_ERROR (Status); + + for (i = 0; i < Count; i++) { + Status = pBS->HandleProtocol (Buffer[i], &gEfiPciIoProtocolGuid, &PciIo); + ASSERT_EFI_ERROR (Status); + + PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 8, 1, &PciCfg); // Reg 8,9,A,B + + // + // Skip enabling device for: + // - VGA + // - Old VGA + // - IDE + // - LPC Bridge + // + if ((PciCfg[3]==PCI_CL_DISPLAY && PciCfg[2]==PCI_CL_DISPLAY_SCL_VGA) + || (PciCfg[3]==PCI_CL_OLD && PciCfg[2]==PCI_CL_OLD_SCL_VGA) + || (PciCfg[3]==PCI_CL_MASS_STOR && PciCfg[2]==PCI_CL_MASS_STOR_SCL_IDE)) { + continue; + } + Status = PciIo->Attributes (PciIo, + EfiPciIoAttributeOperationSupported, 0, + &Capabilities); // Get device capabilities + ASSERT_EFI_ERROR(Status); + + Status = PciIo->Attributes (PciIo, + EfiPciIoAttributeOperationEnable, + Capabilities & EFI_PCI_DEVICE_ENABLE, + NULL); // Enable device + ASSERT_EFI_ERROR(Status); + } + + pBS->FreePool(Buffer); + + return EFI_SUCCESS; +} + + +//<AMI_PHDR_START> +//------------------------------------------------------------------------------------ +// +// Name: UpdatePciLastBus +// +// Description: +// In a multiple root-complex platform, the CSM16 routine "rth_pci_get_last_bus" +// needs to return the correct bus number. For example, in a 2 IOH system, the +// base bus #s for IOH0 can be 0 and IOH1 can be 80h. It should not be assumned +// there is only one root-complex and return the correct bus # (max bus of first IOH), +// for the card is plugged into the 2nd IOH. +// +// This function creates a callback notification event for EfiPciRootBridgeProtocol GUID +// installation. The callback function then will process the list of root bridges and +// will update the LastPciBus field of EFI_COMPATIBILITY16_TABLE accordingly. +// +//------------------------------------------------------------------------------------ +//<AMI_PHDR_END> + +EFI_STATUS UpdatePciLastBus() +{ + EFI_STATUS Status; + EFI_EVENT UpdatePciLastBusEvent; + VOID *UpdatePciLastBusReg = NULL; + EFI_GUID AmiExtPciBusProtocolGuid = AMI_PCI_BUS_EXT_PROTOCOL_GUID; + + // + // Create the notification and register callback function on the AmiExtPciBusProtocolGuid, + // callback function will update Pci Last Bus in Csm16 header. + // + Status = pBS->CreateEvent ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + UpdatePciLastBusCallback, + NULL, + &UpdatePciLastBusEvent); + ASSERT_EFI_ERROR(Status); + + if (EFI_ERROR(Status)) return Status; + + Status = pBS->RegisterProtocolNotify ( + &AmiExtPciBusProtocolGuid, + UpdatePciLastBusEvent, + &UpdatePciLastBusReg); + ASSERT_EFI_ERROR(Status); + + return Status; +} + +VOID ReadyToBootNotify(EFI_EVENT Event, VOID *Context) +{ + EFI_TO_COMPATIBILITY16_INIT_TABLE *Csm16InitTable; + + Csm16InitTable = &CoreBiosInfo->Thunk->Csm16InitTable; + pBS->FreePool((VOID*)(UINTN)Csm16InitTable->HiPmmMemory); + pBS->CloseEvent(Event); +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: CsmEntryPoint +// +// Description: +// CSM driver entry point +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +CsmEntryPoint( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + UINT16 IrqMask, SaveIrqMask; + UINTN Size=sizeof(SETUP_DATA); + EFI_EVENT Event; + EFI_HANDLE Handle = NULL; + EFI_GUID AMICSMStartedProtocolGuid = AMI_CSM_DRIVER_STARTED_GUID; + EFI_GUID AMICSMLoadProtocolGuid = AMI_LOAD_CSM_GUID; + + InitAmiLib(ImageHandle, SystemTable); + + PROGRESS_CODE(DXE_CSM_INIT); + + // Indicate that CSM has been launched. This protocol can be used as dependecy for other driver instead of + // LegacyBIOS protocol which may or may not be installed. + pBS->InstallProtocolInterface ( + &Handle, &AMICSMStartedProtocolGuid, EFI_NATIVE_INTERFACE, NULL + ); + + // Clear uninitialized memory @ 0..640K + Status = ClearFreeMemory(0, 0xa0000); + ASSERT_EFI_ERROR(Status); + if (EFI_ERROR(Status)) return Status; + +#if CsmOptOut_SUPPORT + { + VOID *CsmLoad; + + // Check if CSM needs to be enabled or not + Status = pBS->LocateProtocol (&AMICSMLoadProtocolGuid, NULL, &CsmLoad); + if (EFI_ERROR(Status)) { + // Unload the image if CSM needs to be disabled + return Status; + } + } +#endif + + // + // Initialize LegacyBiosPlatform + // + Status = InitCsmBoard (ImageHandle, SystemTable); + if (EFI_ERROR(Status)) return Status; + + // + // Initialize Csm Simple Key In + // + Status = InitCsmSimpleIn (ImageHandle, SystemTable); + if (EFI_ERROR(Status)) return Status; + + // + // Instantiate LEGACY_BIOS + // + Status = pBS->AllocatePool(EfiBootServicesData, sizeof(BIOS_INFO), &CoreBiosInfo); + if (EFI_ERROR(Status)) return Status; + + pBS->SetMem(CoreBiosInfo, sizeof(BIOS_INFO), 0); + CoreBiosInfo->hImage = ImageHandle; + + Status = pBS->LocateProtocol (&gEfiLegacyRegionProtocolGuid, NULL, &CoreBiosInfo->iRegion); + if (EFI_ERROR(Status)) return Status; + + Status = pBS->LocateProtocol (&gEfiLegacyBiosPlatformProtocolGuid, NULL, &CoreBiosInfo->iBiosPlatform); + if (EFI_ERROR(Status)) return Status; + + Status = pBS->LocateProtocol (&gEfiLegacy8259ProtocolGuid, NULL, &CoreBiosInfo->i8259); + if (EFI_ERROR(Status)) return Status; + + Status = pBS->LocateProtocol (&gEfiLegacyInterruptProtocolGuid, NULL, &CoreBiosInfo->iInterrupt); + if (EFI_ERROR(Status)) return Status; + + Status = pBS->LocateProtocol(&gAmiBoardInfoProtocolGuid, NULL,(VOID**)&gAmiBoardInfo); + if(EFI_ERROR(Status)) return Status; + + CoreBiosInfo->iBios.Int86 = Int86; + CoreBiosInfo->iBios.FarCall86 = FarCall86; + CoreBiosInfo->iBios.CheckPciRom = CheckPciRom; + CoreBiosInfo->iBios.InstallPciRom = InstallPciRom; + CoreBiosInfo->iBios.PrepareToBootEFI = PrepareToBoot; + CoreBiosInfo->iBios.LegacyBoot = LegacyBoot; + CoreBiosInfo->iBios.GetBbsInfo = GetBbsInfo; + CoreBiosInfo->iBios.ShadowAllLegacyOproms = ShadowAllLegacyOproms; + CoreBiosInfo->iBios.GetLegacyRegion = GetLegacyRegion; + CoreBiosInfo->iBios.CopyLegacyRegion = CopyLegacyRegion; + CoreBiosInfo->iBios.UpdateKeyboardLedStatus = UpdateKeyboardLedStatus; + // + // Call LegacyBiosPlatform to get the end of OpROM + // + Status = CoreBiosInfo->iBiosPlatform->GetPlatformInfo( + CoreBiosInfo->iBiosPlatform, + EfiGetPlatformEndRomShadowAddr, + NULL, NULL, + &gMaxOpRomAddress, + NULL, NULL, NULL); + if (EFI_ERROR(Status)) { + gMaxOpRomAddress = 0xDFFFF; + } + + ASSERT(gMaxOpRomAddress > 0xC0000 && gMaxOpRomAddress < 0xF0000); + + // + // Initialize memory + // + Status = InitializeLegacyMemory(CoreBiosInfo); + if (EFI_ERROR(Status)) return Status; + + // Get the current IRQ mask + Status = CoreBiosInfo->i8259->GetMask(CoreBiosInfo->i8259, &SaveIrqMask, NULL, NULL, NULL); + ASSERT_EFI_ERROR(Status); + + // Mask all interrupts + IrqMask = -1; + Status = CoreBiosInfo->i8259->SetMask(CoreBiosInfo->i8259, &IrqMask, NULL, NULL, NULL); + ASSERT_EFI_ERROR(Status); + + Status = pRS->GetVariable(L"Setup",&guidSetup, NULL, &Size, &gSetup); + if (EFI_ERROR(Status)) { + pBS->SetMem(&gSetup, sizeof(SETUP_DATA), 0); + } + + // The following code implements the video mode switching policy during + // Option ROMs installation. There are two ingredients in this policy + // implementation - one SDL token and one setup question: + // + // - SDL token CSM_DEFAULT_VMODE_SWITCHING + // - Setup question "Option ROM Messages" (use BIOS/keep current) + // + // Meaning of the "Option ROM Messages" setup options: + // - "Keep Current" installs dummy INT10, output from Option ROMs is + // suppressed, value of CSM_DEFAULT_VMODE_SWITCHING is ignored. + // - "Use BIOS" will have INT10 available for the Option ROMs to output + // the messages. + // Meaning of the CSM_DEFAULT_VMODE_SWITCHING: + // - 0 - switch video mode from graphics to text before executing the + // Option ROM, switch back to graphics afterwards + // - 1 - use text mode during all Option ROMs execution time, no mode + // switching during this time frame. + + gSetTxtMode = CSM_DEFAULT_VMODE_SWITCHING; + if (Status == EFI_SUCCESS && gSetup.ExpansionCardText == 0) { + gSetTxtMode = 2; + } + + // + // Copy Compatibility16 binary into shadow and + // call its Func0 (InitializeYourself) + // + Status = InitCompatibility16(CoreBiosInfo, SystemTable); + if (EFI_ERROR(Status)) return Status; + + // Re-enable IRQ mask + Status = CoreBiosInfo->i8259->SetMask(CoreBiosInfo->i8259, &SaveIrqMask, NULL, NULL, NULL); + ASSERT_EFI_ERROR(Status); + + // + // Create entries for legacy SW SMIs + // + Status = CoreBiosInfo->iBiosPlatform->SmmInit( + CoreBiosInfo->iBiosPlatform, + &CoreBiosInfo->Thunk->Csm16BootTable); + ASSERT_EFI_ERROR(Status); + + // + // Make a new handle and install the protocol + // + CoreBiosInfo->hBios = NULL; + Status = pBS->InstallMultipleProtocolInterfaces( + &CoreBiosInfo->hBios, + &gEfiLegacyBiosProtocolGuid, &CoreBiosInfo->iBios, + &gEfiLegacyBiosExtProtocolGuid, &gAmiCsmExtensionsProtocol, + NULL + ); + ASSERT_EFI_ERROR(Status); + if (EFI_ERROR(Status)) return Status; + + CoreBiosInfo->hVga = NULL; + + gNextRomAddress = (UINT8*)0xC0000; // Beginning of shadow region + gIsBootPrepared = FALSE; + gIsBbsInitialized = FALSE; + gIsMassStorageInstalled = FALSE; + + // + // Allocate memory for saved OpROM structures + // + Status = pBS->AllocatePool(EfiBootServicesData, + MAX_BCV_OPROMS * sizeof(SAVED_PCI_ROM), + &gSavedOprom); + ASSERT_EFI_ERROR(Status); + if (EFI_ERROR(Status)) return Status; + + pBS->SetMem(gSavedOprom, MAX_BCV_OPROMS * sizeof(SAVED_PCI_ROM), 0); + gSavedOprom++; // 1st entry is zero, this will let us find the beginning + // afterwards. + // + // Allocate memory for PciIo's with executed OpROMs + // + Status = pBS->AllocatePool(EfiBootServicesData, + MAX_EXECUTED_OPROMS * sizeof(EXECUTED_PCI_ROM), + &gExecutedRomsPci); + ASSERT_EFI_ERROR(Status); + if (EFI_ERROR(Status)) return Status; + + pBS->SetMem(gExecutedRomsPci, MAX_EXECUTED_OPROMS * sizeof(EXECUTED_PCI_ROM), 0); + gExecutedRomsPci++; // 1st entry is zero, this will let us find the + // beginning afterwards. + // + // Register callback notification on AllDriverConnected. + // This is set to TPL_NOTIFY so that this callback gets executed first + // and GOP will be ready for the other callback function, who wants to + // display based on the AllDriverconnected event + // + Status = pBS->CreateEvent( EFI_EVENT_NOTIFY_SIGNAL, + TPL_NOTIFY, + AllConnectedCallback, + NULL, + &Event ); + + ASSERT_EFI_ERROR(Status); + + Status = pBS->RegisterProtocolNotify( + &gBdsAllDriversConnectedProtocolGuid, + Event, + &gProtocolNotifyRegistration); + + + ASSERT_EFI_ERROR(Status); + + UpdatePciLastBus(); // Update Pci Last Bus number in Csm16 Header + + Status = CreateReadyToBootEvent(TPL_CALLBACK, ReadyToBootNotify, NULL, &Event); + ASSERT_EFI_ERROR(Status); + + return EFI_SUCCESS; // Force success: every unsuccessful status is branched + // before, GetVariable status will not be successful on + // a "fresh" boot. +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: AllConnectedCallback +// +// Description: +// This function is executed after all drivers have been connected. +// +// Notes: +// Specific to Core version, first time this event is signaled in 4.6.3.1. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID +AllConnectedCallback ( + EFI_EVENT Event, + VOID *Context +) +{ + if (gSetTxtMode == 1 && gVgaHandle != NULL) { + pBS->ConnectController(gVgaHandle, NULL, NULL, TRUE); + } +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: FindCompatibility16Table +// +// Description: +// This function identifies the validity of CSM16 binary by searching "$EFI" +// and verifying table checksum and returs the location of $EFI table +// +// Input: +// RomImageStart Binary location address +// RomImageSize Size in bytes +// +// Output: +// Address of the beginning of $EFI table or NULL if this table is not found +// +// Notes: +// Compatibility16 binary is linked with the current section +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_COMPATIBILITY16_TABLE* +FindCompatibility16Table( + VOID *RomImageStart, + UINTN RomImageSize +) +{ + UINT8 *ImageStart = RomImageStart; + UINT8 *ImageEnd = ImageStart + RomImageSize; + + for (;ImageStart < ImageEnd; ImageStart +=16) { + if (*(UINT32*)ImageStart == '$EFI') { + UINT8 TableLength = ((EFI_COMPATIBILITY16_TABLE*)ImageStart)->TableLength; + UINT8 Checksum = 0; + UINT8 i; + for(i=0; i < TableLength; ++i) Checksum += ImageStart[i]; + return (Checksum == 0) ? (EFI_COMPATIBILITY16_TABLE*)ImageStart : 0; + } + } + + return NULL; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: ClearFreeMemory +// +// Description: +// This function goes through system memory map and clears memory that is not +// allocated within the given range. +// +// Input: +// Start and End addresses +// +// Output: +// EFI_STATUS the status of memory clearing operation +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS ClearFreeMemory( + EFI_PHYSICAL_ADDRESS AddrFrom, + EFI_PHYSICAL_ADDRESS AddrTo +) +{ + EFI_MEMORY_DESCRIPTOR *MemoryMap = NULL; + EFI_MEMORY_DESCRIPTOR *MemDesc = NULL; + UINTN DescriptorSize = 0; + UINTN NumberOfDescriptors = 0; + EFI_STATUS Status; + UINTN i; + UINTN Size; + + Status = GetSystemMemoryMap(&MemoryMap, &DescriptorSize, &NumberOfDescriptors); + ASSERT_EFI_ERROR(Status); + + if (EFI_ERROR(Status)) return Status; + + for (i = 0; i < NumberOfDescriptors; i++) + { + MemDesc = (EFI_MEMORY_DESCRIPTOR*)((UINT8*)MemoryMap + i * DescriptorSize); + + if (MemDesc->Type == EfiConventionalMemory && + MemDesc->PhysicalStart < AddrTo && + MemDesc->PhysicalStart >= AddrFrom + ) + { + Size = (UINTN)MemDesc->NumberOfPages * EFI_PAGE_SIZE; + if (((UINTN)MemDesc->PhysicalStart + Size) > (UINTN)AddrTo) + { + Size = (UINTN)AddrTo - (UINTN)MemDesc->PhysicalStart; + } + + pBS->SetMem((VOID*)(UINTN)MemDesc->PhysicalStart, Size, 0); + } + } + + pBS->FreePool(MemoryMap); + + return EFI_SUCCESS; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: InitializeLegacyMemory +// +// Description: +// This function initializes CSM related memory regions +// +// Input: +// BIOS_INFO *CoreBiosInfo +// +// Output: +// EFI_STATUS Legacy memory initialization status +// +// Referrals: +// BIOS_INFO +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS InitializeLegacyMemory(BIOS_INFO *CoreBiosInfo) +{ + EFI_PHYSICAL_ADDRESS Address; + EFI_CPU_ARCH_PROTOCOL Cpu; + EFI_CPU_ARCH_PROTOCOL *pCpu = &Cpu; + EFI_GUID gCpu = EFI_CPU_ARCH_PROTOCOL_GUID; + EFI_STATUS Status; + BDA_DATA *bda; + UINT8 *ebda; + BBS_TABLE *BbsEntry; + UINT16 i; + UINT32 TopOfBaseMemory; + + // + // Set memory attributes for legacy regions + // + Status = pBS->LocateProtocol(&gCpu, NULL, &pCpu); + if (EFI_ERROR(Status)) return Status; + pCpu->SetMemoryAttributes(pCpu, 0xC0000, 0x40000, EFI_MEMORY_WP); // WriteProtected + + // + // Allocate PMM and EBDA areas at the top of 640K; if some memory was already allocated, + // then adjust base memory information accordingly in 40:13 and EBDA + // + Address = 0xa0000; + Status = pBS->AllocatePages ( + AllocateMaxAddress, + EfiBootServicesCode, + PMM_EBDA_LOMEM_SIZE >> 12, // Bytes->4KiloBytes conversion + &Address); + + ASSERT_EFI_ERROR(Status); + if (EFI_ERROR(Status)) return Status; + + TopOfBaseMemory = (UINT32)Address+PMM_EBDA_LOMEM_SIZE; + ASSERT(TopOfBaseMemory>=PMM_EBDA_LOMEM_SIZE+0x8000); // PMM, EBDA, and extra 32KB must fit in + if (TopOfBaseMemory<(PMM_EBDA_LOMEM_SIZE+0x8000)) + return EFI_OUT_OF_RESOURCES; + + // + // Allocate base memory for IVT/BDA(0..2K), PMM data(2K..6K), Thunk (6K..32K), + // low memory PMM and EBDA (640K-PMM_EBDA_LOMEM_SIZE .. 640K). + // + Address = 0; // Allocate 0..32K + Status = pBS->AllocatePages (AllocateAddress, + EfiBootServicesCode, 8, &Address); + ASSERT_EFI_ERROR(Status); + + CoreBiosInfo->Thunk = (THUNK_MEMORY*)0x1800; // at 6K + + // + // Initialize BDA and EBDA + // + bda = (BDA_DATA*)((UINTN) 0x400); + + bda->system_memory = (TopOfBaseMemory>>10)-1; // 1K is for BIOS EBDA + bda->kb_buf_head_ptr = bda->kb_buf_tail_ptr = 0x1E; + bda->motor_time_count = 0xFF; + bda->kb_buff_begin = 0x1E; + bda->kb_buff_end = 0x3E; + + bda->current_floppy_media[0] = 7; + bda->winch_number = 0; +// bda->machine_config is updated later when SIO information becomes available + + bda->ext_bios_data_seg = (TopOfBaseMemory>>4)-0x40; + + ebda = (UINT8*)((UINTN)(TopOfBaseMemory-0x400)); + *ebda = 1; // 1K + + // + // Create BBS table and initialize it with BBS_IGNORE_ENTRY values + // + Status = pBS->AllocatePool( + EfiBootServicesData, + sizeof(BBS_TABLE)*MAX_BBS_ENTRIES_NO, + &CoreBiosInfo->BbsTable); + pBS->SetMem(CoreBiosInfo->BbsTable, sizeof(BBS_TABLE)*MAX_BBS_ENTRIES_NO, 0); + + for (BbsEntry = CoreBiosInfo->BbsTable, i = 0; i < MAX_BBS_ENTRIES_NO; i++, BbsEntry++) { + BbsEntry->BootPriority = BBS_IGNORE_ENTRY; + } + + CoreBiosInfo->BbsEntriesNo = MAX_IDE_CONTROLLER*2 + 1; // 1 floppy + up to MAX_IDE_CONTROLLER*2 HDD + + return Status; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: InitCompatibility16 +// +// Description: +// This function reads Compatibility16 binary into the pre-defined shadow +// memory region, executes InitializeYourself function and initializes Thunk +// data structures. +// +// Input: +// BIOS_INFO *CoreBiosInfo +// EFI_SYSTEM_TABLE *SystemTable +// +// Output: +// EFI_SUCCESS = Success +// +// Notes: +// InitializeLegacyMemory has to be executed prior to this function +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +InitCompatibility16( + IN BIOS_INFO *CoreBiosInfo, + IN EFI_SYSTEM_TABLE *SystemTable +) +{ + EFI_STATUS Status; + VOID *RomImageStart; + UINTN RomImageSize; + EFI_IA32_REGISTER_SET RegSet; + EFI_TO_COMPATIBILITY16_INIT_TABLE *Csm16InitTable; + UINT32 *ivt = (UINT32*)0; + UINT16 RedirSeg, RedirOfs; + UINT8 i; + UINTN LowPmmMemorySizeInBytes; + UINTN HiPmmMemorySizeInBytes; + VOID *HiPmmMemory; + UINTN PciExpressBase; + + struct IRQ_REDIRECTION_CODE { + UINT8 intOpCode; + UINT8 intnumOpCode; + UINT8 iretOpCode; + } RedirTable[8] = { + {0xcd, 0x08, 0xcf}, // int 8, iret + {0xcd, 0x09, 0xcf}, // int 9, iret + {0xcd, 0x0a, 0xcf}, // int a, iret + {0xcd, 0x0b, 0xcf}, // int b, iret + {0xcd, 0x0c, 0xcf}, // int c, iret + {0xcd, 0x0d, 0xcf}, // int d, iret + {0xcd, 0x0e, 0xcf}, // int e, iret + {0xcd, 0x0f, 0xcf} // int f, iret + }; + + UINT8 *InterruptsToPreserve; + UINTN NumberOfInterruptsToPreserve; + + // + // Open all shadow regions for writing and initalize them + // + Status = CoreBiosInfo->iRegion->UnLock (CoreBiosInfo->iRegion, + 0xC0000, 0x40000, NULL); + + pBS->SetMem((UINT8*)(UINTN)0xC0000, gMaxOpRomAddress-0xBFFFF, 0xFF); + pBS->SetMem((UINT8*)(gMaxOpRomAddress+1), 0xFFFFF-gMaxOpRomAddress, 0); + + CoreBiosInfo->HddCount = 0; + + // + // Get Eficompatibility16 binary + // + Status = CoreBiosInfo->iBiosPlatform->GetPlatformInfo( + CoreBiosInfo->iBiosPlatform, + EfiGetPlatformBinarySystemRom, + &RomImageStart, &RomImageSize, + NULL, NULL, NULL, NULL); + if (EFI_ERROR(Status)) return Status; + + pBS->CopyMem((VOID*)((UINTN)(0x100000-RomImageSize)), RomImageStart, RomImageSize); + RomImageStart = (VOID*)((UINTN)(0x100000-RomImageSize)); + + CoreBiosInfo->Csm16Header = FindCompatibility16Table(RomImageStart, RomImageSize); + if (CoreBiosInfo->Csm16Header == NULL) return EFI_NOT_FOUND; + + // + // Save CSM16 entry point + // + CoreBiosInfo->Csm16EntrySeg = CoreBiosInfo->Csm16Header->Compatibility16CallSegment; + CoreBiosInfo->Csm16EntryOfs = CoreBiosInfo->Csm16Header->Compatibility16CallOffset; + + // + // Get PCIe base address + // + Status = CoreBiosInfo->iBiosPlatform->GetPlatformInfo( + CoreBiosInfo->iBiosPlatform, + EfiGetPlatformPciExpressBase, + NULL, NULL, + &PciExpressBase, + NULL, NULL, NULL); + + CoreBiosInfo->Csm16Header->PciExpressBase = (EFI_ERROR(Status))? 0 : (UINT32)PciExpressBase; + +//TODOx64: What is SystemTable pointer is more the 4G in 64 bit mode? +//CSM specification 0.96 defines the pointer as UINT32 + CoreBiosInfo->Csm16Header->EfiSystemTable = (UINT32)SystemTable; + + // + // Initialize thunk code + // + Status = InitializeThunk(CoreBiosInfo); + if (EFI_ERROR(Status)) return Status; + + // + // Fill in EFI_TO_COMPATIBILITY16_INIT_TABLE for InitializeYourself input + // + Csm16InitTable = &CoreBiosInfo->Thunk->Csm16InitTable; // Located below 1 MB + Csm16InitTable->ThunkStart = (UINT32)CoreBiosInfo->Thunk; + Csm16InitTable->ThunkSizeInBytes = sizeof (THUNK_MEMORY); + Csm16InitTable->LowPmmMemory = 0xa0000-PMM_EBDA_LOMEM_SIZE; + Csm16InitTable->ReverseThunkCallSegment = Csm16InitTable->ThunkStart >> 4; + Csm16InitTable->ReverseThunkCallOffset = *(UINT16*)(UINTN)(Csm16InitTable->ThunkStart + 4); + + GetExtendedMemSize(&Csm16InitTable->OsMemoryAbove1Mb); + + // + // E820 table will be valid before PrepareToBoot + // + Csm16InitTable->NumberE820Entries = 0; + + // + // Call LegacyBiosPlatform to get the PMM boundaries + // + Status = CoreBiosInfo->iBiosPlatform->GetPlatformInfo( + CoreBiosInfo->iBiosPlatform, + EfiGetPlatformPmmSize, + NULL, + &LowPmmMemorySizeInBytes, + NULL, + &HiPmmMemorySizeInBytes, + NULL, + NULL); + ASSERT_EFI_ERROR(Status); + + Csm16InitTable->LowPmmMemorySizeInBytes = (UINT32)LowPmmMemorySizeInBytes; + Csm16InitTable->HiPmmMemorySizeInBytes = (UINT32)HiPmmMemorySizeInBytes; + + // + // Allocate Hi memory for PMM + // + Status = pBS->AllocatePool( + EfiBootServicesData, + Csm16InitTable->HiPmmMemorySizeInBytes, + &HiPmmMemory); + ASSERT_EFI_ERROR(Status); + Csm16InitTable->HiPmmMemory = (UINT32)HiPmmMemory; + + // + // Make a call to 16 bit code to initialize itself + // + pBS->SetMem(&RegSet, sizeof (EFI_IA32_REGISTER_SET), 0); + RegSet.X.AX = Compatibility16InitializeYourself; + RegSet.X.ES = EFI_SEGMENT (Csm16InitTable); + RegSet.X.BX = EFI_OFFSET (Csm16InitTable); + + FarCall86 (&CoreBiosInfo->iBios, + CoreBiosInfo->Csm16EntrySeg, + CoreBiosInfo->Csm16EntryOfs, + &RegSet, + NULL, + 0); + if (RegSet.X.AX) Status = (RegSet.X.AX & 0x7FFF) | EFI_ERROR_BIT; + ASSERT_EFI_ERROR(Status); + if (EFI_ERROR(Status)) return Status; + + // InitializeYourself (func #0) that has just executed, returns a pointer to + // LEGACY16_TO_EFI_DATA_TABLE_STRUC to pass the AMIBIOS specific data to CSM16 + // This structure is AMI BIOS specific, so that the following call that updates + // CSM16 data structures must be avoided for non-AMI CSM16 binaries. + + if (IsAMICSM16(CoreBiosInfo->Csm16Header)) { + // Program POST/RT variables in CSM16 based on Setup settings, OEM porting overrides + InitializeCsm16MiscInfo( + (LEGACY16_TO_EFI_DATA_TABLE_STRUC*)(UINTN)Csm16InitTable->BiosLessThan1MB, &gSetup + ); + } + + Status = InitializePortingHooks(CoreBiosInfo); + if (EFI_ERROR(Status)) { + TRACE((-1,"No OEM/Chipset CSM16 porting hooks found.\n")); + } + + // Update project specific fields in CSM16 bin + if (IsAMICSM16(CoreBiosInfo->Csm16Header)) { + + // BIOS date, time, and version information + UINT8 BiosDate[] = TODAY; + UINT8 BiosTime[] = NOW; + UINT8 *p = (UINT8*)0xff55b; + + pBS->CopyMem(p, BiosDate, 6); // MM/DD/ + // Place two-digit year since TODAY is in a different format + p[6] = BiosDate[8]; + p[7] = BiosDate[9]; + + pBS->CopyMem(&p[9], BiosTime, 8); // BIOS time + + Sprintf(&p[23], "%02X.%02X.%02X", + CORE_MAJOR_VERSION, CORE_MINOR_VERSION, CORE_REVISION); + + // Update BIOS project tag + p = (UINT8*)0xff4f0; + + // The following conversion assumes the following: + // 1. PROJECT_TAG to be 5 Bytes long, e.g. '0ABCD'; this assumption + // follows AMI project naming convention. + // 2. PROJECT_MAJOR_VERSION is limited to one decimal digit, i.e. in + // the range from 0 to 9. + // If it is greater than 9, then the upper digit(s) will be truncated. This is + // needed to keep the length of the project tag as 8. + Sprintf(&p[0], "%s%1d%02d", + CONVERT_TO_STRING(PROJECT_TAG), PROJECT_MAJOR_VERSION, PROJECT_MINOR_VERSION); + } + + ChecksumCSM16Header(CoreBiosInfo->Csm16Header); + + // + // Lock legacy region + // + CoreBiosInfo->iRegion->Lock ( + CoreBiosInfo->iRegion, + 0xC0000, + 0x40000, + NULL + ); + + // + // Initialize interrupt save tables with 0 + // + pBS->SetMem(gIrqSav, sizeof(gIrqSav), 0); + + // + // Prepare hardware interrupt (IRQ0...IRQF) redirection table + // + pBS->CopyMem(&CoreBiosInfo->Thunk->InterruptRedirectionCode, RedirTable, 8*3); + RedirSeg = EFI_SEGMENT(CoreBiosInfo->Thunk->InterruptRedirectionCode); + RedirOfs = EFI_OFFSET(CoreBiosInfo->Thunk->InterruptRedirectionCode); + + CoreBiosInfo->i8259->GetVector(CoreBiosInfo->i8259, 0, &irq0); + + for(i = 0; i < 8; i++) { + UINT32 vector; + + HwIrqRedirSav[i] = ivt[irq0 + i]; + vector = RedirSeg << 4 | RedirOfs; + ivt[irq0 + i] = vector; + RedirOfs += 3; + } + + Status = CoreBiosInfo->iBiosPlatform->GetPlatformInfo(CoreBiosInfo->iBiosPlatform, + EfiGetPlatformIntSaveRestoreTable, + &InterruptsToPreserve, + &NumberOfInterruptsToPreserve, + NULL, NULL, 0, 0); + if (!EFI_ERROR(Status)) { + if (NumberOfInterruptsToPreserve > MAX_NUM_IRQS_SAVERESTORE) { + NumberOfInterruptsToPreserve = MAX_NUM_IRQS_SAVERESTORE; + } + for (i = 0; i < NumberOfInterruptsToPreserve; i++) { + gIrqSav[i].irq_num = InterruptsToPreserve[i]; + gIrqSav[i].irq_adr = ivt[InterruptsToPreserve[i]]; + } + } + + + return EFI_SUCCESS; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: GetBbsInfo +// +// Description: +// Presents BBS information to external agents. +// +// Input: +// This Indicates the EFI_LEGACY_BIOS_PROTOCOL instance. +// HddCount Number of HDD_INFO structures. +// HddInfo Onboard IDE controller information. +// BbsCount Number of BBS_TABLE structures. +// BbsTable BBS entry. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +GetBbsInfo ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + OUT UINT16 *HddCount, + OUT struct _HDD_INFO **HddInfo, + OUT UINT16 *BbsCount, + IN OUT struct _BBS_TABLE **BbsTable +) +{ + BBS_TABLE *BbsEntry; + UINT8 count=0; + EFI_STATUS Status; + EFI_IA32_REGISTER_SET RegSet; + + if (!gIsBbsInitialized) { + // + // Insert floppy drive entry + // + BbsEntry = CoreBiosInfo->BbsTable; + BbsEntry->Bus = 0xFF; + BbsEntry->Device = 0xFF; + BbsEntry->Function = 0xFF; + BbsEntry->DeviceType = BBS_FLOPPY; + BbsEntry->Class = 1; + BbsEntry->SubClass = 2; + + switch (GetFDDStatus()) { + case NO_FLOPPY_DRIVE: BbsEntry->BootPriority = BBS_IGNORE_ENTRY; break; + case NO_FLOPPY_DISK: + case FLOPPY_INSERTED: BbsEntry->BootPriority = BBS_UNPRIORITIZED_ENTRY; break; + } + + if (!gIsMassStorageInstalled) { + InstallLegacyMassStorageDevices(); + } + Status = UpdateCsm16Configuration(&CoreBiosInfo->Thunk->Csm16BootTable); + ASSERT_EFI_ERROR(Status); + + // + // Make UpdateBBS call to CSM16 to adjust the table if needed. + // + pBS->SetMem(&RegSet, sizeof (EFI_IA32_REGISTER_SET), 0); + RegSet.X.AX = Compatibility16UpdateBbs; + RegSet.X.ES = EFI_SEGMENT (&CoreBiosInfo->Thunk->Csm16BootTable); + RegSet.X.BX = EFI_OFFSET (&CoreBiosInfo->Thunk->Csm16BootTable); + + Status = CoreBiosInfo->iRegion->UnLock ( + CoreBiosInfo->iRegion, + (UINT32)gMaxOpRomAddress+1, + 0xFFFFF-(UINT32)gMaxOpRomAddress, + NULL + ); + ASSERT_EFI_ERROR(Status); + + FarCall86 (&CoreBiosInfo->iBios, + CoreBiosInfo->Csm16EntrySeg, + CoreBiosInfo->Csm16EntryOfs, + &RegSet, + NULL, + 0); + Status = (RegSet.X.AX)? ((RegSet.X.AX & 0x7FFF) | EFI_ERROR_BIT) : EFI_SUCCESS; + ASSERT_EFI_ERROR(Status); + CoreBiosInfo->iRegion->Lock ( + CoreBiosInfo->iRegion, + (UINT32)gMaxOpRomAddress+1, + 0xFFFFF-(UINT32)gMaxOpRomAddress, + NULL + ); + + CoreBiosInfo->BbsEntriesNo = CoreBiosInfo->Thunk->Csm16BootTable.NumberBbsEntries; + gIsBbsInitialized = TRUE; + } + + *HddCount = CoreBiosInfo->HddCount; + *HddInfo = CoreBiosInfo->Thunk->Csm16BootTable.HddInfo; + *BbsCount = CoreBiosInfo->BbsEntriesNo; + *BbsTable = CoreBiosInfo->BbsTable; + + return EFI_SUCCESS; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: UpdateKeyboardLedStatus +// +// Description: +// Updates the BDA to reflect status of the Scroll Lock, Num Lock, and Caps +// Lock keys and LEDs. +// +// Input: +// This Indicates the EFI_LEGACY_BIOS_PROTOCOL instance. +// Leds Current LED status, as follows: +// Bit 0 - Scroll Lock +// Bit 1 - Num Lock +// Bit 2 - Caps Lock +// Output: +// EFI_SUCCESS The BDA was updated successfully. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +UpdateKeyboardLedStatus( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN UINT8 Leds +) +{ + *(UINT8*)0x417 &= 0x8F; // Clear BIT4, BIT5 and BIT6 + *(UINT8*)0x417 |= (Leds << 4); // Set the state of xLock keys + return EFI_SUCCESS; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: CopyLegacyTable +// +// Description: +// This fuction allocates CSM16 memory within E0000..FFFFF and then copies the +// passed data into allocated region. +// +// Input: +// Data to be copied, data size and CSM16 and memory location attribute +// (F0000_BIT or E0000_BIT or both) +// +// Notes: +// CSM16 memory must be open for writing. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINTN +CopyLegacyTable( + VOID *Table, + UINT16 TableSize, + UINT16 Alignment, + UINT16 Csm16LocationAttribute) +{ + EFI_IA32_REGISTER_SET RegSet; + EFI_STATUS Status; + UINTN Dest = 0; + + Status = CoreBiosInfo->iRegion->UnLock ( + CoreBiosInfo->iRegion, + (UINT32)gMaxOpRomAddress+1, + 0xFFFFF-(UINT32)gMaxOpRomAddress, + NULL + ); + ASSERT_EFI_ERROR(Status); + + pBS->SetMem(&RegSet, sizeof (EFI_IA32_REGISTER_SET), 0); + RegSet.X.AX = Compatibility16GetTableAddress; + RegSet.X.BX = Csm16LocationAttribute; + RegSet.X.CX = TableSize; + RegSet.X.DX = Alignment; + + FarCall86 (&CoreBiosInfo->iBios, + CoreBiosInfo->Csm16EntrySeg, + CoreBiosInfo->Csm16EntryOfs, + &RegSet, + 0, 0); + + Status = (RegSet.X.AX)? EFI_OUT_OF_RESOURCES : EFI_SUCCESS; + ASSERT_EFI_ERROR(Status); + + if (!(EFI_ERROR(Status))) { + Dest = ((UINTN)RegSet.X.DS << 4) + RegSet.X.BX; + pBS->CopyMem((VOID*)Dest, Table, TableSize); + } + + Status = CoreBiosInfo->iRegion->Lock ( + CoreBiosInfo->iRegion, + (UINT32)gMaxOpRomAddress+1, + 0xFFFFF-(UINT32)gMaxOpRomAddress, + NULL + ); + ASSERT_EFI_ERROR(Status); + + return Dest; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: GetLegacyRegion +// +// Description: +// This function is called when EFI needs to reserve an area in the 0xE0000 +// or 0xF0000 64 KB blocks. +// +// Input: +// This Indicates the EFI_LEGACY_BIOS_PROTOCOL instance. +// LegacyMemorySize Requested size in bytes of the region. +// Region Requested region. +// 00 = Either 0xE0000 or 0xF0000 blocks. +// Bit0 = 1 Specify 0xF0000 block +// Bit1 = 1 Specify 0xE0000 block +// Alignment Bit-mapped value specifying the address alignment +// of the requested region. The first nonzero value +// from the right is alignment. +// LegacyMemoryAddress Address assigned. +// +// Output: +// EFI_SUCCESS The requested region was assigned. +// EFI_ACCESS_DENIED The function was previously invoked. +// Other The requested region was not assigned. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +GetLegacyRegion ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN UINTN LegacyMemorySize, + IN UINTN Region, + IN UINTN Alignment, + OUT VOID **LegacyMemoryAddress + ) +{ + EFI_IA32_REGISTER_SET Regs; + EFI_STATUS Status; + + CoreBiosInfo->iRegion->UnLock ( + CoreBiosInfo->iRegion, + (UINT32)gMaxOpRomAddress+1, + 0xFFFFF-(UINT32)gMaxOpRomAddress, + NULL + ); + + pBS->SetMem(&Regs, sizeof (EFI_IA32_REGISTER_SET), 0); + Regs.X.AX = Compatibility16GetTableAddress; + Regs.X.BX = (UINT16) Region; + Regs.X.CX = (UINT16) LegacyMemorySize; + Regs.X.DX = (UINT16) Alignment; + FarCall86 ( + This, + CoreBiosInfo->Csm16EntrySeg, + CoreBiosInfo->Csm16EntryOfs, + &Regs, + NULL, + 0 + ); + + Status = (Regs.X.AX)? ((Regs.X.AX & 0x7FFF) | EFI_ERROR_BIT) : EFI_SUCCESS; + + mAllocatedOnceMemory = (VOID *) (UINTN) ((Regs.X.DS << 4) + Regs.X.BX); + *LegacyMemoryAddress = mAllocatedOnceMemory; + + CoreBiosInfo->iRegion->Lock ( + CoreBiosInfo->iRegion, + (UINT32)gMaxOpRomAddress+1, + 0xFFFFF-(UINT32)gMaxOpRomAddress, + NULL + ); + + return Status; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: CopyLegacyRegion +// +// Description: +// This function is called when copying data to the region assigned by +// EFI_LEGACY_BIOS_PROTOCOL.GetLegacyRegion(). +// +// Input: +// This Indicates the EFI_LEGACY_BIOS_PROTOCOL instance. +// LegacyMemorySize Size in bytes of the memory to copy. +// LegacyMemoryAddress The location within the region returned by +// EFI_LEGACY_BIOS_PROTOCOL.GetLegacyRegion(). +// LegacyMemorySourceAddress Source of the data to copy. +// +// Output: +// EFI_SUCCESS The data was copied successfully. +// EFI_ACCESS_DENIED Either the starting or ending address is out of bounds. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +CopyLegacyRegion ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN UINTN LegacyMemorySize, + IN VOID *LegacyMemoryAddress, + IN VOID *LegacyMemorySourceAddress +) +{ + EFI_STATUS Status = EFI_SUCCESS; + + if (((UINTN)LegacyMemoryAddress <= gMaxOpRomAddress) || + ((UINTN) ((UINTN) (LegacyMemoryAddress) + LegacyMemorySize) > 0xFFFFF)) { + return EFI_ACCESS_DENIED; + } + + Status = CoreBiosInfo->iRegion->UnLock ( + CoreBiosInfo->iRegion, + (UINT32)gMaxOpRomAddress+1, + 0xFFFFF-(UINT32)gMaxOpRomAddress, + NULL + ); + ASSERT_EFI_ERROR(Status); + if (EFI_ERROR(Status)) return Status; + + pBS->CopyMem(LegacyMemoryAddress, LegacyMemorySourceAddress, LegacyMemorySize); + + CoreBiosInfo->iRegion->Lock ( + CoreBiosInfo->iRegion, + (UINT32)gMaxOpRomAddress+1, + 0xFFFFF-(UINT32)gMaxOpRomAddress, + NULL + ); + + return Status; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: PrepareToBoot +// +// Description: +// This function is called when booting an EFI-aware OS with legacy hard disks. +// The legacy hard disks may or may not be the boot device but will be accessed +// by the EFI-aware OS. +// +// Input: +// This Indicates the EFI_LEGACY_BIOS_PROTOCOL instance. +// BbsCount Number of BBS_TABLE structures. +// BbsTable BBS entry. +// +// Output: +// Status of the boot preparation. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +PrepareToBoot( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + OUT UINT16 *BbsCount, + OUT struct _BBS_TABLE **BbsTable +) +{ + EFI_STATUS Status; + EFI_IA32_REGISTER_SET RegSet; + UINTN E820MapAddress; + UINT32 *ivt = (UINT32*)0; + SAVED_PCI_ROM *rom; + UINT32 LockUnlockAddr, LockUnlockSize; + + CoreBiosInfo->NumberE820Entries = UpdateE820Map(CoreBiosInfo->E820Map); + + Status = UpdateCsm16Configuration(&CoreBiosInfo->Thunk->Csm16BootTable); + ASSERT_EFI_ERROR(Status); + + // + // Copy prepared ACPI, E820 tables to F000 segment and update EFI header. + // Note that after executing CopyLegacyTable function E/F000 regions are read-only. + // + E820MapAddress = CopyLegacyTable( + CoreBiosInfo->E820Map, + CoreBiosInfo->NumberE820Entries * sizeof(E820_ENTRY), + 0, // alignment + 0); // either E000 or F000 segment + ASSERT(E820MapAddress); + + // + // Unlock the shadow regions necessary for OpROM execution + // + Status = UnlockShadow( + (UINT8*)(UINTN)0xC0000, + (UINTN)gNextRomAddress-0xC0000, + &LockUnlockAddr, + &LockUnlockSize + ); + ASSERT_EFI_ERROR(Status); + + CoreBiosInfo->Csm16Header->E820Pointer = (UINT32)E820MapAddress; + CoreBiosInfo->Csm16Header->E820Length = CoreBiosInfo->NumberE820Entries * sizeof(E820_ENTRY); + + // + // Restore saved OpROMs and EBDAs associated with them + // + for (rom=gSavedOprom-1; rom->Address; rom--) { + pBS->CopyMem ( + rom->Address, + rom->Data, + ((LEGACY_OPT_ROM_HEADER*)rom->Data)->Size512 * 0x200 + ); + + if (rom->rtDataAddr) { + // Adjust rt data address according to the current EBDA location + if (rom->isEbda) { + rom->rtDataAddr = (UINT8*)(UINTN)((((UINT32)*(UINT16*)0x40e) << 4) + rom->ebdaOffset); + } + + pBS->CopyMem ( + rom->rtDataAddr, + rom->rtData, + rom->rtDataSize + ); + } + } + + // + // Reset number of ATA drives to let CSM16 PrepareToBoot function connect the drives + // + *(UINT8*)0x475 = 0; + // + // Make PrepareToBoot 16 bit call + // + pBS->SetMem(&RegSet, sizeof (EFI_IA32_REGISTER_SET), 0); + RegSet.X.AX = Compatibility16PrepareToBoot; + RegSet.X.ES = EFI_SEGMENT (&CoreBiosInfo->Thunk->Csm16BootTable); + RegSet.X.BX = EFI_OFFSET (&CoreBiosInfo->Thunk->Csm16BootTable); + + FarCall86 (&CoreBiosInfo->iBios, + CoreBiosInfo->Csm16EntrySeg, + CoreBiosInfo->Csm16EntryOfs, + &RegSet, + NULL, + 0); + + Status = LockShadow( + LockUnlockAddr, + LockUnlockSize + ); + ASSERT_EFI_ERROR(Status); + + if (RegSet.X.AX) Status = (RegSet.X.AX & 0x7FFF) | EFI_ERROR_BIT; + + if (EFI_ERROR(Status)) return Status; + + gIsBootPrepared = TRUE; + + *BbsCount = CoreBiosInfo->BbsEntriesNo; + *BbsTable = CoreBiosInfo->BbsTable; + + // + // Reinitialize keyboard buffer tail and head + // + *(UINT16*)0x41A = 0x1E; + *(UINT16*)0x41C = 0x1E; + + return EFI_SUCCESS; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: LegacyBoot +// +// Description: +// Boots a traditional OS +// +// Input: +// This Indicates the EFI_LEGACY_BIOS_PROTOCOL instance. +// BootOption The EFI device path from BootXXXX variable. +// LoadOptionSize Size of LoadOption. +// LoadOption The load option from BootXXXX variable. +// +// Output: +// EFI_DEVICE_ERROR Failed to boot from any legacy boot device +// +// Notes: +// This function normally never returns. It will either boot the OS or +// reset the system if memory has been "corrupted" by loading a boot sector +// and passing control to it. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +LegacyBoot ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN BBS_BBS_DEVICE_PATH *BootOption, + IN UINT32 LoadOptionsSize, + IN VOID *LoadOptions +) +{ + UINT16 BbsCount; + BBS_TABLE *BbsTable; + EFI_EVENT eLegacyBoot; + EFI_STATUS Status; + EFI_IA32_REGISTER_SET RegSet; + UINT32 *ivt = (UINT32*)0; + UINT16 i; + EFI_TIME boottime; + UINT32 localtime; + BDA_DATA *bda; + UINTN Count; + EFI_HANDLE *Buffer; + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TxtOut; + UINTN Size; + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *MediaDevicePath=(MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)BootOption; + EFI_TIMER_ARCH_PROTOCOL *Timer; + UINT8 Data; + static EFI_GUID EfiGlobalVariableGuid = EFI_GLOBAL_VARIABLE; + EFI_EVENT Event; + + PROGRESS_CODE(DXE_LEGACY_BOOT); + + // + // Check if Secure Boot is on; if so, return EFI_SECURITY_VIOLATION + // + Size = sizeof(UINT8); + Status = pRS->GetVariable(EFI_SECURE_BOOT_NAME, &EfiGlobalVariableGuid, NULL, &Size, &Data); + if(!EFI_ERROR(Status) && (Data != 0)) { + return EFI_SECURITY_VIOLATION; // no CSM in secure boot mode + } + + // + // Clear all screens + // + Status = pBS->LocateHandleBuffer(ByProtocol, + &gEfiSimpleTextOutProtocolGuid, + NULL, + &Count, + &Buffer); + + if (!EFI_ERROR (Status)) { + for (i = 0; i < Count; i++) { + Status = pBS->HandleProtocol (Buffer[i], &gEfiSimpleTextOutProtocolGuid, &TxtOut); + ASSERT_EFI_ERROR (Status); + TxtOut->ClearScreen(TxtOut); + } + } + + bda = (BDA_DATA*)((UINTN) 0x400); + if (bda->mode_of_vdo != 3) { + RegSet.X.AX = 3; + Status = CoreBiosInfo->iBios.Int86 (&CoreBiosInfo->iBios, 0x10, &RegSet); + ASSERT_EFI_ERROR(Status); + } + + // + // Update local time data in BDA (dword at 40:6C and byte at 40:70) + // + pRS->GetTime (&boottime, NULL); + localtime = (boottime.Hour * 3600 + boottime.Minute * 60 + boottime.Second) + 1; + + localtime = (localtime * 182)/10; // Count number of timer ticks. + + bda->timer_count = localtime; + bda->timer_count_rolled = 0; + for (i=0; i<4; i++) bda->print_time_max[i] = 0x14; // Maximum time for printing + for (i=0; i<4; i++) bda->rs_232_time_max[i] = 0x1; // Maximum transmission time for COM ports + + UpdateCmos(); // This function unconditionally enables NMI + EnableDisableNmi(); + + // + // Restore saved interrupts + // + for(i = 0; gIrqSav[i].irq_adr; i++) { + ivt[gIrqSav[i].irq_num] = gIrqSav[i].irq_adr; + } + + Status = ShadowAllLegacyOproms(This); // Launch remaining OpROMs + ASSERT_EFI_ERROR(Status); + + // For the 1st boot store BBS table, else update the entries + if (gOriginalBbsTable == NULL){ + Status = pBS->AllocatePool(EfiBootServicesData, (sizeof(BBS_TABLE))*CoreBiosInfo->BbsEntriesNo, + &gOriginalBbsTable); + ASSERT_EFI_ERROR(Status); + pBS->CopyMem(gOriginalBbsTable, CoreBiosInfo->BbsTable, (sizeof(BBS_TABLE))*CoreBiosInfo->BbsEntriesNo); + } + else + { + // find the lowest priority and update failed-to-boot entries with even lower priority values + UINT16 LowestPriority = 0; + + for (i = 0; i < CoreBiosInfo->BbsEntriesNo; i++) + { + if (CoreBiosInfo->BbsTable[i].BootPriority > LowestPriority + && CoreBiosInfo->BbsTable[i].BootPriority <= BBS_LOWEST_ACTIVE_PRIORITY) + { + LowestPriority = CoreBiosInfo->BbsTable[i].BootPriority; + } + } + // the failed entries have the priority of BBS_UNPRIORITIZED_ENTRY (set by TSE) + for (i = 0; i < CoreBiosInfo->BbsEntriesNo; i++) + { + if (CoreBiosInfo->BbsTable[i].BootPriority == BBS_UNPRIORITIZED_ENTRY + && gOriginalBbsTable[i].BootPriority != BBS_UNPRIORITIZED_ENTRY) + { + CoreBiosInfo->BbsTable[i].BootPriority = ++LowestPriority; // bump the entry all the way back + ASSERT(LowestPriority < BBS_LOWEST_ACTIVE_PRIORITY); + } + } + } + + DumpBbsTable(0); + + Status = EnablePciDevices(This); + ASSERT_EFI_ERROR(Status); + +// The following call moved to LEGACYREGION.Lock, EIP29087 +// RemoveDecodingForShadow((UINT32)gNextRomAddress); + + Status = pBS->LocateProtocol(&gEfiTimerArchProtocolGuid, NULL, &Timer); + ASSERT_EFI_ERROR(Status); + + // + // Signal EFI_EVENT_SIGNAL_LEGACY_BOOT event + // + Status = CreateLegacyBootEvent ( + TPL_CALLBACK, NULL, NULL, &eLegacyBoot + ); + + if (Status == EFI_SUCCESS) { + Status = pBS->SignalEvent(eLegacyBoot); + ASSERT_EFI_ERROR(Status); + pBS->CloseEvent(eLegacyBoot); + } + + Timer->SetTimerPeriod (Timer, 0); // Kill timer, mask its interrupt + + Status = CoreBiosInfo->iBiosPlatform->PrepareToBoot( + CoreBiosInfo->iBiosPlatform, + BootOption, + CoreBiosInfo->BbsTable, + LoadOptionsSize, + LoadOptions, + &CoreBiosInfo->Thunk->Csm16BootTable + ); + + Status = PrepareToBoot(This, &BbsCount, &BbsTable); + ASSERT_EFI_ERROR(Status); + + HaltApsBeforeBoot(); + + SignalAmiLegacyBootEvent(); + + // + // Set NumLock state according to Setup question + // + Size = sizeof(SETUP_DATA); + Status = pRS->GetVariable(L"Setup",&guidSetup, NULL, &Size, &gSetup); + if (Status==EFI_SUCCESS) { + i = (gSetup.Numlock)? 2 : 0; + } else { + i = 2; // NumLock is on + } + // + // Note: GetVariable call could have been done once in the entry point, + // but in this case we will have to require reset on Setup.Numlock + // change. + // + UpdateKeyboardLedStatus(This, (UINT8)i); + //(EIP52733+)> + DisconnectSerialIO(); + CoreBiosInfo->i8259->GetMask(CoreBiosInfo->i8259, NULL, NULL, &gProtectedIrqMask, NULL); // Save current Mask + //<(EIP52733+) + + // + // Restore redirected HW IRQ0..7 + // + //(EIP52733+)> + gOldTplValue = pBS->RaiseTPL(TPL_HIGH_LEVEL); // disable interrupts + //<(EIP52733+) + // + // Note: after this point TPL stays HIGH + // + for(i = 0; i < 8; i++) { + ivt[irq0 + i] = HwIrqRedirSav[i]; + } + + // + // Program legacy vector base in 8259 + // + CoreBiosInfo->i8259->SetVectorBase (CoreBiosInfo->i8259, 8, 0x70); + + if(guidcmp(&MediaDevicePath->NameGuid, &WinceGuid) == 0) { + return EFI_NOT_FOUND; // WinCE boot request, called from WinCE module + } + // + // Pass control to CSM16 to execute Int19 + // + pBS->SetMem(&RegSet, sizeof (EFI_IA32_REGISTER_SET), 0); + RegSet.X.AX = Compatibility16Boot; + + FarCall86 (&CoreBiosInfo->iBios, + CoreBiosInfo->Csm16EntrySeg, + CoreBiosInfo->Csm16EntryOfs, + &RegSet, + NULL, + 0); + //(EIP52733+)> + pBS->RaiseTPL(TPL_HIGH_LEVEL); // disable interrupts + CoreBiosInfo->i8259->SetVectorBase(CoreBiosInfo->i8259, MASTER_INTERRUPT_BASE, SLAVE_INTERRUPT_BASE); + CoreBiosInfo->i8259->SetMask(CoreBiosInfo->i8259, NULL , NULL, &gProtectedIrqMask, NULL); + + pBS->RestoreTPL(gOldTplValue); + Timer->SetTimerPeriod (Timer, DEFAULT_TICK_DURATION); + + Status = pBS->CreateEventEx( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + DummyFunction, + NULL, + &gLTEBGuid, + &Event); + + pBS->SignalEvent(Event); + pBS->CloseEvent(Event); + + + if (gVgaHandle != NULL){ + pBS->DisconnectController(gVgaHandle, NULL, NULL); + pBS->ConnectController(gVgaHandle, NULL, NULL, TRUE); + } + ConnectSerialIO(); + + return EFI_SUCCESS; + + //<(EIP52733+) +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: InitializePortingHooks +// +// Description: +// Initialize the data areas for Chipset/OEM 16 bit and 32 bit routines and +// interrupt handlers. +// +// Input: +// BIOS_INFO *CoreBiosInfo +// +// Output: +// EFI_STATUS Success of failure of the operation. +// +// Notes: +// At the point of calling CSM16 is loaded, no CSM16 function is executed. +// E0000..FFFFF area is unlocked. +// +// Referrals: +// BIOS_INFO +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +InitializePortingHooks ( + BIOS_INFO *CoreBiosInfo +) +{ + EFI_COMPATIBILITY16_TABLE *Csm16; + + EFI_IA32_REGISTER_SET Registers; + EFI_STATUS Status; + VOID *OemData; + UINTN OemDataSize; + + Csm16 = CoreBiosInfo->Csm16Header; + + // + // Read OEM code/data image from the FW. The following steps are to be taken: + // 1) Copy it into E000/F000 area + // 2) Initialize the appropriate pointers in CSM16: Csm16->OemIntSegment/Offset, + // Csm16->Oem32Segment/Offset, Csm16->Oem16Segment/Offset. + // + Status = FindEmbeddedRom(OEM_MODULEID, CSM16_VENDORID, CSM16_DEVICEID, + &OemData, &OemDataSize); + + if (EFI_ERROR(Status)) return Status; + + pBS->SetMem(&Registers, sizeof (EFI_IA32_REGISTER_SET), 0); + Registers.X.AX = Compatibility16GetTableAddress; + Registers.X.BX = E0000_BIT; // Allocate from 0xE0000 64 KB block + Registers.X.CX = (UINT32)OemDataSize; + Registers.X.DX = 1; // Alignment + + FarCall86 (&CoreBiosInfo->iBios, + CoreBiosInfo->Csm16EntrySeg, CoreBiosInfo->Csm16EntryOfs, + &Registers, 0, 0); + Status = (Registers.X.AX)? ((Registers.X.AX & 0x7FFF) | EFI_ERROR_BIT) : EFI_SUCCESS; + ASSERT_EFI_ERROR(Status); + if (EFI_ERROR(Status)) return Status; + + gCsm16IntStart = (OEMINT_FUNC*)(UINTN)(((UINTN)Registers.X.DS << 4) + Registers.X.BX); + + // + // Copy the data to E000/F000 + // + pBS->CopyMem((VOID*)gCsm16IntStart, OemData, OemDataSize); + + // + // Initialize OEM data and update CSM16 data pointers + // + gCsm16FuncAddress = InitializeOemInt(&Csm16->OemIntSegment); + gCsm32DataAddress = InitializeOem16(&Csm16->Oem16Segment); +// InitializeOemData(&Csm16->Oem32Segment); + + return EFI_SUCCESS; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: InitializeOemInt +// +// Description: +// Initialize OEM interrupts and update CSM16 OEM int pointer +// +// Input: +// Csm16TableStart The address of the beginning of OEM table +// Csm16Address The address of the beginning of OEM interrupt table handler(s) +// Csm16InitSegPtr The address of the field with OEM interrupt pointer that is +// passed to CSM16. +// +// Output: +// Pointer to the next type of OEM code/data +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +OEM16_FUNC* +InitializeOemInt( + IN OUT UINT16 *Csm16InitSegPtr +) +{ + OEMINT_FUNC *IntFuncTable; + + UINT32 *ivt = (UINT32*)0; + UINT32 *IntSavAddress; + + UINT16 Seg16 = (UINT16)((UINTN)gCsm16IntStart >> 4); + + // + // Update Csm16 data pointer + // + *Csm16InitSegPtr = Seg16; + *(Csm16InitSegPtr+1) = 0; + + // + // Initialize interrupt handlers with the interrupt original locations + // + for (IntFuncTable=gCsm16IntStart;IntFuncTable->interrupt!=0xFFFF;IntFuncTable++) { + IntSavAddress = (UINT32*)((UINTN)gCsm16IntStart+IntFuncTable->funcoffset-sizeof(UINT32)); + // interrupt vector handshake + *IntSavAddress = ivt[IntFuncTable->interrupt]; + ivt[IntFuncTable->interrupt] = ((UINT32)Seg16 << 16) + IntFuncTable->funcoffset; + } + + // + // Return the pointer to the OEM16 function table that immediately follows OEMINT table + // + return (OEM16_FUNC*)(++IntFuncTable); +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: InitializeOem16 +// +// Description: +// Initialize OEM interrupts and update CSM16 OEM int pointer +// +// Input: +// Csm16TableStart The address of the beginning of OEM table +// Csm16Address The address of the beginning of OEM16 data/code +// Csm16InitSegPtr The address of the field with OEM16 pointer +// that is passed to CSM16. +// +// Output: +// Pointer to the next type of OEM code/data +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINTN +InitializeOem16( + IN OUT UINT16 *Csm16InitSegPtr +) +{ + OEM16_FUNC *Oem16FuncTable; + + UINT16 Seg16 = (UINT16)(((UINTN)gCsm16FuncAddress >> 4) & 0xf000); + UINT16 Ofs16 = (UINT16)((UINTN)gCsm16FuncAddress & 0xffff); + + // + // Update Csm16 data pointer + // + *Csm16InitSegPtr = Seg16; + *(Csm16InitSegPtr+1) = Ofs16; + + // + // Find the offset of the first OEM16 routine, use it to update the + // entry points of each CSM16 routine + // + Ofs16 = 0xffff; + for (Oem16FuncTable = gCsm16FuncAddress; + Oem16FuncTable->funcID != 0xffff; Oem16FuncTable++) { + if (Ofs16 > *(UINT16*)&Oem16FuncTable->funcOffset) { + Ofs16 = *(UINT16*)&Oem16FuncTable->funcOffset; + } + } + + for (Oem16FuncTable = gCsm16FuncAddress; + Oem16FuncTable->funcID != 0xffff; Oem16FuncTable++) { + *(UINT16*)&Oem16FuncTable->funcOffset -= Ofs16; + } + + // + // Update the OEM16 segment to SEG so that the 1st routine has an + // entry point at SEG:0. Store this SEG value at gCsm16FuncAddress-2 + // This will make all offsets in OEM16_CSEG valid. + // + *(UINT16*)((UINTN)gCsm16FuncAddress-2) = (UINT16)(((UINTN)gCsm16IntStart + Ofs16) >> 4); + + // + // Return the pointer to the OEM16 function table that immediately follows OEMINT table + // + return (UINTN)(++Oem16FuncTable); +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: Get16BitFuncAddress +// +// Description: +// LegacyBiosExt API, returns the entry point of 16-bit function which was +// added using "CsmOem16Functions" eLink +// +// Input: +// id function ID +// +// Output: +// EFI_SUCCESS if found, Addr is updated with 32-bit pointer to the function +// EFI_NOT_FOUND if function with the requested ID is not found +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +Get16BitFuncAddress ( + IN UINT16 id, + OUT UINT32 *Addr +) +{ + OEM16_FUNC *Oem16FuncTable; + UINT16 Seg16; + + if (gCsm16FuncAddress == NULL) return EFI_NOT_FOUND; + + Oem16FuncTable = gCsm16FuncAddress; + Seg16 = *(UINT16*)((UINTN)gCsm16FuncAddress-2); + + for (; Oem16FuncTable->funcID != 0xffff; Oem16FuncTable++) { + if (Oem16FuncTable->funcID == id) { + *Addr = ((UINT32)Seg16<<4)+(UINT32)Oem16FuncTable->funcOffset; + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: HaltApsBeforeBoot +// +// Description: +// This call is halting APs before giving control to Legacy OS. +// +// Input: +// None +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID +HaltApsBeforeBoot() +{ + UINTN NumberOfCPUs; + EFI_STATUS Status; + EFI_MP_SERVICES_PROTOCOL *MpServices; + + // Execute on running APs + Status = pBS->LocateProtocol (&gEfiMpServicesProtocolGuid, NULL, &MpServices); + ASSERT_EFI_ERROR(Status); + if (EFI_ERROR(Status)) return; + +// Use the #else path for the CPU modules compliant with PI1.1 +#if PI_SPECIFICATION_VERSION < 0x0001000A || BACKWARD_COMPATIBLE_MODE && defined(NO_PI_MP_SERVICES_SUPPORT) + MpServices->GetGeneralMPInfo(MpServices, + &NumberOfCPUs, NULL, NULL, NULL, NULL); +#else +{ + UINTN NumberOfEnabledProcessors; + + MpServices->GetNumberOfProcessors(MpServices, + &NumberOfCPUs, &NumberOfEnabledProcessors); +} +#endif + + NumberOfCPUs--; //Exclude BSP + while(NumberOfCPUs) { + MpServices->EnableDisableAP( + MpServices, + NumberOfCPUs, + FALSE, + NULL); + NumberOfCPUs--; + } +} + + +VOID DumpBbsTable(UINT32 CaseNumber) +{ +#ifdef EFI_DEBUG + BBS_TABLE *BbsEntry; + EFI_HANDLE Handle; + EFI_GUID DevicePathProtocolGuid = EFI_DEVICE_PATH_PROTOCOL_GUID; + EFI_DEVICE_PATH_PROTOCOL *dpp; + UINT32 i; + EFI_STATUS Status; + + TRACE((-1,"_____BBS_TABLE(%x)_____\n", CaseNumber)); + for (BbsEntry = CoreBiosInfo->BbsTable, i = 0; i < MAX_BBS_ENTRIES_NO; i++, BbsEntry++) { + if (BbsEntry->BootPriority == BBS_IGNORE_ENTRY) continue; + TRACE((-1, "#%02d: %d %02X/%02X/%02X %x %x %x %04X handle: %x %x, %s\n", i, BbsEntry->BootPriority, + (BbsEntry->Bus==0xffffffff)? 0xff : BbsEntry->Bus, + (BbsEntry->Device==0xffffffff)? 0xff : BbsEntry->Device, + (BbsEntry->Function==0xffffffff)? 0xff : BbsEntry->Function, + BbsEntry->Class, BbsEntry->SubClass, + BbsEntry->DeviceType, BbsEntry->StatusFlags, + BbsEntry->IBV1, BbsEntry->IBV2, + (UINTN)((UINTN)BbsEntry->DescStringSegment<<4) + BbsEntry->DescStringOffset + )); + Handle = *(VOID**)(&BbsEntry->IBV1); + if (Handle == 0) continue; + Status = pBS->HandleProtocol(Handle, &DevicePathProtocolGuid, &dpp); + TRACE((-1, "Handle=%x, HandleProtocol status: %r, DevicePath: %x\n", Handle, Status, dpp)); + } +#endif +} + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2013, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** |