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/CsmOpROM.c | |
download | zprj-master.tar.xz |
Diffstat (limited to 'Core/EM/CSM/CsmOpROM.c')
-rw-r--r-- | Core/EM/CSM/CsmOpROM.c | 2726 |
1 files changed, 2726 insertions, 0 deletions
diff --git a/Core/EM/CSM/CsmOpROM.c b/Core/EM/CSM/CsmOpROM.c new file mode 100644 index 0000000..15cf5c5 --- /dev/null +++ b/Core/EM/CSM/CsmOpROM.c @@ -0,0 +1,2726 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2010, 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/CsmOpROM.c 171 8/06/14 4:24p Fasihm $ +// +// $Revision: 171 $ +// +// $Date: 8/06/14 4:24p $ +// +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Modules/CSM/Generic/Core/CsmOpROM.c $ +// +// 171 8/06/14 4:24p Fasihm +// [TAG] EIP180681 +// [Category] Improvement +// [Severity] Normal +// [Symptom] Aptio 4 CSM: Clean the setup settings and options. +// [Solution] INT19 trap setup question removed, cleaned code. +// [Files] +// Board\EM\Csm\csm.sd +// Board\EM\Csm\csm.uni +// Core\EM\CSM\CsmBsp.c +// Core\EM\CSM\CsmOpROM.c +// +// 170 11/20/13 6:03p Olegi +// EIP144132: Extend the checking for VGA controller. +// +// 169 10/25/13 3:10p Olegi +// [TAG] EIP141160 +// [Category] Improvement +// [Description] InstallPciRom has the code that updates the list of +// executed ROMs; the condition used there is not correct. +// +// 168 6/04/13 12:15p Olegi +// [TAG] EIP125092 +// [Category] Improvement +// [Description] CSM does not handle PCI ROM 2.1+3.0 combination +// +// 167 5/15/13 3:32p Olegi +// [TAG] EIP123915 +// [Category] Improvement +// [Description] BBS table update in CSM should be atomic operation +// [Files] CsmOpROM.c +// CsmLib.c +// +// 166 4/01/13 8:46a Olegi +// [TAG] EIP111209 +// [Category] Improvement +// [Description] ISA boot devices controlled by the Option ROM are added +// to the boot list. +// [Files] CsmOprom.c +// +// 165 12/20/12 11:02a Olegi +// +// 164 10/23/12 4:45p Olegi +// EIP 104052 - Support for generic Option ROMs with PCI3.0 headers +// +// 163 10/22/12 10:02a Olegi +// [TAG] EIP100790 +// [Category] Improvement +// +// ConnectSerialIO is moved after Video is reconnected. +// +// 162 7/23/12 12:05p Olegi +// [TAG] EIP92895 +// [Category] New Feature +// [Description] Event-based PreProcessOpRom replacement for AptioV +// +// 161 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 +// +// 160 6/15/12 10:39a Olegi +// [TAG] EIP83856 +// [Description] Audio device show can not start under Device Manager +// with UEFI win7 +// +// 159 6/15/12 10:23a Olegi +// [TAG] EIP90155 +// [Category] Improvement +// [Description] CSM changes to support OpRomTxt module genericly +// [Files] CsmOpROM.c +// CsmBsp.c +// +// 158 6/13/12 12:56p Olegi +// [TAG] EIP91376 +// [Category] Improvement +// [Description] Added the verification of gExecutedRomsPci before PCI +// Option ROM execution. +// Increased the number of maximum PCI Option ROMs to 32. +// [Files] CSM.h +// CsmOpROM.c +// +// 157 4/24/12 6:49p Olegi +// +// 156 4/24/12 6:40p Olegi +// [TAG] EIP86770 +// [Category] Improvement +// [Description] Added ExecuteBcv function. +// +// 155 2/10/12 10:09a Olegi +// [TAG] EIP82449 +// [Category] Bug Fix +// [Severity] Important +// [Symptom] During LegacyBoot some EBDA locations might be destroyed +// [RootCause] The amount of EBDA allocated by the Option ROM was not +// properly calculated in case Option ROM uses several allocation methods +// at the same time: EBDA and 40-:13. +// [Solution] Corrected the calculation of the size of allocated EBDA +// [Files] CsmOpROM.c +// +// 154 12/23/11 2:47p Olegi +// [TAG] EIP79228 +// [Category] Improvement +// [Description] Implement CSM_INT19_TRAP_IMMEDIATE_ACTION functionality +// [Files] CsmOpROM.c +// CSM.c +// +// 153 12/13/11 10:58a Matthewh +// +// 152 12/13/11 10:53a Matthewh +// [TAG] EIP77897 +// [Category] Bug Fix +// [Severity] Normal +// [Symptom] Using More then one ISA PnP Card with an Option ROM that have +// overlapping Memory ranges only one Option ROM will be run. Address range +// may be skipped if the address is already aligned properly before "AND"ing +// with the Aln variable and adding the alignment. +// [RootCause] The global variable gNextRomAddress is not moved to the next +// available locatation untill the InstallIsaRom function is run but by then +// both Option Roms have already been assigned to the same address. There is +// no check to see if the address is already aligned properly before the +// alignment calculation is applied. +// [Solution] Change GetShadowRamAddress function to update gNextRomAddress +// and remove the update of gNextRomAddress from InstallIsaRom. Update +// GetShadowRamAddress function to take into account that the address may +// already be aligned and no need to add the alignment. +// [Files] CsmOpROM.c + +// +// 151 11/11/11 6:09p Olegi +// [TAG] EIP74894 +// [Category] Improvement +// [Description] In some cases OEM logo partially remains on the screen +// during EFI shell/boot popup menu. +// [Files] csmoprom.c +// +// 150 10/31/11 12:38p Olegi +// [TAG] EIP72804 +// [Category] Improvement +// [Description] Promise FastTrak 2650 Option ROM hangs the system. +// [Files] CsmOprom.c +// +// 149 10/12/11 2:56p Olegi +// [TAG] EIP72177 +// [Category] Improvement +// [Description] CheckPmmTable function suppressed. +// [Files] CsmOpROM.c +// CSM.c +// CsmBsp.c +// CSM.SDL +// +// 148 9/30/11 12:46p Olegi +// Undone all changes related to EIP70382 (check-in 144, 146, 147. INT19 +// trapping modifications are added to CSM16. +// +// 147 9/29/11 10:52a Olegi +// Continuation of check-in #144 related to EIP70382; clearing keyboard +// status is moved to FarCall86. +// +// 146 9/29/11 9:45a Olegi +// Continuation of check-in #144 related to EIP70382; adding a check for +// Setup.I19Trap. +// +// 145 9/28/11 10:45a Olegi +// [TAG] EIP71227 +// [Category] Improvement +// [Description] Added out-of-resource reporting during memory +// allocation failure. +// [Files] csmoprom.c +// +// 144 9/27/11 6:26p Olegi +// [TAG] EIP70382 +// [Category] Bug Fix +// [Severity] Important +// [Symptom] Keyboard is not functional in some Option ROM setup utility +// [RootCause] When Option ROM hot key combination has Ctrl as a part of +// it (Ctrl-H), then the state of Ctrl key might remain in 40:17 after +// control comes back to EFI. +// If after this another 16-bit code is executed and requires keyboard +// handling, having improper settings in 40:17 affect the key reporting +// data. +// [Solution] Make sure the booting process go through INT19, and Option +// ROM setup is not invoked earlier during PrepareToBoot. +// INT19 code has the initialization of 40:17 that resolves the issue. +// [Files] CsmOpROM.c +// +// 143 8/25/11 10:06a Olegi +// Change in CheckPmmTable: skip the low memory PMM entries. +// +// 142 8/22/11 9:59a Olegi +// [TAG] EIP66613 +// [Category] Improvement +// [Description] Dynamic PMM size. +// [Files] CsmOprom.c +// +// 141 8/15/11 5:52p Olegi +// Changed the type of the counter variable in CheckPmmTable function from +// UINT8 to UINTN. +// +// 140 8/11/11 4:23p Olegi +// [TAG] EIP66636 +// [Category] Improvement +// [Description] Validation of legacy Option ROM modified: some Option +// ROMs are not properly report last image indicator (Adaptec SCSI BIOS +// v4.31.4 (c) 2007). +// [Files] CsmOpROM.c +// +// 139 6/21/11 2:03p Olegi +// 1. EIP62285: Immediate INT19 execution call added +// 2. VGA enabling properly done after VGA driver is disconnected +// 3. Multiple legacy Option ROMs handling corrected to return the 1st +// legacy +// +// 138 6/15/11 10:43a Olegi +// [TAG] EIP61986 +// [Category] Bug Fix +// [Severity] Normal +// [Symptom] Post Screen corruption occurs while loading multiple Option +// ROMS. +// [RootCause] There are cases when video get reconnected outside CSM, +// in between Option ROM execution. That gets VGA disconnect/connect logic +// out of hand. +// [Solution] Added the LegacyVgaStartCounter to keep the sync between +// disconnect/connect video, so that setting CSM_DEFAULT_VMODE_SWITCHING +// to 1 will work correctly. +// [Files] CsmOpROM.c +// +// 137 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 +// +// 136 5/20/11 11:27a Olegi +// [TAG] EIP60317 +// [Category] Improvement +// [Description] Do not enable PCI siblings for VGA; if multiple VGA is +// enabled at the same time, OS might have a problem. +// [Files] CsmOprom.c +// +// 135 3/22/11 1:52p Olegi +// [TAG] EIP54935 +// [Category] Improvement +// [Description] Added checking for EBDA deallocation done by the Option +// ROM. +// [Files] CsmOprom.c +// +// 134 3/18/11 10:02a Olegi +// [TAG] EIP56215 +// [Category] Improvement +// [Description] Added $PnP checksum validation. +// [Files] CsmOprom.c +// +// 133 3/15/11 3:54p Olegi +// Changes from #127 are restored. +// +// 132 3/14/11 10:00a Olegi +// [TAG] EIP54942 +// [Category] New Feature +// [Description] CLP support implementation +// [Files] CsmOprom.c LegacyBiosExt.h +// +// 131 3/10/11 5:38a Rajeshms +// [TAG] - EIP 39307 +// [Category]- BUG FIX +// [Severity]- Normal +// [Symptom] - Enter DOS no screen when legacy serial redirection enable +// with option rom message display option is set to " Keep current" in +// setup. +// [RootCause] - Actual INT 10h handler was not replaced after dispatching +// option rom. Legacy console redirection driver INT10h was replaced +// instead of actual handler when option rom message display option was +// set to " Keep current". +// [Solution] - Legacy Console redirection is disabled after its handler +// is replaced in INT 10h place by the dummy handler so that actual INT10h +// handler is replaced by Legacy Console redirection driver. To Support +// redirection for ISA oprom's , enable and disable of legacy console +// redirection has been moved to CsmOpRom.c from OemDxe.c. +// [Files] - CsmOpRom.c, OemDxe.c +// +// 130 3/08/11 2:15p Olegi +// [TAG] EIP55344 +// [Category] Improvement +// [Description] In some cases screen mode is not properly set in +// ConsoleControl after Option ROM execution. +// [Files] CsmOprom.c +// +// 129 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 +// +// 128 2/21/11 1:59p Olegi +// [TAG] EIP54262 +// [Category] Improvement +// [Description] Modification CheckPciRom that sometimes does not return +// the proper PCI ROM Status. +// [Files] CsmOprom.c +// +// 127 1/31/11 4:34p Olegi +// [TAG] EIP51947 +// [Category] Improvement +// [Description] Change the handling of Option ROMs that trap INT19. +// [Files] CsmOpROM.C, AmiLegacy16.bin +// +// 126 1/19/11 10:18a Olegi +// +// 124 12/17/10 12:09p Olegi +// Zero FinalLocationSegment field before executing 2.1 (or any other less +// than 3.0) PCI Option ROM. +// +// 123 12/15/10 1:24p Olegi +// [TAG] EIP47379 +// [Category] Bug Fix +// [RootCause] For multiple images in the Option ROM, if the 1st image +// in not IA32 type, the IA32 image will not be found. +// [Solution] Modified IsValidLegacyPciOpROM routine, now it does not +// break on the non-IA32 image. +// [Files] CsmOpROM.c +// +// 122 12/14/10 11:44a Olegi +// [TAG] EIP48212 +// [Category] Improvement +// [Description] The default implementation of CheckEnablePciSiblings +// can be improved. It could enable all PCI devices with the same VID/DID +// because most of the Option ROMs expect that. +// [Files] CsmOpROM.C +// +// 121 11/08/10 9:21a Olegi +// Modified CsmInstallRom function to use correct PciIo. +// +// 120 10/29/10 11:39a Olegi +// [TAG] EIP47186 +// [Category] Bug Fix +// [RootCause] FindAnyVga returns EFI_SUCCESS in case of headless +// system. +// [Solution] Correct the logic in FindAnyVga. +// [Files] CsmOprom.c +// +// 119 10/21/10 4:34p Olegi +// [TAG] EIP46470 +// [Category] Bug Fix +// [Severity] Important +// [Symptom] VGA enable bit is being set in the upstream PCI bridge +// control register for a non-VGA device that uses an option ROM +// [RootCause] ShadowAllLegacyOproms was enabling EFI_VGA_DEVICE_ENABLE +// attribute before the Option ROM execution; that was done for all +// devices, VGA or not. +// [Solution] Move enabling EFI_VGA_DEVICE_ENABLE attribute inside +// InstallPciRom, do it for VGA controllers only +// [Files] CsmOprom.c +// +// 118 8/17/10 3:15p Olegi +// Fixes discovered by Klockwork II engine: EIP37977 +// +// 117 7/29/10 3:16p Olegi +// EIP39768:: Added a call to ConsolControl->SetMode after switching to +// text mode. +// +// 116 7/21/10 9:30a Olegi +// +// 115 7/20/10 8:59a Olegi +// EIP40907: Initialize Option ROM size field to 0 before ROM execution +// +// 114 7/16/10 12:34p Olegi +// - removed GetPciControllerClassCode function, replaced with inline code +// - Connect/DisconnectSerialIO functions are moved to CSMLIB.C +// +// 113 6/18/10 10:35a Olegi +// Added checking for EFI ROM in IsValidLegacyPciOpROM function. +// +// 112 5/17/10 4:26p Olegi +// Modified the meaning of the 2nd parameter in GetShadowRamAddress +// function. +// +// 111 5/14/10 4:13p Olegi +// +// 110 5/06/10 4:47p Olegi +// +// 109 4/28/10 11:51a Olegi +// Added InstallIsaRom funtion. +// +// 108 4/27/10 12:19p Olegi +// ERROR_CODE is changed to DEVICE_ERROR_CODE, EIP#37648 +// +// +// 104 3/02/10 5:11p Olegi +// Changed the parameters for Pre/PostProcessOpROM function. EIP34085. +// +// 103 2/17/10 4:06p Olegi +// Change in InstallPciRom: if during Option ROM execution there is a +// change in the BBS table, it was not processed correctly. EIP35247. +// +// 102 1/12/10 11:46a Olegi +// Copyright message updated. +// +// 101 12/28/09 8:05a Olegi +// Changed the sequence of updating INT10 vector with the dummy and +// calling PostprocessOpRom function. EIP#32832 +// +// 100 12/21/09 3:03p Olegi +// +// 99 12/08/09 5:07p Olegi +// EIP#15138::Implementation of CheckEnablePciSiblings +// +// 98 11/02/09 9:32a Olegi +// EIP#29425 Added platform function to get the ROMs from FV, since the +// default method do not always satisfy OEM requirements. +// +// 97 8/07/09 2:35p Rameshr +// SD boot support Added. +// +// 96 8/05/09 5:54p Olegi +// - Added check for runtime size being FF +// - Added check for BCV and BEV both being 0 +// - Change related to EIP#24327 +// +// 95 6/15/09 5:50p Olegi +// Disconnect/Reconnect serial IO devices while executing OpROMs. +// EIP#20254. +// +// 94 2/21/09 3:47p Olegi +// FetchBbsDevices is modified to properly handle iSCSI drives. EIP#19614. +// +// 93 12/31/08 11:41a Olegi +// Change in FetchBbsBootDevices: device class and subclass information is +// taken from PCI configuration space, not from PnP header. +// +// 92 12/30/08 9:06a Olegi +// Modification in CheckPciRom: added a check for a valid legacy OpROM +// after calling FindEmbeddedRom. EIP#18520. +// +// 91 12/12/08 3:16p Olegi +// +// 90 12/09/08 4:06p Olegi +// +// 89 11/13/08 1:01p Olegi +// +// 88 11/12/08 4:58p Olegi +// Modified InstallPciRom function that now calls LegacyBiosPlatform to +// get the VGA switching policy override. +// +// 87 10/10/08 3:34p Olegi +// Added PciRomAlreadyExecuted function. +// +// 86 9/23/08 2:18p Olegi +// +// 85 8/18/08 4:53p Olegi +// Modified the rule that verifies the presence of KBC: port 64 is only +// checked for 0xFF, checking for 0x00 is removed. +// +// 84 6/05/08 12:00p Olegi +// - PreProcessRom execution is moved before checking for VGA OpROM is +// installed. +// - ShadowAllRoms function is modified to execute VGA OpROM if it was not +// executed. +// +// 83 6/02/08 3:59p Olegi +// Changes in InstallPciRom that address the memory deallocation issues. +// +// 82 5/21/08 5:00p Olegi +// Bugfix in InstallPciRom: did not free up low memory for 3.0 OpROMs if +// PreprocessOprom returned error. +// +// 81 5/19/08 12:37p Olegi +// Removed EBDA size limitation. +// +// 80 5/09/08 3:26p Olegi +// +// 79 3/12/08 12:56p Olegi +// PROGRESS_CODE((DXE_LEGACY_OPROM_NO_SPACE) is changed to +// ERROR_CODE(DXE_LEGACY_OPROM_NO_SPACE, EFI_ERROR_MAJOR) +// +// 78 3/12/08 11:59a Olegi +// Added progress status codes. +// +// 77 12/17/07 4:22p Olegi +// KBC_SUPPORT dependency removed. +// +// 76 12/04/07 11:07a Olegi +// +// 75 10/17/07 3:25p Olegi +// Replaced NextRomAddress with gNextRomAddress. +// +// 74 9/19/07 2:04p Olegi +// Modified UnlockShadow to return the proper LockUnlockSize. +// +// 73 8/21/07 11:10a Olegi +// Added Intel AHCI Option ROM in the list of PCI 3.0 pretenders +// +// 72 8/10/07 11:04a Olegi +// VGA handling changed. +// +// 71 7/27/07 9:33a Olegi +// PreprocessOpRom call is moved before the shadow memory is open. +// +// 70 7/12/07 5:47p Olegi +// Save BX after dispatching Option ROM to use it later for # of non-BBS +// compliant drives checking. +// +// 69 7/09/07 6:05p Olegi +// +// 68 7/09/07 6:04p Olegi +// Change in FetchBbsDevices for nVIDIA MCP55 LAN device in bridge mode. +// +// 67 6/27/07 3:52p Olegi +// Workaround for OpROMs that use 40:13 to allocate memory, not EBDA. +// +// 66 6/21/07 10:32a Olegi +// +// 65 6/18/07 5:45p Olegi +// bugfix in InstallPciRom for non-BBS compliant card that traps int19 +// +// 64 6/08/07 7:57a Olegi +// Fix in FetchBbsBootDevices that properly creates CDROM, not HDD entry +// for BEV mass storage devices. +// +// 63 6/04/07 12:34p Olegi +// +// 62 6/02/07 10:23a Olegi +// Shadow size correction. +// +// 61 30/05/07 12:34p Anandakrishnanl +// Updated LockShadow routine. +// +// 60 5/29/07 12:20p Olegi +// Added the code to disable Shadow W/R for the unused shadow regions +// after every OpROM execution. +// +// 59 4/27/07 5:13p Olegi +// CSM.CHM file preparation. +// +// 58 4/12/07 1:30p Olegi +// +// 57 4/10/07 5:17p Olegi +// PreprocessOptionRom call moved closer to the actual option ROM +// execution. +// +// 56 3/29/07 5:38p Olegi +// Temporarily revert the option rom code execution: from +// DispatchOptionRom C function to CSM16 function #5. +// +// 55 3/01/07 9:11a Olegi +// +// 54 1/03/07 12:57p Felixp +// New code introduced in label 4.5.3_CSM.6.32_41 had problems. +// Option ROM handling reverted back to label 4.5.2_CSM.6.32_40 +// +// 51 11/14/06 12:37p Olegi +// +// 50 9/22/06 6:13p Olegi +// Introduction of DispatchOptionRom routine. +// +// 49 9/15/06 11:48a Markw +// Removed warning. Added typecast. +// +// 48 8/24/06 6:49p Felixp +// x64 support (warnings/errors fixed) +// +// 47 8/22/06 9:08a Olegi +// "pci30pretender" list is updated with the new Robson card VID/DID. +// +// 46 7/31/06 4:05p Olegi +// +// 45 7/28/06 4:49p Olegi +// +// 43 7/10/06 5:52p Ambikas +// +// 42 5/25/06 2:23p Olegi +// +// 41 5/16/06 1:57p Olegi +// +// 40 5/11/06 12:40p Fredericko +// Make F000 segment writable along with OpROM shadow area for the cases +// where F000 area needs to be updated during DispatchOptionRom call, e.g. +// for non-BBS OpROMs. +// TODO:: remove this call when OpROM handling is moved out of CSM16. +// +// 39 5/01/06 5:06p Olegi +// Added checking for VGA class code in ShadowAllLegacyOproms: enabling +// VGA devices is skipped. +// +// 38 5/01/06 3:23p Olegi +// IsValidLegacyPciOpROM: removed checking for DID/VID as some OpROMs +// might serve several devices. +// +// 37 4/24/06 8:37a Olegi +// +// 36 4/18/06 12:08p Olegi +// Lock/Unlock PAM regions before and after OpROMs. +// +// 35 12/12/05 10:05a Felixp +// Video driver disconnected before switching to text mode +// +// 34 11/29/05 4:17p Olegi +// Get the run-time Option ROM size right after Oprom is executed; the +// value of OpROMSeg:0002 can change later, for example after BCV +// execution (noticed on PCI NetCell RAID SATA card). +// +// 33 10/13/05 6:22p Olegi +// Added HW interrupt handling. +// +// 32 9/30/05 6:27p Olegi +// VC7.1 compatibility issues solved. +// +// 31 9/29/05 5:19p Olegi +// UpdateEbdaMap routine added. +// +// 26 8/02/05 11:26a Olegi +// FetchBbsBootDevices returns if runtime size of OpROM equals 0. +// +// 23 6/22/05 8:35a Olegi +// PCI3.0 support +// +// 22 6/21/05 12:12p Olegi +// LegacyBios and LegacyBiosPlatform are combined into one FFS. +// +// 21 4/21/05 9:06a Olegi +// Added the logic for switching the video mode. +// +// 20 4/19/05 11:12a Olegi +// ShadowAllLegacyOproms function added. +// +// 16 3/04/05 1:52p Mandal +// +//**************************************************************************** + +//**************************************************************************** +//<AMI_FHDR_START> +// +// Name: CsmOpROM.c +// Description: CSM PCI ROM interface routines +// +//<AMI_FHDR_END> +//**************************************************************************** + +#include "csm.h" +#include <Protocol/PciIo.h> +#include "token.h" +#include <AmiDxeLib.h> +#include "pci.h" +#include <Protocol/PciIo.h> +#include <Protocol/CsmPlatform.h> +//#include <Protocol/ConsoleControl.h> +#include "setup.h" + +#if LEGACYSREDIR_SUPPORT +#include "Protocol\LegacySredir.h" +#endif + +#if LEGACYSREDIR_SUPPORT +EFI_LEGACY_SREDIR_PROTOCOL *gLegacySredir=NULL; +#endif + +extern SETUP_DATA gSetup; + +extern UINT8 *gNextRomAddress; +extern EXECUTED_PCI_ROM *gExecutedRomsPci; +//extern EFI_GUID gPciIoProtocol; +extern SAVED_PCI_ROM *gSavedOprom; + +EFI_HANDLE gVgaHandle = NULL; + +BOOLEAN gBbsUpdateInProgress = FALSE; + +// +// gSetTxtMode +// 0 - switching to text mode is needed +// 1 - switching is needed, restoration is not +// 2 - neither switching nor restoration is needed +// +extern UINT8 gSetTxtMode; +extern BOOLEAN gServiceRomsExecuted; + +#pragma pack(push, 1) + +// EFI Load Option needed for call to LegacyBios->LegacyBoot() +static struct { + EFI_LOAD_OPTION LoadOption; + CHAR16 Description[10]; + BBS_BBS_DEVICE_PATH BbsDevicePath; + EFI_DEVICE_PATH_PROTOCOL DevicePathEnd; +} DummyLoadOption = { + { // EFI_LOAD_OPTION LoadOption + 0, // Attributes (UINT32) + sizeof (BBS_BBS_DEVICE_PATH) + + sizeof (EFI_DEVICE_PATH_PROTOCOL), // FilePathListLength (UINT16) + }, + + L"DummyLoad", // Description + + { // BbsDevicePath + { // Header + BBS_DEVICE_PATH, // Type + BBS_BBS_DP, // Subtype + sizeof(BBS_BBS_DEVICE_PATH) // Length + }, + + BBS_HARDDISK, // DeviceType + 0, // StatusFlags + 0, // String + }, + + { // DevicePathEnd + END_DEVICE_PATH, // Type + END_ENTIRE_SUBTYPE, // SubType + sizeof(EFI_DEVICE_PATH_PROTOCOL) // Size + } +}; + +#pragma pack(pop) + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: IsValidLegacyPciOpROM +// +// Description: Tests PCI ROM for Legacy PCI ROM compatibility. +// +// Output: +// TRUE - Image is valid +// FALSE - Image is not valid +// +// Notes: +// From PCI Fw Specification 3.0, 5.2.1.21. Backward Compatibility of Option ROMs Page # 86. +// It is also possible to have two separate ROM images for the same PCI device: one for PCI 2.1 +// System Firmware and one for PCI 3.0 compliance. In this case, the PCI 2.1 Option ROM image +// must appear first in the sequence of images. PCI 3.0 System Firmware will first search for a +// PCI 3.0 Option ROM image and only use the PCI 2.1 Option ROM image if no PCI 3.0 Option ROM +// image is found. +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +BOOLEAN +IsValidLegacyPciOpROM ( + IN UINT32 VidDid, // PCI vendor ID/Device ID + IN OUT VOID **Image, // Pointer to the beginning of PCI Option ROM + IN OUT UINTN *Size // Input: PciIo->RomSize, Output: OpROM size in bytes +) +{ + PCI_DATA_STRUCTURE *pcir; + BOOLEAN IsLastImage = FALSE; + UINT8 *RomStart = *Image; + UINTN RomSize = 0; + BOOLEAN FoundLegacyRom = FALSE; + UINTN RomEnd = (UINTN)*Image + *Size; + + for(; !IsLastImage, (UINTN)RomStart < RomEnd; ) { + // + // Check for 55AA in the beginning of the image + // + if (((LEGACY_OPT_ROM_HEADER*)RomStart)->Signature != 0xaa55) { + RomStart += 512; + continue; + } + + // + // Validate "PCIR" data + // + pcir = (PCI_DATA_STRUCTURE *)(RomStart + *(UINT16*)(RomStart + 0x18)); + if (pcir->Signature != 0x52494350) return FALSE; // "PCIR" + + IsLastImage = pcir->Indicator & 0x80; + + // Code Type Description + // 0x00 Intel IA-32, PC-AT compatible + // 0x01 Open Firmware standard for PCI + // 0x02 Hewlett-Packard PA RISC + // 0x03 EFI Image + // 0x04-0xFF Reserved + // + if (pcir->CodeType == 0) { // IA-32, PC-AT compatible + + if (pcir->Revision != 3 && FoundLegacyRom) + { + // More than one legacy OpROM is present with revision less + // than 3.0; return the pointer and the size of the previous one. + // Image and Size are updated when FoundLegacyRom became TRUE. + // This implements backward compatibility mentioned in the notes + // above. + // + return TRUE; + } + + RomSize = ((LEGACY_OPT_ROM_HEADER*)RomStart)->Size512 << 9; + + if (RomSize == 0) return FALSE; + + *Image = RomStart; + *Size = RomSize; + + if (pcir->Revision == 3) return TRUE; + + FoundLegacyRom = TRUE; + RomStart += RomSize; + continue; + } + + // Non-legacy ROM; find the size from "PCIR" structure + RomSize = pcir->ImageLength << 9; + RomStart += RomSize; + } + + return FoundLegacyRom; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: UpdateEbdaMap +// +// Description: This routine is called after every OpROM (BBS or non-BBS) is +// executed. It updates the locations of EBDA in SAVED_PCI_ROM.ebdaAddr +// fields after OpROM expands EBDA. +// +// Input: The size of EBDA created by the OpROM +// +// Output: None +// +// Notes: When this function is called SAVED_PCI_ROM structure will not have +// the current OpROM information inserted; gSavedOprom is pointing to NULL +// located right after the last valid entry (1st entry is also NULL). +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID +UpdateEbdaMap(UINT32 AddrChange) +{ + SAVED_PCI_ROM *SavedOprom; + + // + // for every SAVED_PCI_ROM update ebdaAddr + // + for (SavedOprom=gSavedOprom-1; SavedOprom->Address; SavedOprom--) { + if (SavedOprom->isEbda && SavedOprom->rtDataAddr) { + SavedOprom->rtDataAddr -= AddrChange; + } + } +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: SaveOprom +// +// Description: This routine saves Oprom that was just executed to the next +// gSavedOprom data field; gSavedOprom is incremented. +// +// Input: Rom address +// Address and size or runtime data taken during ROM initialization +// +// Notes: Saving Oprom data is only required for the option ROMs that +// produce BCV because of early BCV execution; it should not be +// called for non-BBS compliant OpROMs, for those OpROMs related +// memory context will be the same til the system is booted. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID +SaveOprom ( + UINT8 *Rom, + UINT8 *RtDataAddr, + UINT32 RtDataSize, + BOOLEAN IsEbda, + UINT32 EbdaOffset +) +{ + UINTN RomSize = ((LEGACY_OPT_ROM_HEADER*)Rom)->Size512 << 9; + + if (RomSize==0) return; + pBS->AllocatePool(EfiBootServicesData, RomSize, &gSavedOprom->Data); + pBS->CopyMem(gSavedOprom->Data, Rom, RomSize); + gSavedOprom->Address = Rom; + // + // Save runtime data associated with this ROM + // + if (RtDataSize) { + ASSERT(RtDataAddr); // if size is not zero, address must not be zero + gSavedOprom->rtDataAddr = RtDataAddr; + gSavedOprom->rtDataSize = RtDataSize; + gSavedOprom->isEbda = IsEbda; + gSavedOprom->ebdaOffset = EbdaOffset; + pBS->AllocatePool(EfiBootServicesData, RtDataSize, &gSavedOprom->rtData); + pBS->CopyMem(gSavedOprom->rtData, RtDataAddr, RtDataSize); + } + gSavedOprom++; // Points to zero address/data now. +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: ExecuteBcv +// +// Description: +// Checks if the platform allows BCV execution; if so, executes BCV and logs +// the status of HW interrupt changes. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +ExecuteBcv ( + BIOS_INFO *BiosInfo, + UINT8 *PciCfg, + UINT16 BcvSeg, + UINT16 BcvOfs, + UINT8 *Disk +) +{ + EFI_STATUS Status; + UINTN TotalDevices; + UINT32 *DeviceList; + UINTN Counter; + EFI_IA32_REGISTER_SET RegSet; + UINT8 Irq; + UINT32 *Ivt = (UINT32*)0; + UINT32 IrqHandler = 0; + + Status = BiosInfo->iBiosPlatform->GetPlatformInfo(BiosInfo->iBiosPlatform, + EfiGetBcvSkipDeviceList, + &DeviceList, + &TotalDevices, + NULL, NULL, 0, 0); + + ASSERT_EFI_ERROR(Status); + if (EFI_ERROR(Status)) return Status; + + if (TotalDevices > 0 && *DeviceList == 0xffffffff) return EFI_UNSUPPORTED; // Force to skip BCV execution + + for (Counter = 0; Counter < TotalDevices; Counter++) + { + if (*(UINT32*)PciCfg == DeviceList[Counter]) return EFI_UNSUPPORTED; + } + + // Get the hardware interrupt vector and its handler pointer + Irq = *(PciCfg+0x3C); + if (Irq > 0 && Irq < 0xF) + { + Status = BiosInfo->i8259->GetVector (BiosInfo->i8259, Irq, &Irq); // irq has INT number + ASSERT_EFI_ERROR(Status); + IrqHandler = Ivt[Irq]; + } + + // + // Execute BCV + // + pBS->SetMem (&RegSet, sizeof (EFI_IA32_REGISTER_SET), 0); + RegSet.X.ES = BiosInfo->Csm16Header->PnPInstallationCheckSegment; + RegSet.X.DI = BiosInfo->Csm16Header->PnPInstallationCheckOffset; + + FarCall86 (&BiosInfo->iBios, + BcvSeg, + BcvOfs, + &RegSet, + NULL, + 0); + if (IrqHandler && (Ivt[Irq] != IrqHandler)) { + *Disk |= 0x40; // Indicate BCV has hooked HW IRQ + } + + return EFI_SUCCESS; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: FetchBbsBootDevices +// +// Description: Check PCI ROM for PnP structures and inserts BCV/BEV devices +// into BBS table. +// +// Input: Pointer to PCI ROM. +// +// Output: Number of devices installed. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID +FetchBbsBootDevices( + BIOS_INFO *BiosInfo, + UINT8 *Rom, + UINT8 *PciCfgOfs8, + UINTN Bus, UINTN Dev, UINTN Fun, + UINT8 *DiskFrom, + BOOLEAN NewInt18, + BOOLEAN NewInt19) +{ + UINT16 BbsDevType, bbsDevType; + PCI_PNP_EXPANSION_HEADER *PnpHdr; + UINT16 PnpSeg = (UINT16)((UINTN)Rom >> 4); + UINT16 PnpOfs; + BBS_TABLE *BbsTable = BiosInfo->BbsTable; + UINT8 BbsCount; + UINT32 *ivt = (UINT32*)0; + UINT8 i, Checksum; + + gBbsUpdateInProgress = TRUE; + + BbsCount = BiosInfo->BbsEntriesNo; + + // + // Get BBS device type + // +TRACE((-1, "FetchBbsBootDevices: B%x/D%x/F%x, ClassCode %x\n", Bus, Dev, Fun, *(PciCfgOfs8+0xB))); + + if (Bus|Dev|Fun) { + switch (*(PciCfgOfs8+0xB)) { // class code + case PCI_CL_SYSTEM_PERIPHERALS: + if(*(PciCfgOfs8+0xA) == PCI_CL_SYSTEM_PERIPHERALS_SCL_SD) { + BbsDevType = BBS_HARDDISK; + } else { + BbsDevType = BBS_UNKNOWN; + } + break; + case PCI_CL_MASS_STOR: + case PCI_CL_I2O: BbsDevType = BBS_HARDDISK; break; + case PCI_CL_NETWORK: BbsDevType = BBS_EMBED_NETWORK; break; + case PCI_CL_BRIDGE: BbsDevType = BBS_EMBED_NETWORK; //for nVIDIA MCP55 LAN device is bridge mode + break; + case PCI_CL_SER_BUS: BbsDevType = BBS_BEV_DEVICE; break; + + default: BbsDevType = BBS_UNKNOWN; + } + } else { + BbsDevType = BBS_EMBED_NETWORK; // Service ROMs + } + // + // Get PnP information from ROM header and fill BBS structures + // + PnpOfs = *((UINT16*)(Rom + 0x1A));// Offset of the 1st PnP header + for (;;PnpOfs = (UINT16)PnpHdr->NextHeaderOffset) { + PnpHdr = (PCI_PNP_EXPANSION_HEADER*) (Rom + PnpOfs); + if (*((UINT32*)PnpHdr) != 0x506E5024) break; // "$PnP" + + // + // Calculate the CheckSum and check if table is valid + // + Checksum = 0; + for (i = 0; i < sizeof(PCI_PNP_EXPANSION_HEADER); i++){ + Checksum += *(((UINT8*)PnpHdr) + i); + } + if (Checksum) continue; + + if (PnpHdr->BCV == 0 && PnpHdr->BEV == 0 && + !(NewInt18 || NewInt19)) continue; + + // + // Change BbsType from BBS_HARDDISK to BBS_CDROM if BCV==0 and BEV!=0 + // + bbsDevType = BbsDevType; + if (BbsDevType == BBS_HARDDISK && (!PnpHdr->BCV) && PnpHdr->BEV) { + bbsDevType = BBS_CDROM; + } + if (PnpHdr->BCV != 0) { + bbsDevType = BBS_HARDDISK; + } + + BbsTable[BbsCount].DeviceType = bbsDevType; + BbsTable[BbsCount].Bus = (UINT32)Bus; + BbsTable[BbsCount].Device = (UINT32)Dev; + BbsTable[BbsCount].Function = (UINT32)Fun; + BbsTable[BbsCount].Class = *(PciCfgOfs8+0xB); + BbsTable[BbsCount].SubClass = *(PciCfgOfs8+0xA); + BbsTable[BbsCount].DescStringSegment = PnpSeg; + BbsTable[BbsCount].DescStringOffset = PnpHdr->ProductNamePtr; + BbsTable[BbsCount].MfgStringSegment = PnpSeg; + BbsTable[BbsCount].MfgStringOffset = PnpHdr->MfgPtr; + BbsTable[BbsCount].BootPriority = BBS_UNPRIORITIZED_ENTRY; + BbsTable[BbsCount].BootHandlerSegment = PnpSeg; + if (NewInt18) { + BbsTable[BbsCount].AdditionalIrq18Handler = ivt[0x18]; + BbsTable[BbsCount].BootHandlerOffset = ivt[0x18]; + } + if (NewInt19) { + BbsTable[BbsCount].AdditionalIrq19Handler = ivt[0x19]; + BbsTable[BbsCount].BootHandlerOffset = ivt[0x19]; + } + + if (PnpHdr->BCV) { + BbsTable[BbsCount].BootHandlerOffset = PnpHdr->BCV; + ExecuteBcv(BiosInfo, PciCfgOfs8, PnpSeg, PnpHdr->BCV, DiskFrom); + } + if (PnpHdr->BEV && !(NewInt18 || NewInt19)) { + BbsTable[BbsCount].BootHandlerOffset = PnpHdr->BEV; + } + + BbsCount++; + } + + // + // Update number of BBS entries + // + BiosInfo->BbsEntriesNo = BbsCount; + gBbsUpdateInProgress = FALSE; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: Check30ROM +// +// Description: Verifies whether the passed PCI ROM image is PCI 3.0 compatible. +// If so, returns the projected (runtime) size of this ROM. +// +// Output: TRUE - image is PCI 3.0 compliant ROM, size is updated +// FALSE - image is not PCI 3.0 compliant ROM, size remains untouched. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +BOOLEAN +Check30ROM( + IN VOID *RomLocation, + IN OUT UINTN *Size, + IN EFI_HANDLE PciHandle +) +{ + PCI_DATA_STRUCTURE *pcir; + EFI_STATUS Status; + // TODO:: move this patchy data elswhere + static UINT32 pci30pretender[] = { + 0x00041103, // Adaptec 1200 (did 0004 vid 1103) + 0x444d8086, // Intel ROBSON Technology card (444D) + 0x444e8086, // Intel ROBSON Technology card (444E) + 0x26818086 // Intel AHCI Option ROM + }; + + // + // Check for 55AA in the beginning of the image + // + if (((LEGACY_OPT_ROM_HEADER*)RomLocation)->Signature != 0xAA55) return FALSE; + // + // Validate "PCIR" data + // + pcir = (PCI_DATA_STRUCTURE *)((UINT8*)RomLocation + *(UINT16*)((UINT8*)RomLocation + 0x18)); + if (pcir->Signature != 0x52494350) return FALSE; // "PCIR" + + if (pcir->Revision == 3) { + UINT8 i; // check for the OpROMs that are faking PCI3.0 compatibility + UINT32 VidDid; + EFI_PCI_IO_PROTOCOL *PciIo; + + if (PciHandle != NULL) { + + Status = pBS->HandleProtocol(PciHandle, &gEfiPciIoProtocolGuid, &PciIo); + ASSERT(PciIo); + + if (EFI_ERROR(Status)) return FALSE; + + Status = PciIo->Pci.Read(PciIo, EfiPciIoWidthUint32, + 0, // offset + 1, // width + &VidDid); + ASSERT_EFI_ERROR(Status); + + for (i=0; i<(sizeof(pci30pretender)/sizeof(pci30pretender[0])); i++) { + if (pci30pretender[i] == VidDid) return FALSE; + } + } + + *Size = pcir->Reserved1 << 9; // Follow PCI.H definitions + return TRUE; + } + return FALSE; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: CheckPciRom +// +// Description: Tests to see if a traditional PCI ROM exists for this device +// +// Input: +// This Indicates the EFI_LEGACY_BIOS_PROTOCOL instance. +// PciHandle The handle for this device. Type EFI_HANDLE is defined in +// InstallProtocolInterface() in the EFI 1.10 Specification. +// RomImage Pointer to the ROM image. +// RomSize The size of the ROM image. +// Flags The type of ROM discovered. Multiple bits can be set, as follows: +// 00 = No ROM +// 01 = ROM Found +// 02 = ROM is a valid legacy ROM +// +// Output: EFI_SUCCESS A traditional OpROM is available for this device. +// EFI_UNSUPPORTED A traditional OpROM is not supported. +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS CheckPciRom ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN EFI_HANDLE PciHandle, + OUT VOID **RomImage, OPTIONAL + OUT UINTN *RomSize, OPTIONAL + OUT UINTN *Flags +) +{ + EFI_PCI_IO_PROTOCOL *pPciIo; + UINT32 VidDid; + VOID *PciRom; + UINTN PciRomSize = 0; + EFI_STATUS Status; + BOOLEAN ValidRom = FALSE; + UINTN RomStatus = 0; + PCI_STD_DEVICE Pci; + EXECUTED_PCI_ROM *ExecutedRom = gExecutedRomsPci-1; + EXECUTED_PCI_ROM *er; + UINTN PciSegment, PciBus, PciDeviceNumber, PciFunction; + + Status = pBS->HandleProtocol(PciHandle, &gEfiPciIoProtocolGuid, &pPciIo); + if (EFI_ERROR(Status) || (&pPciIo == NULL)) return EFI_UNSUPPORTED; + + PciRom = pPciIo->RomImage; + + Status = pPciIo->Pci.Read(pPciIo, + EfiPciIoWidthUint32, + 0, // offset + 1, // width + &VidDid); + ASSERT_EFI_ERROR(Status); + + if (PciRom) { + PciRomSize = (UINTN)pPciIo->RomSize; + ValidRom = IsValidLegacyPciOpROM(VidDid, &PciRom, &PciRomSize); + RomStatus = ValidRom? 2 : 1; + } + if (!ValidRom) { + Status = GetPlatformPciEmbeddedRom(pPciIo, &PciRom, &PciRomSize); + + if (EFI_ERROR(Status)) { + Status = FindEmbeddedRom(OPROM_MODULEID, (UINT16)VidDid, + *((UINT16*)&VidDid+1), &PciRom, &PciRomSize); + } + + // + // Check whether the identified ROM is a legacy OptionROM, + // and correspondingly modify the value of "RomStatus". + // Note: PciRomSize is initialized here + if (!EFI_ERROR(Status)) { + ValidRom = IsValidLegacyPciOpROM(VidDid, &PciRom, &PciRomSize); + RomStatus = ValidRom? 2 : 1; + } + } + + if(!ValidRom) { + + Status = pPciIo->GetLocation(pPciIo, + &PciSegment, &PciBus, &PciDeviceNumber, &PciFunction); + + // + // Sd option rom can handle all the function on one time + // So if any of one of the function on device already launched option + // no need to launch the option rom for other functions. + // + for (er = ExecutedRom; er->Seg | er->Bus | er->Dev | er->Fun; er--) { + if (er->Seg == PciSegment && er->Bus == PciBus && + er->Dev == PciDeviceNumber) { + break; + } + } + + // + //SD option can handle all the function. So don't launch option for other functions. + // + if(!(er->Seg | er->Bus | er->Dev | er->Fun)) { + + Status = pPciIo->Pci.Read (pPciIo, + EfiPciIoWidthUint32, + 0, + sizeof (Pci) / sizeof (UINT32), + &Pci); + // + //Check For SD controller. If it's SD controller find Sd option rom and launch it. + // + if ( Pci.Header.ClassCode[1] == PCI_CL_SYSTEM_PERIPHERALS_SCL_SD && \ + Pci.Header.ClassCode[2] == PCI_CL_SYSTEM_PERIPHERALS ) { + Status=FindEmbeddedRom( CSM16_MODULEID, CSM16_VENDORID, CSM16_SD_BOOT_DID, &PciRom, &PciRomSize); + if (!EFI_ERROR(Status)) { + ValidRom = IsValidLegacyPciOpROM(VidDid, &PciRom, &PciRomSize); + RomStatus = ValidRom? 2 : 1; + } + } + } + } + + *Flags = RomStatus; + + if (RomStatus == 2) { + if (RomImage != NULL) *RomImage = PciRom; + if (RomSize != NULL) *RomSize = PciRomSize; + return EFI_SUCCESS; + } + + return EFI_UNSUPPORTED; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: FindAnyVga +// +// Description: Returns the first VGA controller handle from PciIo device list. +// +// Input: None +// +// Output: PCI VGA controller PciIo handle +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS FindAnyVga( + OUT EFI_HANDLE* hVga +) +{ + EFI_HANDLE *HandleBuffer; + UINTN n, HandleCount; + EFI_STATUS Status; + UINT8 dData[4]; + EFI_PCI_IO_PROTOCOL *PciIo; + EFI_STATUS VgaStatus = EFI_NOT_FOUND; + + // + // Locate all PciIo handles + // + Status = pBS->LocateHandleBuffer ( + ByProtocol, + &gEfiPciIoProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer); + + ASSERT_EFI_ERROR(Status); + if (EFI_ERROR (Status)) { + return Status; + } + for (n = 0 ; n < HandleCount; n++) { + + Status = pBS->HandleProtocol ( + HandleBuffer[n], + &gEfiPciIoProtocolGuid, + &PciIo); // Get PciIo protocol + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR(Status)) break; + + Status = PciIo->Pci.Read( + PciIo, + EfiPciIoWidthUint32, + 8, // offset + 1, // width + dData); + ASSERT_EFI_ERROR(Status); + if (EFI_ERROR(Status)) break; + + if (dData[3]==PCI_CL_DISPLAY) { + *hVga = HandleBuffer[n]; + VgaStatus = EFI_SUCCESS; + break; + } + } + pBS->FreePool(HandleBuffer); + return VgaStatus; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: PciRomAlreadyExecuted +// +// Description: Reports whether OpROM for a given PciIo already executed. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EXECUTED_PCI_ROM* +PciRomAlreadyExecuted( + IN EFI_PCI_IO_PROTOCOL *PciIo +) +{ + UINTN Seg, Bus, Dev, Fun; + EXECUTED_PCI_ROM *ExecutedRom; + EFI_STATUS Status; + + + Status = PciIo->GetLocation(PciIo, &Seg, &Bus, &Dev, &Fun); + ASSERT_EFI_ERROR(Status); + + for (ExecutedRom = gExecutedRomsPci-1; + ExecutedRom->Seg | ExecutedRom->Bus | ExecutedRom->Dev | ExecutedRom->Fun; + ExecutedRom--) + { + if (ExecutedRom->Seg == Seg && ExecutedRom->Bus == Bus && + ExecutedRom->Dev == Dev && ExecutedRom->Fun == Fun) { + return ExecutedRom; + } + } + return NULL; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: CheckEnablePciSiblings +// +// Description: +// This function manages the ability of the Option ROM to control several PCI +// devices in the system. +// For example, SCSI Option ROM designed for the multi-channel SCSI adaptor +// usually controls all the channels even though they are different PCI +// functions of the same device. Likewise, NIC Option ROM may be able to control +// several NICs located on different PCI devices or even on different PCI buses. +// +// Input: +// PciIo - PCI I/O protocol of the PCI device whose Option ROM is about +// to be executed +// PciCfgData - byte array of device's PCI configuration space (registers 0..3f) +// +// Output: +// EFI_SUCCESS - Option ROM is okay execute +// EFI_ALREADY_STARTED - Option ROM must be skipped +// +// Notes: +// Function code flow: +// 1) Execute OEM porting hook to see if OEM overrides the default device enable +// policy. If so, return EFI_ALREADY_STARTED. +// 2) Enable all function of the given PciIo. +// 3) Enable all PCI devices with the same VID/DID as in given PciIo. +// 4) Return EFI_SUCCESS indicating "greenlight" for Option ROM execution. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +CheckEnablePciSiblings( + EFI_PCI_IO_PROTOCOL *PciIo, + UINT8 *PciCfgData +) +{ + EFI_STATUS Status; + EXECUTED_PCI_ROM *ExecutedRom = gExecutedRomsPci-1; + EFI_HANDLE *HandleBuffer; + UINTN Count; + UINTN HandleCount; + UINTN PciSegment, PciBus, PciDeviceNumber, PciFunction; + UINTN Seg, Bus, Dev, Func; + EFI_PCI_IO_PROTOCOL *CurrentPciIo; + UINT64 Capabilities; + UINT32 VidDid; + UINT8 PciCfgData1[40]; + Status = pBS->LocateHandleBuffer (ByProtocol, &gEfiPciIoProtocolGuid, + NULL, &HandleCount, &HandleBuffer); + ASSERT_EFI_ERROR(Status); + + Status = CheckOemPciSiblings(PciIo, ExecutedRom); + if (Status == EFI_SUCCESS) return EFI_ALREADY_STARTED; + + Status = EnableOemPciSiblings(PciIo); + if (Status == EFI_SUCCESS) return EFI_SUCCESS; + + + Status = PciIo->GetLocation(PciIo, &Seg, &Bus, &Dev, &Func); + ASSERT_EFI_ERROR(Status); + + for (Count = 0; Count < HandleCount; Count++) { + Status = pBS->HandleProtocol (HandleBuffer[Count], &gEfiPciIoProtocolGuid, &CurrentPciIo); + ASSERT_EFI_ERROR(Status); + + Status = CurrentPciIo->GetLocation(CurrentPciIo, + &PciSegment, &PciBus, &PciDeviceNumber, &PciFunction); + + // Check if it is the same device + if (PciBus == Bus && PciDeviceNumber == Dev && PciFunction == Func) continue; + + Status = CurrentPciIo->Pci.Read(CurrentPciIo, EfiPciIoWidthUint32, 0, 1, &VidDid); + ASSERT_EFI_ERROR(Status); + + // Do not do anything else for VGA; if multiple VGA is enabled at the same time, + // OS might have a problem. EIP60317. + Status = CurrentPciIo->Pci.Read(CurrentPciIo, EfiPciIoWidthUint8, 0, 40, PciCfgData1); + ASSERT_EFI_ERROR(Status); + if (PciCfgData1[0xb] == PCI_CL_DISPLAY) continue; + + // Check if it is a different function of the same device or if VID/DID is the same + if ((PciBus == Bus && PciDeviceNumber == Dev) + || (*(UINT32*)PciCfgData == VidDid)) { + + Status = CurrentPciIo->Attributes (CurrentPciIo, + EfiPciIoAttributeOperationSupported, 0, + &Capabilities); // Get device capabilities + ASSERT_EFI_ERROR(Status); + + Status = CurrentPciIo->Attributes (CurrentPciIo, + EfiPciIoAttributeOperationEnable, + Capabilities & EFI_PCI_DEVICE_ENABLE, + NULL); // Enable device + ASSERT_EFI_ERROR(Status); + TRACE((TRACE_ALWAYS, + "CSM OPROM: device B%x/d%x/F%x was enabled for B%x/d%x/F%x OPROM execution.\n", + PciBus, PciDeviceNumber, PciFunction, Bus, Dev, Func)); + } + } + + return EFI_SUCCESS; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: ClpExecute +// +// Description: +// This is CLP execution protocol function that is called by any driver that +// needs to perform device configuration using Command Line Protocol. +// +// Input: +// PciIo Command Line Protocol instance pointer +// CmdInputLine Pointer to a null-terminated input string +// CmdResponseBuffer Pointer to command output buffer +// CmdStatus CLP command execution status +// +// Output: +// EFI_SUCCESS Execution succeeded, result is in CmdStatus +// Any other value Error status of the execution +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +ClpExecute ( + IN EFI_CLP_PROTOCOL *This, + IN OUT UINT8 *CmdInputLine, + IN OUT UINT8 *CmdResponseBuffer, + OUT UINT32 *CmdStatus +) +{ + EFI_STATUS Status; + BOOLEAN FarCallStatus; + EFI_IA32_REGISTER_SET RegSet; + static EFI_LEGACY_BIOS_PROTOCOL *LegacyBios = NULL; + EFI_PCI_IO_PROTOCOL *PciIo; + UINTN Seg, Bus, Dev, Fun; + + // Get LegacyBios protocol for FarCall86 execution + if (LegacyBios == NULL) { + Status = pBS->LocateProtocol(&gEfiLegacyBiosProtocolGuid, NULL, &LegacyBios); + ASSERT_EFI_ERROR(Status); + if (EFI_ERROR(Status)) { + return Status; + } + } + + // Get PciIo protocol for the PCI bus/dev/func information + Status = pBS->HandleProtocol(This->Handle, &gEfiPciIoProtocolGuid, &PciIo); + ASSERT_EFI_ERROR(Status); + if (EFI_ERROR(Status)) { + return Status; + } + + PciIo->GetLocation(PciIo, &Seg, &Bus, &Dev, &Fun); + + // Prepare the registers for CLP execution + pBS->SetMem(&RegSet, sizeof (EFI_IA32_REGISTER_SET), 0); + RegSet.H.AH = (UINT8)Bus; + RegSet.H.AL = ((UINT8)Dev << 3) | (UINT8)Fun; + RegSet.E.EDI = (UINT32)(UINTN)CmdInputLine; + RegSet.E.ESI = (UINT32)(UINTN)CmdResponseBuffer; + + // Execute CLP command + FarCallStatus = FarCall86 (LegacyBios, + This->EntrySeg, + This->EntryOfs, + &RegSet, + NULL, + 0); + + if (FarCallStatus == FALSE) { + Status = EFI_SUCCESS; + *CmdStatus = RegSet.E.EAX; + } else { + Status = EFI_DEVICE_ERROR; + } + + return Status; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: InitClp +// +// Description: +// This function is initializing and installing the CLP protocol. +// +// Input: +// Handle PCI device handle +// Csm16DOT Option ROM related data structure +// +// Output: +// EFI_SUCCESS CLP protocol successfully installed +// EFI_UNSUPPORTED CLP protocol can not be installed on this device +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +InitClp ( + IN EFI_HANDLE Handle, + IN EFI_DISPATCH_OPROM_TABLE *Csm16DOT +) +{ + UINT8 *RomLocation; + PCI_PCIR30_DATA_STRUCTURE *Pcir; + EFI_CLP_PROTOCOL *ClpProtocol; + EFI_STATUS Status; + static EFI_GUID guidClp = EFI_CLP_PROTOCOL_GUID; + + RomLocation = (UINT8*)(UINTN)((UINT32)Csm16DOT->OpromSegment << 4); + + Pcir = (PCI_PCIR30_DATA_STRUCTURE *)(RomLocation + *(UINT16*)(RomLocation + 0x18)); + + if (Pcir->Signature != 0x52494350) { + TRACE((-1, "Init CLP: PCIR signature is missing.")); + return EFI_UNSUPPORTED; + } + + if (Pcir->Revision < 3) { + TRACE((-1, "Init CLP: CLP support requires PCI version 3.0 or above.")); + return EFI_UNSUPPORTED; + } + + if (Pcir->ClpEntryPoint == 0) { + TRACE((-1, "Init CLP: CLP entry point is not present.")); + return EFI_UNSUPPORTED; + } + + if (Handle == NULL) { + TRACE((-1, "Init CLP: CLP ROM must be associated with PCI device.")); + return EFI_UNSUPPORTED; + } + + Status = pBS->AllocatePool(EfiBootServicesData, sizeof(EFI_CLP_PROTOCOL), &ClpProtocol); + ASSERT_EFI_ERROR(Status); + + ClpProtocol->Handle = Handle; + ClpProtocol->EntrySeg = Csm16DOT->OpromSegment; + ClpProtocol->EntryOfs = Pcir->ClpEntryPoint; + ClpProtocol->Execute = ClpExecute; + + return pBS->InstallProtocolInterface( + &Handle, &guidClp, EFI_NATIVE_INTERFACE, ClpProtocol); +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: CsmInstallRom +// +// Description: Executes a given ROM using parameters pre-defined as input in +// EFI_DISPATCH_OPROM_TABLE data structure. +// +// Input: +// CoreBiosInfo The pointer to the BIOS_INFO variable +// PciIo PCI IO handle, NULL for non-PCI ROMs +// Csm16DOT ROM execution input parameters +// NextRomAddress The location in the shadow that will have the run-time image +// of the ROM +// IsVga Video ROM indicator +// +// Output: +// NewRomSize Run-time size of the ROM, in Bytes +// ProcessBootDevices Indicator of the new bootable devices found during +// ROM execution +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +CsmInstallRom ( + IN BIOS_INFO *CoreBiosInfo, + IN EFI_HANDLE Handle, + IN EFI_DISPATCH_OPROM_TABLE *Csm16DOT, + IN UINTN NextRomAddress, + IN BOOLEAN IsVga, + OUT UINT32 *NewRomSize, + OUT BOOLEAN *ProcessBootDevices +) +{ + UINT16 ebdaSeg1, ebdaSeg2; // ebda pointer before and after OpROM execution + UINT16 baseMem1, baseMem2; // 40:13 before and after OpROM execution + UINT32 ebdaSize1, ebdaSize2; // ebda size before and after OpROM execution + BOOLEAN IsEbda; + UINT8 ebdaSizeKB; + EFI_IA32_REGISTER_SET RegSet; + UINT16 RegBX; + UINT8 *RtData = NULL; + UINT32 RtDataSize; + UINT32 RtRomSize; + UINTN SetTxtMode; + EFI_STATUS Status; + UINT32 CurrentInt10 = 0; + UINT8 CurrentMode = 0; + BOOLEAN VgaWasConnected = FALSE; +// static EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl = NULL; + UINT32 EbdaOffset; + EFI_PCI_IO_PROTOCOL *PciIo = NULL; + EFI_PCI_IO_PROTOCOL *VgaPciIo; + static UINT8 LegacyVgaStartCounter = 0; + UINT64 VgaCapabilities; + + if (Handle != NULL) { + Status = pBS->HandleProtocol ( + Handle, + &gEfiPciIoProtocolGuid, + &PciIo); + ASSERT_EFI_ERROR (Status); + } + + // Call LegacyBiosPlatform to get the VGA switching policy override + + Status = CoreBiosInfo->iBiosPlatform->GetPlatformInfo(CoreBiosInfo->iBiosPlatform, + EfiGetPlatformOpromVideoMode, + &PciIo, + &SetTxtMode, + 0, + 0, + (UINT16)gSetTxtMode, + 0); + if (EFI_ERROR(Status)) { + SetTxtMode = (UINTN)gSetTxtMode; + } + + if (IsVga) { + LegacyVgaStartCounter++; + } else { + // If it is not for VGA, than video mode might be forced to 3 for compatibility. + // Current video mode is saved before the call and restored afterwards. + DisconnectSerialIO(); + if (SetTxtMode != 2 && SetTxtMode != 3) { + CurrentMode = *(UINT8*)(UINTN)0x449; + Status = pBS->DisconnectController(gVgaHandle, NULL, NULL); + + // Note: later VgaWasConnected is checked only for SetTxtMode == 0 + + VgaWasConnected = (BOOLEAN)(Status == EFI_SUCCESS); + + if (VgaWasConnected) { + UINT64 Capabilities; + // + // VGA was successfully disconnected. Store the current attributes (to + // be restored after executing OptionROM), and enable MEM/IO/VGA + // decoding according to the supported attributes + // + Status = pBS->HandleProtocol ( + gVgaHandle, + &gEfiPciIoProtocolGuid, + &VgaPciIo); + ASSERT_EFI_ERROR(Status); + + // Store the attributes set by DisconnectController + Status = VgaPciIo->Attributes (VgaPciIo, EfiPciIoAttributeOperationGet, 0, + &VgaCapabilities); + ASSERT_EFI_ERROR(Status); + + Status = VgaPciIo->Attributes (VgaPciIo, EfiPciIoAttributeOperationSupported, 0, + &Capabilities); + ASSERT_EFI_ERROR(Status); + + // Enable VGA legacy MEM/IO access, do not check the status + VgaPciIo->Attributes (VgaPciIo, EfiPciIoAttributeOperationEnable, + (Capabilities & EFI_PCI_DEVICE_ENABLE) + | EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY | EFI_PCI_IO_ATTRIBUTE_VGA_IO, + NULL); + } + +// if (ConsoleControl == NULL) { +// Status = pBS->LocateProtocol(&gEfiConsoleControlProtocolGuid,NULL,&ConsoleControl); +// if (!EFI_ERROR(Status)) { +// Status = ConsoleControl->SetMode(ConsoleControl, EfiConsoleControlScreenText); +// ASSERT_EFI_ERROR(Status); +// } +// } + } + +#if LEGACYSREDIR_SUPPORT + // Enable Legacy Serial Redirection if enabled in the project + pBS->LocateProtocol ( + &gEfiLegacySredirProtocolGuid, + NULL, + &gLegacySredir + ); + if(gLegacySredir != NULL) { + gLegacySredir->EnableLegacySredir(gLegacySredir); + } +#endif + + if (SetTxtMode == 2) { + CurrentInt10 = *(UINT32*)(UINTN)0x40; + *(UINT32*)(UINTN)0x40 = 0xf000f065; // legacy int10 + } + } + + // Initialize CLP (Command Line Protocol) support for this ROM + Status = InitClp(Handle, Csm16DOT); + + // + // Save the current EBDA location to check if OpROM modifies it + ebdaSeg1 = *(UINT16*)(UINTN)0x40e; + ebdaSizeKB = *(UINT8*)((UINTN)ebdaSeg1<<4); + ebdaSize1 = (UINT32)ebdaSizeKB << 10; + ASSERT(ebdaSizeKB); // should be initialized, can not be 0 + baseMem1 = *(UINT16*)(UINTN)0x413; + + // Execute OpROM + +// Status = DispatchOptionRom(CoreBiosInfo, Csm16DOT); +// ASSERT_EFI_ERROR(Status); + + pBS->SetMem(&RegSet, sizeof (EFI_IA32_REGISTER_SET), 0); + RegSet.X.AX = Compatibility16DispatchOprom; + RegSet.X.ES = EFI_SEGMENT (Csm16DOT); + RegSet.X.BX = EFI_OFFSET (Csm16DOT); + + FarCall86 (&CoreBiosInfo->iBios, + CoreBiosInfo->Csm16EntrySeg, + CoreBiosInfo->Csm16EntryOfs, + &RegSet, + NULL, + 0); + + RegBX = RegSet.X.BX; + + // Get the run-time Option ROM size right away; note that the value of + // OpROMSeg:0002 can change later, for example after BCV execution (noticed + // on NetCell PCI SATA RAID card). + RtRomSize = ((LEGACY_OPT_ROM_HEADER*)NextRomAddress)->Size512 * 0x200; +TRACE((-1, "InstallRom...Run-time ROM Size = %x Bytes\n", RtRomSize)); + + // Update EBDA map + ebdaSeg2 = *(UINT16*)(UINTN)0x40e; + ebdaSize2 = *(UINT8*)((UINTN)ebdaSeg2<<4) << 10; + + RtDataSize = 0; + if (ebdaSeg1 > ebdaSeg2) { + RtDataSize = ebdaSize2 - ebdaSize1; // #of bytes taken by this OpROM + UpdateEbdaMap((UINT32)(ebdaSeg1 - ebdaSeg2) << 4); + } + + // Check for a ROM size not being FF + if (RtRomSize == 0x1fe00) RtRomSize = 0; + + // Prepare the output parameters + *ProcessBootDevices = (RegBX == 0 && RtRomSize != 0); + *NewRomSize = RtRomSize; + + if (IsVga) return EFI_SUCCESS; // Done for VBIOS + + // Restore video mode + if (SetTxtMode == 2) { + *(UINT32*)(UINTN)0x40 = CurrentInt10; + } + + // Disable Legacy console redirection +#if LEGACYSREDIR_SUPPORT + if(gLegacySredir == NULL) { + pBS->LocateProtocol ( + &gEfiLegacySredirProtocolGuid, + NULL, + &gLegacySredir + ); + } + if(gLegacySredir != NULL) { + gLegacySredir->DisableLegacySredir(gLegacySredir); + } +#endif + + + // VGA needs to be reconnected in several cases: + // 1) SetTxtMode == 0 + // 2) SetTxtMode == 1 and VGA was started outside CSM control; this is determined + // by the value of LegacyVgaStartCounter (greater than 1) + if (SetTxtMode == 0 || (SetTxtMode == 1 && LegacyVgaStartCounter > 1)) + { + if (VgaWasConnected) { + // Restore VgaCapabilities on VgaPciIo + VgaPciIo->Attributes (VgaPciIo, EfiPciIoAttributeOperationSet, VgaCapabilities, 0); + } else { + RegSet.H.AL = CurrentMode; + RegSet.H.AH = 0; + Status = CoreBiosInfo->iBios.Int86 (&CoreBiosInfo->iBios, 0x10, &RegSet); + ASSERT_EFI_ERROR(Status); + } + + pBS->ConnectController(gVgaHandle, NULL, NULL, TRUE); + + // Reset counter so that following OpROMs will properly switch video when SetTxtMode is 1 + LegacyVgaStartCounter = 1; + +// if (ConsoleControl != NULL) { +// Status = ConsoleControl->SetMode(ConsoleControl, EfiConsoleControlScreenGraphics); +// ASSERT_EFI_ERROR(Status); +// } + } + + ConnectSerialIO(); + + // Update BBS device count + if (CoreBiosInfo->BbsEntriesNo != Csm16DOT->NumberBbbsEntries) { + // CSM16 had inserted some BBS entries for non-BBS devices + CoreBiosInfo->BbsEntriesNo = Csm16DOT->NumberBbbsEntries; + } + + // Process boot devices + if (RegBX == 0 && RtRomSize != 0) { // Either BBS OpROM or no bootable devices connected + + // Save the BBS compliant OpROM memory context here. Note that saving Oprom + // data is only required for the option ROMs that produce BCV because of early + // BCV execution; it should not be called for non-BBS compliant OpROMs, for + // those OpROMs memory context will be the same til the system is booted. + + if (RtDataSize) { + // EBDA was allocated, calculate the address + IsEbda = TRUE; + RtData = (UINT8*)(((UINTN)ebdaSeg2<<4) + ((UINTN)ebdaSizeKB<<10)); + } else { + // EBDA was not allocated; verify data is not requested + // by a blind update of 40:13. This memory allocation method + // was observed on OpROM by Adaptec 39160, FW ver V2.55.0. + IsEbda = FALSE; + baseMem2 = *(UINT16*)(UINTN)0x413; + RtDataSize = (UINT32)(baseMem1-baseMem2)<<10; + if (RtDataSize) { + RtData = (UINT8*)((UINTN)baseMem2<<10); + } + } + + EbdaOffset = IsEbda? (UINT32)ebdaSizeKB<<10 : 0; + SaveOprom ((UINT8*)NextRomAddress, RtData, RtDataSize, IsEbda, EbdaOffset); + } + + return EFI_SUCCESS; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: InstallPciRom +// +// Description: Shadows an OpROM +// +// Input: +// This Indicates the EFI_LEGACY_BIOS_PROTOCOL instance. +// PciHandle The PCI PC-AT* OpROM from this device's ROM BAR will be loaded +// RomImage A PCI PC-AT ROM image. This argument is non-NULL if there is +// no hardware associated with the ROM and thus no PciHandle; +// otherwise it must be NULL. An example is the PXE base code. +// Flags The type of ROM discovered. Multiple bits can be set, as follows: +// 00 = No ROM. +// 01 = ROM found. +// 02 = ROM is a valid legacy ROM. +// DiskStart Disk number of the first device hooked by the ROM. If DiskStart is +// the same as DiskEnd, no disks were hooked. +// DiskEnd Disk number of the last device hooked by the ROM. +// RomShadowAddress Shadow address of PC-AT ROM. +// ShadowedRomSize Size in bytes of RomShadowAddress. +// +// Output: +// EFI_SUCCESS The OpROM was shadowed +// EFI_UNSUPPORTED The PciHandle was not found +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +InstallPciRom ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN EFI_HANDLE PciHandle, + IN VOID **RomImage, + OUT UINTN *Flags, + OUT UINT8 *DiskStart, OPTIONAL + OUT UINT8 *DiskEnd, OPTIONAL + OUT VOID **RomShadowAddress, OPTIONAL + OUT UINT32 *ShadowedRomSize OPTIONAL + ) +{ + EFI_STATUS Status, Status1 = EFI_SUCCESS; + VOID* RomLocation; + EFI_PHYSICAL_ADDRESS Rom30Address = 0; + UINTN RomSize, Rom30Size = 0; + EFI_DISPATCH_OPROM_TABLE *Csm16DOT; + UINTN PciSegment, PciBus, PciDeviceNumber, PciFunction; + BIOS_INFO *CoreBiosInfo = (BIOS_INFO*)This; + UINT32 NewRomSize = 0; + BOOLEAN IsVga = FALSE; + UINT8 DiskFrom = 0x80; + UINT8 DiskTo = 0x80; + UINT8 PciCfgData[0x40]; + EFI_HANDLE *VgaHandlePtr = &gVgaHandle; + UINTN VgaHandleCount; + EFI_PCI_IO_PROTOCOL *PciIo = NULL; + UINT64 Capabilities; + BOOLEAN is30ROM = FALSE; + UINT32 LockUnlockAddr, LockUnlockSize; + CSM_PLATFORM_PROTOCOL *CsmPlatformProtocol; + UINTN LowMem4KPages = 0; + EXECUTED_PCI_ROM *ExecutedRom = NULL; + BOOLEAN ProcessBootDevices; + volatile UINT32 *ivt = (UINT32*)0; + UINT32 Int18; + UINT32 Int19; + BOOLEAN Int19Trapped = FALSE; + UINT32 NumberAlreadyExecutedPciRoms; + + // + // Handle separately HW independent OpROMs, e.g. PXE + // + if (PciHandle == NULL) { + IsVga = FALSE; + PciSegment = 0; PciBus = 0; PciDeviceNumber = 0; PciFunction = 0; + } + else { + Status = pBS->HandleProtocol ( + PciHandle, + &gEfiPciIoProtocolGuid, + &PciIo); // Get PciIo protocol + ASSERT_EFI_ERROR (Status); + + // + // NOTE: The following call will check whether the LegacyOpROM + // has already been executed for PciIo. If so, it returns EFI_SUCCESS. + // + ExecutedRom = PciRomAlreadyExecuted(PciIo); + if (ExecutedRom != NULL) { + *Flags = ExecutedRom->Flags; + if (DiskStart) *DiskStart = ExecutedRom->DiskFrom; + if (DiskEnd) *DiskEnd = ExecutedRom->DiskTo; + if (RomShadowAddress) *RomShadowAddress = ExecutedRom->RomAddress; + if (ShadowedRomSize) *ShadowedRomSize = ExecutedRom->RomSize; + + return EFI_SUCCESS; + } + + // Verify the number of already executed PCI ROMs does not exceed MAX_EXECUTED_OPROMS + NumberAlreadyExecutedPciRoms = 0; + for ( + ExecutedRom = gExecutedRomsPci-1; + ExecutedRom->Seg | ExecutedRom->Bus | ExecutedRom->Dev | ExecutedRom->Fun; + NumberAlreadyExecutedPciRoms++, ExecutedRom-- + ){} + + if (NumberAlreadyExecutedPciRoms >= MAX_EXECUTED_OPROMS) + { + return EFI_OUT_OF_RESOURCES; + } + + Status = PciIo->Pci.Read( + PciIo, + EfiPciIoWidthUint8, + 0, // offset + 0x40, // width + PciCfgData); + ASSERT_EFI_ERROR(Status); + + if (PciCfgData[0xB]==PCI_CL_OLD && PciCfgData[0xA]==PCI_CL_OLD_SCL_VGA) { + IsVga = TRUE; + } + if (PciCfgData[0xB]==PCI_CL_DISPLAY && PciCfgData[0xA]==PCI_CL_DISPLAY_SCL_VGA) { + IsVga = TRUE; + } + + Status = CheckEnablePciSiblings(PciIo, PciCfgData); + if (EFI_ERROR(Status)) return Status; + + Status = PciIo->GetLocation(PciIo, + &PciSegment, &PciBus, &PciDeviceNumber, &PciFunction); + ASSERT_EFI_ERROR(Status); + } + + // + // Execute platform pre-OpROM function + // + pBS->LocateProtocol(&gCsmPlatformProtocolGuid, NULL, &CsmPlatformProtocol); + + if (CsmPlatformProtocol) { + Status = CsmPlatformProtocol->PreProcessOpRom(CsmPlatformProtocol, PciIo, RomImage); + if (EFI_ERROR(Status)) { + CsmPlatformProtocol->PostProcessOpRom(CsmPlatformProtocol, PciIo, RomImage); + return Status; + } + } + + if (IsVga) { + if (CoreBiosInfo->hVga != NULL) { + // + // More than one legacy video is not supported + // We return EFI_SUCCESS so that Video Thunk driver start function + // does not fail. + // + if (CsmPlatformProtocol) { + CsmPlatformProtocol->PostProcessOpRom(CsmPlatformProtocol, PciIo, RomImage); + } + return EFI_SUCCESS; + } + Status = CoreBiosInfo->iBiosPlatform->GetPlatformHandle( + CoreBiosInfo->iBiosPlatform, + EfiGetPlatformVgaHandle, + 0, + &VgaHandlePtr, + &VgaHandleCount, + NULL); + if (!EFI_ERROR(Status)) { // Platform returned VGA handle + if (PciHandle != *VgaHandlePtr) { // Not the one requested by platform + if (CsmPlatformProtocol) { + CsmPlatformProtocol->PostProcessOpRom(CsmPlatformProtocol, PciIo, RomImage); + } + return EFI_UNSUPPORTED; + } + } + } + else { // Not VGA + if (CoreBiosInfo->hVga == NULL) { + EFI_PCI_IO_PROTOCOL *VgaPciIo = NULL; + // + // The control is passed to this routine to install non-VGA OpROM and VGA BIOS is + // not yet installed. This could happen in the following scenarios: + // 1) Video is controlled by Efi native video driver + // 2) BDS is connecting mass storage before consoles + // 3) The system is headless (no video controller) + // + // We will try to find video and launch its oprom; for case #1 we will disconnect + // the native driver and reconnect it after OpROM is executed. + // + Status = CoreBiosInfo->iBiosPlatform->GetPlatformHandle( + CoreBiosInfo->iBiosPlatform, + EfiGetPlatformVgaHandle, + 0, + &VgaHandlePtr, + &VgaHandleCount, + NULL); + if (EFI_ERROR(Status)) { // Platform did not return VGA handle, try to find one + Status1 = FindAnyVga(VgaHandlePtr); + } + if (!EFI_ERROR(Status) || !EFI_ERROR(Status1)) { // Found VGA - enable it and launch OpROM + Status = pBS->HandleProtocol ( + *VgaHandlePtr, + &gEfiPciIoProtocolGuid, + &VgaPciIo); // Get PciIo protocol + ASSERT_EFI_ERROR(Status); + + Status = VgaPciIo->Attributes (VgaPciIo, + EfiPciIoAttributeOperationSupported, 0, + &Capabilities); // Get device capabilities + ASSERT_EFI_ERROR(Status); + + Status = VgaPciIo->Attributes (VgaPciIo, + EfiPciIoAttributeOperationEnable, + Capabilities & EFI_PCI_DEVICE_ENABLE, + NULL); // Enable device + ASSERT_EFI_ERROR(Status); + + InstallPciRom(This, // Recursive call + *VgaHandlePtr, NULL, Flags, + NULL, NULL, NULL, NULL); + } + } + } + + VgaHandlePtr = &gVgaHandle; + + if (IsVga) { + ASSERT(PciIo != NULL); + Status = PciIo->Attributes (PciIo, EfiPciIoAttributeOperationGet, 0, + &Capabilities); // Get device capabilities + ASSERT_EFI_ERROR(Status); + + Status = PciIo->Attributes (PciIo, EfiPciIoAttributeOperationEnable, + Capabilities | EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY | EFI_PCI_IO_ATTRIBUTE_VGA_IO, + NULL); // Enable VGA legacy MEM/IO access + ASSERT_EFI_ERROR(Status); + + CoreBiosInfo->hVga = PciHandle; + *VgaHandlePtr = PciHandle; + } + + // + // Get the ROM image location + // + if (PciHandle != NULL) { + Status = CheckPciRom (This, PciHandle, &RomLocation, &RomSize, Flags); + if (EFI_ERROR(Status) || (RomLocation == NULL)) { + if (CsmPlatformProtocol) { + CsmPlatformProtocol->PostProcessOpRom(CsmPlatformProtocol, PciIo, RomImage); + } + return EFI_UNSUPPORTED; + } + + is30ROM = Check30ROM(RomLocation, &Rom30Size, PciHandle); + } + else { // ROM is not associated with PCI device + RomLocation = *RomImage; + RomSize = ((LEGACY_OPT_ROM_HEADER*)RomLocation)->Size512 * 0x200; + if (RomSize == 0) { + if (CsmPlatformProtocol) { + CsmPlatformProtocol->PostProcessOpRom(CsmPlatformProtocol, PciIo, RomImage); + } + return EFI_UNSUPPORTED; + } + is30ROM = Check30ROM(RomLocation, &Rom30Size, NULL); + } + + // + // For PCI3.0 compliant ROMs reserve base memory for ROM Init code + // + if (is30ROM) { + Rom30Address = 0xA0000; + LowMem4KPages = RomSize >> 12; // Number of 4KB units + if (RomSize % 0x1000) { + LowMem4KPages++; + } + Status = pBS->AllocatePages(AllocateMaxAddress, + EfiBootServicesData, + LowMem4KPages, + &Rom30Address); + ASSERT_EFI_ERROR(Status); + if (EFI_ERROR(Status)) { + if (CsmPlatformProtocol) { + CsmPlatformProtocol->PostProcessOpRom(CsmPlatformProtocol, PciIo, RomImage); + } + DEVICE_ERROR_CODE(DXE_LEGACY_OPROM_NO_SPACE, EFI_ERROR_MAJOR, PciHandle); + return EFI_OUT_OF_RESOURCES; + } + + if (Rom30Address < 0x8000) { + if (CsmPlatformProtocol) { + CsmPlatformProtocol->PostProcessOpRom(CsmPlatformProtocol, PciIo, RomImage); + } + Status = EFI_OUT_OF_RESOURCES; + TRACE(((UINTN)TRACE_ALWAYS,"Can not execute PCI 3.0 OPROM: out of Base Memory.\n")); + DEVICE_ERROR_CODE(DXE_LEGACY_OPROM_NO_SPACE, EFI_ERROR_MAJOR, PciHandle); + goto ReturnErrorStatus; + } + } + + PROGRESS_CODE(DXE_LEGACY_OPROM_INIT); + + // + // Check for the room in shadow for this ROM and copy it from RomLocation. + // + { + UINTN SizeInShadow = is30ROM? Rom30Size : RomSize; + UINTN CopyToAddress = is30ROM? (UINTN)Rom30Address : (UINTN)gNextRomAddress; + + if(((UINTN)(gNextRomAddress) + SizeInShadow) > OPROM_MAX_ADDRESS){ + if (CsmPlatformProtocol) { + CsmPlatformProtocol->PostProcessOpRom(CsmPlatformProtocol, PciIo, RomImage); + } + TRACE(((UINTN)TRACE_ALWAYS,"Can not execute PCI OPROM: out of resources. RomAddr %x RomSize %x\n", gNextRomAddress, SizeInShadow)); + Status = EFI_OUT_OF_RESOURCES; + DEVICE_ERROR_CODE(DXE_LEGACY_OPROM_NO_SPACE, EFI_ERROR_MAJOR, PciHandle); + goto ReturnErrorStatus; + } + + Status = UnlockShadow(gNextRomAddress, SizeInShadow, &LockUnlockAddr, &LockUnlockSize); + ASSERT_EFI_ERROR(Status); + + // + // Initilize the size field to 0. + // + ((LEGACY_OPT_ROM_HEADER*)gNextRomAddress)->Size512=0; + pBS->CopyMem((VOID*)CopyToAddress, RomLocation, RomSize); + } + + DiskFrom = *(UINT8*)(UINTN)0x475 + 0x80; + + Csm16DOT = &CoreBiosInfo->Thunk->DispatchOpromTable; + Csm16DOT->PnpInstallationCheckSegment = CoreBiosInfo->Csm16Header->PnPInstallationCheckSegment; + Csm16DOT->PnpInstallationCheckOffset = CoreBiosInfo->Csm16Header->PnPInstallationCheckOffset; + if (is30ROM) { + Csm16DOT->OpromSegment = (UINT16)(Shr64(Rom30Address, 4)); + Csm16DOT->FinalLocationSegment = (UINT16)((UINTN)gNextRomAddress >> 4); + } + else { + Csm16DOT->OpromSegment = (UINT16)((UINTN)gNextRomAddress >> 4); + Csm16DOT->FinalLocationSegment = 0; + } + + Csm16DOT->PciBus = (UINT8)PciBus; + Csm16DOT->PciDeviceFunction = (UINT8)(PciDeviceNumber << 3 | PciFunction); + Csm16DOT->NumberBbbsEntries = CoreBiosInfo->BbsEntriesNo; + Csm16DOT->BbsTable = (UINT32)(UINTN)(CoreBiosInfo->BbsTable); + + TRACE((TRACE_ALWAYS, "OptionROM for B%x/D%x/F%x is executed from %x:0003\n", + PciBus, PciDeviceNumber, PciFunction, Csm16DOT->OpromSegment)); + + // Save INT18 and INT19 to be able to see its trapping after ROM execution + Int19 = ivt[0x19]; + Int18 = ivt[0x18]; + + Status = CsmInstallRom(CoreBiosInfo, PciHandle, + Csm16DOT, (UINTN)gNextRomAddress, IsVga, &NewRomSize, &ProcessBootDevices); + + Int19Trapped = Int19 != ivt[0x19]; + + if (ProcessBootDevices) { + FetchBbsBootDevices(CoreBiosInfo, + gNextRomAddress, + PciCfgData, + PciBus, + PciDeviceNumber, + PciFunction, + &DiskFrom, + Int18 != ivt[0x18], + Int19 != ivt[0x19]); + } + + // Restore INT18 and INT19 + ivt[0x18] = Int18; + ivt[0x19] = Int19; + + DiskTo = DiskFrom + *(UINT8*)(UINTN)0x475; + + if (CsmPlatformProtocol) { + CsmPlatformProtocol->PostProcessOpRom(CsmPlatformProtocol, PciIo, RomImage); + } + + if (is30ROM) { + // + // For PCI3.0 do necessary things with Setup Routine here, then + // free Rom30Address memory + // + pBS->FreePages(Rom30Address, LowMem4KPages); + } + + if (!is30ROM) { + if (RomSize > NewRomSize) { + pBS->SetMem(gNextRomAddress+NewRomSize, RomSize-NewRomSize, 0xFF); + } + } + Status = LockShadow(LockUnlockAddr, LockUnlockSize); + ASSERT_EFI_ERROR(Status); + + // + // Make the rom size 2K aligned + // + if (NewRomSize % 0x800) { + NewRomSize += (0x800 - (NewRomSize % 0x800)); + } + + // + // Return OPTIONAL parameters: updated disks, oprom address and size. + // + if (DiskStart) *DiskStart = DiskFrom; + if (DiskEnd) *DiskEnd = DiskTo; + if (RomShadowAddress) *RomShadowAddress = gNextRomAddress; + if (ShadowedRomSize) *ShadowedRomSize = NewRomSize; + + // + // Update the list of Executed Roms + // + if (PciHandle) { + gExecutedRomsPci->Seg = PciSegment; + gExecutedRomsPci->Bus = PciBus; + gExecutedRomsPci->Dev = PciDeviceNumber; + gExecutedRomsPci->Fun = PciFunction; + gExecutedRomsPci->Flags = *Flags; + gExecutedRomsPci->DiskFrom = DiskFrom; + gExecutedRomsPci->DiskTo = DiskTo; + gExecutedRomsPci->RomAddress = gNextRomAddress; + gExecutedRomsPci->RomSize = NewRomSize; + gExecutedRomsPci++; + } +TRACE((TRACE_ALWAYS, "PCI OPROM(handle %x, %x/%x/%x): addr %x, size %x\n", + PciHandle, PciBus, PciDeviceNumber, PciFunction, gNextRomAddress, NewRomSize)); + gNextRomAddress += NewRomSize; + + if (Int19Trapped && !IsVga) + { + LegacyBoot ( + &CoreBiosInfo->iBios, + &(DummyLoadOption.BbsDevicePath), + sizeof(DummyLoadOption), + &DummyLoadOption + ); + ASSERT(FALSE); // CONTROL MUST NOT BE GIVEN BACK HERE + // If by any chance we are here, we have to do the needful: + pRS->ResetSystem(EfiResetCold, EFI_SUCCESS, 0, NULL); + } + + return EFI_SUCCESS; + +ReturnErrorStatus: + if (LowMem4KPages != 0) { + pBS->FreePages(Rom30Address, LowMem4KPages); + } + return Status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: GetShadowRamAddress +// +// Description: +// Returns the available shadow RAM address out of the given range. +// +// Input: +// UINT32 *AddrMin Min address +// UINT32 AddrMax Max address +// UINT32 Size Range size, in Bytes +// UINT32 Alignment Range alignment +// +// Output: +// EFI_SUCCESS AddrMin variable contains the available address +// EFI_OUT_OF_RESOURCES The requested memory range is not available in +// the shadow RAM +// Notes: +// This function does not reserve or allocate memory in the shadow RAM +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +GetShadowRamAddress( + IN OUT UINT32 *AddrMin, + IN UINT32 AddrMax, + IN UINT32 Size, + IN UINT32 Alignment +) +{ + UINT32 Addr = *AddrMin; + UINT32 Aln; + + if (Addr > AddrMax) return EFI_INVALID_PARAMETER; + if (Size == 0x00) return EFI_INVALID_PARAMETER; + if (Alignment > OPROM_MAX_ADDRESS) return EFI_INVALID_PARAMETER; + if (AddrMax + Size > (OPROM_MAX_ADDRESS + 1)) return EFI_OUT_OF_RESOURCES; + if (AddrMax < (UINT32)(UINTN)gNextRomAddress) return EFI_OUT_OF_RESOURCES; + + if(Alignment != 0) Alignment--; + Aln = ~Alignment; + + if (Addr < (UINT32)(UINTN)gNextRomAddress) { + Addr = (UINT32)(UINTN)gNextRomAddress; + } + + if ((Alignment !=0) && (Addr & Aln)) { + if ( (Addr & Aln) != Addr){ + Addr += (Alignment+1); + Addr &= Aln; + + } + } + gNextRomAddress = (UINT8 *)(Addr + Size); + *AddrMin = Addr; + +return EFI_SUCCESS; +} + + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: InstallIsaRom +// +// Description: Executes ISA Option ROM +// +// Input: +// This Indicates the EFI_LEGACY_BIOS_PROTOCOL instance. +// RomAddress Location of the Option ROM +// +// Output: +// EFI_SUCCESS ROM was successfully executed +// EFI_OUT_OF_RESOURCES Shadow RAM full, ROM was not executed +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +InstallIsaRom( + IN EFI_LEGACY_BIOS_EXT_PROTOCOL *This, + IN UINTN RomAddress +) +{ + UINTN RomSize; + BOOLEAN ProcessBootDevices; + EFI_STATUS Status; + EFI_DISPATCH_OPROM_TABLE *Csm16DOT; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; + BIOS_INFO *CoreBiosInfo; + CSM_PLATFORM_PROTOCOL *CsmPlatformProtocol; + UINT8 PciCfgData[0x40] = {0}; + UINT8 DiskFrom = 0x80; + volatile UINT32 *ivt = (UINT32*)0; + UINT32 Int18; + UINT32 Int19; + + // Validate ISA ROM + if (((LEGACY_OPT_ROM_HEADER*)RomAddress)->Signature != 0xAA55) { + TRACE((-1, "Can not execute ISA ROM: missing 0xAA55 signature.\n")); + return EFI_UNSUPPORTED; + } + + // See if ROM fits in the shadow + RomSize = ((LEGACY_OPT_ROM_HEADER*)RomAddress)->Size512 << 9; + if((RomAddress + RomSize) > OPROM_MAX_ADDRESS) { + TRACE((-1, "Can not execute ISA ROM: won't fit in the shadow memory.\n")); + return EFI_OUT_OF_RESOURCES; + } + + // Get BIOS_INFO variable pointer + Status = pBS->LocateProtocol(&gEfiLegacyBiosProtocolGuid, NULL, &LegacyBios); + ASSERT_EFI_ERROR(Status); + CoreBiosInfo = (BIOS_INFO*)LegacyBios; + + // + // Execute platform pre-OpROM function + // + pBS->LocateProtocol(&gCsmPlatformProtocolGuid, NULL, &CsmPlatformProtocol); + + if (CsmPlatformProtocol) { + Status = CsmPlatformProtocol->PreProcessOpRom(CsmPlatformProtocol, NULL, (VOID*)&RomAddress); + if (EFI_ERROR(Status)) { + CsmPlatformProtocol->PostProcessOpRom(CsmPlatformProtocol, NULL, (VOID*)&RomAddress); + return Status; + } + } + + DiskFrom = *(UINT8*)(UINTN)0x475 + 0x80; + + Csm16DOT = &CoreBiosInfo->Thunk->DispatchOpromTable; + Csm16DOT->OpromSegment = (UINT16)(RomAddress >> 4); + Csm16DOT->NumberBbbsEntries = CoreBiosInfo->BbsEntriesNo; + Csm16DOT->BbsTable = (UINT32)(UINTN)(CoreBiosInfo->BbsTable); + + TRACE((TRACE_ALWAYS, "OptionROM for ISA Device is executed from %x:0003\n", Csm16DOT->OpromSegment)); + + // Save INT18 and INT19 to be able to see its trapping after ROM execution + Int19 = ivt[0x19]; + Int18 = ivt[0x18]; + + Status = CsmInstallRom(CoreBiosInfo, NULL, + Csm16DOT, RomAddress, FALSE, NULL, &ProcessBootDevices); + + if (ProcessBootDevices) { + FetchBbsBootDevices(CoreBiosInfo, + (UINT8*)RomAddress, + PciCfgData, + 0, + 0, + 0, + &DiskFrom, + Int18 != ivt[0x18], + Int19 != ivt[0x19]); + } + + // Restore INT18 and INT19 + ivt[0x18] = Int18; + ivt[0x19] = Int19; + + if (CsmPlatformProtocol) { + CsmPlatformProtocol->PostProcessOpRom(CsmPlatformProtocol, NULL, (VOID*)&RomAddress); + } + + return Status; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: ShadowAllLegacyOproms +// +// Description: Allows external agents to force loading of all legacy OpROMs. +// This function can be invoked before GetBbsInfo() to ensure all +// devices are counted. +// Input: +// This Indicates the EFI_LEGACY_BIOS_PROTOCOL instance. +// +// Output: +// EFI_SUCCESS OpROMs are shadowed successfully. +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +ShadowAllLegacyOproms ( + IN EFI_LEGACY_BIOS_PROTOCOL *This +) +{ + EFI_HANDLE *HandleBuffer; + UINTN n, HandleCount; + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *PciIo; + BIOS_INFO *CoreBiosInfo = (BIOS_INFO*)This; + UINT64 Capabilities; + UINTN Flags; + UINT8 dData[4]; + UINT8 SetTxtMode = gSetTxtMode; + + // + // Locate all PciIo handles + // + Status = pBS->LocateHandleBuffer ( + ByProtocol, + &gEfiPciIoProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer); + + ASSERT_EFI_ERROR(Status); + if (EFI_ERROR (Status)) { + return Status; + } + + for (n = 0; n < HandleCount; n++) { + Status = pBS->HandleProtocol (HandleBuffer[n], &gEfiPciIoProtocolGuid, &PciIo); + ASSERT_EFI_ERROR(Status); + + if (PciRomAlreadyExecuted(PciIo)) continue; + + // + // Skip the VGA devices: the active VGA controller might have + // been already enabled, all other VGA controllers have to be disabled. + // + if (CoreBiosInfo->hVga != NULL) { + Status = PciIo->Pci.Read( + PciIo, + EfiPciIoWidthUint32, + 8, // offset + 1, // width + &dData); + ASSERT_EFI_ERROR(Status); + if (dData[3]==PCI_CL_DISPLAY) continue; + } + + // + // See if device has OpROM, if so - enable device and istlall OpROM; assume + // CSM has already assinged IRQ and programmed IRQ router and register 3C + // + Status = CheckPciRom(This, HandleBuffer[n], NULL, NULL, &Flags); + if (EFI_ERROR(Status) || (Flags != 2)) continue; // No OpROM or OpROM is invalid + + 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 + + if (EFI_ERROR(Status)) continue; + + InstallPciRom(This, + HandleBuffer[n], NULL, &Flags, + NULL, NULL, NULL, NULL); + } + pBS->FreePool(HandleBuffer); + + if (!gServiceRomsExecuted) { + // + // Launch service ROMs + // + Status = CoreBiosInfo->iBiosPlatform->PlatformHooks( + CoreBiosInfo->iBiosPlatform, + EfiPlatformHookShadowServiceRoms, + 0, NULL, NULL, NULL, NULL); + gServiceRomsExecuted = TRUE; + } + + gSetTxtMode = SetTxtMode; + + return EFI_SUCCESS; +} + + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2010, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** |