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 | |
download | zprj-master.tar.xz |
Diffstat (limited to 'Core/EM/CSM')
43 files changed, 27856 insertions, 0 deletions
diff --git a/Core/EM/CSM/BiosData.h b/Core/EM/CSM/BiosData.h new file mode 100644 index 0000000..dfb8e71 --- /dev/null +++ b/Core/EM/CSM/BiosData.h @@ -0,0 +1,179 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (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/biosdata.h 7 1/12/10 11:46a Olegi $ +// +// $Revision: 7 $ +// +// $Date: 1/12/10 11:46a $ +// +//**************************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Modules/CSM/Generic/Core/biosdata.h $ +// +// 7 1/12/10 11:46a Olegi +// Copyright message updated. +// +// 6 4/27/07 5:13p Olegi +// CSM.CHM file preparation. +// +// 5 5/16/06 1:57p Olegi +// +// 4 8/02/05 11:27a Olegi +// +// 3 3/04/05 1:51p Mandal +// +//********************************************************************** +//---------------------------------------------------------------------------- +// BIOSDATA.H -- BIOS Global Data Area and EBDA +//---------------------------------------------------------------------------- +#ifndef __BIOS_DATA_AREA__ +#define __BIOS_DATA_AREA__ + +#ifdef __cplusplus +extern "C" { +#endif + +#pragma pack (1) + +typedef struct _BDA_DATA { + +UINT16 rs_232_address[4]; // 00 - RS232 adapters addresses +UINT16 printer_address[3]; // 08 - Printer addresses +UINT16 ext_bios_data_seg; // 0E - Segment pointer to EBDA +UINT16 machine_config; // 10 - Hardware Equipment Status +UINT8 test_scratch; // 12 - Scratch byte during init +UINT16 system_memory; // 13 - System Memory in KBytes +UINT8 sys_info; // 15 - miscellaneous system info +UINT8 dummy_byte_1; // 16 +UINT8 kb_stat_flag; // 17 - Keyboard Status Flag +UINT8 kb_hold_flag; // 18 - Toggle key's hold flag +UINT8 kb_alt_char; // 19 - Alt_character byte +UINT16 kb_buf_head_ptr; // 1A - Keyboard buffer head pointer +UINT16 kb_buf_tail_ptr; // 1C - Keyboard buffer tail pointer +UINT16 kb_buffer[16]; // 1E - Keyboard buffer (15 char max) +UINT8 recal_int_flag; // 3E - Status for recalibration +UINT8 motor_status_flag; // 3F - Status for drive motors +UINT8 motor_time_count; // 40 - Turn off time for motor +UINT8 floppy_io_status; // 41 - Return code status byte +UINT8 task_file[7]; // 42 - A.K.A. fdc_8272_status +UINT8 mode_of_vdo; // 49 - Current Video Mode (set by user) +UINT16 columns_of_vdo; // 4A - Number of columns per row +UINT16 page_length; // 4C - Number of bytes per Video Page +UINT16 page_start; // 4E - Start address of Active Video Page +UINT16 position_of_cursor[8]; // 50 - Cursor position for each Video Page +UINT16 mode_of_cursor; // 60 - Current cursor mode setting +UINT8 active_page_no; // 62 - Current display page no +UINT16 address_of_6845; // 63 - Address of 6845 index reg +UINT8 current_mode_set; // 65 - Mode set in 6845 control port +UINT8 current_palette; // 66 - Current palette set +//--------------------------------------- +// POST DATA STORAGES +//--------------------------------------- +UINT16 offset_shutdown; // 67 - Offset of shutdown routine +UINT16 segment_shutdown; // 69 - Segment of shutdown routine +UINT8 interrupt_flag; // 6B - Interrupt flag +//---------------------------------------------------------------------------- +// TIMER DATA STORAGES +//---------------------------------------------------------------------------- +//UINT16 timer_low_count; // 6C - Low Word of timer count +//UINT16 timer_high_count; // 6E - High Word of timer count +UINT32 timer_count; // 6C - timer count +UINT8 timer_count_rolled; // 70 - Timer Rolled Over +//---------------------------------------------------------------------------- +// BIOS DATA STORAGES EXTENDED +//---------------------------------------------------------------------------- +UINT8 break_flag; // 71 - Flag for CTRL-BREAK key key +UINT16 dummy_word; // 72 - Unused data word +//---------------------------------------------------------------------------- +// WINCHESTER DATA STORAGES +//---------------------------------------------------------------------------- +UINT8 winch_status; // 74 - Status of Hard Disk operation +UINT8 winch_number; // 75 - Number of Hard Disk drives +UINT8 winch_control_byte; // 76 +UINT8 dummy_byte_2; // 77 +//---------------------------------------------------------------------------- +// PRINTER & RS232 DATA STORAGES +//---------------------------------------------------------------------------- +UINT8 print_time_max[4]; // 78 - Maximum time for printing +UINT8 rs_232_time_max[4]; // 7C - Maximum transmission time for COM ports +//---------------------------------------------------------------------------- +// KEYBOARD DATA STORAGES EXTENDED +//---------------------------------------------------------------------------- +UINT16 kb_buff_begin; // 80 - Start address of Keyboard Buffer +UINT16 kb_buff_end; // 82 - End address of Keyboard Buffer +UINT8 rows_of_vdo[7]; // 84 - EGA/VGA control state +//---------------------------------------------------------------------------- +// FLOPPY DATA STORAGES EXTENDED +//---------------------------------------------------------------------------- +UINT8 last_xfer_rate; // 8B - Last data transfer rate (Floppy) +//---------------------------------------------------------------------------- +// WINCHESTER DATA STORAGES EXTENDED +//---------------------------------------------------------------------------- +UINT8 winch_stat_reg; // 8C - Hard Disk status register +UINT8 winch_error_reg; // 8D - Hard Disk error register, a.k.a. iraid_int_flag +UINT8 winch_int_flag; // 8E - Hard Disk interrupt status +//---------------------------------------------------------------------------- +// FLOPPY DATA STORAGES EXTENDED +//---------------------------------------------------------------------------- +UINT8 duel_card; // 8F - Availability of 1.2M Floppy Drive +UINT8 current_floppy_media[2]; // 90 - Type of floppy drive/media +UINT8 run_scratch1; // 92 - Runtime Scratch data byte 1 +UINT8 run_scratch2; // 93 - Runtime Scratch data byte 1 +UINT8 current_cylinder[2];// 94 - Cylinder position of Floppy Disk +//---------------------------------------------------------------------------- +// KEYBOARD DATA STORAGES EXTENDED +//---------------------------------------------------------------------------- +UINT8 dummy_byte_3; // 96 - Keyboard Type byte +UINT8 kb_leds_flag; // 97 - Keyboard LED's status byte +//---------------------------------------------------------------------------- +// REAL TIME CLOCK DATA STORAGES +//---------------------------------------------------------------------------- +UINT16 user_flag_offset; // 98 - Offset of user defined flag +UINT16 user_flag_segment; // 9A - Segment of user defined flag +UINT16 user_wait_low; // 9C - Low WORD of user defined time +UINT16 user_wait_high; // 9E - High WORD of user defined time +UINT8 user_wait_flag[23]; // A0 - User defined time active flag, Video data area +//---------------------------------------------------------------------------- +// APM HANDLING BIOS DATA AREA USED FOR GREEN PC/NOTE BOOK +//---------------------------------------------------------------------------- +UINT8 apm_data[73]; // B7 +UINT8 prtsc_status_flag; // 100 - Print Screen status byte + +} BDA_DATA; + +#pragma pack () + +/****** DO NOT WRITE BELOW THIS LINE *******/ +#ifdef __cplusplus +} +#endif + +#endif + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2010, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** 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 ** +//** ** +//********************************************************************** +//********************************************************************** diff --git a/Core/EM/CSM/CSM.dxs b/Core/EM/CSM/CSM.dxs new file mode 100644 index 0000000..55d82f2 --- /dev/null +++ b/Core/EM/CSM/CSM.dxs @@ -0,0 +1,62 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (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/csm.dxs 18 4/09/13 9:25a Olegi $ +// +// $Revision: 18 $ +// +// $Date: 4/09/13 9:25a $ +//********************************************************************** + +//********************************************************************** +//<AMI_FHDR_START> +// +// Name: CSM.DXS +// +// Description: AMI CSM dependency file. +// +//<AMI_FHDR_END> +//********************************************************************** +#include <Protocol/LegacyRegion.h> +#include <Protocol/LegacyInterrupt.h> +#include <Protocol/Legacy8259.h> +#include <Protocol/Cpu.h> +#include <Protocol/CsmPlatform.h> +#include <Protocol/Variable.h> +#include <Protocol/AmiBoardInfo.h> + +DEPENDENCY_START + EFI_LEGACY_INTERRUPT_PROTOCOL_GUID AND + EFI_LEGACY_REGION_PROTOCOL_GUID AND + EFI_LEGACY_8259_PROTOCOL_GUID AND + EFI_CPU_ARCH_PROTOCOL_GUID AND + EFI_VARIABLE_ARCH_PROTOCOL_GUID AND + AMI_BOARD_INFO_PROTOCOL_GUID AND + EFI_VARIABLE_WRITE_ARCH_PROTOCOL_GUID +DEPENDENCY_END + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2010, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** diff --git a/Core/EM/CSM/CSM.h b/Core/EM/CSM/CSM.h new file mode 100644 index 0000000..1016a5b --- /dev/null +++ b/Core/EM/CSM/CSM.h @@ -0,0 +1,1089 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2014, 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.h 88 8/06/14 3:20p Fasihm $ +// +// $Revision: 88 $ +// +// $Date: 8/06/14 3:20p $ +//********************************************************************** + +//********************************************************************** +//<AMI_FHDR_START> +// +// Name: CSM.H +// +// Description: AMI CSM header file. +// +//<AMI_FHDR_END> +//********************************************************************** + +#ifndef __CSM_HEADER__ +#define __CSM_HEADER__ + +#include "efi.h" +#include <Protocol\DevicePath.h> +#include <Protocol\LegacyBios.h> +#include <Protocol\LegacyRegion.h> +#include <Protocol\Legacy8259.h> +#include <Protocol\LegacyInterrupt.h> +#include <Protocol\LegacyBiosPlatform.h> +#include <Protocol\SimpleTextOut.h > +#include <GenericSio.h> +#include <Protocol\LegacyBiosExt.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#pragma pack (1) + +#define EFI_LEGACY_BIOS_GUID \ + { 0x2e3044ac, 0x879f, 0x490f, 0x97, 0x60, 0xbb, 0xdf, 0xaf, 0x69, 0x5f, 0x50 } + + +//<AMI_SHDR_START> +//---------------------------------------------------------------------------- +// Name: EFI_TO_COMPATIBILITY16_INIT_TABLE +// +// Description: Data structure passed to Compatibility16InitializeYourself +// function. +// Fields: +// BiosLessThan1MB UINT32 Starting address of memory under 1 MB.The ending address is assumed to be 640 KB or 0x9FFFF. +// +// HiPmmMemory UINT32 Starting address of the high memory block +// +// HiPmmMemorySizeInBytes UINT32 Length of high memory block +// +// ReverseThunkCallSegment UINT16 The segment of the reverse thunk call code +// +// ReverseThunkCallOffset UINT16 The offset of the reverse thunk call code +// +// Number820Entries UINT32 The number of E820 entries copied to the Compatibility16 BIOS +// +// OsMemoryAbove1Mb UINT32 The amount of usable memory above 1 MB, e.g., E820 type 1 memory +// +// ThunkStart UINT32 The start of thunk code in main memory. Memory cannot be used by BIOS or PMM. +// +// ThunkSizeInBytes UINT32 The size of the thunk code +// +// LowPmmMemory UINT32 Starting address of memory below 1MB +// +// LowPmmMemorySizeInBytes UINT32 Length of low Memory block +// +// Referrals: Compatibility16InitializeYourself +// +// Notes: - The address of the ReverseThunkCall code is provided in case +// the Compatibility16 code needs to invoke a Compatibility16 +// function. It is not used to return from this function or any +// other traditional BIOS interface function. These functions simply +// do a far return. +// - CSM16 must handle cases where PMM pointers are NULL. That indicates +// that PMM is not supported for that range. If both pointers are NULL +// then PMM is not supported. That covers cases where no add-in cards +// are supported and/or memory given to EFI. +// - CSM16 must initialize PMM regions to zero prior to usage by OpROMs. +// CSM16 can not assume the CSM32 had zeroed out the regions. +// - CSM16 must monitor for EBDA size increase after OpROM is initalized +// and adjust PMM below 1MB, if required. +// - BiosLessThan1MB field is maintained for compatibility with the +// previous versions of the specification and the CSM16 should not use this +// field. The CSM16 should use LowPmmMemory and LowPmmMemorySizeInBytes fields +// for the low memory that can be used for PMM. +//---------------------------------------------------------------------------- +//<AMI_SHDR_END> + +typedef struct { + UINT32 BiosLessThan1MB; + UINT32 HiPmmMemory; + UINT32 HiPmmMemorySizeInBytes; + UINT16 ReverseThunkCallSegment; + UINT16 ReverseThunkCallOffset; + UINT32 NumberE820Entries; + UINT32 OsMemoryAbove1Mb; + UINT32 ThunkStart; + UINT32 ThunkSizeInBytes; + UINT32 LowPmmMemory; + UINT32 LowPmmMemorySizeInBytes; +} EFI_TO_COMPATIBILITY16_INIT_TABLE; + +//**************************************************** +// CSM16 related equates +//**************************************************** +// misc_info bits +#define CSM16_HEADLESS_INT19_RETRY_BIT 0x80 +#define CSM16_I19_TRAP_BIT 0x40 +#define CSM16_I13_HDD_MBR_WP_BIT 0x20 +#define CSM16_NO_USB_BOOT_BIT 0x10 +#define CSM16_NO_KBC_PRESENT_BIT 0x08 +#define CSM16_ZIP_HDD_EMUL_BIT 0x04 +#define CSM16_FLEXBOOT_ENABLE_BIT 0x02 +#define CSM16_FLEXBOOT_ENABLE_SHIFT_CNT 1 +#define CSM16_FAST_GATE_A20_BIT 0x01 + +// rt_cmos_byte bits +#define CSM_RT_CMOS_LTE_PONR_BIT 0x02 +#define CSM_RT_CMOS_PARITY_BIT 0x08 +#define CSM_RT_CMOS_SKIP_GA20_DEACTIVATION_BIT 0x10 +#define CSM_RT_CPU_RM_ONBOOT_BIT 0x20 +#define CSM_RT_CMOS_PS2_BIT 0x40 +#define CSM_RT_CMOS_LTE_BIT 0x80 + +//**************************************************** +// Type values +//**************************************************** +#define STANDARD_IO 0x00 +#define STANDARD_MEMORY 0x01 + +//**************************************************** +// PortGranularity values +//**************************************************** +#define PORT_SIZE_8 0x00 +#define PORT_SIZE_16 0x01 +#define PORT_SIZE_32 0x02 +#define PORT_SIZE_64 0x03 + +//**************************************************** +// DataGranularity values +//**************************************************** +#define DATA_SIZE_8 0x00 +#define DATA_SIZE_16 0x01 +#define DATA_SIZE_32 0x02 +#define DATA_SIZE_64 0x03 + +#define EFI_SEGMENT(_Adr) (UINT16)((UINT16) (((UINTN)(_Adr)) >> 4) & 0xf000) +#define EFI_OFFSET(_Adr) (UINT16)(((UINT16)((UINTN)_Adr)) & 0xffff) + +//<AMI_SHDR_START> +//---------------------------------------------------------------------------- +// Name: SMM_FUNCTION +// +// Fields: +// Function UINT16 Function this Soft SMI is to initiate +// Owner UINT16 The definer of the function +// +//---------------------------------------------------------------------------- +//<AMI_SHDR_END> + +typedef struct { + UINT16 Function : 15; + UINT16 Owner : 1; +} SMM_FUNCTION; + + +//**************************************************************************** +// Function values +//**************************************************************************** +#define INT15_D042 0x0000 +#define GET_USB_BOOT_INFO 0x0001 +#define DMI_PNP_50_57 0x0002 +// +// Following is a description of the fields in the above definition. +// +// INT15_D042 - System Configuration Data functions accessed via INT15 AX=0xD042. +// GET_USB_BOOT_INFO - Retrieves USB boot device information for integration with BBS. +// DMI_PNP_50_57 - Process the DMI Plug and Play functions 0x50 through +// 0x57 via SMM code. +// The other values are reserved for future use. +// + +//**************************************************************************** +// Owner values +//**************************************************************************** +#define STANDARD_OWNER 0x0 +#define OEM_OWNER 0x1 +// +// Following is a description of the fields in the above definition. +// +// STANDARD_OWNER - This document has defined the function. +// OEM_OWNER - An agent, other than this document, has defined the function. +// + +//<AMI_SHDR_START> +//---------------------------------------------------------------------------- +// Name: SMM_ATTRIBUTES +// +// Fields: +// Type UINT16 Access mechanism used to generate the soft SMI +// PortGranularity UINT16 Size of "port" in bits +// DataGranularity UINT16 Size of data in bits +// Reserved UINT16 Reserved for future use +// +//---------------------------------------------------------------------------- +//<AMI_SHDR_END> + +typedef struct { + UINT16 Type : 3; + UINT16 PortGranularity : 3; + UINT16 DataGranularity : 3; + UINT16 Reserved : 7; +} SMM_ATTRIBUTES; + + +//<AMI_SHDR_START> +//---------------------------------------------------------------------------- +// Name: SMM_ENTRY +// +// Fields: +// SmmAttributes SMM_ATTRIBUTES Describes the access mechanism, SmmPort, and SmmData sizes +// SmmFunction SMM_FUNCTION Function Soft SMI is to perform +// SmmPort UINT16 SmmPort size depends upon SmmAttributes and ranges from 2 bytes to 16 bytes +// SmmData UINT16 SmmData size depends upon SmmAttributes and ranges from 2 bytes to 16 bytes +// +// Referrals: SMM_ATTRIBUTES, SMM_FUNCTION +// +//---------------------------------------------------------------------------- +//<AMI_SHDR_END> + +typedef struct { + SMM_ATTRIBUTES SmmAttributes; + SMM_FUNCTION SmmFunction; + UINT16 SmmPort; + UINT16 SmmData; +} SMM_ENTRY; + +//<AMI_SHDR_START> +//---------------------------------------------------------------------------- +// Name: SMM_TABLE +// +// Description: SMM Table definitions; SMM table has a header that provides +// the number of entries. Following the header is a variable +// length amount of data. +// Fields: +// NumSmmEntries UINT16 Number of entries represented by SmmEntry +// SmmEntry SMM_ENTRY One entry per function +// +// Referrals: SMM_ENTRY +// +//---------------------------------------------------------------------------- +//<AMI_SHDR_END> + +typedef struct { + UINT16 NumSmmEntries; + SMM_ENTRY SmmEntry; +} SMM_TABLE; + + +//<AMI_SHDR_START> +//---------------------------------------------------------------------------- +// Name: LEGACY_DEVICE_FLAGS +// +// Fields: +// A20Kybd UINT32:1 A20 controller by keyboard controller. +// A20Port92 UINT32:1 A20 controlled by port 0x92. +// Reserved UINT32:30 Reserved for future usage. +// +// Notes: A20Kybd and A20Port92 are not mutually exclusive. +// +//---------------------------------------------------------------------------- +//<AMI_SHDR_END> + +typedef struct { + UINT32 A20Kybd:1; + UINT32 A20Port92:1; + UINT32 Reserved:30; +} LEGACY_DEVICE_FLAGS; + + +//<AMI_SHDR_START> +//---------------------------------------------------------------------------- +// Name: DEVICE_PRODUCER_FLOPPY +// +// Fields: +// Address UINT16 I/O address assigned to the floppy +// Irq UINT8 IRQ assigned to the floppy. +// Dma UINT8 DMA assigned to the floppy. +// NumberOfFloppy UINT8 Number of floppies in the system. +// +//---------------------------------------------------------------------------- +//<AMI_SHDR_END> + +typedef struct { + UINT16 Address; + UINT8 Irq; + UINT8 Dma; + UINT8 NumberOfFloppy; +} DEVICE_PRODUCER_FLOPPY; + +typedef enum {FLOPPY_INSERTED, NO_FLOPPY_DISK, NO_FLOPPY_DRIVE} FDD_STATUS; + +//<AMI_SHDR_START> +//---------------------------------------------------------------------------- +// Name: DEVICE_PRODUCER_PARALLEL +// +// Fields: +// Address UINT16 I/O address assigned to the parallel port +// Irq UINT8 IRQ assigned to the parallel port. +// Dma UINT8 DMA assigned to the parallel port. +// Mode PARALLEL_MODE Mode of the parallel port. +// +//---------------------------------------------------------------------------- +//<AMI_SHDR_END> + +//**************************************************************************** +// Parallel Mode values +//**************************************************************************** +#define DEVICE_PARALLEL_MODE_MODE_OUTPUT_ONLY 0x00 +#define DEVICE_PARALLEL_MODE_MODE_BIDIRECTIONAL 0x01 +#define DEVICE_PARALLEL_MODE_MODE_EPP 0x02 +#define DEVICE_PARALLEL_MODE_MODE_ECP 0x03 + +typedef UINT8 PARALLEL_MODE; + +typedef struct { + UINT16 Address; + UINT8 Irq; + UINT8 Dma; + PARALLEL_MODE Mode; +} DEVICE_PRODUCER_PARALLEL; + + +//<AMI_SHDR_START> +//---------------------------------------------------------------------------- +// Name: DEVICE_PRODUCER_SERIAL +// +// Fields: +// Address UINT16 I/O address assigned to the serial port +// Irq UINT8 IRQ assigned to the serial port +// Mode SERIAL_MODE Mode of serial port +// +//---------------------------------------------------------------------------- +//<AMI_SHDR_END> + +//**************************************************************************** +// Serial Mode values +//**************************************************************************** +#define DEVICE_SERIAL_MODE_NORMAL 0x00 +#define DEVICE_SERIAL_MODE_IRDA 0x01 +#define DEVICE_SERIAL_MODE_ASK_IR 0x02 +#define DEVICE_SERIAL_MODE_DUPLEX_HALF 0x00 +#define DEVICE_SERIAL_MODE_DUPLEX_FULL 0x10 + +typedef UINT8 SERIAL_MODE; +typedef struct { + UINT16 Address; + UINT8 Irq; + SERIAL_MODE Mode; +} DEVICE_PRODUCER_SERIAL; + + +//<AMI_SHDR_START> +//---------------------------------------------------------------------------- +// Name: DEVICE_PRODUCER_DATA_HEADER +// +// Fields: +// Serial DEVICE_PRODUCER_SERIAL Data for serial port x +// Parallel DEVICE_PRODUCER_PARALLEL Data for parallel port x +// Floppy DEVICE_PRODUCER_FLOPPY Data for floppy +// MousePresent UINT8 Flag to indicate if mouse is present +// Flags LEGACY_DEVICE_FLAGS Miscellaneous Boolean state information passed to CSM +// +// Referrals: DEVICE_PRODUCER_SERIAL, DEVICE_PRODUCER_PARALLEL, +// DEVICE_PRODUCER_FLOPPY, LEGACY_DEVICE_FLAGS +// +//---------------------------------------------------------------------------- +//<AMI_SHDR_END> + +typedef struct { + DEVICE_PRODUCER_SERIAL Serial[4]; + DEVICE_PRODUCER_PARALLEL Parallel[3]; + DEVICE_PRODUCER_FLOPPY Floppy; + UINT8 MousePresent; + LEGACY_DEVICE_FLAGS Flags; +} DEVICE_PRODUCER_DATA_HEADER; + + +//<AMI_SHDR_START> +//---------------------------------------------------------------------------- +// Name: EFI_TO_COMPATIBILITY16_BOOT_TABLE +// +// Description: Data structure passed to Compatibility16InitializeYourself +// function. +// Fields: +// MajorVersion UINT16 The EfiCompatibility major version number. +// MinorVersion UINT16 The EfiCompatibility minor version number. +// AcpiTable UINT32 Location of the RSDT ACPI table. +// SmbiosTable UINT32 Location of the SMBIOS table in EFI memory. +// SmbiosTableLength UINT32 Length of the SMBIOS table in bytes. +// SioData DEVICE_PRODUCER_DATA_HEADER Standard traditional device information. +// DevicePathType UINT16 The default boot type. See notes for details. +// PciIrqMask UINT16 Mask of which IRQs have been assigned to PCI. +// NumberE820Entries UINT32 Number of E820 entries. +// HddInfo HDD_INFO Hard disk drive information, including raw Identify Drive data. +// NumberBbsEntries UINT32 Number of entries in the BBS table +// BbsTable UINT32 Pointer to the BBS table. +// SmmTable UINT32 Pointer to the SMM table. +// OsMemoryAbove1Mb UINT32 The amount of usable memory above 1 MB, i.e. E820 type 1 memory. +// UnconventionalDeviceTable UINT32 Information to boot off an unconventional device like a PARTIES partition. +// +// Referrals: Compatibility16InitializeYourself, EFI_TO_COMPATIBILITY16_INIT_TABLE, HDD_INFO +// +// Notes: Following are the defined DevicePathType values: +// FD = Floppy +// HD = Hard Disk +// CDROM = CD-ROM +// PCMCIA = PCMCIA +// USB = USB +// NET = Networks +// BEV = BBS BEV devices +//---------------------------------------------------------------------------- +//<AMI_SHDR_END> +//#define MAX_IDE_CONTROLLER 8 +#define MAX_IDE_CONTROLLER 12 +struct _UD_TABLE; + +typedef struct { + UINT16 MajorVersion; + UINT16 MinorVersion; + + UINT32 AcpiTable; // 4 GB range + UINT32 SmbiosTable; // 4 GB range + UINT32 SmbiosTableLength; + // + // Legacy SIO state + // + DEVICE_PRODUCER_DATA_HEADER SioData; + UINT16 DevicePathType; + UINT16 PciIrqMask; + UINT32 NumberE820Entries; + // + // Controller & Drive Identify[2] per controller information + // + HDD_INFO HddInfo[MAX_IDE_CONTROLLER]; + UINT32 NumberBbsEntries; + UINT32 BbsTable; + UINT32 SmmTable; + UINT32 OsMemoryAbove1Mb; + UINT32 UnconventionalDeviceTable; +} EFI_TO_COMPATIBILITY16_BOOT_TABLE; + + +//<AMI_SHDR_START> +//---------------------------------------------------------------------------- +// Name: EFI_LEGACY_INSTALL_PCI_HANDLER +// +// Fields: +// PciBus UINT8 The PCI bus of the device. +// PciDeviceFun UINT8 The PCI device in bits 7:3 and function in bits 2:0. +// PciSegment UINT8 The PCI segment of the device. +// PciClass UINT8 The PCI class code of the device. +// PciSubclass UINT8 The PCI subclass code of the device. +// PciInterface UINT8 The PCI interface code of the device. +// PrimaryIrq UINT8 The primary device IRQ. +// PrimaryReserved UINT8 Reserved. +// PrimaryControl UINT16 The primary device control I/O base. +// PrimaryBase UINT16 The primary device I/O base. +// PrimaryBusMaster UINT16 The primary device bus master I/O base. +// SecondaryIrq UINT8 The secondary device IRQ. +// SecondaryReserved UINT8 Reserved. +// SecondaryControl UINT16 The secondary device control I/O base. +// SecondaryBase UINT16 The secondary device I/O base. +// SecondaryBusMaster UINT16 The secondary device bus master I/O base. +//---------------------------------------------------------------------------- +//<AMI_SHDR_END> + +typedef struct { + UINT8 PciBus; + UINT8 PciDeviceFun; + UINT8 PciSegment; + UINT8 PciClass; + UINT8 PciSubclass; + UINT8 PciInterface; + // + // Primary section + // + UINT8 PrimaryIrq; + UINT8 PrimaryReserved; + UINT16 PrimaryControl; + UINT16 PrimaryBase; + UINT16 PrimaryBusMaster; + // + // Secondary section + // + UINT8 SecondaryIrq; + UINT8 SecondaryReserved; + UINT16 SecondaryControl; + UINT16 SecondaryBase; + UINT16 SecondaryBusMaster; +} EFI_LEGACY_INSTALL_PCI_HANDLER; + + +//<AMI_SHDR_START> +//---------------------------------------------------------------------------- +// Name: EFI_DISPATCH_OPROM_TABLE +// +// Fields: +// PnpInstallationCheckSegment UINT16 Segment of the PnpInstallationCheck data structure. +// PnpInstallationCheckOffset UINT16 Offset of the PnpInstallationCheck data structure. +// OpromSegment UINT16 The segment where the OpROM was placed. Offset is assumed to be 3. +// PciBus UINT8 The PCI bus. +// PciDeviceFunction UINT8 The PCI device * 0x08 | PCI function. +// NumberBbsEntries UINT8 The number of valid BBS table entries upon entry and exit. +// BbsTable UINT32 Pointer to the BBS table. +// +//---------------------------------------------------------------------------- +//<AMI_SHDR_END> +#define MAX_EXECUTED_OPROMS 32 + +typedef struct { + IN UINT16 PnpInstallationCheckSegment; + IN UINT16 PnpInstallationCheckOffset; + IN UINT16 OpromSegment; + IN UINT8 PciBus; + IN UINT8 PciDeviceFunction; + IN OUT UINT8 NumberBbbsEntries; + UINT32 BbsTable; + IN UINT16 FinalLocationSegment; +} EFI_DISPATCH_OPROM_TABLE; + +typedef struct { + UINTN Seg; + UINTN Bus; + UINTN Dev; + UINTN Fun; + UINTN Flags; + UINT8 DiskFrom; + UINT8 DiskTo; + VOID *RomAddress; + UINT32 RomSize; +} EXECUTED_PCI_ROM; + +BOOLEAN Int86 ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN UINT8 BiosInt, + IN EFI_IA32_REGISTER_SET *Regs +); + +BOOLEAN FarCall86 ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN UINT16 Segment, + IN UINT16 Offset, + IN EFI_IA32_REGISTER_SET *Regs, + IN VOID *Stack, + IN UINTN StackSize +); + +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_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 +ShadowAllLegacyOproms ( + IN EFI_LEGACY_BIOS_PROTOCOL *This +); + +EFI_STATUS FindEmbeddedRom( + UINT16 ModuleId, UINT16 VendorId, UINT16 DeviceId, + VOID **ImageStart, UINTN *ImageSize +); + +EFI_STATUS +GetLegacyRegion ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN UINTN LegacyMemorySize, + IN UINTN Region, + IN UINTN Alignment, + OUT VOID **LegacyMemoryAddress +); + +EFI_STATUS +CopyLegacyRegion ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN UINTN LegacyMemorySize, + IN VOID *LegacyMemoryAddress, + IN VOID *LegacyMemorySourceAddress +); + +EFI_STATUS +UnlockShadow( + IN UINT8 *Address, + IN UINTN Size, + OUT UINT32 *LockUnlockAddr, + OUT UINT32 *LockUnlockSize +); + +EFI_STATUS +LockShadow( + IN UINT32 LockAddr, + IN UINT32 LockSize +); + +EFI_STATUS +RemoveDecodingForShadow( + IN UINT32 DecodeAddr +); +//<AMI_SHDR_START> +//---------------------------------------------------------------------------- +// Name: AMIIRQ_HEADER +// +// Description: AMI IRQ Routing Table Header Structure +// +//---------------------------------------------------------------------------- +//<AMI_SHDR_END> + +typedef struct { + UINT32 dSignature; // '$IRT' signature + UINT8 bTotalEntries; // total number of slot entries present in the table + UINT8 bUsedEntries; // number of used slot entries in the table + UINT16 wExclusiveIRQ; // bitmap of IRQs used exclusively for PCI + UINT32 dPtrIRQSlotStart; // pointer to start of IRQ slot entries +} AMIIRQ_HEADER; + + +//<AMI_SHDR_START> +//---------------------------------------------------------------------------- +// Name: EFI_ADDON_PCIBUS_TABLE +// +// Description: Table that holds the information about the buses generated by +// P2P bridges that are not listed in $PIR table +// +//---------------------------------------------------------------------------- +//<AMI_SHDR_END> + +typedef struct { + UINT8 Bus; + EFI_LEGACY_PIRQ_ENTRY PirqEntry[4]; +} EFI_ADDON_PCIBUS_TABLE; + + +//********************************************************************** +// +// The following sections is a list of the CSM16 APIs. They do not +// require definitions and given here for reference only. (And of course +// these headers could be used to prepare the interactive help file.) +// +//********************************************************************** + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: Compatibility16InitializeYourself (Function 0) +// +// Description: Causes the Compatibility16 code to do any internal initialization +// required. The EFI_TO_COMPATIBILITY16_INIT_TABLE pointer is passed +// into this function. +// Input: +// AX = Compatibility16InitializeYourself +// ES:BX = Pointer to EFI_TO_COMPATIBILITY16_INIT_TABLE +// +// Output: Status Codes Returned +// +// Referrals: EFI_TO_COMPATIBILITY16_INIT_TABLE, EFI_IA32_REGISTER_SET +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: Compatibility16UpdateBbs (Function 1) +// +// Description: Causes the Compatibility16 BIOS to perform any drive number +// translations to match the boot sequence. +// Input: +// AX = Compatibility16UpdateBbs +// ES:BX = Pointer to EFI_TO_COMPATIBILITY16_BOOT_TABLE +// +// Output: Status Codes Returned +// EFI_SUCCESS 0x0000 +// +// Referrals: EFI_TO_COMPATIBILITY16_BOOT_TABLE, EFI_IA32_REGISTER_SET +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: Compatibility16PrepareToBoot (Function 2) +// +// Description: Allows the Compatibility16 code to perform any final actions +// before booting. The Compatibility16 code is read/write. +// Input: +// AX = Compatibility16PrepareToBoot +// ES:BX = Pointer to EFI_TO_COMPATIBILITY16_BOOT_TABLE structure +// +// Output: Status Codes Returned +// +// Referrals: EFI_TO_COMPATIBILITY16_BOOT_TABLE, DEVICE_PRODUCER_DATA_HEADER +// HDD_INFO, BBS_TABLE, BBS_STATUS_FLAGS, SMM_TABLE, UD_TABLE, +// UDC_ATTRIBUTES, EFI_IA32_REGISTER_SET +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: Compatibility16Boot (Function 3) +// +// Description: Causes the Compatibility16 BIOS to boot. The Compatibility16 +// code is Read/Only. +// Input: AX = Compatibility16Boot +// +// Output: Status Codes Returned +// +// Referrals: EFI_TO_COMPATIBILITY16_BOOT_TABLE, EFI_IA32_REGISTER_SET +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: Compatibility16RetrieveLastBootDevice (Function 4) +// +// Description: Allows the Compatibility16 code to get the last device from +// which a boot was attempted. This is stored in CMOS and is +// the priority number of the last attempted boot device. +// +// Input: AX = Compatibility16RetrieveLastBootDevice +// +// Output: AX = Returned status codes: +// EFI_SUCCESS 0x0000 +// EFI_ABORTED 0x8015 +// BX = Priority number of the boot device +// +// Referrals: EFI_IA32_REGISTER_SET +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: Compatibility16DispatchOprom (Function 5) +// +// Description: Allows the Compatibility16 code rehook INT13, INT18, and/or +// INT19 after dispatching a legacy OpROM. +// Input: AX = Compatibility16DispatchOprom +// ES:BX = Pointer to EFI_DISPATCH_OPROM_TABLE +// +// Output: AX = Returned status codes +// BX = Number of non-BBS-compliant devices found. Equals 0 if +// BBS compliant. +// +// Referrals: EFI_DISPATCH_OPROM_TABLE, EFI_IA32_REGISTER_SET +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: Compatibility16GetTableAddress (Function 6) +// +// Description: Finds a free area in the 0xFxxxx or 0xExxxx region of the +// specified length and returns the address of that region. +// Input: AX = Compatibility16GetTableAddress +// BX = Allocation region +// 00 = Allocate from either 0xE0000 or 0xF0000 64 KB blocks. +// Bit 0 = 1 Allocate from 0xF0000 64 KB block +// Bit 1 = 1 Allocate from 0xE0000 64 KB block +// CX = Requested length in bytes. +// DX = Required address alignment. Bit mapped. First non-zero bit +// from the right is the alignment. +// +// Output: AX = Returned status codes: +// EFI_SUCCESS 0x0000 +// EFI_OUT_OF_RESOURCES 0x8009 +// DS:BX = Address of the region +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: Compatibility16SetKeyboardLeds (Function 7) +// +// Description: Enables the EfiCompatibility module to do any nonstandard +// processing of keyboard LEDs or state. +// Input: AX = Compatibility16SetKeyboardLeds +// CL = LED status: +// Bit 0 - Scroll Lock 0 = Off +// Bit 1 - Num Lock +// Bit 2 - Caps Lock +// Output: Status Codes Returned +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: Compatibility16InstallPciHandler (Function 8) +// +// Description: Enables the EfiCompatibility module to install an interrupt +// handler for PCI mass media devices that do not have an OpROM +// associated with them. An example is SATA +// +// Input: AX = Compatibility16InstallPciHandler +// ES:BX = Pointer to EFI_LEGACY_INSTALL_PCI_HANDLER structure +// +// Output: Status Codes Returned +// +// Referrals: EFI_LEGACY_INSTALL_PCI_HANDLER +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +#define MAX_DRIVE_NAME 32 + +typedef struct _DRIVE_DISPLAY_NAME { + UINT8 DriveName[MAX_DRIVE_NAME]; +} DRIVE_DISPLAY_NAME; + +typedef struct _IDE_CONTROLLER_INFO_STRUC { + UINT16 BusDevFun; // Bus, Device and Function number + UINT8 ControllerNo; // Controller number for IDE controller +} IDE_CONTROLLER_INFO_STRUC; + +typedef struct { + UINT8 ThunkCode[0x4000]; // 12KB = 4KB of code + 8KB of stack + UINT8 InterruptRedirectionCode[24]; // 3 bytes of code per interrupt + EFI_TO_COMPATIBILITY16_INIT_TABLE Csm16InitTable; + EFI_TO_COMPATIBILITY16_BOOT_TABLE Csm16BootTable; + EFI_LEGACY_INSTALL_PCI_HANDLER PciHandler; + EFI_DISPATCH_OPROM_TABLE DispatchOpromTable; + DRIVE_DISPLAY_NAME DriveDisplayName[2*MAX_IDE_CONTROLLER]; +} THUNK_MEMORY; + +#define MAX_E820_ENTRIES 256 +typedef enum { + MemRangeAvl = 1, + MemRangeRes = 2, + MemRangeAcpiReclaim = 3, + MemRangeAcpiNVS = 4 +} E820_MEMORY_TYPE; + +#define E820_EXTATTR_ADDRESS_RANGE_ENABLED 1 +#define E820_EXTATTR_ADDRESS_RANGE_NONVOLATILE 2 +typedef struct { + UINT64 Adr; + UINT64 Len; + E820_MEMORY_TYPE Type; + UINT32 ExtendedAttr; +} E820_ENTRY; + +#define PMM_TABLE_SIZE 0x1000 +#define PMM_SYSTEM_HANDLE 0x24494D41 // Handle used by AMIBIOS 'AMI$' +#define EFI_MEMORY_HANDLE 0x24494645 // Handle used by EFI Memory 'EFI$' +typedef struct { + UINT32 StartAddress; // Start address of the memory block + UINT32 Size; // Size of the memory block in bytes + UINT32 Handle; // Associated handle + UINT8 Reserved[4]; // Reserved for future use +} MEMORY_ALLOCATION_ENTRY; + +typedef struct { + UINT32 Signature; + UINT8 Revision; + UINT8 Length; + UINT16 NextHeaderOffset; + UINT8 Reserved; + UINT8 Checksum; + UINT32 DevId; + UINT16 MfgPtr; + UINT16 ProductNamePtr; + UINT8 Class; + UINT8 SubClass; + UINT8 Interface; + UINT8 DevIndicators; + UINT16 BCV; + UINT16 DisconnectVector; + UINT16 BEV; + UINT16 Reserved1; + UINT16 StaticResourceVector; +} PCI_PNP_EXPANSION_HEADER; + +#define MAX_BCV_OPROMS 32 +typedef struct { + UINT8 *Address; + UINT8 *Data; + UINT8 *rtData; + UINT8 *rtDataAddr; + UINT32 rtDataSize; + BOOLEAN isEbda; + UINT32 ebdaOffset; +} SAVED_PCI_ROM; + +typedef struct { + UINT8 irq_num; + UINT32 irq_adr; +} IVT_SAVE_RESTORE; + + +//<AMI_SHDR_START> +//---------------------------------------------------------------------------- +// Name: BIOS_INFO +// +// Description: +// This structure is not specified in CSM specification. It defines the useful +// fields for the global variable to be used throughout POST. +// +// Fields: +// iBios EFI_LEGACY_BIOS_PROTOCOL LegacyBios instance pointer +// iRegion EFI_LEGACY_REGION_PROTOCOL LegacyRegion instance pointer +// iBiosPlatform EFI_LEGACY_BIOS_PLATFORM_PROTOCOL LegacyPlatform instance pointer +// iInterrupt EFI_LEGACY_INTERRUPT_PROTOCOL LegacyInterrupt instance pointer +// i8259 EFI_LEGACY_8259_PROTOCOL Legacy8259 instance pointer +// hBios EFI_HANDLE +// hImage EFI_HANDLE This driver LoadedImage handle +// hVga EFI_HANDLE Video controller handle +// Csm16Header EFI_COMPATIBILITY16_TABLE Pointer to CSM16 header +// Thunk THUNK_MEMORY Pointer to thunk memory area +// Csm16EntrySeg UINT16 CSM16 entry point segment +// Csm16EntryOfs UINT16 CSM16 entry point offset +// BbsTable BBS_TABLE BBS table pointer +// BbsEntriesNo UINT8 Number of BBS entries +// HddCount UINT8 Number of hard disks in the system +// E820Map E820_ENTRY E820 memory map entries +// NumberE820Entries UINT16 Number of E820 entries populated +// +//---------------------------------------------------------------------------- +//<AMI_SHDR_END> + +typedef struct { + EFI_LEGACY_BIOS_PROTOCOL iBios; + EFI_LEGACY_REGION_PROTOCOL *iRegion; + EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *iBiosPlatform; + EFI_LEGACY_INTERRUPT_PROTOCOL *iInterrupt; + EFI_LEGACY_8259_PROTOCOL *i8259; + EFI_HANDLE hBios; + EFI_HANDLE hImage; + EFI_HANDLE hVga; + EFI_COMPATIBILITY16_TABLE *Csm16Header; + THUNK_MEMORY *Thunk; + UINT16 Csm16EntrySeg; + UINT16 Csm16EntryOfs; + BBS_TABLE *BbsTable; + UINT8 BbsEntriesNo; + UINT8 HddCount; + E820_ENTRY E820Map[MAX_E820_ENTRIES]; + UINT16 NumberE820Entries; +} BIOS_INFO; + +typedef struct { + EFI_HANDLE hImage; + EFI_HANDLE hBios; + EFI_LEGACY_BIOS_PLATFORM_PROTOCOL iBiosPlatform; +} PLATFORM_BIOS_INFO; + +EFI_STATUS BspUpdatePrt( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN VOID *RoutingTable +); + +typedef struct _OEMINT_FUNC { + UINT16 interrupt; + UINT16 funcoffset; +} OEMINT_FUNC; + +typedef struct _OEM16_FUNC { + UINT16 funcID; + UINT16 funcOffset; +} OEM16_FUNC; + +typedef struct _LEGACY16_TO_EFI_DATA_TABLE_EXT { + LEGACY16_TO_EFI_DATA_TABLE_STRUC PublicData; + UINT16 RbMinBusArrayOfs; + UINT8 RbArrayCount; +} LEGACY16_TO_EFI_DATA_TABLE_EXT; + +EFI_STATUS Get16BitFuncAddress (UINT16, UINT32*); +UINTN CopyLegacyTable(VOID*, UINT16, UINT16, UINT16); +EFI_STATUS GetEmbeddedRom(UINT16, UINT16, UINT16, VOID**, UINTN*); +EFI_STATUS GetBbsTable (BBS_TABLE**, UINT8*); +EFI_STATUS AddBbsEntry(BBS_TABLE*); +EFI_STATUS InsertBbsEntryAt(EFI_LEGACY_BIOS_EXT_PROTOCOL*, BBS_TABLE*, UINT8*); +EFI_STATUS RemoveBbsEntryAt(EFI_LEGACY_BIOS_EXT_PROTOCOL*, UINT8); +EFI_STATUS AllocateEbda(EFI_LEGACY_BIOS_EXT_PROTOCOL*, UINT8, UINT32*, UINT32*); +EFI_STATUS UnlockShadow(UINT8*, UINTN, UINT32*, UINT32*); +EFI_STATUS LockShadow(UINT32, UINT32); +EFI_STATUS InitCompatibility16(BIOS_INFO*, EFI_SYSTEM_TABLE*); +EFI_STATUS InitializeThunk(BIOS_INFO*); +EFI_STATUS InitializeLegacyMemory(BIOS_INFO*); +EFI_STATUS PrepareToBoot(EFI_LEGACY_BIOS_PROTOCOL*, UINT16*, struct _BBS_TABLE**); +EFI_STATUS LegacyBoot(EFI_LEGACY_BIOS_PROTOCOL*, BBS_BBS_DEVICE_PATH*, UINT32, VOID*); +EFI_STATUS GetBbsInfo(EFI_LEGACY_BIOS_PROTOCOL*, UINT16*, HDD_INFO**, UINT16*, BBS_TABLE**); +EFI_STATUS UpdateKeyboardLedStatus(EFI_LEGACY_BIOS_PROTOCOL*, UINT8); +EFI_STATUS EnableDisableNmi(); +//EFI_STATUS GetAtaAtapiInfo(HDD_INFO**); +VOID HaltApsBeforeBoot(); +VOID InstallLegacyMassStorageDevices(); +VOID GetExtendedMemSize(UINT32*); +UINT32 UpdateE820Map(E820_ENTRY *); +EFI_STATUS UpdateCsm16Configuration(EFI_TO_COMPATIBILITY16_BOOT_TABLE*); +EFI_STATUS InitCsmBoard(EFI_HANDLE, EFI_SYSTEM_TABLE*); +EFI_STATUS InitCsmSimpleIn(EFI_HANDLE, EFI_SYSTEM_TABLE*); +EFI_STATUS UpdateCmos(); +EFI_STATUS InitializePortingHooks (BIOS_INFO*); +OEM16_FUNC* InitializeOemInt(UINT16*); +UINTN InitializeOem16(UINT16*); +FDD_STATUS GetFDDStatus(); +VOID AllConnectedCallback (EFI_EVENT, VOID*); +EFI_STATUS GetPlatformEmbeddedRom(UINT16, UINT16, UINT16, VOID**, UINTN*); +EFI_STATUS GetComPortResource(UINT8, UINT16*, UINT8*); +EFI_STATUS GetLptResource(UINT16*, UINT8*); +VOID UpdatePciLastBusCallback(EFI_EVENT, VOID*); +EFI_STATUS GetPlatformPciEmbeddedRom(EFI_PCI_IO_PROTOCOL*, VOID**, UINTN*); +EFI_STATUS CheckOemPciSiblings(EFI_PCI_IO_PROTOCOL*, EXECUTED_PCI_ROM*); +EFI_STATUS EnableOemPciSiblings(EFI_PCI_IO_PROTOCOL*); +EFI_STATUS InstallIsaRom(EFI_LEGACY_BIOS_EXT_PROTOCOL*, UINTN); +EFI_STATUS GetShadowRamAddress(UINT32*, UINT32, UINT32, UINT32); + +// SD class/subclass defined in PCI.H in 4.6.3.7 +#ifndef PCI_CL_SYSTEM_PERIPHERALS +#define PCI_CL_SYSTEM_PERIPHERALS 0x08 +#endif +#ifndef PCI_CL_SYSTEM_PERIPHERALS_SCL_SD +#define PCI_CL_SYSTEM_PERIPHERALS_SCL_SD 0x05 +#endif + +VOID DisconnectSerialIO(); +VOID ConnectSerialIO(); +BOOLEAN IsAMICSM16(EFI_COMPATIBILITY16_TABLE*); +UINT8 ChecksumCSM16Header(EFI_COMPATIBILITY16_TABLE*); +EFI_STATUS GetSystemMemoryMap(EFI_MEMORY_DESCRIPTOR**, UINTN*,UINTN*); +EFI_STATUS ClearFreeMemory(EFI_PHYSICAL_ADDRESS,EFI_PHYSICAL_ADDRESS); +EFI_STATUS Csm16Configuration(CSM16_CONFIGURATION_ACTION, CSM16_FEATURE, UINT32*); + +#pragma pack () +/****** DO NOT WRITE BELOW THIS LINE *******/ +#ifdef __cplusplus +} +#endif +#endif + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2014, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** diff --git a/Core/EM/CSM/CSM.mak b/Core/EM/CSM/CSM.mak new file mode 100644 index 0000000..9e651c2 --- /dev/null +++ b/Core/EM/CSM/CSM.mak @@ -0,0 +1,174 @@ +#********************************************************************** +#********************************************************************** +#** ** +#** (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.mak 36 10/07/13 8:58a Olegi $ +# +# $Revision: 36 $ +# +# $Date: 10/07/13 8:58a $ +#********************************************************************** + +#********************************************************************** +#<AMI_FHDR_START> +# +# Name: CSMCORE.MAK +# +# Description: Make file for the CSM component +# +#<AMI_FHDR_END> +#********************************************************************** + +all : CSMCORE + +!IF $(CORE_COMBINED_VERSION) < 262795 +!ERROR This version of CSM is compatible with Core 4.6.5.1 or later. +!ELSE +CSMCORE : CSMELINKFUNCTIONS $(BUILD_DIR)\csmcore.mak LEGACY_ROM CSMCOREBin +!ENDIF + +!IFDEF LEGACY_TO_EFI_BOOT_SUPPORT +!IF $(LEGACY_TO_EFI_BOOT_SUPPORT) == 1 +!ERROR LEGACY_TO_EFI_BOOT_SUPPORT detected: disable or remove LegacyToEfiBoot module. This version of CSM implements all features of LegacyToEfiBoot. +!ENDIF +!ENDIF + +CSMELINKFUNCTIONS : + type << >$(BUILD_DIR)\CsmElinkFunctions.h +#define CSM_GET_OPROM_VIDEO_SWITCHING_MODE_FUNCTIONS $(CSM_GET_OPROM_VIDEO_SWITCHING_MODE_FUNCTIONS:},=},\^ +) +#define CSM_GET_CUSTOM_PCI_PIRQ_MASK_FUNCTIONS $(CSM_GET_CUSTOM_PCI_PIRQ_MASK_FUNCTIONS:},=},\^ +) +#define CSM_GET_GATE_A20_INFORMATION_FUNCTIONS $(CSM_GET_GATE_A20_INFORMATION_FUNCTIONS:},=},\^ +) +#define CSM_GET_NMI_INFORMATION_FUNCTIONS $(CSM_GET_NMI_INFORMATION_FUNCTIONS:},=},\^ +) +#define CSM_GET_OEM_INT_DATA_FUNCTIONS $(CSM_GET_OEM_INT_DATA_FUNCTIONS:},=},\^ +) +#define CSM_GET_PLATFORM_HANDLE_FUNCTIONS $(CSM_GET_PLATFORM_HANDLE_FUNCTIONS:},=},\^ +) +#define CSM_GET_PLATFORM_PCI_EMBEDDED_ROM_FUNCTIONS $(CSM_GET_PLATFORM_PCI_EMBEDDED_ROM_FUNCTIONS:},=},\^ +) +#define CSM_GET_PLATFORM_EMBEDDED_ROM_FUNCTIONS $(CSM_GET_PLATFORM_EMBEDDED_ROM_FUNCTIONS:},=},\^ +) +#define CSM_CHECK_OEM_PCI_SIBLINGS_FUNCTIONS $(CSM_CHECK_OEM_PCI_SIBLINGS_FUNCTIONS:},=},\^ +) +#define CSM_ENABLE_OEM_PCI_SIBLINGS_FUNCTIONS $(CSM_ENABLE_OEM_PCI_SIBLINGS_FUNCTIONS:},=},\^ +) +#define CSM_GET_ROUTING_TABLE_FUNCTIONS $(CSM_GET_ROUTING_TABLE_FUNCTIONS:},=},\^ +) +#define CSM_BSP_UPDATE_PRT_FUNCTIONS $(CSM_BSP_UPDATE_PRT_FUNCTIONS:},=},\^ +) +#define CSM_BSP_PREPARE_TO_BOOT_FUNCTIONS $(CSM_BSP_PREPARE_TO_BOOT_FUNCTIONS:},=},\^ +) +#define CSM_INIT_LEGACY_MEMORY_FUNCTIONS $(CSM_INIT_LEGACY_MEMORY_FUNCTIONS:},=},\^ +) +<< + +$(BUILD_DIR)\csmcore.mak : $(CSMCORE_DIR)\csmcore.cif $(CSMCORE_DIR)\csm.mak $(BUILD_RULES) + $(CIF2MAK) $(CSMCORE_DIR)\csmcore.cif $(CIF2MAK_DEFAULTS) + +$(BUILD_DIR)\thunk.obj: $(X86THUNK_DIR)\thunk.c $(BUILD_DIR)\token.h $(CSMCORE_DIR)\csm.h + $(CC) $(CFLAGS) /Fo$(BUILD_DIR)\ $(PROJECT_DIR)\$(X86THUNK_DIR)\thunk.c /I$(CSMCORE_DIR) + +CSMCOREBin : $(BUILD_DIR)\thunk.obj $(AMIDXELIB) $(AMICSPLib) + $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\ + /f $(BUILD_DIR)\csmcore.mak all\ + GUID=A062CF1F-8473-4aa3-8793-600BC4FFE9A8 \ + ENTRY_POINT=CsmEntryPoint \ + "CFLAGS=$(CFLAGS) /I$(CSMCORE_DIR)"\ + TYPE=BS_DRIVER \ + EXT_HEADERS=$(BUILD_DIR)\token.h\ + BINFILE=$(BUILD_DIR)\ROMs.bin \ + SECTION_GUID=E6F4F8F7-4992-47b2-8302-8508745E4A23 \ + COMPRESS=1\ + +LEGACY_ROM: $(BUILD_DIR)\ROMs.inf + $(PACKOPROM) /o$(BUILD_DIR)\ROMs.bin $(BUILD_DIR)\ROMs.inf + +$(BUILD_DIR)\ROMs.inf: $(OEM_SERVICE_ROM_LIST) $(CSM_OEM_BIN_FILE) $(CSM_CUSTOM_INFS) + @copy << $@ +[MODULE] +ModuleID = 1 +VendorID = 0 +DeviceID = 0 +File = $(AMILEGACY16_BIN) +!if "$(PCI_ROMS_OUTSIDE_CSM)"=="0" +$(PCI_OPT_ROM_LIST) +!endif +!if "$(PXE_BASECODE_ROM)"=="1" +[MODULE] +ModuleID = 2 +VendorID = 0 +DeviceID = 0 +File = $(PXE_BASECODE_ROM_FILE) +!endif + +!if "$(OEM_SERVICE_ROM_LIST)"!="" +[MODULE] +ModuleID = 2 +VendorID = 0 +DeviceID = 0 +File = $(OEM_SERVICE_ROM_LIST: =^ + +[MODULE]^ +ModuleID = 2^ +VendorID = 0^ +DeviceID = 0^ +File = ) + +!endif +!if "$(CSM_OEM_SUPPORT)"=="1" +[MODULE] +ModuleID = 3 +VendorID = 0 +DeviceID = 0 +File = $(CSM_OEM_BIN_FILE) + +!endif +<< + +!if "$(CSM_CUSTOM_INFS)"!="" + copy $@+$(CSM_CUSTOM_INFS: =+) $@ +!endif + + +#--------------------------------------------------------------------------- +# Create CSM Setup Screens +#--------------------------------------------------------------------------- +SetupSdbs: $(BUILD_DIR)\csm.sdb +SetupBin: $(BUILD_DIR)\csmsetup.obj + +$(BUILD_DIR)\csm.sdb : $(CSM_SETUP_DIR)\csm.sd $(CSM_SETUP_DIR)\csm.uni + $(STRGATHER) -i INCLUDE -parse -newdb -db $(BUILD_DIR)\csm.sdb $(CSM_SETUP_DIR)\csm.uni + $(STRGATHER) -scan -db $(BUILD_DIR)\csm.sdb -od $(BUILD_DIR)\csm.sdb $(CSM_SETUP_DIR)\csm.sd + +$(BUILD_DIR)\csmsetup.obj: $(CSM_SETUP_DIR)\csmsetup.c $(BUILD_DIR)\SetupStrTokens.h + $(CC) $(CFLAGS) /Fo$(BUILD_DIR)\ $(CSM_SETUP_DIR)\csmsetup.c +#--------------------------------------------------------------------------- + + +#********************************************************************** +#********************************************************************** +#** ** +#** (C)Copyright 1985-2013, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#********************************************************************** +#********************************************************************** diff --git a/Core/EM/CSM/CsmBsp.c b/Core/EM/CSM/CsmBsp.c new file mode 100644 index 0000000..9bc04c8 --- /dev/null +++ b/Core/EM/CSM/CsmBsp.c @@ -0,0 +1,1295 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (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/CsmBsp.c 39 8/06/14 4:40p Fasihm $ +// +// $Revision: 39 $ +// +// $Date: 8/06/14 4:40p $ +// +//**************************************************************************** + +//********************************************************************** +//<AMI_FHDR_START> +// +// Name: CsmBsp.c +// +// Description: +// Compatibility Support Module - Board Support Package. +// This driver implements LEGACY_BIOS_PLATFORM_PTOTOCOL interface functions. +// +//<AMI_FHDR_END> +//**************************************************************************** + +#include "Efi.h" +#include <Protocol/DevicePath.h> +#include <Protocol/LegacyBios.h> +#include <Protocol/LoadedImage.h> +#include "csm.h" +#include <AmiDxeLib.h> +#include <Protocol/LegacyBiosPlatform.h> +#include <Protocol/FirmwareVolumeBlock.h> +#include "token.h" +#include "setup.h" +#include "CsmElinkFunctions.h" + +typedef EFI_STATUS (CSM_GET_OPROM_VIDEO_SWITCHING_MODE)( + IN EFI_PCI_IO_PROTOCOL *PciIo OPTIONAL, + IN UINT16 TextSwitchingMode, + OUT UINTN *SetTxtSwitchingMode); +extern CSM_GET_OPROM_VIDEO_SWITCHING_MODE CSM_GET_OPROM_VIDEO_SWITCHING_MODE_FUNCTIONS EndOfGetOpRomVideoModeFunctions; +CSM_GET_OPROM_VIDEO_SWITCHING_MODE *CsmGetOpRomVideoModeSwitchingFunctions[] = { CSM_GET_OPROM_VIDEO_SWITCHING_MODE_FUNCTIONS NULL }; + +typedef EFI_STATUS (CSM_GET_CUSTOM_PCI_PIRQ_MASK)( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT16 IrqMask, + OUT UINTN *ModifiedIrqMask); +extern CSM_GET_CUSTOM_PCI_PIRQ_MASK CSM_GET_CUSTOM_PCI_PIRQ_MASK_FUNCTIONS EndOfGetCustomPciPirqMaskFunctions; +CSM_GET_CUSTOM_PCI_PIRQ_MASK *CsmGetCustomPciPirqMaskFunctions[] = { CSM_GET_CUSTOM_PCI_PIRQ_MASK_FUNCTIONS NULL }; + +typedef EFI_STATUS (CSM_GET_GATE_A20_INFORMATION)(OUT UINTN *GateA20Info); +extern CSM_GET_GATE_A20_INFORMATION CSM_GET_GATE_A20_INFORMATION_FUNCTIONS EndOfGetGateA20InformationFunctions; +CSM_GET_GATE_A20_INFORMATION *CsmGetGateA20InformationFunctions[] = { CSM_GET_GATE_A20_INFORMATION_FUNCTIONS NULL }; + +typedef EFI_STATUS (CSM_GET_NMI_INFORMATION)(OUT UINTN *NmiInfo); +extern CSM_GET_NMI_INFORMATION CSM_GET_NMI_INFORMATION_FUNCTIONS EndOfGetNmiInformationFunctions; +CSM_GET_NMI_INFORMATION *CsmGetNmiInformationFunctions[] = { CSM_GET_NMI_INFORMATION_FUNCTIONS NULL }; + +// Get Platform Handle ELINK function list +typedef EFI_STATUS (CSM_GET_PLATFORM_HANDLE)( + EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *This, + EFI_GET_PLATFORM_HANDLE_MODE Mode, + UINT16 Type, + EFI_HANDLE **HandleBuffer, + UINTN *HandleCount, + VOID OPTIONAL **AdditionalData); +extern CSM_GET_PLATFORM_HANDLE CSM_GET_PLATFORM_HANDLE_FUNCTIONS EndOfPlatformHandleFunctions; +CSM_GET_PLATFORM_HANDLE *CsmGetPlatformFunctions[] = { CSM_GET_PLATFORM_HANDLE_FUNCTIONS NULL }; + +typedef EFI_STATUS (CSM_GET_PLATFORM_EMBEDDED_ROM)(UINT16 ModuleId, UINT16 VendorId, UINT16 DeviceId, VOID **ImageStart, UINTN *ImageSize); +extern CSM_GET_PLATFORM_EMBEDDED_ROM CSM_GET_PLATFORM_EMBEDDED_ROM_FUNCTIONS EndOfGetPlatformEmbeddedRomFunctions; +CSM_GET_PLATFORM_EMBEDDED_ROM *CsmGetPlatformEmbeddedRomFunctions[] = { CSM_GET_PLATFORM_EMBEDDED_ROM_FUNCTIONS NULL }; + +typedef EFI_STATUS (CSM_GET_PLATFORM_PCI_EMBEDDED_ROM)(IN EFI_PCI_IO_PROTOCOL *PciIo, OUT VOID **PciRom, OUT UINTN *PciRomSize); +extern CSM_GET_PLATFORM_PCI_EMBEDDED_ROM CSM_GET_PLATFORM_PCI_EMBEDDED_ROM_FUNCTIONS EndOfGetPlatformPciEmbeddedRomFunctions; +CSM_GET_PLATFORM_PCI_EMBEDDED_ROM *CsmGetPlatformPciEmbeddedRomFunctions[] = { CSM_GET_PLATFORM_PCI_EMBEDDED_ROM_FUNCTIONS NULL }; + +typedef EFI_STATUS (CSM_CHECK_OEM_PCI_SIBLINGS)(EFI_PCI_IO_PROTOCOL *PciIo, EXECUTED_PCI_ROM *ExecutedRom); +extern CSM_CHECK_OEM_PCI_SIBLINGS CSM_CHECK_OEM_PCI_SIBLINGS_FUNCTIONS EndOfCheckOemPciSiblingsFunctions; +CSM_CHECK_OEM_PCI_SIBLINGS *CsmCheckOemPciSiblingsFunctions[] = { CSM_CHECK_OEM_PCI_SIBLINGS_FUNCTIONS NULL }; + +typedef EFI_STATUS (CSM_ENABLE_OEM_PCI_SIBLINGS)(EFI_PCI_IO_PROTOCOL *PciIo); +extern CSM_ENABLE_OEM_PCI_SIBLINGS CSM_ENABLE_OEM_PCI_SIBLINGS_FUNCTIONS EndOfEnableOemPciSiblingsFunctions; +CSM_ENABLE_OEM_PCI_SIBLINGS *CsmEnableOemPciSiblingsFunctions[] = { CSM_ENABLE_OEM_PCI_SIBLINGS_FUNCTIONS NULL }; + +typedef EFI_STATUS (CSM_GET_ROUTING_TABLE)( + IN EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *This, + OUT VOID **RoutingTable, + OUT UINTN *RoutingTableEntries, + OUT VOID **LocalPirqTable, OPTIONAL + OUT UINTN *PirqTableSize, OPTIONAL + OUT VOID **LocalIrqPriorityTable, OPTIONAL + OUT UINTN *IrqPriorityTableEntries OPTIONAL); +extern CSM_GET_ROUTING_TABLE CSM_GET_ROUTING_TABLE_FUNCTIONS EndOfGetRoutingTableFunctions; +CSM_GET_ROUTING_TABLE *CsmGetRoutingTableFunctions[] = { CSM_GET_ROUTING_TABLE_FUNCTIONS NULL }; + +typedef EFI_STATUS (CSM_BSP_UPDATE_PRT)(IN EFI_LEGACY_BIOS_PROTOCOL *This, IN VOID *RoutingTable); +extern CSM_BSP_UPDATE_PRT CSM_BSP_UPDATE_PRT_FUNCTIONS EndOfBspUpdatePrtFunctions; +CSM_BSP_UPDATE_PRT *CsmBspUpdatePrtFunctions[] = { CSM_BSP_UPDATE_PRT_FUNCTIONS NULL }; + +typedef EFI_STATUS (CSM_BSP_PREPARE_TO_BOOT)( IN EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *This, + IN BBS_BBS_DEVICE_PATH *BbsDevicePath, + IN VOID *BbsTable, + IN UINT32 LoadOptionsSize, + IN VOID *LoadOptions, + IN VOID *EfiToLegacyBootTable); +extern CSM_BSP_PREPARE_TO_BOOT CSM_BSP_PREPARE_TO_BOOT_FUNCTIONS EndOfBspPrepareToBootFunctions; +CSM_BSP_PREPARE_TO_BOOT *CsmBspPrepareToBootFunctions[] = { CSM_BSP_PREPARE_TO_BOOT_FUNCTIONS NULL }; + +// end of CSM elink functions + + +PLATFORM_BIOS_INFO *BspBiosInfo; + + +extern EFI_LEGACY_PIRQ_TABLE_HEADER *MsPrt; + +//AMIIRQ_HEADER *AmiPrt; +extern EFI_LEGACY_IRQ_ROUTING_ENTRY *Prt; +BOOLEAN IsValidPrt; + +EFI_STATUS InitPrt(EFI_LEGACY_BIOS_PLATFORM_PROTOCOL*); +EFI_STATUS Intx2Pirq (EFI_LEGACY_BIOS_PLATFORM_PROTOCOL*, + UINTN, UINTN, UINTN, UINT8*, UINT8*, UINT16*); + +extern VOID *EmbeddedRom; +extern UINTN EmbeddedRomSize; +extern UINT16 CurrentIrqMask; +extern UINTN gUsedPciEntries; +extern SETUP_DATA gSetup; + +// +// The following table has a list of interrupts to be saved after +// CSM Init call and restored before LegacyBoot. The default list +// is defined in CSM.SDL and contains three interrups: int13, int15, +// and int40. +// This list can be expanded according to the project needs. Only +// MAX_NUM_IRQS_SAVERESTORE entries will be processed, others will +// be ignored. +// +UINT8 gInterruptsToPreserve[] = INTERRUPTS_TO_PRESERVE; + +// +// The following table is the list of VID/DID (combined into DWORDs) +// that will have problems with BCV executed during early POST right +// after Option ROM is initialized, or problems with BCV executed +// multiple times during POST. The examples of such "problematic" +// BCVs would be trapping BIOS interrupts that are not BCV specific, +// allocating blocks of memory, etc. +// Note that for these devices BCV will be executed during PrepareToBoot; +// drivers that require BCV execution before that (CsmBlockIo) will not +// support these devices. +// +UINT32 gSkipBcvDeviceList[] = SKIP_EARLY_BCV_DEVICES; + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: GetOpromVideoSwitchingMode +// +// Description: This function is called from LEGACY_BIOS.InstallPciRom() +// before and after OpROM execution. It allows OEM override the +// default video mode switching policy during OpROM execution. +// +// Input: +// +// PciIo PciIo protocol of the device associated with the OpROM; +// This is an optional field, if NULL then it is ignored. +// +// TextSwitchingMode The current text switching mode. Possible values are: +// 0 - switching to text mode is needed; +// 1 - switching is needed, restoration is not; +// 2 - neither switching nor restoration is needed. +// Output: +// +// SetTxtSwitchingMode The mode that will be used for this OpROM. The valid +// values are 0, 1, and 2. The meaning is the same as +// TextSwitchingMode (above). +// +// EFI_SUCCESS The value of SetTxtSwithcingMode is updated according +// to the platform policy and will be used for video mode +// switching for the given PciIo's Option ROM. +// +// EFI_UNSUPPORTED The value of SetTxtSwitchingMode is not valid. +// +// +// Notes: This function can change the policy of video switching for selected +// Option ROMs by looking up the PCI VID/DID. It also can change this +// policy for all OpROMs. +// +// Use SetTxtSwitchingMode value to adjust the platform policy. For +// example, value equal to 1 probably indicates the end of the boot +// process, when system is already in text mode and switching back +// is not desired. In this case platform may choose not to interfere +// with the default policy. This can be done by either returning +// EFI_UNSUPPORTED or returning EFI_SUCCESS with SetTxtSwitchingMode +// equal to TextSwitchingMode. +// +// Returning EFI_SUCCESS must be carefully considered. If function +// returns EFI_SUCCESS, please make sure SetTxtSwitchingMode is +// assigned the valid values: 0, 1, 2 and 3. If the wrong value is +// assigned, then video switching policy will fail. +// +// The default implementation simply returns EFI_SUCCESS with the +// SetTxtSwitchingMode set to the value passed in TextSwitchingMode. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +GetOpromVideoSwitchingMode( + IN EFI_PCI_IO_PROTOCOL *PciIo OPTIONAL, + IN UINT16 TextSwitchingMode, + OUT UINTN *SetTxtSwitchingMode +) +{ +/* +// Here is an example of the platform implementation of this function. + UINT32 VidDid; + EFI_STATUS Status; + + if (TextSwitchingMode == 1) return EFI_UNSUPPORTED; // see the notes + + if (PciIo == NULL) return EFI_UNSUPPORTED; + + // + // Force mode switching for certaing PCI cards + // + Status = PciIo->Pci.Read(PciIo, EfiPciIoWidthUint32, + 0, // offset + 1, // width + &VidDid); + ASSERT_EFI_ERROR(Status); + + if (VidDid == 0x12345678) { + *SetTxtSwitchingMode = 0; + return EFI_SUCCESS; + } + return EFI_UNSUPPORTED; +*/ + + EFI_STATUS Status; + UINTN i = 0; + + // default value + *SetTxtSwitchingMode = (UINTN)TextSwitchingMode; + + for(i = 0; CsmGetOpRomVideoModeSwitchingFunctions[i] != NULL; i++) + { + Status = CsmGetOpRomVideoModeSwitchingFunctions[i](PciIo, TextSwitchingMode, SetTxtSwitchingMode); + if(!EFI_ERROR(Status)) break; + } + + return EFI_SUCCESS; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: GetCustomPciIrqMask +// +// Description: This function is called from PciInterrupts.ProgramPciIrq() +// before programming PCI register 3C. This function is given +// the PciIo of the device and a list of possible IRQ choices +// for this device. +// The possible IRQs are given in a form of UINT16 IRQ mask, +// where 1 is a masked IRQ level. +// This function can modify this list and return EFI_SUCCESS. +// A caller then will AND the existing mask with the one returned +// by this function. Note that this way the existing list can +// only be shrunk, not extended. +// +// Input: +// +// PciIo PciIo protocol of the device +// +// IrqMask The current bit mask of IRQ levels available for this device +// +// Output: +// +// ModifiedIrqMask The value that a caller will use to OR with the existing +// mask. +// +// EFI_SUCCESS Function is returning a valid ModifiedIrqMask +// +// EFI_UNSUPPORTED Function is not ported for this PciIo, value returned +// in ModifiedIrqMask will be ignored. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +GetCustomPciIrqMask ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT16 IrqMask, + OUT UINTN *ModifiedIrqMask +) +{ +/* Implementation example - force IRQ11 for device 0x12345678 + + UINT32 VidDid; + EFI_STATUS Status; + + Status = PciIo->Pci.Read(PciIo, EfiPciIoWidthUint32, + 0, // offset + 1, // width + &VidDid); + ASSERT_EFI_ERROR(Status); + + if (VidDid == 0x12345678) { + if (IrqMask & 0xF7FF) { + *ModifiedIrqMask = 0xF7FF; // leave only IRQ11 unmaksed + return EFI_SUCCESS; + } + } + + return EFI_UNSUPPORTED; +*/ + + EFI_STATUS Status = EFI_UNSUPPORTED; + UINTN i = 0; + + // Set a default value + *ModifiedIrqMask = IrqMask; + + for(i = 0; CsmGetCustomPciPirqMaskFunctions[i] != NULL; i++) + { + Status = CsmGetCustomPciPirqMaskFunctions[i](PciIo, IrqMask, ModifiedIrqMask); + if(!EFI_ERROR(Status)) break; + } + + return Status; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: GetGateA20Information +// +// Description: This function is called from LegacyBios entry point and it +// returns the board specific information related to the way of +// controlling GateA20. Two different aspects of GateA20 control +// can be returned by this function: +// 1) Line GA20 can be activated/deactivated through KBC's GPIO +// (command D1), or through Port92 (Bit2). +// 2) Deactivation of GA20 is be desirable at all, any CSM16 +// function related to deactivation will be skipped. +// +// Input: None +// +// Output: GateA20Info: +// BIT0 0 - GA20 controlled through KBC +// 1 - GA20 controlled through Port92 +// BIT1 0 - Do not skip GA20 deactivation +// 1 - Skip GA20 deactivation +// EFI_SUCCESS GateA20Info has valid bits 0 and 1 +// +// EFI_UNSUPPORTED Function is not supported, GateA20Info information +// is invalid; CSM core will use the default GA20 policy. +// +// Note: Skipping GA20 deactivation is needed when APs are running above +// 1MB; if GA20 is inactive, then any access >1MB may be invalid. +// At the same time, keeping GA20 active all the time may fail the +// applications that test GA20 enable/disable functionality. It may +// also affect some applications that rely on GA20 being inactive +// after legacy boot. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +GetGateA20Information( + OUT UINTN *GateA20Info +) +{ + EFI_STATUS Status; + UINTN i = 0; + + // Set BIT0 if using Port92, Set BIT1 to skip GA20 deactivation + if (gSetup.KeepGA20Active == 1) *GateA20Info = 3; + else *GateA20Info = 1; + + for(i = 0; CsmGetGateA20InformationFunctions[i] != NULL; i++) + { + Status = CsmGetGateA20InformationFunctions[i](GateA20Info); + if(!EFI_ERROR(Status)) break; + } + + return EFI_SUCCESS; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: GetNmiInformation +// +// Description: +// This function is called from LegacyBios entry point and it returns the board +// specific information related to NMI. +// +// Input: +// None +// +// Output: +// NMI information: +// BIT0 0 - NMI should be kept disabled +// 1 - enable NMI +// EFI_SUCCESS GateA20Info has valid bits 0 and 1 +// EFI_UNSUPPORTED Function is not supported, NMI information is invalid; CSM +// will use the default NMI policy. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +GetNmiInformation( + OUT UINTN *NmiInfo +) +{ + EFI_STATUS Status; + UINTN i = 0; + + // prime the return value to enabled + *NmiInfo = 1; + + for(i = 0; CsmGetNmiInformationFunctions[i] != NULL; i++) + { + Status = CsmGetNmiInformationFunctions[i](NmiInfo); + if(!EFI_ERROR(Status)) break; + } + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: GetPlatformInfo +// +// Description: Finds the binary data or other platform information. +// Refer to the subfunctions for additional information. +// +// Input: +// This Indicates the EFI_LEGACY_BIOS_PLATFORM_PROTOCOL instance. +// Mode Specifies what data to return: +// EfiGetPlatformBinaryMpTable +// EfiGetPlatformBinaryOemIntData +// EfiGetPlatformBinaryOem16Data +// EfiGetPlatformBinaryOem32Data +// EfiGetPlatformBinaryTpmBinary +// EfiGetPlatformBinarySystemRom +// EfiGetPlatformPciExpressBase +// EfiGetPlatformPmmSize +// EfiGetPlatformEndRomShadowAddr +// EfiGetPlatformOpromVideoMode +// EfiGetPlatformIntSaveRestoreTable +// EfiGetPlatformPciIrqMask +// EfiGetPlatformGateA20Information +// +// Table Pointer to OEM legacy 16-bit code or data. +// TableSize Size of data. +// Location Location to place table. +// Bit 0 = 1 0xF0000 64 KB block. +// Bit 1 = 1 0xE0000 64 KB block. +// Note: Multiple bits can be set. +// Alignment Bit-mapped address alignment granularity. The first +// nonzero bit from the right is the address granularity. +// LegacySegment Segment where EfiCompatibility code will place the +// table or data. +// LegacyOffset Offset where EfiCompatibility code will place the +// table or data. +// +// Output: +// EFI_SUCCESS The data was returned successfully. +// EFI_UNSUPPORTED Mode is not supported on this platform. +// EFI_NOT_FOUND Binary image not found. +// +// Referrals: EFI_GET_PLATFORM_INFO_MODE +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +GetPlatformInfo ( + IN EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *This, + IN EFI_GET_PLATFORM_INFO_MODE Mode, + IN OUT VOID **Table, + IN OUT UINTN *TableSize, + IN OUT UINTN *Location, + OUT UINTN *Alignment, + IN UINT16 LegacySegment, + IN UINT16 LegacyOffset + ) +{ + switch (Mode) { + case EfiGetPlatformPmmSize: + // + // Return PMM area size below 1MB to be allocated in bytes. + // This size should be a multiple of 32K + // + *TableSize = PMM_LOMEM_SIZE; + // + // Return PMM area size above 1MB to be allocated in bytes. + // This size should be a multiple of 64k. + // Note: This field is not bit-mapped for this function. + // + *Alignment = PMM_HIMEM_SIZE; + return EFI_SUCCESS; + + case EfiGetPlatformEndRomShadowAddr: + *Location = OPROM_MAX_ADDRESS; + return EFI_SUCCESS; + + case EfiGetPlatformBinarySystemRom: + return FindEmbeddedRom(CSM16_MODULEID, CSM16_VENDORID, CSM16_DEVICEID, + Table, TableSize); + + case EfiGetPlatformPciExpressBase: + *(UINT64*)Location = PCIEX_BASE_ADDRESS; + return EFI_SUCCESS; + + case EfiGetPlatformOpromVideoMode: + return GetOpromVideoSwitchingMode((EFI_PCI_IO_PROTOCOL*)(*Table), + LegacySegment, TableSize); + + case EfiGetPlatformIntSaveRestoreTable: + *Table = gInterruptsToPreserve; + *TableSize = sizeof(gInterruptsToPreserve); + return EFI_SUCCESS; + + case EfiGetPlatformPciIrqMask: + return GetCustomPciIrqMask((EFI_PCI_IO_PROTOCOL*)(*Table), + LegacySegment, Alignment); + + case EfiGetPlatformGateA20Information: + return GetGateA20Information(Alignment); + + case EfiGetPlatformNmiInformation: + return GetNmiInformation(Alignment); + + case EfiGetBcvSkipDeviceList: + *Table = gSkipBcvDeviceList; + *TableSize = sizeof(gSkipBcvDeviceList)/4; + return EFI_SUCCESS; + } + + return EFI_UNSUPPORTED; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: GetPlatformHandle +// +// Description: Returns a buffer of handles for the requested subfunction. +// +// Input: +// This Indicates the EFI_LEGACY_BIOS_PLATFORM_PROTOCOL instance. +// Mode Specifies what handle to return. +// GetVgaHandle +// GetIdeHandle +// GetIsaBusHandle +// GetUsbHandle +// Type Handle Modifier - Mode specific +// HandleBuffer Pointer to buffer containing all Handles matching the +// specified criteria. Handles are sorted in priority order. +// Type EFI_HANDLE is defined in InstallProtocolInterface() +// in the EFI 1.10 Specification. +// HandleCount Number of handles in HandleBuffer. +// AdditionalData Pointer to additional data returned - mode specific.. +// +// Output: +// EFI_SUCCESS The handle is valid. +// EFI_UNSUPPORTED Mode is not supported on this platform. +// EFI_NOT_FOUND The handle is not known. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +GetPlatformHandle ( + IN EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *This, + IN EFI_GET_PLATFORM_HANDLE_MODE Mode, + IN UINT16 Type, + OUT EFI_HANDLE **HandleBuffer, + OUT UINTN *HandleCount, + OUT VOID OPTIONAL **AdditionalData + ) +{ + EFI_STATUS Status = EFI_UNSUPPORTED; + UINT16 i = 0; + + for(i = 0; CsmGetPlatformFunctions[i] != NULL; i++) + { + // Call all ELINK functions until one returns EFI_SUCCESS + Status = CsmGetPlatformFunctions[i](This, Mode, Type, HandleBuffer, HandleCount, AdditionalData); + if(!EFI_ERROR(Status)) break; + } + return Status; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: GetPlatformPciEmbeddedRom +// +// Description: This function is called from CheckPciRom and allows OEM to +// have a custom code that looks for a binary. +// +// Input: Same as in FindEmbeddedRom function. +// +// Output: EFI_UNSUPPORTED - Function is not implemented +// EFI_NOT_FOUND - No ROM found +// EFI_SUCCESS - ROM is found, output is the same as +// in FindEmbeddedRom function. +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +GetPlatformPciEmbeddedRom ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + OUT VOID **PciRom, + OUT UINTN *PciRomSize +) +{ + EFI_STATUS Status = EFI_UNSUPPORTED; + UINTN i = 0; + + for(i = 0; CsmGetPlatformPciEmbeddedRomFunctions[i] != NULL; i++) + { + Status = CsmGetPlatformPciEmbeddedRomFunctions[i](PciIo, PciRom, PciRomSize); + if(!EFI_ERROR(Status)) break; + } + return Status; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: GetPlatformEmbeddedRom +// +// Description: +// This function is called from FindEmbeddedRom and allows OEM to have a custom +// code that looks for a binary. By default all addon ROMs are packed as BINFILE +// section. This function may be needed if binary is packed in a way that is +// different from default (for example it can be FFS file, etc.). +// +// Input: +// Same as in FindEmbeddedRom function. +// +// Output: +// EFI_NOT_FOUND No ROM found, or function is not implemented. +// EFI_SUCCESS ROM is found, output is the same as in FindEmbeddedRom +// function. +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS GetPlatformEmbeddedRom( + UINT16 ModuleId, UINT16 VendorId, UINT16 DeviceId, + VOID **ImageStart, UINTN *ImageSize) +{ + EFI_STATUS Status = EFI_NOT_FOUND; + UINTN i = 0; + + for(i = 0; CsmGetPlatformEmbeddedRomFunctions[i] != NULL; i++) + { + Status = CsmGetPlatformEmbeddedRomFunctions[i](ModuleId, VendorId, DeviceId, ImageStart, ImageSize); + if(!EFI_ERROR(Status)) break; + } + + return Status; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: CheckOemPciSiblings +// +// Description: +// This function checks whether a given PCI device can be controlled by one of +// the Option ROMs that have been already executed. +// +// Input: +// PciIo PCI I/O protocol of the device whose Option ROM is about to +// execute +// ExecutedRom Pointer to the last element of EXECUTED_PCI_ROM structure +// +// Output: +// EFI_UNSUPPORTED Function is not implemented, use the default +// device match criteria +// EFI_SUCCESS Device can be managed by one of the loaded ROMs +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +CheckOemPciSiblings( + EFI_PCI_IO_PROTOCOL *PciIo, + EXECUTED_PCI_ROM *ExecutedRom +) +{ +/* By default this function returns EFI_UNSUPPORTED to make every Option ROM execute + One of the possible implementation is to execute only one Option ROM for all functions + of the PCI device. The sample below implements this kind of policy. Uncomment if needed. + + EFI_STATUS Status; + UINTN Seg, Bus, Dev, Func; + EXECUTED_PCI_ROM *er; + + // Go through ExecutedRoms and search for the ROM that has been executed for + // similar device (PCI Bus/Dev match) + Status = PciIo->GetLocation(PciIo, &Seg, &Bus, &Dev, &Func); + ASSERT_EFI_ERROR(Status); + + for (er = ExecutedRom; er->Seg | er->Bus | er->Dev | er->Fun; er--) { + if (er->Bus == Bus && er->Dev == Dev) { + TRACE((TRACE_ALWAYS, "CSM OPROM: skip OpROM execution for device B%x/d%x/F%x.\n", + Bus, Dev, Func)); + return EFI_SUCCESS; + } + } +*/ + EFI_STATUS Status = EFI_UNSUPPORTED; + UINTN i = 0; + + for(i = 0; CsmCheckOemPciSiblingsFunctions[i] != NULL; i++) + { + Status = CsmCheckOemPciSiblingsFunctions[i](PciIo, ExecutedRom); + if(!EFI_ERROR(Status)) break; + } + return Status; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: EnableOemPciSiblings +// +// Description: +// This function enables devices on PCI bus that can be controlled by the Option +// ROM associated with the given PCI device. +// +// Input: +// PciIo PCI I/O protocol of the device whose Option ROM is about to execute +// +// Output: +// EFI_UNSUPPORTED Function is not implemented +// EFI_SUCCESS Function has enabled all related devices +// +// Notes: +// If OEM code can not decide for ALL related devices, it may enable only devices +// it knows about, and still return EFI_UNSUPPORTED. In this case CSM Core will +// finish the job. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +EnableOemPciSiblings( + EFI_PCI_IO_PROTOCOL *PciIo +) +{ + EFI_STATUS Status = EFI_UNSUPPORTED; + UINTN i = 0; + + for(i = 0; CsmEnableOemPciSiblingsFunctions[i] != NULL; i++) + { + Status = CsmEnableOemPciSiblingsFunctions[i](PciIo); + if(!EFI_ERROR(Status)) break; + } + + return Status; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: SmmInit +// +// Description: Loads and registers the Compatibility16 handler with the EFI SMM code. +// In also updates EFI_TO_COMPATIBILITY16_BOOT_TABLE.SmmTable. +// +// Input: +// This Indicates the EFI_LEGACY_BIOS_PLATFORM_PROTOCOL instance. +// EfiToCompatibility16BootTable The boot table passed to the Compatibility16. +// +// Output: +// EFI_SUCCESS The SMM code loaded. +// EFI_DEVICE_ERROR The SMM code failed to load. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +SmmInit( + IN EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *This, + IN VOID *EfiToCompatibility16BootTable + ) +{ + SMM_TABLE *SmmTable; + SMM_ENTRY *SmmEntry; + EFI_STATUS Status; + // + // Currently this function is implemented for two SW SMI handlers: INT15_D042 and USB + // change NUMBER_OF_CSM_SUPPORTED_SW_SMIS and add the new SMM_ENTRYs if needed + // + #define NUMBER_OF_CSM_SUPPORTED_SW_SMIS 2 + + Status = pBS->AllocatePool(EfiBootServicesData, + sizeof (SMM_TABLE) + NUMBER_OF_CSM_SUPPORTED_SW_SMIS * sizeof(SMM_ENTRY), + &SmmTable); + ASSERT_EFI_ERROR (Status); + pBS->SetMem(SmmTable, + sizeof(SMM_TABLE) + NUMBER_OF_CSM_SUPPORTED_SW_SMIS * sizeof(SMM_ENTRY), 0); + + // + // Fill in two SMM entries - one for INT15 func D042, another for USB + // + SmmTable->NumSmmEntries = NUMBER_OF_CSM_SUPPORTED_SW_SMIS; + + SmmEntry = &SmmTable->SmmEntry; + + SmmEntry->SmmAttributes.Type = STANDARD_IO; + SmmEntry->SmmAttributes.PortGranularity = PORT_SIZE_16; + SmmEntry->SmmAttributes.DataGranularity = DATA_SIZE_8; + SmmEntry->SmmFunction.Function = INT15_D042; + SmmEntry->SmmFunction.Owner = STANDARD_OWNER; + SmmEntry->SmmPort = SW_SMI_IO_ADDRESS; + SmmEntry->SmmData = INT15_D042_SWSMI; + SmmEntry++; + // + // SmmPort and SmmData are UINT16 data fields, in our case SmmEntry data is UINT8. + // We need to adjust the pointer to the next SmmEntry accofdingly so that CSM16 will + // find it correctly. + // + (UINT8*)SmmEntry = (UINT8*)SmmEntry - 1; + + SmmEntry->SmmAttributes.Type = STANDARD_IO; + SmmEntry->SmmAttributes.PortGranularity = PORT_SIZE_16; + SmmEntry->SmmAttributes.DataGranularity = DATA_SIZE_8; + SmmEntry->SmmFunction.Function = GET_USB_BOOT_INFO; + SmmEntry->SmmFunction.Owner = STANDARD_OWNER; + SmmEntry->SmmPort = SW_SMI_IO_ADDRESS; + SmmEntry->SmmData = USB_SWSMI; + +//TODOx64: What is SmmTable pointer is more the 4G in 64 bit mode? +//CSM specification 0.96 defines the pointer as UINT32 + ((EFI_TO_COMPATIBILITY16_BOOT_TABLE*)EfiToCompatibility16BootTable)->SmmTable = (UINT32)SmmTable; + + return EFI_SUCCESS; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: ShadowServiceRoms +// +// Description: Executes Option ROMs that are not associated with PCI device, +// e.g. PXE base code image. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +ShadowServiceRoms ( + IN EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *This +) +{ + void *RomImageStart; + UINTN RomImageSize; + EFI_STATUS Status; + EFI_LEGACY_BIOS_PROTOCOL *iLegacyBios; + UINTN Flags; + UINTN NoHandles; + EFI_HANDLE *HandleBuffer; + +#pragma pack(push,1) + typedef struct{ + UINT16 ModuleId, VendorId, DeviceId; + UINT32 Size; + } OPROM_HEADER; +#pragma pack(pop) + OPROM_HEADER *Header; + + Status = pBS->LocateHandleBuffer ( + ByProtocol, + &gEfiLegacyBiosProtocolGuid, + NULL, + &NoHandles, + &HandleBuffer); + if (EFI_ERROR(Status)) return Status; + + Status = pBS->HandleProtocol( + HandleBuffer[0], + &gEfiLegacyBiosProtocolGuid, + &iLegacyBios + ); + pBS->FreePool(HandleBuffer); + if (EFI_ERROR(Status)) return Status; + + Status = FindEmbeddedRom(SERVICEROM_MODULEID, 0, 0, &RomImageStart, &RomImageSize); + if (EFI_ERROR(Status)) return Status; + + // + // Execute InstallPciRom for service ROMs: the 1st service ROM is pointed by + // RomImageStart; install this ROM and all consequent service ROMs + // + do { + TRACE((-1, "CsmBsp: Installing service ROM, %x...", RomImageStart)); + Status = iLegacyBios->InstallPciRom( + iLegacyBios, + NULL, // PciHandle; + &RomImageStart, + &Flags, + NULL, NULL, NULL, NULL); + ASSERT_EFI_ERROR(Status); + if (EFI_ERROR(Status)) return Status; + + Header = (OPROM_HEADER*)RomImageStart-1; + TRACE((-1, "...OK, size %x\n", Header->Size)); + Header = (OPROM_HEADER*)((UINT8*)RomImageStart+Header->Size); + RomImageStart = Header+1; + } while(Header->ModuleId == SERVICEROM_MODULEID); + + return EFI_SUCCESS; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: PlatformHooks +// +// Description: Allows platform to perform any required action after a LegacyBios +// operation. +// Input: +// DeviceHandle List of PCI devices in the system. Type EFI_HANDLE is defined in +// InstallProtocolInterface() in the EFI 1.10 Specification. +// ShadowAddress First free OpROM area, after other OpROMs have been dispatched.. +// Compatibility16Table Pointer to the Compatibility16 Table. +// AdditionalData Pointer to additional data returned - mode specific.. +// +// Output: +// EFI_SUCCESS The operation performed successfully. +// EFI_UNSUPPORTED Mode is not supported on this platform. +// EFI_SUCCESS Mode specific. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +PlatformHooks ( + IN EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *This, + IN EFI_GET_PLATFORM_HOOK_MODE Mode, + IN UINT16 Type, + IN EFI_HANDLE OPTIONAL DeviceHandle, + IN OUT UINTN OPTIONAL *ShadowAddress, + IN EFI_COMPATIBILITY16_TABLE OPTIONAL *Compatibility16Table, + OUT VOID OPTIONAL **AdditionalData + ) +{ + switch (Mode) { + case EfiPlatformHookPrepareToScanRom: + return EFI_UNSUPPORTED; + case EfiPlatformHookShadowServiceRoms: + return ShadowServiceRoms(This); + case EfiPlatformHookAfterRomInit: + return EFI_UNSUPPORTED; + } + return EFI_UNSUPPORTED; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: GetRoutingTable +// +// Description: Returns information associated with PCI IRQ routing. +// +// Input: +// This Indicates the EFI_LEGACY_BIOS_PLATFORM_PROTOCOL instance. +// RoutingTable Pointer to the PCI IRQ routing table. This location is +// the $PIR table minus the header. The contents is defined +// by the PCI IRQ Routing Table Specification; it has the +// number of RoutingTableEntries of EFI_LEGACY_IRQ_ROUTING_ENTRY. +// RoutingTableEntries Number of entries in the PCI IRQ routing table. +// LocalPirqTable $PIR table. It contains EFI_LEGACY_PIRQ_TABLE_HEADER, +// immediately followed by RoutingTable. +// PirqTableSize Size of $PIR table. +// LocalIrqPriorityTable A priority table of IRQs to assign to PCI. This table +// has IrqPriorityTableEntries entries of +// EFI_LEGACY_IRQ_PRIORITY_TABLE_ENTRY type and is used to +// prioritize the allocation of IRQs to PCI. +// IrqPriorityTableEntries Number of entries in the priority table. +// +// Output: +// EFI_SUCCESS Data was returned successfully. +// +// Referrals: +// EFI_LEGACY_BIOS_PLATFORM_PROTOCOL, EFI_LEGACY_IRQ_ROUTING_ENTRY, +// EFI_LEGACY_PIRQ_TABLE_HEADER, EFI_LEGACY_IRQ_PRIORITY_TABLE_ENTRY +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +GetRoutingTable( + IN EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *This, + OUT VOID **RoutingTable, + OUT UINTN *RoutingTableEntries, + OUT VOID **LocalPirqTable, OPTIONAL + OUT UINTN *PirqTableSize, OPTIONAL + OUT VOID **LocalIrqPriorityTable, OPTIONAL + OUT UINTN *IrqPriorityTableEntries OPTIONAL + ) +{ + UINTN i = 0; + EFI_STATUS Status = EFI_NOT_READY; + + if(IsValidPrt) + { + *RoutingTable = Prt; + // *RoutingTableEntries = AmiPrt->bUsedEntries; + *RoutingTableEntries = gUsedPciEntries; + if (LocalPirqTable != NULL) *LocalPirqTable = MsPrt; + if (PirqTableSize != NULL) *PirqTableSize = MsPrt->TableSize; + if (LocalIrqPriorityTable != NULL || IrqPriorityTableEntries != NULL) return EFI_UNSUPPORTED; + Status = EFI_SUCCESS; + + for(i = 0; CsmGetRoutingTableFunctions[i] != NULL; i++) + { + // Do not check the return status incase there are multiple functions that update + // each of the tables individually. + Status = CsmGetRoutingTableFunctions[i](This, + RoutingTable, + RoutingTableEntries, + LocalPirqTable, + PirqTableSize, + LocalIrqPriorityTable, + IrqPriorityTableEntries); + } + } + return Status; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: BspUpdatePrt +// +// Description: This function is called from PciInterrupts.c when PCI Interrupt +// routing table is ready for copying to shadow memory. Do the final +// updates of the routing information. +// +// Input: +// This Indicates the EFI_LEGACY_BIOS_PLATFORM_PROTOCOL instance. +// RoutingTable Pointer to the PCI IRQ routing table. This location is +// the $PIR table. The contents is defined by the PCI IRQ +// Routing Table Specification; it has the number of +// RoutingTableEntries of EFI_LEGACY_IRQ_ROUTING_ENTRY. +// +// Output: +// EFI_SUCCESS Data was updated successfully. +// +// Notes: Checksum of the table is not required in this routine, it will +// be done after this call is executed. +// +// Referrals: +// EFI_LEGACY_BIOS_PLATFORM_PROTOCOL, EFI_LEGACY_IRQ_ROUTING_ENTRY, +// EFI_LEGACY_PIRQ_TABLE_HEADER, EFI_LEGACY_IRQ_PRIORITY_TABLE_ENTRY +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +BspUpdatePrt( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN VOID *RoutingTable +) +{ + UINTN i = 0; + EFI_STATUS Status = EFI_UNSUPPORTED; + + for(i = 0; CsmBspUpdatePrtFunctions[i] != NULL; i++) + { + Status = CsmBspUpdatePrtFunctions[i](This, RoutingTable); + if(!EFI_ERROR(Status)) break; + } + + return Status; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: TranslatePirq +// +// Description: This function translates the given PIRQ back through all +// buses, if required, and returns the true PIRQ and associated IRQ. +// Input: +// This Indicates the EFI_LEGACY_BIOS_PLATFORM_PROTOCOL instance. +// PciBus PCI bus number for this device. +// PciDevice PCI device number for this device. +// PciFunction PCI function number for this device. +// Pirq The PIRQ. PIRQ A = 0, PIRQ B = 1, and so on. +// PirqIrq IRQ assigned to the indicated PIRQ. +// +// Output: +// EFI_SUCCESS The PIRQ was translated. +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +TranslatePirq ( + IN EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *This, + IN UINTN PciBus, + IN UINTN PciDevice, + IN UINTN PciFunction, + IN OUT UINT8 *Pirq, + OUT UINT8 *PciIrq + ) +{ + return Intx2Pirq( + This, + PciBus, PciDevice, PciFunction, + Pirq, PciIrq, NULL); +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: BspPrepareToBoot +// +// Description: Prepares the attempt to boot a traditional OS. +// +// Input: +// This Indicates the EFI_LEGACY_BIOS_PLATFORM_PROTOCOL instance. +// BbsDevicePath EFI Device Path from BootXXXX variable. Type +// BBS_BBS_DEVICE_PATH is defined in EFI_LEGACY_BIOS_PROTOCOL.LegacyBoot(). +// BbsTable A list of BBS entries of type BBS_TABLE. Type BBS_TABLE is +// defined in Compatibility16PrepareToBoot(). +// LoadOptionsSize Size of LoadOption in bytes. +// LoadOptions LoadOption from BootXXXX variable. +// EfiToLegacyBootTable Pointer to EFI_TO_COMPATIBILITY16_BOOT_TABLE. Type +// EFI_TO_COMPATIBILITY16_BOOT_TABLE is defined +// in Compatibility16PrepareToBoot(). +// Output: +// EFI_SUCCESS Ready to boot. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +BspPrepareToBoot ( + IN EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *This, + IN BBS_BBS_DEVICE_PATH *BbsDevicePath, + IN VOID *BbsTable, + IN UINT32 LoadOptionsSize, + IN VOID *LoadOptions, + IN VOID *EfiToLegacyBootTable + ) +{ + EFI_STATUS Status = EFI_UNSUPPORTED; + UINTN i = 0; + + for(i = 0; CsmBspPrepareToBootFunctions[i] != NULL; i++) + { + Status = CsmBspPrepareToBootFunctions[i](This, BbsDevicePath, BbsTable, LoadOptionsSize, LoadOptions, EfiToLegacyBootTable); + if(!EFI_ERROR(Status)) break; + } + return Status; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: InitCsmBoard +// +// Description: CSM BSP driver entry point, it will instantinate +// LEGACY_BIOS_PLATFORM_PTOTOCOL interface +// +// Input: Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT +// +// Output: The status of CSM board initalization +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +InitCsmBoard ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; + EFI_GUID gFile; + EFI_FIRMWARE_VOLUME_PROTOCOL *pFV; + UINT32 Authentication; + +// InitAmiLib(ImageHandle, SystemTable); + Status = pBS->AllocatePool( + EfiBootServicesData, + sizeof(PLATFORM_BIOS_INFO), + &BspBiosInfo); + if (EFI_ERROR(Status)) return Status; + + pBS->SetMem(BspBiosInfo, sizeof(PLATFORM_BIOS_INFO), 0); + + // + // Get LOADED_IMAGE protocol in order to get to the file name GUID + // + Status = pBS->HandleProtocol( + ImageHandle, &gEfiLoadedImageProtocolGuid, &LoadedImage); + if (EFI_ERROR(Status)) return Status; + + // + // Now we have EFI_DEVICE_PATH_PROTOCOL *LoadedImage->FilePath + // + gFile = ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH*)(LoadedImage->FilePath))->NameGuid; + + // + // Get the Firmware Volume Protocol + // + Status = pBS->HandleProtocol ( + LoadedImage->DeviceHandle, + &gEfiFirmwareVolumeProtocolGuid, + &pFV + ); + if (EFI_ERROR(Status)) return Status; + + // + // Read section with Legacy ROMs + // + EmbeddedRom = NULL; // make ReadSection allocate memory + EmbeddedRomSize = 0; + Status = pFV->ReadSection ( + pFV, + &gFile, + EFI_SECTION_RAW, + 0, + &EmbeddedRom, + &EmbeddedRomSize, + &Authentication); + if (EFI_ERROR(Status)) return Status; + + BspBiosInfo->hImage = ImageHandle; + BspBiosInfo->iBiosPlatform.GetPlatformInfo = GetPlatformInfo; + BspBiosInfo->iBiosPlatform.GetPlatformHandle = GetPlatformHandle; + BspBiosInfo->iBiosPlatform.SmmInit = SmmInit; + BspBiosInfo->iBiosPlatform.PlatformHooks = PlatformHooks; + BspBiosInfo->iBiosPlatform.GetRoutingTable = GetRoutingTable; + BspBiosInfo->iBiosPlatform.TranslatePirq = TranslatePirq; + BspBiosInfo->iBiosPlatform.PrepareToBoot = BspPrepareToBoot; + + InitPrt(&BspBiosInfo->iBiosPlatform); + + // + // Make a new handle and install the protocol + // + BspBiosInfo->hBios = NULL; + Status = pBS->InstallProtocolInterface ( + &BspBiosInfo->hBios, + &gEfiLegacyBiosPlatformProtocolGuid, + EFI_NATIVE_INTERFACE, + &BspBiosInfo->iBiosPlatform + ); + + 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 ** +//** ** +//********************************************************************** +//********************************************************************** diff --git a/Core/EM/CSM/CsmHwInfo.c b/Core/EM/CSM/CsmHwInfo.c new file mode 100644 index 0000000..ab4bce8 --- /dev/null +++ b/Core/EM/CSM/CsmHwInfo.c @@ -0,0 +1,2063 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2014, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** + +//**************************************************************************** +// $Header: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/EM/CSM/CsmHwInfo.c 1 7/31/17 4:55a Chienhsieh $ +// +// $Revision: 1 $ +// +// $Date: 7/31/17 4:55a $ +// +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/EM/CSM/CsmHwInfo.c $ +// +// 1 7/31/17 4:55a Chienhsieh +// [TAG] EIP184371 +// [Description] Filter the DiskInfo protocols while creating HddInfo +// [Files] CsmHwInfo.c +// +// 114 8/07/14 12:44p Fasihm +// [TAG] EIP180683 +// [Category] Improvement +// [Severity] Normal +// [Symptom] Aptio 4 CSM: CSM build error when disabling +// X64_SUPPORT. +// [Solution] Changed file to fix the build error. +// [Files] +// Core\EM\CSM\CsmBsp.c +// Core/EM/CSM/CsmHwInfo.c +// +// 113 8/06/14 5:21p Fasihm +// [TAG] EIP180688 +// [Category] Improvement +// [Severity] Normal +// [Symptom] Aptio 4 CSM: PMM high memory life cycle. +// [Solution] Changed file to address the PMM high memory life cycle. +// [Files] +// Core/EM/CSM/CsmHwInfo.c +// +// 112 8/06/14 3:21p Fasihm +// [TAG] EIP180674 +// [Category] Bug Fix +// [Severity] Normal +// [Symptom] Aptio 4 CSM: CSM16: RT PCI function find_device should +// skip buses that do not exist. +// [Solution] find_device function in RT-PCI.ASM has been modified to +// look for the device on the buses that are physically present in the +// system. +// [Files] +// Addon/AmiLegacy16.bin +// Core/EM/CSM/CSM.h +// Core/EM/CSM/CsmHwInfo.c +// +// 111 8/06/14 12:31p Fasihm +// [TAG] EIP180666 +// [Category] Bug Fix +// [Severity] Normal +// [Symptom] Aptio4: Sata boot options need to be distinguished when +// there are more than one controller. +// [Solution] While displaying Boot option in the Set up screen, +// Proposed to display in format ( C<Controller Number> :: P<Port Number> +// - Model Number). +// [Files] +// Core/EM/CSM/CSM.h +// Core/EM/CSM/CsmHwInfo.c +// +// 110 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 +// +// 109 12/12/12 2:54p Olegi +// [TAG] EIP109283 +// [Category] Bug Fix +// [Symptom] PCI RT32 last bus improperly reported +// [RootCause] The last PCI bus is reported based on the chipset +// specific PCI bus configuration. +// [Solution] Update RT32 binary with the last bus obtained from PCI Bus +// driver. +// [Files] CsmHwInfo.c, rt32core.asm +// +// 108 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 +// +// 107 2/09/12 10:19a Olegi +// [TAG] EIP71972 +// Correction to the original EIP71972 resolution: Slave IDE device was +// not getting proper drive handle. +// +// 106 11/04/11 12:39p Olegi +// [TAG] EIP74722 +// [Category] Improvement +// [Description] IDE drive information is not displayed correctly in the +// Boot page in Setup when both Master and Slave drives are connected +// [Files] CsmHwInfo.c +// +// 105 10/28/11 9:24a Olegi +// [TAG] EIP71972 +// [Category] Improvement +// [Description] In some cases HddInfo information is not properly used +// to create BBS entry. +// Cases are: +// - slave drive appears before master in DisdInfo hanle array +// - higher controller PCI function appears before lower function in the +// DiskInfo list +// [Files] csmhwinfo.c +// +// 104 5/04/11 2:15p Olegi +// [TAG] EIP59632 +// [Category] Improvement +// [Description] Removed the break from for loop in +// UpdateCsm16Configuration; this allows to finish all COM data +// initialization. +// [Files] CsmHwInfo.c +// +// 103 4/11/11 12:56p Olegi +// [TAG] EIP56926 +// [Category] Improvement +// [Description] Added Primary/Secondary Master/Slave information in the +// drive string. +// [Files] csmhwinfo.c +// +// 102 2/04/11 10:19a Olegi +// [TAG] EIP53139 +// [Category] Improvement +// [Description] Typo corrected +// [Files] csmhwinfo.c +// +// 101 12/03/10 12:43p Olegi +// [TAG] EIP48471 +// [Category] Bug Fix +// [Severity] Normal +// [Symptom] COM Port addresses are not filled in correctly in BDA when +// COM 0(First COM port) disabled in setup. +// [RootCause] For the COM port resource details in BDA, we should not +// depend on the UID of the Com port. +// [Solution] 1) Get the 1st COM port details and fill the details in +// CSm16bootable , BDA 40:0 and increment Serial Port count in 40:0x10. +// 2) Get the 2nd Com port details and fill the details in CSm16bootable , +// BDA 40:2 and increment Serial Port count in 40:0x10..Continue this for +// 4 com ports. +// [Files] CsmHwInfo.c +// CsmLib.c +// +// 100 11/08/10 9:06a Olegi +// Added CloseEvent call in UpdateLastPciBus callback function. +// +// 99 8/17/10 3:10p Olegi +// Fixes discovered by Klockwork II engine: EIP37977 +// +// 98 7/16/10 12:12p Olegi +// EIP39395: Update CSM16 header checksum after LastPciBus field of it has +// been changed. +// +// 97 6/18/10 10:29a Olegi +// EIP39149: Bugfix in UpdatePciLastBusCallback function. +// +// 96 5/07/10 5:04p Felixp +// Bug fix in GetSystemMemoryMap +// +// 95 5/07/10 5:00p Felixp +// Minor improvement in GetSystemMemoryMap (EIP 38327): +// use memory map descriptor size returned by the GetMemoryMap instead of +// hard-coded value. +// +// 94 4/28/10 2:51p Oleksiyy +// EIP 35563 Fixed logic when looking for ACPI 1.1 only tables. +// +// 93 1/12/10 11:46a Olegi +// Copyright message updated. +// +// 92 12/28/09 7:46a Olegi +// Added GetLptResource function. +// +// 91 12/28/09 7:33a Olegi +// +// 90 12/08/09 9:52a Olegi +// +// 89 12/01/09 11:38a Olegi +// Bugfix in EnableDisableNmi function. +// +// 88 8/18/09 2:02p Rameshr +// AhciBus driver doesn't work for Multi Entry. +// Ahci Int13 initilization code moved from AhciBus to CsmHwinfo.c +// EIP: 25369 +// +// 87 8/06/09 11:42a Olegi +// MaxPciBus reporting change: do not report FF; this is XP limitation, +// EIP#24852. +// +// 86 6/16/09 4:11p Olegi +// Generic modifications to update LastPciBus field in +// EFI_COMPATIBILITY16_TABLE. +// +// 85 6/16/09 10:09a Olegi +// Resolved the incompatibility with the GenericSio.h definitions. +// +// 84 6/05/09 10:32a Olegi +// EIP20813 - make IRQ7 handler execute from E000 segment, this is the +// workaround for DOS problem, that will take over IRQ7 handler if it is +// located in F000. +// +// 83 4/02/09 2:12p Olegi +// Removed the hardcoding of COM port base address/interrupt. +// +// 82 3/13/09 5:23p Olegi +// Modifications in GetAtaAtapiInfo(): +// - removed checking if ABAR (PciCfg[24h]) is 0: under the condition +// where Subclass code is 6 this checking does not make sense +// - added the clarification of checking for SATA device path vs. AE bit +// +// 81 12/02/08 10:20a Olegi +// Changed the logic of extended memory size calculation. +// +// 80 10/10/08 3:36p Olegi +// +// 79 6/04/08 11:09a Olegi +// Bugfix in the previous modification. +// +// 78 6/02/08 6:13p Olegi +// Modified GetAtaAtapiInfo to handle non-IDE mass storage controllers. +// +// 77 3/28/08 3:01p Olegi +// Bugfix in GetAtaAtapiInfo for AHCI enabled controller. +// +// 76 2/25/08 4:48p Olegi +// GetAtaAtapiInfo is modified to handle the situation when SATA +// controller is in RAID mode and RAID OpROM is not handling all connected +// devices (CDROM). +// +// 75 12/10/07 1:34p Olegi +// Bug in the previous checkin is fixed. +// +// 74 12/10/07 12:27p Olegi +// Modified AHCI controller checking. +// +// 73 12/04/07 11:07a Olegi +// +// 72 11/07/07 10:44a Olegi +// Fix in GetExtendedMemSize function: if the amount of memory is 4GB or +// more, some memory is remapped above 4GB by the chipset. In this case +// this function will return the amount of memory before the remapped +// area. +// +// 71 10/02/07 10:34a Olegi +// Modified GetFDDStatus() routine to properly use IsSioDevicePluggedIn(). +// +// 2 7/17/07 6:17p Fasihm +// +// 69 6/26/07 9:59a Olegi +// MMIO regions with runtime attribute set will have the corresponding +// E820 reserved entry. +// +// 68 6/18/07 5:46p Olegi +// +// 67 6/06/07 8:16a Olegi +// Added CSM_CREATES_ATA_ATAPI_STRINGS dependency in CreateDriveString +// function. +// +// 66 6/04/07 12:34p Olegi +// +// 65 6/02/07 10:26a Olegi +// Shadow size correction. +// +// 64 5/18/07 11:46a Olegi +// Changed setting BIT2 in 410h (legacy mouse present bit) in +// UpdateCsm16Configuration to avoid clearing this bit if it is already +// set. +// +// 63 5/09/07 1:56p Olegi +// +// 62 4/27/07 5:13p Olegi +// CSM.CHM file preparation. +// +// 61 4/13/07 9:40a Olegi +// +// 60 3/29/07 5:44p Olegi +// Modification in UpdateE820Map function to accomodate Legacy Redirection +// data area. +// +// 59 12/15/06 2:09p Olegi +// Bugfix in DiskInfoHandles usage. +// +// 58 12/14/06 11:06a Olegi +// Adding AGGRESSIVELY_JOINED_E820_ENTRIES flag. +// +// 57 12/12/06 5:33p Olegi +// DiskInfo handles inserted in BBS table as IBV1/IBV2. +// +// 56 9/26/06 4:19p Olegi +// GetFDDStatus is modified to make default number of FDDs 0. +// +// 55 9/20/06 3:11p Olegi +// +// 54 9/13/06 9:34a Felixp +// +// 53 9/13/06 9:32a Felixp +// +// 52 9/12/06 6:10p Markw +// Update EFI_TO_COMPATIBILITY16_BOOT_TABLE structure to UINT32 instead of +// pointer. This structure is used for CSM16 which expects 4 byte +// pointers. +// +// 51 8/28/06 9:49a Olegi +// Bugfix in InstallLegacyMassStorageDevices routine. +// +// 50 8/14/06 11:24a Olegi +// +// 49 8/04/06 12:05p Olegi +// E820 table optimization added. +// +// 48 7/28/06 4:43p Olegi +// +// 47 5/16/06 1:57p Olegi +// +// 45 5/04/06 10:55a Robert +// +// 44 5/04/06 9:42a Olegi +// Removed the logic that fixes the location of PATA/SATA in BBS table. +// +// 43 5/03/06 3:42p Robert +// Added the code to sort out the DiskInfo handles so that PATA goes +// first, SATA next. +// +// 40 3/31/06 2:30p Olegi +// +// 39 3/13/06 2:32p Felixp +// +// 38 12/14/05 4:16p Olegi +// NMI enable/disable changes. +// +// 37 11/29/05 11:38a Olegi +// Bugfix - not all ATAPI devices are CDROMs, as it used to be considered +// in the GetAtaAtapi routine. +// +// 35 10/17/05 8:56a Olegi +// +// 34 10/13/05 6:25p Olegi +// +// 33 10/11/05 11:56a Olegi +// +// 32 10/10/05 7:27p Olegi +// +// 31 10/07/05 5:16p Olegi +// +// 30 10/06/05 8:11p Felixp +// +// 29 10/06/05 11:52a Felixp +// +// 28 9/30/05 6:27p Olegi +// VC7.1 compatibility issues solved. +// +// 27 9/29/05 5:20p Olegi +// +// 26 9/28/05 8:30a Olegi +// +// 25 9/21/05 3:56p Olegi +// +// 24 9/09/05 6:04p Olegi +// +// 23 9/09/05 11:19a Olegi +// +// 22 6/30/05 7:55p Olegi +// PS/2 mouse handling reported correctly. +// +// 21 6/21/05 12:12p Olegi +// LegacyBios and LegacyBiosPlatform are combined into one FFS. +// +// 20 5/12/05 5:15p Yakovlevs +// +// 19 4/22/05 2:10p Olegi +// +// 19 4/21/05 9:00a Olegi +// Modified the rule for inserting E820 entries for regions >4GB +// +// 18 4/19/05 11:12a Olegi +// +// 17 3/30/05 12:28p Olegi +// InstallIdePciHandler - IDE control port calculation corrected. +// +// 16 3/04/05 1:54p Mandal +// +//********************************************************************** +//<AMI_FHDR_START> +// +// Name: CsmHwInfo.c +// Description: Hardware Information routines +// +//<AMI_FHDR_END> +//**************************************************************************** + +#include "token.h" +#include "csm.h" +#include <Protocol/PciIo.h> +#include <Protocol/PDiskInfo.h> +#include <Protocol/DevicePath.h> +#include <Protocol/PciRootBridgeIo.h> +#include <Protocol/PIdeController.h> +#include <Protocol/BlockIo.h> +#include <AmiDxeLib.h> +#include "pci.h" +#include "biosdata.h" +#include <Protocol/CsmPlatform.h> +#include <AcpiRes.h> +#ifdef AhciSrc_SUPPORT +#if AhciSrc_SUPPORT +#include <Protocol/LegacyAhci.h> +#endif +#endif + +#define MASTER_DRIVE 0 +#define SLAVE_DRIVE 1 +#define PRIMARY_CHANNEL 0 +#define SECONDARY_CHANNEL 1 +#define MAX_IDE_PCI_CONTROLLER (MAX_IDE_CONTROLLER << 1) + +// Controller information where IDE devices are connected +IDE_CONTROLLER_INFO_STRUC IdeControllerInfo[MAX_IDE_PCI_CONTROLLER]; +UINT8 gIdeController = 0; + +UINT16 aInstalledPciIrq[MAX_IDE_PCI_CONTROLLER]; + +EFI_GUID gDiskInfoProtocol = EFI_DISK_INFO_PROTOCOL_GUID; +EFI_GUID gSataControllerProtocol = SATA_CONTROLLER_PROTOCOL_GUID; +EFI_GUID gAcpiRsdtPtr = ACPI_20_TABLE_GUID; +EFI_GUID gAcpiRsdtPtr1_0 = ACPI_10_TABLE_GUID; +EFI_GUID gSmbiosTable = SMBIOS_TABLE_GUID; + +typedef struct { + ATAPI_IDENTIFY *IdentifyPtr; + EFI_HANDLE DriveHandle; +} CSM_DRIVE_HANDLE_LIST; + +CSM_DRIVE_HANDLE_LIST DriveHandle[MAX_IDE_CONTROLLER*2] ; + +EFI_STATUS UpdateCsm16Configuration(EFI_TO_COMPATIBILITY16_BOOT_TABLE*); +VOID GetExtendedMemSize(UINT32*); +VOID GetSioDeviceStatus(SIO_DEV_STATUS *devices); +BOOLEAN IsSioDevicePluggedIn(SIO_DEV_STATUS *plugged_devices, EFI_HANDLE *Handle); + +extern BIOS_INFO *CoreBiosInfo; +extern BOOLEAN gIsMassStorageInstalled; +extern UINTN gMaxOpRomAddress; + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: UpdateCsm16Configuration +// +// Description: +// This function updates Csm16BootTable and BDA. It can be called multiple +// times during POST as the new hardware is discovered and configured. +// +// Input: +// Csm16BootTable pointer to EFI_TO_COMPATIBILITY16_BOOT_TABLE +// +// Output: +// EFI_SUCCESS Table is updated successfully. +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +UpdateCsm16Configuration( + IN OUT EFI_TO_COMPATIBILITY16_BOOT_TABLE *Csm16BootTable +) +{ + SIO_DEV_STATUS sio_devices; + SIO_DEV_STATUS sio_devices_plugged_in; + BDA_DATA *bda; + UINT16 machineconfig = 0; + EFI_HANDLE Handle; + EFI_STATUS Status; + UINT16 Address; + UINT8 Irq; + UINT8 ComPortIndex; + + // + // Fill in EFI_TO_COMPATIBILITY16_BOOT_TABLE + // Note: CSM specification 0.96 defines the pointer as UINT32 - it is + // assumed BbsTable pointer is within 4GB address space. + Csm16BootTable->BbsTable = (UINT32)CoreBiosInfo->BbsTable; + Csm16BootTable->NumberBbsEntries = CoreBiosInfo->BbsEntriesNo; + + // + // Updade SIO status in Csm16BootTable->SioData and in BDA + // + bda = (BDA_DATA*)((UINTN) 0x400); + +// The following definitions are from the up-to-date GenericSio.h +// they can be used after GenericSio.h will be labeled with these changes. +//#define SIO_DEV_COM3 0x1000 +//#define SIO_DEV_COM4 0x2000 + + sio_devices.DEV_STATUS = SIO_DEV_COM1 | SIO_DEV_COM2 | 0x1000 | 0x2000 | + SIO_DEV_LPT | SIO_DEV_FDC | SIO_DEV_PS2MS; + GetSioDeviceStatus(&sio_devices); + + if (sio_devices.Fdd) { + Csm16BootTable->SioData.Floppy.NumberOfFloppy = 1; + machineconfig |= 1; + } + + for(ComPortIndex = 0; ComPortIndex < 4; ComPortIndex ++){ + Status = GetComPortResource(ComPortIndex, &Address, &Irq); + if (!EFI_ERROR(Status)) + { + Csm16BootTable->SioData.Serial[ComPortIndex].Address = Address; + Csm16BootTable->SioData.Serial[ComPortIndex].Irq = Irq; + Csm16BootTable->SioData.Serial[ComPortIndex].Mode = DEVICE_SERIAL_MODE_NORMAL; + bda->rs_232_address[ComPortIndex] = Address; + machineconfig += 0x200; + } + } + // Note that SIO_DEV_STATUS limits the number of LPT to one + if (sio_devices.Lpt) { + Status = GetLptResource(&Address, &Irq); + if (!EFI_ERROR(Status)){ + Csm16BootTable->SioData.Parallel[0].Address = Address; + Csm16BootTable->SioData.Parallel[0].Irq = Irq; + Csm16BootTable->SioData.Parallel[0].Mode = DEVICE_PARALLEL_MODE_MODE_OUTPUT_ONLY; + bda->printer_address[0] = Address; + machineconfig |= 0x4000; + } + } + + if ((bda->machine_config & 4) || sio_devices.Ps2Mouse) { + machineconfig |= 0x4; + + sio_devices_plugged_in.DEV_STATUS = 0; + sio_devices_plugged_in.Ps2Mouse = 1; + if (IsSioDevicePluggedIn(&sio_devices_plugged_in, &Handle)) { + Csm16BootTable->SioData.MousePresent = 1; + } + } + + machineconfig |= 2; // coprocessor is always reported present + + bda->machine_config = machineconfig; + + GetExtendedMemSize(&Csm16BootTable->OsMemoryAbove1Mb); + Csm16BootTable->NumberE820Entries = CoreBiosInfo->NumberE820Entries; + + // + // Get ACPI&SMBIOS pointers + // +//TODOx64: What is these pointers are more the 4G in 64 bit mode? +//CSM specification 0.96 defines the pointers as UINT32 + Csm16BootTable->AcpiTable = (UINT32)GetEfiConfigurationTable(pST, &gAcpiRsdtPtr); + if (Csm16BootTable->AcpiTable == 0) + Csm16BootTable->AcpiTable = (UINT32)GetEfiConfigurationTable(pST, &gAcpiRsdtPtr1_0); + + TRACE((-1,"CSM - GetEfiConfigurationTable: ACPI table is at %x\n", Csm16BootTable->AcpiTable)); + + Csm16BootTable->SmbiosTable = (UINT32)GetEfiConfigurationTable(pST, &gSmbiosTable); + + return EFI_SUCCESS; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// FUNCTION: GetFDDStatus +// +// DESCRIPTION: This function returns the status of the floppy drive. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +FDD_STATUS GetFDDStatus() +{ + SIO_DEV_STATUS sio_devices; + EFI_STATUS Status; + FDD_STATUS DriveStatus = NO_FLOPPY_DRIVE; + EFI_HANDLE Handle; + EFI_BLOCK_IO_PROTOCOL *blkiop; + + sio_devices.DEV_STATUS = 0; + sio_devices.Fdd = 1; + + if (!IsSioDevicePluggedIn(&sio_devices, &Handle)) return NO_FLOPPY_DRIVE; + + Status = pBS->HandleProtocol(Handle,&gEfiBlockIoProtocolGuid, &blkiop); + ASSERT_EFI_ERROR(Status); + + if (!EFI_ERROR(Status)) { + DriveStatus = blkiop->Media->MediaPresent? FLOPPY_INSERTED : NO_FLOPPY_DISK; + } + + return DriveStatus; + +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// FUNCTION: InstallIdePciHandler +// +// DESCRIPTION: This function makes InstallPciHandler CSM16 call +// +// PARAMETERS: PCI IDE controller data needed for the IRQ installation +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +InstallIdePciHandler( + HDD_INFO* HddInfo1, + HDD_INFO* HddInfo2 +) +{ + EFI_IA32_REGISTER_SET RegSet; + EFI_STATUS Status; + UINT8 i; + EFI_LEGACY_INSTALL_PCI_HANDLER *PciHandlerData = &CoreBiosInfo->Thunk->PciHandler; + UINT16 wPciDev = 0xFFFF; + BOOLEAN IsNativeMode; + // + // Check whether PCI IRQ handler for this PCI device has been installed, exit if so. + // + for (i = 0; i < MAX_IDE_PCI_CONTROLLER; i++) { + wPciDev = (UINT16)((HddInfo1->Bus << 8) | (HddInfo1->Device << 3) | HddInfo1->Function); + if (!aInstalledPciIrq[i]) break; // New entry found + if (wPciDev == aInstalledPciIrq[i]) return EFI_SUCCESS; + } + ASSERT(i < MAX_IDE_PCI_CONTROLLER); + if (i == MAX_IDE_PCI_CONTROLLER) return EFI_OUT_OF_RESOURCES; // Error - no free entries + + // + // Prepare PCI handler data in Thunk memory + // + PciHandlerData->PciBus = (UINT8)HddInfo1->Bus; + PciHandlerData->PciDeviceFun = (UINT8)((HddInfo1->Device << 3) | HddInfo1->Function); + PciHandlerData->PciSegment = 0; + PciHandlerData->PciClass = PCI_CL_MASS_STOR; + PciHandlerData->PciSubclass = PCI_CL_MASS_STOR_SCL_IDE; + IsNativeMode = HddInfo1->HddIrq != 14; + PciHandlerData->PciInterface = (IsNativeMode)?0x8F:0x8A; + + // + // Primary section + // + PciHandlerData->PrimaryIrq = HddInfo1->HddIrq; + PciHandlerData->PrimaryReserved = 0; + PciHandlerData->PrimaryControl = HddInfo1->ControlBaseAddress; + PciHandlerData->PrimaryBase = HddInfo1->CommandBaseAddress; + PciHandlerData->PrimaryBusMaster = HddInfo1->BusMasterAddress; + // + // Secondary section + // + PciHandlerData->SecondaryIrq = HddInfo2->HddIrq; + PciHandlerData->SecondaryReserved = 0; + PciHandlerData->SecondaryControl = HddInfo2->ControlBaseAddress; + PciHandlerData->SecondaryBase = HddInfo2->CommandBaseAddress; + PciHandlerData->SecondaryBusMaster = HddInfo2->BusMasterAddress; + + pBS->SetMem(&RegSet, sizeof (EFI_IA32_REGISTER_SET), 0); + RegSet.X.AX = Compatibility16InstallPciHandler; + RegSet.X.ES = EFI_SEGMENT (PciHandlerData); + RegSet.X.BX = EFI_OFFSET (PciHandlerData); + + 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); + if (!EFI_ERROR(Status)) { + aInstalledPciIrq[i] = wPciDev; // Save the new PCI device entry + } + + Status = CoreBiosInfo->iRegion->Lock (CoreBiosInfo->iRegion, + (UINT32)gMaxOpRomAddress+1, + 0xFFFFF-(UINT32)gMaxOpRomAddress, + NULL + ); + ASSERT_EFI_ERROR(Status); + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// Procedure: UpdateIdeControllerInfo +// +// Description: This function will check if the BusDevFunc is existing in +// Idecontrollerinfo structure array,if it exist then it return. +// If it is not exist, it will add BusDevFunc into IdeControllerInfo structure. +// +// Input: IdeBusDevFun - It contain the BusDevFunc number for a device +// +// Output: VOID +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +void UpdateIdeControllerInfo(UINT16 IdeBusDevFun) +{ + UINTN i; + + for(i=0; i < gIdeController ; i++) { + if(IdeControllerInfo[i].BusDevFun == IdeBusDevFun) { + /// Controller detected + return; + } + } + + // + // A new controller is found so BusDevFunc and ControllerNo is added + // into the array of structure. + // + IdeControllerInfo[gIdeController].BusDevFun = IdeBusDevFun; + IdeControllerInfo[gIdeController].ControllerNo = gIdeController++; + + return; + +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// FUNCTION: GetAtaAtapiInfo +// +// DESCRIPTION: This function collects the information about currently connected +// ATA/ATAPI devices. It stores this information in the HDD_INFO data +// structure and installs legacy interrupt handlers. +// +// PARAMETERS: DiskInfoHandles - array of handles with DiskInfo protocol +// Info - pointer to HDD_INFO array to be updated +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS GetAtaAtapiInfo( + IN OUT EFI_HANDLE **DiskInfoHandles, + OUT HDD_INFO* Info +) +{ + EFI_STATUS Status; + UINTN i, j, HandlesNo; + EFI_DISK_INFO_PROTOCOL *pDiskInfo; + EFI_DEVICE_PATH_PROTOCOL *pDevicePath; + EFI_PCI_IO_PROTOCOL *pPciIo; + EFI_HANDLE Handle; + UINTN Seg, Bus, Dev, Func; + HDD_INFO *HddInfo; + UINT32 PriSec, MasterSlave; + UINT8 pciCfg[0x40]; + UINT16 priCmdIoAddr, secCmdIoAddr; + UINT16 priCtlIoAddr, secCtlIoAddr; + UINT16 bmIoAddr; + UINT8 priIrq, secIrq; + BOOLEAN IsNativeMode, IsAtapiDevice, IsSataDevice; + ATAPI_IDENTIFY *pAtapiIdentifyBuffer; + UINT32 DataCount = sizeof (ATAPI_IDENTIFY); + CSM_DRIVE_HANDLE_LIST *pDriveHandle = DriveHandle; + + // Clear drive handles list + pBS->SetMem(pDriveHandle, sizeof(CSM_DRIVE_HANDLE_LIST)*MAX_IDE_CONTROLLER*2, 0); + + // + // Get the list of DiskInfo handles + // + Status = pBS->LocateHandleBuffer( + ByProtocol, + &gDiskInfoProtocol, + NULL, + &HandlesNo, + DiskInfoHandles); + if (EFI_ERROR(Status)) return EFI_NOT_FOUND; + + + for (i = 0; i < HandlesNo; i++) { +// [ EIP184371 ]+> + // Check DiskInfo.Interface field + static EFI_GUID DiIntrfGuid = EFI_DISK_INFO_IDE_INTERFACE_GUID; + + Status = pBS->HandleProtocol ( + (*DiskInfoHandles)[i], + &gDiskInfoProtocol, + &pDiskInfo); // Get DiskInfo protocol + ASSERT_EFI_ERROR (Status); + + + if (guidcmp(&pDiskInfo->Interface, &DiIntrfGuid)) continue; +// [ EIP184371 ]+< + + Status = pBS->HandleProtocol ((*DiskInfoHandles)[i], + &gEfiDevicePathProtocolGuid, + (VOID*)&pDevicePath); + ASSERT_EFI_ERROR(Status); + + // + // Get PCI device/function info out of DiskInfo device path + // + Status = pBS->LocateDevicePath( + &gEfiPciIoProtocolGuid, // Search key + &pDevicePath, // Will be updated with PCI device path + &Handle); // Will be updated with PCI device handle + if (EFI_ERROR(Status)) continue; // PCI device path is not found + + // check if SataController protocol is installed + Status = pBS->HandleProtocol ( + Handle, + &gSataControllerProtocol, + &pPciIo); //Dummy. Interface is null. + IsSataDevice = !(BOOLEAN)EFI_ERROR(Status); + + Status = pBS->HandleProtocol ( + Handle, + &gEfiPciIoProtocolGuid, + &pPciIo); // Get PciIo protocol + ASSERT_EFI_ERROR (Status); + +// [ EIP184371 ]+> +// Status = pBS->HandleProtocol ( +// (*DiskInfoHandles)[i], +// &gDiskInfoProtocol, +// &pDiskInfo); // Get DiskInfo protocol +// ASSERT_EFI_ERROR (Status); +// [ EIP184371 ]+< + + pDiskInfo->WhichIde(pDiskInfo, &PriSec, &MasterSlave); // Device/Channel info + Status = pPciIo->GetLocation(pPciIo, &Seg, &Bus, &Dev, &Func); // Location on PCI bus + ASSERT_EFI_ERROR(Status); + + /// Update controller Number for the IDE device + UpdateIdeControllerInfo(((UINT16)Bus<<8) + ((UINT16)Dev<<3) + (UINT16)Func); + + pPciIo->Pci.Read( + pPciIo, + EfiPciIoWidthUint32, + 0, + 0x10, + &pciCfg); // Get 40h bytes of PCI device configuration registers + + if (pciCfg[0xB] != PCI_CL_MASS_STOR) continue; + + if (pciCfg[0xA] == PCI_CL_MASS_STOR_SCL_RAID) continue; + + if (pciCfg[0xA] == 6) { + + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + // + // SATA controller is in AHCI mode; we can only handle it if + // AE bit is not set and controller is operated using legacy ATA/ATAPI + // mechanisms, not AHCI descriptors. Verify this by checking if + // SATA device path is installed on this device. + // + // Note: previously we were checking for the status of AE in controller's + // MMIO (ABAR at PciCfg[0x24]+4, Bit31). It was found that for some + // controllers it is not safe to access MMIO directly. Example: Intel + // ESB2 controller loses index/data access functionality after any + // AHCI MMIO register is read directly. + // + DevicePath = DPGetLastNode(pDevicePath); + if (DevicePath->Type == MESSAGING_DEVICE_PATH && + DevicePath->SubType == MSG_USB_SATA_DP) { + continue; + } + } + + IsNativeMode = pciCfg[9] & 1; + + if (IsNativeMode) { // for native mode get data from PCI config space + priCmdIoAddr = *(UINT16*)&pciCfg[0x10] & 0xFFFE; + secCmdIoAddr = *(UINT16*)&pciCfg[0x18] & 0xFFFE; + priCtlIoAddr = (*(UINT16*)&pciCfg[0x14] & 0xFFFE) + 2; + secCtlIoAddr = (*(UINT16*)&pciCfg[0x1C] & 0xFFFE) + 2; + priIrq = secIrq = pciCfg[0x3C]; + } + else { // for legacy mode use hardcoded data + priCmdIoAddr = 0x1F0; + secCmdIoAddr = 0x170; + priCtlIoAddr = 0x3F6; + secCtlIoAddr = 0x376; + priIrq = 0xE; + secIrq = 0xF; + } + bmIoAddr = *(UINT16*)&pciCfg[0x20] & 0xFFFE; + + // + // All necessary HW data is received; the following loop searches for the + // next available HddInfo, fills in HDD_INFO structure and installs legacy + // PCI interrupt if needed. + // + for (j = 0, HddInfo = Info; j < MAX_IDE_CONTROLLER; j++, HddInfo++) { + if (!HddInfo->Bus && !HddInfo->Device && !HddInfo->Function) { + HddInfo->Status = HDD_PRIMARY; + HddInfo->Bus = (UINT32)Bus; + HddInfo->Device = (UINT32)Dev; + HddInfo->Function = (UINT32)Func; + HddInfo->CommandBaseAddress = priCmdIoAddr; + HddInfo->ControlBaseAddress = priCtlIoAddr; + HddInfo->BusMasterAddress = bmIoAddr; + HddInfo->HddIrq = priIrq; + HddInfo++; + HddInfo->Status = HDD_SECONDARY; + HddInfo->Bus = (UINT32)Bus; + HddInfo->Device = (UINT32)Dev; + HddInfo->Function = (UINT32)Func; + HddInfo->CommandBaseAddress = secCmdIoAddr; + HddInfo->ControlBaseAddress = secCtlIoAddr; + HddInfo->BusMasterAddress = bmIoAddr+8; + HddInfo->HddIrq = secIrq; + if (PriSec == PRIMARY_CHANNEL) HddInfo--; + break; + } + if (Bus == HddInfo->Bus && Dev == HddInfo->Device && Func == HddInfo->Function) { + if (PriSec == SECONDARY_CHANNEL) HddInfo++; + break; + } + } + + // + // Copy the IDENTIFY_DRIVE information into appropriate HDD_INFO field + // + pAtapiIdentifyBuffer = HddInfo->IdentifyDrive; + if (MasterSlave != MASTER_DRIVE) pAtapiIdentifyBuffer++; + pDiskInfo->Identify(pDiskInfo, pAtapiIdentifyBuffer, &DataCount); + pDriveHandle->IdentifyPtr = pAtapiIdentifyBuffer; + pDriveHandle->DriveHandle = (*DiskInfoHandles)[i]; + pDriveHandle++; + // + // Check whether device is ATA or ATAPI - WORD 0 bits 14 and 15 + // + IsAtapiDevice = (BOOLEAN)((*(UINT16*)pAtapiIdentifyBuffer & 0xC000) == 0x8000); + // + // Update HDD_INFO status + // + if (PriSec == PRIMARY_CHANNEL) { + HddInfo->Status |= HDD_PRIMARY; + } else { + HddInfo->Status |= HDD_SECONDARY; + } + if (MasterSlave == MASTER_DRIVE) { + if (IsAtapiDevice) { + HddInfo->Status |= HDD_MASTER_ATAPI; + } else { + HddInfo->Status |= HDD_MASTER_IDE; + } + } else { // SLAVE_DRIVE + if (IsAtapiDevice) { + HddInfo->Status |= HDD_SLAVE_ATAPI; + } else { + HddInfo->Status |= HDD_SLAVE_IDE; + } + } + if (IsSataDevice) HddInfo->Status |= HDD_SATA_PATA; + CoreBiosInfo->HddCount++; + } + + return EFI_SUCCESS; +} + + //(EIP20813+)> +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: SetINT0F_E0000 +// +// Description: Change INT0F Vector To E000 Segment +// +// Output: EFI_STATUS Success of failure of the operation. +// +// Notes: If the IRQ7 vector is in F000 segment, MS-DOS will take over +// the IRQ7 ISR and cause HDDs not working. This routine places IRQ7 +// handler in E000 segment to avoid this problem. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +#pragma pack(1) +typedef struct +{ + UINT8 Far_JMP; + UINT32 Address; +}E0000_Int0f; +#pragma pack() + +EFI_STATUS +SetINT0F_E0000() +{ + EFI_STATUS Status; + E0000_Int0f *P_E0000_Int0f; + UINT32 LockUnlockAddr, LockUnlockSize; + UINT32 *PInt15; + + PInt15=(UINT32*)(0x0f*4); + + // + // Allocate legacy region in E000 segment; store SEG:OFS of the allocated + // memory in global variables + // + Status =GetLegacyRegion(&CoreBiosInfo->iBios, sizeof(E0000_Int0f), E0000_BIT, 0x10, &P_E0000_Int0f); + + if(EFI_ERROR(Status)) return Status; + + UnlockShadow((UINT8*)P_E0000_Int0f, sizeof(E0000_Int0f), &LockUnlockAddr, &LockUnlockSize); + + P_E0000_Int0f->Far_JMP=0xEA; //far jump + P_E0000_Int0f->Address=*PInt15; //save original vector + *PInt15= EFI_SEGMENT(P_E0000_Int0f) * 0x10000 | EFI_OFFSET (P_E0000_Int0f); //Set New INT0F Vector + + LockShadow(LockUnlockAddr, LockUnlockSize); + + return EFI_SUCCESS; +} + + //<(EIP20813+) + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// FUNCTION: InstallIdeInterrupts +// +// DESCRIPTION: This function installs PCI interrupts for all PATA and SATA +// controllers. +// +// PARAMETERS: HDD_INFO +// +// NOTES: HDD_INFO is expected to be populated before this call. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS InstallIdeInterrupts( + IN HDD_INFO *HddInfo +) +{ + UINT8 j; + UINT8 hdd_irq7_set=0; + HDD_INFO *HddInfo1 = HddInfo; + HDD_INFO *HddInfo2 = HddInfo; + EFI_STATUS Status; + + for (j = 0; j < (MAX_IDE_CONTROLLER/2); j++) { + HddInfo2 = HddInfo1+1; + if ((HddInfo1->Status & + (HDD_MASTER_ATAPI | HDD_SLAVE_ATAPI | + HDD_MASTER_IDE | HDD_SLAVE_IDE))|| + (HddInfo2->Status & + (HDD_MASTER_ATAPI | HDD_SLAVE_ATAPI | + HDD_MASTER_IDE | HDD_SLAVE_IDE))) + { + Status = InstallIdePciHandler(HddInfo1, HddInfo2); + ASSERT_EFI_ERROR(Status); + + //if (EFI_ERROR(Status)) return Status; //(EIP20813-) + + //(EIP20813+)> + + if( HddInfo1->HddIrq==0x07 || HddInfo2->HddIrq==0x07) + hdd_irq7_set=1; + + if (EFI_ERROR(Status)) break; + + //<(EIP20813+) + } + HddInfo1+=2; + } + //(EIP20813+)> + if(hdd_irq7_set) + SetINT0F_E0000(); + + //<(EIP20813+) + return EFI_SUCCESS; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// FUNCTION: CreateDriveString +// +// DESCRIPTION: This function prepares the description string for the ATA/ATAPI +// drive and places its pointer in the BBS entry. +// +// PARAMETERS: IdentifyDriveData - IDENTIFY_DRIVE data for this device +// DriveDisplayName - pointer to the string to be updated +// BbsDescStringOffset - pointer to the string description offset +// in the corresponding BBS entry +// +// NOTE: 1) DriveDisplayName must be located below 1MB +// 2) BbsDescStringSegment is UINT16 followed by BbsDescStringOffset +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID +CreateDriveString ( + IN UINT16 *IdentifyDriveData, + IN UINT16 ChannelInfo, + OUT DRIVE_DISPLAY_NAME *DriveDisplayName, + OUT UINT16 *BbsDescStringOffset, + UINTN DeviceAddress +) +{ +#if CSM_CREATES_ATA_ATAPI_STRINGS + UINT8 i, data8; + UINT16 data16 = IdentifyDriveData[76]; + UINT8 s[MAX_DRIVE_NAME] = {0}; + // Temp variable introduced in order to reduce the Code length + UINTN Temp = 0; + + if(gIdeController > 1) { + pBS->CopyMem(&s[0], "xC::APAT :",14); // "PATA: " + Temp = 4; + + /// find and replace the Controller Number in String + for(i=0;i<gIdeController;i++) { + if(IdeControllerInfo[i].BusDevFun == DeviceAddress) { + //// Controller for the AHCI Device found + s[0] = IdeControllerInfo[i].ControllerNo + 0x30; + break; + } + } + } + else { + pBS->CopyMem(&s[0], "APAT :",10); // "PATA: " + } + + // Check Word76 for BIT1 and BIT2; set for SATA drives + if ((data16 != 0xFFFF) && (data16 & 6)) { + s[1 + Temp] = 'S'; + } + + if(ChannelInfo & HDD_PRIMARY) { + s[7 + Temp]='P'; + if(ChannelInfo & (HDD_MASTER_IDE | HDD_MASTER_ATAPI )) { + s[6 + Temp]='M'; + } else { + s[6 + Temp]='S'; + } + } else if(ChannelInfo & HDD_SECONDARY) { + s[7 + Temp]='S'; + if(ChannelInfo & (HDD_MASTER_IDE | HDD_MASTER_ATAPI )) { + s[6 + Temp]='M'; + } else { + s[6 + Temp]='S'; + } + } + + // Get the drive name out of IdentifyDrive data word 27..46 (upto 40 chars) + pBS->CopyMem(&s[10 + Temp], IdentifyDriveData+27, MAX_DRIVE_NAME- (11+Temp) ); + // Swap the bytes + for (i=0; i<MAX_DRIVE_NAME; i+=2) { + data8=s[i]; + s[i]=s[i+1]; + s[i+1]=data8; + } + + pBS->CopyMem(DriveDisplayName, s, MAX_DRIVE_NAME); + // Update string pointer in BBS after converting it to SEG:OFS format + *BbsDescStringOffset = (UINT16)(UINTN)DriveDisplayName; + *(BbsDescStringOffset+1) = (UINT16)(((UINTN)DriveDisplayName >> 4) & 0xF000); +#endif +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// FUNCTION: GetAtapiDeviceType +// +// DESCRIPTION: This function returns ATAPI device type depending on the information +// provided by IDENDIFY_DRIVE data. It could call CSM platform functions +// to return platform specific ATAPI device type or if the type is +// selectable in System Setup. +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT16 +GetAtapiDeviceType( + IN ATAPI_IDENTIFY *IdentifyDriveData +) +{ + UINT16 DevType; + EFI_STATUS Status; + CSM_PLATFORM_PROTOCOL *CsmPlatformProtocol; + + pBS->LocateProtocol(&gCsmPlatformProtocolGuid, NULL, &CsmPlatformProtocol); + // + // LocateProtocol will return CsmPlatformProtocol = NULL if protocol is not found. + // + if (CsmPlatformProtocol) { + Status = CsmPlatformProtocol->GetAtapiDeviceType(CsmPlatformProtocol, IdentifyDriveData, &DevType); + if (!EFI_ERROR(Status)) return DevType; // Identified + } + // + // Use default, "generic" method of device identification + // + DevType = BBS_FLOPPY; + + if ((IdentifyDriveData->Raw[0] & 0x1F00) == 0x500) + { + DevType = BBS_CDROM; + } + return DevType; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: GetDriveHandle +// +// Description: +// This function searches for the IDE mass storage device handle in the list +// of handles and returns the one that matches with the given IdentifyDrive +// information. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_HANDLE GetDriveHandle(ATAPI_IDENTIFY *IdentifyPtr) +{ + UINT8 i; + for (i=0; i<MAX_IDE_CONTROLLER*2; i++){ + if (DriveHandle[i].IdentifyPtr == IdentifyPtr) + return DriveHandle[i].DriveHandle; + } + + return NULL; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// FUNCTION: InstallLegacyMassStorageDevices +// +// DESCRIPTION: This function prepares BBS table, inserts FDD/IDE/SATA entries +// in the table and calls CSM16->UpdateBbs function to bring up +// non-BBS compliant entries as well. +// +// NOTE: This function should be executed only once, when DiskInfo handles +// are ready. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID InstallLegacyMassStorageDevices() +{ + HDD_INFO *AtaAtapiInfo; + UINT8 IdeCtl, Indx; + EFI_STATUS Status; + UINT8 count = 0; + EFI_HANDLE *DiskInfoHandles = 0; + + BBS_TABLE *BbsEntry = CoreBiosInfo->BbsTable; + + // + // Insert ATA/ATAPI devices into CoreBiosInfo->Thunk->Csm16BootTable.HddInfo + // + for (Indx = 0; Indx < MAX_IDE_PCI_CONTROLLER; Indx++) aInstalledPciIrq[Indx] = 0; + AtaAtapiInfo = CoreBiosInfo->Thunk->Csm16BootTable.HddInfo; + + Status = GetAtaAtapiInfo(&DiskInfoHandles, AtaAtapiInfo); + + if (!EFI_ERROR(Status)) { // some IDE device are connected + InstallIdeInterrupts(AtaAtapiInfo); + // + // Update BBS table with controller/device information + // + for (IdeCtl = 0; IdeCtl < MAX_IDE_CONTROLLER; IdeCtl++) { + if (!(AtaAtapiInfo[IdeCtl].Status & + ( HDD_MASTER_ATAPI | HDD_SLAVE_ATAPI | HDD_MASTER_IDE | HDD_SLAVE_IDE ))) { + continue; + } + Indx = IdeCtl*2 + 1; // 1st entry is taken for floppy + + BbsEntry[Indx].Bus = BbsEntry[Indx+1].Bus = AtaAtapiInfo[IdeCtl].Bus; + BbsEntry[Indx].Device = BbsEntry[Indx+1].Device = AtaAtapiInfo[IdeCtl].Device; + BbsEntry[Indx].Function = BbsEntry[Indx+1].Function = AtaAtapiInfo[IdeCtl].Function; + BbsEntry[Indx].Class = BbsEntry[Indx+1].Class = 1; + BbsEntry[Indx].SubClass = BbsEntry[Indx+1].SubClass = 1; + + if (AtaAtapiInfo[IdeCtl].CommandBaseAddress) { // real controller + // + // Create entry for master device connected to this controller + // + if (AtaAtapiInfo[IdeCtl].Status & (HDD_MASTER_IDE | HDD_MASTER_ATAPI)) { + BbsEntry[Indx].BootPriority = BBS_UNPRIORITIZED_ENTRY; + if (AtaAtapiInfo[IdeCtl].Status & HDD_MASTER_ATAPI) { + BbsEntry[Indx].DeviceType = GetAtapiDeviceType(&AtaAtapiInfo[IdeCtl].IdentifyDrive[0]); + } else { + BbsEntry[Indx].DeviceType = BBS_HARDDISK; + } + CreateDriveString( + AtaAtapiInfo[IdeCtl].IdentifyDrive[0].Raw, + AtaAtapiInfo[IdeCtl].Status & ~(HDD_SLAVE_IDE | HDD_SLAVE_ATAPI), + &CoreBiosInfo->Thunk->DriveDisplayName[count++], + &BbsEntry[Indx].DescStringOffset, + ((UINT16)AtaAtapiInfo[IdeCtl].Bus << 8) +((UINT16)AtaAtapiInfo[IdeCtl].Device<<3)\ + + ((UINT16) AtaAtapiInfo[IdeCtl].Function ) + ); + //TRACE((-1, "i=%d, bbsentry=%x, diskinfo=%x\n", Indx, &BbsEntry[Indx], *DiskInfoHandles)); + *(UINTN*)(&BbsEntry[Indx].IBV1) = (UINTN)GetDriveHandle(AtaAtapiInfo[IdeCtl].IdentifyDrive);//(EIP71972) + } + // + // Create entry for slave device connected to this controller + // + if (AtaAtapiInfo[IdeCtl].Status & (HDD_SLAVE_IDE | HDD_SLAVE_ATAPI)) { + BbsEntry[Indx+1].BootPriority = BBS_UNPRIORITIZED_ENTRY; + if (AtaAtapiInfo[IdeCtl].Status & HDD_SLAVE_ATAPI) { + BbsEntry[Indx+1].DeviceType = GetAtapiDeviceType(&AtaAtapiInfo[IdeCtl].IdentifyDrive[1]); + } else { + BbsEntry[Indx+1].DeviceType = BBS_HARDDISK; + } + CreateDriveString( + AtaAtapiInfo[IdeCtl].IdentifyDrive[1].Raw, + AtaAtapiInfo[IdeCtl].Status & ~(HDD_MASTER_IDE | HDD_MASTER_ATAPI), + &CoreBiosInfo->Thunk->DriveDisplayName[count++], + &BbsEntry[Indx+1].DescStringOffset, + ((UINT16)AtaAtapiInfo[IdeCtl].Bus << 8) +((UINT16)AtaAtapiInfo[IdeCtl].Device<<3)\ + + ((UINT16) AtaAtapiInfo[IdeCtl].Function ) + ); + //TRACE((-1, "i=%d, bbsentry=%x, diskinfo=%x\n", Indx, &BbsEntry[Indx+1], *DiskInfoHandles)); + *(UINTN*)(&BbsEntry[Indx+1].IBV1) = (UINTN)GetDriveHandle(&AtaAtapiInfo[IdeCtl].IdentifyDrive[1]);//(EIP71972) + } + } + } + } + +#ifdef AhciSrc_SUPPORT +#if AhciSrc_SUPPORT +{ + EFI_AHCI_INT13_INIT_PROTOCOL *Aint13; + + // + // Initialize legacy AHCI support + // + Status = pBS->LocateProtocol(&gAint13ProtocolGuid, NULL, &Aint13); + if (!EFI_ERROR(Status)) { + Aint13->InitAhciInt13Support(); + } + +} +#endif +#endif + + gIsMassStorageInstalled = TRUE; + + return; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// FUNCTION: GetSystemMemoryMap +// +// DESCRIPTION: This function returns system memory map and count of the memory +// entries in the map. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS GetSystemMemoryMap( + OUT EFI_MEMORY_DESCRIPTOR **MemMap, + OUT UINTN *MemDescSize, + OUT UINTN *MemEntriesCount +) +{ + EFI_STATUS Status; + UINTN MemMapSize, MemMapKey; + UINT32 MemDescVer; + + if (MemMap == NULL || MemDescSize == NULL || MemEntriesCount == NULL) + { + ASSERT(FALSE); + return EFI_INVALID_PARAMETER; + } + + *MemMap = NULL; + MemMapSize = 0; // GetMemoryMap will return the size needed for the map + Status = pBS->GetMemoryMap(&MemMapSize, *MemMap, + &MemMapKey, MemDescSize, &MemDescVer); + + ASSERT(Status == EFI_BUFFER_TOO_SMALL); + if (Status != EFI_BUFFER_TOO_SMALL) { + *MemEntriesCount = 0; + return EFI_INVALID_PARAMETER; + } + + // The following memory allocation may alter memory map. + // Let's add space for 5 more descriptors to be sure buffer is big enough + MemMapSize += 5 * *MemDescSize; + Status = pBS->AllocatePool(EfiBootServicesData, MemMapSize, MemMap); + ASSERT_EFI_ERROR(Status); + + Status = pBS->GetMemoryMap(&MemMapSize, *MemMap, + &MemMapKey, MemDescSize, &MemDescVer); + ASSERT_EFI_ERROR(Status); + + *MemEntriesCount = (UINT16)(MemMapSize / *MemDescSize); + + return Status; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// FUNCTION: GetExtendedMemSize +// +// DESCRIPTION: This function looks through the system memory map, finds the +// available memory regions and returns the size in bytes of the +// system memory above 1 MB. +// NOTE: If there is more than 4 GB of memory installed, then function +// will return 4GB-1MB. +// If the amount of memory is 4GB or more, some memory is remapped +// above 4GB by the chipset. In this case this function will return +// the amount of memory before the remapped area. +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID GetExtendedMemSize(UINT32* ExtMemSize) +{ + UINTN MemDescSize; + EFI_MEMORY_DESCRIPTOR *MemMap; + EFI_MEMORY_DESCRIPTOR *mm; + UINTN count = 0; + UINTN MemEntriesCount; + UINT64 cs = 0x100000; + + GetSystemMemoryMap(&MemMap, &MemDescSize, &MemEntriesCount); + + for (mm = MemMap; count < MemEntriesCount; mm=(EFI_MEMORY_DESCRIPTOR*)((UINT8*)mm+MemDescSize), count++) { + if (mm->PhysicalStart < 0x100000) continue; // skip low memory entries + + if (mm->Type == EfiReservedMemoryType || + mm->Type == EfiMemoryMappedIO || + mm->Type == EfiMemoryMappedIOPortSpace || + mm->Type == EfiRuntimeServicesCode || + mm->Type == EfiRuntimeServicesData || + mm->Type == EfiUnusableMemory || + mm->Type == EfiPalCode || + mm->Type == EfiACPIReclaimMemory || + mm->Type == EfiACPIMemoryNVS) + { + break; + } + + cs = mm->PhysicalStart + Shl64(mm->NumberOfPages, EFI_PAGE_SHIFT); + } + pBS->FreePool(MemMap); + + *ExtMemSize = (UINT32)cs - 0x100000; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// FUNCTION: InsertE820Entry +// +// DESCRIPTION: This function fills in the E820 table entry and adjusts +// the input entry pointer. If the new entry is the extension of +// the previous one, then entry is "extended". +// PARAMETERS: Pointer to E820 entry to be filled. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID +InsertE820Entry ( + E820_ENTRY **Entry, + UINT64 Address, + UINT64 Size, + E820_MEMORY_TYPE Type, + UINT16 *Count) +{ + E820_ENTRY *E820Entry = *Entry; + E820_ENTRY *PrevE820Entry = E820Entry - 1; + + if (((PrevE820Entry->Adr + PrevE820Entry->Len) == Address) && + ((PrevE820Entry->Type == Type) +#if AGGRESSIVELY_JOINED_E820_ENTRIES + || ((Type == MemRangeAvl) && (Address != 0x100000)) +#endif +)) + { + // extend the current entry without touching Adr and Type + E820Entry = PrevE820Entry; + E820Entry->Len += Size; + } else { // new entry + E820Entry->Adr = Address; + E820Entry->Len = Size; + E820Entry->Type = Type; + (*Count)++; + } + E820Entry->ExtendedAttr = E820_EXTATTR_ADDRESS_RANGE_ENABLED; + *Entry = ++E820Entry; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// FUNCTION: UpdateE820Map +// +// DESCRIPTION: This function retrieves the system memory map and converts it +// into E820 map format. +// PARAMETERS: Pointer to the 1st E820 entry in BIOS_INFO data structure +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT32 +UpdateE820Map(E820_ENTRY *e820_entry) +{ + UINT16 Count = 0; + UINTN MemDescSize; + EFI_MEMORY_DESCRIPTOR *MemMap; + EFI_MEMORY_DESCRIPTOR *mm; + UINTN MemEntriesCount; + UINTN i; + E820_ENTRY *E820Entry = e820_entry; + E820_MEMORY_TYPE MemType; + UINT32 EbdaAddress; + BDA_DATA *bda; + + GetSystemMemoryMap(&MemMap, &MemDescSize, &MemEntriesCount); + + bda = (BDA_DATA*)((UINTN) 0x400); // 40:0 + + EbdaAddress = (bda->ext_bios_data_seg)<<4; // 40:0e + // + // Start creating E820 table entries + // + InsertE820Entry(&E820Entry, 0, (640 - ((UINT8)((0xA0000 - EbdaAddress) >> 10)) )<< 10, MemRangeAvl, &Count); + InsertE820Entry(&E820Entry, (640 - ((UINT8)((0xA0000 - EbdaAddress) >> 10)) ) << 10, ((UINT8)((0xA0000 - EbdaAddress) >> 10)) << 10, MemRangeRes, &Count); + InsertE820Entry(&E820Entry, 0xE0000, 0x20000, MemRangeRes, &Count); // E0000..FFFFF + // + // Insert entries according to memory map; EFI memory types are mapped to ACPI address + // range types according to ACPI 3.0 Specification, Chapter 14.3. + // + for (mm = MemMap, i = 0; i < MemEntriesCount; i++, mm=(EFI_MEMORY_DESCRIPTOR*)((UINT8*)mm+MemDescSize)) { + if (mm->PhysicalStart < 0x100000) continue; // skip low memory entries + switch (mm->Type) { + case EfiMemoryMappedIO: + if (!(mm->Attribute & EFI_MEMORY_RUNTIME)) continue; + case EfiReservedMemoryType: + case EfiRuntimeServicesCode: + case EfiRuntimeServicesData: + case EfiUnusableMemory: + case EfiMemoryMappedIOPortSpace: + case EfiPalCode: + MemType = MemRangeRes; + break; + case EfiACPIReclaimMemory: + MemType = MemRangeAcpiReclaim; + break; + case EfiACPIMemoryNVS: + MemType = MemRangeAcpiNVS; + break; + default: MemType = MemRangeAvl; + } + InsertE820Entry(&E820Entry, + mm->PhysicalStart, + Shl64(mm->NumberOfPages, EFI_PAGE_SHIFT), + MemType, + &Count); + if (Count == MAX_E820_ENTRIES) break; + } + pBS->FreePool(MemMap); + return Count; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// FUNCTION: CmosRW +// +// DESCRIPTION: CMOS access helper +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS CmosRW( + BOOLEAN rw, + UINT32 reg, + UINT8 *data +) +{ + UINT32 reg_; + UINT8 data_; + EFI_STATUS Status; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRB; + + Status = pBS->LocateProtocol (&gEfiPciRootBridgeIoProtocolGuid, + NULL, + &PciRB + ); + ASSERT_EFI_ERROR(Status); + if (EFI_ERROR (Status)) return Status; + + reg_ = reg; + + PciRB->Io.Write (PciRB, EfiPciWidthUint8, 0x70, 1, ®_); // Set index + + if (rw) { // read + PciRB->Io.Read (PciRB, EfiPciWidthUint8, 0x71, 1, &data_); + *data = data_; + } else { // write + data_ = *data; + PciRB->Io.Write (PciRB, EfiPciWidthUint8, 0x71, 1, &data_); + } + return EFI_SUCCESS; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// FUNCTION: UpdateCmos +// +// DESCRIPTION: This function updates CMOS before booting to Legacy OS +// +// NOTE: This function enables NMI +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS UpdateCmos() +{ +// UINT8 reg; + UINT8 data; + // + // Clear bits 0..3 on the CMOS ofs 0xE + // + CmosRW(TRUE, 0xE, &data); // Read register E + data &= 0xF0; + CmosRW(FALSE, 0xE, &data); + + return EFI_SUCCESS; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// FUNCTION: NmiToBeEnabled +// +// DESCRIPTION: This function returns the current selection of NMI to be +// enabled/disabled. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +BOOLEAN NmiToBeEnabled() +{ + return TRUE; // TODO::Currently hardcoded, could be setup driven +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// FUNCTION: EnableDisableNmi +// +// DESCRIPTION: This function enables or disables NMI according to setup +// question. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +EnableDisableNmi() +{ + UINT16 data16; + UINT8 data8; + EFI_STATUS Status; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRB; + + Status = pBS->LocateProtocol (&gEfiPciRootBridgeIoProtocolGuid, + NULL, + &PciRB + ); + ASSERT_EFI_ERROR(Status); + if (EFI_ERROR (Status)) return Status; + + // + // Update IO reg 61h - NMI_SC-NMI Status and Control Register + // + PciRB->Io.Read (PciRB, EfiPciWidthUint8, 0x61, 1, &data8); + data8 &= 0xF3; + data16 = NmiToBeEnabled()? 0xD : 0xC8D; + data8 |= (data16 >> 8); + PciRB->Io.Write (PciRB, EfiPciWidthUint8, 0x61, 1, &data8); + // + // Update IO reg 70h - NMI_EN-NMI Enable(and Real Time Clock Index) + // + data8 = (UINT8)data16; + PciRB->Io.Write (PciRB, EfiPciWidthUint8, 0x70, 1, &data8); + + return EFI_SUCCESS; +} + + +//<AMI_PHDR_START> +//------------------------------------------------------------------------------------ +// +// Name: UpdatePciLastBusCallback +// +// Description: This callback function then will process the list of root bridges +// and will update the LastPciBus field of EFI_COMPATIBILITY16_TABLE +// accordingly. +// +//------------------------------------------------------------------------------------ +//<AMI_PHDR_END> + +VOID +UpdatePciLastBusCallback ( + IN EFI_EVENT Event, + IN VOID *Context +) +{ + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *RBProtocol; + ASLR_QWORD_ASD *Descriptors; + UINTN Count=0,i=0; + EFI_HANDLE *Buffer; + UINT8 MaxBus=0; + EFI_STATUS Status; + + LEGACY16_TO_EFI_DATA_TABLE_EXT *Csm16Data; + UINT8 *NextRootBridgeBus; + UINT8 CsmRbCount = 0; + BOOLEAN Csm16Is75Plus; + // + // UnLock E000 and F000 segments + // + Status = CoreBiosInfo->iRegion->UnLock ( + CoreBiosInfo->iRegion, + (UINT32)0xe0000, + (UINT32)0x20000, + NULL + ); + ASSERT_EFI_ERROR(Status); + + // + //Locate the RootBridge protocol + // + Status = pBS->LocateHandleBuffer ( + ByProtocol, + &gEfiPciRootBridgeIoProtocolGuid, + NULL, + &Count, + &Buffer + ); + ASSERT_EFI_ERROR(Status); + if (EFI_ERROR(Status)) return; + + Csm16Is75Plus = *(UINT8*)0xf0019 > 0x75; // CSM version 76 or later + + if (Csm16Is75Plus) { + Csm16Data = (LEGACY16_TO_EFI_DATA_TABLE_EXT*)(UINTN)(0xf0000 + *(UINT16*)0xfff4c); + NextRootBridgeBus = (UINT8*)((UINTN)Csm16Data->RbMinBusArrayOfs + 0xf0000); + } + + for (i = 0; i < Count; i++) { + Status = pBS->HandleProtocol ( + Buffer[i], + &gEfiPciRootBridgeIoProtocolGuid, + &RBProtocol + ); + + if (EFI_ERROR(Status)) continue; + // + // Get the Configuration + // + RBProtocol->Configuration( + RBProtocol, + &Descriptors + ); + + if ((Descriptors)->Hdr.HDR != ASLV_END_TAG_HDR) { + // + // go till we get the Resource type = Bus Number range + // + while (Descriptors->Hdr.HDR != ASLV_END_TAG_HDR) { + + if (Descriptors->Type == ASLRV_SPC_TYPE_BUS) { + // + // We got the type;update the LastPCiBus of csm16header + // + if (Csm16Is75Plus) { + if (++CsmRbCount < Csm16Data->RbArrayCount) { + *NextRootBridgeBus++ = (UINT8)Descriptors->_MIN; + } + } + if((UINT8)Descriptors->_MAX > MaxBus ) { + MaxBus =(UINT8)Descriptors->_MAX; + } + } + Descriptors++; + } + } + } + + // Update Pci Last Bus in Csm16 header + // Note: do not report FF; this is XP limitation, EIP#24852 + CoreBiosInfo->Csm16Header->LastPciBus = (MaxBus == 0xff)? 0xfe : MaxBus; + + // Update CSM16 header checksum as LastPciBus field of it has been changed + ChecksumCSM16Header(CoreBiosInfo->Csm16Header); + + // Look for _32_ structure and update offset 16 (0x10) with the MaxBus + { + UINTN Adr = 0xe0000; + + TRACE((-1,"CSM - Attempting to update RT32 binary with the MaxBus (0x%x)\n", MaxBus)); + + for (; Adr < 0x100000; Adr += 0x10) { + if (*(UINT32*)Adr == 0x5f32335f) { + // found '_32_', verify checksum + UINT8 i; + UINT8 CheckSum = 0; + TRACE((-1,"_32_ signature is found at %x,", Adr)); + for (i=0; i<0x10; i++) { + CheckSum += *((UINT8*)Adr+i); + } + if (CheckSum == 0) { + TRACE((-1,"checksum is OK\n")); + *((UINT8*)Adr+0x10) = MaxBus; + } + else { + TRACE((-1,"checksum is invalid.\n")); + } + } + } + } + + // + // Lock E000 and F000 segments + // + Status = CoreBiosInfo->iRegion->Lock ( + CoreBiosInfo->iRegion, + (UINT32)0xe0000, + (UINT32)0x20000, + NULL + ); + ASSERT_EFI_ERROR (Status); + + // Close event, this function is to be executed once. + if (Event != NULL) { + pBS->CloseEvent(Event); + } +} + +/** + * Goes through memory map looking for the requested memory block within 1MB..2GB range + * + * @param[in] MemDesc Starting memory descriptor of the memory map + * @param[in] MemEntriesCount Count of the memory map entries + * @param[in] MemDescSize Size of the memory descriptor + * @param[in] DesiredBlockSize Number of pages requested to be found + * @param[out] MemAddress Found memory block + * @param[out] NumberOfPages Found memory block size + * @retval EFI_SUCCESS Memory block is found + * @retval EFI_NOT_FOUND Memory block is not found + */ +EFI_STATUS FindMemoryBlockForHiPmm( + EFI_MEMORY_DESCRIPTOR *MemMap, + UINTN MemEntriesCount, + UINTN MemDescSize, + UINTN DesiredBlockSize, + EFI_PHYSICAL_ADDRESS *MemAddress, + UINT64 *NumberOfPages +) +{ + EFI_MEMORY_DESCRIPTOR *mm; + UINTN count = 0; + + for (mm = MemMap; count < MemEntriesCount; mm=(EFI_MEMORY_DESCRIPTOR*)((UINT8*)mm+MemDescSize), count++) { + if (mm->PhysicalStart < 0x100000) continue; // skip low memory entries + // Skip above 2GB memory entries: + // CORE0292.1 - value above 2GB will be assumed a negative number in find_free_memory algorithm + if (mm->PhysicalStart > 0x7fffffff) continue; + + if (mm->Type == EfiConventionalMemory && (mm->NumberOfPages >= DesiredBlockSize)) + { + *MemAddress = mm->PhysicalStart; + *NumberOfPages = mm->NumberOfPages; + break; + } + } + + return (count == MemEntriesCount)? EFI_NOT_FOUND : EFI_SUCCESS; +} + +/** + Allocates the memory at 1MB..2GB that can be used for high memory PMM allocations. + + This EfiBootServicesData memory block should be outside the "main" BS memory + so that it can be freed during READY_TO_BOOT. For that we go through EFI memory + map looking for unallocated region of a given size. + + @param[in] BlockSize The number of pages to be allocated. + @param[out] BlockAddr The address of the allocated block. + + @retval EFI_SUCCESS Memory block is allocated. + @retval Error Value Memory can not be allocated. + +*/ +EFI_STATUS AllocateHiMemPmmBlock( + IN UINTN BlockSize, + OUT UINTN *BlockAddr +) +{ + UINTN MemDescSize; + EFI_MEMORY_DESCRIPTOR *MemMap; + EFI_MEMORY_DESCRIPTOR *mm; + UINTN count = 0; + UINTN MemEntriesCount; + EFI_PHYSICAL_ADDRESS HiPmmMemory; + EFI_STATUS Status; + UINT64 NumberOfPages; + + GetSystemMemoryMap(&MemMap, &MemDescSize, &MemEntriesCount); + + // print memory map + for (mm = MemMap; count < MemEntriesCount; mm=(EFI_MEMORY_DESCRIPTOR*)((UINT8*)mm+MemDescSize), count++) { + TRACE((-1, "%02d: %08x, %05x, ", count, mm->PhysicalStart, mm->NumberOfPages)); + switch (mm->Type) { + case EfiReservedMemoryType: TRACE((-1, "EfiReservedMemoryType\n")); break; + case EfiLoaderCode: TRACE((-1, "EfiLoaderCode\n")); break; + case EfiLoaderData: TRACE((-1, "EfiLoaderData\n")); break; + case EfiBootServicesCode: TRACE((-1, "EfiBootServicesCode\n")); break; + case EfiBootServicesData: TRACE((-1, "EfiBootServicesData\n")); break; + case EfiRuntimeServicesCode: TRACE((-1, "EfiRuntimeServicesCode\n")); break; + case EfiRuntimeServicesData: TRACE((-1, "EfiRuntimeServicesData\n")); break; + case EfiConventionalMemory: TRACE((-1, "EfiConventionalMemory\n")); break; + case EfiUnusableMemory: TRACE((-1, "EfiUnusableMemory\n")); break; + case EfiACPIReclaimMemory: TRACE((-1, "EfiACPIReclaimMemory\n")); break; + case EfiACPIMemoryNVS: TRACE((-1, "EfiACPIMemoryNVS\n")); break; + case EfiMemoryMappedIO: TRACE((-1, "EfiMemoryMappedIO\n")); break; + case EfiMemoryMappedIOPortSpace: TRACE((-1, "EfiMemoryMappedIOPortSpace\n")); break; + case EfiPalCode: TRACE((-1, "EfiPalCode\n")); break; + default: TRACE((-1, "%x\n", mm->Type)); + } + } + + // Try to allocate Size*4 block and use the middle of it; if not found, then try to allocate Size*2 + // and use the end + Status = FindMemoryBlockForHiPmm(MemMap, MemEntriesCount, MemDescSize, BlockSize*4, &HiPmmMemory, &NumberOfPages); + if (!EFI_ERROR(Status)) { + HiPmmMemory += Shl64(NumberOfPages, 11); // Middle of the block + } else { + Status = FindMemoryBlockForHiPmm(MemMap, MemEntriesCount, MemDescSize, BlockSize*2, &HiPmmMemory, &NumberOfPages); + HiPmmMemory += Shl64(NumberOfPages, 12); // End of the block + } + ASSERT_EFI_ERROR(Status); + + + pBS->FreePool(MemMap); + + + Status = pBS->AllocatePages(AllocateMaxAddress, EfiBootServicesData, BlockSize*2, &HiPmmMemory); + *BlockAddr = (UINTN)HiPmmMemory; + + return Status; +} + +// TODO: The following definition is from DebugLib.h; currently it can not be included +// as it clashes with AmiDxeLib.h definitions +#define DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED 0x08 +BOOLEAN +ClearMemoryEnabled ( + VOID + ) +{ + // In AptioV this feature is controlled by DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of PcdDebugPropertyMask + // In Aptio4 this is project specific. By default we will return TRUE + return TRUE; +} + +/** + READY_TO_BOOT notification callback that frees high memory PMM allocations. + + Hi memory PMM is a double buffer. First half is a real PMM memory, second half is + a backup. Before freeing make a backup copy, then free the first block, then restore + memory, then free the backup block. This is done to prevent clearing memory while + executing FreePages. + Note: double buffering is only needed when DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED is + set in PcdDebugPropertyMask. +*/ +VOID FreePmmBeforeBoot ( + IN EFI_EVENT Event, + IN VOID *Context +) +{ + EFI_STATUS Status; + UINTN NumberOfPages = (CoreBiosInfo->Thunk->Csm16InitTable.HiPmmMemorySizeInBytes >> 12) + 1; + UINTN Size = NumberOfPages << 12; + UINTN Address = CoreBiosInfo->Thunk->Csm16InitTable.HiPmmMemory; + + if (ClearMemoryEnabled ()) + { + pBS->CopyMem((VOID*)(Address+Size), (VOID*)Address, Size); + Status = pBS->FreePages(Address, NumberOfPages); + ASSERT_EFI_ERROR(Status); + pBS->CopyMem((VOID*)Address, (VOID*)(Address+Size), Size); + Status = pBS->FreePages(Address+Size, NumberOfPages); + ASSERT_EFI_ERROR(Status); + } + else + { + Status = pBS->FreePages(Address, NumberOfPages*2); + ASSERT_EFI_ERROR(Status); + } + pBS->CloseEvent(Event); + + TRACE((-1, "Free HI PMM memory: %r\n", Status)); + +} + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2014, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** diff --git a/Core/EM/CSM/CsmLib.c b/Core/EM/CSM/CsmLib.c new file mode 100644 index 0000000..d0605ae --- /dev/null +++ b/Core/EM/CSM/CsmLib.c @@ -0,0 +1,1617 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (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/CsmLib.c 69 1/10/14 12:21p Olegi $ +// +// $Revision: 69 $ +// +// $Date: 1/10/14 12:21p $ +// +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Modules/CSM/Generic/Core/CsmLib.c $ +// +// 69 1/10/14 12:21p Olegi +// EIP149769: LegacyToEfi boot management +// Changed default setting, added new token to extend the functionality +// +// 68 10/31/13 9:45a Olegi +// Typo in Csm16ResetFeature case. +// +// 67 10/18/13 12:38p Olegi +// EIP139866 +// Create interface to manage LegacyToEfi CSM feature +// +// 66 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 +// +// 65 5/17/13 10:28a Olegi +// [TAG] EIP123915 +// [Category] Improvement +// [Description] BBS table update in CSM should be atomic operation +// (extra reentrance guards added) +// +// 64 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 +// +// 63 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 +// +// 62 11/06/12 10:02a Olegi +// [TAG] EIP105801 +// [Category] Bug Fix +// [Severity] Important +// [Symptom] CSM: FindEmbeddedRom improperly calls Check30ROM +// [RootCause] Check30ROM updates Size parameter with the runtime size +// of the ROM. FindEmbeddedRom passes the Init size, so after calling +// Check30ROM init size value is lost +// [Solution] Use dummy size variable to pass to Check30ROM +// [Files] CsmLib.c +// +// 61 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 +// +// 60 11/11/11 1:00p Olegi +// [TAG] EIP71556 +// [Category] Improvement +// [Description] Support for 6 IDE Controllers +// [Files] CSM.h +// CsmLib.c +// +// 59 10/12/11 3:16p Olegi +// +// 58 8/10/11 4:26p Olegi +// [TAG] EIP65882 +// [Category] Improvement +// [Description] Added checking for OPROM_MULTIPLE_MODULEID in +// FindEmbeddedRom, PCI3.0 Option ROM section. +// [Files] CsmLib.c +// +// 57 8/03/11 4:27p Olegi +// [TAG] EIP61035, EIP65224 +// [Category] Bug Fix +// [Severity] Important +// [Symptom] When AMIDebugger is using COM port, system halts in +// DisconnectSerialIO(). +// [RootCause] DisconnectSerialIO() Function present in CsmLib.c +// disconnects all SerialIO controllers including the AMI Debugger's +// DebugPort driver. +// [Solution] Before disconnecting SerialIo validate the controller by +// checking if device path protocol is installed on it. +// [Files] csmlib.c +// +// 56 5/05/11 10:18a Olegi +// [TAG] EIP59628 +// [Category] Bug Fix +// [Severity] Important +// [Symptom] BDA is not initialized correctly, reporting the maximum of +// 2 comports in the system with 4 comports. +// [RootCause] aPnP table did not have entries for COM3 and COM4 +// [Solution] added COM3/COM4 entries in the aPnP table. +// [Files] csmlib.c +// +// 55 1/31/11 4:31p Olegi +// [TAG] EIP50327 +// [Category] Improvement +// +// 54 1/18/11 11:30a Olegi +// [TAG] EIP52322 +// [Category] Improvement +// [Description] Projects with two or more PCI 3.0 embedded ROMs: if +// ROM's Device List all support one device, only one option ROM would be +// invoked. +// [Files] Changed the search method of FindEmbeddedRom() +// +// 53 12/22/10 9:07a Olegi +// Added code to clear BBS entry before setting the BBS_IGNORE priority in +// RemoveBbsEntryAt function. +// +// 52 12/03/10 12:43p Olegi +// [TAG] EIP48471 +// [Category] Bug Fix +// [Severity] Normal +// [Symptom] COM Port addresses are not filled in correctly in BDA when +// COM 0(First COM port) disabled in setup. +// [RootCause] For the COM port resource details in BDA, we should not +// depend on the UID of the Com port. +// [Solution] 1) Get the 1st COM port details and fill the details in +// CSm16bootable , BDA 40:0 and increment Serial Port count in 40:0x10. +// 2) Get the 2nd Com port details and fill the details in CSm16bootable , +// BDA 40:2 and increment Serial Port count in 40:0x10..Continue this for +// 4 com ports. +// [Files] CsmHwInfo.c +// CsmLib.c +// +// 51 10/07/10 9:07a Olegi +// EIP44674: Reverted changes in GetComResource function. +// +// 50 10/06/10 4:42p Olegi +// Finalized changes related to EIP35156. +// +// 49 10/01/10 4:43p Oleksiyy +// Issue Number: 39752 +// +// Category: Improvement +// +// Description: functuanality to hide Com1 from legacy OS if we are using +// Trace in Runtime is added. +// +// Files: Uart1.asl, Tokens.c, Runtime.c, GenericSio.c, EfiLib.c, +// CsmLib.c, AmiDxeLib.h and StatusCode eModule. +// +// 48 10/01/10 4:30p Olegi +// A call GetPlatformEmbeddedRom is replaced with the ELINK; this serves +// the purpose of OEM function portability. EIP35156. +// +// 47 9/20/10 1:04p Olegi +// EIP42722: Corrected GetComResource function. +// +// 46 9/01/10 10:37a Olegi +// EIP42523: Added VendorId checking for PCI3.0 Option ROMs. +// Background: CSM would check Device List to find the correct ROM image +// if option ROM is PCI 3.0. But there was a lack of VendorID checking in +// the search rule, this may cause FindEmbeddedRom return incorrect ROM +// image. +// +// 45 8/30/10 4:56p Olegi +// Added EFI_NOT_FOUND output to RemoveBbsEntryAt function. +// +// 44 7/16/10 12:08p Olegi +// ConnectSerialIO/DisconnectSerialIO functions moved here from CSM.C. +// +// 43 7/08/10 11:31a Olegi +// Added SignalAmiLegacyBootEvent function. EIP39089 +// +// 42 5/21/10 2:29p Olegi +// Modification in GetComPortResource: removed unneeded typecasting to +// SIO_DEV. +// +// 41 1/28/10 9:27a Olegi +// Bugfix in GetComPortResource::EIP33931. +// +// 40 1/12/10 11:46a Olegi +// Copyright message updated. +// +// 39 12/28/09 8:49a Olegi +// Modification in LockShadow, remove decoding of the unused shadow area. +// EIP#29087 +// +// 38 12/28/09 7:46a Olegi +// Added GetLptResource function. +// +// 37 8/05/09 5:56p Olegi +// FindEmbeddedRom() is modified to implement the feature of PCI3.0 OpROM +// that handles multiple devices. EIP#24327 +// +// 36 4/02/09 2:12p Olegi +// Added GetComPortResource function. +// +// 35 12/22/08 5:27p Olegi +// Added GetPlatformEmbeddedRom function. This allows different packing of +// the OpROM, can be used to pack it as FFS file. +// +// 34 10/22/08 6:22p Robert +// In UnlockShadow, moved the assignment of LockUnlockAddr and +// LockUnlockSize outside the if (size) scope to cover the case where size +// = 0 +// +// 33 10/10/08 11:56a Olegi +// +// 32 10/10/08 11:54a Olegi +// UnlockShadow: calculation of size adjustment is changed. +// +// 31 9/23/08 2:18p Olegi +// +// 30 6/30/08 3:53p Olegi +// Added AddBbsEntryAt and RemoveBbsEntryAt functions. +// +// 29 6/10/08 11:05a Olegi +// Bugfix in RemoveDecodingForShadow, the size of the region was not +// calculated correctly. +// +// 28 5/19/08 12:37p Olegi +// Removed EBDA size limitation. +// +// 27 5/08/08 6:03p Olegi +// Modified FindEmbeddedRom routine to support multiple DID for one OpROM +// for PCI onboard devices +// +// 26 4/14/08 2:46p Rameshraju +// Removed the decoding for the remaining Shadow region +// +// 25 1/31/08 11:53a Olegi +// AllocateEbda definition changed. +// +// 24 1/16/08 2:17p Olegi +// Modified AllocateEbda function. +// +// 23 12/04/07 11:07a Olegi +// +// 22 10/08/07 5:24p Olegi +// Bugfix in AllocateEbda() - after allocation all EBDA pointers +// associated with already executed OpROMs must be updated. +// +// 21 10/02/07 10:42a Olegi +// Modified IsSioDevicePluggedIn() function. +// +// 1 7/08/07 5:19p Fasihm +// +// 19 4/27/07 5:13p Olegi +// CSM.CHM file preparation. +// +// 18 4/20/07 4:41p Olegi +// AllocateEbda function is modified so that it properly updates 40:13 +// +// 17 12/13/06 11:09a Olegi +// AllocateEbda function introduction (not tested). +// +// 16 8/29/06 5:48p Olegi +// +// 15 8/28/06 11:11a Olegi +// IsConnected[] array data is corrected. +// +// 14 8/24/06 6:57p Felixp +// +// 13 8/24/06 6:49p Felixp +// x64 support (warnings/errors fixed) +// +// 12 8/16/06 2:38p Olegi +// Previous typecast changes undone. +// +// 11 8/11/06 4:54p Olegi +// +// 10 5/19/06 11:22p Felixp +// Device Path code updated to use NEXT_NODE/NODE_LENGTH/SET_NODE_LENGTH +// macros to remove direct access to the Length field +// +// 9 3/13/06 2:33p Felixp +// +// 8 11/23/05 11:22a Felixp +// dev_status renamed to DEV_STATUS. +// +// 7 11/23/05 9:40a Felixp +// +//********************************************************************** +//<AMI_FHDR_START> +// +// Name: CsmLib.c +// +// Description: Functions and variables used in different CSM modules +// +//<AMI_FHDR_END> +//********************************************************************** +#include "csm.h" +#include "AmiDxeLib.h" +#include "AcpiRes.h" +#include <Protocol\AmiSio.h> +#include <Protocol\SimplePointer.h> +#include <Protocol\BlockIo.h> +#include "token.h" +#include "pci.h" +#include <Protocol/SerialIo.h> +#include <Protocol/AmiBoardInfo.h> + +extern BIOS_INFO *CoreBiosInfo; +extern UINTN gMaxOpRomAddress; + +VOID *EmbeddedRom; +UINTN EmbeddedRomSize; + +VOID UpdateEbdaMap(UINT32); + +extern AMI_BOARD_INFO_PROTOCOL *gAmiBoardInfo; +extern BOOLEAN gBbsUpdateInProgress; + +BOOLEAN +Check30ROM( + IN VOID *RomLocation, + IN OUT UINTN *Size, + IN EFI_HANDLE PciHandle +); + +static UINT16 aPnP[16] = { + 0x0501, // 0 - UART1 + 0x0501, // 1 - UART2 + 0x0400, // 2 - LPT1 + 0x0604, // 3 - FDC + 0, 0, 0, 0, 0, 0, + 0x0303, // A - KBC + 0, // B - EC + 0x0501, //C - UART3 + 0x0501, // D - UART4 + 0x0F03, // E - PS/2 Mouse + 0 // F - Reserved +}; + +typedef EFI_STATUS (*IsConnectedFunc)(EFI_HANDLE); + +EFI_STATUS IsConnectedDummy(EFI_HANDLE); +EFI_STATUS IsConnectedPS2MS(EFI_HANDLE); +EFI_STATUS IsConnectedFloppy(EFI_HANDLE); + +static +IsConnectedFunc IsConnected[] = { + IsConnectedDummy, // 0 - UART1 + IsConnectedDummy, // 1 - UART2 + IsConnectedDummy, // 2 - LPT1 + IsConnectedFloppy, // 3 - FDC + IsConnectedDummy, // 4 - SB16 + IsConnectedDummy, // 5 - MIDI + IsConnectedDummy, // 6 - MSS AUDIO + IsConnectedDummy, // 7 - FM Synthesizer + IsConnectedDummy, // 8 - Game Port1 + IsConnectedDummy, // 9 - Game Port2 + IsConnectedDummy, // A - KBC + IsConnectedDummy, // B - EC + IsConnectedDummy, // C - reserved + IsConnectedDummy, // D - reserved + IsConnectedPS2MS, // E - PS/2 Mouse + IsConnectedDummy // F - reserved +}; + +typedef struct _ACPI_PNPID { + UINT32 Signature :16; + UINT32 PnpID :16; +} ACPI_PNPID; + +EFI_HANDLE *gSerialIoHandleBuffer=NULL; +UINTN gSerialIoHandleCount=0; + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: FindEmbeddedRom +// +// Description: This function searches for ROM within the data previously loaded +// from the main FV image and returns its pointer and size. +// +// Output: EFI_SUCCESS or EFI_NOT_FOUND +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> +typedef EFI_STATUS (*CSM_GET_EMBEDDED_PCI_ROM) ( + UINT16 VendorId, UINT16 DeviceId, VOID **ImageStart, UINTN *ImageSize); + +EFI_STATUS FindEmbeddedRom( + UINT16 ModuleId, UINT16 VendorId, UINT16 DeviceId, + VOID **ImageStart, UINTN *ImageSize +) +{ + OPROM_HEADER *Header; + EFI_STATUS Status; + PARTIAL_OPROM_HEADER *PartialHeader = NULL; + UINT8 NumAdditionalDevicesWithSameOpRom = 0; + UINT32 SizeOfPartialHeaders = 0; + UINT32 i = 0; + PCI_DATA_STRUCTURE *pcir; + UINT16 *DeviceIDList; + CSM_GET_EMBEDDED_PCI_ROM GetEmbeddedPciRom = (CSM_GET_EMBEDDED_PCI_ROM)gAmiBoardInfo->BoardOemInfo; + + Status = GetPlatformEmbeddedRom(ModuleId, VendorId, DeviceId, ImageStart, ImageSize); + if (!EFI_ERROR(Status)) return Status; + + if ((ModuleId == OPROM_MODULEID) && (gAmiBoardInfo->BoardOemInfo != NULL)) + { + GetEmbeddedPciRom = (CSM_GET_EMBEDDED_PCI_ROM)gAmiBoardInfo->BoardOemInfo; + Status = GetEmbeddedPciRom( + VendorId, DeviceId, ImageStart, ImageSize); + return Status; + } + + + for( Header = (OPROM_HEADER*)EmbeddedRom + ; (UINT8*)Header<(UINT8*)EmbeddedRom+EmbeddedRomSize + ; Header = (OPROM_HEADER*)((UINT8*)(Header+1)+ + SizeOfPartialHeaders+ + Header->Size) + ) + { + if ( Header->ModuleId==ModuleId + && Header->VendorId==VendorId + && Header->DeviceId==DeviceId + ) + { + *ImageStart = Header+1; + *ImageSize=Header->Size; + return EFI_SUCCESS; + } + else + { + // try LinkDid/LinkVid for OpROMs + //If there is more than 1 device using an option rom, + //the header of the first device has a module id with the follow format: + // 0xA0XX + //where the least significant byte is the additional number of devices using the option ROM. + // e.g. If there are 2 devices using the option rom, then the header of the + //first device has module id 0xA001. + //The first device device has a complete header, and the remaining devices have partial headers. + //A partial header is the complete header without the 'Size' field. + if ((Header->ModuleId & 0xFF00) == OPROM_MULTIPLE_MODULEID) + { + NumAdditionalDevicesWithSameOpRom = (UINT8) (Header->ModuleId & 0xFF); + SizeOfPartialHeaders = sizeof(PARTIAL_OPROM_HEADER) * + NumAdditionalDevicesWithSameOpRom; + //check the first header + //we do not check the module id + if ((Header->VendorId == VendorId) && + (Header->DeviceId==DeviceId)) { + *ImageStart = (UINT8 *)(Header+1)+SizeOfPartialHeaders; + *ImageSize=Header->Size; + return EFI_SUCCESS; + } + //Check the partial headers of the remaining devices using this option rom. + //The first partial header directly follows the regular header. + PartialHeader = (PARTIAL_OPROM_HEADER *)(Header+1); + for (i = 0; i < NumAdditionalDevicesWithSameOpRom; i++) { + if ((PartialHeader->ModuleId == ModuleId) && + (PartialHeader->VendorId == VendorId) && + (PartialHeader->DeviceId == DeviceId)) { + *ImageStart = (UINT8 *)(Header+1)+SizeOfPartialHeaders; + *ImageSize=Header->Size; + return EFI_SUCCESS; + } + PartialHeader++; + } + } else { + SizeOfPartialHeaders = 0; + } + } + *ImageStart = 0; + *ImageSize = 0; + } + + // Linked List failed. So check if it is a PCI 3.0 Option and has a valid Device List pointer + for( Header = (OPROM_HEADER*)EmbeddedRom + ; (UINT8*)Header<(UINT8*)EmbeddedRom+EmbeddedRomSize + ; Header = (OPROM_HEADER*)((UINT8*)(Header+1)+ + SizeOfPartialHeaders+ + Header->Size) + ) + { + UINTN DummyImageSize; + + if ((Header->ModuleId & 0xFF00) == OPROM_MULTIPLE_MODULEID) + { + NumAdditionalDevicesWithSameOpRom = (UINT8) (Header->ModuleId & 0xFF); + SizeOfPartialHeaders = sizeof(PARTIAL_OPROM_HEADER) * NumAdditionalDevicesWithSameOpRom; + PartialHeader = (PARTIAL_OPROM_HEADER *)(Header+1); + for (i = 0; i < NumAdditionalDevicesWithSameOpRom; i++) { + PartialHeader++; + } + } else { + SizeOfPartialHeaders = 0; + } + + *ImageStart = (UINT8 *)(Header+1)+SizeOfPartialHeaders; + *ImageSize = Header->Size; + if (Check30ROM(*ImageStart, &DummyImageSize, NULL)){ + // Check for valid Device List Pointer + pcir = (PCI_DATA_STRUCTURE *)((UINT8*)*ImageStart + *(UINT16*)((UINT8*)*ImageStart + 0x18)); + if ((pcir->VendorId == VendorId) && (pcir->Reserved0)) { //(EIP42523) + DeviceIDList = (UINT16 *)((UINT8 *)pcir + pcir->Reserved0); + for (;*DeviceIDList; DeviceIDList++ ){ + if (*DeviceIDList == DeviceId) { + return EFI_SUCCESS; + } + } + } + } + *ImageStart = 0; + *ImageSize = 0; + } + + return EFI_NOT_FOUND; +} + + +EFI_STATUS IsConnectedDummy(EFI_HANDLE handle) +{ + return EFI_UNSUPPORTED; +} + +EFI_STATUS IsConnectedPS2MS(EFI_HANDLE handle) +{ + EFI_STATUS Status; + EFI_SIMPLE_POINTER_PROTOCOL *spp; + EFI_SIMPLE_POINTER_STATE state; + + Status = pBS->HandleProtocol(handle,&gEfiSimplePointerProtocolGuid,&spp); + if (!EFI_ERROR(Status)) { + Status = spp->GetState(spp, &state); + // ask A. to fix this if - should return DEVICE_ERROR, not NO_READY + //if (Status != EFI_DEVICE_ERROR) { + if (Status != EFI_NOT_READY) { + Status = EFI_SUCCESS; + } + } + return Status; +} + + +EFI_STATUS IsConnectedFloppy(EFI_HANDLE handle) +{ + EFI_STATUS Status; + EFI_BLOCK_IO_PROTOCOL *blkiop; + + Status = pBS->HandleProtocol(handle,&gEfiBlockIoProtocolGuid,&blkiop); + + return Status; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Function: IsSioDevicePluggedIn +// +// Description: Returns connect status of certain SIO device. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +BOOLEAN IsSioDevicePluggedIn( + IN SIO_DEV_STATUS *dev_plugged_in, + OUT EFI_HANDLE *hDevice +) +{ + EFI_STATUS Status; + UINT16 dev; + UINTN i,j,cnt; + ACPI_HID_DEVICE_PATH *siodp; + ACPI_PNPID *pnpid; + EFI_HANDLE *hbuff = NULL; + EFI_DEVICE_PATH_PROTOCOL *dp; + BOOLEAN bIsConnected = FALSE; + + dev = dev_plugged_in->DEV_STATUS; + Status = pBS->LocateHandleBuffer(ByProtocol,&gEfiAmiSioProtocolGuid, NULL, &cnt, &hbuff); +// ASSERT_EFI_ERROR(Status); + + if (EFI_ERROR(Status)) return FALSE; + + // + // Find the device index. Note, that this function does not support multiple devices. + // + for (j=0; j<16; j++, dev>>=1) { + if (dev & 1) break; + } + if (j==16) { + pBS->FreePool(hbuff); + return FALSE; + } + + for(i=0; i<cnt; i++){ + Status=pBS->HandleProtocol(hbuff[i],&gEfiDevicePathProtocolGuid,&dp); + if(EFI_ERROR(Status)) continue; + + siodp=DPGetLastNode(dp); + if(siodp->Header.Type!=ACPI_DEVICE_PATH + || siodp->Header.SubType!=ACPI_DP + || NODE_LENGTH(&siodp->Header) != ACPI_DEVICE_PATH_LENGTH) continue; + + pnpid=(ACPI_PNPID*)&siodp->HID; + if (pnpid->PnpID == aPnP[j]) { + bIsConnected = (BOOLEAN) (IsConnected[j](hbuff[i]) == EFI_SUCCESS); + *hDevice = hbuff[i]; + break; + } + } + pBS->FreePool(hbuff); + return bIsConnected; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Function: GetSioDeviceStatus +// +// Description: Returns present/absent status of SIO device. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID +GetSioDeviceStatus( + IN OUT SIO_DEV_STATUS *devsts +) +{ + static EFI_GUID SioDevStatusVarGuid = SIO_DEV_STATUS_VAR_GUID; + SIO_DEV_STATUS siost; + UINTN i, j, cnt; + EFI_STATUS Status; + ACPI_HID_DEVICE_PATH *siodp; + ACPI_PNPID *pnpid; + EFI_HANDLE *hbuff = NULL; + UINT16 shifty; + EFI_DEVICE_PATH_PROTOCOL *dp; + + siost.DEV_STATUS = 0; + i = sizeof(siost); + Status = pRS->GetVariable( + SIO_DEV_STATUS_VAR_NAME, + &SioDevStatusVarGuid, + NULL, + &i, + &siost.DEV_STATUS); + if (EFI_ERROR(Status)) { + // + // NVRAM variable is not found, let us try to get status directly. + // + Status = pBS->LocateHandleBuffer(ByProtocol,&gEfiAmiSioProtocolGuid, NULL, &cnt, &hbuff); +// ASSERT_EFI_ERROR(Status); + if(EFI_ERROR(Status)) return; + + for (shifty=1,j=0; j<16; j++, shifty<<=1) { // 16 is the number of device types + if (!(devsts->DEV_STATUS | shifty)) continue; // not this device + for(i=0; i<cnt; i++){ + Status=pBS->HandleProtocol(hbuff[i],&gEfiDevicePathProtocolGuid,&dp); + if(EFI_ERROR(Status)) continue; + + siodp=DPGetLastNode(dp); + if(siodp->Header.Type!=ACPI_DEVICE_PATH + || siodp->Header.SubType!=ACPI_DP + || NODE_LENGTH(&siodp->Header) != ACPI_DEVICE_PATH_LENGTH) continue; + + pnpid=(ACPI_PNPID*)&siodp->HID; + if (pnpid->PnpID == aPnP[j]) { + siost.DEV_STATUS |= shifty; + break; + } + } + } + pBS->FreePool(hbuff); + } + + *devsts = siost; + +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Function: GetComPortResource +// +// Description: Returns COM port base address and interrupt +// +// Input: ComNo - COM port number, 0-based. +// +// Output: EFI_NOT_FOUND - COM port is not found. +// EFI_SUCCESS - COM port found, the output variables are updated: +// Address - IO base address +// Irq - IRQ number +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +GetComPortResource( + IN UINT8 ComNo, + OUT UINT16 *Address, + OUT UINT8 *Irq +) +{ + EFI_HANDLE *Handle = NULL; + UINTN Count; + UINTN i; + EFI_STATUS Status; + UINT8 ComNumber = (UINT8)-1; + AMI_SIO_PROTOCOL *AmiSio; + SPIO_DEV *SpIoDev; + + // Hide COM1 from legacy OS if we are using Trace in Runtime + if (ComNo == 0) { +#if RUNTIME_TRACE_SUPPORT + return EFI_NOT_FOUND; +#endif + } + + Status = pBS->LocateHandleBuffer( + ByProtocol, &gEfiAmiSioProtocolGuid, NULL, &Count, &Handle); + if(EFI_ERROR(Status)) return Status; + + for (i = 0; i < Count; i++) + { + Status = pBS->HandleProtocol(Handle[i],&gEfiAmiSioProtocolGuid, &AmiSio); + if (EFI_ERROR(Status)) continue; + + Status = EFI_NOT_FOUND; + + SpIoDev = (SPIO_DEV*)(UINTN)AmiSio; + + if (SpIoDev->DeviceInfo->Type != dsUART) continue; // not COM port + if (SpIoDev->VlData.DevImplemented == 0) + { + continue; + } + ComNumber++; + // + // Check if we have reached "ComNo" th instance of UART devices + // + if(ComNumber!=ComNo)continue; + + + *Address = (UINT16)SpIoDev->VlData.DevBase1; + *Irq = (UINT8)SpIoDev->VlData.DevIrq1; + + Status = EFI_SUCCESS; + break; + } + + pBS->FreePool(Handle); + + return Status; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Function: GetLptResource +// +// Description: Returns LPT base address and interrupt +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +GetLptResource( + OUT UINT16 *Address, + OUT UINT8 *Irq +) +{ + EFI_HANDLE *Handle = NULL; + UINTN Count; + UINTN i; + EFI_STATUS Status; + + AMI_SIO_PROTOCOL *AmiSio; + SPIO_DEV *SpIoDev; + + Status = pBS->LocateHandleBuffer( + ByProtocol, &gEfiAmiSioProtocolGuid, NULL, &Count, &Handle); + if(EFI_ERROR(Status)) return Status; + + for (i = 0; i < Count; i++) { + Status = pBS->HandleProtocol(Handle[i],&gEfiAmiSioProtocolGuid, &AmiSio); + if (EFI_ERROR(Status)) continue; + + SpIoDev = (SPIO_DEV*)(UINTN)AmiSio; + + if (SpIoDev->DeviceInfo->Type != dsLPT) continue; // not LPT + if (SpIoDev->VlData.DevImplemented == 0) continue; + + *Address = (UINT16)SpIoDev->VlData.DevBase1; + *Irq = (UINT8)SpIoDev->VlData.DevIrq1; + + Status = EFI_SUCCESS; + break; + } + + pBS->FreePool(Handle); + + Status = (i == Count)? EFI_NOT_FOUND : EFI_SUCCESS; + + return Status; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// FUNCTION: AllocateEbda +// +// DESCRIPTION: This function attempts to allocate EBDA. +// +// INPUT: EBDA size in kilo Bytes +// +// RETURN: 32-bit pointer of the allocated memory block inside EBDA +// The allocated address offset off the beginning of EBDA +// EFI_OUT_OF_RESOURCES if EBDA can not be allocated +// EFI_SUCCESS if memory is successfully allocated +// +// NOTE: - This routine can be called multiple times and every time EBDA +// data is copied to a different location. It is the caller +// responsibility to obtain the current EBDA segment and its size +// and adjust the offsets before accessing the data. +// - NewEbdaAddress could be used immediately after allocation. If +// the allocated block is not used immediately, - any successive +// call moves the existing data - then the caller should use +// EbdaStartOffset to calculate the correct address of the previously +// allocated data. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +AllocateEbda( + IN EFI_LEGACY_BIOS_EXT_PROTOCOL *This, + IN UINT8 RequestedSizeKB, + OUT UINT32 *NewEbdaAddress, + OUT UINT32 *EbdaStartOffset +) +{ + UINT16 CurEbdaSeg = *(UINT16*)(UINTN)0x40E; + UINTN CurEbdaLocation, NewEbdaLocation; + UINT8 CurEbdaSizeKB; + UINTN CurEbdaSize, EbdaSize; + UINTN MinEbdaAddress = 0xA0000-PMM_EBDA_LOMEM_SIZE; + + // + // Check the current EBDA allocation and see if there is still room in it + // + CurEbdaLocation = (UINTN)CurEbdaSeg<<4; + ASSERT(CurEbdaLocation > MinEbdaAddress); // either not allocated or already full + + EbdaSize = (UINTN)RequestedSizeKB << 10; + NewEbdaLocation = CurEbdaLocation - EbdaSize; + + if (NewEbdaLocation < MinEbdaAddress) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Do the allocation: + // - copy old EBDA + // - clear the allocated EBDA + // - update EBDA pointer and EBDA size + // + CurEbdaSizeKB = *(UINT8*)CurEbdaLocation; + CurEbdaSize = (UINTN)CurEbdaSizeKB<<10; + + pBS->CopyMem((VOID*)NewEbdaLocation, (VOID*)CurEbdaLocation, CurEbdaSize); + + pBS->SetMem((UINT8*)(NewEbdaLocation+CurEbdaSize), EbdaSize, 0); + + *(UINT16*)(UINTN)0x40E = (UINT16)(NewEbdaLocation>>4); + *(UINT8*)NewEbdaLocation = CurEbdaSizeKB + RequestedSizeKB; + + // + // Update 40:13 with the new size of available base memory + // + *(UINT16*)(UINTN)0x413 = (*(UINT16*)(UINTN)0x413) - RequestedSizeKB; + + // + // Update the EBDA information for the saved OpROMs + // + UpdateEbdaMap((UINT32)EbdaSize); + + *NewEbdaAddress = (UINT32)(NewEbdaLocation+CurEbdaSize); + *EbdaStartOffset = (UINT32)CurEbdaSizeKB << 10; + + return EFI_SUCCESS; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: UnlockShadow +// +// Description: Opens the shadow region(s) for writing. +// +// Input: Address - starting address +// Size - size of the region +// +// Output: LockUnlockAddr - address of the first unlocked block +// LockUnlockSize - unlocked address space +// Function returns EFI_OUT_OF_RESOURCES if there is not enough room +// in the shadow. +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +UnlockShadow( + IN UINT8 *Address, + IN UINTN Size, + OUT OPTIONAL UINT32 *LockUnlockAddr, + OUT OPTIONAL UINT32 *LockUnlockSize +) +{ + UINT32 Granularity; + UINT32 addr, size; + UINT32 addr_adjustment; + UINT32 size_adjustment = 0; + EFI_STATUS Status; + + addr = (UINT32)(UINTN)Address; + size = (UINT32)Size; + if (size) { + Status = CoreBiosInfo->iRegion->UnLock (CoreBiosInfo->iRegion, + addr, size, &Granularity); + ASSERT_EFI_ERROR(Status); + if (EFI_ERROR(Status)) return Status; + + addr_adjustment = addr % Granularity; + + if (((addr+size) % Granularity) != 0) { + size_adjustment = Granularity - ((addr+size) % Granularity); + } + + // Adjust the address to align with the granularity + addr -= addr_adjustment; + // Adjust the size to align with the granularity + size += addr_adjustment; // Align left + size += size_adjustment; + + } + + // moved these outside the if (size) for case when size = 0 + if (LockUnlockAddr != NULL) *LockUnlockAddr = addr; + if (LockUnlockSize != NULL) *LockUnlockSize = size; + + // + // Finally make CSM16 area writable for the cases where + // CSM16 area needs to be updated during DispatchOptionRom + // call, e.g. for non-BBS OpROMs. + // + Status = CoreBiosInfo->iRegion->UnLock ( + CoreBiosInfo->iRegion, + (UINT32)gMaxOpRomAddress+1, + 0xFFFFF-(UINT32)gMaxOpRomAddress, + NULL + ); + ASSERT_EFI_ERROR(Status); + + return EFI_SUCCESS; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: LockShadow +// +// Description: Locks the shadow region(s). +// +// Input: LockAddr - Starting address of the area to be locked +// LockSize - Size of the area to be locked +// +// Output: Status of the lock operation. +// +// Notes: This function will also clear the R/W attribute for the region +// from LockAddr+LockSize to gMaxOpRomAddress; this is needed for +// some OS drivers to be loaded properly (Win PCMCIA driver) +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +LockShadow( + IN UINT32 LockAddr, + IN UINT32 LockSize +) +{ + UINT32 Granularity; + EFI_STATUS Status = EFI_SUCCESS; + + if (LockSize && ((LockAddr+LockSize) < gMaxOpRomAddress)) { + Status = CoreBiosInfo->iRegion->Lock (CoreBiosInfo->iRegion, LockAddr, LockSize, &Granularity); + ASSERT_EFI_ERROR(Status); + // + // Disable Shadow W/R for the unused shadow regions + // Take care of the boundary conditions: LockAddr+LockSize is not nesessarily + // within Granularity boundaries. For example, if LockAddr is 0xC0000, LockSize + // is 0x1400 and Granularity is 0x1000, then area from 0xC0000 to 0xC2000 is + // locked. The next call must not use 0xC0000+LockSize, otherwise part of the + // OpROM becomes unreadable. + // + if (LockSize % Granularity) LockSize += Granularity; + LockSize = (LockSize/Granularity)*Granularity; + } + + if( LockAddr!=0 && LockSize!=0 ) { + BOOLEAN On=FALSE; + if ((LockAddr+LockSize) < gMaxOpRomAddress) { + Status = CoreBiosInfo->iRegion->Decode (CoreBiosInfo->iRegion, + LockAddr+LockSize, + (UINT32)gMaxOpRomAddress-LockSize-LockAddr+1, + &On); + ASSERT_EFI_ERROR(Status); + } + } + + CoreBiosInfo->iRegion->Lock ( + CoreBiosInfo->iRegion, + (UINT32)gMaxOpRomAddress+1, + 0xFFFFF-(UINT32)gMaxOpRomAddress, + NULL + ); + + return Status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: RemoveDecodingForShadow +// +// Description: This function will clear the R/W attribute for the region +// from DecodeAddr to gMaxOpRomAddress; this is needed for +// some OS drivers to be loaded properly (Win PCMCIA driver). +// +// Input: DecodeAddr - Starting address of the area to remove the decoding +// +// Output: Status of the decoding operation. +// +// Notes: +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +RemoveDecodingForShadow( + IN UINT32 DecodeAddr +) +{ + BOOLEAN On=FALSE; + EFI_STATUS Status=EFI_SUCCESS; + UINT32 Granularity; + UINT32 addr, size=1; + UINT32 addr_adjustment, size_adjustment; + + addr = DecodeAddr; + + // + //Find the nearest starting address + // + if (size) { +TRACE((TRACE_ALWAYS, "RemoveDecoding: addr %x\n", addr)); + Status = CoreBiosInfo->iRegion->UnLock (CoreBiosInfo->iRegion, + addr, size, &Granularity); + ASSERT_EFI_ERROR(Status); + if (EFI_ERROR(Status)) return Status; + + addr_adjustment = addr % Granularity; + size_adjustment = Granularity - ((addr+size) % Granularity); + // Adjust the address to align with the granularity + addr -= addr_adjustment; + // Adjust the size to align with the granularity + size += addr_adjustment; // Align left + size += size_adjustment; + } + + Status = CoreBiosInfo->iRegion->Lock (CoreBiosInfo->iRegion, addr, size, &Granularity); + + if(addr == DecodeAddr) { + DecodeAddr=addr; + } else { + DecodeAddr=addr+size; + } + + if (DecodeAddr < gMaxOpRomAddress) { + + Status = CoreBiosInfo->iRegion->Decode (CoreBiosInfo->iRegion, + DecodeAddr, + (UINT32)((gMaxOpRomAddress+1)-DecodeAddr), + &On); + ASSERT_EFI_ERROR(Status); + } + + return Status; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: GetBbsTable +// +// Description: This function returns a pointer to the BBS table and the +// number of entries. +// +// Output: BbsTable - Pointer to BBS table. +// BbsCount - Number of entries in table. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +GetBbsTable ( + IN OUT BBS_TABLE **BbsTable, + IN OUT UINT8 *BbsCount +) +{ + if ((BbsTable == NULL) || (BbsCount == NULL)) + return EFI_INVALID_PARAMETER; + + if (CoreBiosInfo == NULL) + return EFI_NOT_READY; + + if (CoreBiosInfo->BbsTable == NULL) + return EFI_NOT_READY; + + *BbsTable = CoreBiosInfo->BbsTable; + *BbsCount = CoreBiosInfo->BbsEntriesNo; + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: AddBbsEntry +// +// Description: This function adds given BBS entry to a BBS table. +// +// Input: BbsEntry - BBS table entry to be added to a table. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +AddBbsEntry ( + IN BBS_TABLE *BbsEntry +) +{ + if (gBbsUpdateInProgress) return EFI_NOT_READY; + + gBbsUpdateInProgress = TRUE; + + CoreBiosInfo->BbsTable[CoreBiosInfo->BbsEntriesNo] = *BbsEntry; + CoreBiosInfo->BbsTable[CoreBiosInfo->BbsEntriesNo].BootPriority = BBS_UNPRIORITIZED_ENTRY; + CoreBiosInfo->BbsEntriesNo++; + + gBbsUpdateInProgress = FALSE; + + return EFI_SUCCESS; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: InsertBbsEntryAt +// +// Description: This function is an extension of AddBbsEntry function; it +// allows to add a BBS_ENTRY at a particular location or add +// a new entry and return its new location. +// +// Input: This - Instance of LegacyBiosExt protocol. +// EntryNumber - Pointer to 0-based index in BBS table. The +// value of 0xFF will generate a new entry. +// +// Output: EFI_INVALID_PARAMETER - EntryNumber is NULL. +// EFI_SUCCESS - EntryNumber is updated with the index of updated +// BBS entry. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +InsertBbsEntryAt ( + IN EFI_LEGACY_BIOS_EXT_PROTOCOL *This, + IN BBS_TABLE *BbsEntry, + IN OUT UINT8 *EntryNumber +) +{ + UINT8 EntryNo; + + if (gBbsUpdateInProgress) return EFI_NOT_READY; + + if (EntryNumber == NULL) return EFI_INVALID_PARAMETER; + + gBbsUpdateInProgress = TRUE; + + if (*EntryNumber != 0xff) { + EntryNo = *EntryNumber; + } else { + // + // Find an empty entry within MAX_IDE_CONTROLLER*2+1..BbsEntriesNo-1 + // + for (EntryNo = MAX_IDE_CONTROLLER*2+1; EntryNo < CoreBiosInfo->BbsEntriesNo; EntryNo++) + { + if (CoreBiosInfo->BbsTable[EntryNo].BootPriority == BBS_IGNORE_ENTRY) + { + break; + } + } + // + // If not found, EntryNo will be equal BbsEntriesNo + // + } + CoreBiosInfo->BbsTable[EntryNo] = *BbsEntry; + CoreBiosInfo->BbsTable[EntryNo].BootPriority = BBS_UNPRIORITIZED_ENTRY; + + // + // BbsEntriesNo should not be incremented for the BBS entries + // with indexes from 0 to CoreBiosInfo->BbsEntriesNo-1 + // + if (EntryNo >= CoreBiosInfo->BbsEntriesNo) { + CoreBiosInfo->BbsEntriesNo++; + } + *EntryNumber = EntryNo; + + gBbsUpdateInProgress = FALSE; + + return EFI_SUCCESS; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: RemoveBbsEntryAt +// +// Description: This function removes BBS entry from BBS table. +// +// Input: This - Instance of LegacyBiosExt protocol. +// EntryNumber - Entry index to be removed. +// +// Output: EFI_INVALID_PARAMETER - EntryNumber exceeds the current table. +// EFI_NOT_FOUND - Entry does not exist. +// EFI_SUCCESS - Entry has been successfully removed. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +RemoveBbsEntryAt ( + IN EFI_LEGACY_BIOS_EXT_PROTOCOL *This, + IN UINT8 EntryNumber +) +{ + EFI_STATUS Status = EFI_SUCCESS; + + if (gBbsUpdateInProgress) return EFI_NOT_READY; + + gBbsUpdateInProgress = TRUE; + + // + // Can only remove a particular entry within 0..CoreBiosInfo->BbsEntriesNo-1 range; + // + if (EntryNumber >= CoreBiosInfo->BbsEntriesNo) Status = EFI_INVALID_PARAMETER; + + if (!EFI_ERROR(Status)) { + if (CoreBiosInfo->BbsTable[EntryNumber].BootPriority == BBS_IGNORE_ENTRY) { + Status = EFI_NOT_FOUND; + } + } + + if (!EFI_ERROR(Status)) { + // + // Decrement CoreBiosInfo->BbsEntriesNo only if requested index equals + // CoreBiosInfo->BbsEntriesNo-1 + // + if (EntryNumber == (CoreBiosInfo->BbsEntriesNo-1)) { + CoreBiosInfo->BbsEntriesNo--; + } + + pBS->SetMem(&CoreBiosInfo->BbsTable[EntryNumber], sizeof(BBS_TABLE), 0); + CoreBiosInfo->BbsTable[EntryNumber].BootPriority = BBS_IGNORE_ENTRY; + } + + gBbsUpdateInProgress = FALSE; + + return Status; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: SignalProtocolEvent +// +// Description: Internal function that installs/uninstall protocol +// with a specified GUID and NULL interface. +// Such protocols can be used as event signaling mechanism. +// +// Input: ProtocolGuid Pointer to the protocol GUID +// +// Output: None +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID +SignalAmiLegacyBootEvent() +{ + EFI_HANDLE Handle = NULL; + static EFI_GUID ProtocolGuid = EFI_AMI_LEGACYBOOT_PROTOCOL_GUID; + pBS->InstallProtocolInterface ( + &Handle, &ProtocolGuid, EFI_NATIVE_INTERFACE, NULL + ); + pBS->UninstallProtocolInterface ( + Handle, &ProtocolGuid, NULL + ); +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: ConnectSerialIO +// +// Description: Connect all the serial IO that was disconnected before. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID ConnectSerialIO() +{ + UINTN n; + + for (n = 0; n < gSerialIoHandleCount; n++) { + pBS->ConnectController(gSerialIoHandleBuffer[n],NULL,NULL,TRUE); + } + + return; + +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: DisconnectSerialIO +// +// Description: Disconnect the All the Serial io Handles +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID DisconnectSerialIO() +{ + UINTN n; + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + // + // Locate all Serial IO handles + // + Status = pBS->LocateHandleBuffer ( + ByProtocol, + &gEfiSerialIoProtocolGuid, + NULL, + &gSerialIoHandleCount, + &gSerialIoHandleBuffer); + + if (EFI_ERROR (Status)) { + return ; + } + + for (n = 0; n < gSerialIoHandleCount; n++) { + // + // Check if we have DevicePath Protocol installed on Controller handle. + // If not, do not disconnect the controller because it may not be handled + // by the Serial IO drvier. + // + Status = pBS->HandleProtocol ( + gSerialIoHandleBuffer[n], + &gEfiDevicePathProtocolGuid, + &DevicePath); + + if (!EFI_ERROR (Status)) { + pBS->DisconnectController(gSerialIoHandleBuffer[n],NULL,NULL); + } + } + + return; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: IsAMICSM16 +// +// Description: +// This function checks whether the CSM16 image is made by AMI. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +BOOLEAN +IsAMICSM16( + EFI_COMPATIBILITY16_TABLE* Csm16Header +) +{ + // Check for "AMIBIOS(" at F000:F500 + return (*(UINT32*)0xff500 == 0x42494d41 && + *(UINT32*)0xff504 == 0x28534f49); +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: ChecksumCSM16Header +// +// Description: +// Calculates and updates a checksum field of $EFI header. +// +// Input: +// Csm16Header Pointer to the EFI_COMPATIBILITY16_TABLE structure +// +// Output: +// Checksum byte +// +// Notes: +// Shadow region must be open for writing +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT8 +ChecksumCSM16Header ( + EFI_COMPATIBILITY16_TABLE *Csm16Header +) +{ + UINT8 i; + UINT8 chksum; + UINT8 *p; + + Csm16Header->TableChecksum = 0; + p = (UINT8*)CoreBiosInfo->Csm16Header; + for (chksum = 0, i = 0; i < Csm16Header->TableLength; i++) { + chksum += *p++; + } + Csm16Header->TableChecksum = ~(--chksum); + + return Csm16Header->TableChecksum; +} + +typedef struct { + CSM16_FEATURE Feature; + UINT8 Bit; + UINT8 InfoByteOfs; +} CSM16_FEATURE_LOOKUP; + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: Csm16Configuration +// +// Description: +// This is LegacyBiosExt interface function that manages CSM16 configuration +// settings. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +Csm16Configuration( + IN CSM16_CONFIGURATION_ACTION ConfigAction, + IN CSM16_FEATURE Param, + OUT OPTIONAL UINT32 *Data +) +{ + LEGACY16_TO_EFI_DATA_TABLE_STRUC *Csm16Data; + UINT8 MiscInfo; + UINT8 RtCmosByte; + volatile UINT8 ProbeData = *(UINT8*)0xf0000; + UINT32 Granularity; + EFI_STATUS Status; + BOOLEAN F000WasOpen; + UINT32 i; + UINT32 Count; + + static CSM16_FEATURE_LOOKUP Csm16Feature[] = { + { Csm16HeadlessI19Retry, CSM16_HEADLESS_INT19_RETRY_BIT, 0 }, + { Csm16I13MbrWriteProtect, CSM16_I13_HDD_MBR_WP_BIT, 0 }, + { Csm16LegacyFree, CSM16_NO_KBC_PRESENT_BIT, 0 }, + { Csm16ZipHddEmulation, CSM16_ZIP_HDD_EMUL_BIT, 0 }, + { Csm16NoUsbBoot, CSM16_NO_USB_BOOT_BIT, 0 }, + { Csm16I19Trap, CSM16_I19_TRAP_BIT, 0 }, + { Csm16Flexboot, CSM16_FLEXBOOT_ENABLE_BIT, 0 }, + { Csm16GA20, CSM16_FAST_GATE_A20_BIT, 0 }, + { Csm16SkipGA20Deactivation, CSM_RT_CMOS_SKIP_GA20_DEACTIVATION_BIT, 1 }, + { Csm16Nmi, CSM_RT_CMOS_PARITY_BIT, 1 }, + { Csm16CpuRealModeOnBoot, CSM_RT_CPU_RM_ONBOOT_BIT, 1 }, + { Csm16PS2, CSM_RT_CMOS_PS2_BIT, 1 }, + { Csm16LegacyToEfi, CSM_RT_CMOS_LTE_BIT, 1 }, + { Csm16LegacyToEfiPonr, CSM_RT_CMOS_LTE_PONR_BIT, 1 } + }; + + Csm16Data = (LEGACY16_TO_EFI_DATA_TABLE_STRUC*)(UINTN)(0xf0000 + *(UINT16*)0xfff4c); + MiscInfo = *(UINT8*)(UINTN)Csm16Data->MiscInfoAddress; + RtCmosByte = *(UINT8*)(UINTN)Csm16Data->RtCmosByteAddress; + + // see if F000 needs to be made writable + *(UINT8*)0xf0000 = ProbeData + 1; + F000WasOpen = *(UINT8*)0xf0000 != ProbeData; + if (F000WasOpen) { + *(UINT8*)0xf0000 = ProbeData; // restore byte + } else { + Status = CoreBiosInfo->iRegion->UnLock (CoreBiosInfo->iRegion, 0xf0000, 0x10000, &Granularity); + ASSERT_EFI_ERROR(Status); + if (EFI_ERROR(Status)) return EFI_ACCESS_DENIED; + } + + // Find parameter in the lookup table + Count = sizeof(Csm16Feature)/sizeof(CSM16_FEATURE_LOOKUP); + for (i = 0; i < Count; i++) { + if (Csm16Feature[i].Feature == Param) break; + } + + if (i == Count) { + Status = EFI_INVALID_PARAMETER; + goto Done; + } + + Status = EFI_SUCCESS; + + switch (ConfigAction) { + case Csm16FeatureGet: + if (Data == NULL) { + Status = EFI_INVALID_PARAMETER; break; + } + if (Csm16Feature[i].InfoByteOfs == 0) + *Data = (MiscInfo & Csm16Feature[i].Bit)? 1 : 0; + else + *Data = (RtCmosByte & Csm16Feature[i].Bit)? 1 : 0; + break; + + case Csm16FeatureSet: + if (Csm16Feature[i].InfoByteOfs == 0) { + MiscInfo |= Csm16Feature[i].Bit; + *(UINT8*)(UINTN)Csm16Data->MiscInfoAddress = MiscInfo; + } else { + RtCmosByte |= Csm16Feature[i].Bit; + *(UINT8*)(UINTN)Csm16Data->RtCmosByteAddress = RtCmosByte; + } + break; + + case Csm16FeatureReset: + if (Csm16Feature[i].InfoByteOfs == 0) { + MiscInfo &= ~Csm16Feature[i].Bit; + *(UINT8*)(UINTN)Csm16Data->MiscInfoAddress = MiscInfo; + } else { + RtCmosByte &= ~Csm16Feature[i].Bit; + *(UINT8*)(UINTN)Csm16Data->RtCmosByteAddress = RtCmosByte; + } + break; + + default: ASSERT(FALSE); Status = EFI_INVALID_PARAMETER; + } + +Done: + + if (!F000WasOpen) { + CoreBiosInfo->iRegion->Lock (CoreBiosInfo->iRegion, 0xf0000, 0x10000, &Granularity); + } + + return Status; +} + +//**************************************************************************** +//**************************************************************************** +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Norcross, GA 30093 ** +//** ** +//** Phone (770)-246-8600 ** +//** ** +//**************************************************************************** +//**************************************************************************** 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 ** +//** ** +//********************************************************************** +//********************************************************************** diff --git a/Core/EM/CSM/CsmSimpleIn.c b/Core/EM/CSM/CsmSimpleIn.c new file mode 100644 index 0000000..67540a7 --- /dev/null +++ b/Core/EM/CSM/CsmSimpleIn.c @@ -0,0 +1,604 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (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/CsmSimpleIn.c 9 10/18/13 10:18a Olegi $ +// +// $Revision: 9 $ +// +// $Date: 10/18/13 10:18a $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Modules/CSM/Generic/Core/CsmSimpleIn.c $ +// +// 9 10/18/13 10:18a Olegi +// [TAG] EIP140252 +// [Category] Improvement +// [Description] Connect CsmSimpleIn on ConInStarted installation +// +// 8 5/27/13 7:20a Rameshr +// [TAG] EIP122428 +// [Category] Improvement +// [Description] Clear the LED's status before setting it. +// [Files] CsmSimpleIn.c +// +// 7 2/21/13 12:53p Olegi +// [TAG] EIP115727 +// [Category] Bug Fix +// [Severity] Normal +// [Symptom] CsmSimpleIn->RegisterKeyNotify problem +// [RootCause] If someone uses RegisterKeyNotify() to register +// notification more than one time, then UnRegisterKeyNotify() will free +// wrong pointer when unregistering it. +// [Solution] Remove global KEY_WAITING_RECORD variable, add a code to +// manage multiple instances of KEY_WAITING_RECORD +// [Files] CsmSimpleIn.c +// +// 6 9/06/12 8:15a Olegi +// +// 4 5/14/10 11:13a Olegi +// Modified RegisterKeyNotify/UnregisterKeyNotify functions to pass SCT. +// +// 3 5/07/10 10:23a Olegi +// Added input validation in CsmSimpleInInputReadKeyEx. +// +// 2 1/12/10 11:46a Olegi +// Copyright message updated. +// +// 1 11/10/09 8:16a Olegi +// +// +//********************************************************************** +//<AMI_FHDR_START> +// +// Name: CsmSimpleIn.c +// +// Description: Implements the SimpleTextIn protocol for the Csm. +// +//<AMI_FHDR_END> +//********************************************************************** + +#include <efi.h> +#include <AmiDxeLib.h> +#include <Protocol\SimpleTextIn.h> +#include <Protocol\SimpleTextInEx.h> +#include <Protocol\AmiKeycode.h> +#include <Protocol\SimpleTextOut.h > +#include <Protocol\ConsoleControl.h> + + +typedef struct _CSMSIMPLEIN_DEV { + EFI_SIMPLE_TEXT_INPUT_PROTOCOL SimpleTextInput; + EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL SimpleTextInputEx; + AMI_EFIKEYCODE_PROTOCOL EfiKeycodeInput; +} CSMSIMPLEIN_DEV; + +UINT8 CurrentKeyState=0; + +typedef struct _KEY_WAITING_RECORD{ + DLINK Link; + EFI_KEY_DATA Context; + EFI_KEY_NOTIFY_FUNCTION Callback; +} KEY_WAITING_RECORD; + +DLIST mCsmKeyboardData; + +//Simple Input: + +EFI_STATUS CsmSimpleInInputReset( + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, + IN BOOLEAN ExtendedVerification +); + +EFI_STATUS CsmSimpleInInputReadKey( + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, + OUT EFI_INPUT_KEY *Key +); + +//Simple Input Ex: + +EFI_STATUS CsmSimpleInInputResetEx( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN BOOLEAN ExtendedVerification +); + +EFI_STATUS CsmSimpleInInputReadKeyEx( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + OUT EFI_KEY_DATA *KeyData +); + +EFI_STATUS CsmSimpleInInputSetState ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN EFI_KEY_TOGGLE_STATE *KeyToggleState +); + +EFI_STATUS CsmSimpleInInputRegisterKeyNotify( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN EFI_KEY_DATA *KeyData, + IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction, + OUT EFI_HANDLE *NotifyHandle +); + +EFI_STATUS CsmSimpleInInputUnRegisterKeyNotify( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN EFI_HANDLE NotificationHandle +); + +// AMI KeyCode: + +EFI_STATUS +CsmSimpleInInputReadEfiKey( + IN AMI_EFIKEYCODE_PROTOCOL *This, + OUT AMI_EFI_KEY_DATA *KeyData +); + +VOID ConnectCsmSimpleIn( + IN EFI_EVENT Event, + IN VOID *Context +); + +EFI_HANDLE gCsmSimpleInHandle=NULL; + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: InitCsmSimpleIn +// +// Description: CSM SimpleIn driver entry point, +// +// Input: Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT +// +// Output: The status of CSM board initalization +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +InitCsmSimpleIn ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + + EFI_STATUS Status; + CSMSIMPLEIN_DEV *CsmSimpleInDev = NULL; + static EFI_GUID GuidConInStarted = CONSOLE_IN_DEVICES_STARTED_PROTOCOL_GUID; + EFI_EVENT Event; + VOID *pRegistration; + + + Status = pBS->AllocatePool( + EfiBootServicesData, + sizeof(CSMSIMPLEIN_DEV), + &CsmSimpleInDev); + + if (EFI_ERROR(Status)) { + return Status; + } + + pBS->SetMem(CsmSimpleInDev, sizeof(CSMSIMPLEIN_DEV), 0); + + CsmSimpleInDev->SimpleTextInput.Reset = CsmSimpleInInputReset; + CsmSimpleInDev->SimpleTextInput.ReadKeyStroke = CsmSimpleInInputReadKey; + CsmSimpleInDev->SimpleTextInput.WaitForKey = NULL; + + CsmSimpleInDev->SimpleTextInputEx.Reset = CsmSimpleInInputResetEx; + CsmSimpleInDev->SimpleTextInputEx.ReadKeyStrokeEx = CsmSimpleInInputReadKeyEx; + CsmSimpleInDev->SimpleTextInputEx.SetState = CsmSimpleInInputSetState; + CsmSimpleInDev->SimpleTextInputEx.RegisterKeyNotify = CsmSimpleInInputRegisterKeyNotify; + CsmSimpleInDev->SimpleTextInputEx.UnregisterKeyNotify = CsmSimpleInInputUnRegisterKeyNotify; + CsmSimpleInDev->SimpleTextInputEx.WaitForKeyEx = NULL; + + CsmSimpleInDev->EfiKeycodeInput.Reset = CsmSimpleInInputResetEx; + CsmSimpleInDev->EfiKeycodeInput.ReadEfikey = CsmSimpleInInputReadEfiKey; + CsmSimpleInDev->EfiKeycodeInput.SetState = CsmSimpleInInputSetState; + CsmSimpleInDev->EfiKeycodeInput.RegisterKeyNotify = CsmSimpleInInputRegisterKeyNotify; + CsmSimpleInDev->EfiKeycodeInput.UnregisterKeyNotify = CsmSimpleInInputUnRegisterKeyNotify; + CsmSimpleInDev->EfiKeycodeInput.WaitForKeyEx = NULL; + + Status = pBS->InstallMultipleProtocolInterfaces( + &gCsmSimpleInHandle, + &gEfiSimpleTextInProtocolGuid, &CsmSimpleInDev->SimpleTextInput, + &gEfiSimpleTextInExProtocolGuid, &CsmSimpleInDev->SimpleTextInputEx, + &gAmiEfiKeycodeProtocolGuid, &CsmSimpleInDev->EfiKeycodeInput, + NULL + ); + + RegisterProtocolCallback( + &GuidConInStarted, ConnectCsmSimpleIn, + NULL, &Event,&pRegistration + ); + + + return EFI_SUCCESS; +} + +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: ConnectCsmSimpleIn +// +// Description: +// This function Connect the CsmSimpleIn handle +// +// Input: +// IN EFI_EVENT Event - signalled event +// IN VOID *Context - pointer to event context +// +// Output: +// VOID +// +// +//-------------------------------------------------------------------------- +// <AMI_PHDR_END> + +VOID ConnectCsmSimpleIn( + IN EFI_EVENT Event, + IN VOID *Context +) +{ + // Connect the CsmSimpleIn, So that Consplitter gets notified + pBS->ConnectController(gCsmSimpleInHandle, NULL, NULL, TRUE); + // Kill the Event + pBS->CloseEvent(Event); + + return; +} + +//********************************************************************** +//<AMI_PHDR_START> +// +// Procedure: CsmSimpleInInputReset +// +// Description: In our implementation, this function does nothing. +// +// Input: +// IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This +// IN BOOLEAN ExtendedVerification +// +// Output: +// EFI_STATUS +// +//<AMI_PHDR_END> +//********************************************************************** +EFI_STATUS CsmSimpleInInputReset( + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, + IN BOOLEAN ExtendedVerification +) +{ + return EFI_SUCCESS; +} + + +//********************************************************************** +//<AMI_PHDR_START> +// +// Procedure: CsmSimpleInInputResetEx +// +// Description: In our implementation, this function does nothing. +// +// Input: +// IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This +// IN BOOLEAN ExtendedVerification +// +// Output: +// EFI_STATUS +// +//<AMI_PHDR_END> +//********************************************************************** +EFI_STATUS CsmSimpleInInputResetEx( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN BOOLEAN ExtendedVerification +) +{ + return EFI_SUCCESS; +} + + +//********************************************************************** +//<AMI_PHDR_START> +// +// Procedure: CsmSimpleInInputReadKey +// +// Description: Returns a EFI_INPUT_KEY Key if possible. +// +// Input: +// IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This +// OUT EFI_INPUT_KEY *Key +// +// Output: +// EFI_STATUS +// +//<AMI_PHDR_END> +//********************************************************************** +EFI_STATUS CsmSimpleInInputReadKey( + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, + OUT EFI_INPUT_KEY *Key +) +{ + return EFI_NOT_READY; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: CsmSimpleInToggleState +// +// Description: Get the Key Toggle State from the BDA +// +// Paremeters: +// KeyToggleState - Pointer to the EFI_KEY_TOGGLE_STATE to +// set the state for the input device. +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS CsmSimpleInToggleState( + OUT EFI_KEY_TOGGLE_STATE *KeyToggleState +) +{ + UINT8 KeyState; + + KeyState = *(UINT8*)(UINTN)0x417; + if(KeyState != CurrentKeyState) { + if(KeyState & 0x10) { + *KeyToggleState |= SCROLL_LOCK_ACTIVE; + } + if(KeyState & 0x20) { + *KeyToggleState |= NUM_LOCK_ACTIVE; + } + if(KeyState & 0x40) { + *KeyToggleState |= CAPS_LOCK_ACTIVE; + } + *KeyToggleState |= TOGGLE_STATE_VALID; + CurrentKeyState=*(UINT8*)(UINTN)0x417; + return EFI_SUCCESS; + } + return EFI_NOT_READY; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: CsmSimpleInInputReadKeyEx +// +// Description: Reads the next keystroke from the input device and +// returns data in the form of EFI_KEY_DATA structure. +// This routine is a part of SimpleTextInEx protocol +// implementation. +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +CsmSimpleInInputReadKeyEx( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + OUT EFI_KEY_DATA *KeyData +) +{ + EFI_STATUS Status; + + if(KeyData == NULL) + return EFI_INVALID_PARAMETER; + + pBS->SetMem (KeyData, sizeof(EFI_KEY_DATA) , 0); + Status=CsmSimpleInToggleState(&(KeyData->KeyState.KeyToggleState)); + return Status; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: CsmSimpleInInputSetState +// +// Description: Set certain state for the input device. +// +// Paremeters: This - A pointer to the EFI_SIMPLE_TEXT_INPUT_PROTOCOL_EX +// instance. +// KeyToggleState - Pointer to the EFI_KEY_TOGGLE_STATE to +// set the state for the input device. +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +CsmSimpleInInputSetState ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN EFI_KEY_TOGGLE_STATE *KeyToggleState +) +{ + if(KeyToggleState == NULL ) { + return EFI_INVALID_PARAMETER; + } + + if (!(*KeyToggleState & TOGGLE_STATE_VALID) || + ((*KeyToggleState & (~(TOGGLE_STATE_VALID | KEY_STATE_EXPOSED | SCROLL_LOCK_ACTIVE | NUM_LOCK_ACTIVE | CAPS_LOCK_ACTIVE)))) ) { + return EFI_UNSUPPORTED; + } + + CurrentKeyState = *(UINT8*)(UINTN)0x417; + + // Clear NumLock, CapsLock, Scroll Lock status + CurrentKeyState &= 0x8F; + + if (*KeyToggleState & SCROLL_LOCK_ACTIVE) { + CurrentKeyState |= 0x10; + } + + if (*KeyToggleState & NUM_LOCK_ACTIVE) { + CurrentKeyState |= 0x20; + } + + if (*KeyToggleState & CAPS_LOCK_ACTIVE) { + CurrentKeyState |= 0x40; + } + + *(UINT8*)(UINTN)0x417 = CurrentKeyState; + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: CsmSimpleInInputRegisterKeyNotify +// +// Description: Register a notification function for a particular +// keystroke for the input device. +// +// Input: This - A pointer to the EFI_SIMPLE_TEXT_INPUT_PROTOCOL_EX +// instance. +// KeyData - Key value +// KeyNotificationFunction- Pointer to the Notification Function +// NotificationHandle - Handle to be unregisterd +// +// Output None +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +CsmSimpleInInputRegisterKeyNotify( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN EFI_KEY_DATA *KeyData, + IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction, + OUT EFI_HANDLE *NotifyHandle +) +{ + + EFI_STATUS Status; + KEY_WAITING_RECORD *CsmKeyIn; + + if(KeyData == NULL || KeyNotificationFunction == NULL || NotifyHandle == NULL ) { + return EFI_INVALID_PARAMETER; + } + + + // + // Create database record and add to database + // + Status = pBS->AllocatePool ( + EfiRuntimeServicesData, + sizeof (KEY_WAITING_RECORD), + &CsmKeyIn + ); + + if(EFI_ERROR(Status)) { + return Status; + } + + // + // Gather information about the registration request + // + + CsmKeyIn->Context = *KeyData; + CsmKeyIn->Callback = KeyNotificationFunction; + + DListAdd (&mCsmKeyboardData, &(CsmKeyIn->Link)); + + // + // Child's handle will be the address linked list link in the record + // + *NotifyHandle = (EFI_HANDLE) (&CsmKeyIn->Link); + + return EFI_SUCCESS; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: CsmSimpleInInputUnRegisterKeyNotify +// +// Description: Removes the notification which was previously +// registered by CsmSimpleInInputRegisterKeyNotify. +// +// Input: This - A pointer to the EFI_SIMPLE_TEXT_INPUT_PROTOCOL_EX +// instance. +// NotificationHandle - Handle to be unregisterd +// +// Output None +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +CsmSimpleInInputUnRegisterKeyNotify( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN EFI_HANDLE NotificationHandle +) +{ + DLINK *ListPtr; + KEY_WAITING_RECORD *CsmKeyIn; + + if(NotificationHandle == NULL ) { + return EFI_INVALID_PARAMETER; + } + + ListPtr = mCsmKeyboardData.pHead; + while ( ListPtr != NULL) + { + CsmKeyIn = OUTTER(ListPtr, Link, KEY_WAITING_RECORD); + if ( (&CsmKeyIn->Link) == NotificationHandle) + { + DListDelete(&mCsmKeyboardData, ListPtr); + pBS->FreePool(CsmKeyIn); + return EFI_SUCCESS; + } + + ListPtr = ListPtr->pNext; + } + + return EFI_INVALID_PARAMETER; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: CsmSimpleInInputReadEfiKey +// +// Description: Reads the next keystroke from the input device and +// returns data in the form of AMI_EFI_KEY_DATA structure. +// This routine is a part of AmiEfiKeycode protocol +// implementation. +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +CsmSimpleInInputReadEfiKey( + IN AMI_EFIKEYCODE_PROTOCOL *This, + OUT AMI_EFI_KEY_DATA *KeyData +) +{ + EFI_STATUS Status; + pBS->SetMem (KeyData, sizeof(AMI_EFI_KEY_DATA) , 0); + Status=CsmSimpleInToggleState(&(KeyData->KeyState.KeyToggleState)); + return Status; +} + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2010, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** diff --git a/Core/EM/CSM/OemPir.dat b/Core/EM/CSM/OemPir.dat new file mode 100644 index 0000000..26fc35e --- /dev/null +++ b/Core/EM/CSM/OemPir.dat @@ -0,0 +1,227 @@ +;********************************************************************** +;********************************************************************** +;** ** +;** (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/OemPir.dat 4 1/12/10 11:46a Olegi $ +; +; $Revision: 4 $ +; +; $Date: 1/12/10 11:46a $ +;********************************************************************** +;********************************************************************** +; Revision History +; ---------------- +; $Log: /Alaska/SOURCE/Modules/CSM/Generic/Core/OemPir.dat $ +; +; 4 1/12/10 11:46a Olegi +; Copyright message updated. +; +; 3 4/27/07 5:13p Olegi +; CSM.CHM file preparation. +; +; 2 5/16/06 1:57p Olegi +; +; 1 11/07/05 7:11p Olegi +; +; 2 11/07/05 4:37p Olegi +; +; 1 6/21/05 12:12p Olegi +; LegacyBios and LegacyBiosPlatform are combined into one FFS. +; +; 3 4/04/05 5:08p Mandal +; +;********************************************************************** +;<AMI_FHDR_START> +; +; Name: PciInfo.asm +; +; Description: This file includes the PCI related tables generated by AMISDL +; +;<AMI_FHDR_END> +;********************************************************************** + +.586P +.model small +option language:c + +; MS IRQ Routing Table Header Structure +;------------------------------------------------------------------------------ +MSIRQ_HEADER STRUC + dSignature dd ? ;'$PIR' signature + wVersion dw ? ;version (low byte = minor, high byte = major) + wSize dw ? ;length of routing table including header and slots + bRouterBus db ? ;PCI IRQ Router bus# + bRouterDevFunc db ? ;PCI IRQ Router dev#(7:3), func#(2:0) + wExclusiveIRQ dw ? ;bitmap of IRQs used exclusively for PCI + dCompatibleRouter dd ? ;VendorID, DeviceID of compatible IRQ router (low word = VendorID, high word = DeviceID) + dMiniPortData dd ? ;MiniPort Data + bReserved db 11 dup(?); reserved bytes (set to 0) + bChecksum db ? ;checksum +MSIRQ_HEADER ENDS +; PCI_IRQ_ENTRY follows the MSIRQ_HEADER, one entry per slot + +PCI_IRQ_ENTRY STRUC + pirq_bus_number db ? ;PCI bus number of device + pirq_device_number db ? ;PCI device number of device (in upper 5 bits) + pirq_inta_reg db ? ;Chipset register for this dev's Int A Pin + pirq_inta_irqs dw ? ;Bitmap of IRQs routable to Int A Pin + pirq_intb_reg db ? ;Chipset register for this dev's Int B Pin + pirq_intb_irqs dw ? ;Bitmap of IRQs routable to Int B Pin + pirq_intc_reg db ? ;Chipset register for this dev's Int C Pin + pirq_intc_irqs dw ? ;Bitmap of IRQs routable to Int C Pin + pirq_intd_reg db ? ;Chipset register for this dev's Int D Pin + pirq_intd_irqs dw ? ;Bitmap of IRQs routable to Int D Pin + pirq_phys_slot db ? ;Physical slot number of device + pirq_reserved db ? +PCI_IRQ_ENTRY ENDS + +;PCIDATA_SEG SEGMENT USE32 'DATA' +PCIDATA_SEG SEGMENT 'DATA' + +;<AMI_THDR_START> +;---------------------------------------------------------------------------- +; Name: ms_irq_routing_table +; +; Type: Structure Array +; +; Description: The information below is used for two purposes: +; 1. PCI IRQ routing during POST +; 2. Runtime dynamic IRQ routing (using Int 1A functions +; B10E / B10F) +; +; The IRQ routing table should contain one entry for each +; on-board PCI device or PCI slot. Chipset devices such as host +; bridges and ISA bridges do not need an entry. A generic BIOS +; can contain a few unused entries that BCP can use when adapting +; a generic BIOS to a customized BIOS for a motherboard containing +; on board devices such as PCI IDE, PCI SCSI, or PCI Network chips. +; BCP can also use a blank entry if a motherboard OEM decides to +; put an extra +; PCI slot on their board. +; +; The rth_pci_device_limit byte should be set to the total number +; of entries that are present including any blank entries. +; +; The rth_pci_device_count byte should be set to the number of +; non-blank entries (entries that are actually used in this BIOS). +; +; The rth_pci_dedicated_irqs word is a bitmask of IRQs that are +; dedicated to the PCI bus. (Bit 0 = IRQ 0, ..., Bit 15 = IRQ +; 15) In most cases this word will be set to all 0's. This +; word may be used in systems that implement IRQ routing with +; jumpers. +; +; The fields in each table entry are discussed below: +; +; - PCI Bus Number: Most boards contain only a single PCI bus, +; so this byte should usually be set to 0. If a board has +; multiple PCI busses, then this byte should be set to indicate +; which bus the device or slot is on. +; +; - Dev Num: This field should be set to a slot's or device's +; address on the PCI bus shifted left by three bits (the device +; number should be in bits 7:3 and bits 2:0 should be 000). +; +; - Int A Pin, Chipset Reg: This field should be set to the +; chipset register number that controls this slot's (or device's) +; Int A Pin. The value in this field is basically arbitrary, +; the value is returned by the function rth_pci_get_irq_reg. +; Slots and devices that share the same chipset interrupt signal +; should have the same value for this field. +; For example: +; if Slot 1's Int A pin and Slot 2's Int B pin are both connected +; to the same chipset interrupt signal, then the Chipset Reg +; value for Slot 1 Int A should match Slot 2 Int B. The core +; BIOS (and configuration software) need this information to +; know how IRQs are shared between slots. If a slot or device +; has nothing connected to its Int A pin, then this field should +; be set to 0. If a slot or device has its Int A pin hardwired +; directly to an IRQ, then set this field to 0Fxh (where x is +; 0-F for IRQ 0 - IRQ 15). This is useful if a motherboard has +; a PCI IDE chip that has its Int A pin hardwired to IRQ 14. +; +; - Int A Pin, Bitmap of IRQs Routeable to Pin: This field should +; be set to indicate which IRQs the chipset is capable of routing +; to the slot's (or device's) Int A pin. If the value for Chipset +; Reg (see above) was set to 0, then set all bits in this field +; to 0 also. If the value for Chipset Reg was set to 0Fxh to +; indicate a hardwired connection to a certain IRQ, then only one +; bit corresponding to that IRQ should be set in this field. +; +; - Int B,C,D Pin, Chipset Reg: These fields work exactly like +; the Chipset Reg field for Int A Pin (see above). +; +; - Int B,C,D Pin, Bitmap of IRQs Routeable to Pin: These fields +; work exactly like the corresponding field for Int A Pin (see above). +; +; - Physical Slot Number: This field should be set to the slot +; number of a PCI slot as it appears to the end user. Numbers +; like 1, 2, 3, 4 should be used. On board PCI devices such as +; PCI IDE chips should have this field set to 0 to indicate that +; the device is not a removable card that is plugged into a slot. +; Configuration software can use this value to translate a PCI +; device number (0 - 1F) to a value that is meaningful to an end +; user. +; +; - Reserved Byte: Always set to 0. +; +; Notes: +; +;---------------------------------------------------------------------------- +;<AMI_THDR_END> + +ALIGN 16 + +ms_irq_routing_table LABEL BYTE +; MS IRQ routing table header. this header is followed by all PCI slot entries. +; MSIRQ_HEADER <> + db '$PIR' ; signature + db 0, 1 ;version (low byte = minor, high byte = major) + dw size(MSIRQ_HEADER) + (OFFSET Irq_table_empty_entries - \ + OFFSET rth_pci_irq_routing_table) ;length of routing table including header and slots + db 0 ;PCI IRQ Router bus# (to be updated during runtime) + db 0 ;PCI IRQ Router dev#(7:3), func#(2:0), to be updated during runtime. + dw 0 ;bitmap of IRQs used exclusively for PCI + dd 0 ;VendorID, DeviceID of compatible IRQ router (low word = VendorID, high word = DeviceID) + dd 0 ;MiniPort Data + db 11 dup(0); reserved bytes (set to 0) + db 0 ;checksum (to be updated during runtime) + +rth_pci_irq_routing_table LABEL BYTE + include oempir.inc +pci_irq_entry <> + +Irq_table_empty_entries LABEL BYTE +; PCI IRQ routing entries defined after this label are not included. + + PUBLIC IRQ_Table_end +IRQ_Table_end LABEL BYTE + +PCIDATA_SEG ENDS +end + + +;********************************************************************** +;********************************************************************** +;** ** +;** (C)Copyright 1985-2010, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;********************************************************************** +;********************************************************************** diff --git a/Core/EM/CSM/PciInfo.asm b/Core/EM/CSM/PciInfo.asm new file mode 100644 index 0000000..0662e0a --- /dev/null +++ b/Core/EM/CSM/PciInfo.asm @@ -0,0 +1,83 @@ +;********************************************************************** +;********************************************************************** +;** ** +;** (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/PciInfo.asm 6 1/12/10 11:46a Olegi $ +; +; $Revision: 6 $ +; +; $Date: 1/12/10 11:46a $ +;********************************************************************** +;********************************************************************** +; Revision History +; ---------------- +; $Log: /Alaska/SOURCE/Modules/CSM/Generic/Core/PciInfo.asm $ +; +; 6 1/12/10 11:46a Olegi +; Copyright message updated. +; +; 5 4/27/07 5:13p Olegi +; CSM.CHM file preparation. +; +; 4 8/24/06 3:05p Felixp +; 1. x64 support +; 2. Unused code removed +; +; 3 5/16/06 1:57p Olegi +; +; 2 11/07/05 4:37p Olegi +; +; 1 6/21/05 12:12p Olegi +; LegacyBios and LegacyBiosPlatform are combined into one FFS. +; +; 3 4/04/05 5:08p Mandal +; +;********************************************************************** +;<AMI_FHDR_START> +; +; Name: PciInfo.asm +; +; Description: This file includes the PCI related tables generated by AMISDL +; +;<AMI_FHDR_END> +;********************************************************************** + +IFNDEF EFIx64 +.586P +option language:c +ENDIF + +IFNDEF EFIx64 +PCIDATA_SEG SEGMENT USE32 'DATA' +ELSE +PCIDATA_SEG SEGMENT 'DATA' +ENDIF + include busnumxlat.inc +PCIDATA_SEG ENDS +end + + +;********************************************************************** +;********************************************************************** +;** ** +;** (C)Copyright 1985-2010, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;********************************************************************** +;********************************************************************** diff --git a/Core/EM/CSM/PciInterrupts.c b/Core/EM/CSM/PciInterrupts.c new file mode 100644 index 0000000..057315d --- /dev/null +++ b/Core/EM/CSM/PciInterrupts.c @@ -0,0 +1,1136 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (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/PciInterrupts.c 55 4/09/13 9:25a Olegi $ +// +// $Revision: 55 $ +// +// $Date: 4/09/13 9:25a $ +// +//**************************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Modules/CSM/Generic/Core/PciInterrupts.c $ +// +// 55 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 +// +// 54 11/16/12 10:15a Olegi +// Typo in previous checkin. +// +// 53 11/13/12 12:15p Olegi +// [TAG] EIP99683 +// [Category] Bug Fix +// [Severity] Normal +// [Symptom] System Hang at status code AE with Optimization disabled +// [RootCause] Intx2Pirq function (PciInterrupts.c) returns various +// errors. However, only EFI_NOT_FOUND is taken into consideration by the +// caller. +// [Solution] Analyze all errors returned by Intx2Pirq function. +// [Files] PciInterrupts.c +// +// 52 4/09/12 5:32p Olegi +// [TAG] EIP86722 +// [Category] Bug Fix +// [Severity] Important +// [Symptom] Function "GetXlatPciBusNumber" does not work +// [RootCause] C-style output does not match with the ASM style output +// [Solution] Corrected the XLAT table parse function depending on the +// version of PCI driver. +// [Files] PciInterrupts.c +// +// 51 12/13/11 11:31a Olegi +// [TAG] EIP77755 +// [Category] Improvement +// [Description] Modified CreateAddonBusEntry function to return if +// requested bus # is already present in AddonPciBusTable. +// [Files] PciInterrupts.c +// +// 50 12/14/10 12:02p Olegi +// [TAG] EIP44553 +// [Category] Bug Fix +// [Severity] Important +// [Symptom] PCI recovery card is disabled during its Option ROM +// execution +// [RootCause] Some mass storage controllers are not enabled before +// option ROM execution. +// [Solution] Modified CsmBlkIo driver to enable device before calling +// InstallPciRom function. Device enable code is removed from +// PciIterrupts.c +// [Files] PciInterrupts.c, CsmBlkIo.c +// +// 49 11/09/10 9:39a Olegi +// PCI_TRACE macro replaced with TRACE. +// +// 48 7/08/10 11:35a Olegi +// Modified IRQ distribution logic to achieve maximum interrupt +// dispersion. EIP39733 +// +// 47 6/18/10 10:30a Olegi +// EIP39733: Change in RoutePciIrq function. +// +// 46 3/02/10 5:17p Olegi +// Making use of AmiExtPciBusProtocol when PCI Bus driver version is 240 +// or newer. +// +// 45 1/28/10 9:07a Olegi +// ProgramPciIrq: added code that sends a notification about PCI IRQ +// programming. +// +// 44 1/12/10 11:46a Olegi +// Copyright message updated. +// +// 43 12/08/09 5:06p Olegi +// +// 42 9/23/09 9:25a Olegi +// GetP2PSecondaryBusNum:: Fixed the problem of reading PCI device on bus +// 80h or more. +// +// 41 8/07/09 2:43p Rameshr +// SD boot support Added. +// +// 40 8/05/09 5:25p Olegi +// Variable types redefinition that fixes the 32-bit mode compilation +// warning. +// +// 39 6/16/09 1:52p Olegi +// Correction in UpdatePrt() function for multiple root bridge +// configuration. +// +// 38 3/10/09 1:49p Olegi +// Added trace message in RoutePciIrq. +// +// 37 3/09/09 11:47a Olegi +// Bugfix in ProgramPciIrq OEM interrupt masking: EIP#18668 +// +// 36 12/11/08 10:16a Olegi +// Bugfix in ProgramPciIrq; EIP#16563 +// +// 35 11/13/08 1:01p Olegi +// Added GetPlatformInfo call before programming PCI IRQ. +// +// 34 11/03/08 2:19p Olegi +// Bugfix in UpdatePrt(), EIP #15167 +// +// 33 10/01/08 11:50a Olegi +// Fix for a device behind two or more P2P bridges (EIP#16563). +// +// 32 8/08/08 9:26a Olegi +// Modified UpdatePrt function, invalid entries in BusNumXlat table as +// well as in $PIR table are suppressed. +// +// 31 6/20/08 10:20a Olegi +// Fix for the PCI IRQ routing table parser when PCI bus is FF. +// +// 30 11/02/07 10:39a Olegi +// Added BspUpdatePrt function. +// +// 29 9/19/07 10:14a Olegi +// Bugfix in CreateAddonBusEntry. +// +// 28 6/18/07 5:47p Olegi +// +// 27 6/04/07 10:47a Olegi +// +// 26 4/27/07 5:47p Olegi +// +// 25 4/27/07 5:13p Olegi +// CSM.CHM file preparation. +// +// 24 4/26/07 4:24p Olegi +// +// 23 4/26/07 2:44p Olegi +// Correction in RoutePciIrq routine, that will not do the routing if the +// given register is already programmed. +// +// 22 4/13/07 9:46a Olegi +// +//********************************************************************** + +//**************************************************************************** +//<AMI_FHDR_START> +// +// Name: PciInterrupts.c +// +// Description: PCI Interrupt routing functions +// +//<AMI_FHDR_END> +//**************************************************************************** + + +#include <AmiDxeLib.h> +#include <Pci.h> +#define PCI_BASE_CLASS_INTELLIGENT 0x0e +#define PCI_SUB_CLASS_INTELLIGENT 0x00 + +#include <AcpiRes.h> +#include <Token.h> +#include <Protocol/PciRootBridgeIo.h> +#include <Protocol/DevicePath.h> +#include <Protocol/LegacyBios.h> +#include <Protocol/LegacyBiosPlatform.h> +#include <Protocol/PciIo.h> +#include <Protocol/Legacy8259.h> +#include "csm.h" +#include "AmiCspLib.h" +#include <Protocol/AmiBoardInfo.h> + +EFI_GUID gEfiPciRootBridgeIoProtocol = EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GUID; + +VOID *gPciIoNotifyReg; +extern EFI_BOOT_SERVICES *pBS; +BIOS_INFO *CoreBiosInfo; +EFI_LEGACY_PIRQ_TABLE_HEADER *MsPrt; // To be obtained after +EFI_LEGACY_IRQ_ROUTING_ENTRY *Prt; // reading GUIDed section. +UINTN gUsedPciEntries; + + + +extern BOOLEAN IsValidPrt; +extern PLATFORM_BIOS_INFO *BspBiosInfo; + +EFI_GUID gBusNumXlatProtocol = AMICSM_PCIBUSNUM_XLAT_PROTOCOL_GUID; +AMICSM_PCIBUSNUM_XLAT_PROTOCOL BusNumXlatProtocol; + +extern AMI_BOARD_INFO_PROTOCOL *gAmiBoardInfo; + +UINTN CopyLegacyTable(VOID*, UINT16, UINT16, UINT16); + +UINT8 *BusNumXlat; +UINT8 *BusNumXlatEnd; + +EFI_HANDLE gHandle = NULL; +UINTN PciRBHandlesNo=0; +EFI_HANDLE *PciRBHandles=NULL; +UINT16 XlatTblEntriesRemaining=0; +// +// The following two external variables specifiy the PCI device/function number of the root +// bridge(s). Number of entries in this table defined by RbCount. +// This data is a missing link between RootBridgeIo and PciIo, which allows to update +// BusNumXlat table with actual bus numbers. +// Each entry in the RbMap is a pair of RootBridge UID (UINT32), provided in RootBridge +// device path, and PCI Dev/Func number (UINT8) that can be used to access Root Bridge on +// PCI bus. +// +extern ROOT_BRIDGE_MAPPING_ENTRY RbMap[]; +extern UINTN RbCount; + +UINT8 SBGen_GetPIRQIndex (UINT8); + +UINT8 irq_priority_map[] = {11, 10, 9, 15, 5, 3, 7, 4, 14}; +UINT8 irq_allocated_count[sizeof(irq_priority_map)] = {0}; +UINT16 IsaIrqMask; + +EFI_ADDON_PCIBUS_TABLE AddonPciBusTable[MAX_ADDITIONAL_P2P_BRIDGES]; + +UINT8 gAddonPciBusIndx; + +EFI_LEGACY_8259_PROTOCOL *i8259; + +PROGRAMMED_PCIIRQ_CTX gIrqPgmCtx = {0}; +EFI_GUID gPciIrqProgramGuid = EFI_PCIIRQ_PGM_PROTOCOL_GUID; + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: RoutePciIrq +// +// Description: This routine selects the IRQ from the list of allowed PCI +// interrupts, picks the best interrupt number according to +// interrupt priority table and programs the PCI interrupt +// router. +// Input: +// Int - zero based index in the list of router registers for INTA, INTB,... +// Irq - new interrupt number +// IrqMask - IRQ bit mask, bits are set for the interrupts that are not allowed +// +// Output: EFI_SUCCESS if interrupt is routed +// EFI_ABORTED if routing register is already programmed +// +// Notes: This routine can not be called externally. It is to be +// called after TranslatePirq returns the Rirq register is +// not programmed. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +RoutePciIrq( + IN UINT8 Int, + OUT UINT8 *Irq, + IN UINT16 IrqMask +) +{ + UINT16 Mask = ~IrqMask; // PIC-style mask (1 is for interrupts that are not allowed) + EFI_LEGACY_INTERRUPT_PROTOCOL *iInterrupt; + UINT8 NewIrq; + EFI_STATUS Status; + UINT8 i; + UINT8 IrqIndex; + UINT8 IrqFound = FALSE; + + Status = pBS->LocateProtocol (&gEfiLegacyInterruptProtocolGuid, NULL, &iInterrupt); + if (EFI_ERROR(Status)) return Status; + + // + // See if routing register is already programmed, return EFI_ABORTED if so. + // + Status = iInterrupt->ReadPirq(iInterrupt, Int, &NewIrq); + ASSERT_EFI_ERROR(Status); + if (EFI_ERROR(Status)) return Status; + + for (i=0; irq_priority_map[i]; i++) { + if (NewIrq==irq_priority_map[i]) { +TRACE(((UINTN)-1, "The requested PIRQ[%d] is already programmed to IRQ%x. PCI Routing ABORTED.\n", Int, NewIrq)); + return EFI_ABORTED; + } + } + +TRACE(((UINTN)-1,"..........IRQ MASK %x....", Mask)); + // + // Remove ISA interrupts from Mask + // + Mask |= IsaIrqMask; + +TRACE(((UINTN)-1,"%x....\n", Mask)); + // + // Find the next available interrupt; irq_priority_map is zero-terminated array + // used as priority list. Lower index in irq_priority_map indicates higher priority + // interrupt. + // Initially irq_priority_index is the index of zero in irq_priority_map; it will + // be advanced to the beginning in the following for loop. + // + for (IrqIndex = 0; IrqIndex < sizeof(irq_priority_map); IrqIndex++) { +TRACE(((UINTN)-1,"IrqIndex %d....Allocated %d....\n", IrqIndex, irq_allocated_count[IrqIndex])); + if (!((1 << irq_priority_map[IrqIndex]) & Mask)) { + IrqFound = TRUE; // Assume that IRQ was found + for (i = 0; i < sizeof(irq_allocated_count); i++) { + // Check if the least allocated IRQ + if (!((1 << irq_priority_map[i]) & Mask)) { + if (irq_allocated_count[IrqIndex] > irq_allocated_count[i]) { + IrqFound = FALSE; + break; + } + } + } + } + if (IrqFound) break; + } + if (!IrqFound) return EFI_NOT_FOUND; + + irq_allocated_count[IrqIndex] += 1; + NewIrq = irq_priority_map[IrqIndex]; + + // Adjust irq_priority_index + + Status = iInterrupt->WritePirq(iInterrupt, Int, NewIrq); + if (EFI_ERROR(Status)) return Status; + + *Irq = NewIrq; + return EFI_SUCCESS; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: Intx2Pirq +// +// Description: This function is similar to TranslatePirq with the additional +// output of IrqMask. See TranslatePirq description. +// Input: +// This Indicates the EFI_LEGACY_BIOS_PLATFORM_PROTOCOL instance. +// PCI bus, device and function number for this device. +// Pirq The PIRQ. PIRQ A = 0, PIRQ B = 1, and so on. +// PirqIrq IRQ assigned to the indicated PIRQ. +// IrqMask Mask of IRQs that could be assigned to this register +// +// Output: +// EFI_SUCCESS The PIRQ was translated. +// EFI_NOT_FOUND The device was not in the table. +// EFI_NOT_READY The interrupt translation table is not ready. +// EFI_INVALID_PARAMETER Wrong input +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +Intx2Pirq ( + IN EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *This, + IN UINTN PciBus, + IN UINTN PciDevice, + IN UINTN PciFunction, + IN OUT UINT8 *Pirq, + OUT UINT8 *PciIrq, + OUT UINT16 *IrqMask OPTIONAL + ) +{ + UINT8 Irq; + UINT8 counter; + EFI_LEGACY_IRQ_ROUTING_ENTRY *p; + EFI_LEGACY_INTERRUPT_PROTOCOL *iInterrupt; + EFI_STATUS Status; + + UINT8 PciDev; + UINT8 rr = 0; // Router register + UINT8 rrIndx; // Router register index + UINT8 pirq = *Pirq; + UINT8 i; + + if (!IsValidPrt) return EFI_NOT_READY; + + if (pirq > 3) { + TRACE (((UINTN)TRACE_ALWAYS, "Invalid PIRQ value (%d, %d, %d) %d\n", PciBus, PciDevice, PciFunction, pirq)); + return EFI_INVALID_PARAMETER; + } + + PciDev = (UINT8)(PciDevice << 3); + + for (p = Prt, counter = 0; counter < gUsedPciEntries; counter++, p++) { + if ((PciBus == p->Bus) && (PciDev == p->Device)) { + rr = p->PirqEntry[pirq].Pirq; + if (IrqMask != NULL) *IrqMask = p->PirqEntry[pirq].IrqMask; + break; // rrIndx is found + } + } + + if (counter == gUsedPciEntries) { + if (gAddonPciBusIndx == 0) return EFI_NOT_FOUND; // No additional P2P bridges + + // + // Not found in &PIR - see if device is generated by the P2P which is not + // listed in BusNumXlat, e.g. it is behind P2P bridge located on off-board card. + // + for (counter = 0; counter < gAddonPciBusIndx; counter++) { + if (AddonPciBusTable[counter].Bus == PciBus) { + i = (UINT8)((PciDevice + pirq) % 4); // INTA/B/C/D for Dev0, INTB/C/D/A for dev1, etc. + rr = AddonPciBusTable[counter].PirqEntry[i].Pirq; + if (IrqMask != NULL) *IrqMask = AddonPciBusTable[counter].PirqEntry[i].IrqMask; + break; + } + } + if (counter == gAddonPciBusIndx) return EFI_NOT_FOUND; // Device not found + } + + // + // Find the index of given register within RRegs + // + rrIndx = SBGen_GetPIRQIndex (rr); + if (rrIndx == 0xFF) return EFI_UNSUPPORTED; + + // + // Get the programmed interrupt number off the LegacyInterrupt for rrIndx + // + Status = pBS->LocateProtocol (&gEfiLegacyInterruptProtocolGuid, NULL, &iInterrupt); + if (EFI_ERROR(Status)) return Status; + + Status = iInterrupt->ReadPirq(iInterrupt, rrIndx, &Irq); + if (EFI_ERROR(Status)) return Status; + + *Pirq = rrIndx; + *PciIrq = Irq; + + return EFI_SUCCESS; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: CreateAddonBusEntry +// +// Description: This function inserts a new entry into AddonPciBusTable. +// +// Input: +// Bus - new bus number +// PirqData - pointer to the new PIRQ data array +// +// Output: +// EFI_SUCCESS Entry has been created successfully. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +CreateAddonBusEntry( + UINT8 Bus, + VOID *PirqData +) +{ + UINT8 i; + + // Check if the requested entry already exists in AddonPciBusTable. This will be + // the case when PCI bus driver has been reconnected. + // + for (i = 0; i < gAddonPciBusIndx; i++) { + if (AddonPciBusTable[i].Bus == Bus) { + return EFI_SUCCESS; + } + } + + // + // Insert new entry into AddonPciBusTable + // + AddonPciBusTable[gAddonPciBusIndx].Bus = Bus; + pBS->CopyMem( + AddonPciBusTable[gAddonPciBusIndx].PirqEntry, + PirqData, + sizeof(EFI_LEGACY_PIRQ_ENTRY)*4 + ); + TRACE((-1, "AddonPciBusTable entry [%d] created: Bus %x, PIRQs: %x %x %x %x\n", + gAddonPciBusIndx, + AddonPciBusTable[gAddonPciBusIndx].Bus, + AddonPciBusTable[gAddonPciBusIndx].PirqEntry[0].Pirq, + AddonPciBusTable[gAddonPciBusIndx].PirqEntry[1].Pirq, + AddonPciBusTable[gAddonPciBusIndx].PirqEntry[2].Pirq, + AddonPciBusTable[gAddonPciBusIndx].PirqEntry[3].Pirq)); + + gAddonPciBusIndx++; + ASSERT(gAddonPciBusIndx<MAX_ADDITIONAL_P2P_BRIDGES); + return EFI_SUCCESS; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: CheckP2PBridge +// +// Description: This function verifies whether device is P2P bridge which is +// not listed in BusNumXlat table, e.g. bridge is on PCI Add-on card. +// For this bridge we create a new entry in AddonPciBusTable which +// will be used for PCI IRQ routing for the devices that are located +// behind this bridge. +// Input: +// PciIo pointer to EFI_PCI_IO_PROTOCOL protocol associated with this device +// Bus, Dev PCI bus location for this device +// +// Output: +// EFI_SUCCESS Device is P2P bridge; if bus generated by this bridge is not +// described in $PIR table, then another entry in AddonPciBusTable +// is created. +// EFI_NOT_FOUND Device is not P2P bridge. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +CheckP2PBridge( + EFI_PCI_IO_PROTOCOL *PciIo, + UINT8 Bus, + UINT8 Dev +) +{ + EFI_STATUS Status; + UINT16 PciClassSubclass; + UINT8 SecBusNum; + EFI_LEGACY_IRQ_ROUTING_ENTRY *re; + UINT8 counter; + + // + // Check if this is a P2P bridge + // + Status = PciIo->Pci.Read(PciIo, EfiPciIoWidthUint16, 0xA, 1, &PciClassSubclass); + ASSERT_EFI_ERROR(Status); + // + // Base Class=6 Ofs B (Bridge), SubClass=4 Ofs A (P2P Bridge) + // + if (PciClassSubclass != 0x0604) return EFI_NOT_FOUND; + // + // It is P2P bridge - read its secondary bus number and try to find a match in + // BusNumXlat table + // + TRACE((-1,"P2P bridge.\n")); + Status = PciIo->Pci.Read( + PciIo, + EfiPciIoWidthUint8, + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET, + 1, + &SecBusNum); + ASSERT_EFI_ERROR(Status); + + // + // Locate the P2P bridge as PCI device in $PIR and get EFI_LEGACY_IRQ_ROUTING_ENTRY; + // if found - insert new entry into AddonPciBusTable and return EFI_SUCCESS, + // otherwise return EFI_NOT_FOUND. + // + for (re = Prt, counter = 0; counter < gUsedPciEntries; counter++, re++) { + if ((re->Bus == Bus) && (re->Device == (Dev << 3))) { + return CreateAddonBusEntry(SecBusNum, re->PirqEntry); + } + } + // + // Not found in $PIR table - try AddonPciBusTable + // + + if (gAddonPciBusIndx == 0) return EFI_NOT_FOUND; // No additional P2P bridges + + for (counter = 0; counter < gAddonPciBusIndx; counter++) { + if (AddonPciBusTable[counter].Bus == Bus) { + // + // Connected to an add-on bridge, do the INT pin swizzling + // + EFI_LEGACY_PIRQ_ENTRY PirqData[4]; + UINT8 RoundRobinXlatTable[4][4] = { + 0, 1, 2, 3, + 1, 2, 3, 0, + 2, 3, 0, 1, + 3, 0, 1, 2 + }; + UINT8 i = (UINT8)(Dev % 4); + UINT8 counter1; + + for (counter1 = 0; counter1 < 4; counter1++) { + pBS->CopyMem( + &PirqData[counter1], + &AddonPciBusTable[counter].PirqEntry[RoundRobinXlatTable[i][counter1]], + sizeof(EFI_LEGACY_PIRQ_ENTRY) + ); + } + + return CreateAddonBusEntry(SecBusNum, PirqData); + } + } + return EFI_NOT_FOUND; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: GetIsaIrqs +// +// Description: Returns the ISA interrupt mask +// +// Input: None +// +// Output: ISA interrupt mask +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +GetIsaIrqs( + OUT UINT16 *IrqMask +) +{ + EFI_STATUS Status; + + Status=AmiIsaIrqMask(IrqMask, TRUE); + if(EFI_ERROR(Status)){ + *IrqMask = ISA_IRQ_MASK; // allow IRQ 0..8, 12..15 for ISA + Status=AmiIsaIrqMask(IrqMask, FALSE); + TRACE(((UINTN)-1, "PciInterrupts: Set ISA_IRQ_MASK, Status=%r\n", Status)); + } + return Status; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: ProgramPciIrq +// +// Description: This function assigns IRQ to a PCI device. It programs PCI +// IRQ register if: +// - device requires IRQ to be assigned (reg 3D is 1..3) +// - PCI bus information is updated in $PIR table (step 1 +// has been completed) +// - device is present in IRQ routing table +// When all these conditions are met, then IRQ is assigned to this +// device according to the PCI IRQ priorities; then IRQ is programmed +// in PCI register 3C +// +// Input: PCI Bus, Device and Function number of the PCI device +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID ProgramPciIrq( + EFI_PCI_IO_PROTOCOL *PciIo, + VOID *Context) +{ + UINT16 IrqMask; + UINT16 Mask, EdgeLevel; + UINT8 Int, Irq; + EFI_STATUS Status; + EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *iBiosPlatform; + UINTN Seg, Bus, Dev, Func; + UINTN OemIrqMask; + + Status = PciIo->GetLocation(PciIo, &Seg, &Bus, &Dev, &Func); + ASSERT_EFI_ERROR(Status); + if (EFI_ERROR(Status)) return; + + TRACE((-1,"PCI device: %x %x %x ... ", Bus, Dev, Func)); + + // + // Find out whether device is P2P bridge that is not listed in BusXlatNum table; + // if found - add entry into P2P bridge table and exit. Function returns: + // EFI_NOT_FOUND - not P2P bridge; EFI_SUCCESS - P2P bridge found and bridge table + // is updated. + // + Status = CheckP2PBridge(PciIo, (UINT8)Bus, (UINT8)Dev); + + // + // Check if device requires IRQ + // + Status = PciIo->Pci.Read(PciIo, EfiPciIoWidthUint8, 0x3D, 1, &Int); + ASSERT_EFI_ERROR(Status); + + if (EFI_ERROR(Status)) return; + + if (!Int) { + TRACE((-1,"does not require IRQ.\n")); + return; // Device does not support IRQ + } + + Int--; // Zero based INTx + iBiosPlatform = (EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *)Context; + Status = Intx2Pirq( + iBiosPlatform, + Bus, Dev, Func, + &Int, + &Irq, + &IrqMask); + + TRACE((-1,"Intx2Pirq returns %r\n", Status)); + + if (Status == EFI_NOT_FOUND) { + // Device is not in the table + TRACE((-1,"Device is not found in the PCI IRQ routing table.\n")); + } + + if (EFI_ERROR(Status)) { + return; + } + + // + // Intx2Pirq returns: + // Int - routing register index; + // Irq - interrupt currently programmed in that index. + // IrqMask - bit mask of the interrupts that can possibly be + // assigned to this device. + // + + // Call OEM function that can modify the list of interrupts that can be + // assigned. Note that the list can only be shrunk, not extended. + + Status = CoreBiosInfo->iBiosPlatform->GetPlatformInfo( + CoreBiosInfo->iBiosPlatform, + EfiGetPlatformPciIrqMask, + &PciIo, + NULL, NULL, + &OemIrqMask, + IrqMask, + 0); + if (!EFI_ERROR(Status)) { + IrqMask &= (UINT16)OemIrqMask; + } + + Status = RoutePciIrq(Int, &Irq, IrqMask); + + TRACE((-1,"RoutePciIrq status: %r, Intx2Pirq: Int %x IRQ %x mask %x\n", Status, Int, Irq, IrqMask)); + + Status = PciIo->Pci.Write(PciIo, EfiPciIoWidthUint8, 0x3C, 1, &Irq); + ASSERT_EFI_ERROR(Status); + + if (EFI_ERROR(Status)) return; + + // + // Set corresponding mask and edge/level mode in 8259 for real mode operation + // + i8259->GetMask(i8259, &Mask, &EdgeLevel, NULL, NULL); + Mask &= (UINT16)~(1 << Irq); + EdgeLevel |= (UINT16)(1 << Irq); + i8259->SetMask(i8259, &Mask, &EdgeLevel, NULL, NULL); + + // Send out a word about programmed PCI interrupt + gIrqPgmCtx.PciIo = (VOID*)PciIo; + gIrqPgmCtx.Irq = Irq; + Status = pBS->ReinstallProtocolInterface( + gHandle, + &gPciIrqProgramGuid, + &gIrqPgmCtx, + &gIrqPgmCtx + ); + ASSERT_EFI_ERROR(Status); +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: GetXlatPciBusNumber +// +// Description: This function returns the PCI bus number translated according +// to Xlat table defined in BusNumXlat.inc. This translation file +// is generated by AMISDL using "BUSNUM_XLAT" output type. +// +// Input: Build time PCI bus number - 1st coulmn of the xlat table +// +// Output: EFI_SUCCESS, real PCI bus number - 2nd column of the xlat table +// EFI_NOT_FOUND, the requested bus is not found in the xlat table +// EFI_INVALID_PARAMETER, if NULL pointer is supplied on input. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +GetXlatPciBusNumber ( + IN OUT UINT8 *busNumber +) +{ + UINT8 *p; + + if (busNumber == NULL) return EFI_UNSUPPORTED; + + for(p = BusNumXlat; p < BusNumXlatEnd; p++) { + if (*p == *busNumber) { + if (*(p+1)==0xFE) return EFI_NOT_FOUND; + *busNumber = *(p+1); + return EFI_SUCCESS; + } + while (*p != 0xFF) {p++;} // p points to -1 at the end of the line + // C style BusXlatNum output adds five more Bytes after FF, so skip them + p+=5; + } + return EFI_NOT_FOUND; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: UpdatePrt +// +// Description: This function updates $PIR table with the actual PCI bus numbers. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID UpdatePrt() +{ + EFI_STATUS Status; + UINTN count1;//, count2, count3; + UINT8 *p; + UINT8 chksum = 0; + UINTN PrtAddress; +//----------------------------------------- + + //Check if PciBus Driver updated IRQ Routing Table yet + ASSERT(gAmiBoardInfo->DataValid==TRUE); + + //Create an instance of IRQ ROUTING tasble with $PIR Headr + p=MallocZ(sizeof(EFI_LEGACY_PIRQ_TABLE_HEADER) + gAmiBoardInfo->PicRoutLength); + MemCpy(p,MsPrt,sizeof(EFI_LEGACY_PIRQ_TABLE_HEADER)); + + //Since $PRT Table header was created separately + //free memory used for Header instance since we have copy it already. + pBS->FreePool(MsPrt); + MsPrt=(EFI_LEGACY_PIRQ_TABLE_HEADER*)p; + p+=sizeof(EFI_LEGACY_PIRQ_TABLE_HEADER); + MemCpy(p, gAmiBoardInfo->PicRoutTable, gAmiBoardInfo->PicRoutLength); + + //Update gUsedPciEntries since PciBus Driver removed unused entries from the table + gUsedPciEntries=gAmiBoardInfo->PicRoutLength/sizeof(PCI_IRQ_PIC_ROUTE); + + //Update Prt pointer to point at new instance of table and header together. + Prt=(EFI_LEGACY_IRQ_ROUTING_ENTRY*)p; + + //Update table size in $PRT header + MsPrt->TableSize = (UINT16)(gAmiBoardInfo->PicRoutLength + sizeof(EFI_LEGACY_PIRQ_TABLE_HEADER)); + + // Call BSP routine to do Chipset/OEM specific modifications to PRT + BspUpdatePrt(&CoreBiosInfo->iBios, MsPrt); + + + // Checksum the table + for (count1 = 0; count1 < MsPrt->TableSize; count1++) { + chksum = chksum + *((UINT8*)MsPrt+count1); + } + MsPrt->Checksum = (~chksum) + 1; + IsValidPrt = TRUE; + + // Load the PCI routing table into CSM16 + PrtAddress = CopyLegacyTable( + MsPrt, + (UINT16)MsPrt->TableSize, + 1, // alignment + F0000_BIT); + ASSERT(PrtAddress); + + Status = CoreBiosInfo->iRegion->UnLock (CoreBiosInfo->iRegion, 0xF0000, 0x10000, NULL); + ASSERT_EFI_ERROR(Status); + + CoreBiosInfo->Csm16Header->IrqRoutingTablePointer = (UINT32)PrtAddress; + CoreBiosInfo->Csm16Header->IrqRoutingTableLength = (UINT32)MsPrt->TableSize; + + Status = CoreBiosInfo->iRegion->Lock (CoreBiosInfo->iRegion, 0xF0000, 0x10000, NULL); + ASSERT_EFI_ERROR(Status); + + BusNumXlatProtocol.GetXlatPciBusNum = GetXlatPciBusNumber; + Status = pBS->InstallProtocolInterface( + &gHandle, + &gBusNumXlatProtocol, + EFI_NATIVE_INTERFACE, + &BusNumXlatProtocol + ); + ASSERT_EFI_ERROR(Status); +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: PciIoNotifyCallback +// +// Description: PciIo notification callback. It serves two purposes: +// 1) Updates bus numbers in BusNumXlat table and in $PIR table. For +// this the routine uses PciIo to get PCI loaction of the handle; +// then it will match the found dev/fun against BusNumXlat table +// and fill global RootBridges data and update bus numbers in +// $PIR table. +// 2) Programs PCI IRQ register if: +// - device requires IRQ to be assigned (reg 3D is 1..3) +// - PCI bus information is updated in $PIR table (step 1 +// has been completed) +// - device is present in IRQ routing table +// When all these conditions are met, then IRQ is assigned to this +// device according to the PCI IRQ priorities; then IRQ is programmed +// in PCI register 3C +// +// Input: Event - event signaled by the DXE Core upon PciIo installation +// Context - event context +// +// Output: Nothing +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID PciIoNotifyCallback ( + EFI_EVENT Event, + VOID *Context) +{ +// UINT16 counter; + UINTN BufferSize = sizeof(EFI_HANDLE); + EFI_HANDLE Handle; + EFI_PCI_IO_PROTOCOL *PciIo; + EFI_STATUS Status; + BOOLEAN IsRootBridge; + UINT8 dData[4]; + UINT16 IrqMask; + + if (!IsValidPrt) { + // + // Set 8259 interrupt mask for 16 bit mode + // + Status = GetIsaIrqs(&IsaIrqMask); // Ones for ISA IRQs + // TRACE((-1, "PciInterrupts: Init PRT Get ISA_IRQ_MASK, Status=%r\n", Status)); + ASSERT_EFI_ERROR(Status); + + IrqMask = ~IsaIrqMask; + + Status = i8259->SetMask(i8259, &IrqMask, NULL, NULL, NULL); + ASSERT_EFI_ERROR(Status); + + UpdatePrt(); // Update bus numbers in PRT + } + + //gBS->LocateProtocol(&gEfiPciIoProtocol, gPciIoNotifyReg, &PciIo); + Status = pBS->LocateHandle(ByRegisterNotify, + NULL, gPciIoNotifyReg, &BufferSize, &Handle); + ASSERT_EFI_ERROR(Status); + if (EFI_ERROR(Status)) return; + + // + // Locate PciIo protocol installed on Handle + // + Status = pBS->HandleProtocol(Handle, &gEfiPciIoProtocolGuid, &PciIo); + ASSERT_EFI_ERROR(Status); + if (EFI_ERROR(Status)) return; + + // + // Check whether Handle is PCI Root Bridge handle. + // + Status = PciIo->Pci.Read( + PciIo, + EfiPciIoWidthUint32, + 8, // offset + 1, // width + &dData); + ASSERT_EFI_ERROR(Status); + if (EFI_ERROR(Status)) return; + + IsRootBridge = (dData[1] == 0) && + (dData[2] == PCI_CL_BRIDGE_SCL_HOST) && + (dData[3] == PCI_CL_BRIDGE); // Host bridge + + if (IsRootBridge) return; // Do not process root bridges + + ProgramPciIrq(PciIo, Context); +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: InitPrt +// +// Description: Initialize PCI IRQ routing table +// +// Input: iBiosPlatform - pointer to EFI_LEGACY_BIOS_PLATFORM_PROTOCOL +// +// Output: PCI IRQ routing table initialization status +// +// Notes: 1) BusNumXlat table is generated by AMISDL and requires the actual PCI bus +// number fields to be updated. Actual PCI bus numbers can not be obtained at +// this time due to the following: +// - BusNumXlat table provides PCI dev/fun information for the PCI Host Bridge(s), +// whereas PciRootBridgeIo does not give PCI dev/fun information; in case of +// several PCI Root Bridges, PCI location ambiguity can not be resolved at this +// time. +// - PCI Dev/Fun information for PCI Host bridge(s) is not available until +// PCI Bus driver installs PciIo on PCI Host Bridge devices' handles. +// +// 2) In order to match PCI Root Bridge(s) against the BusNumXlat table, we +// will register callback notification function that will be called every +// time PciIo protocol is installed. This would identify every PCI RootBridge's +// PCI location(dev/fun), allow to match this PCI location against XlatBusNum table, +// traverse through XlatBusNum table entry and update the appropriate bus number +// fields in $PIR table. +// +// 3) This driver must be made dependent on PciRootBridge driver since it expects +// the valid information about PCI root bridges. +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS InitPrt( + EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *iBiosPlatform +) +{ + EFI_EVENT Event; + EFI_STATUS Status; + EFI_LEGACY_INTERRUPT_PROTOCOL *iInterrupt; + UINT8 Dev, Func; +//------------------------------------------ + + Status = pBS->LocateProtocol (&gEfiLegacyInterruptProtocolGuid, NULL, &iInterrupt); + if (EFI_ERROR(Status)) return Status; + + // + // Initialize global variables + // + MsPrt = MallocZ(sizeof(EFI_LEGACY_PIRQ_TABLE_HEADER)); + ASSERT(MsPrt!=NULL); + + + BusNumXlat = (UINT8*)gAmiBoardInfo->BusXlatTable; + BusNumXlatEnd = (UINT8*)((UINTN)gAmiBoardInfo->BusXlatTable+gAmiBoardInfo->BusXlatLength); + Prt = (EFI_LEGACY_IRQ_ROUTING_ENTRY*)gAmiBoardInfo->PicRoutTable; + gUsedPciEntries=gAmiBoardInfo->PicRoutLength/sizeof(PCI_IRQ_PIC_ROUTE); + IsValidPrt = FALSE; // becomes TRUE after bus numbers and checksum in $PRT table is updated + + pBS->SetMem(AddonPciBusTable, sizeof(EFI_ADDON_PCIBUS_TABLE)*MAX_ADDITIONAL_P2P_BRIDGES, 0); + gAddonPciBusIndx = 0; + + //Fill MSPRT Structure Header + MsPrt->Signature=0x52495024; //"$PIR" + MsPrt->MinorVersion=0; //version (low byte = minor, high byte = major) + MsPrt->MajorVersion=1; + MsPrt->TableSize=sizeof(EFI_LEGACY_PIRQ_TABLE_HEADER); //It's only header for now we will connet header and table later + + Status = iInterrupt->GetLocation(iInterrupt, &MsPrt->Bus, &Dev, &Func); + if (EFI_ERROR(Status)) return Status; + + MsPrt->DevFun = (Dev << 3) + Func; + MsPrt->CompatibleVid = SB_PIRQ_ROUTER_VID; + MsPrt->CompatibleDid = SB_PIRQ_ROUTER_DID; + + MemSet(irq_allocated_count, sizeof(irq_allocated_count), 0); + + // + // Set 8259 interrupt mask for 16 bit mode + // + Status = pBS->LocateProtocol (&gEfiLegacy8259ProtocolGuid, NULL, &i8259); + ASSERT_EFI_ERROR(Status); + + // + // Count number of entries in BusNumXlat table globally in XlatTblEntriesRemaining + // + XlatTblEntriesRemaining=gAmiBoardInfo->BusXlatEntries; + // + // Get the list of PCI Root Bridge handles; later on, in the notification callback function, + // use this list to find the corresponding bus number. + // + Status = pBS->LocateHandleBuffer( + ByProtocol, + &gEfiPciRootBridgeIoProtocol, + NULL, + &PciRBHandlesNo, + &PciRBHandles); + ASSERT_EFI_ERROR(Status); + if EFI_ERROR(Status) return Status; + + // + // Create the notification and register callback function on the PciIo installation, + // callback function will update $PIR table + // + Status = pBS->CreateEvent ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + PciIoNotifyCallback, + iBiosPlatform, + &Event); + ASSERT_EFI_ERROR(Status); + if (EFI_ERROR(Status)) return Status; + + Status = pBS->RegisterProtocolNotify ( + &gEfiPciIoProtocolGuid, + Event, + &gPciIoNotifyReg); + ASSERT_EFI_ERROR(Status); + + // Install PCI IRQ programming interface + gIrqPgmCtx.PciIo = NULL; + gIrqPgmCtx.Irq = 0; + Status = pBS->InstallProtocolInterface( + &gHandle, + &gPciIrqProgramGuid, + EFI_NATIVE_INTERFACE, + &gIrqPgmCtx + ); + ASSERT_EFI_ERROR(Status); + + return Status; +} + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2013, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** diff --git a/Core/EM/CSM/csmcore.cif b/Core/EM/CSM/csmcore.cif new file mode 100644 index 0000000..160bbf3 --- /dev/null +++ b/Core/EM/CSM/csmcore.cif @@ -0,0 +1,23 @@ +<component> + name = "CSM Core" + category = ModulePart + LocalRoot = "Core\EM\CSM" + RefName = "CSMCORE" +[files] +"CSM.mak" +"CSM.dxs" +"CSM.h" +"CsmOpROM.c" +"BiosData.h" +"CSM.c" +"CsmHwInfo.c" +"PciInterrupts.c" +"PciInfo.asm" +"OemPir.dat" +"CsmBsp.c" +"CsmLib.c" +"CsmSimpleIn.c" +[parts] +"THUNK" +"CSM_OEM_HOOKS" +<endComponent> diff --git a/Core/EM/CSM/thunk/BlockIo/CsmBlkIoComponentName.c b/Core/EM/CSM/thunk/BlockIo/CsmBlkIoComponentName.c new file mode 100644 index 0000000..6807d3e --- /dev/null +++ b/Core/EM/CSM/thunk/BlockIo/CsmBlkIoComponentName.c @@ -0,0 +1,260 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (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/Thunk/INT13/CsmBlkIoComponentName.c 6 12/23/13 3:38p Olegi $ +// +// $Revision: 6 $ +// +// $Date: 12/23/13 3:38p $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Modules/CSM/Generic/Thunk/INT13/CsmBlkIoComponentName.c $ +// +// 6 12/23/13 3:38p Olegi +// EIP128504: implement EFI_COMPONENT2_NAME_PROTOCOL for CsmBlockIo driver +// +// 5 1/12/10 11:50a Olegi +// Copyright message updated. +// +// 4 10/03/07 4:41p Yakovlevs +// Removed Component Name Protocol and its Strings in NO DEBUG mode to +// save some space. +// +// 3 4/27/07 5:14p Olegi +// CSM.CHM file preparation. +// +// 2 3/04/05 1:43p Mandal +// +// 1 2/15/05 10:59a Olegi +// Initial VSS check-in. +// +//********************************************************************** +//<AMI_FHDR_START> +// +// Name: CsmBlkIoComponentName.c +// +// Description: Set of functions that implement Component Name protocol +// for the CSM BlockIO driver. +// +//<AMI_FHDR_END> +//********************************************************************** + +#include "CsmBlockIo.h" + +#ifndef EFI_COMPONENT_NAME2_PROTOCOL_GUID //old Core +#define LANGUAGE_CODE_ENGLISH "eng" +#define EFI_COMPONENT_NAME2_PROTOCOL EFI_COMPONENT_NAME_PROTOCOL +#endif + +// +// EFI Component Name Functions +// +EFI_STATUS +CsmBlockIoComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME2_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ); + +EFI_STATUS +CsmBlockIoComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME2_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +CHAR16 *gCsmBlockIoDriverName = L"AMI CSM Block I/O Driver"; +CHAR16 gCsmBlockIoControllerName[256]; + +EFI_COMPONENT_NAME2_PROTOCOL gCsmBlockIoComponentName = { + CsmBlockIoComponentNameGetDriverName, + CsmBlockIoComponentNameGetControllerName, + LANGUAGE_CODE_ENGLISH +}; + +static BOOLEAN LanguageCodesEqual( + CONST CHAR8* LangCode1, CONST CHAR8* LangCode2 +){ + return LangCode1[0]==LangCode2[0] + && LangCode1[1]==LangCode2[1] + && LangCode1[2]==LangCode2[2]; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// FUNCTION: CsmBlockIoComponentNameGetDriverName +// +// DESCRIPTION: Retrieves a Unicode string that is the user readable name of +// the EFI Driver. +// +// +// PARAMETERS: +// This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. +// Language - A pointer to a three character ISO 639-2 language identifier. +// This is the language of the driver name that that the caller +// is requesting, and it must match one of the languages specified +// in SupportedLanguages. The number of languages supported by a +// driver is up to the driver writer. +// DriverName - A pointer to the Unicode string to return. This Unicode string +// is the name of the driver specified by This in the language +// specified by Language. +// +// RETURN: +// EFI_SUCCES - The Unicode string for the Driver specified by This +// and the language specified by Language was returned +// in DriverName. +// EFI_INVALID_PARAMETER - Language is NULL. +// EFI_INVALID_PARAMETER - DriverName is NULL. +// EFI_UNSUPPORTED - The driver specified by This does not support the +// language specified by Language. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +CsmBlockIoComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME2_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +{ + // + //Supports only English + // + if (!Language || !DriverName) return EFI_INVALID_PARAMETER; + if (!LanguageCodesEqual( Language, LANGUAGE_CODE_ENGLISH)) return EFI_UNSUPPORTED; + *DriverName = gCsmBlockIoDriverName; + return EFI_SUCCESS; +} + +//--------------------------------------------------------------------------- +//<AMI_PHDR_START> +// +// FUNCTION: CsmBlockIoComponentNameGetControllerName +// +// DESCRIPTION: Retrieves a Unicode string that is the user readable name of +// the controller that is being managed by an EFI Driver. +// +// PARAMETERS: +// This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. +// ControllerHandle - The handle of a controller that the driver specified by +// This is managing. This handle specifies the controller +// whose name is to be returned. +// ChildHandle - The handle of the child controller to retrieve the name +// of. This is an optional parameter that may be NULL. It +// will be NULL for device drivers. It will also be NULL +// for a bus drivers that wish to retrieve the name of the +// bus controller. It will not be NULL for a bus driver +// that wishes to retrieve the name of a child controller. +// Language - A pointer to a three character ISO 639-2 language +// identifier. This is the language of the controller name +// that that the caller is requesting, and it must match one +// of the languages specified in SupportedLanguages. The +// number of languages supported by a driver is up to the +// driver writer. +// ControllerName - A pointer to the Unicode string to return. This Unicode +// string is the name of the controller specified by +// ControllerHandle and ChildHandle in the language +// specified by Language from the point of view of the +// driver specified by This. +// +// RETURNS: +// EFI_SUCCESS - The Unicode string for the user readable name in the +// language specified by Language for the driver +// specified by This was returned in DriverName. +// EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE. +// EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid +// EFI_HANDLE. +// EFI_INVALID_PARAMETER - Language is NULL. +// EFI_INVALID_PARAMETER - ControllerName is NULL. +// EFI_UNSUPPORTED - The driver specified by This is not currently +// managing the controller specified by +// ControllerHandle and ChildHandle. +// EFI_UNSUPPORTED - The driver specified by This does not support the +// language specified by Language. +// +//<AMI_PHDR_END> +//--------------------------------------------------------------------------- + +EFI_STATUS +CsmBlockIoComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME2_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +{ + EFI_STATUS Status; + EFI_LEGACY_BIOS_EXT_PROTOCOL *LegacyBiosExt; + UINT8 BbsCount; + BBS_TABLE *BbsEntry; + UINT32 i; + EFI_HANDLE Handle; + CHAR8 *Str; + UINT8 Index = 0; + + // + //Supports only "eng" + // + if (!Language || !ControllerName) return EFI_INVALID_PARAMETER; + if (!LanguageCodesEqual( Language, LANGUAGE_CODE_ENGLISH)) return EFI_UNSUPPORTED; + if (ChildHandle == NULL) return EFI_UNSUPPORTED; + + Status = pBS->LocateProtocol(&gEfiLegacyBiosExtProtocolGuid, NULL, (VOID**)&LegacyBiosExt); + if (EFI_ERROR(Status)) return Status; + + Status = LegacyBiosExt->GetBbsTable(&BbsEntry, &BbsCount); + if (EFI_ERROR(Status)) return Status; + + ZeroMemory(gCsmBlockIoControllerName, sizeof(gCsmBlockIoControllerName)); + + for (i = 0; i < MAX_BBS_ENTRIES_NO; i++, BbsEntry++) { + Handle = *(VOID**)(&BbsEntry->IBV1); + if (Handle == ChildHandle) { + Str = (CHAR8*)(UINTN)((BbsEntry->DescStringSegment<<4) + BbsEntry->DescStringOffset); + if (Str == NULL) return EFI_UNSUPPORTED; + // + // Transfer Ascii code to Unicode + // + while (Str[Index] != 0) { + gCsmBlockIoControllerName[Index] = (CHAR16)Str[Index]; + Index++; + } + + *ControllerName = gCsmBlockIoControllerName; + return EFI_SUCCESS; + } + } + return EFI_UNSUPPORTED; +} + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2010, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** diff --git a/Core/EM/CSM/thunk/BlockIo/CsmBlockIo.c b/Core/EM/CSM/thunk/BlockIo/CsmBlockIo.c new file mode 100644 index 0000000..14438f5 --- /dev/null +++ b/Core/EM/CSM/thunk/BlockIo/CsmBlockIo.c @@ -0,0 +1,1076 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2014, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** + +//********************************************************************** +// $Header: /Alaska/SOURCE/Modules/CSM/Generic/Thunk/INT13/CsmBlockIo.c 49 8/06/14 1:20p Fasihm $ +// +// $Revision: 49 $ +// +// $Date: 8/06/14 1:20p $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Modules/CSM/Generic/Thunk/INT13/CsmBlockIo.c $ +// +// 49 8/06/14 1:20p Fasihm +// [TAG] EIP180668 +// [Category] Bug Fix +// [Severity] Normal +// [Symptom] Aptio 4 CSM: CsmBlkIO: Start function might incorrectly +// initialize IBV fields in BBS table. +// [Solution] Maintain the number of newly created BBS entries; +// initialize IBV fields only for those entries created by the Option ROM. +// [Files] +// Core\EM\CSM\thunk\BlockIo\CsmBlockIo.c +// +// 48 12/23/13 3:38p Olegi +// EIP128504: implement EFI_COMPONENT_NAME2_PROTOCOL for CsmBlockIo driver +// +// 47 12/23/13 3:14p Olegi +// EIP148138: use AMI_BLOCKIO_WRITE_PROTECTION_PROTOCOL instead of +// EFI_MBR_WRITE_PROTECTION_PROTOCOL +// +// 46 12/23/13 10:22a Olegi +// EIP148123: CSM includes file which name has been changed +// +// 45 12/06/13 12:07a Rameshr +// [TAG] EIP143793 +// [Category] Improvement +// [Description] For onboard Raid controller, consumed +// DevicePathProtocol - By driver and as a child controller, instead of +// the PciIo Protocol. Because PciIo protocol us already consumed by +// SataController driver. +// [Files] CsmBlockIo.c +// +// 44 7/01/13 5:56a Kapilporwal +// [TAG] EIP125560 +// [Category] Improvement +// [Description] Please support Boot Sector Virus Protection for CSM +// Disabled Mode +// [Files] VirusProtect.c, VirusProtect.dxs, AhciBus.c, +// AhciController.c, CsmBlockIo.c, CsmInt13.c, Ata.c, IdeBus.c, +// SdioBlkIo.c, SdioDriver.c, efiusbmass.c +// +// 43 3/07/13 10:47p Olegi +// [TAG] EIP117323 +// [Category] New Feature +// [Description] Fiber Channel controllers support in CsmBlockIo +// +// 42 12/14/12 3:29p Olegi +// +// 41 12/23/11 2:12p Olegi +// [TAG] EIP78921 +// [Category] Improvement +// [Description] CsmBlockIo should create device handle in BBS table +// [Files] CsmBlockIo.c +// CsmBlockIo.h +// +// 39 11/10/11 7:15p Olegi +// Installed thunk driver GUID +// +// 38 11/04/11 12:41p Olegi +// +// 37 8/15/11 9:45a Olegi +// +// 36 8/12/11 3:05p Olegi +// Correction to the previous check-in: in Supported function some +// protocols can not be open BY_DRIVER for the onboard RAID. Changed the +// OpenProtocol attributes. +// +// 35 8/10/11 11:48a Olegi +// GUID and variable names are corrected; Supported function modified to +// close PciIo protocol right after it is used. EIP49352. +// +// 34 7/20/11 12:21p Olegi +// Added dependency on the HDD security SDL token. +// +// 33 6/27/11 4:50p Olegi +// Cleaning the headers and the comments. Change in Supported function +// that partially undoing EIP39017 and allows non-Intel RAID option ROMs +// produce BlkIo. +// +// 32 4/27/11 6:47p Olegi +// [TAG] EIP54911 +// [Category] Improvement +// [Description] Start function modified to return the proper value. +// [Files] CsmBlockIo.c +// +// 31 1/19/11 10:19a Olegi +// +// 29 12/14/10 12:08p Olegi +// [TAG] EIP48212 +// [Category] Bug Fix +// [Severity] Important +// [Symptom] Some controllers are not enabled before executing their +// Option ROM +// [RootCause] There is no code that enable a device in CsmBlockIo start +// function. +// [Solution] Added a call that enables device to the CsmBlockIo start +// function. +// [Files] CsmBlockIo.c, PciInterrupts.c +// +// 28 7/29/10 3:20p Olegi +// EIP39017:: Added code in Supported function to prevent BlockIo from +// binding prematurely. +// +// 27 3/12/10 9:49a Olegi +// Onboard RAID option ROM related changes. EIP34602. +// +// 26 1/12/10 11:50a Olegi +// Copyright message updated. +// +// 25 8/07/09 2:46p Rameshr +// SD boot support Added. +// +// 24 10/04/07 3:04p Olegi +// Bugfix in CsmBlockIoStart for HW interrupt save/restore in case of +// multiple drives connected. +// +// 23 10/03/07 4:41p Yakovlevs +// Removed Component Name Protocol and its Strings in NO DEBUG mode to +// save some space. +// +// 22 4/27/07 5:14p Olegi +// CSM.CHM file preparation. +// +// 21 4/13/07 9:37a Olegi +// +// 20 3/29/07 5:51p Olegi +// +// 19 3/29/07 1:37p Felixp +// Bug fix in BuildDevicePath: properly initialize device path for unknown +// devices +// +// 18 12/07/06 3:13p Olegi +// Support for embedded OpROMs added. +// +// 17 7/31/06 4:11p Olegi +// +// 16 5/19/06 11:25p Felixp +// Device Path code updated to use NEXT_NODE/NODE_LENGTH/SET_NODE_LENGTH +// macros to remove direct access to the Length field +// +// 15 5/01/06 3:57p Olegi +// CheckPciRom will be called from LegacyBios.InstallPciRom, no need to +// call it again. +// +// 14 3/13/06 4:15p Felixp +// +// 13 3/13/06 2:38p Felixp +// +// 12 10/13/05 6:21p Olegi +// Added HW interrupt handling +// +// 11 8/30/05 9:06a Olegi +// BuildDevicePath correction. +// +// 10 7/26/05 2:51p Olegi +// +// 9 6/23/05 5:26p Olegi +// +// 8 6/22/05 8:34a Olegi +// +// 7 4/20/05 4:16p Olegi +// INT 13 vector maintenance has been moved to the main CSM module. +// +// 6 4/12/05 12:21p Olegi +// +// 5 3/16/05 11:05a Olegi +// +// 4 3/04/05 1:45p Mandal +// +//********************************************************************** +//<AMI_FHDR_START> +// +// Name: CsmBlockIo.c +// +// Description: CSM Block I/O Module. Main module, containing entry, +// supported, start, and stop functions. +// +//<AMI_FHDR_END> +//********************************************************************** + +#include "CsmBlockIo.h" +#include <Protocol\Legacy8259.h> +#include <Protocol\IdeControllerInit.h> + +#if defined CORE_COMBINED_VERSION && (CORE_COMBINED_VERSION > 0x4028E) +#include <Protocol\AmiBlockIoWriteProtection.h> +AMI_BLOCKIO_WRITE_PROTECTION_PROTOCOL *gBlockIoWriteProtectionProtocol = NULL; +#endif + +// EFI Driver Binding Protocol Instance +EFI_DRIVER_BINDING_PROTOCOL gCsmBlockIoDriverBinding = { + CsmBlockIoSupported, + CsmBlockIoStart, + CsmBlockIoStop, + 0x10, + NULL, + NULL +}; + +#ifndef EFI_COMPONENT_NAME2_PROTOCOL_GUID //old Core +EFI_GUID gComponentNameProtocolGuid = EFI_COMPONENT_NAME_PROTOCOL_GUID; +extern EFI_COMPONENT_NAME_PROTOCOL gCsmBlockIoComponentName; +#else +EFI_GUID gComponentNameProtocolGuid = EFI_COMPONENT_NAME2_PROTOCOL_GUID; +extern EFI_COMPONENT_NAME2_PROTOCOL gCsmBlockIoComponentName; +#endif + +// Number of current users of this driver +UINTN mCurrentUsers = 0; + +// Real mode buffer to contain the buffers below +EFI_PHYSICAL_ADDRESS mRealModeBuffer = 0; + +// Packet buffer under 1 MB for all version EDD calls +EDD_DEVICE_ADDRESS_PACKET *mEDDPacketBuffer; + +// EDD 1.1 transfer buffer +VOID *mEDDTransferBuffer; + +// This is a buffer for INT 13h func 48 information +CSM_LEGACY_DRIVE *mDriveParameterBuffer; + +// The following variables will track the onboard mass storage controller +// in RAID mode with the Option ROM that can not handle ATAPI devices: +// +// - gOnboardRaidGuid is GUID installed on such controller in SBDXE +// - gOnboardRaid is the switch indicating the requested controller +// has gOnboardRaidGuid installed on it +// +#define ONBOARD_RAID_GUID \ + { 0x5d206dd3, 0x516a, 0x47dc, 0xa1, 0xbc, 0x6d, 0xa2, 0x4, 0xaa, 0xbe, 0x8}; +EFI_GUID gOnboardRaidGuid = ONBOARD_RAID_GUID; + +// The following GUID is used to ensure the Start function is executed after all +// individual drives in RAID are unlocked before RAID Option ROM is executed +// +#define HDD_UNLOCKED_GUID \ + { 0x1fd29be6, 0x70d0, 0x42a4, 0xa6, 0xe7, 0xe5, 0xd1, 0xe, 0x6a, 0xc3, 0x76}; +EFI_GUID gHddUnlockedGuid = HDD_UNLOCKED_GUID; + + +//<AMI_PHDR_START> +//********************************************************************** +// +// Procedure: CsmBlockIoEntryPoint +// +// Description: +// This is the CsmBlockIo driver entry point. It installs +// gCsmBlockIoDriverBinding protocol +// +//********************************************************************** +//<AMI_PHDR_END> + +EFI_STATUS +CsmBlockIoEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) + +{ + static EFI_GUID gCsmThunkDriverGuid = + { 0x2362ea9c, 0x84e5, 0x4dff, 0x83, 0xbc, 0xb5, 0xac, 0xec, 0xb5, 0x7c, 0xbb }; + + gCsmBlockIoDriverBinding.DriverBindingHandle = ImageHandle; + gCsmBlockIoDriverBinding.ImageHandle = ImageHandle; + + InitAmiLib(ImageHandle, SystemTable); + + return pBS->InstallMultipleProtocolInterfaces( + &gCsmBlockIoDriverBinding.DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, &gCsmBlockIoDriverBinding, + &gComponentNameProtocolGuid, &gCsmBlockIoComponentName, + &gCsmThunkDriverGuid, NULL, + NULL + ); +} + +//<AMI_PHDR_START> +//********************************************************************** +// +// Procedure: CsmBlockIoSupported +// +// Description: +// This is a binding protocol function. It checks whether or not this +// driver supports the given controller +// +// +// Input: +// IN EFI_DRIVER_BINDING_PROTOCOL *This, +// IN EFI_HANDLE Controller, +// IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath +// +//********************************************************************** +//<AMI_PHDR_END> + +EFI_STATUS +CsmBlockIoSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; + EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; + EFI_PCI_IO_PROTOCOL *PciIo; + PCI_STD_DEVICE Pci; + VOID *IdeControllerInterface; + + // See if the Legacy BIOS Protocol is available + Status = pBS->LocateProtocol( &gEfiLegacyBiosProtocolGuid, + NULL, (VOID**)&LegacyBios); + if (EFI_ERROR (Status)) { + return Status; + } + + // Check whether DevicePath Protocol has been installed on this controller + Status = pBS->OpenProtocol( Controller, + &gEfiDevicePathProtocolGuid, + (VOID**)&ParentDevicePath, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER ); + + if (EFI_ERROR (Status)) { + return Status; + } + + pBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller); + + // Check whether this is Onboard RAID + Status = pBS->OpenProtocol( Controller, + &gOnboardRaidGuid, + NULL, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL ); + + // Do the checkings/manipulations with the onboard RAID + if(!EFI_ERROR(Status)) + { + // Make sure drives are unlocked +#if defined SETUP_IDE_SECURITY_SUPPORT && SETUP_IDE_SECURITY_SUPPORT == 1 + Status = pBS->OpenProtocol( Controller, + &gHddUnlockedGuid, + NULL, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL ); +#endif + if(EFI_ERROR(Status)) { + return EFI_UNSUPPORTED; + } + + // Make sure IDE_CONTROLLER_PROTOCOL is installed; this ensures the + // controller is initialized + Status = pBS->OpenProtocol( Controller, + &gEfiIdeControllerInitProtocolGuid, + (VOID **)&IdeControllerInterface, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL); + + if (EFI_ERROR(Status)) { + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS; + } + + // Check whether PCI Protocol has been installed on this controller + Status = pBS->OpenProtocol( Controller, + &gEfiPciIoProtocolGuid, + (VOID**)&PciIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER ); + + if (EFI_ERROR(Status)) return Status; + + // Read PCI configuration + Status = PciIo->Pci.Read (PciIo, + EfiPciIoWidthUint32, + 0, + sizeof (Pci) / sizeof (UINT32), + &Pci); + if (EFI_ERROR(Status)) return Status; + + pBS->CloseProtocol( Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller ); + + + // Status is EFI_SUCCESS here + + if ( Pci.Header.ClassCode[2] != PCI_CL_MASS_STOR && \ + (Pci.Header.ClassCode[2] != PCI_BASE_CLASS_INTELLIGENT || \ + Pci.Header.ClassCode[1] != PCI_SUB_CLASS_INTELLIGENT) ) + { + Status = EFI_UNSUPPORTED; + } + if ( Pci.Header.ClassCode[1] == PCI_CL_SYSTEM_PERIPHERALS_SCL_SD && \ + Pci.Header.ClassCode[2] == PCI_CL_SYSTEM_PERIPHERALS ) + { + Status = EFI_SUCCESS; + } + if ( Pci.Header.ClassCode[1] == PCI_CL_SER_BUS_SCL_FIBCHAN && + Pci.Header.ClassCode[2] == PCI_CL_SER_BUS ) + { + Status = EFI_SUCCESS; + } + +// TRACE((-1, "\nCsmBlockIo.Supported: called for VID/DID: %x %x, CL %x SCL %x; Status = %r\n", +// Pci.Header.VendorId, Pci.Header.DeviceId, Pci.Header.ClassCode[2], Pci.Header.ClassCode[1], Status)); + + return Status; +} + + +//<AMI_PHDR_START> +//********************************************************************** +// +// Procedure: CsmBlockIoStart +// +// Description: +// Installs BlockIoProtocol using INT13 services produced by Option ROM +// +// Input: +// IN EFI_DRIVER_BINDING_PROTOCOL *This, +// IN EFI_HANDLE Controller, +// IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath +// +// Notes: +// Here is the control flow of this function: +// 1. Open PCI and Devicepath protocol +// 2. Enable the device +// 3. Post the option rom +// 4. If first time, allocate buffer for real mode thunk code +// 5. For each disk... +// a. Allocate and initialize a private structure +// b. Install block I/O protocol on a new child device +// c. Open the child device +// 6. Increment user counter +// +//********************************************************************** +//<AMI_PHDR_END> + +EFI_STATUS +CsmBlockIoStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath +) +{ + EFI_STATUS Status; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; + EFI_PCI_IO_PROTOCOL *PciIo = NULL; + UINT8 FirstDisk; + UINT8 LastDisk; + UINT8 x = 0; + CSM_BLOCK_IO_DEV *PrivateBlockIoStruc = NULL; + EFI_DEVICE_PATH_PROTOCOL *PciDevPath; + UINTN i = 0; + UINTN Flags; + UINTN TempAddress = 0; + UINT8 irq = 0; + EFI_LEGACY_8259_PROTOCOL *i8259; + UINT32 *ivt = (UINT32*)0; + UINT32 TempInt; + UINT32 HwInterruptHandler; + UINT64 Capabilities; + UINT8 j = 0; + UINT8 BbsCount; + BBS_TABLE* BbsEntry = NULL; + BBS_TABLE* BbsTable = NULL; + BOOLEAN BbsEntryPresent[MAX_BBS_ENTRIES_NO] = {0}; + UINTN FirstNewBbsEntry = 0; + EFI_LEGACY_BIOS_EXT_PROTOCOL *LegacyBiosExt; + BOOLEAN OnboardRaidController=FALSE; + EFI_DEVICE_PATH_PROTOCOL *ChildPciDevPath; + UINT8 NumberOfBbsEntriesBeforeOprom = 0; + UINT8 NumberOfBbsEntriesAfterOprom = 0; + UINT8 NewBbsEntries; + + // See if the Legacy BIOS Protocol is available + Status = pBS->LocateProtocol( &gEfiLegacyBiosProtocolGuid, + NULL, (VOID **)&LegacyBios); + if (EFI_ERROR (Status)) { + return Status; + } + + // See if the Legacy BIOS Ext Protocol is available + Status = pBS->LocateProtocol ( &gEfiLegacyBiosExtProtocolGuid, + NULL, (VOID**)&LegacyBiosExt); + if (EFI_ERROR (Status)) { + return Status; + } + +#if defined CORE_COMBINED_VERSION && (CORE_COMBINED_VERSION > 0x4028E) + if(gBlockIoWriteProtectionProtocol == NULL) + pBS->LocateProtocol(&gAmiBlockIoWriteProtectionProtocolGuid, NULL, &gBlockIoWriteProtectionProtocol); +#endif + Status = pBS->OpenProtocol( Controller, + &gEfiDevicePathProtocolGuid, + (VOID**)&PciDevPath, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER ); + + if (EFI_ERROR (Status)) { + return Status; + } + + // Check whether this is Onboard RAID + Status = pBS->OpenProtocol( Controller, + &gOnboardRaidGuid, + NULL, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL ); + + if (!EFI_ERROR (Status)) { + OnboardRaidController=TRUE; + } + + // Open PCI I/O Protocol + if (OnboardRaidController) { + Status = pBS->OpenProtocol( Controller, + &gEfiPciIoProtocolGuid, + (VOID **)&PciIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL ); + + } else { + Status = pBS->OpenProtocol( Controller, + &gEfiPciIoProtocolGuid, + (VOID **)&PciIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER ); + } + + if ( EFI_ERROR(Status) ) { + return Status; + } + + // Get the hardware interrupt vector and its handler pointer + Status = PciIo->Pci.Read(PciIo, EfiPciIoWidthUint8, 0x3C, 1, &irq); + ASSERT_EFI_ERROR(Status); + if (irq > 0 && irq < 0xF) { + Status = pBS->LocateProtocol(&gEfiLegacy8259ProtocolGuid, NULL, &i8259); + ASSERT_EFI_ERROR(Status); + + Status = i8259->GetVector (i8259, irq, &irq); // irq has INT number + ASSERT_EFI_ERROR(Status); + } + + // Store HW interrupt vector, to be restored for PnP ROMs + TempInt = ivt[irq]; + + // Enable the device + 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); + + // Check to see if there is a legacy option ROM image associated with this PCI device + Status = LegacyBios->CheckPciRom (LegacyBios, + Controller, + NULL, + NULL, + &Flags + ); + + if ( EFI_ERROR(Status) ) { + Status = EFI_SUCCESS; + goto Done; + } + + // Get BBS table + Status = LegacyBiosExt->GetBbsTable( + &BbsEntry, + &BbsCount); + ASSERT_EFI_ERROR(Status); + BbsTable = BbsEntry; + + // Loop through table and note entries which are populated + for (i = 0; i < MAX_BBS_ENTRIES_NO; i++, BbsEntry++) { + + if (BbsEntry->BootPriority == BBS_IGNORE_ENTRY) + continue; + + BbsEntryPresent[i] = TRUE; + NumberOfBbsEntriesBeforeOprom++; + } + + // Post the legacy option ROM if it is available. + Status = LegacyBios->InstallPciRom( LegacyBios, + Controller, + NULL, + &Flags, + &FirstDisk, + &LastDisk, + NULL, + NULL ); + if (EFI_ERROR (Status)) { + goto Done; + } + + BbsEntry = BbsTable; + + // Loop through BBS table and find first new entry, added due to OpROM execution + for (i = 0; i < MAX_BBS_ENTRIES_NO; i++, BbsEntry++) { + if (BbsEntry->BootPriority == BBS_IGNORE_ENTRY) + continue; + if ((BbsEntryPresent[i] == FALSE) && (FirstNewBbsEntry == 0)) { + FirstNewBbsEntry = i; + } + NumberOfBbsEntriesAfterOprom++; + } + + ASSERT(NumberOfBbsEntriesAfterOprom >= NumberOfBbsEntriesBeforeOprom); + NewBbsEntries = NumberOfBbsEntriesAfterOprom - NumberOfBbsEntriesBeforeOprom; + + HwInterruptHandler = ivt[irq]; + + // All users share a buffer under 1MB to put real mode thunk code in + // If it has not been allocated, then we allocate it. + if (mRealModeBuffer == 0) { + // Allocate below 1MB + mRealModeBuffer = 0x00000000000FFFFF; + Status = pBS->AllocatePages( AllocateMaxAddress, + EfiBootServicesData, + BLOCK_IO_BUFFER_PAGE_SIZE, + &mRealModeBuffer ); + + // Check memory allocation success + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + mRealModeBuffer = 0; + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + + // Set up real mode memory for Thunk + TempAddress = (UINTN)mRealModeBuffer; + // Setup the EDD 1.1 transfer buffer + TempAddress += AlignAddress(TempAddress); + mEDDTransferBuffer = (VOID *)(TempAddress); + // Setup the Legacy Drive buffer + TempAddress += MAX_EDD11_XFER; + TempAddress += AlignAddress(TempAddress); + mDriveParameterBuffer = (CSM_LEGACY_DRIVE *)(TempAddress); + // Setup the EDD Packet buffer + TempAddress += sizeof (CSM_LEGACY_DRIVE); + TempAddress += AlignAddress(TempAddress); + mEDDPacketBuffer = (EDD_DEVICE_ADDRESS_PACKET *)TempAddress; + } + + // Allocate the private device structure for each disk + for (i = FirstDisk, j = 0; i < LastDisk; i++, j++) { + + Status = pBS->AllocatePool( EfiBootServicesData, + sizeof (CSM_BLOCK_IO_DEV), + &PrivateBlockIoStruc ); + + if (EFI_ERROR(Status)) { + pBS->CloseProtocol( Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller ); + + pBS->CloseProtocol( Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller ); + + if (mRealModeBuffer != 0 && mCurrentUsers == 0) { + pBS->FreePages (mRealModeBuffer, BLOCK_IO_BUFFER_PAGE_SIZE); + mRealModeBuffer = 0; + } + + return Status; + } + + // Zero the private device structure + ZeroMemory (PrivateBlockIoStruc, sizeof (CSM_BLOCK_IO_DEV)); + + // Initialize the private device structure + PrivateBlockIoStruc->ControllerHandle = Controller; + PrivateBlockIoStruc->LegacyBios = LegacyBios; + PrivateBlockIoStruc->PciIo = PciIo; + + PrivateBlockIoStruc->Drive.Floppy = FALSE; + x = (i & 0x40)? 0x40 : 0; + if (x) { + PrivateBlockIoStruc->HwInt = irq; + PrivateBlockIoStruc->HwIntHandler = HwInterruptHandler; + ivt[irq] = TempInt; // Restore HW interrupt + } + PrivateBlockIoStruc->Drive.Number = (UINT8) i - x; + PrivateBlockIoStruc->Drive.Letter = (UINT8)(i - x - 0x80 + 'C'); + PrivateBlockIoStruc->BlockMedia.RemovableMedia = FALSE; + + if (InitBlockIo (PrivateBlockIoStruc)) { + BuildDevicePath( PciDevPath, + &PrivateBlockIoStruc->Drive, + &PrivateBlockIoStruc->DevicePath); + + // Install the Block Io Protocol onto a new child handle + Status = pBS->InstallMultipleProtocolInterfaces( &PrivateBlockIoStruc->Handle, + &gEfiBlockIoProtocolGuid, + &PrivateBlockIoStruc->BlockIo, + &gEfiDevicePathProtocolGuid, + PrivateBlockIoStruc->DevicePath, + NULL ); + if (EFI_ERROR (Status)) { + pBS->FreePool (PrivateBlockIoStruc); + } + + // Set handle to which BlockIO has been installed + if (j < NewBbsEntries) + { + *(UINTN*)(&(BbsTable[FirstNewBbsEntry + j].IBV1)) = (UINTN)(PrivateBlockIoStruc->Handle); + } + if(OnboardRaidController) { + // Open For Child Device + Status = pBS->OpenProtocol( Controller, + &gEfiDevicePathProtocolGuid, + (VOID**)&ChildPciDevPath, + This->DriverBindingHandle, + PrivateBlockIoStruc->Handle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER ); + + } else { + + // Open For Child Device + Status = pBS->OpenProtocol( Controller, + &gEfiPciIoProtocolGuid, + (VOID**)&PrivateBlockIoStruc->PciIo, + This->DriverBindingHandle, + PrivateBlockIoStruc->Handle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER ); + } + } else { + pBS->FreePool (PrivateBlockIoStruc); + } + } // end for loop + + mCurrentUsers++; + + return Status; + +Done: + pBS->CloseProtocol( Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller ); + pBS->CloseProtocol( Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller ); + return Status; + +} + + +//<AMI_PHDR_START> +//********************************************************************** +// +// Procedure: CsmBlockIoStop +// +// Description: Installs IdeControllerProtocol +// +// Input: +// IN EFI_DRIVER_BINDING_PROTOCOL *This, +// IN EFI_HANDLE Controller, +// IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath +// +// Notes: +// Here is the control flow of this function: +// 1. Decrement user counter +// 2. Free global buffer +// 3. Release PCI I/O protocol and Block I/O protocol for each child handle. +// 4. Shut down the hardware for each child handle. +// +//********************************************************************** +//<AMI_PHDR_END> + +EFI_STATUS +CsmBlockIoStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer +) +{ + EFI_STATUS Status; + BOOLEAN AllChildrenStopped; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + CSM_BLOCK_IO_DEV *PrivateBlockIoStruc; + UINTN i; + BOOLEAN OnboardRaidController=FALSE; + + // Decrement the number of current users + mCurrentUsers--; + + if (mCurrentUsers == 0) { + // Free our global buffer + Status = pBS->FreePages (mRealModeBuffer, BLOCK_IO_BUFFER_PAGE_SIZE); + ASSERT_EFI_ERROR (Status); + mRealModeBuffer = 0; + } + + // Check whether this is Onboard RAID + Status = pBS->OpenProtocol( Controller, + &gOnboardRaidGuid, + NULL, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL ); + + if (!EFI_ERROR (Status)) { + OnboardRaidController=TRUE; + } + + AllChildrenStopped = TRUE; + + // Close protocols and shut down hardware for each child handle. + for (i = 0; i < NumberOfChildren; i++) { + + Status = pBS->OpenProtocol( ChildHandleBuffer[i], + &gEfiBlockIoProtocolGuid, + (VOID**)&BlockIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL ); + + if (EFI_ERROR (Status)) { + return Status; + } + + PrivateBlockIoStruc = (CSM_BLOCK_IO_DEV *) BlockIo; + + if(OnboardRaidController) { + pBS->CloseProtocol( Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + ChildHandleBuffer[i] ); + } + + // Release PCI I/O and Block IO Protocols on the clild handle. + Status = pBS->UninstallMultipleProtocolInterfaces( ChildHandleBuffer[i], + &gEfiBlockIoProtocolGuid, + &PrivateBlockIoStruc->BlockIo, + &gEfiDevicePathProtocolGuid, + PrivateBlockIoStruc->DevicePath, + NULL ); + + if (EFI_ERROR(Status)) { + AllChildrenStopped = FALSE; + } + + // Shutdown the hardware + PrivateBlockIoStruc->PciIo->Attributes ( + PrivateBlockIoStruc->PciIo, + EfiPciIoAttributeOperationDisable, + EFI_PCI_DEVICE_ENABLE, + NULL); + + + if(!OnboardRaidController) { + pBS->CloseProtocol( Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + ChildHandleBuffer[i] ); + } + + pBS->FreePool (PrivateBlockIoStruc); + } // end for loop + + if (!AllChildrenStopped) { + return EFI_DEVICE_ERROR; + } + + Status = pBS->CloseProtocol( Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller ); + + if(!OnboardRaidController) { + Status = pBS->CloseProtocol( Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller); + } + + return EFI_SUCCESS; +} + + +// LOCAL FUNCTIONS +//********************************************************************** + +//<AMI_PHDR_START> +//********************************************************************** +// +// Procedure: BuildDevicePath +// +// Description: Builds device path for this device +// +// Input: +// IN EFI_DEVICE_PATH_PROTOCOL *BaseDevicePath, +// IN CSM_LEGACY_DRIVE *Drive, +// OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath +// +// Notes: +// Here is the control flow of this function: +// 1. Decrement user counter +// 2. Free global buffer +// 3. Release PCI I/O protocol and Block I/O protocol for each child handle. +// 4. Shut down the hardware for each child handle. +// +//********************************************************************** +//<AMI_PHDR_END> + +VOID +BuildDevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL *BaseDevicePath, + IN CSM_LEGACY_DRIVE *Drive, + OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath +) +{ + EFI_GUID UnknownDevGuid = UNKNOWN_DEVICE_GUID; // ditto + EFI_DEV_PATH Node; + UINT32 Controller; + + Node.DevPath.Type = 0; + if (Drive->EddVersion == EDD_VERSION_30 && + Drive->Parameters.StructureSize > 0x1A && + *(UINT32*)Drive->Parameters.InterfaceType != 0) { + // Build device path for EDD 3.0 device + Controller = (UINT32)Drive->Parameters.InterfacePath.Pci.Controller; + if ((MemCmp ("ATAPI", Drive->Parameters.InterfaceType, 5) == 0) || + (MemCmp ("ATA", Drive->Parameters.InterfaceType, 3) == 0)) { + // ATA or ATAPI drive found + Node.Atapi.Header.Type = MESSAGING_DEVICE_PATH; + Node.Atapi.Header.SubType = MSG_ATAPI_DP; + SET_NODE_LENGTH(&Node.Atapi.Header,sizeof(ATAPI_DEVICE_PATH)); + Node.Atapi.SlaveMaster = Drive->Parameters.DevicePath.Atapi.Master; + Node.Atapi.Lun = Drive->Parameters.DevicePath.Atapi.Lun; + Node.Atapi.PrimarySecondary = (UINT8)Controller; + } else { + // Not an ATA/ATAPI drive + if (Controller != 0) { + Node.Controller.Header.Type = HARDWARE_DEVICE_PATH; + Node.Controller.Header.SubType = HW_CONTROLLER_DP; + SET_NODE_LENGTH(&Node.Controller.Header,sizeof(CONTROLLER_DEVICE_PATH)); + Node.Controller.Controller = Controller; + *DevicePath = DPAddNode (BaseDevicePath, &Node.DevPath); + Node.DevPath.Type = 0; + } + // Since it's not ATA/ATAPI, find out what kind it is + if (MemCmp("SCSI", Drive->Parameters.InterfaceType, 4) == 0 ) { + // SCSI drive + Node.Scsi.Header.Type = MESSAGING_DEVICE_PATH; + Node.Scsi.Header.SubType = MSG_SCSI_DP; + SET_NODE_LENGTH(&Node.Scsi.Header,sizeof(SCSI_DEVICE_PATH)); + Node.Scsi.Lun = (UINT16)Drive->Parameters.DevicePath.Scsi.Lun; + Node.Scsi.Pun = Drive->Parameters.DevicePath.Scsi.TargetId; + } else if (MemCmp("USB", Drive->Parameters.InterfaceType, 3) == 0 ) { + // USB drive + Node.Usb.Header.Type = MESSAGING_DEVICE_PATH; + Node.Usb.Header.SubType = MSG_USB_DP; + SET_NODE_LENGTH(&Node.Usb.Header,sizeof(USB_DEVICE_PATH)); + Node.Usb.ParentPortNumber = (UINT8)Drive->Parameters.DevicePath.Usb.Reserved; + } else if (MemCmp("1394", Drive->Parameters.InterfaceType, 4) == 0 ) { + // 1394 drive + Node.F1394.Header.Type = MESSAGING_DEVICE_PATH; + Node.F1394.Header.SubType = MSG_1394_DP; + SET_NODE_LENGTH(&Node.F1394.Header,sizeof(F1394_DEVICE_PATH)); + Node.F1394.Guid = Drive->Parameters.DevicePath.FireWire.Guid; + } else if (MemCmp("FIBRE", Drive->Parameters.InterfaceType, 5) == 0 ) { + // Fibre Channel drive + Node.FibreChannel.Header.Type = MESSAGING_DEVICE_PATH; + Node.FibreChannel.Header.SubType = MSG_FIBRECHANNEL_DP; + SET_NODE_LENGTH(&Node.FibreChannel.Header,sizeof(FIBRECHANNEL_DEVICE_PATH)); + Node.FibreChannel.WWN = Drive->Parameters.DevicePath.FibreChannel.Wwn; + Node.FibreChannel.Lun = Drive->Parameters.DevicePath.FibreChannel.Lun; + } + } + } + // If Device Path Type is still zero, it means this is either EDD 1.1 device + // or unreconized EDD 3.0 device. Add vendor HW device node for such devices + if (Node.DevPath.Type == 0) { + Node.UnknownVendor.DevicePath.Header.Type = HARDWARE_DEVICE_PATH; + Node.UnknownVendor.DevicePath.Header.SubType = HW_VENDOR_DP; + SET_NODE_LENGTH(&Node.UnknownVendor.DevicePath.Header,sizeof(UNKNOWN_DEVICE_VENDOR_DEVICE_PATH)); + Node.UnknownVendor.DevicePath.Guid = UnknownDevGuid; + Node.UnknownVendor.LegacyDriveLetter = Drive->Number; + } + *DevicePath = DPAddNode (BaseDevicePath, &Node.DevPath); +} + +// Align address on boundary of UINTN for this compiler +UINTN AlignAddress (UINTN Address) +{ + if((UINTN)Address % sizeof(UINTN)) { + return sizeof(UINTN) - ((UINTN)Address % sizeof(UINTN)); + } else { + return 0; + } +} + +// Zero memory +VOID ZeroMemory ( + VOID *Buffer, + UINTN Size +) +{ + UINT8 *Ptr; + Ptr = Buffer; + while (Size--) { + *(Ptr++) = 0; + } +} + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2014, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** diff --git a/Core/EM/CSM/thunk/BlockIo/CsmBlockIo.h b/Core/EM/CSM/thunk/BlockIo/CsmBlockIo.h new file mode 100644 index 0000000..59ce30b --- /dev/null +++ b/Core/EM/CSM/thunk/BlockIo/CsmBlockIo.h @@ -0,0 +1,277 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (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/Thunk/INT13/CsmBlockIo.h 10 12/23/11 2:12p Olegi $ +// +// $Revision: 10 $ +// +// $Date: 12/23/11 2:12p $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Modules/CSM/Generic/Thunk/INT13/CsmBlockIo.h $ +// +// 10 12/23/11 2:12p Olegi +// [TAG] EIP78921 +// [Category] Improvement +// [Description] CsmBlockIo should create device handle in BBS table +// [Files] CsmBlockIo.c +// CsmBlockIo.h +// +// 9 6/27/11 4:50p Olegi +// +// 8 1/12/10 11:50a Olegi +// Copyright message updated. +// +// 7 9/23/09 11:18a Olegi +// +// 6 8/07/09 2:46p Rameshr +// SD boot support Added. +// +// 5 10/03/07 4:42p Yakovlevs +// Removed Component Name Protocol and its Strings in NO DEBUG mode to +// save some space. +// +// 4 4/27/07 5:14p Olegi +// CSM.CHM file preparation. +// +// 3 3/13/06 2:38p Felixp +// +// 2 3/04/05 1:45p Mandal +// +// 1 2/15/05 11:00a Olegi +// Initial VSS check-in. +// +//********************************************************************** +//<AMI_FHDR_START> +// +// Name: CsmBlockIo.h +// +// Description: CSM BlockIO driver header file. +// +//<AMI_FHDR_END> +//********************************************************************** + +#ifndef _CsmBlockIo_ +#define _CsmBlockIo_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <Efi.h> +#include <Token.h> +#include <Dxe.h> +#include <PCI.h> +#include <AmiDxeLib.h> +#include <Protocol\PciIo.h> +#include <Protocol\DevicePath.h> +#include <Protocol\LegacyBios.h> +#include <Protocol\LegacyBiosExt.h> +#include <protocol\DriverBinding.h> +#include <Protocol\ComponentName.h> +#include <protocol\BlockIo.h> + +#include "CsmEdd.h" + + +// Global Variables +#if EFI_DEBUG +extern EFI_COMPONENT_NAME_PROTOCOL gBiosBlockIoComponentName; +#endif + + +// Define the I2O class code + +#define PCI_BASE_CLASS_INTELLIGENT 0x0e +#define PCI_SUB_CLASS_INTELLIGENT 0x00 + +// SD class/subclass defined in PCI.H in 4.6.3.7 +#ifndef PCI_CL_SYSTEM_PERIPHERALS +#define PCI_CL_SYSTEM_PERIPHERALS 0x08 +#endif +#ifndef PCI_CL_SYSTEM_PERIPHERALS_SCL_SD +#define PCI_CL_SYSTEM_PERIPHERALS_SCL_SD 0x05 +#endif + + +// Number of pages needed for our buffer under 1MB + +#define BLOCK_IO_BUFFER_PAGE_SIZE (((sizeof (EDD_DEVICE_ADDRESS_PACKET) + sizeof (CSM_LEGACY_DRIVE) + MAX_EDD11_XFER) / EFI_PAGE_SIZE) + 1) + + +// PROTOTYPES + +// Driver Binding Protocol functions + +EFI_STATUS +CsmBlockIoSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +CsmBlockIoStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +CsmBlockIoStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + +// Block I/O functions + +EFI_STATUS +CsmBlockIoFlushBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This + ); + +EFI_STATUS +CsmBlockIoReset ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ); + +// These prototypes aren't actually used -- they are the generic for the specific +// functions below +EFI_STATUS +CsmBlockIoReadBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN UINTN BufferSize, + OUT VOID *Buffer + ); + +EFI_STATUS +CsmBlockIoWriteBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN UINTN BufferSize, + OUT VOID *Buffer + ); + +// Specific read/write function prototypes +EFI_STATUS +Edd30CsmReadBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN UINTN BufferSize, + OUT VOID *Buffer + ); + +EFI_STATUS +Edd30CsmWriteBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN UINTN BufferSize, + OUT VOID *Buffer + ); + +EFI_STATUS +Edd11CsmReadBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN UINTN BufferSize, + OUT VOID *Buffer + ); + +EFI_STATUS +Edd11CsmWriteBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN UINTN BufferSize, + OUT VOID *Buffer + ); + +EFI_STATUS +LegacyCsmReadBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN UINTN BufferSize, + OUT VOID *Buffer + ); + +EFI_STATUS +LegacyCsmWriteBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN UINTN BufferSize, + OUT VOID *Buffer + ); + +// Local support function prototypes +BOOLEAN +InitBlockIo ( + IN CSM_BLOCK_IO_DEV *Dev + ); + +// Local function prototypes +VOID +BuildDevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL *BaseDevicePath, + IN CSM_LEGACY_DRIVE *Drive, + IN EFI_DEVICE_PATH_PROTOCOL **DevPath + ); + +EFI_DEVICE_PATH_PROTOCOL * +AppendDevicePathNode ( + IN EFI_DEVICE_PATH_PROTOCOL *DevPath, + IN EFI_DEVICE_PATH_PROTOCOL *Node + ); + +UINTN AlignAddress ( + UINTN Address + ); + +VOID ZeroMemory ( + VOID *Buffer, + UINTN Size +); + +/****** DO NOT WRITE BELOW THIS LINE *******/ +#ifdef __cplusplus +} +#endif + +#endif + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2010, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** diff --git a/Core/EM/CSM/thunk/BlockIo/CsmBlockIo.sdl b/Core/EM/CSM/thunk/BlockIo/CsmBlockIo.sdl new file mode 100644 index 0000000..ac17f94 --- /dev/null +++ b/Core/EM/CSM/thunk/BlockIo/CsmBlockIo.sdl @@ -0,0 +1,25 @@ +TOKEN + Name = "CsmBlockIo_SUPPORT" + Value = "1" + Help = "Main switch to enable CsmBlockIo support in Project" + TokenType = Boolean + TargetMAK = Yes + Master = Yes +End + +PATH + Name = "CSMBLOCKIO_DIR" + Help = "CSM BLOCK I/O source directory" +End + +MODULE + Help = "Includes CsmBlockIo.mak to Project" + File = "biosblkio.mak" +End + +ELINK + Name = "$(BUILD_DIR)\biosblkio.ffs" + Parent = "FV_MAIN" + InvokeOrder = AfterParent +End + diff --git a/Core/EM/CSM/thunk/BlockIo/CsmEdd.h b/Core/EM/CSM/thunk/BlockIo/CsmEdd.h new file mode 100644 index 0000000..0c9ff4c --- /dev/null +++ b/Core/EM/CSM/thunk/BlockIo/CsmEdd.h @@ -0,0 +1,407 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (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/Thunk/INT13/CsmEdd.h 7 1/12/10 11:50a Olegi $ +// +// $Revision: 7 $ +// +// $Date: 1/12/10 11:50a $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Modules/CSM/Generic/Thunk/INT13/CsmEdd.h $ +// +// 7 1/12/10 11:50a Olegi +// Copyright message updated. +// +// 6 4/27/07 5:14p Olegi +// CSM.CHM file preparation. +// +// 5 3/13/06 2:38p Felixp +// +// 4 10/13/05 6:21p Olegi +// +// 3 4/20/05 4:54p Andriyn +// USB_DEVICE_PATH is in core now +// +// 2 3/04/05 1:45p Mandal +// +// 1 2/15/05 11:00a Olegi +// Initial VSS check-in. +// +// +//********************************************************************** +//********************************************************************** +//<AMI_FHDR_START> +// +// Name: CsmEdd.h +// +// Description: EDD support definitions file +// +//<AMI_FHDR_END> +//********************************************************************** + +#ifndef _CSM_EDD_H_ +#define _CSM_EDD_H_ + +#pragma pack(1) + +typedef struct { + UINT8 Bus; + UINT8 Device; + UINT8 Function; + UINT8 Controller; + UINT32 Reserved; +} EDD_PCI; + +typedef struct { + UINT16 Base; + UINT16 Reserved; + UINT32 Reserved2; +} EDD_LEGACY; + +typedef union { + EDD_PCI Pci; + EDD_LEGACY Legacy; +} EDD_INTERFACE_PATH; + +typedef struct { + UINT8 Master; + UINT8 Reserved[15]; +} EDD_ATA; + +typedef struct { + UINT8 Master; + UINT8 Lun; + UINT8 Reserved[14]; +} EDD_ATAPI; + +typedef struct { + UINT16 TargetId; + UINT64 Lun; + UINT8 Reserved[6]; +} EDD_SCSI; + +typedef struct { + UINT64 SerialNumber; + UINT64 Reserved; +} EDD_USB; + +typedef struct { + UINT64 Guid; + UINT64 Reserved; +} EDD_1394; + +typedef struct { + UINT64 Wwn; + UINT64 Lun; +} EDD_FIBRE; + +typedef union { + EDD_ATA Ata; + EDD_ATAPI Atapi; + EDD_SCSI Scsi; + EDD_USB Usb; + EDD_1394 FireWire; + EDD_FIBRE FibreChannel; +} EDD_DEVICE_PATH; + +typedef struct _UNKNOWN_VENDOR_DEVICE_PATH { + VENDOR_DEVICE_PATH DevicePath; + UINT8 LegacyDriveLetter; +} UNKNOWN_DEVICE_VENDOR_DEVICE_PATH; + +//typedef struct _CONTROLLER_DEVICE_PATH { +// EFI_DEVICE_PATH_PROTOCOL Header; +// UINT32 Controller; +//} CONTROLLER_DEVICE_PATH; + +//typedef struct _ATAPI_DEVICE_PATH { +// EFI_DEVICE_PATH_PROTOCOL Header; +// UINT8 Channel; +// UINT8 Device; +// UINT16 Lun; +//} ATAPI_DEVICE_PATH; + +//typedef struct _SCSI_DEVICE_PATH { +// EFI_DEVICE_PATH_PROTOCOL Header; +// UINT16 TargetId; +// UINT16 Lun; +//} SCSI_DEVICE_PATH; + +//typedef struct _FIBRE_CHANNEL_DEVICE_PATH { +// EFI_DEVICE_PATH_PROTOCOL Header; +// UINT32 Reserved; +// UINT64 WorldWideNumber; +// UINT64 Lun; +//} FIBRECHANNEL_DEVICE_PATH; + +//typedef struct _F1394_DEVICE_PATH { +// EFI_DEVICE_PATH_PROTOCOL Header; +// UINT32 Reserved; +// UINT64 _1394Guid; +//} F1394_DEVICE_PATH; +/* AndriyN : must belong to DevicePath.h +typedef struct _USB_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT8 ParentPortNumber; + UINT8 InterfaceNumber; +} USB_DEVICE_PATH; +*/ + +// Union of all possible device paths +typedef union { + EFI_DEVICE_PATH_PROTOCOL DevPath; + PCI_DEVICE_PATH Pci; +// PCCARD_DEVICE_PATH PcCard; +// MEMMAP_DEVICE_PATH MemMap; + VENDOR_DEVICE_PATH Vendor; + UNKNOWN_DEVICE_VENDOR_DEVICE_PATH UnknownVendor; + CONTROLLER_DEVICE_PATH Controller; +// ACPI_HID_DEVICE_PATH Acpi; + ACPI_HID_DEVICE_PATH Acpi; + ATAPI_DEVICE_PATH Atapi; + SCSI_DEVICE_PATH Scsi; + FIBRECHANNEL_DEVICE_PATH FibreChannel; + F1394_DEVICE_PATH F1394; + USB_DEVICE_PATH Usb; + USB_CLASS_DEVICE_PATH UsbClass; + I20_DEVICE_PATH I20; +// MAC_ADDR_DEVICE_PATH MacAddr; + IPv4_DEVICE_PATH Ipv4; + IPv6_DEVICE_PATH Ipv6; + INFINIBAND_DEVICE_PATH InfiniBand; + UART_DEVICE_PATH Uart; + HARDDRIVE_DEVICE_PATH HardDrive; + CDROM_DEVICE_PATH CD; +// FILEPATH_DEVICE_PATH FilePath; +// MEDIA_PROTOCOL_DEVICE_PATH MediaProtocol; +// BBS_BBS_DEVICE_PATH Bbs; +} EFI_DEV_PATH; + +#define HARDWARE_DEVICE_PATH 0x01 +#define HW_VENDOR_DP 0x04 +#define MESSAGING_DEVICE_PATH 0x03 +#define MSG_ATAPI_DP 0x01 +#define HW_CONTROLLER_DP 0x05 +#define MSG_SCSI_DP 0x02 +#define MSG_1394_DP 0x04 +#define MSG_FIBRECHANNEL_DP 0x03 + +typedef struct { + UINT16 StructureSize; + UINT16 Flags; + UINT32 MaxCylinders; + UINT32 MaxHeads; + UINT32 SectorsPerTrack; + UINT64 PhysicalSectors; + UINT16 BytesPerSector; + UINT32 FDPT; + UINT16 Key; + UINT8 DevicePathLength; + UINT8 Reserved1; + UINT16 Reserved2; + CHAR8 HostBusType[4]; + CHAR8 InterfaceType[8]; + EDD_INTERFACE_PATH InterfacePath; + EDD_DEVICE_PATH DevicePath; + UINT8 Reserved3; + UINT8 Checksum; +} EDD_DRIVE_PARAMETERS; + +// Flag definitions for above +#define EDD_GEOMETRY_VALID 0x02 +#define EDD_DEVICE_REMOVABLE 0x04 +#define EDD_WRITE_VERIFY_SUPPORTED 0x08 +#define EDD_DEVICE_CHANGE 0x10 +#define EDD_DEVICE_LOCKABLE 0x20 + +// For WIN98 limitation +#define EDD_DEVICE_GEOMETRY_MAX 0x40 + + +//<AMI_SHDR_START> +//---------------------------------------------------------------------------- +// Name: EDD_DEVICE_ADDRESS_PACKET +// +// Description: Device address packet used during EDD data transfers +// +// Fields: +// PacketSizeInBytes UINT8 Packet size in bytes +// Zero UINT8 +// NumberOfBlocks UINT8 # of blocks to transfer +// Zero2 UINT8 +// SegOffset UINT32 Data address below 1MB +// LBA UINT64 Device Logical Block Address +// TransferBuffer UINT64 Transfer Buffer +// ExtendedBlockCount UINT32 Transferred blocks counter +// Zero3 UINT32 +// +//---------------------------------------------------------------------------- +//<AMI_SHDR_END> + +typedef struct { + UINT8 PacketSizeInBytes; // 0x18 + UINT8 Zero; + UINT8 NumberOfBlocks; // Max 0x7f + UINT8 Zero2; + UINT32 SegOffset; + UINT64 LBA; + UINT64 TransferBuffer; + UINT32 ExtendedBlockCount; // Max 0xffffffff + UINT32 Zero3; +} EDD_DEVICE_ADDRESS_PACKET; + +#define UNKNOWN_DEVICE_GUID \ + { 0xcf31fac5, 0xc24e, 0x11d2, 0x85, 0xf3, 0x0, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b } + +#define EDD_VERSION_30 0x30 + +// Int 13 Error Messages +#define ERR_PASS 0x00 +#define ERR_WRITE_PROTECTED 0x03 +#define ERR_SECTOR_NOT_FOUND 0x04 +#define ERR_RESET_FAILED 0x05 +#define ERR_DISK_CHANGED 0x06 +#define ERR_DRIVE_DOES_NOT_EXIST 0x07 +#define ERR_DMA_ERROR 0x08 +#define ERR_DATA_BOUNADRY_ERROR 0x09 +#define ERR_BAD_SECTOR 0x0a +#define ERR_BAD_TRACK 0x0b +#define ERR_MEDIA_TYPE_NOT_FOUND 0x0c +#define ERR_INVALID_FORMAT 0x0d +#define ERR_ECC_ERROR 0x10 +#define ERR_ECC_CORRECTED_ERROR 0x11 +#define ERR_HARD_DRIVE_FAILURE 0x20 +#define ERR_SEEK_FAILED 0x40 +#define ERR_DRIVE_TIMEOUT 0x80 +#define ERR_DRIVE_NOT_READY 0xaa +#define ERR_UNDEFINED_ERROR 0xbb +#define ERR_WRITE_FAULT 0xcc +#define ERR_SENSE_FAILED 0xff + +#define MAX_EDD11_XFER 0xfe00 + +// PCI classes not defined in PCI.h +#define PCI_BASE_CLASS_INTELLIGENT 0x0e +#define PCI_SUB_CLASS_INTELLIGENT 0x00 + +#define EFI_SEGMENT(_Adr) (UINT16)((UINT16) (((UINTN)(_Adr)) >> 4) & 0xf000) +#define EFI_OFFSET(_Adr) (UINT16)(((UINT16)((UINTN)_Adr)) & 0xffff) + +#pragma pack() + +// Local data structures + +//<AMI_SHDR_START> +//---------------------------------------------------------------------------- +// Name: CSM_LEGACY_DRIVE +// +// Description: Hard drive data structure +// +// Fields: +// Letter CHAR8 Drive letter +// Number UINT8 INT13 drive handle +// EddVersion UINT8 EDD version supported by the drive +// ExtendedInt13 BOOLEAN Extended INT13 support status +// DriveLockingAndEjecting BOOLEAN Locking/Ejecting support +// Edd BOOLEAN EDD support status +// Extensions64Bit BOOLEAN 64 bit extension support +// ParametersValid BOOLEAN Valid parameters (Parameters field) indicator +// ErrorCode UINT8 Error code field +// FdptPointer VOID* Pointer to FDPT +// Floppy BOOLEAN Device-is-a-floppy indicator +// AtapiFloppy BOOLEAN Device-is-an-ATAPI-floppy indicator +// MaxHead UINT8 Number of heads +// MaxSector UINT8 Number of sectors +// MaxCylinder UINT16 Number of cylinders +// Pad UINT16 +// Parameters EDD_DRIVE_PARAMETERS EDD drive parameters +// +//---------------------------------------------------------------------------- +//<AMI_SHDR_END> + +typedef struct { + CHAR8 Letter; + UINT8 Number; + UINT8 EddVersion; + BOOLEAN ExtendedInt13; + BOOLEAN DriveLockingAndEjecting; + BOOLEAN Edd; + BOOLEAN Extensions64Bit; + BOOLEAN ParametersValid; + UINT8 ErrorCode; + VOID *FdptPointer; + BOOLEAN Floppy; + BOOLEAN AtapiFloppy; + UINT8 MaxHead; + UINT8 MaxSector; + UINT16 MaxCylinder; + UINT16 Pad; + EDD_DRIVE_PARAMETERS Parameters; +} CSM_LEGACY_DRIVE; + + +//<AMI_SHDR_START> +//---------------------------------------------------------------------------- +// Name: CSM_BLOCK_IO_DEV +// +// Description: CSM BlockIo device properies +// +// Fields: +// BlockIo EFI_BLOCK_IO_PROTOCOL BlockIo protocol instance +// Handle EFI_HANDLE EFI device handle +// ControllerHandle EFI_HANDLE EFI controller handle +// BlockMedia EFI_BLOCK_IO_MEDIA BlockIo device media +// DevicePath EFI_DEVICE_PATH_PROTOCOL* Device path +// PciIo EFI_PCI_IO_PROTOCOL* Device PciIo +// LegacyBios EFI_LEGACY_BIOS_PROTOCOL* Legacy Bios instance pointer +// Drive CSM_LEGACY_DRIVE Drive data pointer +// HwInt UINT8 Hardware interrupt used by this device +// HwIntHandler UINT32 Storage for the original HW interrupt +// +// Referrals: CSM_LEGACY_DRIVE +// +//---------------------------------------------------------------------------- +//<AMI_SHDR_END> + +typedef struct { + EFI_BLOCK_IO_PROTOCOL BlockIo; + EFI_HANDLE Handle; + EFI_HANDLE ControllerHandle; + EFI_BLOCK_IO_MEDIA BlockMedia; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_PCI_IO_PROTOCOL *PciIo; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; + CSM_LEGACY_DRIVE Drive; + UINT8 HwInt; + UINT32 HwIntHandler; +} CSM_BLOCK_IO_DEV; + +#endif + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2010, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** diff --git a/Core/EM/CSM/thunk/BlockIo/CsmInt13.c b/Core/EM/CSM/thunk/BlockIo/CsmInt13.c new file mode 100644 index 0000000..8e3195e --- /dev/null +++ b/Core/EM/CSM/thunk/BlockIo/CsmInt13.c @@ -0,0 +1,1525 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (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/Thunk/INT13/CsmInt13.c 17 12/23/13 3:14p Olegi $ +// +// $Revision: 17 $ +// +// $Date: 12/23/13 3:14p $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Modules/CSM/Generic/Thunk/INT13/CsmInt13.c $ +// +// 17 12/23/13 3:14p Olegi +// EIP148138: use AMI_BLOCKIO_WRITE_PROTECTION_PROTOCOL instead of +// EFI_MBR_WRITE_PROTECTION_PROTOCOL +// +// 16 12/23/13 10:22a Olegi +// EIP148123: CSM includes file which name has been changed +// +// 15 7/01/13 5:56a Kapilporwal +// [TAG] EIP125560 +// [Category] Improvement +// [Description] Please support Boot Sector Virus Protection for CSM +// Disabled Mode +// [Files] VirusProtect.c, VirusProtect.dxs, AhciBus.c, +// AhciController.c, CsmBlockIo.c, CsmInt13.c, Ata.c, IdeBus.c, +// SdioBlkIo.c, SdioDriver.c, efiusbmass.c +// +// 14 3/09/12 3:22a Deepthins +// [TAG] EIP73940 +// [Category] Improvement +// [Description] CSM BlockIo functions, ReadBlock and WriteBlock should +// return EFI_INVALID_PARAMETER if alignment is not proper. +// [Files] CsmInt13.c +// +// 13 5/27/11 5:47a Rameshr +// [TAG]- EIP 58687 +// [Category]-IMPROVEMENT +// [Description]- Update implementation of EFI_BLOCK_IO_PROTOCOL as +// described in UEFI specification v 2.3.1, page 12.8 +// [Files]- CsmInt13.c +// +// 12 1/12/10 11:50a Olegi +// Copyright message updated. +// +// 11 5/09/08 10:37a Olegi +// Low memory segment is normalized before INT13 execution. +// +// 10 4/27/07 5:14p Olegi +// CSM.CHM file preparation. +// +// 9 12/07/06 4:00p Olegi +// +// 8 3/13/06 2:38p Felixp +// +// 7 10/13/05 6:20p Olegi +// Added HW interrupt handling. +// +// 6 9/06/05 11:55a Olegi +// +// 5 6/26/05 7:19a Olegi +// Actual drive parameters size is used while copying extended drive +// parameters data. +// +// 4 3/04/05 1:43p Mandal +// +// 3 3/02/05 8:24a Olegi +// +// 2 2/21/05 9:33a Olegi +// +// 1 2/15/05 10:59a Olegi +// Initial VSS check-in. +// +// +//********************************************************************** + +//********************************************************************** +//<AMI_FHDR_START> +// +// Name: CsmInt13.c +// +// Description: CSM Block I/O module. Support module containing reset, +// flush, read and write functions. +// +//<AMI_FHDR_END> +//********************************************************************** + +#include "CsmBlockIo.h" +#if defined CORE_COMBINED_VERSION && (CORE_COMBINED_VERSION > 0x4028E) +#include <Protocol\AmiBlockIoWriteProtection.h> +extern AMI_BLOCKIO_WRITE_PROTECTION_PROTOCOL *gBlockIoWriteProtectionProtocol; +#endif + +//extern EFI_BOOT_SERVICES *pBS; +extern EFI_GUID gEfiBlockIoProtocolGuid; + +// Global variables + +// Packet buffer under 1 MB for all version EDD calls +extern EDD_DEVICE_ADDRESS_PACKET *mEDDPacketBuffer; + +// This is a buffer for INT 13h func 48 information +extern CSM_LEGACY_DRIVE *mDriveParameterBuffer; + +// EDD 1.1 transfer buffer +extern VOID *mEDDTransferBuffer; + +// Local function prototypes +BOOLEAN +GetInt13DeviceParameters ( + CSM_BLOCK_IO_DEV *CsmBlockIoDev, + IN CSM_LEGACY_DRIVE *Drive +); + +BOOLEAN +GetInt13Extensions ( + CSM_BLOCK_IO_DEV *CsmBlockIoDev, + IN CSM_LEGACY_DRIVE *Drive +); + +BOOLEAN +GetDriveParameters ( + CSM_BLOCK_IO_DEV *CsmBlockIoDev, + IN CSM_LEGACY_DRIVE *Drive +); + +VOID +PatchHwInterrupt( + CSM_BLOCK_IO_DEV *CsmBlockIoDev +); + +VOID +RestoreHwInterrupt( + CSM_BLOCK_IO_DEV *CsmBlockIoDev +); + +UINT32 gTempHwIntSav; + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: InitBlockIo +// +// Description: Initializes BlockIo protocol for a given device +// +// Input: Device to initialize +// +// Output: TRUE initialization succeeded, FALSE otherwise +// +// Referrals: CSM_BLOCK_IO_DEV, GetInt13DeviceParameters, GetInt13Extensions +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +BOOLEAN +InitBlockIo ( + IN CSM_BLOCK_IO_DEV *Dev +) +{ + EFI_BLOCK_IO_PROTOCOL *BlockIo; + EFI_BLOCK_IO_MEDIA *BlockMedia; + CSM_LEGACY_DRIVE *Drive; + + BlockIo = &Dev->BlockIo; + BlockIo->Media = &Dev->BlockMedia; + BlockMedia = BlockIo->Media; + Drive = &Dev->Drive; + +#if defined CORE_COMBINED_VERSION && CORE_COMBINED_VERSION > 0x4028a + if(pST->Hdr.Revision >= 0x0002001F) { + BlockIo->Revision = EFI_BLOCK_IO_PROTOCOL_REVISION3; + } else { + BlockIo->Revision = 1; + } +#else + BlockIo->Revision = 1; +#endif + + if (GetInt13DeviceParameters (Dev, Drive)) { + if (GetInt13Extensions (Dev, Drive)) { + BlockMedia->LastBlock = (EFI_LBA)Drive->Parameters.PhysicalSectors - 1; + BlockMedia->BlockSize = (UINT32)Drive->Parameters.BytesPerSector; + + if ((Drive->Parameters.Flags & EDD_DEVICE_REMOVABLE) == EDD_DEVICE_REMOVABLE) { + BlockMedia->RemovableMedia = TRUE; + } + + } else { + // No extensions, use Legacy parameters. + BlockMedia->BlockSize = 512; + BlockMedia->LastBlock = (Drive->MaxHead + 1) * Drive->MaxSector * (Drive->MaxCylinder + 1) - 1; + } + +// TRACE((-1," BlockSize = %d LastBlock = %d\n", BlockMedia->BlockSize, BlockMedia->LastBlock)); + + BlockMedia->LogicalPartition = FALSE; + BlockMedia->WriteCaching = FALSE; + + BlockMedia->ReadOnly = FALSE; // Set for removable media in case no media present + BlockMedia->MediaPresent = TRUE; // ditto + + BlockIo->Reset = CsmBlockIoReset; + BlockIo->FlushBlocks = CsmBlockIoFlushBlocks; + + // Need logic here to test for EDD and set read/write functions if so + if (!Drive->ExtendedInt13) { + // No Int 13 extensions, use Legacy functions + BlockIo->ReadBlocks = LegacyCsmReadBlocks; + BlockIo->WriteBlocks = LegacyCsmWriteBlocks; +/* } else if ((Drive->EddVersion == EDD_VERSION_30) && (Drive->Extensions64Bit)) { + // Use EDD 3.0 functions + BlockIo->ReadBlocks = Edd30CsmReadBlocks; + BlockIo->WriteBlocks = Edd30CsmWriteBlocks; +*/ + } else { + // Assume EDD 1.1 Read and Write functions. + BlockIo->ReadBlocks = Edd11CsmReadBlocks; + BlockIo->WriteBlocks = Edd11CsmWriteBlocks; + } + + BlockMedia->LogicalPartition = FALSE; + BlockMedia->WriteCaching = FALSE; + + // + // Check for Core Version > 4.6.5.0 + // +#if defined CORE_COMBINED_VERSION && CORE_COMBINED_VERSION > 0x4028a + + if(pST->Hdr.Revision >= 0x0002001F) { + // + // Default value set to 1 logical blocks per PhysicalBlock + // + BlockMedia->LogicalBlocksPerPhysicalBlock=1; + + // + // Default value set to 0 for Lowest Aligned LBA + // + BlockMedia->LowestAlignedLba=0; + + BlockMedia->OptimalTransferLengthGranularity=BlockMedia->BlockSize; + } + +#endif + + return TRUE; + } + return FALSE; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: GetInt13DeviceParameters +// +// Description: Get hard drive parameters using INT13 function 8 +// +// Input: BlockIo device, Drive +// +// Output: TRUE if operation is successful, FALSE otherwise +// +// Referrals: CSM_BLOCK_IO_DEV, CSM_LEGACY_DRIVE +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +BOOLEAN +GetInt13DeviceParameters ( + CSM_BLOCK_IO_DEV *CsmBlockIoDev, + IN CSM_LEGACY_DRIVE *Drive +) +{ + BOOLEAN CarryFlag; + UINT16 Cylinder; + EFI_IA32_REGISTER_SET Regs; + + Regs.H.AH = 0x08; + Regs.H.DL = Drive->Number; + PatchHwInterrupt(CsmBlockIoDev); + CsmBlockIoDev->LegacyBios->Int86 (CsmBlockIoDev->LegacyBios, 0x13, &Regs); + RestoreHwInterrupt(CsmBlockIoDev); + CarryFlag = (BOOLEAN)Regs.X.Flags.CF; +// TRACE((-1," GetInt13DeviceParameters: INT 13 08 DL=%02x : CF=%d AH=%02x\n", Drive->Number, CarryFlag, Regs.H.AH)); + + if (CarryFlag || Regs.H.AH != 0x00) { + Drive->ErrorCode = Regs.H.AH; + return FALSE; + } + + if (Drive->Floppy) { + if (Regs.H.BL == 0x10) { + Drive->AtapiFloppy = TRUE; + } else { + Drive->MaxHead = Regs.H.DH; + Drive->MaxSector = Regs.H.CL; + Drive->MaxCylinder = Regs.H.CH; + if (Drive->MaxSector == 0) { + return FALSE; + } + } + } else { + Drive->MaxHead = (UINT8)(Regs.H.DH & 0x3f); + Cylinder = (UINT16)(((UINT16)Regs.H.DH & 0xc0) << 4); + Cylinder |= (UINT16)(((UINT16)Regs.H.CL & 0xc0) << 2); + Drive->MaxCylinder = (UINT16)(Cylinder + Regs.H.CH); + Drive->MaxSector = (UINT8)(Regs.H.CL & 0x3f); + } + return TRUE; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: GetInt13Extensions +// +// Description: Executes INT13 func 41 to check EDD extensions +// +// Input: BlockIo device, Drive +// +// Output: TRUE if operation is successful, FALSE otherwise +// +// Referrals: CSM_BLOCK_IO_DEV, CSM_LEGACY_DRIVE +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +BOOLEAN +GetInt13Extensions( + CSM_BLOCK_IO_DEV *CsmBlockIoDev, + IN CSM_LEGACY_DRIVE *Drive +) +{ + BOOLEAN CarryFlag; + EFI_IA32_REGISTER_SET Regs; + + Regs.H.AH = 0x41; + Regs.X.BX = 0x55aa; + Regs.H.DL = Drive->Number; + PatchHwInterrupt(CsmBlockIoDev); + CsmBlockIoDev->LegacyBios->Int86 (CsmBlockIoDev->LegacyBios, 0x13, &Regs); + RestoreHwInterrupt(CsmBlockIoDev); + CarryFlag = (BOOLEAN)Regs.X.Flags.CF; +// TRACE((-1, " GetInt13Extensions: INT 13 41 DL=%02x : CF=%d BX=%04x\n", Drive->Number, CarryFlag, Regs.X.BX)); + + if (CarryFlag || Regs.X.BX != 0xaa55) { + Drive->ExtendedInt13 = FALSE; + Drive->DriveLockingAndEjecting = FALSE; + Drive->Edd = FALSE; + return(FALSE); + } + Drive->EddVersion = Regs.H.AH; + Drive->ExtendedInt13 = (BOOLEAN)((Regs.X.CX & 0x01) == 0x01); + Drive->DriveLockingAndEjecting = (BOOLEAN)((Regs.X.CX & 0x02) == 0x02); + Drive->Edd = (BOOLEAN)((Regs.X.CX & 0x04) == 0x04); + Drive->Extensions64Bit = (BOOLEAN)(Regs.X.CX & 0x08); + + Drive->ParametersValid = (UINT8)GetDriveParameters(CsmBlockIoDev, Drive); + return TRUE; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: GetDriveParameters +// +// Description: Executes INT13 function 48 to get hard disk parameters +// +// Input: BlockIo device, Drive +// +// Output: TRUE if operation is successful, FALSE otherwise +// +// Referrals: CSM_BLOCK_IO_DEV, CSM_LEGACY_DRIVE +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +BOOLEAN +GetDriveParameters( + CSM_BLOCK_IO_DEV *CsmBlockIoDev, + IN CSM_LEGACY_DRIVE *Drive +) +{ + BOOLEAN CarryFlag; + EFI_IA32_REGISTER_SET Regs; + UINTN PointerMath; + UINT8 Temp; + UINT8 FloppyTable [] = { + 1, 9, 79, // Type 3 -- 720 Kb + 1, 18, 79, // Type 4 -- 1.44 Mb + 0, 1, 0, // No type 5 + 1, 36, 79, // Type 6 -- 2.88 Mb + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 1, 9, 39, // Type C -- 360 Kb + 1, 15, 79 // Type D -- 1.2 Mb + }; + + Regs.H.AH = 0x48; + Regs.H.DL = Drive->Number; + + // Get Int13 Parameters + mDriveParameterBuffer->Parameters.StructureSize = sizeof(EDD_DRIVE_PARAMETERS); + Regs.X.DS = EFI_SEGMENT(&mDriveParameterBuffer->Parameters); + Regs.X.SI = EFI_OFFSET(&mDriveParameterBuffer->Parameters); + + PatchHwInterrupt(CsmBlockIoDev); + CsmBlockIoDev->LegacyBios->Int86 (CsmBlockIoDev->LegacyBios, 0x13, &Regs); + CarryFlag = (BOOLEAN)Regs.X.Flags.CF; + + if (CarryFlag || Regs.H.AH != 0x00) { + RestoreHwInterrupt(CsmBlockIoDev); + Drive->ErrorCode = Regs.H.AH; + pBS->SetMem(&Drive->Parameters, sizeof(Drive->Parameters), 0xaf); + return FALSE; + } + +// Copy parameters into real mode buffer + pBS->SetMem (&Drive->Parameters, sizeof(Drive->Parameters), 0); + pBS->CopyMem ( + &Drive->Parameters, + &mDriveParameterBuffer->Parameters, + mDriveParameterBuffer->Parameters.StructureSize // updated by int 13 call + ); + + if (Drive->AtapiFloppy) { + + // Get Media type + Regs.H.AH = 0x20; + Regs.H.DL = Drive->Number; + CsmBlockIoDev->LegacyBios->Int86 (CsmBlockIoDev->LegacyBios, 0x13, &Regs); + CarryFlag = (BOOLEAN)Regs.X.Flags.CF; + if (CarryFlag) { + + // Unknown or no media present + if ((Drive->Parameters.Flags & EDD_GEOMETRY_VALID) == EDD_GEOMETRY_VALID) { + Drive->MaxHead = (UINT8)(Drive->Parameters.MaxHeads - 1); + Drive->MaxSector = (UINT8)Drive->Parameters.SectorsPerTrack; + ASSERT(Drive->MaxSector != 0); + Drive->MaxCylinder = (UINT16)(Drive->Parameters.MaxCylinders - 1); + } else { + Drive->MaxHead = 0; + Drive->MaxSector = 1; + Drive->MaxCylinder = 0; + } + + } else { + + // Media present -- get parameters + Drive->MaxHead = 0; + Drive->MaxSector = 1; + Drive->MaxCylinder = 0; // Assume unknown media + if(Regs.H.AL != 10) { + if((Regs.H.AL >= 3) && (Regs.H.AL <= 0xd)) { + Temp = (Regs.H.AL - 3) * 3; // First drive type is 3 + Drive->MaxHead = FloppyTable[Temp]; + Drive->MaxSector = FloppyTable[Temp+1]; + Drive->MaxCylinder = FloppyTable[Temp+2]; + } + } else { + if ((Drive->Parameters.Flags & EDD_GEOMETRY_VALID) == EDD_GEOMETRY_VALID) { + Drive->MaxHead = (UINT8)(Drive->Parameters.MaxHeads - 1); + Drive->MaxSector = (UINT8)Drive->Parameters.SectorsPerTrack; + ASSERT(Drive->MaxSector != 0); + Drive->MaxCylinder = (UINT16)(Drive->Parameters.MaxCylinders - 1); + } else { + Drive->MaxHead = 0; + Drive->MaxSector = 1; + Drive->MaxCylinder = 0; + } + } + } + Drive->Parameters.PhysicalSectors = (Drive->MaxHead + 1) * Drive->MaxSector * (Drive->MaxCylinder + 1); + Drive->Parameters.BytesPerSector = 512; + } + + // This data comes from the BIOS so it may not allways be valid + // since the BIOS may reuse this buffer for future accesses + PointerMath = EFI_SEGMENT(Drive->Parameters.FDPT) << 4; + PointerMath += EFI_OFFSET(Drive->Parameters.FDPT); + Drive->FdptPointer = (VOID *)PointerMath; + + RestoreHwInterrupt(CsmBlockIoDev); + + return TRUE; +} + +// BLOCK I/O FUNCTIONS + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: CsmBlockIoFlushBlocks +// +// Description: BlockIo protocol function that flushes data onto the device +// +// Input: Instance of the EFI_BLOCK_IO_PROTOCOL +// +// Output: Status of the operation +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +CsmBlockIoFlushBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This + ) +{ + return EFI_SUCCESS; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: CsmBlockIoFlushBlocks +// +// Description: BlockIo protocol function that resets the device +// +// Input: +// Instance of the EFI_BLOCK_IO_PROTOCOL +// ExtendedVerification request +// +// Output: Status of the operation +// +// Referrals: CSM_BLOCK_IO_DEV, EFI_IA32_REGISTER_SET +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +CsmBlockIoReset ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +{ + CSM_BLOCK_IO_DEV *CsmBlockIoDev; + EFI_IA32_REGISTER_SET Regs; + BOOLEAN CarryFlag; + EFI_STATUS Status = EFI_SUCCESS; + + CsmBlockIoDev = (CSM_BLOCK_IO_DEV *) This; + + PatchHwInterrupt(CsmBlockIoDev); + + Regs.H.AH = 0x00; + Regs.H.DL = CsmBlockIoDev->Drive.Number; + CsmBlockIoDev->LegacyBios->Int86 (CsmBlockIoDev->LegacyBios, 0x13, &Regs); + CarryFlag = (BOOLEAN)Regs.X.Flags.CF; + +// TRACE((-1, " CsmBlockIoReset: INT 13 00 DL=%02x : CF=%d AH=%02x\n", CsmBlockIoDev->Drive.Number, CarryFlag, Regs.H.AH)); + + if (CarryFlag) { + if (Regs.H.AL == ERR_RESET_FAILED) { + Regs.H.AH = 0x00; + Regs.H.DL = CsmBlockIoDev->Drive.Number; + CsmBlockIoDev->LegacyBios->Int86 (CsmBlockIoDev->LegacyBios, 0x13, &Regs); + CarryFlag = (BOOLEAN)Regs.X.Flags.CF; + +// TRACE((-1, "CsmBlockIoReset: INT 13 00 DL=%02x : CF=%d AH=%02x\n", CsmBlockIoDev->Drive.Number, CarryFlag, Regs.H.AH)); + + if (CarryFlag) { + CsmBlockIoDev->Drive.ErrorCode = Regs.H.AH; + Status = EFI_DEVICE_ERROR; + } + } + } + + RestoreHwInterrupt(CsmBlockIoDev); + + return Status; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: Edd30CsmReadBlocks +// +// Description: Read device using EDD3.0 read function +// +// Input: BlockIo protocol instance, Media ID, read data buffer +// +// Output: Status of the operation +// +// Referrals: EFI_LBA +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +Edd30CsmReadBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +{ + EFI_BLOCK_IO_MEDIA *Media; + CSM_BLOCK_IO_DEV *CsmBlockIoDev; + EDD_DEVICE_ADDRESS_PACKET *AddressPacket; // I exist only for readability + EFI_IA32_REGISTER_SET Regs; + UINT64 TransferBuffer; + UINTN NumberOfBlocks; + UINTN TransferByteSize; + UINTN BlockSize; + CSM_LEGACY_DRIVE *Drive; + BOOLEAN CarryFlag; + UINTN MaxTransferBlocks; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + EFI_STATUS Status = EFI_SUCCESS; + + Media = This->Media; + BlockSize = Media->BlockSize; + +// Check for error conditions + if (MediaId != Media->MediaId) return EFI_MEDIA_CHANGED; + if (LBA > Media->LastBlock) return EFI_INVALID_PARAMETER; + if ((LBA + (BufferSize / BlockSize) - 1) > Media->LastBlock) return EFI_INVALID_PARAMETER; + if (BufferSize % BlockSize != 0) return EFI_BAD_BUFFER_SIZE; + if (Buffer == NULL) return EFI_INVALID_PARAMETER; + if (BufferSize == 0) return EFI_SUCCESS; + +// CsmBlockIoDev = ((CSM_BLOCK_IO_DEV *) ((CHAR8 *)(This) - (CHAR8 *) &(((CSM_BLOCK_IO_DEV *) 0)->BlockIo))); + CsmBlockIoDev = (CSM_BLOCK_IO_DEV *) This; + AddressPacket = mEDDPacketBuffer; + + MaxTransferBlocks = MAX_EDD11_XFER/BlockSize; + + TransferBuffer = (UINT64)Buffer; + + PatchHwInterrupt(CsmBlockIoDev); + + while (BufferSize) { + NumberOfBlocks = BufferSize/BlockSize; + NumberOfBlocks = NumberOfBlocks > MaxTransferBlocks ? MaxTransferBlocks : NumberOfBlocks; // Max transfer MaxTransferBlocks + + AddressPacket->PacketSizeInBytes = sizeof(EDD_DEVICE_ADDRESS_PACKET); + AddressPacket->Zero = 0; + AddressPacket->NumberOfBlocks = (UINT8)NumberOfBlocks; + AddressPacket->Zero2 = 0; + AddressPacket->SegOffset = 0xffffffff; + AddressPacket->LBA = (UINT64)LBA; + AddressPacket->TransferBuffer = TransferBuffer; + + Regs.H.AH = 0x42; + Regs.H.DL = CsmBlockIoDev->Drive.Number; + Regs.X.SI = EFI_OFFSET(AddressPacket); + Regs.X.DS = EFI_SEGMENT(AddressPacket); + + CsmBlockIoDev->LegacyBios->Int86 (CsmBlockIoDev->LegacyBios, 0x13, &Regs); + CarryFlag = (BOOLEAN)Regs.X.Flags.CF; + +// TRACE((-1, " Edd30CsmReadBlocks: INT 13 42 DL=%02x : CF=%d AH=%02x\n", CsmBlockIoDev->Drive.Number, CarryFlag, Regs.H.AH)); + + Media->MediaPresent = TRUE; + if (CarryFlag) { + // If we have a carry, figure out the error. + CsmBlockIoDev->Drive.ErrorCode = Regs.H.AH; + if (CsmBlockIoDev->Drive.ErrorCode == ERR_DISK_CHANGED) { + Media->MediaId++; + Drive = &CsmBlockIoDev->Drive; + if (GetInt13DeviceParameters(CsmBlockIoDev, Drive)) { + if (GetInt13Extensions (CsmBlockIoDev, Drive)) { + Media->LastBlock = (EFI_LBA)Drive->Parameters.PhysicalSectors - 1; + Media->BlockSize = (UINT32)Drive->Parameters.BytesPerSector; + } else { + ASSERT(FALSE); + } + Media->ReadOnly = FALSE; + pBS->HandleProtocol(CsmBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, (VOID **)&BlockIo); + pBS->ReinstallProtocolInterface (CsmBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, BlockIo, BlockIo); + Status = EFI_MEDIA_CHANGED; + goto Exit; + } + } + + if (Media->RemovableMedia) { + Media->MediaPresent = FALSE; + } + + Status = EFI_DEVICE_ERROR; + goto Exit; + } + + TransferByteSize = NumberOfBlocks * BlockSize; + BufferSize = BufferSize - TransferByteSize; + TransferBuffer += TransferByteSize; + LBA += NumberOfBlocks; + } +Exit: + RestoreHwInterrupt(CsmBlockIoDev); + + return Status; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: Edd30CsmWriteBlocks +// +// Description: Write device using EDD3.0 write function +// +// Input: BlockIo protocol instance, Media ID, write data buffer +// +// Output: Status of the operation +// +// Referrals: EFI_LBA +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +Edd30CsmWriteBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +{ + EFI_BLOCK_IO_MEDIA *Media; + CSM_BLOCK_IO_DEV *CsmBlockIoDev; + EDD_DEVICE_ADDRESS_PACKET *AddressPacket; + EFI_IA32_REGISTER_SET Regs; + UINT64 TransferBuffer; + UINTN NumberOfBlocks; + UINTN TransferByteSize; + UINTN BlockSize; + CSM_LEGACY_DRIVE *Drive; + BOOLEAN CarryFlag; + UINTN MaxTransferBlocks; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + EFI_STATUS Status = EFI_SUCCESS; + + Media = This->Media; + BlockSize = Media->BlockSize; + + if (MediaId != Media->MediaId) return EFI_MEDIA_CHANGED; + if (LBA > Media->LastBlock) return EFI_INVALID_PARAMETER; + if ((LBA + (BufferSize / BlockSize) - 1) > Media->LastBlock) return EFI_INVALID_PARAMETER; + if (BufferSize % BlockSize != 0) return EFI_BAD_BUFFER_SIZE; + if (Buffer == NULL) return EFI_INVALID_PARAMETER; + if (BufferSize == 0) return EFI_SUCCESS; + + CsmBlockIoDev = (CSM_BLOCK_IO_DEV *) This; + AddressPacket = mEDDPacketBuffer; + + MaxTransferBlocks = MAX_EDD11_XFER/BlockSize; + + PatchHwInterrupt(CsmBlockIoDev); + + TransferBuffer = (UINT64)Buffer; + while (BufferSize) { + NumberOfBlocks = BufferSize/BlockSize; + NumberOfBlocks = NumberOfBlocks > MaxTransferBlocks ? MaxTransferBlocks : NumberOfBlocks; // Max transfer MaxTransferBlocks + AddressPacket->PacketSizeInBytes = sizeof(EDD_DEVICE_ADDRESS_PACKET); + AddressPacket->Zero = 0; + AddressPacket->NumberOfBlocks = (UINT8)NumberOfBlocks; + AddressPacket->Zero2 = 0; + AddressPacket->SegOffset = 0xffffffff; + AddressPacket->LBA = (UINT64)LBA; + AddressPacket->TransferBuffer = TransferBuffer; + + Regs.H.AH = 0x43; + Regs.H.AL = 0x00; // Write Verify Off + Regs.H.DL = (UINT8)(CsmBlockIoDev->Drive.Number); + Regs.X.SI = EFI_OFFSET(AddressPacket); + Regs.X.DS = EFI_SEGMENT(AddressPacket); + + CsmBlockIoDev->LegacyBios->Int86 (CsmBlockIoDev->LegacyBios, 0x13, &Regs); + CarryFlag = (BOOLEAN)Regs.X.Flags.CF; + +// TRACE((-1, " Edd30CsmWriteBlocks: INT 13 43 DL=%02x : CF=%d AH=%02x\n", CsmBlockIoDev->Drive.Number, CarryFlag, Regs.H.AH)); + + Media->MediaPresent = TRUE; + if (CarryFlag) { + // If we have a carry, figure out the error. + CsmBlockIoDev->Drive.ErrorCode = Regs.H.AH; + if (CsmBlockIoDev->Drive.ErrorCode == ERR_DISK_CHANGED) { + Media->MediaId++; + Drive = &CsmBlockIoDev->Drive; + if (GetInt13DeviceParameters(CsmBlockIoDev, Drive)) { + if (GetInt13Extensions (CsmBlockIoDev, Drive)) { + Media->LastBlock = (EFI_LBA)Drive->Parameters.PhysicalSectors - 1; + Media->BlockSize = (UINT32)Drive->Parameters.BytesPerSector; + } else { + ASSERT(FALSE); + } + Media->ReadOnly = FALSE; + pBS->HandleProtocol(CsmBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, (VOID **)&BlockIo); + pBS->ReinstallProtocolInterface (CsmBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, BlockIo, BlockIo); + Status = EFI_MEDIA_CHANGED; + goto Exit; + } + } else if (CsmBlockIoDev->Drive.ErrorCode == ERR_WRITE_PROTECTED) { + Media->ReadOnly = TRUE; + return EFI_WRITE_PROTECTED; + } + + if (Media->RemovableMedia) { + Media->MediaPresent = FALSE; + } + Status = EFI_DEVICE_ERROR; + goto Exit; + } + + Media->ReadOnly = FALSE; + TransferByteSize = NumberOfBlocks * BlockSize; + BufferSize = BufferSize - TransferByteSize; + TransferBuffer += TransferByteSize; + LBA += NumberOfBlocks; + } +Exit: + RestoreHwInterrupt(CsmBlockIoDev); + return Status; +} + + +// Older read/write methods +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: Edd11CsmReadBlocks +// +// Description: Read device using EDD1.1 read function +// +// Input: BlockIo protocol instance, Media ID, read data buffer +// +// Output: Status of the operation +// +// Referrals: EFI_LBA +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +Edd11CsmReadBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +{ + EFI_BLOCK_IO_MEDIA *Media; + CSM_BLOCK_IO_DEV *CsmBlockIoDev; + EDD_DEVICE_ADDRESS_PACKET *AddressPacket; + EFI_IA32_REGISTER_SET Regs; + UINT64 TransferBuffer; + UINTN NumberOfBlocks; + UINTN TransferByteSize; + UINTN BlockSize; + CSM_LEGACY_DRIVE *Drive; + BOOLEAN CarryFlag; + UINTN MaxTransferBlocks; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + EFI_STATUS Status = EFI_SUCCESS; + UINT16 AlignedOffset; + UINT16 AlignedSegment; + UINTN BufferAddress; + + Media = This->Media; + BlockSize = Media->BlockSize; + + if (MediaId != Media->MediaId) return EFI_MEDIA_CHANGED; + if (BufferSize == 0) return EFI_SUCCESS; + if (LBA > Media->LastBlock) return EFI_INVALID_PARAMETER; + if ((LBA + (BufferSize / BlockSize) - 1) > Media->LastBlock) return EFI_INVALID_PARAMETER; + if (BufferSize % BlockSize != 0) return EFI_BAD_BUFFER_SIZE; + if (Buffer == NULL) return EFI_INVALID_PARAMETER; + + // + // If IoAlign values is 0 or 1, means that the buffer can be placed + // anywhere in memory or else IoAlign value should be power of 2. To be + // properly aligned the buffer address should be divisible by IoAlign + // with no remainder. + // + (VOID *)BufferAddress = Buffer; + if((Media->IoAlign > 1 ) && (BufferAddress % Media->IoAlign)) { + return EFI_INVALID_PARAMETER; + } + + CsmBlockIoDev = (CSM_BLOCK_IO_DEV *) This; + AddressPacket = mEDDPacketBuffer; + + MaxTransferBlocks = MAX_EDD11_XFER/BlockSize; + + PatchHwInterrupt(CsmBlockIoDev); + + TransferBuffer = (UINT64)mEDDTransferBuffer; + while (BufferSize) { + NumberOfBlocks = BufferSize / BlockSize; + NumberOfBlocks = NumberOfBlocks > MaxTransferBlocks ? MaxTransferBlocks : NumberOfBlocks; // Max transfer MaxTransferBlocks + AddressPacket->PacketSizeInBytes = sizeof(EDD_DEVICE_ADDRESS_PACKET); + AddressPacket->Zero = 0; + AddressPacket->NumberOfBlocks = (UINT8)NumberOfBlocks; + AddressPacket->Zero2 = 0; + + // + // Normalize TransferBuffer address if needed + // + AlignedOffset = EFI_OFFSET(TransferBuffer); + AlignedSegment = EFI_SEGMENT(TransferBuffer); + if(AlignedOffset != 0) { + AlignedSegment = AlignedSegment + (AlignedOffset >> 4); + AlignedOffset = 0; + } + + AddressPacket->SegOffset = AlignedSegment << 16; + AddressPacket->SegOffset |= AlignedOffset; + + AddressPacket->LBA = (UINT64)LBA; + + Regs.H.AH = 0x42; + Regs.H.DL = CsmBlockIoDev->Drive.Number; + Regs.X.SI = EFI_OFFSET(AddressPacket); + Regs.X.DS = EFI_SEGMENT(AddressPacket); + + CsmBlockIoDev->LegacyBios->Int86 (CsmBlockIoDev->LegacyBios, 0x13, &Regs); + CarryFlag = (BOOLEAN)Regs.X.Flags.CF; + +// TRACE((-1, "Edd11CsmReadBlocks: INT 13 42 DL=%02x : CF=%d AH=%02x : LBA 0x%lx Block(s) %0d \n", CsmBlockIoDev->Drive.Number, CarryFlag, Regs.H.AH, LBA, NumberOfBlocks)); + + Media->MediaPresent = TRUE; + if (CarryFlag) { + // If we have a carry, figure out the error. + CsmBlockIoDev->Drive.ErrorCode = Regs.H.AH; + if (CsmBlockIoDev->Drive.ErrorCode == ERR_DISK_CHANGED) { + Media->MediaId++; + Drive = &CsmBlockIoDev->Drive; + if (GetInt13DeviceParameters(CsmBlockIoDev, Drive)) { + if (GetInt13Extensions (CsmBlockIoDev, Drive)) { + Media->LastBlock = (EFI_LBA)Drive->Parameters.PhysicalSectors - 1; + Media->BlockSize = (UINT32)Drive->Parameters.BytesPerSector; + } else { + ASSERT(FALSE); + } + // The media has changed. + Media->ReadOnly = FALSE; + pBS->HandleProtocol(CsmBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, (VOID **)&BlockIo); + pBS->ReinstallProtocolInterface (CsmBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, BlockIo, BlockIo); + Status = EFI_MEDIA_CHANGED; + goto Exit; + } + } + + if (Media->RemovableMedia) { + Media->MediaPresent = FALSE; + } + + Status = EFI_DEVICE_ERROR; + goto Exit; + } + + TransferByteSize = NumberOfBlocks * BlockSize; + pBS->CopyMem (Buffer, (VOID *)(UINTN)TransferBuffer, TransferByteSize); + BufferSize = BufferSize - TransferByteSize; + Buffer = (VOID *)((UINT8 *)Buffer + TransferByteSize); + LBA += NumberOfBlocks; + } +Exit: + RestoreHwInterrupt(CsmBlockIoDev); + return Status; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: Edd11CsmWriteBlocks +// +// Description: Write device using EDD1.1 write function +// +// Input: BlockIo protocol instance, Media ID, write data buffer +// +// Output: Status of the operation +// +// Referrals: EFI_LBA +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +Edd11CsmWriteBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +{ + EFI_BLOCK_IO_MEDIA *Media; + CSM_BLOCK_IO_DEV *CsmBlockIoDev; + EDD_DEVICE_ADDRESS_PACKET *AddressPacket; // I exist only for readability + EFI_IA32_REGISTER_SET Regs; + UINT64 TransferBuffer; + UINTN NumberOfBlocks; + UINTN TransferByteSize; + UINTN BlockSize; + CSM_LEGACY_DRIVE *Drive; + BOOLEAN CarryFlag; + UINTN MaxTransferBlocks; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + EFI_STATUS Status = EFI_SUCCESS; + UINT16 AlignedOffset; + UINT16 AlignedSegment; + UINTN BufferAddress; + + Media = This->Media; + BlockSize = Media->BlockSize; + + if (MediaId != Media->MediaId) return EFI_MEDIA_CHANGED; + if (BufferSize == 0) return EFI_SUCCESS; + if (LBA > Media->LastBlock) return EFI_INVALID_PARAMETER; + if ((LBA + (BufferSize / BlockSize) - 1) > Media->LastBlock) return EFI_INVALID_PARAMETER; + if (BufferSize % BlockSize != 0) return EFI_BAD_BUFFER_SIZE; + if (Buffer == NULL) return EFI_INVALID_PARAMETER; + + // + // If IoAlign values is 0 or 1, means that the buffer can be placed + // anywhere in memory or else IoAlign value should be power of 2. To be + // properly aligned the buffer address should be divisible by IoAlign + // with no remainder. + // + (VOID *)BufferAddress = Buffer; + if((Media->IoAlign > 1 ) && (BufferAddress % Media->IoAlign)) { + return EFI_INVALID_PARAMETER; + } + + CsmBlockIoDev = (CSM_BLOCK_IO_DEV *) This; + AddressPacket = mEDDPacketBuffer; + + MaxTransferBlocks = MAX_EDD11_XFER/BlockSize; + + PatchHwInterrupt(CsmBlockIoDev); + + TransferBuffer = (UINT64)mEDDTransferBuffer; + while (BufferSize) { + NumberOfBlocks = BufferSize/BlockSize; + NumberOfBlocks = NumberOfBlocks > MaxTransferBlocks ? MaxTransferBlocks : NumberOfBlocks; // Max transfer MaxTransferBlocks + AddressPacket->PacketSizeInBytes = sizeof(EDD_DEVICE_ADDRESS_PACKET); + AddressPacket->Zero = 0; + AddressPacket->NumberOfBlocks = (UINT8)NumberOfBlocks; + AddressPacket->Zero2 = 0; + + // + // Normalize TransferBuffer address if needed + // + AlignedOffset = EFI_OFFSET(TransferBuffer); + AlignedSegment = EFI_SEGMENT(TransferBuffer); + + if (AlignedOffset != 0) { + AlignedSegment = AlignedSegment + (AlignedOffset >> 4); + AlignedOffset = 0; + } + + AddressPacket->SegOffset = AlignedSegment << 16; + AddressPacket->SegOffset |= AlignedOffset; + + AddressPacket->LBA = (UINT64)LBA; + + Regs.H.AH = 0x43; + Regs.H.AL = 0x00; // Write Verify disable + Regs.H.DL = CsmBlockIoDev->Drive.Number; + Regs.X.SI = EFI_OFFSET(AddressPacket); + Regs.X.DS = EFI_SEGMENT(AddressPacket); + + TransferByteSize = NumberOfBlocks * BlockSize; + pBS->CopyMem ((VOID *)(UINTN)TransferBuffer, Buffer, TransferByteSize); + + CsmBlockIoDev->LegacyBios->Int86 (CsmBlockIoDev->LegacyBios, 0x13, &Regs); + CarryFlag = (BOOLEAN)Regs.X.Flags.CF; + +// TRACE((-1, "Edd11CsmWriteBlocks: INT 13 43 DL=%02x : CF=%d AH=%02x\n: LBA 0x%lx Block(s) %0d \n", CsmBlockIoDev->Drive.Number, CarryFlag, Regs.H.AH, LBA, NumberOfBlocks)); + + Media->MediaPresent = TRUE; + if (CarryFlag) { + // If we have a carry, figure out the error. + CsmBlockIoDev->Drive.ErrorCode = Regs.H.AH; + if (CsmBlockIoDev->Drive.ErrorCode == ERR_DISK_CHANGED) { + Media->MediaId++; + Drive = &CsmBlockIoDev->Drive; + if (GetInt13DeviceParameters(CsmBlockIoDev, Drive)) { + if (GetInt13Extensions (CsmBlockIoDev, Drive)) { + Media->LastBlock = (EFI_LBA)Drive->Parameters.PhysicalSectors - 1; + Media->BlockSize = (UINT32)Drive->Parameters.BytesPerSector; + } else { + ASSERT(FALSE); + } + // The media has changed. + Media->ReadOnly = FALSE; + pBS->HandleProtocol(CsmBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, (VOID **)&BlockIo); + pBS->ReinstallProtocolInterface (CsmBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, BlockIo, BlockIo); + Status = EFI_MEDIA_CHANGED; + goto Exit; + } + } else if (CsmBlockIoDev->Drive.ErrorCode == ERR_WRITE_PROTECTED) { + Media->ReadOnly = TRUE; + Status = EFI_WRITE_PROTECTED; + goto Exit; + } + + if (Media->RemovableMedia) { + Media->MediaPresent = FALSE; + } + + Status = EFI_DEVICE_ERROR; + goto Exit; + } + + Media->ReadOnly = FALSE; + BufferSize = BufferSize - TransferByteSize; + Buffer = (VOID *)((UINT8 *)Buffer + TransferByteSize); + LBA += NumberOfBlocks; + } +Exit: + RestoreHwInterrupt(CsmBlockIoDev); + return Status; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: LegacyCsmReadBlocks +// +// Description: Read device using INT13 function 2 +// +// Input: BlockIo protocol instance, Media ID, read data buffer +// +// Output: Status of the operation +// +// Referrals: EFI_LBA +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +LegacyCsmReadBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +{ + EFI_BLOCK_IO_MEDIA *Media; + CSM_BLOCK_IO_DEV *CsmBlockIoDev; + EFI_IA32_REGISTER_SET Regs; + UINTN UpperCylinder, Temp; + UINTN Cylinder, Head, Sector; + UINTN NumberOfBlocks, TransferByteSize; + UINTN ShortLba, CheckLba; + UINTN BlockSize; + CSM_LEGACY_DRIVE *Drive; + BOOLEAN CarryFlag; + UINTN Retry; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + EFI_STATUS Status = EFI_SUCCESS; + UINTN BufferAddress; + + Media = This->Media; + BlockSize = Media->BlockSize; + + if (MediaId != Media->MediaId) return EFI_MEDIA_CHANGED; + if (BufferSize == 0) return EFI_SUCCESS; + if (LBA > Media->LastBlock) return EFI_INVALID_PARAMETER; + if ((LBA + (BufferSize / BlockSize) - 1) > Media->LastBlock) return EFI_INVALID_PARAMETER; + if (BufferSize % BlockSize != 0) return EFI_BAD_BUFFER_SIZE; + if (Buffer == NULL) return EFI_INVALID_PARAMETER; + + // + // If IoAlign values is 0 or 1, means that the buffer can be placed + // anywhere in memory or else IoAlign value should be power of 2. To be + // properly aligned the buffer address should be divisible by IoAlign + // with no remainder. + // + (VOID *)BufferAddress = Buffer; + if((Media->IoAlign > 1 ) && (BufferAddress % Media->IoAlign)) { + return EFI_INVALID_PARAMETER; + } + + CsmBlockIoDev = (CSM_BLOCK_IO_DEV *) This; + ShortLba = (UINTN) LBA; + + PatchHwInterrupt(CsmBlockIoDev); + + while (BufferSize) { + // Convert LBA to CHS. + Sector = (ShortLba % CsmBlockIoDev->Drive.MaxSector) + 1; + Temp = ShortLba / CsmBlockIoDev->Drive.MaxSector; + Head = Temp % (CsmBlockIoDev->Drive.MaxHead + 1); + Cylinder = Temp / (CsmBlockIoDev->Drive.MaxHead + 1); + // Limit number of blocks to one head and cylindar + NumberOfBlocks = BufferSize/BlockSize; + Temp = CsmBlockIoDev->Drive.MaxSector - Sector + 1; + NumberOfBlocks = NumberOfBlocks > Temp ? Temp : NumberOfBlocks; + + Retry = 3; + // Loop to perform the read + do { + Regs.H.AH = 2; + Regs.H.AL = (UINT8) NumberOfBlocks; + Regs.H.DL = CsmBlockIoDev->Drive.Number; + + UpperCylinder = (Cylinder & 0x0f00) >> 2; + + CheckLba = Cylinder*(CsmBlockIoDev->Drive.MaxHead + 1) + Head; + CheckLba = CheckLba*CsmBlockIoDev->Drive.MaxSector + Sector - 1; + +// ASSERT(CheckLba == ShortLba); + + Regs.H.CL = (UINT8) ((Sector & 0x3f) + (UpperCylinder & 0xff)); + Regs.H.DH = (UINT8) (Head & 0x3f); + Regs.H.CH = (UINT8) (Cylinder & 0xff); + + Regs.X.BX = EFI_OFFSET(mEDDTransferBuffer); + Regs.X.ES = EFI_SEGMENT(mEDDTransferBuffer); + + CsmBlockIoDev->LegacyBios->Int86 (CsmBlockIoDev->LegacyBios, 0x13, &Regs); + CarryFlag = (BOOLEAN)Regs.X.Flags.CF; + +// TRACE((-1, "LegacyCsmReadBlocks: INT 13 02 DL=%02x : CF=%d AH=%02x\n", CsmBlockIoDev->Drive.Number, CarryFlag, Regs.H.AH)); + + Retry--; + } while (CarryFlag && Retry !=0 && Regs.H.AH != ERR_DISK_CHANGED); + + Media->MediaPresent = TRUE; + if (CarryFlag) { + // If we have a carry, figure out the error. + CsmBlockIoDev->Drive.ErrorCode = Regs.H.AH; + if (CsmBlockIoDev->Drive.ErrorCode == ERR_DISK_CHANGED) { + Media->MediaId++; + Drive = &CsmBlockIoDev->Drive; + if (GetInt13DeviceParameters(CsmBlockIoDev, Drive)) { + // The media has changed + if (GetInt13Extensions (CsmBlockIoDev, Drive)) { + Media->LastBlock = (EFI_LBA)Drive->Parameters.PhysicalSectors - 1; + Media->BlockSize = (UINT32)Drive->Parameters.BytesPerSector; + } else { + Media->LastBlock = (Drive->MaxHead + 1) * Drive->MaxSector * (Drive->MaxCylinder + 1) - 1; + Media->BlockSize = 512; + } + Media->ReadOnly = FALSE; + pBS->HandleProtocol(CsmBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, (VOID **)&BlockIo); + pBS->ReinstallProtocolInterface (CsmBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, BlockIo, BlockIo); + Status = EFI_MEDIA_CHANGED; + goto Exit; + } + } + + if (Media->RemovableMedia) { + Media->MediaPresent = FALSE; + } + + Status = EFI_DEVICE_ERROR; + goto Exit; + } + + TransferByteSize = NumberOfBlocks * BlockSize; + pBS->CopyMem (Buffer, mEDDTransferBuffer, TransferByteSize); + + ShortLba = ShortLba + NumberOfBlocks; + BufferSize = BufferSize - TransferByteSize; + Buffer = (VOID *)((UINT8 *)Buffer + TransferByteSize); + } +Exit: + RestoreHwInterrupt(CsmBlockIoDev); + return Status; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: LegacyCsmWriteBlocks +// +// Description: Write device using INT13 function 3 +// +// Input: BlockIo protocol instance, Media ID, write data buffer +// +// Output: Status of the operation +// +// Referrals: EFI_LBA +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +LegacyCsmWriteBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +{ + EFI_BLOCK_IO_MEDIA *Media; + CSM_BLOCK_IO_DEV *CsmBlockIoDev; + EFI_IA32_REGISTER_SET Regs; + UINTN UpperCylinder, Temp; + UINTN Cylinder, Head, Sector; + UINTN NumberOfBlocks, TransferByteSize; + UINTN ShortLba, CheckLba; + UINTN BlockSize; + CSM_LEGACY_DRIVE *Drive; + BOOLEAN CarryFlag; + UINTN Retry; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + EFI_STATUS Status = EFI_SUCCESS; + UINTN BufferAddress; + + Media = This->Media; + BlockSize = Media->BlockSize; + + if (MediaId != Media->MediaId) return EFI_MEDIA_CHANGED; + if (BufferSize == 0) return EFI_SUCCESS; + if (LBA > Media->LastBlock) return EFI_INVALID_PARAMETER; + if ((LBA + (BufferSize / BlockSize) - 1) > Media->LastBlock) return EFI_INVALID_PARAMETER; + if (BufferSize % BlockSize != 0) return EFI_BAD_BUFFER_SIZE; + if (Buffer == NULL) return EFI_INVALID_PARAMETER; + + // + // If IoAlign values is 0 or 1, means that the buffer can be placed + // anywhere in memory or else IoAlign value should be power of 2. To be + // properly aligned the buffer address should be divisible by IoAlign + // with no remainder. + // + (VOID *)BufferAddress = Buffer; + if((Media->IoAlign > 1 ) && (BufferAddress % Media->IoAlign)) { + return EFI_INVALID_PARAMETER; + } + +#if defined CORE_COMBINED_VERSION && (CORE_COMBINED_VERSION > 0x4028E) + // Verify if write is allowed + if(gBlockIoWriteProtectionProtocol != NULL) { + Status = gBlockIoWriteProtectionProtocol->BlockIoWriteProtectionCheck( + gBlockIoWriteProtectionProtocol, + This, + LBA, + BufferSize + ); + + // Abort operation if denied + if(Status == EFI_ACCESS_DENIED) { + return Status; + } + } +#endif + + CsmBlockIoDev = (CSM_BLOCK_IO_DEV *) This; + ShortLba = (UINTN) LBA; + + PatchHwInterrupt(CsmBlockIoDev); + + while(BufferSize) { + // Convert LBA to CHS + Sector = (ShortLba % CsmBlockIoDev->Drive.MaxSector) + 1; + Temp = ShortLba / CsmBlockIoDev->Drive.MaxSector; + Head = Temp % (CsmBlockIoDev->Drive.MaxHead + 1); + Cylinder = Temp / (CsmBlockIoDev->Drive.MaxHead + 1); + + // Limit number of blocks to one head and cylindar + NumberOfBlocks = BufferSize/BlockSize; + Temp = CsmBlockIoDev->Drive.MaxSector - Sector + 1; + NumberOfBlocks = NumberOfBlocks > Temp ? Temp : NumberOfBlocks; + + + Retry = 3; + // Loop to perform the write. + do { + Regs.H.AH = 3; + Regs.H.AL = (UINT8) NumberOfBlocks; + Regs.H.DL = CsmBlockIoDev->Drive.Number; + + UpperCylinder = (Cylinder & 0x0f00) >> 2; + + CheckLba = Cylinder*(CsmBlockIoDev->Drive.MaxHead + 1) + Head; + CheckLba = CheckLba*CsmBlockIoDev->Drive.MaxSector + Sector - 1; + +// ASSERT(CheckLba == ShortLba); + + Regs.H.CL = (UINT8) ((Sector & 0x3f) + (UpperCylinder & 0xff)); + Regs.H.DH = (UINT8) (Head & 0x3f); + Regs.H.CH = (UINT8) (Cylinder & 0xff); + + Regs.X.BX = EFI_OFFSET(mEDDTransferBuffer); + Regs.X.ES = EFI_SEGMENT(mEDDTransferBuffer); + + TransferByteSize = NumberOfBlocks * BlockSize; + pBS->CopyMem (mEDDTransferBuffer, Buffer, TransferByteSize); + + CsmBlockIoDev->LegacyBios->Int86 (CsmBlockIoDev->LegacyBios, 0x13, &Regs); + CarryFlag = (BOOLEAN)Regs.X.Flags.CF; + +// TRACE((-1, "LegacyCsmWriteBlocks: INT 13 03 DL=%02x : CF=%d AH=%02x\n", CsmBlockIoDev->Drive.Number, CarryFlag, Regs.H.AH)); + + Retry--; + } while (CarryFlag && Retry !=0 && Regs.H.AH != ERR_DISK_CHANGED); + + Media->MediaPresent = TRUE; + if (CarryFlag) { + // If we have a carry, figure out the error. + CsmBlockIoDev->Drive.ErrorCode = Regs.H.AH; + if (CsmBlockIoDev->Drive.ErrorCode == ERR_DISK_CHANGED) { + Media->MediaId++; + Drive = &CsmBlockIoDev->Drive; + if (GetInt13DeviceParameters(CsmBlockIoDev, Drive)) { + if (GetInt13Extensions (CsmBlockIoDev, Drive)) { + Media->LastBlock = (EFI_LBA)Drive->Parameters.PhysicalSectors - 1; + Media->BlockSize = (UINT32)Drive->Parameters.BytesPerSector; + } else { + Media->LastBlock = (Drive->MaxHead + 1) * Drive->MaxSector * (Drive->MaxCylinder + 1) - 1; + Media->BlockSize = 512; + } + // The media has changed. + Media->ReadOnly = FALSE; + pBS->HandleProtocol(CsmBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, (VOID **)&BlockIo); + pBS->ReinstallProtocolInterface (CsmBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, BlockIo, BlockIo); + Status = EFI_MEDIA_CHANGED; + goto Exit; + } + } else if (CsmBlockIoDev->Drive.ErrorCode == ERR_WRITE_PROTECTED) { + Media->ReadOnly = TRUE; + Status = EFI_WRITE_PROTECTED; + goto Exit; + } + + if (Media->RemovableMedia) { + Media->MediaPresent = FALSE; + } + + Status = EFI_DEVICE_ERROR; + goto Exit; + } + Media->ReadOnly = FALSE; + ShortLba = ShortLba + NumberOfBlocks; + BufferSize = BufferSize - TransferByteSize; + Buffer = (VOID *)((UINT8 *)Buffer + TransferByteSize); + } + +Exit: + RestoreHwInterrupt(CsmBlockIoDev); + + return Status; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: PatchHwInterrupt +// +// Description: Saves HW interrupt vector used by this device +// +// Input: BlockIo device +// +// Output: None +// +// Referrals: CSM_BLOCK_IO_DEV +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID +PatchHwInterrupt( + CSM_BLOCK_IO_DEV *CsmBlockIoDev +) +{ + UINT32 *ivt = (UINT32*)0; + if (CsmBlockIoDev->HwInt) { + gTempHwIntSav = ivt[CsmBlockIoDev->HwInt]; + ivt[CsmBlockIoDev->HwInt] = CsmBlockIoDev->HwIntHandler; + } +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: RestoreHwInterrupt +// +// Description: Restores HW interrupt saved by PatchHwInterrupt +// +// Input: BlockIo device +// +// Output: None +// +// Referrals: CSM_BLOCK_IO_DEV, PatchHwInterrupt +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID +RestoreHwInterrupt( + CSM_BLOCK_IO_DEV *CsmBlockIoDev +) +{ + UINT32 *ivt = (UINT32*)0; + if (CsmBlockIoDev->HwInt) { + ivt[CsmBlockIoDev->HwInt] = gTempHwIntSav; + } +} + + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2010, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** diff --git a/Core/EM/CSM/thunk/BlockIo/biosblkio.dxs b/Core/EM/CSM/thunk/BlockIo/biosblkio.dxs new file mode 100644 index 0000000..8a863fa --- /dev/null +++ b/Core/EM/CSM/thunk/BlockIo/biosblkio.dxs @@ -0,0 +1,46 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2011, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** +// $Header: /Alaska/SOURCE/Modules/CSM/Generic/Thunk/INT13/biosblkio.dxs 1 10/03/11 3:38p Olegi $ +// +// $Revision: 1 $ +// +// $Date: 10/03/11 3:38p $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Modules/CSM/Generic/Thunk/INT13/biosblkio.dxs $ +// +// 1 10/03/11 3:38p Olegi +// +//********************************************************************** + +#include <Protocol\LegacyBios.h> + +DEPENDENCY_START + EFI_LEGACY_BIOS_PROTOCOL_GUID +DEPENDENCY_END + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2011, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** diff --git a/Core/EM/CSM/thunk/BlockIo/biosblkio.mak b/Core/EM/CSM/thunk/BlockIo/biosblkio.mak new file mode 100644 index 0000000..879933f --- /dev/null +++ b/Core/EM/CSM/thunk/BlockIo/biosblkio.mak @@ -0,0 +1,63 @@ +#********************************************************************** +#********************************************************************** +#** ** +#** (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/Thunk/INT13/biosblkio.mak 3 1/12/10 11:50a Olegi $ +# +# $Revision: 3 $ +# +# $Date: 1/12/10 11:50a $ +#************************************************************************// +# Revision History +# ---------------- +# $Log: /Alaska/SOURCE/Modules/CSM/Generic/Thunk/INT13/biosblkio.mak $ +# +# 3 1/12/10 11:50a Olegi +# Copyright message updated. +# +# 2 12/02/05 11:44a Felixp +# +# 1 2/15/05 11:00a Olegi +# Initial VSS check-in. +# +# +#************************************************************************// +all : CsmBlockIo + +CsmBlockIo : $(BUILD_DIR)\biosblkio.mak CsmBlockIoBin + +$(BUILD_DIR)\biosblkio.mak : $(CSMBLOCKIO_DIR)\int13thunk.cif $(CSMBLOCKIO_DIR)\biosblkio.mak $(BUILD_RULES) + $(CIF2MAK) $(CSMBLOCKIO_DIR)\int13thunk.cif $(CIF2MAK_DEFAULTS) + +CsmBlockIoBin: $(AMIDXELIB) + $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\ + /f $(BUILD_DIR)\biosblkio.mak all\ + GUID=25ACF158-DD61-4e64-9A49-55851E9A26C7\ + ENTRY_POINT=CsmBlockIoEntryPoint \ + TYPE=BS_DRIVER \ + COMPRESS=1\ + +#********************************************************************** +#********************************************************************** +#** ** +#** (C)Copyright 1985-2010, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#********************************************************************** +#**********************************************************************
\ No newline at end of file diff --git a/Core/EM/CSM/thunk/BlockIo/int13thunk.cif b/Core/EM/CSM/thunk/BlockIo/int13thunk.cif new file mode 100644 index 0000000..24c82f3 --- /dev/null +++ b/Core/EM/CSM/thunk/BlockIo/int13thunk.cif @@ -0,0 +1,15 @@ +<component> + name = "INT13" + category = ModulePart + LocalRoot = "core\em\csm\thunk\BlockIo" + RefName = "BIOSBLKIO" +[files] +"CsmInt13.c" +"CsmBlkIoComponentName.c" +"CsmBlockIo.c" +"CsmBlockIo.h" +"CsmBlockIo.sdl" +"CsmEdd.h" +"biosblkio.mak" +"biosblkio.dxs" +<endComponent> diff --git a/Core/EM/CSM/thunk/CsmVideo/AmiMapping.c b/Core/EM/CSM/thunk/CsmVideo/AmiMapping.c new file mode 100644 index 0000000..88c165b --- /dev/null +++ b/Core/EM/CSM/thunk/CsmVideo/AmiMapping.c @@ -0,0 +1,162 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2006, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 6145-F Northbelt Pkwy, Norcross, GA 30071 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** + +//********************************************************************** +// $Header: /Alaska/SOURCE/Modules/CSM/Generic/Thunk/CsmVideo/AmiMapping.c 2 3/04/11 2:28p Olegi $ +// +// $Revision: 2 $ +// +// $Date: 3/04/11 2:28p $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Modules/CSM/Generic/Thunk/CsmVideo/AmiMapping.c $ +// +// 2 3/04/11 2:28p Olegi +// [TAG] EIP55098 +// [Category] Spec Update +// [Severity] Important +// [Description] Install EFI_COMPONENT_NAME_PROTOCOL if BIOS is in UEFI +// 2.0 mode and EFI_COMPONENT_NAME2_PROTOCOL if BIOS is in UEFI 2.1 mode. +// [Files] UefiBiosVideo.h +// UefiBiosVideo.c +// ComponentName.c +// AmiMapping.h +// AmiMapping.c +// +// 1 12/29/06 3:33p Felixp +// +//********************************************************************** +//<AMI_FHDR_START> +// +// Name: AmiMapping.c +// +// Description: Mapping from EDK to AMI definitions +// +//<AMI_FHDR_END> +//********************************************************************** +#include "AmiMapping.h" +#include "VgaMiniPort.h" + +EFI_GUID gEfiVgaMiniPortProtocolGuid = EFI_VGA_MINI_PORT_PROTOCOL_GUID; + +EFI_STATUS EfiLibInstallAllDriverProtocols ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable, + IN EFI_DRIVER_BINDING_PROTOCOL *DriverBinding, + IN EFI_HANDLE DriverBindingHandle, +#if EFI_SPECIFICATION_VERSION <= 0x20000 + IN EFI_COMPONENT_NAME_PROTOCOL *ComponentName, OPTIONAL +#else + IN EFI_COMPONENT_NAME2_PROTOCOL *ComponentName, OPTIONAL +#endif + IN VOID/*EFI_DRIVER_CONFIGURATION_PROTOCOL*/ *DriverConfiguration, OPTIONAL + IN VOID/*EFI_DRIVER_DIAGNOSTICS_PROTOCOL*/ *DriverDiagnostics OPTIONAL +) +{ + EFI_STATUS Status; + InitAmiLib (ImageHandle, SystemTable); + DriverBinding->ImageHandle = ImageHandle; + DriverBinding->DriverBindingHandle = DriverBindingHandle; + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + NULL + ); + if (EFI_ERROR(Status)) return Status; + if (ComponentName) + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, +#if EFI_SPECIFICATION_VERSION <= 0x20000 + &gEfiComponentNameProtocolGuid, ComponentName, +#else + &gEfiComponentName2ProtocolGuid,ComponentName, +#endif + NULL + ); + return Status; +} + +BOOLEAN +EfiLibCompareLanguage ( + CHAR8 *Language1, + CHAR8 *Language2 + ) + +{ + return *(UINT16*)Language1==*(UINT16*)Language2 + && Language1[2]==Language2[2]; +} + +EFI_STATUS EfiLibLookupUnicodeString ( + CHAR8 *Language, + CHAR8 *SupportedLanguages, + EFI_UNICODE_STRING_TABLE *UnicodeStringTable, + CHAR16 **UnicodeString + ) +{ + // + // Make sure the parameters are valid + // + if (Language == NULL || UnicodeString == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // If there are no supported languages, or the Unicode String Table is empty, then the + // Unicode String specified by Language is not supported by this Unicode String Table + // + if (SupportedLanguages == NULL || UnicodeStringTable == NULL) { + return EFI_UNSUPPORTED; + } + + // + // Make sure Language is in the set of Supported Languages + // + while (*SupportedLanguages != 0) { + if (EfiLibCompareLanguage (Language, SupportedLanguages)) { + + // + // Search the Unicode String Table for the matching Language specifier + // + while (UnicodeStringTable->Language != NULL) { + if (EfiLibCompareLanguage (Language, UnicodeStringTable->Language)) { + + // + // A matching string was found, so return it + // + *UnicodeString = UnicodeStringTable->UnicodeString; + return EFI_SUCCESS; + } + UnicodeStringTable++; + } + return EFI_UNSUPPORTED; + } + SupportedLanguages += 3; + } + return EFI_UNSUPPORTED; +} +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2006, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 6145-F Northbelt Pkwy, Norcross, GA 30071 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//**********************************************************************
\ No newline at end of file diff --git a/Core/EM/CSM/thunk/CsmVideo/AmiMapping.h b/Core/EM/CSM/thunk/CsmVideo/AmiMapping.h new file mode 100644 index 0000000..9c92d54 --- /dev/null +++ b/Core/EM/CSM/thunk/CsmVideo/AmiMapping.h @@ -0,0 +1,153 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2006, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 6145-F Northbelt Pkwy, Norcross, GA 30071 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** + +//********************************************************************** +// $Header: /Alaska/SOURCE/Modules/CSM/Generic/Thunk/CsmVideo/AmiMapping.h 3 12/23/13 10:21a Olegi $ +// +// $Revision: 3 $ +// +// $Date: 12/23/13 10:21a $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Modules/CSM/Generic/Thunk/CsmVideo/AmiMapping.h $ +// +// 3 12/23/13 10:21a Olegi +// [TAG] EIP148123 +// [Description] CSM includes file which name has been changed +// +// 2 3/04/11 2:28p Olegi +// [TAG] EIP55098 +// [Category] Spec Update +// [Severity] Important +// [Description] Install EFI_COMPONENT_NAME_PROTOCOL if BIOS is in UEFI +// 2.0 mode and EFI_COMPONENT_NAME2_PROTOCOL if BIOS is in UEFI 2.1 mode. +// [Files] UefiBiosVideo.h +// UefiBiosVideo.c +// ComponentName.c +// AmiMapping.h +// AmiMapping.c +// +// 1 12/29/06 3:33p Felixp +// +//********************************************************************** +//<AMI_FHDR_START> +// +// Name: AmiMapping.h +// +// Description: Mapping from EDK to AMI definitions +// +//<AMI_FHDR_END> +//********************************************************************** +#ifndef __AMI_MAPPING__H__ +#define __AMI_MAPPING__H__ +#ifdef __cplusplus +extern "C" { +#endif +#include <Protocol/DriverBinding.h> +#include <Protocol/ComponentName.h> +#include <AmiDxeLib.h> +#include <Token.h> + +#define STATIC static +#define EFI_GUID_DEFINITION(a) +#define EFI_PROTOCOL_DEFINITION(a) CONVERT_TO_STRING(Protocol/a.h) +#define EFI_DRIVER_ENTRY_POINT(a) +#define EFI_TPL_NOTIFY TPL_NOTIFY +#define EFI_SIGNATURE_16(A,B) ((A) | (B<<8)) +#define EFI_SIGNATURE_32(A,B,C,D) (EFI_SIGNATURE_16(A,B) | (EFI_SIGNATURE_16(C,D) << 16)) + +#define EfiZeroMem(Address, Length) gBS->SetMem ((Address), (Length), 0) +#define gBS pBS +#define ReportStatusCodeWithDevicePath(a,b,c,d,e) + +#define ACPI_ADR_DISPLAY_TYPE_VGA 1 +#define ACPI_DISPLAY_ADR(_DeviceIdScheme, _HeadId, _NonVgaOutput, _BiosCanDetect, _VendorInfo, _Type, _Port, _Index) \ + ((UINT32) ( (((_DeviceIdScheme) & 0x1) << 31) | \ + (((_HeadId) & 0x7) << 18) | \ + (((_NonVgaOutput) & 0x1) << 17) | \ + (((_BiosCanDetect) & 0x1) << 16) | \ + (((_VendorInfo) & 0xf) << 12) | \ + (((_Type) & 0xf) << 8) | \ + (((_Port) & 0xf) << 4) | \ + ((_Index) & 0xf) )) +#if defined CORE_COMBINED_VERSION && (CORE_COMBINED_VERSION < 0x4028F) +#define SetDevicePathNodeLength SET_NODE_LENGTH +#endif + +#define EfiAppendDevicePathNode DPAddNode +#define CR(pField, OutterType, Field, Signature) OUTTER(pField, Field, OutterType) +#define EFI_SEGMENT(_Adr) (UINT16) ((UINT16) (((UINTN) (_Adr)) >> 4) & 0xf000) +#define EFI_OFFSET(_Adr) (UINT16) (((UINT16) ((UINTN) (_Adr))) & 0xffff) +#define EFI_SIMPLE_TEXT_OUT_PROTOCOL EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL +#define EFI_SIMPLE_TEXT_OUTPUT_MODE SIMPLE_TEXT_OUTPUT_MODE +#define CHAR_NULL 0x0000 +#define CHAR_BACKSPACE 0x0008 +#define CHAR_TAB 0x0009 +#define CHAR_LINEFEED 0x000A +#define CHAR_CARRIAGE_RETURN 0x000D + +typedef struct { + CHAR8 *Language; + CHAR16 *UnicodeString; +} EFI_UNICODE_STRING_TABLE; + +#define INSTALL_ALL_DRIVER_PROTOCOLS EfiLibInstallAllDriverProtocols +EFI_STATUS +EfiLibInstallAllDriverProtocols ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable, + IN EFI_DRIVER_BINDING_PROTOCOL *DriverBinding, + IN EFI_HANDLE DriverBindingHandle, +#if EFI_SPECIFICATION_VERSION <= 0x20000 + IN EFI_COMPONENT_NAME_PROTOCOL *ComponentName, OPTIONAL +#else + IN EFI_COMPONENT_NAME2_PROTOCOL *ComponentName, OPTIONAL +#endif + IN VOID/*EFI_DRIVER_CONFIGURATION_PROTOCOL*/ *DriverConfiguration, OPTIONAL + IN VOID/*EFI_DRIVER_DIAGNOSTICS_PROTOCOL*/ *DriverDiagnostics OPTIONAL + ); + +EFI_STATUS +EfiLibLookupUnicodeString ( + CHAR8 *Language, + CHAR8 *SupportedLanguages, + EFI_UNICODE_STRING_TABLE *UnicodeStringTable, + CHAR16 **UnicodeString + ); + +EFI_STATUS +EFIAPI +VgaClassDriverEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); +/****** DO NOT WRITE BELOW THIS LINE *******/ +#ifdef __cplusplus +} +#endif +#endif +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2006, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 6145-F Northbelt Pkwy, Norcross, GA 30071 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//**********************************************************************
\ No newline at end of file diff --git a/Core/EM/CSM/thunk/CsmVideo/ComponentName.c b/Core/EM/CSM/thunk/CsmVideo/ComponentName.c new file mode 100644 index 0000000..786cec4 --- /dev/null +++ b/Core/EM/CSM/thunk/CsmVideo/ComponentName.c @@ -0,0 +1,324 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2013, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** + +/*++ + This file contains a 'Sample Driver' and is licensed as such + under the terms of your license agreement with Intel or your + vendor. This file may be modified by the user, subject to + the additional terms of the license agreement +--*/ +/*++ + +Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved +This software and associated documentation (if any) is furnished +under a license and may only be used or copied in accordance +with the terms of the license. Except as permitted by such +license, no part of this software or documentation may be +reproduced, stored in a retrieval system, or transmitted in any +form or by any means without the express written consent of +Intel Corporation. + +Module Name: + + ComponentName.c + +Abstract: + +--*/ +//*** AMI PORTING BEGIN ***// +//This file is not part of the component. +//#include "BiosVideo.h" +#include "UefiBiosVideo.h" +//*** AMI PORTING END *****// + +// +// EFI Component Name Functions +// +EFI_STATUS +EFIAPI +BiosVideoComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ); + +EFI_STATUS +EFIAPI +BiosVideoComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +EFI_STATUS + +EFIAPI +BiosVideoComponentName2GetDriverName ( + IN EFI_COMPONENT_NAME2_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ); + + +EFI_STATUS +EFIAPI +BiosVideoComponentName2GetControllerName ( + IN EFI_COMPONENT_NAME2_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + + +// +// EFI Component Name Protocol +// +EFI_COMPONENT_NAME2_PROTOCOL gBiosVideoComponentName2 = { + BiosVideoComponentName2GetDriverName, + BiosVideoComponentName2GetControllerName, + LANGUAGE_CODE_ENGLISH +}; + +EFI_COMPONENT_NAME_PROTOCOL gBiosVideoComponentName = { + BiosVideoComponentNameGetDriverName, + BiosVideoComponentNameGetControllerName, + "eng" +}; + +static EFI_UNICODE_STRING_TABLE mBiosVideoDriverNameTable[] = { + { + "eng", + L"BIOS[INT10] Video Driver" + }, + { + NULL, + NULL + } +}; + +static EFI_UNICODE_STRING_TABLE mBiosVideoDriverNameTable2[] = { + { + LANGUAGE_CODE_ENGLISH, + L"BIOS[INT10] Video Driver" + }, + { + NULL, + NULL + } +}; + +EFI_STATUS +EFIAPI +BiosVideoComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + Language - A pointer to a three character ISO 639-2 language identifier. + This is the language of the driver name that that the caller + is requesting, and it must match one of the languages specified + in SupportedLanguages. The number of languages supported by a + driver is up to the driver writer. + DriverName - A pointer to the Unicode string to return. This Unicode string + is the name of the driver specified by This in the language + specified by Language. + + Returns: + EFI_SUCCESS - The Unicode string for the Driver specified by This + and the language specified by Language was returned + in DriverName. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - DriverName is NULL. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + + return EfiLibLookupUnicodeString ( + Language, + gBiosVideoComponentName.SupportedLanguages, + mBiosVideoDriverNameTable, + DriverName + ); +} + +EFI_STATUS +EFIAPI +BiosVideoComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by an EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + ControllerHandle - The handle of a controller that the driver specified by + This is managing. This handle specifies the controller + whose name is to be returned. + ChildHandle - The handle of the child controller to retrieve the name + of. This is an optional parameter that may be NULL. It + will be NULL for device drivers. It will also be NULL + for a bus drivers that wish to retrieve the name of the + bus controller. It will not be NULL for a bus driver + that wishes to retrieve the name of a child controller. + Language - A pointer to a three character ISO 639-2 language + identifier. This is the language of the controller name + that that the caller is requesting, and it must match one + of the languages specified in SupportedLanguages. The + number of languages supported by a driver is up to the + driver writer. + ControllerName - A pointer to the Unicode string to return. This Unicode + string is the name of the controller specified by + ControllerHandle and ChildHandle in the language specified + by Language from the point of view of the driver specified + by This. + + Returns: + EFI_SUCCESS - The Unicode string for the user readable name in the + language specified by Language for the driver + specified by This was returned in DriverName. + EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - ControllerName is NULL. + EFI_UNSUPPORTED - The driver specified by This is not currently managing + the controller specified by ControllerHandle and + ChildHandle. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + return EFI_UNSUPPORTED; +} + + +EFI_STATUS +EFIAPI +BiosVideoComponentName2GetDriverName ( + IN EFI_COMPONENT_NAME2_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + Language - A pointer to a three character ISO 639-2 language identifier. + This is the language of the driver name that that the caller + is requesting, and it must match one of the languages specified + in SupportedLanguages. The number of languages supported by a + driver is up to the driver writer. + DriverName - A pointer to the Unicode string to return. This Unicode string + is the name of the driver specified by This in the language + specified by Language. + + Returns: + EFI_SUCCESS - The Unicode string for the Driver specified by This + and the language specified by Language was returned + in DriverName. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - DriverName is NULL. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + + return EfiLibLookupUnicodeString ( + Language, + gBiosVideoComponentName2.SupportedLanguages, + mBiosVideoDriverNameTable2, + DriverName + ); +} + + +EFI_STATUS +EFIAPI +BiosVideoComponentName2GetControllerName ( + IN EFI_COMPONENT_NAME2_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by an EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + ControllerHandle - The handle of a controller that the driver specified by + This is managing. This handle specifies the controller + whose name is to be returned. + ChildHandle - The handle of the child controller to retrieve the name + of. This is an optional parameter that may be NULL. It + will be NULL for device drivers. It will also be NULL + for a bus drivers that wish to retrieve the name of the + bus controller. It will not be NULL for a bus driver + that wishes to retrieve the name of a child controller. + Language - A pointer to a three character ISO 639-2 language + identifier. This is the language of the controller name + that that the caller is requesting, and it must match one + of the languages specified in SupportedLanguages. The + number of languages supported by a driver is up to the + driver writer. + ControllerName - A pointer to the Unicode string to return. This Unicode + string is the name of the controller specified by + ControllerHandle and ChildHandle in the language specified + by Language from the point of view of the driver specified + by This. + + Returns: + EFI_SUCCESS - The Unicode string for the user readable name in the + language specified by Language for the driver + specified by This was returned in DriverName. + EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - ControllerName is NULL. + EFI_UNSUPPORTED - The driver specified by This is not currently managing + the controller specified by ControllerHandle and + ChildHandle. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + return EFI_UNSUPPORTED; +} diff --git a/Core/EM/CSM/thunk/CsmVideo/CsmVideo.cif b/Core/EM/CSM/thunk/CsmVideo/CsmVideo.cif new file mode 100644 index 0000000..e357445 --- /dev/null +++ b/Core/EM/CSM/thunk/CsmVideo/CsmVideo.cif @@ -0,0 +1,20 @@ +<component> + name = "CsmVideo" + category = ModulePart + LocalRoot = "Core\EM\CSM\Thunk\CsmVideo\" + RefName = "CsmVideo" +[files] +"CsmVideo.sdl" +"CsmVideo.mak" +"UefiBiosVideo.h" +"UefiBiosVideo.c" +"ComponentName.c" +"VesaBiosExtensions.h" +"pci22.h" +"AmiMapping.h" +"AmiMapping.c" +"VgaMiniPort.h" +"VgaClass.h" +"VgaClass.c" +"CsmVideo.dxs" +<endComponent> diff --git a/Core/EM/CSM/thunk/CsmVideo/CsmVideo.dxs b/Core/EM/CSM/thunk/CsmVideo/CsmVideo.dxs new file mode 100644 index 0000000..2f961f5 --- /dev/null +++ b/Core/EM/CSM/thunk/CsmVideo/CsmVideo.dxs @@ -0,0 +1,46 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2011, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** +// $Header: /Alaska/SOURCE/Modules/CSM/Generic/Thunk/CsmVideo/CsmVideo.dxs 1 11/10/11 6:34p Olegi $ +// +// $Revision: 1 $ +// +// $Date: 11/10/11 6:34p $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Modules/CSM/Generic/Thunk/CsmVideo/CsmVideo.dxs $ +// +// 1 11/10/11 6:34p Olegi +// +//********************************************************************** + +#include <Protocol\LegacyBios.h> + +DEPENDENCY_START + EFI_LEGACY_BIOS_PROTOCOL_GUID +DEPENDENCY_END + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2011, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** diff --git a/Core/EM/CSM/thunk/CsmVideo/CsmVideo.mak b/Core/EM/CSM/thunk/CsmVideo/CsmVideo.mak new file mode 100644 index 0000000..4d59620 --- /dev/null +++ b/Core/EM/CSM/thunk/CsmVideo/CsmVideo.mak @@ -0,0 +1,66 @@ +#********************************************************************** +#********************************************************************** +#** ** +#** (C)Copyright 1985-2006, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 6145-F Northbelt Pkwy, Norcross, GA 30071 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#********************************************************************** +#********************************************************************** + +#********************************************************************** +# $Header: /Alaska/SOURCE/Modules/CSM/Generic/Thunk/CsmVideo/CsmVideo.mak 2 4/27/07 5:18p Olegi $ +# +# $Revision: 2 $ +# +# $Date: 4/27/07 5:18p $ +#********************************************************************** +# Revision History +# ---------------- +# $Log: /Alaska/SOURCE/Modules/CSM/Generic/Thunk/CsmVideo/CsmVideo.mak $ +# +# 2 4/27/07 5:18p Olegi +# +# 1 12/29/06 3:33p Felixp +# +#********************************************************************** +#<AMI_FHDR_START> +# +# Name: CsmVideo.mak +# +# Description: CSM Video make file +# +#<AMI_FHDR_END> +#********************************************************************** +all : CsmVideo + +CsmVideo : $(BUILD_DIR)\CsmVideo.mak CsmVideoBin + +$(BUILD_DIR)\CsmVideo.mak : $(CsmVideo_DIR)\$(@B).cif $(CsmVideo_DIR)\$(@B).mak $(BUILD_RULES) + $(CIF2MAK) $(CsmVideo_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS) + +CsmVideoBin : $(AMIDXELIB) + $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\ + /f $(BUILD_DIR)\CsmVideo.mak all\ + GUID=29CF55F8-B675-4f5d-8F2F-B87A3ECFD063\ + ENTRY_POINT=BiosVideoDriverEntryPoint\ + EXT_HEADERS=$(BUILD_DIR)\Token.h\ + TYPE=BS_DRIVER \ + COMPRESS=1 +#********************************************************************** +#********************************************************************** +#** ** +#** (C)Copyright 1985-2006, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 6145-F Northbelt Pkwy, Norcross, GA 30071 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#********************************************************************** +#**********************************************************************
\ No newline at end of file diff --git a/Core/EM/CSM/thunk/CsmVideo/CsmVideo.sdl b/Core/EM/CSM/thunk/CsmVideo/CsmVideo.sdl new file mode 100644 index 0000000..19768e8 --- /dev/null +++ b/Core/EM/CSM/thunk/CsmVideo/CsmVideo.sdl @@ -0,0 +1,58 @@ +TOKEN + Name = "CsmVideo_SUPPORT" + Value = "1" + Help = "Main switch to enable CsmVideo support in Project" + TokenType = Boolean + TargetEQU = Yes + TargetMAK = Yes + Master = Yes +End + +TOKEN + Name = "INT10_VESA_GO_SUPPORT" + Value = "1" + Help = "Enables/Disables support of the Graphics Output protocol using VESA INT10 extensions" + TokenType = Boolean + TargetH = Yes +End + +TOKEN + Name = "INT10_VGA_GO_SUPPORT" + Value = "0" + Help = "Enables/Disables support of the Graphics Output protocol using standard VGA INT10 calls in 640x480 16 color mode.\If both VGA_GO_SUPPORT and VESA_GO_SUPPORT enabled, VGA calls will only be used if VESA extensions are not supported by the video card." + TokenType = Boolean + TargetH = Yes +End + +TOKEN + Name = "INT10_SIMPLE_TEXT_SUPPORT" + Value = "1" + Help = "Enables/Disables support of the Simple Text Output protocol using text mode.\If VGA_GO_SUPPORT or VESA_GO_SUPPORT or both enabled, text mode will will only be used if neither VESA nor standard VGA graphical modes are supported" + TokenType = Boolean + TargetH = Yes +End + +TOKEN + Name = "INT10_TRUST_EDID_INFORMATION" + Value = "1" + Help = "Some SSUs(Server Switch Units) return invalid EDID information, for these turn this switch off." + TokenType = Boolean + TargetH = Yes +End + + +PATH + Name = "CsmVideo_DIR" +End + +MODULE + Help = "Includes CsmVideo.mak to Project" + File = "CsmVideo.mak" +End + +ELINK + Name = "$(BUILD_DIR)\CsmVideo.ffs" + Parent = "FV_MAIN" + InvokeOrder = AfterParent +End + diff --git a/Core/EM/CSM/thunk/CsmVideo/UefiBiosVideo.c b/Core/EM/CSM/thunk/CsmVideo/UefiBiosVideo.c new file mode 100644 index 0000000..ddbe46c --- /dev/null +++ b/Core/EM/CSM/thunk/CsmVideo/UefiBiosVideo.c @@ -0,0 +1,3886 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2014, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** + +/*++ + This file contains a 'Sample Driver' and is licensed as such + under the terms of your license agreement with Intel or your + vendor. This file may be modified by the user, subject to + the additional terms of the license agreement +--*/ +/*++ + +Copyright (c) 2006 Intel Corporation. All rights reserved +This software and associated documentation (if any) is furnished +under a license and may only be used or copied in accordance +with the terms of the license. Except as permitted by such +license, no part of this software or documentation may be +reproduced, stored in a retrieval system, or transmitted in any +form or by any means without the express written consent of +Intel Corporation. + +Module Name: + + BiosVideo.c + +Abstract: + + ConsoleOut Routines that speak VGA. + +Revision History + +--*/ + +//*** AMI PORTING BEGIN ***// +#include "AcpiRes.h" +//*** AMI PORTING END *****// +#include "UefiBiosVideo.h" + +#define TRACE_BIOS_VIDEO TRACE_ALWAYS +//#define TRACE_BIOS_VIDEO TRACE_NEVER + +// +// EFI Driver Binding Protocol Instance +// +EFI_DRIVER_BINDING_PROTOCOL gBiosVideoDriverBinding = { + BiosVideoDriverBindingSupported, + BiosVideoDriverBindingStart, + BiosVideoDriverBindingStop, + 0x00000024, + NULL, + NULL +}; + +typedef struct _TEXT_MODE { + INT32 ModeNum; + INT32 Col; + INT32 Row; + UINT32 VideoCol; // horizontal pixels + UINT32 VideoRow; // vertical pixels +} TEXT_MODE; + +#if CORE_COMBINED_VERSION < 0x4028e +const TEXT_MODE TextModeArray[] = {GC_MODE_LIST}; +const INT32 MaxTextMode=(sizeof(TextModeArray)/sizeof(TEXT_MODE)); +#else +extern TEXT_MODE TextModeArray[]; +extern INT32 MaxTextMode; +#endif + +// remove the following line when Protocol/EdidOverride.h becomes available +EFI_GUID gEfiEdidOverrideProtocolGuid = EFI_EDID_OVERRIDE_PROTOCOL_GUID; + +//*** AMI PORTING BEGIN ***// +#if INT10_VGA_GO_SUPPORT==1 +//*** AMI PORTING END *****// +// +// Global lookup tables for VGA graphics modes +// +UINT8 mVgaLeftMaskTable[] = { 0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01 }; + +UINT8 mVgaRightMaskTable[] = { 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff }; + +UINT8 mVgaBitMaskTable[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; + +EFI_GRAPHICS_OUTPUT_BLT_PIXEL mVgaColorToGraphicsOutputColor[] = { + { 0x00, 0x00, 0x00, 0x00 }, + { 0x98, 0x00, 0x00, 0x00 }, + { 0x00, 0x98, 0x00, 0x00 }, + { 0x98, 0x98, 0x00, 0x00 }, + { 0x00, 0x00, 0x98, 0x00 }, + { 0x98, 0x00, 0x98, 0x00 }, + { 0x00, 0x98, 0x98, 0x00 }, + { 0x98, 0x98, 0x98, 0x00 }, + { 0x10, 0x10, 0x10, 0x00 }, + { 0xff, 0x10, 0x10, 0x00 }, + { 0x10, 0xff, 0x10, 0x00 }, + { 0xff, 0xff, 0x10, 0x00 }, + { 0x10, 0x10, 0xff, 0x00 }, + { 0xf0, 0x10, 0xff, 0x00 }, + { 0x10, 0xff, 0xff, 0x00 }, + { 0xff, 0xff, 0xff, 0x00 } +}; + +//*** AMI PORTING BEGIN ***// +#endif //if INT10_VGA_GO_SUPPORT==1 +#if INT10_VESA_GO_SUPPORT==1 +//*** AMI PORTING END *****// + +// +// Standard timing defined by VESA EDID +// +VESA_BIOS_EXTENSIONS_EDID_TIMING mEstablishedEdidTiming[] = { + // + // Established Timing I + // + {800, 600, 60}, + {800, 600, 56}, + {640, 480, 75}, + {640, 480, 72}, + {640, 480, 67}, + {640, 480, 60}, + {720, 400, 88}, + {720, 400, 70}, + // + // Established Timing II + // + {1280, 1024, 75}, + {1024, 768, 75}, + {1024, 768, 70}, + {1024, 768, 60}, + {1024, 768, 87}, + {832, 624, 75}, + {800, 600, 75}, + {800, 600, 72}, + // + // Established Timing III + // + {1152, 870, 75} +}; +//*** AMI PORTING BEGIN ***// +#endif //if INT10_VESA_GO_SUPPORT==1 +//*** AMI PORTING END *****// + +UINT32 SupportedResolutions[29] = { 0 }; + +EFI_STATUS +BiosVideoChildHandleInstall ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ParentHandle, + IN EFI_PCI_IO_PROTOCOL *ParentPciIo, + IN EFI_LEGACY_BIOS_PROTOCOL *ParentLegacyBios, + IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +; + +EFI_STATUS +BiosVideoChildHandleUninstall ( + EFI_DRIVER_BINDING_PROTOCOL *This, + EFI_HANDLE Controller, + EFI_HANDLE Handle + ) +; + +VOID +BiosVideoDeviceReleaseResource ( + BIOS_VIDEO_DEV *BiosVideoPrivate + ) +; + +//*** AMI PORTING BEGIN ***// +//CsmVideo Policy Protocol support +//The protocol can be used to set the driver policy. +// The two supported policies are: +// SimpleTextOut over the text mode 3 (TextMode=TRUE) +// GOP over graphical mode (TextMode=FALSE) +EFI_HANDLE VgaControllerHandle = NULL; +BOOLEAN TextModePolicy = FALSE; + +EFI_STATUS CsmVideoPolicySetMode( + IN CSM_VIDEO_POLICY_PROTOCOL *This, + IN BOOLEAN TextMode, IN BOOLEAN ForceModeChange +){ +#if INT10_SIMPLE_TEXT_SUPPORT==0 + return (TextMode) ? EFI_UNSUPPORTED : EFI_SUCCESS; +#else + EFI_STATUS Status; + BOOLEAN OriginalPolicy=TextModePolicy; + EFI_HANDLE Handle; + + TextModePolicy = TextMode; + if ( VgaControllerHandle == NULL + || OriginalPolicy==TextModePolicy && !ForceModeChange + ) return EFI_SUCCESS; + + // save the VGA handle + // the global variable VgaControllerHandle will be nullified + // by the Stop function during Disconnect. + Handle = VgaControllerHandle; + Status = pBS->DisconnectController( Handle, NULL, NULL ); + if (!EFI_ERROR(Status)) + Status = pBS->ConnectController( Handle, NULL, NULL, TRUE ); + else + TextModePolicy = OriginalPolicy; + if (EFI_ERROR(Status)) return Status; + return (TextModePolicy==TextMode) ? EFI_SUCCESS : EFI_UNSUPPORTED; +#endif +} + +EFI_STATUS CsmVideoPolicyGetMode( + IN CSM_VIDEO_POLICY_PROTOCOL *This,IN BOOLEAN *IsTextMode +){ + if (IsTextMode!=NULL) *IsTextMode = TextModePolicy; + return (VgaControllerHandle == NULL) ? EFI_NOT_STARTED : EFI_SUCCESS; +} + +CSM_VIDEO_POLICY_PROTOCOL CsmVideoPolicyProtocol = { + CsmVideoPolicyGetMode, CsmVideoPolicySetMode +}; +//*** AMI PORTING END *****// + +EFI_STATUS GetBadEdid ( + IN EFI_EDID_OVERRIDE_PROTOCOL *This, + IN EFI_HANDLE *ChildHandle, + OUT UINT32 *Attributes, + IN OUT UINTN *EdidSize, + IN OUT UINT8 **Edid + ) +{ + static UINT8 EdidData[0x80] = {0}; + EdidData[0x7f] = 1; // invalid checksum + + *Edid = EdidData; + *EdidSize = 0x80; + *Attributes = 0; + + return EFI_SUCCESS; +} + + +// +// Driver Entry Point +// +EFI_DRIVER_ENTRY_POINT (BiosVideoDriverEntryPoint) + +EFI_STATUS +EFIAPI +BiosVideoDriverEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + + Routine Description: + + Driver Entry Point. + + Arguments: + + ImageHandle - Handle of driver image. + SystemTable - Pointer to system table. + + Returns: + + EFI_STATUS + +--*/ +{ + EFI_STATUS Status; + static EFI_GUID gCsmThunkDriverGuid = + { 0x2362ea9c, 0x84e5, 0x4dff, 0x83, 0xbc, 0xb5, 0xac, 0xec, 0xb5, 0x7c, 0xbb }; + + Status = EfiLibInstallAllDriverProtocols ( + ImageHandle, + SystemTable, + &gBiosVideoDriverBinding, + ImageHandle, +#if EFI_SPECIFICATION_VERSION <= 0x20000 + &gBiosVideoComponentName, +#else + &gBiosVideoComponentName2, +#endif + NULL, + NULL + ); +//*** AMI PORTING BEGIN ***// +#if INT10_SIMPLE_TEXT_SUPPORT==1 +{ +//create new handle + EFI_HANDLE Handle = NULL; + VgaClassDriverEntryPoint(Handle,SystemTable); +} +#endif + +#if INT10_TRUST_EDID_INFORMATION == 0 +{ + // Install EdidOverride with the dummy EDID information; this is needed to ignore + // bad EDID information + EFI_STATUS Status; + static EFI_EDID_OVERRIDE_PROTOCOL EdidOverride = { GetBadEdid }; + + Status = gBS->InstallMultipleProtocolInterfaces( + &ImageHandle, + &gEfiEdidOverrideProtocolGuid, &EdidOverride, + NULL + ); +} +#endif + +// Install CsmVideoPolicy protocol + gBS->InstallMultipleProtocolInterfaces( + &ImageHandle, + &gCsmVideoPolicyProtocolGuid, &CsmVideoPolicyProtocol, + &gCsmThunkDriverGuid, NULL, + NULL + ); + +//AMI CSM Core does not need Legacy BIOS GUID +//Just return the status + return Status; +/* + if (EFI_ERROR (Status)) { + return Status; + } + // + // Install Legacy BIOS GUID to mark this driver as a BIOS Thunk Driver + // + return gBS->InstallMultipleProtocolInterfaces ( + &ImageHandle, + &gEfiLegacyBiosGuid, + NULL, + NULL + ); +*/ +//*** AMI PORTING END *****// +} +//*** AMI PORTING BEGIN ***// +//Exit Boot Services callback is not needed. +/* +VOID +BiosVideoExitBootServices ( + EFI_EVENT Event, + VOID *Context + ) +*/ +/*++ + +Routine Description: + + Callback function for exit boot service event + +Arguments: + + Event - EFI_EVENT structure + Context - Event context + +Returns: + + None + +--*/ +/*{ + BIOS_VIDEO_DEV *BiosVideoPrivate; + EFI_IA32_REGISTER_SET Regs; + + // + // Get our context + // + BiosVideoPrivate = (BIOS_VIDEO_DEV *) Context; + + // + // Set the 80x25 Text VGA Mode + // + Regs.H.AH = 0x00; + Regs.H.AL = 0x83; + BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs); + + Regs.H.AH = 0x11; + Regs.H.AL = 0x14; + Regs.H.BL = 0; + BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs); +} +*/ +//*** AMI PORTING END *****// + +EFI_STATUS +EFIAPI +BiosVideoDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + + Routine Description: + + Supported. + + Arguments: + + This - Pointer to driver binding protocol + Controller - Controller handle to connect + RemainingDevicePath - A pointer to the remaining portion of a device path + + + Returns: + + EFI_STATUS - EFI_SUCCESS:This controller can be managed by this driver, + Otherwise, this controller cannot be managed by this driver + +--*/ +{ + EFI_STATUS Status; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; + EFI_PCI_IO_PROTOCOL *PciIo; + PCI_TYPE00 Pci; + + // + // See if the Legacy BIOS Protocol is available + // + Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Open the IO Abstraction(s) needed to perform the supported test + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // See if this is a PCI Graphics Controller by looking at the Command register and + // Class Code Register + // + Status = PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint32, + 0, + sizeof (Pci) / sizeof (UINT32), + &Pci + ); + if (EFI_ERROR (Status)) { + Status = EFI_UNSUPPORTED; + goto Done; + } + + Status = EFI_UNSUPPORTED; + if (Pci.Hdr.ClassCode[2] == 0x03 || (Pci.Hdr.ClassCode[2] == 0x00 && Pci.Hdr.ClassCode[1] == 0x01)) { + Status = EFI_SUCCESS; + } + +Done: + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return Status; +} + +EFI_STATUS +EFIAPI +BiosVideoDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + + Routine Description: + + Install Graphics Output Protocol onto VGA device handles + + Arguments: + + This - Pointer to driver binding protocol + Controller - Controller handle to connect + RemainingDevicePath - A pointer to the remaining portion of a device path + + Returns: + + EFI_STATUS + +--*/ +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; + EFI_PCI_IO_PROTOCOL *PciIo; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; + UINTN Flags; +//*** AMI PORTING BEGIN ***// +// See comments below regarding the Capabilities usage + UINT64 Capabilities = 0; +//*** AMI PORTING END *****// + + PciIo = NULL; + // + // Prepare for status code + // + Status = gBS->HandleProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + (VOID **) &ParentDevicePath + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + // + // Open the IO Abstraction(s) needed + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + // + // See if the Legacy BIOS Protocol is available + // + Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios); + if (EFI_ERROR (Status)) { + goto Done; + } + + ReportStatusCodeWithDevicePath ( + EFI_PROGRESS_CODE, + EFI_P_PC_ENABLE, + 0, + &gEfiCallerIdGuid, + ParentDevicePath + ); + // + // Enable the device and make sure VGA cycles are being forwarded to this VGA device + // +//*** AMI PORTING BEGIN ***// +// We need to check what is supported by the hardware before enabling attributes + Status = PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationSupported, + 0, + &Capabilities + ); + + if ( EFI_ERROR(Status) ) { + goto Done; + } + + Status = PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationEnable, + Capabilities & EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY | EFI_PCI_IO_ATTRIBUTE_VGA_IO, + NULL + ); +/* + Status = PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationEnable, + EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY | EFI_PCI_IO_ATTRIBUTE_VGA_IO, + NULL + ); +*/ +//*** AMI PORTING END *****// + if (EFI_ERROR (Status)) { + ReportStatusCodeWithDevicePath ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_RESOURCE_CONFLICT, + 0, + &gEfiCallerIdGuid, + ParentDevicePath + ); + goto Done; + } + // + // Check to see if there is a legacy option ROM image associated with this PCI device + // + Status = LegacyBios->CheckPciRom ( + LegacyBios, + Controller, + NULL, + NULL, + &Flags + ); + if (EFI_ERROR (Status)) { + goto Done; + } + // + // Post the legacy option ROM if it is available. + // + ReportStatusCodeWithDevicePath ( + EFI_PROGRESS_CODE, + EFI_P_PC_RESET, + 0, + &gEfiCallerIdGuid, + ParentDevicePath + ); + Status = LegacyBios->InstallPciRom ( + LegacyBios, + Controller, + NULL, + &Flags, + NULL, + NULL, + NULL, + NULL + ); + if (EFI_ERROR (Status)) { + ReportStatusCodeWithDevicePath ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_CONTROLLER_ERROR, + 0, + &gEfiCallerIdGuid, + ParentDevicePath + ); + goto Done; + } + + // + // Create child handle and install GraphicsOutputProtocol on it + // + Status = BiosVideoChildHandleInstall ( + This, + Controller, + PciIo, + LegacyBios, + ParentDevicePath, + RemainingDevicePath + ); + +Done: + if (EFI_ERROR (Status)) { + if (PciIo != NULL) { + ReportStatusCodeWithDevicePath ( + EFI_PROGRESS_CODE, + EFI_P_PC_DISABLE, + 0, + &gEfiCallerIdGuid, + ParentDevicePath + ); + // + // Turn off the PCI device and disable forwarding of VGA cycles to this device + // + if (Capabilities != 0) + { + PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationDisable, +//*** AMI PORTING BEGIN ***// + Capabilities & EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY | EFI_PCI_IO_ATTRIBUTE_VGA_IO, +// EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY | EFI_PCI_IO_ATTRIBUTE_VGA_IO, +//*** AMI PORTING END *****// + NULL + ); + } + // + // Release PCI I/O Protocols on the controller handle. + // + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + } + } + + return Status; +} + +EFI_STATUS +EFIAPI +BiosVideoDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +/*++ + + Routine Description: + + Stop. + + Arguments: + + This - Pointer to driver binding protocol + Controller - Controller handle to connect + NumberOfChilren - Number of children handle created by this driver + ChildHandleBuffer - Buffer containing child handle created + + Returns: + + EFI_SUCCESS - Driver disconnected successfully from controller + EFI_UNSUPPORTED - Cannot find BIOS_VIDEO_DEV structure + +--*/ +{ + EFI_STATUS Status; + BIOS_VIDEO_DEV *BiosVideoPrivate; + BOOLEAN AllChildrenStopped; + UINTN Index; + EFI_PCI_IO_PROTOCOL *PciIo; + UINT64 Capabilities; + + BiosVideoPrivate = NULL; + + if (NumberOfChildren == 0) { +//*** AMI PORTING BEGIN ***// +//In text mode, the child handle is not created +//and the mini port protocol is installed on the PciIo handle. +//Original implementation does not stop controller in this case +//Here is the fix: +#if INT10_SIMPLE_TEXT_SUPPORT==1 + Status = gBS->OpenProtocol ( + Controller, + &gEfiVgaMiniPortProtocolGuid, + NULL, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL + ); + if (!EFI_ERROR(Status)){ + return BiosVideoChildHandleUninstall (This, Controller, Controller); + } +#endif + + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + &PciIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + ASSERT_EFI_ERROR(Status); + + Status = PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationSupported, + 0, + &Capabilities + ); + ASSERT_EFI_ERROR(Status); + + Status = PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationDisable, + Capabilities & EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY | EFI_PCI_IO_ATTRIBUTE_VGA_IO, + NULL + ); + + ASSERT_EFI_ERROR(Status); + if(EFI_ERROR(Status)) return EFI_DEVICE_ERROR; +//*** AMI PORTING END *****// + // + // Close PCI I/O protocol on the controller handle + // + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return EFI_SUCCESS; + } + + AllChildrenStopped = TRUE; + for (Index = 0; Index < NumberOfChildren; Index++) { + Status = BiosVideoChildHandleUninstall (This, Controller, ChildHandleBuffer[Index]); + + if (EFI_ERROR (Status)) { + AllChildrenStopped = FALSE; + } + } + + if (!AllChildrenStopped) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +BiosVideoChildHandleInstall ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ParentHandle, + IN EFI_PCI_IO_PROTOCOL *ParentPciIo, + IN EFI_LEGACY_BIOS_PROTOCOL *ParentLegacyBios, + IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + Install child handles if the Handle supports MBR format. + +Arguments: + This - Calling context. + Handle - Parent Handle + PciIo - Parent PciIo interface + LegacyBios - Parent LegacyBios interface + DevicePath - Parent Device Path + +Returns: + EFI_SUCCESS - If a child handle was added + other - A child handle was not added + +--*/ +{ + EFI_STATUS Status; + BIOS_VIDEO_DEV *BiosVideoPrivate; + PCI_TYPE00 Pci; + ACPI_ADR_DEVICE_PATH AcpiDeviceNode; + + // + // Allocate the private device structure for video device + // + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (BIOS_VIDEO_DEV), + &BiosVideoPrivate + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + EfiZeroMem (BiosVideoPrivate, sizeof (BIOS_VIDEO_DEV)); + + // + // See if this is a VGA compatible controller or not + // + Status = ParentPciIo->Pci.Read ( + ParentPciIo, + EfiPciIoWidthUint32, + 0, + sizeof (Pci) / sizeof (UINT32), + &Pci + ); + if (EFI_ERROR (Status)) { + ReportStatusCodeWithDevicePath ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_CONTROLLER_ERROR, + 0, + &gEfiCallerIdGuid, + ParentDevicePath + ); + goto Done; + } + BiosVideoPrivate->VgaCompatible = FALSE; + if (Pci.Hdr.ClassCode[2] == 0x00 && Pci.Hdr.ClassCode[1] == 0x01) { + BiosVideoPrivate->VgaCompatible = TRUE; + } + + if (Pci.Hdr.ClassCode[2] == 0x03 && Pci.Hdr.ClassCode[1] == 0x00 && Pci.Hdr.ClassCode[0] == 0x00) { + BiosVideoPrivate->VgaCompatible = TRUE; + } + + // + // Initialize the child private structure + // + BiosVideoPrivate->Signature = BIOS_VIDEO_DEV_SIGNATURE; + BiosVideoPrivate->Handle = NULL; + +//*** AMI PORTING BEGIN ***// +//Exit Boot Services callback is not needed. +/* + Status = gBS->CreateEvent ( + EFI_EVENT_SIGNAL_EXIT_BOOT_SERVICES, + EFI_TPL_NOTIFY, + BiosVideoExitBootServices, + BiosVideoPrivate, + &BiosVideoPrivate->ExitBootServicesEvent + ); + if (EFI_ERROR (Status)) { + goto Done; + } +*/ +//*** AMI PORTING END *****// + + // + // Fill in Graphics Output specific mode structures + // + BiosVideoPrivate->HardwareNeedsStarting = TRUE; + BiosVideoPrivate->ModeData = NULL; + BiosVideoPrivate->LineBuffer = NULL; + BiosVideoPrivate->VgaFrameBuffer = NULL; + BiosVideoPrivate->VbeFrameBuffer = NULL; + +//*** AMI PORTING BEGIN ***// +//Let's do it only if VgaMiniPort is going to be installed +/* + // + // Fill in the VGA Mini Port Protocol fields + // + BiosVideoPrivate->VgaMiniPort.SetMode = BiosVideoVgaMiniPortSetMode; + BiosVideoPrivate->VgaMiniPort.VgaMemoryOffset = 0xb8000; + BiosVideoPrivate->VgaMiniPort.CrtcAddressRegisterOffset = 0x3d4; + BiosVideoPrivate->VgaMiniPort.CrtcDataRegisterOffset = 0x3d5; + BiosVideoPrivate->VgaMiniPort.VgaMemoryBar = EFI_PCI_IO_PASS_THROUGH_BAR; + BiosVideoPrivate->VgaMiniPort.CrtcAddressRegisterBar = EFI_PCI_IO_PASS_THROUGH_BAR; + BiosVideoPrivate->VgaMiniPort.CrtcDataRegisterBar = EFI_PCI_IO_PASS_THROUGH_BAR; +*/ + // + // Assume that Graphics Output Protocol will be produced until proven otherwise + // + BiosVideoPrivate->ProduceGraphicsOutput = TRUE; + + // + // Set Gop Device Path, here RemainingDevicePath will not be one End of Device Path Node. + // + if ((RemainingDevicePath == NULL) || (!IsDevicePathEnd (RemainingDevicePath))) { + if (RemainingDevicePath == NULL) { + EfiZeroMem (&AcpiDeviceNode, sizeof (ACPI_ADR_DEVICE_PATH)); + AcpiDeviceNode.Header.Type = ACPI_DEVICE_PATH; + AcpiDeviceNode.Header.SubType = ACPI_ADR_DP; + AcpiDeviceNode.ADR = ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA, 0, 0); + SetDevicePathNodeLength (&AcpiDeviceNode.Header, sizeof (ACPI_ADR_DEVICE_PATH)); + + BiosVideoPrivate->DevicePath = EfiAppendDevicePathNode ( + ParentDevicePath, + (EFI_DEVICE_PATH_PROTOCOL *) &AcpiDeviceNode + ); + } else { + BiosVideoPrivate->DevicePath = EfiAppendDevicePathNode (ParentDevicePath, RemainingDevicePath); + } + + // + // Create child handle associated with device path + // The newely created handle can be used for calling EDID_OVERRIDE_PROTOCOL + // + BiosVideoPrivate->Handle = NULL; + Status = gBS->InstallMultipleProtocolInterfaces ( + &BiosVideoPrivate->Handle, + &gEfiDevicePathProtocolGuid, + BiosVideoPrivate->DevicePath, + NULL + ); + if (EFI_ERROR (Status)) { + goto Done; + } + } + + // + // Child handle need to consume the Legacy Bios protocol + // + BiosVideoPrivate->LegacyBios = ParentLegacyBios; + + // + // When check for VBE, PCI I/O protocol is needed, so use parent's protocol interface temporally + // + BiosVideoPrivate->PciIo = ParentPciIo; + + // + // Check for VESA BIOS Extensions for modes that are compatible with Graphics Output + // +//*** AMI PORTING BEGIN ***// +// Status = BiosVideoCheckForVbe (BiosVideoPrivate); +#if INT10_VESA_GO_SUPPORT==1 + if ( TextModePolicy ) + Status = EFI_UNSUPPORTED; + else + Status = BiosVideoCheckForVbe (BiosVideoPrivate, &Pci); +#else + Status = EFI_UNSUPPORTED; +#endif +//*** AMI PORTING END *****// + if (EFI_ERROR (Status)) { + // + // The VESA BIOS Extensions are not compatible with Graphics Output, so check for support + // for the standard 640x480 16 color VGA mode + // +//*** AMI PORTING BEGIN ***// +// if (BiosVideoPrivate->VgaCompatible) { +// Status = BiosVideoCheckForVga (BiosVideoPrivate); +// } +#if INT10_VGA_GO_SUPPORT==1 + if (!TextModePolicy && BiosVideoPrivate->VgaCompatible) { + Status = BiosVideoCheckForVga (BiosVideoPrivate); + } +#endif +//*** AMI PORTING END *****// + + if (EFI_ERROR (Status)) { + // + // Neither VBE nor the standard 640x480 16 color VGA mode are supported, so do + // not produce the Graphics Output protocol. Instead, produce the VGA MiniPort Protocol. + // + BiosVideoPrivate->ProduceGraphicsOutput = FALSE; + + // + // INT services are available, so on the 80x25 and 80x50 text mode are supported + // + BiosVideoPrivate->VgaMiniPort.MaxMode = 2; + } + } + + if (BiosVideoPrivate->ProduceGraphicsOutput) { + // + // Create child handle and install Graphics Output Protocol,EDID Discovered/Active Protocol + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &BiosVideoPrivate->Handle, + &gEfiGraphicsOutputProtocolGuid, + &BiosVideoPrivate->GraphicsOutput, + &gEfiEdidDiscoveredProtocolGuid, + &BiosVideoPrivate->EdidDiscovered, + &gEfiEdidActiveProtocolGuid, + &BiosVideoPrivate->EdidActive, + NULL + ); + + if (!EFI_ERROR (Status)) { + // + // Open the Parent Handle for the child + // + Status = gBS->OpenProtocol ( + ParentHandle, + &gEfiPciIoProtocolGuid, + (VOID **) &BiosVideoPrivate->PciIo, + This->DriverBindingHandle, + BiosVideoPrivate->Handle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + } + } else { +//*** AMI PORTING BEGIN ***// +#if INT10_SIMPLE_TEXT_SUPPORT==1 +//The code if moved here from BiosVideoChildHandleInstall + // + // Fill in the VGA Mini Port Protocol fields + // + BiosVideoPrivate->VgaMiniPort.SetMode = BiosVideoVgaMiniPortSetMode; + BiosVideoPrivate->VgaMiniPort.VgaMemoryOffset = 0xb8000; + BiosVideoPrivate->VgaMiniPort.CrtcAddressRegisterOffset = 0x3d4; + BiosVideoPrivate->VgaMiniPort.CrtcDataRegisterOffset = 0x3d5; + BiosVideoPrivate->VgaMiniPort.VgaMemoryBar = EFI_PCI_IO_PASS_THROUGH_BAR; + BiosVideoPrivate->VgaMiniPort.CrtcAddressRegisterBar = EFI_PCI_IO_PASS_THROUGH_BAR; + BiosVideoPrivate->VgaMiniPort.CrtcDataRegisterBar = EFI_PCI_IO_PASS_THROUGH_BAR; +//*** AMI PORTING END *****// +//*** AMI PORTING BEGIN ***// + //This is needed! Otherwise VgaClass driver rejects VgaMiniPort + //device due to the lack of PciIo protocol + BiosVideoPrivate->Handle=ParentHandle; +//*** AMI PORTING END *****// + // + // Install VGA Mini Port Protocol + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &BiosVideoPrivate->Handle, + &gEfiVgaMiniPortProtocolGuid, + &BiosVideoPrivate->VgaMiniPort, + NULL + ); +//*** AMI PORTING BEGIN ***// +#else +#endif //INT10_SIMPLE_TEXT_SUPPORT==1 +//*** AMI PORTING END *****// + } + +Done: + if (EFI_ERROR (Status)) { + // + // Free private data structure + // + BiosVideoDeviceReleaseResource (BiosVideoPrivate); + } +//*** AMI PORTING BEGIN ***// +// The protocols are installed. +// Update global variables used by the CsmVideoPolicy protocol implementation. + TextModePolicy = !BiosVideoPrivate->ProduceGraphicsOutput; + VgaControllerHandle = ParentHandle; +//*** AMI PORTING END *****// + return Status; +} + +EFI_STATUS +BiosVideoChildHandleUninstall ( + EFI_DRIVER_BINDING_PROTOCOL *This, + EFI_HANDLE Controller, + EFI_HANDLE Handle + ) +/*++ + +Routine Description: + + Deregister an video child handle and free resources + +Arguments: + + This - Protocol instance pointer. + Controller - Video controller handle + Handle - Video child handle + +Returns: + + EFI_STATUS + +--*/ +{ + EFI_STATUS Status; + EFI_IA32_REGISTER_SET Regs; + EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; + EFI_VGA_MINI_PORT_PROTOCOL *VgaMiniPort; + BIOS_VIDEO_DEV *BiosVideoPrivate; + EFI_PCI_IO_PROTOCOL *PciIo; + + BiosVideoPrivate = NULL; + + Status = gBS->OpenProtocol ( + Handle, + &gEfiGraphicsOutputProtocolGuid, + (VOID **) &GraphicsOutput, + This->DriverBindingHandle, + Handle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (GraphicsOutput); + } + + Status = gBS->OpenProtocol ( + Handle, + &gEfiVgaMiniPortProtocolGuid, + (VOID **) &VgaMiniPort, + This->DriverBindingHandle, + Handle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_VGA_MINI_PORT_THIS (VgaMiniPort); + } + + if (BiosVideoPrivate == NULL) { + return EFI_UNSUPPORTED; + } + + // + // Close PCI I/O protocol that opened by child handle + // + Status = gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Handle + ); + + // + // Uninstall protocols on child handle + // + if (BiosVideoPrivate->ProduceGraphicsOutput) { + Status = gBS->UninstallMultipleProtocolInterfaces ( + BiosVideoPrivate->Handle, + &gEfiDevicePathProtocolGuid, + BiosVideoPrivate->DevicePath, + &gEfiGraphicsOutputProtocolGuid, + &BiosVideoPrivate->GraphicsOutput, + &gEfiEdidDiscoveredProtocolGuid, + &BiosVideoPrivate->EdidDiscovered, + &gEfiEdidActiveProtocolGuid, + &BiosVideoPrivate->EdidActive, + NULL + ); + } else { + Status = gBS->UninstallMultipleProtocolInterfaces ( + BiosVideoPrivate->Handle, + &gEfiVgaMiniPortProtocolGuid, + &BiosVideoPrivate->VgaMiniPort, + NULL + ); + } + if (EFI_ERROR (Status)) { + gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + Handle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + return Status; + } + + // + // Set the 80x25 Text VGA Mode + // + Regs.H.AH = 0x00; + Regs.H.AL = 0x03; + BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs); + + Regs.H.AH = 0x11; + Regs.H.AL = 0x14; + Regs.H.BL = 0; + BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs); + + // + // Do not disable IO/memory decode since that would prevent legacy ROM from working + // + + // + // Release all allocated resources + // + BiosVideoDeviceReleaseResource (BiosVideoPrivate); +//*** AMI PORTING BEGIN ***// +// The protocols are uninstalled. +// Update global variables used by the CsmVideoPolicy protocol implementation. + VgaControllerHandle = NULL; +//*** AMI PORTING END *****// + return EFI_SUCCESS; +} + +VOID +BiosVideoDeviceReleaseResource ( + BIOS_VIDEO_DEV *BiosVideoPrivate + ) +/*++ +Routing Description: + + Release resources of an video child device before stopping it. + +Arguments: + + BiosVideoPrivate - Video child device private data structure + +Returns: + + NONE + +---*/ +{ + if (BiosVideoPrivate == NULL) { + return ; + } + + // + // Release all the resourses occupied by the BIOS_VIDEO_DEV + // + + // + // Free VGA Frame Buffer + // + if (BiosVideoPrivate->VgaFrameBuffer != NULL) { + gBS->FreePool (BiosVideoPrivate->VgaFrameBuffer); + BiosVideoPrivate->VgaFrameBuffer = NULL; + } + // + // Free VBE Frame Buffer + // + if (BiosVideoPrivate->VbeFrameBuffer != NULL) { + gBS->FreePool (BiosVideoPrivate->VbeFrameBuffer); + BiosVideoPrivate->VbeFrameBuffer = NULL; + } + // + // Free line buffer + // + if (BiosVideoPrivate->LineBuffer != NULL) { + gBS->FreePool (BiosVideoPrivate->LineBuffer); + BiosVideoPrivate->LineBuffer = NULL; + } + // + // Free mode data + // + if (BiosVideoPrivate->ModeData != NULL) { + gBS->FreePool (BiosVideoPrivate->ModeData); + BiosVideoPrivate->ModeData = NULL; + } + // + // Free memory allocated below 1MB + // + if (BiosVideoPrivate->PagesBelow1MB != 0) { + gBS->FreePages (BiosVideoPrivate->PagesBelow1MB, BiosVideoPrivate->NumberOfPagesBelow1MB); + } + + if (BiosVideoPrivate->VbeSaveRestorePages != 0) { + gBS->FreePages (BiosVideoPrivate->VbeSaveRestoreBuffer, BiosVideoPrivate->VbeSaveRestorePages); + } + // + // Free graphics output protocol occupied resource + // + if (BiosVideoPrivate->GraphicsOutput.Mode != NULL) { + if (BiosVideoPrivate->GraphicsOutput.Mode->Info != NULL) { + gBS->FreePool (BiosVideoPrivate->GraphicsOutput.Mode->Info); + BiosVideoPrivate->GraphicsOutput.Mode->Info = NULL; + } + gBS->FreePool (BiosVideoPrivate->GraphicsOutput.Mode); + BiosVideoPrivate->GraphicsOutput.Mode = NULL; + } + // + // Free EDID discovered protocol occupied resource + // + if (BiosVideoPrivate->EdidDiscovered.Edid != NULL) { + gBS->FreePool (BiosVideoPrivate->EdidDiscovered.Edid); + BiosVideoPrivate->EdidDiscovered.Edid = NULL; + } + // + // Free EDID active protocol occupied resource + // + if (BiosVideoPrivate->EdidActive.Edid != NULL) { + gBS->FreePool (BiosVideoPrivate->EdidActive.Edid); + BiosVideoPrivate->EdidActive.Edid = NULL; + } + + if (BiosVideoPrivate->DevicePath!= NULL) { + gBS->FreePool (BiosVideoPrivate->DevicePath); + BiosVideoPrivate->DevicePath = NULL; + } + + // + // Close the ExitBootServices event + // +//*** AMI PORTING BEGIN ***// +//ExitBootServicesEvent is not used +/* + if (BiosVideoPrivate->ExitBootServicesEvent != NULL) { + gBS->CloseEvent (BiosVideoPrivate->ExitBootServicesEvent); + } +*/ +//*** AMI PORTING END *****// + + gBS->FreePool (BiosVideoPrivate); + + return ; +} + +//*** AMI PORTING BEGIN ***// +#if INT10_VESA_GO_SUPPORT==1 +//*** AMI PORTING END *****// +STATIC +UINT32 +CalculateEdidKey ( + VESA_BIOS_EXTENSIONS_EDID_TIMING *EdidTiming + ) +/*++ + + Routine Description: + + Generate a search key for a specified timing data. + + Arguments: + + EdidTiming - Pointer to EDID timing + + Returns: + The 32 bit unique key for search. + +--*/ +{ + UINT32 Key; + + // + // Be sure no conflicts for all standard timing defined by VESA. + // + Key = (EdidTiming->HorizontalResolution * 2) + EdidTiming->VerticalResolution + EdidTiming->RefreshRate; + return Key; +} + +STATIC +BOOLEAN +ParseEdidData ( + UINT8 *EdidBuffer + ) +/*++ + + Routine Description: + + Parse the Established Timing and Standard Timing in EDID data block. + + Arguments: + + EdidBuffer - Pointer to EDID data block + ValidEdidTiming - Valid EDID timing information + + Returns: + TRUE - The EDID data is valid. + FALSE - The EDID data is invalid. + +--*/ +{ + UINT8 CheckSum; + UINT32 Index; + UINT32 ValidNumber; + UINT32 TimingBits; + UINT8 *BufferIndex; + UINT16 HorizontalResolution; + UINT16 VerticalResolution; + UINT8 AspectRatio; + VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK *EdidDataBlock; + + EdidDataBlock = (VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK *) EdidBuffer; + + // + // Check the checksum of EDID data + // + CheckSum = 0; + for (Index = 0; Index < VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE; Index ++) { + CheckSum = CheckSum + EdidBuffer[Index]; + } + if (CheckSum != 0) { + TRACE((TRACE_BIOS_VIDEO, "EDID checksum is invalid, EDID will be ignored.\n")); + return FALSE; + } + + ValidNumber = 0; + // + // Established timing data + // + TimingBits = EdidDataBlock->EstablishedTimings[0] | + (EdidDataBlock->EstablishedTimings[1] << 8) | + ((EdidDataBlock->EstablishedTimings[2] & 0x80) << 9) ; + for (Index = 0; Index < VESA_BIOS_EXTENSIONS_EDID_ESTABLISHED_TIMING_MAX_NUMBER; Index ++) { + if (TimingBits & 0x1) { + SupportedResolutions[Index] = mEstablishedEdidTiming[Index].VerticalResolution | + (mEstablishedEdidTiming[Index].HorizontalResolution << 16); + ValidNumber ++; + } + TimingBits = TimingBits >> 1; + } + + // + // If no Established timing data, read the standard timing data + // + BufferIndex = &EdidDataBlock->StandardTimingIdentification[0]; + for (Index = 0; Index < 8; Index ++) { + if ((BufferIndex[0] != 0x1) && (BufferIndex[1] != 0x1)){ + // + // A valid Standard Timing + // + HorizontalResolution = BufferIndex[0] * 8 + 248; + AspectRatio = BufferIndex[1] >> 6; + switch (AspectRatio) { + case 0: + VerticalResolution = HorizontalResolution / 16 * 10; + break; + case 1: + VerticalResolution = HorizontalResolution / 4 * 3; + break; + case 2: + VerticalResolution = HorizontalResolution / 5 * 4; + break; + case 3: + VerticalResolution = HorizontalResolution / 16 * 9; + break; + default: + VerticalResolution = HorizontalResolution / 4 * 3; + break; + } + + SupportedResolutions[Index + 17] = VerticalResolution |(HorizontalResolution << 16); + ValidNumber ++; + } + BufferIndex += 2; + } + + if ( (EdidDataBlock->FeatureSupport & 2) == 2) { + // Preferred timing mode is indicated in the first detailed timing block + for (Index = 0; Index < 4; Index ++) { + if ((EdidDataBlock->DetailedTimingDescriptions[Index*18 + 0] | + EdidDataBlock->DetailedTimingDescriptions[Index*18 + 1]) && + (EdidDataBlock->DetailedTimingDescriptions[Index*18 + 2] | + (EdidDataBlock->DetailedTimingDescriptions[Index*18 + 4] & 0xf0))) { + + SupportedResolutions[Index + 25] = + (EdidDataBlock->DetailedTimingDescriptions[Index*18 + 5] | ((UINT16)(EdidDataBlock->DetailedTimingDescriptions[Index*18 + 7] & 0xF0) << 4)) + | ((UINT32)(EdidDataBlock->DetailedTimingDescriptions[Index*18 + 2] | ((UINT16)(EdidDataBlock->DetailedTimingDescriptions[Index*18 + 4] & 0xF0) << 4)) << 16); + +TRACE((TRACE_BIOS_VIDEO, "EDID Detailed timing[%d]: inserted resolution 0x%x (%dx%d)\n", Index, SupportedResolutions[Index + 25], + EdidDataBlock->DetailedTimingDescriptions[Index*18 + 2] | ((EdidDataBlock->DetailedTimingDescriptions[Index*18 + 4] & 0xF0) << 4), + EdidDataBlock->DetailedTimingDescriptions[Index*18 + 5] | ((EdidDataBlock->DetailedTimingDescriptions[Index*18 + 7] & 0xF0) << 4) +)); + + ValidNumber ++; + } + } + } + +//*** AMI PORTING BEGIN ***// +// Bug fix. The function was returning TRUE even when no valid timings found. +// return TRUE; + return (ValidNumber != 0); +//*** AMI PORTING END ***// +} + +STATIC +BOOLEAN +SearchEdidTiming ( + UINT32 ResolutionKey + ) +/*++ + + Routine Description: + + Search a specified Timing in all the valid EDID timings. + + Arguments: + + ValidEdidTiming - All valid EDID timing information. + EdidTiming - The Timing to search for. + + Returns: + + TRUE - Found. + FALSE - Not found. + +--*/ +{ + UINT32 Index; + for (Index = 0; Index < 29; Index ++) { + if (ResolutionKey == SupportedResolutions[Index]) { + return TRUE; + } + } + + return FALSE; +} + +//*** AMI PORTING BEGIN ***// +#if CSM_VGA_64BITBAR_WORKAROUND +BOOLEAN CheckAbove4g(PCI_TYPE00 *PciConfSpace){ + UINTN i; +//--------------------- + for(i=0; i<PCI_MAX_BAR-1;i++){ + //check all six bars if + if((PciConfSpace->Device.Bar[i] & 0x04) && ( PciConfSpace->Device.Bar[i+1]!=0) ) return TRUE; + } + return FALSE; +} + + +EFI_STATUS Update64BitLinearBufferAddr(EFI_PCI_IO_PROTOCOL *PciIo, UINT64 *LowerAddrPart, PCI_TYPE00 *PciConfSpace){ + UINTN i,j; + EFI_STATUS Status; + ASLR_QWORD_ASD *BarRes=NULL; + UINT64 start, end, bar, test; + UINT32 *pUp32; +//----------------------------- + + //pBS->SetMem(&BarRes[0], sizeof(BarRes), 0); + //Get PciIo Bar ACPI QW Resource Descriptor and Count... + + for(i=0; i<PCI_MAX_BAR; i++){ + //Free Memory allocated for us by PciBus Driver... + //if we got here by continue statement... + if(BarRes!=NULL){ + pBS->FreePool(BarRes); + BarRes=NULL; + } + + Status = PciIo->GetBarAttributes(PciIo,(UINT8)i, NULL, &BarRes); + if(EFI_ERROR(Status)) return Status; + + //care only about 64 bit resources end filter out Unused BARs and NOT64bit BARs + if(BarRes->Hdr.Name==ASLV_SR_EndTag) continue; + if(BarRes->_GRA < 64) continue; + + start=BarRes->_MIN; + end=BarRes->_MAX; + test=*LowerAddrPart; + + //Free Memory allocated for us by PciBus Driver... + if(BarRes!=NULL){ + pBS->FreePool(BarRes); + BarRes=NULL; + } + + //now try to match what we read from PCI Config to Res Descriptor returned by the call to PciIo... + for(j=0, bar=0; j<PCI_MAX_BAR-1;j++){ + if(PciConfSpace->Device.Bar[j] & 0x04){ + //here we got 64 bit BAR.... + bar=PciConfSpace->Device.Bar[j] & (~0xF); //Mask read only Bar Type bits... + //fill Upper Part of BAR address + j++; + pUp32=((UINT32*)&bar)+1; + *pUp32=PciConfSpace->Device.Bar[j]; + pUp32=((UINT32*)&test)+1; + *pUp32=PciConfSpace->Device.Bar[j]; + + //Check if we found match? + if(start==bar){ + if((start <= test) && (test < end)) { + *LowerAddrPart=test; + return EFI_SUCCESS; + } else break; + } + } + } + } + return EFI_SUCCESS; +} +#endif +//*** AMI PORTING END *****// + +EFI_STATUS CheckForDuplicateMode (BIOS_VIDEO_DEV *VideoDev, UINTN ModeNumber) +{ + UINT16 Xres = VideoDev->VbeModeInformationBlock->XResolution; + UINT16 Yres = VideoDev->VbeModeInformationBlock->YResolution; + UINTN i; + BIOS_VIDEO_MODE_DATA *ModeData = VideoDev->ModeData; + + // walk through the list of published modes, see if there is a match + for (i = 0; i < ModeNumber; i++) + { + if (ModeData->HorizontalResolution == Xres + && ModeData->VerticalResolution == Yres) + { + return EFI_SUCCESS; + } + ModeData++; + } + return EFI_NOT_FOUND; +} + +EFI_STATUS +EFIAPI +BiosVideoCheckForVbe ( + IN OUT BIOS_VIDEO_DEV *BiosVideoPrivate, +//*** AMI PORTING BEGIN ***// + PCI_TYPE00 *PciConfSpace +//*** AMI PORTING END *****// + ) +/*++ + + Routine Description: + + Check for VBE device + + Arguments: + + BiosVideoPrivate - Pointer to BIOS_VIDEO_DEV structure + + Returns: + + EFI_SUCCESS - VBE device found + +--*/ +{ + EFI_STATUS Status; + EFI_IA32_REGISTER_SET Regs; + UINT16 *ModeNumberPtr; + BOOLEAN ModeFound; + BOOLEAN EdidFound; + BOOLEAN EdidMatch; + BIOS_VIDEO_MODE_DATA *ModeBuffer; + BIOS_VIDEO_MODE_DATA *CurrentModeData; + UINTN PreferMode; + UINTN ModeNumber; + UINT32 ResolutionKey; + EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *GraphicsOutputMode; + INT32 i; + EFI_EDID_OVERRIDE_PROTOCOL *EdidOverride; + UINT32 EdidAttributes; + BOOLEAN EdidOverrideFound; + UINTN EdidOverrideDataSize; + UINT8 *EdidOverrideDataBlock; + UINTN EdidActiveDataSize; + UINT8 *EdidActiveDataBlock; +//*** AMI PORTING BEGIN ***// +#if CSM_VGA_64BITBAR_WORKAROUND + BOOLEAN Above4g; +#endif +//*** AMI PORTING END *****// + + EdidOverrideFound = FALSE; + EdidOverrideDataBlock = NULL; + EdidActiveDataSize = 0; + EdidActiveDataBlock = NULL; + +//*** AMI PORTING BEGIN ***// +#if CSM_VGA_64BITBAR_WORKAROUND + Above4g=CheckAbove4g(PciConfSpace); +#endif +//*** AMI PORTING END *****// + + // + // Allocate buffer under 1MB for VBE data structures + // + BiosVideoPrivate->NumberOfPagesBelow1MB = EFI_SIZE_TO_PAGES ( + sizeof (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK) + + sizeof (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK) + + sizeof (VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK) + + sizeof (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK) + ); + + BiosVideoPrivate->PagesBelow1MB = 0x00100000 - 1; + + Status = gBS->AllocatePages ( + AllocateMaxAddress, + EfiBootServicesData, + BiosVideoPrivate->NumberOfPagesBelow1MB, + &BiosVideoPrivate->PagesBelow1MB + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Fill in the Graphics Output Protocol + // + BiosVideoPrivate->GraphicsOutput.QueryMode = BiosVideoGraphicsOutputQueryMode; + BiosVideoPrivate->GraphicsOutput.SetMode = BiosVideoGraphicsOutputSetMode; + BiosVideoPrivate->GraphicsOutput.Blt = BiosVideoGraphicsOutputVbeBlt; + BiosVideoPrivate->GraphicsOutput.Mode = NULL; + + // + // Fill in the VBE related data structures + // + BiosVideoPrivate->VbeInformationBlock = (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK *) (UINTN) (BiosVideoPrivate->PagesBelow1MB); + BiosVideoPrivate->VbeModeInformationBlock = (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK *) (BiosVideoPrivate->VbeInformationBlock + 1); + BiosVideoPrivate->VbeEdidDataBlock = (VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK *) (BiosVideoPrivate->VbeModeInformationBlock + 1); + BiosVideoPrivate->VbeCrtcInformationBlock = (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK *) (BiosVideoPrivate->VbeModeInformationBlock + 1); + BiosVideoPrivate->VbeSaveRestorePages = 0; + BiosVideoPrivate->VbeSaveRestoreBuffer = 0; + + // + // Test to see if the Video Adapter is compliant with VBE 3.0 + // + gBS->SetMem (&Regs, sizeof (Regs), 0); + Regs.X.AX = VESA_BIOS_EXTENSIONS_RETURN_CONTROLLER_INFORMATION; + gBS->SetMem (BiosVideoPrivate->VbeInformationBlock, sizeof (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK), 0); + BiosVideoPrivate->VbeInformationBlock->VESASignature = VESA_BIOS_EXTENSIONS_VBE2_SIGNATURE; + Regs.X.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeInformationBlock); + Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeInformationBlock); + + BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs); + + Status = EFI_DEVICE_ERROR; + + // + // See if the VESA call succeeded + // + if (Regs.X.AX != VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) { + return Status; + } + // + // Check for 'VESA' signature + // + if (BiosVideoPrivate->VbeInformationBlock->VESASignature != VESA_BIOS_EXTENSIONS_VESA_SIGNATURE) { + return Status; + } + // + // Check to see if this is VBE 2.0 or higher + // + if (BiosVideoPrivate->VbeInformationBlock->VESAVersion < VESA_BIOS_EXTENSIONS_VERSION_2_0) { + return Status; + } + + EdidFound = FALSE; + EdidAttributes = 0xff; + EdidOverrideDataSize = 0; + + // + // Check if EDID Override protocol is installed by platform. + // + Status = gBS->LocateProtocol ( + &gEfiEdidOverrideProtocolGuid, + NULL, + (VOID **) &EdidOverride + ); + + if (!EFI_ERROR (Status)) { + // + // Allocate double size of VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE to avoid overflow + // + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof ((VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE * 2)), + &EdidOverrideDataBlock + ); + + if (EFI_ERROR(Status)) { + goto Done; + } + + Status = EdidOverride->GetEdid ( + EdidOverride, + BiosVideoPrivate->Handle, + &EdidAttributes, + &EdidOverrideDataSize, + (UINT8 **) &EdidOverrideDataBlock + ); + if (!EFI_ERROR (Status) && +//*** AMI PORTING BEGIN ***// +// EdidAttributes == 0 && +//*** AMI PORTING END ***// + EdidOverrideDataSize != 0) { + // + // Succeeded to get EDID Override Data + // + TRACE((TRACE_BIOS_VIDEO, "EDID override protocol found: data size %x, attribute %x\n", EdidOverrideDataSize, EdidAttributes)); + EdidOverrideFound = TRUE; + } + } + + + // "EdidFound" is forcibly FALSE, + // because some SSUs(Server Switch Unit) return invalid response. + if (!EdidOverrideFound || EdidAttributes == EFI_EDID_OVERRIDE_DONT_OVERRIDE) { + // + // If EDID Override data doesn't exist or EFI_EDID_OVERRIDE_DONT_OVERRIDE returned, + // read EDID information through INT10 call and fill in EdidDiscovered structure + // + gBS->SetMem (&Regs, sizeof (Regs), 0); + Regs.X.AX = VESA_BIOS_EXTENSIONS_EDID; + Regs.X.BX = 1; + Regs.X.CX = 0; + Regs.X.DX = 0; + Regs.X.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeEdidDataBlock); + Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeEdidDataBlock); + + BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs); + if (Regs.X.AX == VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) { + + BiosVideoPrivate->EdidDiscovered.SizeOfEdid = VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE; + Status = gBS->AllocatePool ( + EfiBootServicesData, + VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE, + &BiosVideoPrivate->EdidDiscovered.Edid + ); + if (EFI_ERROR (Status)) { + goto Done; + } + gBS->CopyMem ( + BiosVideoPrivate->EdidDiscovered.Edid, + BiosVideoPrivate->VbeEdidDataBlock, + VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE + ); + + EdidFound = TRUE; + } + } + + // + // Set up ActiveEdid data pointer and size + // + if (EdidFound) { + EdidActiveDataSize = VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE; + EdidActiveDataBlock = BiosVideoPrivate->EdidDiscovered.Edid; + } else if (EdidOverrideFound) { + EdidActiveDataSize = EdidOverrideDataSize; + EdidActiveDataBlock = EdidOverrideDataBlock; + EdidFound = TRUE; + } + + if (EdidFound) { + // + // Parse EDID data structure to retrieve modes supported by monitor + // + if (ParseEdidData ((UINT8 *) EdidActiveDataBlock) == TRUE) { + // + // Copy EDID Override Data to EDID Active Data + // + BiosVideoPrivate->EdidActive.SizeOfEdid = (UINT32)EdidActiveDataSize; + Status = gBS->AllocatePool ( + EfiBootServicesData, + EdidActiveDataSize, + &BiosVideoPrivate->EdidActive.Edid + ); + if (EFI_ERROR (Status)) { + goto Done; + } + gBS->CopyMem ( + BiosVideoPrivate->EdidActive.Edid, + EdidActiveDataBlock, + EdidActiveDataSize + ); + } + } else { + BiosVideoPrivate->EdidActive.SizeOfEdid = 0; + BiosVideoPrivate->EdidActive.Edid = NULL; + EdidFound = FALSE; + } + + // + // Walk through the mode list to see if there is at least one mode the is compatible with the EDID mode + // + ModeNumberPtr = (UINT16 *) + ( + (((UINTN) BiosVideoPrivate->VbeInformationBlock->VideoModePtr & 0xffff0000) >> 12) | + ((UINTN) BiosVideoPrivate->VbeInformationBlock->VideoModePtr & 0x0000ffff) + ); + + PreferMode = 0; + ModeNumber = 0; + + TRACE((TRACE_BIOS_VIDEO, "VESA: fetching the list of VESA modes supported by the controller from %x\n", ModeNumberPtr)); + + for (; *ModeNumberPtr != VESA_BIOS_EXTENSIONS_END_OF_MODE_LIST; ModeNumberPtr++) { + // + // Make sure this is a mode number defined by the VESA VBE specification. If it isn'tm then skip this mode number. + // + TRACE((TRACE_BIOS_VIDEO,"VESA mode %x ", *ModeNumberPtr)); + + if ((*ModeNumberPtr & VESA_BIOS_EXTENSIONS_MODE_NUMBER_VESA) == 0) { + TRACE((TRACE_BIOS_VIDEO,".. skipping as it is not a proper VESA mode number\n")); + continue; + } + + // + // Get the information about the mode + // + gBS->SetMem (&Regs, sizeof (Regs), 0); + Regs.X.AX = VESA_BIOS_EXTENSIONS_RETURN_MODE_INFORMATION; + Regs.X.CX = *ModeNumberPtr; + gBS->SetMem (BiosVideoPrivate->VbeModeInformationBlock, sizeof (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK), 0); + Regs.X.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeModeInformationBlock); + Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeModeInformationBlock); + + BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs); + + // + // See if the call succeeded. If it didn't, then try the next mode. + // + if (Regs.X.AX != VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) { + TRACE((TRACE_BIOS_VIDEO,".. skipping as we can not retrieve mode details\n")); + continue; + } + + TRACE((TRACE_BIOS_VIDEO, "(%dx%d) ", BiosVideoPrivate->VbeModeInformationBlock->XResolution, BiosVideoPrivate->VbeModeInformationBlock->YResolution)); + + // + // See if the mode supported in hardware. If it doesn't then try the next mode. + // + if ((BiosVideoPrivate->VbeModeInformationBlock->ModeAttributes & VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_HARDWARE) == 0) { + TRACE((TRACE_BIOS_VIDEO,"skipping as the mode is not supported in hardware...\n")); + continue; + } + + // + // See if the mode supports color. If it doesn't then try the next mode. + // + if ((BiosVideoPrivate->VbeModeInformationBlock->ModeAttributes & VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_COLOR) == 0) { + TRACE((TRACE_BIOS_VIDEO,"is invalid, skipping...\n")); + continue; + } + // + // See if the mode supports graphics. If it doesn't then try the next mode. + // + if ((BiosVideoPrivate->VbeModeInformationBlock->ModeAttributes & VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_GRAPHICS) == 0) { + TRACE((TRACE_BIOS_VIDEO,"skipping as the mode is not graphical...\n")); + continue; + } + // + // See if the mode supports a linear frame buffer. If it doesn't then try the next mode. + // + if ((BiosVideoPrivate->VbeModeInformationBlock->ModeAttributes & VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER) == 0) { + TRACE((TRACE_BIOS_VIDEO,"skipping as the mode has not linear frame buffer...\n")); + continue; + } + // + // See if the mode supports 32 bit color. If it doesn't then try the next mode. + // 32 bit mode can be implemented by 24 Bits Per Pixel. Also make sure the + // number of bits per pixel is a multiple of 8 or more than 32 bits per pixel + // + if (BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel < 24) { + TRACE((TRACE_BIOS_VIDEO,"skipping as BPP (%d) is less than 24...\n", BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel)); + continue; + } + + if (BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel > 32) { + TRACE((TRACE_BIOS_VIDEO,"skipping as BPP (%d) is more than 32...\n", BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel)); + continue; + } + + if ((BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel % 8) != 0) { + TRACE((TRACE_BIOS_VIDEO,"skipping as BPP (%d) modulo 8 is non-zero...\n", BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel)); + continue; + } + // + // See if the physical base pointer for the linear mode is valid. If it isn't then try the next mode. + // + if (BiosVideoPrivate->VbeModeInformationBlock->PhysBasePtr == 0) { + TRACE((TRACE_BIOS_VIDEO,"skipping as PhysBasePtr is zero...\n")); + continue; + } + EdidMatch = FALSE; + if (EdidFound) { + // + // EDID exist, check whether this mode match with any mode in EDID + // + ResolutionKey = BiosVideoPrivate->VbeModeInformationBlock->YResolution | + (BiosVideoPrivate->VbeModeInformationBlock->XResolution << 16); + + if (SearchEdidTiming (ResolutionKey) == TRUE) { + EdidMatch = TRUE; + TRACE((TRACE_BIOS_VIDEO, "EDID match found.\n")); + } + } + + // + // Select a reasonable mode to be set for current display mode + // + ModeFound = FALSE; + + for(i = 0; i < MaxTextMode; i++) + { + if(TextModeArray[i].VideoCol == BiosVideoPrivate->VbeModeInformationBlock->XResolution && + TextModeArray[i].VideoRow == BiosVideoPrivate->VbeModeInformationBlock->YResolution) + { + ModeFound = TRUE; + TRACE((TRACE_BIOS_VIDEO, "MODE match found (%d).\n", i)); + } + } + if ((!EdidMatch) && (!ModeFound)) { + // + // When EDID exist and if the timing matches with VESA add it. + // And also add three possible resolutions, i.e. 1024x768, 800x600, 640x480 + // + TRACE((TRACE_BIOS_VIDEO, "neither EDID nor MODE match is found.\n", i)); + continue; + } + + if (CheckForDuplicateMode(BiosVideoPrivate, ModeNumber) == EFI_SUCCESS) + { + TRACE((TRACE_BIOS_VIDEO, "skipping as the same resolution (%dx%d) is already available\n", + BiosVideoPrivate->VbeModeInformationBlock->XResolution, + BiosVideoPrivate->VbeModeInformationBlock->YResolution)); + continue; + } + + // + // Add mode to the list of available modes + // + ModeNumber ++; + Status = gBS->AllocatePool ( + EfiBootServicesData, + ModeNumber * sizeof (BIOS_VIDEO_MODE_DATA), + (VOID **) &ModeBuffer + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + if (ModeNumber > 1) { + gBS->CopyMem ( + ModeBuffer, + BiosVideoPrivate->ModeData, + (ModeNumber - 1) * sizeof (BIOS_VIDEO_MODE_DATA) + ); + } + + if (BiosVideoPrivate->ModeData != NULL) { + gBS->FreePool (BiosVideoPrivate->ModeData); + BiosVideoPrivate->ModeData = NULL; + } + + CurrentModeData = &ModeBuffer[ModeNumber - 1]; + CurrentModeData->VbeModeNumber = *ModeNumberPtr; + if (BiosVideoPrivate->VbeInformationBlock->VESAVersion >= VESA_BIOS_EXTENSIONS_VERSION_3_0) { + CurrentModeData->BytesPerScanLine = BiosVideoPrivate->VbeModeInformationBlock->LinBytesPerScanLine; + CurrentModeData->Red.Position = BiosVideoPrivate->VbeModeInformationBlock->LinRedFieldPosition; + CurrentModeData->Red.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinRedMaskSize) - 1); + CurrentModeData->Blue.Position = BiosVideoPrivate->VbeModeInformationBlock->LinBlueFieldPosition; + CurrentModeData->Blue.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinBlueMaskSize) - 1); + CurrentModeData->Green.Position = BiosVideoPrivate->VbeModeInformationBlock->LinGreenFieldPosition; + CurrentModeData->Green.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinGreenMaskSize) - 1); + CurrentModeData->Reserved.Position = BiosVideoPrivate->VbeModeInformationBlock->LinRsvdFieldPosition; + CurrentModeData->Reserved.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinRsvdMaskSize) - 1); + } else { + CurrentModeData->BytesPerScanLine = BiosVideoPrivate->VbeModeInformationBlock->BytesPerScanLine; + CurrentModeData->Red.Position = BiosVideoPrivate->VbeModeInformationBlock->RedFieldPosition; + CurrentModeData->Red.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->RedMaskSize) - 1); + CurrentModeData->Blue.Position = BiosVideoPrivate->VbeModeInformationBlock->BlueFieldPosition; + CurrentModeData->Blue.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->BlueMaskSize) - 1); + CurrentModeData->Green.Position = BiosVideoPrivate->VbeModeInformationBlock->GreenFieldPosition; + CurrentModeData->Green.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->GreenMaskSize) - 1); + CurrentModeData->Reserved.Position = BiosVideoPrivate->VbeModeInformationBlock->RsvdFieldPosition; + CurrentModeData->Reserved.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->RsvdMaskSize) - 1); + } +//*** AMI PORTING BEGIN ***// +//Bug fix: The original logic did not work for a modes with 24-bit pixels. +// For a 24-bit pixels, the PixelFormat must be set to PixelBitMask, which +// was not happening with the original "if" statement +// if ((CurrentModeData->Red.Mask == 0xff) && (CurrentModeData->Green.Mask == 0xff) && (CurrentModeData->Blue.Mask == 0xff)) { + if ( (BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel == 32) + && (CurrentModeData->Red.Mask == 0xff) && (CurrentModeData->Green.Mask == 0xff) && (CurrentModeData->Blue.Mask == 0xff) + ) { +//*** AMI PORTING END *****// + if ((CurrentModeData->Red.Position == 0) && (CurrentModeData->Green.Position == 8)) { + CurrentModeData->PixelFormat = PixelRedGreenBlueReserved8BitPerColor; + } else if ((CurrentModeData->Blue.Position == 0) && (CurrentModeData->Green.Position == 8)) { + CurrentModeData->PixelFormat = PixelBlueGreenRedReserved8BitPerColor; + } + } else { + CurrentModeData->PixelFormat = PixelBitMask; + } + CurrentModeData->PixelBitMask.RedMask = ((UINT32) CurrentModeData->Red.Mask) << CurrentModeData->Red.Position; + CurrentModeData->PixelBitMask.GreenMask = ((UINT32) CurrentModeData->Green.Mask) << CurrentModeData->Green.Position; + CurrentModeData->PixelBitMask.BlueMask = ((UINT32) CurrentModeData->Blue.Mask) << CurrentModeData->Blue.Position; + CurrentModeData->PixelBitMask.ReservedMask = ((UINT32) CurrentModeData->Reserved.Mask) << CurrentModeData->Reserved.Position; + +//*** AMI PORTING BEGIN ***// +#if CSM_VGA_64BITBAR_WORKAROUND + if(Above4g){ + UINT64 PhysBasePtr4g=BiosVideoPrivate->VbeModeInformationBlock->PhysBasePtr; + //------------------------------------ + Status=Update64BitLinearBufferAddr(BiosVideoPrivate->PciIo, &PhysBasePtr4g, PciConfSpace); + if (EFI_ERROR (Status)) { + goto Done; + } + + CurrentModeData->LinearFrameBuffer = (VOID *) (UINTN)PhysBasePtr4g; + }else +#endif + { + CurrentModeData->LinearFrameBuffer = (VOID *) (UINTN)BiosVideoPrivate->VbeModeInformationBlock->PhysBasePtr; + } + //CurrentModeData->LinearFrameBuffer = (VOID *) (UINTN)BiosVideoPrivate->VbeModeInformationBlock->PhysBasePtr; + +//*** AMI PORTING END *****// + CurrentModeData->HorizontalResolution = BiosVideoPrivate->VbeModeInformationBlock->XResolution; + CurrentModeData->VerticalResolution = BiosVideoPrivate->VbeModeInformationBlock->YResolution; + + CurrentModeData->BitsPerPixel = BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel; + +//*** AMI PORTING BEGIN ***// +// UEFI SCT 2.3.1 Summer Summit version reports that framebuffersize mismatch in query mode of SCT test +// Calculated the framebuffersize based for each mode configuration + if(CurrentModeData->PixelFormat == PixelRedGreenBlueReserved8BitPerColor || + CurrentModeData->PixelFormat == PixelBlueGreenRedReserved8BitPerColor) { + CurrentModeData->FrameBufferSize=((CurrentModeData->BytesPerScanLine * 8) / CurrentModeData->BitsPerPixel) * + CurrentModeData->VerticalResolution * + sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL); + } else { + CurrentModeData->FrameBufferSize = BiosVideoPrivate->VbeInformationBlock->TotalMemory * 64 * 1024; + } +//*** AMI PORTING END *****// + + CurrentModeData->RefreshRate = 60; + + BiosVideoPrivate->ModeData = ModeBuffer; + } + // + // Check to see if we found any modes that are compatible with GRAPHICS OUTPUT + // + if (ModeNumber == 0) { + Status = EFI_DEVICE_ERROR; + goto Done; + } + + // + // Allocate buffer for Graphics Output Protocol mode information + // + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE), + (VOID **) &BiosVideoPrivate->GraphicsOutput.Mode + ); + if (EFI_ERROR (Status)) { + goto Done; + } + GraphicsOutputMode = BiosVideoPrivate->GraphicsOutput.Mode; + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION), + (VOID **) &GraphicsOutputMode->Info + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + GraphicsOutputMode->MaxMode = (UINT32) ModeNumber; + // + // Current mode is still unknown, set it to an invalid mode. + // + GraphicsOutputMode->Mode = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER; + TRACE((TRACE_BIOS_VIDEO, "Total number of GOP modes: %d\n", ModeNumber)); + // + // Find the best mode to initialize + // + Status = BiosVideoGraphicsOutputSetMode (&BiosVideoPrivate->GraphicsOutput, (UINT32) PreferMode); + if (EFI_ERROR (Status)) { + for (PreferMode = 0; PreferMode < ModeNumber; PreferMode ++) { + Status = BiosVideoGraphicsOutputSetMode ( + &BiosVideoPrivate->GraphicsOutput, + (UINT32) PreferMode + ); + if (!EFI_ERROR (Status)) { + break; + } + } + if (PreferMode == ModeNumber) { + // + // None mode is set successfully. + // + goto Done; + } + } + +Done: + // + // If there was an error, then free the mode structure + // + if (EFI_ERROR (Status)) { + if (BiosVideoPrivate->ModeData != NULL) { + gBS->FreePool (BiosVideoPrivate->ModeData); + BiosVideoPrivate->ModeData = NULL; + } + if (BiosVideoPrivate->GraphicsOutput.Mode != NULL) { + if (BiosVideoPrivate->GraphicsOutput.Mode->Info != NULL) { + gBS->FreePool (BiosVideoPrivate->GraphicsOutput.Mode->Info); + BiosVideoPrivate->GraphicsOutput.Mode->Info = NULL; + } + gBS->FreePool (BiosVideoPrivate->GraphicsOutput.Mode); + BiosVideoPrivate->GraphicsOutput.Mode = NULL; + } + } + + return Status; +} + +//*** AMI PORTING BEGIN ***// +#endif//if INT10_VESA_GO_SUPPORT==1 +//*** AMI PORTING END *****// +//*** AMI PORTING BEGIN ***// +#if INT10_VGA_GO_SUPPORT==1 +//*** AMI PORTING END *****// +EFI_STATUS +EFIAPI +BiosVideoCheckForVga ( + IN OUT BIOS_VIDEO_DEV *BiosVideoPrivate + ) +/*++ + + Routine Description: + + Check for VGA device + + Arguments: + + BiosVideoPrivate - Pointer to BIOS_VIDEO_DEV structure + + Returns: + + EFI_SUCCESS - Standard VGA device found + +--*/ +{ + EFI_STATUS Status; + BIOS_VIDEO_MODE_DATA *ModeBuffer; + + // + // Fill in the Graphics Output Protocol + // + BiosVideoPrivate->GraphicsOutput.QueryMode = BiosVideoGraphicsOutputQueryMode; + BiosVideoPrivate->GraphicsOutput.SetMode = BiosVideoGraphicsOutputSetMode; + BiosVideoPrivate->GraphicsOutput.Blt = BiosVideoGraphicsOutputVgaBlt; + + // + // Allocate buffer for Graphics Output Protocol mode information + // + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE), + (VOID **) &BiosVideoPrivate->GraphicsOutput.Mode + ); + if (EFI_ERROR (Status)) { + goto Done; + } + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION), + (VOID **) &BiosVideoPrivate->GraphicsOutput.Mode->Info + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + // + // Add mode to the list of available modes + // + BiosVideoPrivate->GraphicsOutput.Mode->MaxMode = 1; + + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (BIOS_VIDEO_MODE_DATA), + (VOID **) &ModeBuffer + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + ModeBuffer->VbeModeNumber = 0x0012; + ModeBuffer->BytesPerScanLine = 640; + ModeBuffer->LinearFrameBuffer = (VOID *) (UINTN) (0xa0000); + ModeBuffer->FrameBufferSize = 0; + ModeBuffer->HorizontalResolution = 640; + ModeBuffer->VerticalResolution = 480; + ModeBuffer->RefreshRate = 60; + ModeBuffer->PixelFormat = PixelBltOnly; +//*** AMI PORTING BEGIN ***// +//Bug fix: initialize BitsPerPixel + ModeBuffer->BitsPerPixel = 4; +//*** AMI PORTING END *****// + + BiosVideoPrivate->ModeData = ModeBuffer; + + // + // Test to see if the Video Adapter support the 640x480 16 color mode + // + BiosVideoPrivate->GraphicsOutput.Mode->Mode = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER; + Status = BiosVideoGraphicsOutputSetMode (&BiosVideoPrivate->GraphicsOutput, 0); + +Done: + // + // If there was an error, then free the mode structure + // + if (EFI_ERROR (Status)) { + if (BiosVideoPrivate->ModeData != NULL) { + gBS->FreePool (BiosVideoPrivate->ModeData); + BiosVideoPrivate->ModeData = NULL; + } + if (BiosVideoPrivate->GraphicsOutput.Mode != NULL) { + if (BiosVideoPrivate->GraphicsOutput.Mode->Info != NULL) { + gBS->FreePool (BiosVideoPrivate->GraphicsOutput.Mode->Info); + BiosVideoPrivate->GraphicsOutput.Mode->Info = NULL; + } + gBS->FreePool (BiosVideoPrivate->GraphicsOutput.Mode); + BiosVideoPrivate->GraphicsOutput.Mode = NULL; + } + } + return Status; +} +//*** AMI PORTING BEGIN ***// +#endif//if INT10_VGA_GO_SUPPORT==1 +//*** AMI PORTING END *****// + +// +// Graphics Output Protocol Member Functions for VESA BIOS Extensions +// +EFI_STATUS +EFIAPI +BiosVideoGraphicsOutputQueryMode ( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, + IN UINT32 ModeNumber, + OUT UINTN *SizeOfInfo, + OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info + ) +/*++ + +Routine Description: + + Graphics Output protocol interface to get video mode + + Arguments: + This - Protocol instance pointer. + ModeNumber - The mode number to return information on. + Info - Caller allocated buffer that returns information about ModeNumber. + SizeOfInfo - A pointer to the size, in bytes, of the Info buffer. + + Returns: + EFI_SUCCESS - Mode information returned. + EFI_DEVICE_ERROR - A hardware error occurred trying to retrieve the video mode. + EFI_NOT_STARTED - Video display is not initialized. Call SetMode () + EFI_INVALID_PARAMETER - One of the input args was NULL. + +--*/ +{ + BIOS_VIDEO_DEV *BiosVideoPrivate; + EFI_STATUS Status; + BIOS_VIDEO_MODE_DATA *ModeData; + + BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This); + + if (BiosVideoPrivate->HardwareNeedsStarting) { + ReportStatusCodeWithDevicePath ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_OUTPUT_ERROR, + 0, + &gEfiCallerIdGuid, + BiosVideoPrivate->DevicePath + ); + return EFI_NOT_STARTED; + } + + if (This == NULL || Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) { + return EFI_INVALID_PARAMETER; + } + + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION), + Info + ); + if (EFI_ERROR (Status)) { + return Status; + } + + *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION); + + ModeData = &BiosVideoPrivate->ModeData[ModeNumber]; + (*Info)->Version = 0; + (*Info)->HorizontalResolution = ModeData->HorizontalResolution; + (*Info)->VerticalResolution = ModeData->VerticalResolution; + (*Info)->PixelFormat = ModeData->PixelFormat; + (*Info)->PixelInformation = ModeData->PixelBitMask; + + (*Info)->PixelsPerScanLine = (ModeData->BytesPerScanLine * 8) / ModeData->BitsPerPixel; + + return EFI_SUCCESS; +} + +//*** AMI PORTING BEGIN ***// +// The AllocateTheBuffers function below and certain modifications of +// the BiosVideoGraphicsOutputVbeBlt nd BiosVideoVgaMiniPortSetMode functions +// are made to address the issues reaised in EIP 35682. +// +// The BLT function (BiosVideoGraphicsOutputVbeBlt) uses several memory buffers. +// Default implementation allocates the buffers in the SetMode(BiosVideoVgaMiniPortSetMode) +// function. We are changing implementation to allocate the buffers right in the BLT function +// before the first use. The code that releases the buffers is still in the SetMode function. +// +// This is a workaround for the "UEFI Windows 7 Startup Repair" bug. +// When Startup Repair option is selected, it crashes with the 0xc0000225 error prior +// to the call to ExitBootServices. +// The problem is caused by the Windows inability to handle memory map changes. +// The memory map changes when Windows calls Gop->SetMode and our implementation of the +// SetMode(BiosVideoGraphicsOutputVbeBlt) allocates the buffers. +// This workaround moves buffer allocation to the BLT function (BiosVideoGraphicsOutputVbeBlt), +// which Windows never calls and therefore memory map never changes. +EFI_STATUS AllocateTheBuffers(BIOS_VIDEO_DEV *BiosVideoPrivate){ + EFI_STATUS Status; + BIOS_VIDEO_MODE_DATA *ModeData; + UINT16 MaxBytesPerScanLine = 0; + UINT32 MaxVerticalResolution = 0; + UINT32 CurrentMode = (BiosVideoPrivate->GraphicsOutput).Mode->Mode; + UINT32 MaxMode = (BiosVideoPrivate->GraphicsOutput).Mode->MaxMode; + UINT32 Index; + + TRACE((TRACE_BIOS_VIDEO, "UefiBiosVideo AllocateTheBuffers()\n")); + for(Index = 0; Index < MaxMode; Index++) { + ModeData = &BiosVideoPrivate->ModeData[Index]; + + if (MaxBytesPerScanLine < ModeData->BytesPerScanLine) { + MaxBytesPerScanLine = ModeData->BytesPerScanLine; + } + if (MaxVerticalResolution < ModeData->VerticalResolution) { + MaxVerticalResolution = ModeData->VerticalResolution; + } + + TRACE((TRACE_BIOS_VIDEO, "VbeModeNumber: 0x%x\n", ModeData->VbeModeNumber)); + TRACE((TRACE_BIOS_VIDEO, "BytesPerScanLine: 0x%x\n", \ + ModeData->BytesPerScanLine)); + TRACE((TRACE_BIOS_VIDEO, "HorizontalResolution: 0x%x\n", \ + ModeData->HorizontalResolution)); + TRACE((TRACE_BIOS_VIDEO, "VerticalResolution: 0x%x\n", \ + ModeData->VerticalResolution)); + } + + TRACE((TRACE_BIOS_VIDEO, "MaxBytesPerScanLine: 0x%x\n", MaxBytesPerScanLine)); + TRACE((TRACE_BIOS_VIDEO, "MaxVerticalResolution: 0x%x\n", \ + MaxVerticalResolution)); + + ModeData = &BiosVideoPrivate->ModeData[CurrentMode]; + + Status = gBS->AllocatePool ( + EfiBootServicesData, + MaxBytesPerScanLine, + &BiosVideoPrivate->LineBuffer + ); + if (EFI_ERROR (Status)) { + BiosVideoPrivate->LineBuffer=NULL; + return Status; + } + MemSet(BiosVideoPrivate->LineBuffer, MaxBytesPerScanLine, 0); + + // + // Allocate a working buffer for BLT operations to the VGA frame buffer + // + Status = gBS->AllocatePool ( + EfiBootServicesData, + 4 * 480 * 80, + &BiosVideoPrivate->VgaFrameBuffer + ); + if (EFI_ERROR (Status)) { + gBS->FreePool (BiosVideoPrivate->LineBuffer); + BiosVideoPrivate->LineBuffer=NULL; + return Status; + } + MemSet(BiosVideoPrivate->VgaFrameBuffer, 4 * 480 * 80, 0); + + // + // Allocate a working buffer for BLT operations to the VBE frame buffer + // + Status = gBS->AllocatePool ( + EfiBootServicesData, + MaxBytesPerScanLine * MaxVerticalResolution, + &BiosVideoPrivate->VbeFrameBuffer + ); + if (EFI_ERROR (Status)) { + gBS->FreePool (BiosVideoPrivate->LineBuffer); + BiosVideoPrivate->LineBuffer=NULL; + return Status; + } + MemSet( + BiosVideoPrivate->VbeFrameBuffer, + MaxBytesPerScanLine * MaxVerticalResolution, + 0 + ); + + // + // Initialize the state of the VbeFrameBuffer + // + if (ModeData->VbeModeNumber >= 0x100) { + gBS->CopyMem ( + BiosVideoPrivate->VbeFrameBuffer, + ModeData->LinearFrameBuffer, + (ModeData->BytesPerScanLine * ModeData->VerticalResolution)); + + } + return Status; +} + +//*** AMI PORTING END *****// + +EFI_STATUS +EFIAPI +BiosVideoGraphicsOutputSetMode ( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL * This, + IN UINT32 ModeNumber + ) +/*++ + +Routine Description: + + Graphics Output protocol interface to set video mode + + Arguments: + This - Protocol instance pointer. + ModeNumber - The mode number to be set. + + Returns: + EFI_SUCCESS - Graphics mode was changed. + EFI_DEVICE_ERROR - The device had an error and could not complete the request. + EFI_UNSUPPORTED - ModeNumber is not supported by this device. + +--*/ +{ +//*** AMI PORTING BEGIN ***// +//Workaround for EIP 35682. See comments above +//AllocateTheBuffers function for additional details. +// EFI_STATUS Status; +//*** AMI PORTING END *****// + BIOS_VIDEO_DEV *BiosVideoPrivate; + EFI_IA32_REGISTER_SET Regs; + BIOS_VIDEO_MODE_DATA *ModeData; + + BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This); + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (ModeNumber >= This->Mode->MaxMode) { + return EFI_UNSUPPORTED; + } +/* + if (ModeNumber == This->Mode->Mode) { + return EFI_SUCCESS; + } +*/ + ModeData = &BiosVideoPrivate->ModeData[ModeNumber]; + + if (BiosVideoPrivate->LineBuffer) { + gBS->FreePool (BiosVideoPrivate->LineBuffer); + BiosVideoPrivate->LineBuffer = NULL; + } + + if (BiosVideoPrivate->VgaFrameBuffer) { + gBS->FreePool (BiosVideoPrivate->VgaFrameBuffer); + BiosVideoPrivate->VgaFrameBuffer = NULL; + } + + if (BiosVideoPrivate->VbeFrameBuffer) { + gBS->FreePool (BiosVideoPrivate->VbeFrameBuffer); + BiosVideoPrivate->VbeFrameBuffer = NULL; + } + + BiosVideoPrivate->LineBuffer = NULL; +//*** AMI PORTING BEGIN ***// +// Workaround for EIP 35682. +// Buffer allocation code is moved to AllocateTheBuffers function, +// which is called from the BiosVideoGraphicsOutputVbeBlt. +// See comments above AllocateTheBuffers function for additional details. +/* + Status = gBS->AllocatePool ( + EfiBootServicesData, + ModeData->BytesPerScanLine, + &BiosVideoPrivate->LineBuffer + ); + if (EFI_ERROR (Status)) { + return Status; + } +*/ +//*** AMI PORTING END *****// + // + // Clear all registers + // + gBS->SetMem (&Regs, sizeof (Regs), 0); + + if (ModeData->VbeModeNumber < 0x100) { + // + // Allocate a working buffer for BLT operations to the VGA frame buffer + // + BiosVideoPrivate->VgaFrameBuffer = NULL; +//*** AMI PORTING BEGIN ***// +//*** AMI PORTING BEGIN ***// +// Workaround for EIP 35682. +// Buffer allocation code is moved to AllocateTheBuffers function, +// which is called from the BiosVideoGraphicsOutputVbeBlt. +// See comments above AllocateTheBuffers function for additional details. +/* + Status = gBS->AllocatePool ( + EfiBootServicesData, + 4 * 480 * 80, + &BiosVideoPrivate->VgaFrameBuffer + ); + if (EFI_ERROR (Status)) { + return Status; + } +*/ +//*** AMI PORTING END *****// + // + // Set VGA Mode + // + Regs.X.AX = ModeData->VbeModeNumber; + BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs); + + } else { + // + // Allocate a working buffer for BLT operations to the VBE frame buffer + // + BiosVideoPrivate->VbeFrameBuffer = NULL; +//*** AMI PORTING BEGIN ***// +//*** AMI PORTING BEGIN ***// +// Workaround for EIP 35682. +// Buffer allocation code is moved to AllocateTheBuffers function, +// which is called from the BiosVideoGraphicsOutputVbeBlt. +// See comments above AllocateTheBuffers function for additional details. +/* + Status = gBS->AllocatePool ( + EfiBootServicesData, + ModeData->BytesPerScanLine * ModeData->VerticalResolution, + &BiosVideoPrivate->VbeFrameBuffer + ); + if (EFI_ERROR (Status)) { + return Status; + } +*/ +//*** AMI PORTING END *****// + // + // Set VBE mode + // + Regs.X.AX = VESA_BIOS_EXTENSIONS_SET_MODE; + Regs.X.BX = (UINT16) (ModeData->VbeModeNumber | VESA_BIOS_EXTENSIONS_MODE_NUMBER_LINEAR_FRAME_BUFFER); + gBS->SetMem (BiosVideoPrivate->VbeCrtcInformationBlock, sizeof (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK), 0); + Regs.X.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeCrtcInformationBlock); + Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeCrtcInformationBlock); + BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs); + + // + // Check to see if the call succeeded + // + if (Regs.X.AX != VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) { + ReportStatusCodeWithDevicePath ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_OUTPUT_ERROR, + 0, + &gEfiCallerIdGuid, + BiosVideoPrivate->DevicePath + ); + return EFI_DEVICE_ERROR; + } +//*** AMI PORTING BEGIN ***// + // + // Initialize the state of the VbeFrameBuffer + // + +/* + Status = BiosVideoPrivate->PciIo->Mem.Read ( + BiosVideoPrivate->PciIo, + EfiPciIoWidthUint32, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) (UINTN) ModeData->LinearFrameBuffer, + (ModeData->BytesPerScanLine * ModeData->VerticalResolution) >> 2, + BiosVideoPrivate->VbeFrameBuffer + ); + if (EFI_ERROR (Status)) { + return Status; + } +*/ +// Workaround for EIP 35682. +// Buffer allocation and initialization code is moved to AllocateTheBuffers function, +// which is called from the BiosVideoGraphicsOutputVbeBlt. +// See comments above AllocateTheBuffers function for additional details. +/* + gBS->CopyMem ( + BiosVideoPrivate->VbeFrameBuffer, + ModeData->LinearFrameBuffer, + (ModeData->BytesPerScanLine * ModeData->VerticalResolution)); +*/ + } +//*** AMI PORTING END ***// + + This->Mode->Mode = ModeNumber; + This->Mode->Info->Version = 0; + This->Mode->Info->HorizontalResolution = ModeData->HorizontalResolution; + This->Mode->Info->VerticalResolution = ModeData->VerticalResolution; + This->Mode->Info->PixelFormat = ModeData->PixelFormat; + This->Mode->Info->PixelInformation = ModeData->PixelBitMask; + This->Mode->Info->PixelsPerScanLine = (ModeData->BytesPerScanLine * 8) / ModeData->BitsPerPixel; + This->Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION); + + // + // Frame BufferSize remain unchanged + // + This->Mode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) ModeData->LinearFrameBuffer; + This->Mode->FrameBufferSize = ModeData->FrameBufferSize; + + BiosVideoPrivate->HardwareNeedsStarting = FALSE; + + return EFI_SUCCESS; +} + +//*** AMI PORTING BEGIN ***// +#if INT10_VESA_GO_SUPPORT==1 +//*** AMI PORTING END *****// +// +// BUGBUG : Add Blt for 16 bit color, 15 bit color, and 8 bit color modes +// +EFI_STATUS +EFIAPI +BiosVideoGraphicsOutputVbeBlt ( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL + IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation, + IN UINTN SourceX, + IN UINTN SourceY, + IN UINTN DestinationX, + IN UINTN DestinationY, + IN UINTN Width, + IN UINTN Height, + IN UINTN Delta + ) +/*++ + +Routine Description: + + Graphics Output protocol instance to block transfer for VBE device + +Arguments: + + This - Pointer to Graphics Output protocol instance + BltBuffer - The data to transfer to screen + BltOperation - The operation to perform + SourceX - The X coordinate of the source for BltOperation + SourceY - The Y coordinate of the source for BltOperation + DestinationX - The X coordinate of the destination for BltOperation + DestinationY - The Y coordinate of the destination for BltOperation + Width - The width of a rectangle in the blt rectangle in pixels + Height - The height of a rectangle in the blt rectangle in pixels + Delta - Not used for EfiBltVideoFill and EfiBltVideoToVideo operation. + If a Delta of 0 is used, the entire BltBuffer will be operated on. + If a subrectangle of the BltBuffer is used, then Delta represents + the number of bytes in a row of the BltBuffer. + +Returns: + + EFI_INVALID_PARAMETER - Invalid parameter passed in + EFI_SUCCESS - Blt operation success + +--*/ +{ + BIOS_VIDEO_DEV *BiosVideoPrivate; + BIOS_VIDEO_MODE_DATA *Mode; + EFI_PCI_IO_PROTOCOL *PciIo; + EFI_TPL OriginalTPL; + UINTN DstY; + UINTN SrcY; + UINTN DstX; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt; + VOID *MemAddress; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL *VbeFrameBuffer; + UINTN BytesPerScanLine; + UINTN Index; + UINT8 *VbeBuffer; + UINT8 *VbeBuffer1; + UINT8 *BltUint8; + UINT32 VbePixelWidth; + UINT32 Pixel; + +//*** AMI PORTING BEGIN ***// +//Bug fix: This is accessed before it's checked on NULL + if (This == NULL || ((UINTN) BltOperation) >= EfiGraphicsOutputBltOperationMax) { + return EFI_INVALID_PARAMETER; + } +//*** AMI PORTING END *****// + BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This); +//*** AMI PORTING BEGIN ***// +// Workaround for EIP 35682. +// Allocate memory buffers during the first call of the funciton. +// See comments above AllocateTheBuffers function for additional details. + if (BiosVideoPrivate->LineBuffer==NULL){ + EFI_STATUS Status = AllocateTheBuffers(BiosVideoPrivate); + if (EFI_ERROR(Status)) return Status; + } +//*** AMI PORTING END *****// + Mode = &BiosVideoPrivate->ModeData[This->Mode->Mode]; + PciIo = BiosVideoPrivate->PciIo; + + VbeFrameBuffer = BiosVideoPrivate->VbeFrameBuffer; + MemAddress = Mode->LinearFrameBuffer; + BytesPerScanLine = Mode->BytesPerScanLine; + VbePixelWidth = Mode->BitsPerPixel / 8; + BltUint8 = (UINT8 *) BltBuffer; + +//*** AMI PORTING BEGIN ***// +//These parameter checks are moved to the beginning of the function +/* + if (This == NULL || ((UINTN) BltOperation) >= EfiGraphicsOutputBltOperationMax) { + return EFI_INVALID_PARAMETER; + } +*/ +//*** AMI PORTING END *****// + + if (Width == 0 || Height == 0) { + return EFI_INVALID_PARAMETER; + } + // + // We need to fill the Virtual Screen buffer with the blt data. + // The virtual screen is upside down, as the first row is the bootom row of + // the image. + // + if (BltOperation == EfiBltVideoToBltBuffer) { + // + // Video to BltBuffer: Source is Video, destination is BltBuffer + // + if (SourceY + Height > Mode->VerticalResolution) { + return EFI_INVALID_PARAMETER; + } + + if (SourceX + Width > Mode->HorizontalResolution) { + return EFI_INVALID_PARAMETER; + } + } else { + // + // BltBuffer to Video: Source is BltBuffer, destination is Video + // + if (DestinationY + Height > Mode->VerticalResolution) { + return EFI_INVALID_PARAMETER; + } + + if (DestinationX + Width > Mode->HorizontalResolution) { + return EFI_INVALID_PARAMETER; + } + } + // + // If Delta is zero, then the entire BltBuffer is being used, so Delta + // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size, + // the number of bytes in each row can be computed. + // + if (Delta == 0) { + Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL); + } + // + // We have to raise to TPL Notify, so we make an atomic write the frame buffer. + // We would not want a timer based event (Cursor, ...) to come in while we are + // doing this operation. + // + OriginalTPL = gBS->RaiseTPL (EFI_TPL_NOTIFY); + + switch (BltOperation) { + case EfiBltVideoToBltBuffer: + for (SrcY = SourceY, DstY = DestinationY; DstY < (Height + DestinationY); SrcY++, DstY++) { + Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) (BltUint8 + DstY * Delta + DestinationX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)); + // + // Shuffle the packed bytes in the hardware buffer to match EFI_GRAPHICS_OUTPUT_BLT_PIXEL + // + VbeBuffer = ((UINT8 *) VbeFrameBuffer + (SrcY * BytesPerScanLine + SourceX * VbePixelWidth)); + for (DstX = DestinationX; DstX < (Width + DestinationX); DstX++) { + Pixel = *(UINT32 *) (VbeBuffer); + Blt->Red = (UINT8) ((Pixel >> Mode->Red.Position) & Mode->Red.Mask); + Blt->Blue = (UINT8) ((Pixel >> Mode->Blue.Position) & Mode->Blue.Mask); + Blt->Green = (UINT8) ((Pixel >> Mode->Green.Position) & Mode->Green.Mask); + Blt->Reserved = 0; + Blt++; + VbeBuffer += VbePixelWidth; + } + + } + break; + + case EfiBltVideoToVideo: + for (Index = 0; Index < Height; Index++) { + if (DestinationY <= SourceY) { + SrcY = SourceY + Index; + DstY = DestinationY + Index; + } else { + SrcY = SourceY + Height - Index - 1; + DstY = DestinationY + Height - Index - 1; + } + + VbeBuffer = ((UINT8 *) VbeFrameBuffer + DstY * BytesPerScanLine + DestinationX * VbePixelWidth); + VbeBuffer1 = ((UINT8 *) VbeFrameBuffer + SrcY * BytesPerScanLine + SourceX * VbePixelWidth); + + gBS->CopyMem ( + VbeBuffer, + VbeBuffer1, + Width * VbePixelWidth + ); + + if (VbePixelWidth == 4) { +//*** AMI PORTING BEGIN ***// +// Replace PciIo.Mem with CopyMem to optimize performance +/* + PciIo->Mem.Write ( + PciIo, + EfiPciIoWidthUint32, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) ((UINTN) MemAddress + (DstY * BytesPerScanLine) + DestinationX * VbePixelWidth), + Width, + VbeBuffer + ); +*/ + gBS->CopyMem ((UINT8*)MemAddress + (DstY * BytesPerScanLine) + DestinationX * VbePixelWidth, + (UINT8*)VbeBuffer, + Width * VbePixelWidth); +//*** AMI PORTING END *****// + } else { +//*** AMI PORTING BEGIN ***// +// Replace PciIo.Mem with CopyMem to optimize performance +/* + PciIo->Mem.Write ( + PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) ((UINTN) MemAddress + (DstY * BytesPerScanLine) + DestinationX * VbePixelWidth), + Width * VbePixelWidth, + VbeBuffer + ); +*/ + gBS->CopyMem ((UINT8*)MemAddress + (DstY * BytesPerScanLine) + DestinationX * VbePixelWidth, + (UINT8*)VbeBuffer, + Width * VbePixelWidth); + } +//*** AMI PORTING END *****// + } + break; + + case EfiBltVideoFill: + VbeBuffer = (UINT8 *) ((UINTN) VbeFrameBuffer + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth); + Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) BltUint8; + // + // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer + // + Pixel = ((Blt->Red & Mode->Red.Mask) << Mode->Red.Position) | + ( + (Blt->Green & Mode->Green.Mask) << + Mode->Green.Position + ) | + ((Blt->Blue & Mode->Blue.Mask) << Mode->Blue.Position); + + for (Index = 0; Index < Width; Index++) { + gBS->CopyMem ( + VbeBuffer, + &Pixel, + VbePixelWidth + ); + VbeBuffer += VbePixelWidth; + } + + VbeBuffer = (UINT8 *) ((UINTN) VbeFrameBuffer + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth); + for (DstY = DestinationY + 1; DstY < (Height + DestinationY); DstY++) { + gBS->CopyMem ( + (VOID *) ((UINTN) VbeFrameBuffer + (DstY * BytesPerScanLine) + DestinationX * VbePixelWidth), + VbeBuffer, + Width * VbePixelWidth + ); + } + + for (DstY = DestinationY; DstY < (Height + DestinationY); DstY++) { +//*** AMI PORTING BEGIN ***// +// Replace PciIo.Mem with CopyMem to optimize performance +/* + PciIo->Mem.Write ( + PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) ((UINTN) MemAddress + (DstY * BytesPerScanLine) + DestinationX * VbePixelWidth), + Width * VbePixelWidth, + VbeBuffer + ); +*/ + gBS->CopyMem ((UINT8*)MemAddress + (DstY * BytesPerScanLine) + DestinationX * VbePixelWidth, + (UINT8*)VbeBuffer, + Width * VbePixelWidth); +//*** AMI PORTING END *****// + } + break; + + case EfiBltBufferToVideo: +//*** AMI PORTING BEGIN ***// +//The original BLT loop is replaced to optimize performance by: +// replacing PciIo->Mem.Write with CopyMem and +// replacing multiplication with addition +/* + for (SrcY = SourceY, DstY = DestinationY; SrcY < (Height + SourceY); SrcY++, DstY++) { + Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) (BltUint8 + (SrcY * Delta) + (SourceX) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)); + VbeBuffer = ((UINT8 *) VbeFrameBuffer + (DstY * BytesPerScanLine + DestinationX * VbePixelWidth)); + for (DstX = DestinationX; DstX < (Width + DestinationX); DstX++) { + // + // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer + // + Pixel = ((Blt->Red & Mode->Red.Mask) << Mode->Red.Position) | + ((Blt->Green & Mode->Green.Mask) << Mode->Green.Position) | + ((Blt->Blue & Mode->Blue.Mask) << Mode->Blue.Position); + gBS->CopyMem ( + VbeBuffer, + &Pixel, + VbePixelWidth + ); + Blt++; + VbeBuffer += VbePixelWidth; + } + + VbeBuffer = ((UINT8 *) VbeFrameBuffer + (DstY * BytesPerScanLine + DestinationX * VbePixelWidth)); + PciIo->Mem.Write ( + PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) ((UINTN) MemAddress + (DstY * BytesPerScanLine) + DestinationX * VbePixelWidth), + Width * VbePixelWidth, + VbeBuffer + ); + } +*/ +{ + UINTN VbeBufferOffset = DestinationY * BytesPerScanLine + DestinationX * VbePixelWidth; + UINT8* BltBufferAddress = BltUint8 + SourceY * Delta + SourceX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL); + UINTN VbeLineWidth = VbePixelWidth*Width; + UINTN BufferOffset = VbeBufferOffset; + + for (SrcY = SourceY; SrcY < (Height + SourceY); SrcY++) { + + VbeBuffer = (UINT8 *) VbeFrameBuffer + BufferOffset; + + if (Mode->PixelFormat != PixelBlueGreenRedReserved8BitPerColor){ + Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *)BltBufferAddress; + for (DstX = DestinationX; DstX < (Width + DestinationX); DstX++) { + // + // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer + // + Pixel = ((Blt->Red & Mode->Red.Mask) << Mode->Red.Position) | + ((Blt->Green & Mode->Green.Mask) << Mode->Green.Position) | + ((Blt->Blue & Mode->Blue.Mask) << Mode->Blue.Position); + gBS->CopyMem ( + VbeBuffer, + &Pixel, + VbePixelWidth + ); + Blt++; + VbeBuffer += VbePixelWidth; + } + VbeBuffer = (UINT8 *) VbeFrameBuffer + BufferOffset; + }else{ + gBS->CopyMem (VbeBuffer, BltBufferAddress, VbeLineWidth); + } + BufferOffset += BytesPerScanLine; + BltBufferAddress += Delta; + } + BufferOffset = VbeBufferOffset; + for (SrcY = SourceY; SrcY < (Height + SourceY); SrcY++) { + gBS->CopyMem ((UINT8*)MemAddress + BufferOffset, + (UINT8 *)VbeFrameBuffer + BufferOffset, + VbeLineWidth); + BufferOffset += BytesPerScanLine; + } +} +//*** AMI PORTING END *****// + break; + } + + gBS->RestoreTPL (OriginalTPL); + + return EFI_SUCCESS; +} +//*** AMI PORTING BEGIN ***// +#endif //if INT10_VESA_GO_SUPPORT==1 +//*** AMI PORTING END *****// +//*** AMI PORTING BEGIN ***// +#if INT10_VGA_GO_SUPPORT==1 +//*** AMI PORTING END *****// +STATIC +VOID +WriteGraphicsController ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINTN Address, + IN UINTN Data + ) +/*++ + +Routine Description: + + Write graphics controller registers + +Arguments: + + PciIo - Pointer to PciIo protocol instance of the controller + Address - Register address + Data - Data to be written to register + +Returns: + + None + +--*/ +{ + Address = Address | (Data << 8); + PciIo->Io.Write ( + PciIo, + EfiPciIoWidthUint16, + EFI_PCI_IO_PASS_THROUGH_BAR, + VGA_GRAPHICS_CONTROLLER_ADDRESS_REGISTER, + 1, + &Address + ); +} + +VOID +VgaReadBitPlanes ( + EFI_PCI_IO_PROTOCOL *PciIo, + UINT8 *HardwareBuffer, + UINT8 *MemoryBuffer, + UINTN WidthInBytes, + UINTN Height + ) +/*++ + +Routine Description: + + Read the four bit plane of VGA frame buffer + +Arguments: + + PciIo - Pointer to PciIo protocol instance of the controller + HardwareBuffer - Hardware VGA frame buffer address + MemoryBuffer - Memory buffer address + WidthInBytes - Number of bytes in a line to read + Height - Height of the area to read + +Returns: + + None + +--*/ +{ + UINTN BitPlane; + UINTN Rows; + UINTN FrameBufferOffset; + UINT8 *Source; + UINT8 *Destination; + + // + // Program the Mode Register Write mode 0, Read mode 0 + // + WriteGraphicsController ( + PciIo, + VGA_GRAPHICS_CONTROLLER_MODE_REGISTER, + VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MODE_0 + ); + + for (BitPlane = 0, FrameBufferOffset = 0; + BitPlane < VGA_NUMBER_OF_BIT_PLANES; + BitPlane++, FrameBufferOffset += VGA_BYTES_PER_BIT_PLANE + ) { + // + // Program the Read Map Select Register to select the correct bit plane + // + WriteGraphicsController ( + PciIo, + VGA_GRAPHICS_CONTROLLER_READ_MAP_SELECT_REGISTER, + BitPlane + ); + + Source = HardwareBuffer; + Destination = MemoryBuffer + FrameBufferOffset; + + for (Rows = 0; Rows < Height; Rows++, Source += VGA_BYTES_PER_SCAN_LINE, Destination += VGA_BYTES_PER_SCAN_LINE) { +//*** AMI PORTING BEGIN ***// +// Replace PciIo.Mem with CopyMem to optimize performance +/* + PciIo->Mem.Read ( + PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) Source, + WidthInBytes, + (VOID *) Destination + ); +*/ + gBS->CopyMem ((UINT8*)Source, + (UINT8*)Destination, + WidthInBytes); +//*** AMI PORTING END *****// + } + } +} + +VOID +VgaConvertToGraphicsOutputColor ( + UINT8 *MemoryBuffer, + UINTN X, + UINTN Y, + EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer + ) +/*++ + +Routine Description: + + Internal routine to convert VGA color to Grahpics Output color + +Arguments: + + MemoryBuffer - Buffer containing VGA color + X - The X coordinate of pixel on screen + Y - The Y coordinate of pixel on screen + BltBuffer - Buffer to contain converted Grahpics Output color + +Returns: + + None + +--*/ +{ + UINTN Mask; + UINTN Bit; + UINTN Color; + + MemoryBuffer += ((Y << 6) + (Y << 4) + (X >> 3)); + Mask = mVgaBitMaskTable[X & 0x07]; + for (Bit = 0x01, Color = 0; Bit < 0x10; Bit <<= 1, MemoryBuffer += VGA_BYTES_PER_BIT_PLANE) { + if (*MemoryBuffer & Mask) { + Color |= Bit; + } + } + + *BltBuffer = mVgaColorToGraphicsOutputColor[Color]; +} + +UINT8 +VgaConvertColor ( + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer + ) +/*++ + +Routine Description: + + Internal routine to convert Grahpics Output color to VGA color + +Arguments: + + BltBuffer - buffer containing Grahpics Output color + +Returns: + + Converted VGA color + +--*/ +{ + UINT8 Color; + + Color = (UINT8) ((BltBuffer->Blue >> 7) | ((BltBuffer->Green >> 6) & 0x02) | ((BltBuffer->Red >> 5) & 0x04)); +//*** AMI PORTING BEGIN ***// +// if ((BltBuffer->Red + BltBuffer->Green + BltBuffer->Blue) > 0x180) { + if ((BltBuffer->Red >= 0xC0) || (BltBuffer->Blue >= 0xC0) || (BltBuffer->Green >= 0xC0)) { + Color |= 0x08; + } + // Prevent "washing out" of single color + if (((BltBuffer->Red >= 0xC0) && (BltBuffer->Blue == 0) && (BltBuffer->Green == 0)) || \ + ((BltBuffer->Blue >= 0xC0) && (BltBuffer->Red == 0) && (BltBuffer->Green == 0)) || \ + ((BltBuffer->Green >= 0xC0) && (BltBuffer->Blue == 0) && (BltBuffer->Red == 0))) { + Color &= 0x07; + } +//*** AMI PORTING END ***// + + return Color; +} + +EFI_STATUS +EFIAPI +BiosVideoGraphicsOutputVgaBlt ( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL + IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation, + IN UINTN SourceX, + IN UINTN SourceY, + IN UINTN DestinationX, + IN UINTN DestinationY, + IN UINTN Width, + IN UINTN Height, + IN UINTN Delta + ) +/*++ + +Routine Description: + + Grahpics Output protocol instance to block transfer for VGA device + +Arguments: + + This - Pointer to Grahpics Output protocol instance + BltBuffer - The data to transfer to screen + BltOperation - The operation to perform + SourceX - The X coordinate of the source for BltOperation + SourceY - The Y coordinate of the source for BltOperation + DestinationX - The X coordinate of the destination for BltOperation + DestinationY - The Y coordinate of the destination for BltOperation + Width - The width of a rectangle in the blt rectangle in pixels + Height - The height of a rectangle in the blt rectangle in pixels + Delta - Not used for EfiBltVideoFill and EfiBltVideoToVideo operation. + If a Delta of 0 is used, the entire BltBuffer will be operated on. + If a subrectangle of the BltBuffer is used, then Delta represents + the number of bytes in a row of the BltBuffer. + +Returns: + + EFI_INVALID_PARAMETER - Invalid parameter passed in + EFI_SUCCESS - Blt operation success + +--*/ +{ + BIOS_VIDEO_DEV *BiosVideoPrivate; + EFI_TPL OriginalTPL; + UINT8 *MemAddress; + UINTN BytesPerScanLine; + UINTN BytesPerBitPlane; + UINTN Bit; + UINTN Index; + UINTN Index1; + UINTN StartAddress; + UINTN Bytes; + UINTN Offset; + UINT8 LeftMask; + UINT8 RightMask; + UINTN Address; + UINTN AddressFix; + UINT8 *Address1; + UINT8 *SourceAddress; + UINT8 *DestinationAddress; + EFI_PCI_IO_PROTOCOL *PciIo; + UINT8 Data; + UINT8 PixelColor; + UINT8 *VgaFrameBuffer; + UINTN SourceOffset; + UINTN SourceWidth; + UINTN Rows; + UINTN Columns; + UINTN X; + UINTN Y; + UINTN CurrentMode; + + BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This); + +//*** AMI PORTING BEGIN ***// +// Workaround for EIP 35682. +// Allocate memory buffers during the first call of the funciton. +// See comments above AllocateTheBuffers function for additional details. + if (BiosVideoPrivate->LineBuffer==NULL){ + EFI_STATUS Status = AllocateTheBuffers(BiosVideoPrivate); + if (EFI_ERROR(Status)) return Status; + } +//*** AMI PORTING END *****// + + CurrentMode = This->Mode->Mode; + PciIo = BiosVideoPrivate->PciIo; + MemAddress = BiosVideoPrivate->ModeData[CurrentMode].LinearFrameBuffer; + BytesPerScanLine = BiosVideoPrivate->ModeData[CurrentMode].BytesPerScanLine >> 3; + BytesPerBitPlane = BytesPerScanLine * BiosVideoPrivate->ModeData[CurrentMode].VerticalResolution; + VgaFrameBuffer = BiosVideoPrivate->VgaFrameBuffer; + + if (This == NULL || ((UINTN) BltOperation) >= EfiGraphicsOutputBltOperationMax) { + return EFI_INVALID_PARAMETER; + } + + if (Width == 0 || Height == 0) { + return EFI_INVALID_PARAMETER; + } + // + // We need to fill the Virtual Screen buffer with the blt data. + // The virtual screen is upside down, as the first row is the bootom row of + // the image. + // + if (BltOperation == EfiBltVideoToBltBuffer) { + // + // Video to BltBuffer: Source is Video, destination is BltBuffer + // + if (SourceY + Height > BiosVideoPrivate->ModeData[CurrentMode].VerticalResolution) { + return EFI_INVALID_PARAMETER; + } + + if (SourceX + Width > BiosVideoPrivate->ModeData[CurrentMode].HorizontalResolution) { + return EFI_INVALID_PARAMETER; + } + } else { + // + // BltBuffer to Video: Source is BltBuffer, destination is Video + // + if (DestinationY + Height > BiosVideoPrivate->ModeData[CurrentMode].VerticalResolution) { + return EFI_INVALID_PARAMETER; + } + + if (DestinationX + Width > BiosVideoPrivate->ModeData[CurrentMode].HorizontalResolution) { + return EFI_INVALID_PARAMETER; + } + } + // + // If Delta is zero, then the entire BltBuffer is being used, so Delta + // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size, + // the number of bytes in each row can be computed. + // + if (Delta == 0) { + Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL); + } + // + // We have to raise to TPL Notify, so we make an atomic write the frame buffer. + // We would not want a timer based event (Cursor, ...) to come in while we are + // doing this operation. + // + OriginalTPL = gBS->RaiseTPL (EFI_TPL_NOTIFY); + + // + // Compute some values we need for VGA + // + switch (BltOperation) { + case EfiBltVideoToBltBuffer: + + SourceOffset = (SourceY << 6) + (SourceY << 4) + (SourceX >> 3); + SourceWidth = ((SourceX + Width - 1) >> 3) - (SourceX >> 3) + 1; + + // + // Read all the pixels in the 4 bit planes into a memory buffer that looks like the VGA buffer + // + VgaReadBitPlanes ( + PciIo, + MemAddress + SourceOffset, + VgaFrameBuffer + SourceOffset, + SourceWidth, + Height + ); + + // + // Convert VGA Bit Planes to a Graphics Output 32-bit color value + // + BltBuffer += (DestinationY * (Delta >> 2) + DestinationX); + for (Rows = 0, Y = SourceY; Rows < Height; Rows++, Y++, BltBuffer += (Delta >> 2)) { + for (Columns = 0, X = SourceX; Columns < Width; Columns++, X++, BltBuffer++) { + VgaConvertToGraphicsOutputColor (VgaFrameBuffer, X, Y, BltBuffer); + } + + BltBuffer -= Width; + } + + break; + + case EfiBltVideoToVideo: + // + // Check for an aligned Video to Video operation + // + if ((SourceX & 0x07) == 0x00 && (DestinationX & 0x07) == 0x00 && (Width & 0x07) == 0x00) { + // + // Program the Mode Register Write mode 1, Read mode 0 + // + WriteGraphicsController ( + PciIo, + VGA_GRAPHICS_CONTROLLER_MODE_REGISTER, + VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MODE_1 + ); + + SourceAddress = (UINT8 *) (MemAddress + (SourceY << 6) + (SourceY << 4) + (SourceX >> 3)); + DestinationAddress = (UINT8 *) (MemAddress + (DestinationY << 6) + (DestinationY << 4) + (DestinationX >> 3)); + Bytes = Width >> 3; + for (Index = 0, Offset = 0; Index < Height; Index++, Offset += BytesPerScanLine) { + PciIo->CopyMem ( + PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) (DestinationAddress + Offset), + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) (SourceAddress + Offset), + Bytes + ); + } + } else { + SourceOffset = (SourceY << 6) + (SourceY << 4) + (SourceX >> 3); + SourceWidth = ((SourceX + Width - 1) >> 3) - (SourceX >> 3) + 1; + + // + // Read all the pixels in the 4 bit planes into a memory buffer that looks like the VGA buffer + // + VgaReadBitPlanes ( + PciIo, + MemAddress + SourceOffset, + VgaFrameBuffer + SourceOffset, + SourceWidth, + Height + ); + } + + break; + + case EfiBltVideoFill: + StartAddress = (UINTN) (MemAddress + (DestinationY << 6) + (DestinationY << 4) + (DestinationX >> 3)); + Bytes = ((DestinationX + Width - 1) >> 3) - (DestinationX >> 3); + LeftMask = mVgaLeftMaskTable[DestinationX & 0x07]; + RightMask = mVgaRightMaskTable[(DestinationX + Width - 1) & 0x07]; + if (Bytes == 0) { + LeftMask &= RightMask; + RightMask = 0; + } + + if (LeftMask == 0xff) { + StartAddress--; + Bytes++; + LeftMask = 0; + } + + if (RightMask == 0xff) { + Bytes++; + RightMask = 0; + } + + PixelColor = VgaConvertColor (BltBuffer); + + // + // Program the Mode Register Write mode 2, Read mode 0 + // + WriteGraphicsController ( + PciIo, + VGA_GRAPHICS_CONTROLLER_MODE_REGISTER, + VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MODE_2 + ); + + // + // Program the Data Rotate/Function Select Register to replace + // + WriteGraphicsController ( + PciIo, + VGA_GRAPHICS_CONTROLLER_DATA_ROTATE_REGISTER, + VGA_GRAPHICS_CONTROLLER_FUNCTION_REPLACE + ); + + if (LeftMask != 0) { + // + // Program the BitMask register with the Left column mask + // + WriteGraphicsController ( + PciIo, + VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER, + LeftMask + ); + + for (Index = 0, Address = StartAddress; Index < Height; Index++, Address += BytesPerScanLine) { + // + // Read data from the bit planes into the latches + // +//*** AMI PORTING BEGIN ***// +// Replace PciIo.Mem with direct memory access to optimize performance +/* + PciIo->Mem.Read ( + PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) Address, + 1, + &Data + ); +*/ + Data = *(volatile UINT8*)(UINTN)Address; +//*** AMI PORTING END *****// + // + // Write the lower 4 bits of PixelColor to the bit planes in the pixels enabled by BitMask + // +//*** AMI PORTING BEGIN ***// +// Replace PciIo.Mem with direct memory access to optimize performance +/* + PciIo->Mem.Write ( + PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) Address, + 1, + &PixelColor + ); +*/ + *(volatile UINT8*)(UINTN)Address = PixelColor; +//*** AMI PORTING END *****// + } + } + + if (Bytes > 1) { + // + // Program the BitMask register with the middle column mask of 0xff + // + WriteGraphicsController ( + PciIo, + VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER, + 0xff + ); + + for (Index = 0, Address = StartAddress + 1; Index < Height; Index++, Address += BytesPerScanLine) { +//*** AMI PORTING BEGIN ***// +// Replace PciIo.Mem with SetMem to optimize performance +/* + PciIo->Mem.Write ( + PciIo, + EfiPciIoWidthFillUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) Address, + Bytes - 1, + &PixelColor + ); +*/ + gBS->SetMem((VOID*)Address, Bytes - 1, PixelColor); +//*** AMI PORTING END ***// + } + } + + if (RightMask != 0) { + // + // Program the BitMask register with the Right column mask + // + WriteGraphicsController ( + PciIo, + VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER, + RightMask + ); + + for (Index = 0, Address = StartAddress + Bytes; Index < Height; Index++, Address += BytesPerScanLine) { + // + // Read data from the bit planes into the latches + // +//*** AMI PORTING BEGIN ***// +// Replace PciIo.Mem with direct memory access to optimize performance +/* + PciIo->Mem.Read ( + PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) Address, + 1, + &Data + ); +*/ + Data = *(volatile UINT8*)(UINTN)Address; +//*** AMI PORTING END *****// + // + // Write the lower 4 bits of PixelColor to the bit planes in the pixels enabled by BitMask + // +//*** AMI PORTING BEGIN ***// +// Replace PciIo.Mem with direct memory access to optimize performance +/* + PciIo->Mem.Write ( + PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) Address, + 1, + &PixelColor + ); +*/ + *(volatile UINT8*)(UINTN)Address = PixelColor; +//*** AMI PORTING END *****// + } + } + break; + + case EfiBltBufferToVideo: + StartAddress = (UINTN) (MemAddress + (DestinationY << 6) + (DestinationY << 4) + (DestinationX >> 3)); + LeftMask = mVgaBitMaskTable[DestinationX & 0x07]; + + // + // Program the Mode Register Write mode 2, Read mode 0 + // + WriteGraphicsController ( + PciIo, + VGA_GRAPHICS_CONTROLLER_MODE_REGISTER, + VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MODE_2 + ); + + // + // Program the Data Rotate/Function Select Register to replace + // + WriteGraphicsController ( + PciIo, + VGA_GRAPHICS_CONTROLLER_DATA_ROTATE_REGISTER, + VGA_GRAPHICS_CONTROLLER_FUNCTION_REPLACE + ); + + for (Index = 0, Address = StartAddress; Index < Height; Index++, Address += BytesPerScanLine) { + for (Index1 = 0; Index1 < Width; Index1++) { + BiosVideoPrivate->LineBuffer[Index1] = VgaConvertColor (&BltBuffer[(SourceY + Index) * (Delta >> 2) + SourceX + Index1]); + } + AddressFix = Address; + + for (Bit = 0; Bit < 8; Bit++) { + // + // Program the BitMask register with the Left column mask + // + WriteGraphicsController ( + PciIo, + VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER, + LeftMask + ); + + for (Index1 = Bit, Address1 = (UINT8 *) AddressFix; Index1 < Width; Index1 += 8, Address1++) { + // + // Read data from the bit planes into the latches + // +//*** AMI PORTING BEGIN ***// +// Replace PciIo.Mem with direct memory access to optimize performance +/* + PciIo->Mem.Read ( + PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) Address1, + 1, + &Data + ); +*/ + Data = *(volatile UINT8*)(UINTN)Address1; + +/* + PciIo->Mem.Write ( + PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) Address1, + 1, + &BiosVideoPrivate->LineBuffer[Index1] + ); +*/ + *(volatile UINT8*)(UINTN)Address1 = BiosVideoPrivate->LineBuffer[Index1]; +//*** AMI PORTING END *****// + } + + LeftMask = (UINT8) (LeftMask >> 1); + if (LeftMask == 0) { + LeftMask = 0x80; + AddressFix++; + } + } + } + + break; + } + + gBS->RestoreTPL (OriginalTPL); + + return EFI_SUCCESS; +} +//*** AMI PORTING BEGIN ***// +#endif //if INT10_VGA_GO_SUPPORT==1 +//*** AMI PORTING END *****// +//*** AMI PORTING BEGIN ***// +#if INT10_SIMPLE_TEXT_SUPPORT==1 +//*** AMI PORTING END *****// +// +// VGA Mini Port Protocol Functions +// +EFI_STATUS +EFIAPI +BiosVideoVgaMiniPortSetMode ( + IN EFI_VGA_MINI_PORT_PROTOCOL *This, + IN UINTN ModeNumber + ) +/*++ + +Routine Description: + + VgaMiniPort protocol interface to set mode + +Arguments: + + This - Pointer to VgaMiniPort protocol instance + ModeNumber - The index of the mode + +Returns: + + EFI_UNSUPPORTED - The requested mode is not supported + EFI_SUCCESS - The requested mode is set successfully + +--*/ +{ + BIOS_VIDEO_DEV *BiosVideoPrivate; + EFI_IA32_REGISTER_SET Regs; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Make sure the ModeNumber is a valid value + // + if (ModeNumber >= This->MaxMode) { + return EFI_UNSUPPORTED; + } + // + // Get the device structure for this device + // + BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_VGA_MINI_PORT_THIS (This); + + switch (ModeNumber) { + case 0: + // + // Set the 80x25 Text VGA Mode + // + Regs.H.AH = 0x00; + Regs.H.AL = 0x83; + BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs); + + Regs.H.AH = 0x11; + Regs.H.AL = 0x14; + Regs.H.BL = 0; + BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs); + break; + + case 1: + // + // Set the 80x50 Text VGA Mode + // + Regs.H.AH = 0x00; + Regs.H.AL = 0x83; + BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs); + Regs.H.AH = 0x11; + Regs.H.AL = 0x12; + Regs.H.BL = 0; + BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs); + break; + + default: + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS; +} +//*** AMI PORTING BEGIN ***// +#endif //if INT10_SIMPLE_TEXT_SUPPORT==1 +//*** AMI PORTING END *****// +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2014, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** diff --git a/Core/EM/CSM/thunk/CsmVideo/UefiBiosVideo.h b/Core/EM/CSM/thunk/CsmVideo/UefiBiosVideo.h new file mode 100644 index 0000000..9421b5e --- /dev/null +++ b/Core/EM/CSM/thunk/CsmVideo/UefiBiosVideo.h @@ -0,0 +1,597 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2013, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** + +// +// This file contains a 'Sample Driver' and is licensed as such +// under the terms of your license agreement with Intel or your +// vendor. This file may be modified by the user, subject to +// the additional terms of the license agreement +// +/*++ + +Copyright (c) 2006 Intel Corporation. All rights reserved +This software and associated documentation (if any) is furnished +under a license and may only be used or copied in accordance +with the terms of the license. Except as permitted by such +license, no part of this software or documentation may be +reproduced, stored in a retrieval system, or transmitted in any +form or by any means without the express written consent of +Intel Corporation. + +Module Name: + + UefiBiosVideo.h + +Abstract: + +Revision History +--*/ + +#ifndef _BIOS_GRAPHICS_OUTPUT_H +#define _BIOS_GRAPHICS_OUTPUT_H + +//*** AMI PORTING BEGIN ***// +#include "AmiMapping.h" +#include "EdkIICommon.h" +//#include "Tiano.h" +//#include "EfiDriverLib.h" +#include <Protocol/CsmVideoPolicy.h> +//*** AMI PORTING END *****// +#include "VesaBiosExtensions.h" +#include "Pci22.h" + +// +// Driver Consumed Protocol Prototypes +// +#include EFI_PROTOCOL_DEFINITION (DevicePath) +#include EFI_PROTOCOL_DEFINITION (PciIo) +#include EFI_PROTOCOL_DEFINITION (LegacyBios) +//*** AMI PORTING BEGIN ***// +//AMI CSM Core does not need this GUID +//#include EFI_GUID_DEFINITION (LegacyBios) +//*** AMI PORTING END *****// +//*** AMI PORTING BEGIN ***// +//#include EFI_GUID_DEFINITION (StatusCodeCallerId) +//#include EFI_GUID_DEFINITION (StatusCodeDataTypeId) +//*** AMI PORTING END *****// + +// +// Driver Produced Protocol Prototypes +// +#include EFI_PROTOCOL_DEFINITION (DriverBinding) +#include EFI_PROTOCOL_DEFINITION (ComponentName) +#include EFI_PROTOCOL_DEFINITION (GraphicsOutput) +#include EFI_PROTOCOL_DEFINITION (EdidDiscovered) +#include EFI_PROTOCOL_DEFINITION (EdidActive) + +//*** AMI PORTING BEGIN ***// +//#include EFI_PROTOCOL_DEFINITION (VgaMiniPort) +#include "VgaMiniPort.h" + +// uncomment the following lind and remove the following block when Protocol/EdidOverride.h is available +//#include EFI_PROTOCOL_DEFINITION (EdidOverride) +#define EFI_EDID_OVERRIDE_PROTOCOL_GUID \ + { 0x48ecb431, 0xfb72, 0x45c0, 0xa9, 0x22, 0xf4, 0x58, 0xfe, 0x4, 0xb, 0xd5 } + +#define EFI_EDID_OVERRIDE_DONT_OVERRIDE 0x01 +#define EFI_EDID_OVERRIDE_ENABLE_HOT_PLUG 0x02 + +typedef struct _EFI_EDID_OVERRIDE_PROTOCOL EFI_EDID_OVERRIDE_PROTOCOL; + +typedef EFI_STATUS (EFIAPI *EFI_EDID_OVERRIDE_PROTOCOL_GET_EDID) ( + IN EFI_EDID_OVERRIDE_PROTOCOL *This, + IN EFI_HANDLE *ChildHandle, + OUT UINT32 *Attributes, + IN OUT UINTN *EdidSize, + IN OUT UINT8 **Edid + ); + +struct _EFI_EDID_OVERRIDE_PROTOCOL { + EFI_EDID_OVERRIDE_PROTOCOL_GET_EDID GetEdid; +}; +//*** AMI PORTING END *****// + +// +// Packed format support: The number of bits reserved for each of the colors and the actual +// position of RGB in the frame buffer is specified in the VBE Mode information +// +typedef struct { + UINT8 Position; // Position of the color + UINT8 Mask; // The number of bits expressed as a mask +} BIOS_VIDEO_COLOR_PLACEMENT; + +// +// BIOS Graphics Output Graphical Mode Data +// +typedef struct { + UINT16 VbeModeNumber; + UINT16 BytesPerScanLine; + VOID *LinearFrameBuffer; + UINTN FrameBufferSize; + UINT32 HorizontalResolution; + UINT32 VerticalResolution; + UINT32 RefreshRate; + UINT32 BitsPerPixel; + BIOS_VIDEO_COLOR_PLACEMENT Red; + BIOS_VIDEO_COLOR_PLACEMENT Green; + BIOS_VIDEO_COLOR_PLACEMENT Blue; + BIOS_VIDEO_COLOR_PLACEMENT Reserved; + EFI_GRAPHICS_PIXEL_FORMAT PixelFormat; + EFI_PIXEL_BITMASK PixelBitMask; +} BIOS_VIDEO_MODE_DATA; + +// +// BIOS video child handle private data Structure +// +#define BIOS_VIDEO_DEV_SIGNATURE EFI_SIGNATURE_32 ('B', 'V', 'M', 'p') + +typedef struct { + UINTN Signature; + EFI_HANDLE Handle; + + // + // Consumed Protocols + // + EFI_PCI_IO_PROTOCOL *PciIo; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; + + // + // Produced Protocols + // + EFI_GRAPHICS_OUTPUT_PROTOCOL GraphicsOutput; + EFI_EDID_DISCOVERED_PROTOCOL EdidDiscovered; + EFI_EDID_ACTIVE_PROTOCOL EdidActive; + EFI_VGA_MINI_PORT_PROTOCOL VgaMiniPort; + + // + // General fields + // + BOOLEAN VgaCompatible; + BOOLEAN ProduceGraphicsOutput; +//*** AMI PORTING BEGIN ***// +// ExitBootServicesEvent is not used +// EFI_EVENT ExitBootServicesEvent; +//*** AMI PORTING END *****// + + // + // Graphics Output Protocol related fields + // + BOOLEAN HardwareNeedsStarting; + BIOS_VIDEO_MODE_DATA *ModeData; + UINT8 *LineBuffer; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL *VbeFrameBuffer; + UINT8 *VgaFrameBuffer; + + // + // VESA Bios Extensions related fields + // + UINTN NumberOfPagesBelow1MB; // Number of 4KB pages in PagesBelow1MB + EFI_PHYSICAL_ADDRESS PagesBelow1MB; // Buffer for all VBE Information Blocks + VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK *VbeInformationBlock; // 0x200 bytes. Must be allocated below 1MB + VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK *VbeModeInformationBlock; // 0x100 bytes. Must be allocated below 1MB + VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK *VbeEdidDataBlock; // 0x80 bytes. Must be allocated below 1MB + VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK *VbeCrtcInformationBlock; // 59 bytes. Must be allocated below 1MB + UINTN VbeSaveRestorePages; // Number of 4KB pages in VbeSaveRestoreBuffer + EFI_PHYSICAL_ADDRESS VbeSaveRestoreBuffer; // Must be allocated below 1MB + // + // Status code + // + EFI_DEVICE_PATH_PROTOCOL *DevicePath; +} BIOS_VIDEO_DEV; + +#define BIOS_VIDEO_DEV_FROM_PCI_IO_THIS(a) CR (a, BIOS_VIDEO_DEV, PciIo, BIOS_VIDEO_DEV_SIGNATURE) +#define BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS(a) CR (a, BIOS_VIDEO_DEV, GraphicsOutput, BIOS_VIDEO_DEV_SIGNATURE) +#define BIOS_VIDEO_DEV_FROM_VGA_MINI_PORT_THIS(a) CR (a, BIOS_VIDEO_DEV, VgaMiniPort, BIOS_VIDEO_DEV_SIGNATURE) + +#define GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER 0xffff + +// +// Global Variables +// +extern EFI_DRIVER_BINDING_PROTOCOL gBiosVideoDriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gBiosVideoComponentName; +extern EFI_COMPONENT_NAME2_PROTOCOL gBiosVideoComponentName2; + +// +// Driver Binding Protocol functions +// +EFI_STATUS +EFIAPI +BiosVideoDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + This - GC_TODO: add argument description + Controller - GC_TODO: add argument description + RemainingDevicePath - GC_TODO: add argument description + +Returns: + + GC_TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +BiosVideoDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + This - GC_TODO: add argument description + Controller - GC_TODO: add argument description + RemainingDevicePath - GC_TODO: add argument description + +Returns: + + GC_TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +BiosVideoDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + This - GC_TODO: add argument description + Controller - GC_TODO: add argument description + NumberOfChildren - GC_TODO: add argument description + ChildHandleBuffer - GC_TODO: add argument description + +Returns: + + GC_TODO: add return values + +--*/ +; + +// +// Private worker functions +// +EFI_STATUS +BiosVideoCheckForVbe ( + BIOS_VIDEO_DEV *BiosVideoPrivate, +//*** AMI PORTING BEGIN ***// + PCI_TYPE00 *PciConfSpace +//*** AMI PORTING END *****// +) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + BiosVideoPrivate - GC_TODO: add argument description + +Returns: + + GC_TODO: add return values + +--*/ +; + +EFI_STATUS +BiosVideoCheckForVga ( + BIOS_VIDEO_DEV *BiosVideoPrivate + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + BiosVideoPrivate - GC_TODO: add argument description + +Returns: + + GC_TODO: add return values + +--*/ +; + +STATIC +EFI_STATUS +DeRegisterVideoChildHandle ( + EFI_DRIVER_BINDING_PROTOCOL *This, + EFI_HANDLE Controller, + EFI_HANDLE Handle + ) +/*++ + +Routine Description: + + Deregister an video child handle and free resources + +Arguments: + + This - Protocol instance pointer. + Controller - Video controller handle + Handle - Video child handle + +Returns: + + EFI_STATUS + +--*/ +; + +VOID +BiosVideoDeviceReleaseResource ( + BIOS_VIDEO_DEV *BiosVideoChildPrivate + ) +/*++ +Routing Description: + + Release resources of a video child device before stopping it. + +Arguments: + + BiosVideoChildPrivate - Video child device private data structure + +Returns: + + NONE + +---*/ +; + +// +// BIOS Graphics Output Protocol functions +// +EFI_STATUS +EFIAPI +BiosVideoGraphicsOutputQueryMode ( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, + IN UINT32 ModeNumber, + OUT UINTN *SizeOfInfo, + OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info + ) +/*++ + +Routine Description: + + Graphics Output protocol interface to get video mode + + Arguments: + This - Protocol instance pointer. + ModeNumber - The mode number to return information on. + Info - Caller allocated buffer that returns information about ModeNumber. + SizeOfInfo - A pointer to the size, in bytes, of the Info buffer. + + Returns: + EFI_SUCCESS - Mode information returned. + EFI_BUFFER_TOO_SMALL - The Info buffer was too small. + EFI_DEVICE_ERROR - A hardware error occurred trying to retrieve the video mode. + EFI_NOT_STARTED - Video display is not initialized. Call SetMode () + EFI_INVALID_PARAMETER - One of the input args was NULL. + +--*/ +; + +EFI_STATUS +EFIAPI +BiosVideoGraphicsOutputSetMode ( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL * This, + IN UINT32 ModeNumber + ) +/*++ + +Routine Description: + + Graphics Output protocol interface to set video mode + + Arguments: + This - Protocol instance pointer. + ModeNumber - The mode number to be set. + + Returns: + EFI_SUCCESS - Graphics mode was changed. + EFI_DEVICE_ERROR - The device had an error and could not complete the request. + EFI_UNSUPPORTED - ModeNumber is not supported by this device. + +--*/ +; + +EFI_STATUS +EFIAPI +BiosVideoGraphicsOutputVbeBlt ( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL + IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation, + IN UINTN SourceX, + IN UINTN SourceY, + IN UINTN DestinationX, + IN UINTN DestinationY, + IN UINTN Width, + IN UINTN Height, + IN UINTN Delta + ) +/*++ + +Routine Description: + + Graphics Output protocol instance to block transfer for VBE device + +Arguments: + + This - Pointer to Graphics Output protocol instance + BltBuffer - The data to transfer to screen + BltOperation - The operation to perform + SourceX - The X coordinate of the source for BltOperation + SourceY - The Y coordinate of the source for BltOperation + DestinationX - The X coordinate of the destination for BltOperation + DestinationY - The Y coordinate of the destination for BltOperation + Width - The width of a rectangle in the blt rectangle in pixels + Height - The height of a rectangle in the blt rectangle in pixels + Delta - Not used for EfiBltVideoFill and EfiBltVideoToVideo operation. + If a Delta of 0 is used, the entire BltBuffer will be operated on. + If a subrectangle of the BltBuffer is used, then Delta represents + the number of bytes in a row of the BltBuffer. + +Returns: + + EFI_INVALID_PARAMETER - Invalid parameter passed in + EFI_SUCCESS - Blt operation success + +--*/ +; + +EFI_STATUS +EFIAPI +BiosVideoGraphicsOutputVgaBlt ( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL + IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation, + IN UINTN SourceX, + IN UINTN SourceY, + IN UINTN DestinationX, + IN UINTN DestinationY, + IN UINTN Width, + IN UINTN Height, + IN UINTN Delta + ) +/*++ + +Routine Description: + + Grahpics Output protocol instance to block transfer for VGA device + +Arguments: + + This - Pointer to Grahpics Output protocol instance + BltBuffer - The data to transfer to screen + BltOperation - The operation to perform + SourceX - The X coordinate of the source for BltOperation + SourceY - The Y coordinate of the source for BltOperation + DestinationX - The X coordinate of the destination for BltOperation + DestinationY - The Y coordinate of the destination for BltOperation + Width - The width of a rectangle in the blt rectangle in pixels + Height - The height of a rectangle in the blt rectangle in pixels + Delta - Not used for EfiBltVideoFill and EfiBltVideoToVideo operation. + If a Delta of 0 is used, the entire BltBuffer will be operated on. + If a subrectangle of the BltBuffer is used, then Delta represents + the number of bytes in a row of the BltBuffer. + +Returns: + + EFI_INVALID_PARAMETER - Invalid parameter passed in + EFI_SUCCESS - Blt operation success + +--*/ +; + +// +// BIOS VGA Mini Port Protocol functions +// +EFI_STATUS +EFIAPI +BiosVideoVgaMiniPortSetMode ( + IN EFI_VGA_MINI_PORT_PROTOCOL *This, + IN UINTN ModeNumber + ) +/*++ + +Routine Description: + + VgaMiniPort protocol interface to set mode + +Arguments: + + This - Pointer to VgaMiniPort protocol instance + ModeNumber - The index of the mode + +Returns: + + EFI_UNSUPPORTED - The requested mode is not supported + EFI_SUCCESS - The requested mode is set successfully + +--*/ +; + +// +// Standard VGA Definitions +// +#define VGA_HORIZONTAL_RESOLUTION 640 +#define VGA_VERTICAL_RESOLUTION 480 +#define VGA_NUMBER_OF_BIT_PLANES 4 +#define VGA_PIXELS_PER_BYTE 8 +#define VGA_BYTES_PER_SCAN_LINE (VGA_HORIZONTAL_RESOLUTION / VGA_PIXELS_PER_BYTE) +#define VGA_BYTES_PER_BIT_PLANE (VGA_VERTICAL_RESOLUTION * VGA_BYTES_PER_SCAN_LINE) + +#define VGA_GRAPHICS_CONTROLLER_ADDRESS_REGISTER 0x3ce +#define VGA_GRAPHICS_CONTROLLER_DATA_REGISTER 0x3cf + +#define VGA_GRAPHICS_CONTROLLER_SET_RESET_REGISTER 0x00 + +#define VGA_GRAPHICS_CONTROLLER_ENABLE_SET_RESET_REGISTER 0x01 + +#define VGA_GRAPHICS_CONTROLLER_COLOR_COMPARE_REGISTER 0x02 + +#define VGA_GRAPHICS_CONTROLLER_DATA_ROTATE_REGISTER 0x03 +#define VGA_GRAPHICS_CONTROLLER_FUNCTION_REPLACE 0x00 +#define VGA_GRAPHICS_CONTROLLER_FUNCTION_AND 0x08 +#define VGA_GRAPHICS_CONTROLLER_FUNCTION_OR 0x10 +#define VGA_GRAPHICS_CONTROLLER_FUNCTION_XOR 0x18 + +#define VGA_GRAPHICS_CONTROLLER_READ_MAP_SELECT_REGISTER 0x04 + +#define VGA_GRAPHICS_CONTROLLER_MODE_REGISTER 0x05 +#define VGA_GRAPHICS_CONTROLLER_READ_MODE_0 0x00 +#define VGA_GRAPHICS_CONTROLLER_READ_MODE_1 0x08 +#define VGA_GRAPHICS_CONTROLLER_WRITE_MODE_0 0x00 +#define VGA_GRAPHICS_CONTROLLER_WRITE_MODE_1 0x01 +#define VGA_GRAPHICS_CONTROLLER_WRITE_MODE_2 0x02 +#define VGA_GRAPHICS_CONTROLLER_WRITE_MODE_3 0x03 + +#define VGA_GRAPHICS_CONTROLLER_MISCELLANEOUS_REGISTER 0x06 + +#define VGA_GRAPHICS_CONTROLLER_COLOR_DONT_CARE_REGISTER 0x07 + +#define VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER 0x08 + +#endif diff --git a/Core/EM/CSM/thunk/CsmVideo/VesaBiosExtensions.h b/Core/EM/CSM/thunk/CsmVideo/VesaBiosExtensions.h new file mode 100644 index 0000000..5adcdfb --- /dev/null +++ b/Core/EM/CSM/thunk/CsmVideo/VesaBiosExtensions.h @@ -0,0 +1,463 @@ +// +// This file contains a 'Sample Driver' and is licensed as such +// under the terms of your license agreement with Intel or your +// vendor. This file may be modified by the user, subject to +// the additional terms of the license agreement +// +/*++ + +Copyright (c) 1999 - 2006 Intel Corporation. All rights reserved +This software and associated documentation (if any) is furnished +under a license and may only be used or copied in accordance +with the terms of the license. Except as permitted by such +license, no part of this software or documentation may be +reproduced, stored in a retrieval system, or transmitted in any +form or by any means without the express written consent of +Intel Corporation. + +Module Name: + + VesaBiosExtensions.h + +Abstract: + +Revision History + +--*/ + +#ifndef _VESA_BIOS_EXTENSIONS_H +#define _VESA_BIOS_EXTENSIONS_H + +// +// Turn on byte packing of data structures +// +#pragma pack(1) +// +// VESA BIOS Extensions status codes +// +#define VESA_BIOS_EXTENSIONS_STATUS_SUCCESS 0x004f + +// +// VESA BIOS Extensions Services +// +#define VESA_BIOS_EXTENSIONS_RETURN_CONTROLLER_INFORMATION 0x4f00 + +/*++ + + Routine Description: + Function 00 : Return Controller Information + + Arguments: + Inputs: + AX = 0x4f00 + ES:DI = Pointer to buffer to place VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK structure + Outputs: + AX = Return Status + +--*/ +#define VESA_BIOS_EXTENSIONS_RETURN_MODE_INFORMATION 0x4f01 + +/*++ + + Routine Description: + Function 01 : Return Mode Information + + Arguments: + Inputs: + AX = 0x4f01 + CX = Mode Number + ES:DI = Pointer to buffer to place VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK structure + Outputs: + AX = Return Status + +--*/ +#define VESA_BIOS_EXTENSIONS_SET_MODE 0x4f02 + +/*++ + + Routine Description: + Function 02 : Set Mode + + Arguments: + Inputs: + AX = 0x4f02 + BX = Desired mode to set + D0-D8 = Mode Number + D9-D10 = Reserved (must be 0) + D11 = 0 - Use current default refresh rate + = 1 - Use user specfieid CRTC values for refresh rate + D12-D13 = Reserved (must be 0) + D14 = 0 - Use windowed frame buffer model + = 1 - Use linear/flat frame buffer model + D15 = 0 - Clear display memory + = 1 - Don't clear display memory + ES:DI = Pointer to buffer to the VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK structure + Outputs: + AX = Return Status + +--*/ +#define VESA_BIOS_EXTENSIONS_RETURN_CURRENT_MODE 0x4f03 + +/*++ + + Routine Description: + Function 03 : Return Current Mode + + Arguments: + Inputs: + AX = 0x4f03 + Outputs: + AX = Return Status + BX = Current mode + D0-D13 = Mode Number + D14 = 0 - Windowed frame buffer model + = 1 - Linear/flat frame buffer model + D15 = 0 - Memory cleared at last mode set + = 1 - Memory not cleared at last mode set + +--*/ +#define VESA_BIOS_EXTENSIONS_SAVE_RESTORE_STATE 0x4f04 + +/*++ + + Routine Description: + Function 04 : Save/Restore State + + Arguments: + Inputs: + AX = 0x4f03 + DL = 0x00 - Return Save/Restore State buffer size + = 0x01 - Save State + = 0x02 - Restore State + CX = Requested Status + D0 = Save/Restore controller hardware state + D1 = Save/Restore BIOS data state + D2 = Save/Restore DAC state + D3 = Save/Restore Regsiter state + ES:BX = Pointer to buffer if DL=1 or DL=2 + Outputs: + AX = Return Status + BX = Number of 64 byte blocks to hold the state buffer if DL=0 + +--*/ +#define VESA_BIOS_EXTENSIONS_EDID 0x4f15 + +/*++ + + Routine Description: + Function 15 : implement VBE/DDC service + + Arguments: + Inputs: + AX = 0x4f15 + BL = 0x00 - Report VBE/DDC Capabilities + CX = 0x00 - Controller unit number (00 = primary controller) + ES:DI = Null pointer, must be 0:0 in version 1.0 + Outputs: + AX = Return Status + BH = Approx. time in seconds, rounded up, to transfer one EDID block(128 bytes) + BL = DDC level supported + D0 = 0 DDC1 not supported + = 1 DDC1 supported + D1 = 0 DDC2 not supported + = 1 DDC2 supported + D2 = 0 Screen not blanked during data transfer + = 1 Screen blanked during data transfer + + Inputs: + AX = 0x4f15 + BL = 0x01 - Read EDID + CX = 0x00 - Controller unit number (00 = primary controller) + DX = 0x00 - EDID block number + ES:DI = Pointer to buffer in which the EDID block is returned + Outputs: + AX = Return Status +--*/ + +// +// Timing data from EDID data block +// +#define VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE 128 +#define VESA_BIOS_EXTENSIONS_EDID_ESTABLISHED_TIMING_MAX_NUMBER 17 + +typedef struct { + UINT16 HorizontalResolution; + UINT16 VerticalResolution; + UINT16 RefreshRate; +} VESA_BIOS_EXTENSIONS_EDID_TIMING; + +typedef struct { + UINT32 ValidNumber; + UINT32 Key[VESA_BIOS_EXTENSIONS_EDID_ESTABLISHED_TIMING_MAX_NUMBER]; +} VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING; + +typedef struct { + UINT8 Header[8]; //EDID header "00 FF FF FF FF FF FF 00" + UINT16 ManufactureName; //EISA 3-character ID + UINT16 ProductCode; //Vendor assigned code + UINT32 SerialNumber; //32-bit serial number + UINT8 WeekOfManufacture; //Week number + UINT8 YearOfManufacture; //Year + UINT8 EdidVersion; //EDID Structure Version + UINT8 EdidRevision; //EDID Structure Revision + UINT8 VideoInputDefinition; + UINT8 MaxHorizontalImageSize; //cm + UINT8 MaxVerticalImageSize; //cm + UINT8 DisplayTransferCharacteristic; + UINT8 FeatureSupport; + UINT8 RedGreenLowBits; //Rx1 Rx0 Ry1 Ry0 Gx1 Gx0 Gy1Gy0 + UINT8 BlueWhiteLowBits; //Bx1 Bx0 By1 By0 Wx1 Wx0 Wy1 Wy0 + UINT8 RedX; //Red-x Bits 9 - 2 + UINT8 RedY; //Red-y Bits 9 - 2 + UINT8 GreenX; //Green-x Bits 9 - 2 + UINT8 GreenY; //Green-y Bits 9 - 2 + UINT8 BlueX; //Blue-x Bits 9 - 2 + UINT8 BlueY; //Blue-y Bits 9 - 2 + UINT8 WhiteX; //White-x Bits 9 - 2 + UINT8 WhiteY; //White-x Bits 9 - 2 + UINT8 EstablishedTimings[3]; + UINT8 StandardTimingIdentification[16]; + UINT8 DetailedTimingDescriptions[72]; + UINT8 ExtensionFlag; //Number of (optional) 128-byte EDID extension blocks to follow + UINT8 Checksum; +} VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK; + +// +// Super VGA Information Block +// +typedef struct { + UINT32 VESASignature; // 'VESA' 4 byte signature + UINT16 VESAVersion; // VBE version number + UINT32 OEMStringPtr; // Pointer to OEM string + UINT32 Capabilities; // Capabilities of video card + UINT32 VideoModePtr; // Pointer to an array of 16-bit supported modes values terminated by 0xFFFF + UINT16 TotalMemory; // Number of 64kb memory blocks + UINT16 OemSoftwareRev; // VBE implementation Software revision + UINT32 OemVendorNamePtr; // VbeFarPtr to Vendor Name String + UINT32 OemProductNamePtr; // VbeFarPtr to Product Name String + UINT32 OemProductRevPtr; // VbeFarPtr to Product Revision String + UINT8 Reserved[222]; // Reserved for VBE implementation scratch area + UINT8 OemData[256]; // Data area for OEM strings. Pad to 512 byte block size +} VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK; + +// +// Super VGA Information Block VESASignature values +// +#define VESA_BIOS_EXTENSIONS_VESA_SIGNATURE EFI_SIGNATURE_32 ('V', 'E', 'S', 'A') +#define VESA_BIOS_EXTENSIONS_VBE2_SIGNATURE EFI_SIGNATURE_32 ('V', 'B', 'E', '2') + +// +// Super VGA Information Block VESAVersion values +// +#define VESA_BIOS_EXTENSIONS_VERSION_1_2 0x0102 +#define VESA_BIOS_EXTENSIONS_VERSION_2_0 0x0200 +#define VESA_BIOS_EXTENSIONS_VERSION_3_0 0x0300 + +// +// Super VGA Information Block Capabilities field bit defintions +// +#define VESA_BIOS_EXTENSIONS_CAPABILITY_8_BIT_DAC 0x01 // 0: DAC width is fixed at 6 bits/color +// 1: DAC width switchable to 8 bits/color +// +#define VESA_BIOS_EXTENSIONS_CAPABILITY_NOT_VGA 0x02 // 0: Controller is VGA compatible +// 1: Controller is not VGA compatible +// +#define VESA_BIOS_EXTENSIONS_CAPABILITY_NOT_NORMAL_RAMDAC 0x04 // 0: Normal RAMDAC operation +// 1: Use blank bit in function 9 to program RAMDAC +// +#define VESA_BIOS_EXTENSIONS_CAPABILITY_STEREOSCOPIC 0x08 // 0: No hardware stereoscopic signal support +// 1: Hardware stereoscopic signal support +// +#define VESA_BIOS_EXTENSIONS_CAPABILITY_VESA_EVC 0x10 // 0: Stero signaling supported via external VESA stereo connector +// 1: Stero signaling supported via VESA EVC connector +// +// Super VGA mode number bite field definitions +// +#define VESA_BIOS_EXTENSIONS_MODE_NUMBER_VESA 0x0100 // 0: Not a VESA defined VBE mode +// 1: A VESA defined VBE mode +// +#define VESA_BIOS_EXTENSIONS_MODE_NUMBER_REFRESH_CONTROL_USER 0x0800 // 0: Use current BIOS default referesh rate +// 1: Use the user specified CRTC values for refresh rate +// +#define VESA_BIOS_EXTENSIONS_MODE_NUMBER_LINEAR_FRAME_BUFFER 0x4000 // 0: Use a banked/windowed frame buffer +// 1: Use a linear/flat frame buffer +// +#define VESA_BIOS_EXTENSIONS_MODE_NUMBER_PRESERVE_MEMORY 0x8000 // 0: Clear display memory +// 1: Preseve display memory +// +// Super VGA Information Block mode list terminator value +// +#define VESA_BIOS_EXTENSIONS_END_OF_MODE_LIST 0xffff + +// +// Window Function +// +typedef +VOID +(*VESA_BIOS_EXTENSIONS_WINDOW_FUNCTION) ( + VOID + ); + +// +// Super VGA Mode Information Block +// +typedef struct { + // + // Manadory fields for all VESA Bios Extensions revisions + // + UINT16 ModeAttributes; // Mode attributes + UINT8 WinAAttributes; // Window A attributes + UINT8 WinBAttributes; // Window B attributes + UINT16 WinGranularity; // Window granularity in k + UINT16 WinSize; // Window size in k + UINT16 WinASegment; // Window A segment + UINT16 WinBSegment; // Window B segment + UINT32 WindowFunction; // Pointer to window function + UINT16 BytesPerScanLine; // Bytes per scanline + // + // Manadory fields for VESA Bios Extensions 1.2 and above + // + UINT16 XResolution; // Horizontal resolution + UINT16 YResolution; // Vertical resolution + UINT8 XCharSize; // Character cell width + UINT8 YCharSize; // Character cell height + UINT8 NumberOfPlanes; // Number of memory planes + UINT8 BitsPerPixel; // Bits per pixel + UINT8 NumberOfBanks; // Number of CGA style banks + UINT8 MemoryModel; // Memory model type + UINT8 BankSize; // Size of CGA style banks + UINT8 NumberOfImagePages; // Number of images pages + UINT8 Reserved1; // Reserved + UINT8 RedMaskSize; // Size of direct color red mask + UINT8 RedFieldPosition; // Bit posn of lsb of red mask + UINT8 GreenMaskSize; // Size of direct color green mask + UINT8 GreenFieldPosition; // Bit posn of lsb of green mask + UINT8 BlueMaskSize; // Size of direct color blue mask + UINT8 BlueFieldPosition; // Bit posn of lsb of blue mask + UINT8 RsvdMaskSize; // Size of direct color res mask + UINT8 RsvdFieldPosition; // Bit posn of lsb of res mask + UINT8 DirectColorModeInfo; // Direct color mode attributes + // + // Manadory fields for VESA Bios Extensions 2.0 and above + // + UINT32 PhysBasePtr; // Physical Address for flat memory frame buffer + UINT32 Reserved2; // Reserved + UINT16 Reserved3; // Reserved + // + // Manadory fields for VESA Bios Extensions 3.0 and above + // + UINT16 LinBytesPerScanLine; // Bytes/scan line for linear modes + UINT8 BnkNumberOfImagePages; // Number of images for banked modes + UINT8 LinNumberOfImagePages; // Number of images for linear modes + UINT8 LinRedMaskSize; // Size of direct color red mask (linear mode) + UINT8 LinRedFieldPosition; // Bit posiiton of lsb of red mask (linear modes) + UINT8 LinGreenMaskSize; // Size of direct color green mask (linear mode) + UINT8 LinGreenFieldPosition; // Bit posiiton of lsb of green mask (linear modes) + UINT8 LinBlueMaskSize; // Size of direct color blue mask (linear mode) + UINT8 LinBlueFieldPosition; // Bit posiiton of lsb of blue mask (linear modes) + UINT8 LinRsvdMaskSize; // Size of direct color reserved mask (linear mode) + UINT8 LinRsvdFieldPosition; // Bit posiiton of lsb of reserved mask (linear modes) + UINT32 MaxPixelClock; // Maximum pixel clock (in Hz) for graphics mode + UINT8 Pad[190]; // Pad to 256 byte block size +} VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK; + +// +// Super VGA Mode Information Block ModeAttributes field bit defintions +// +#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_HARDWARE 0x0001 // 0: Mode not supported in handware +// 1: Mode supported in handware +// +#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_TTY 0x0004 // 0: TTY Output functions not supported by BIOS +// 1: TTY Output functions supported by BIOS +// +#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_COLOR 0x0008 // 0: Monochrome mode +// 1: Color mode +// +#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_GRAPHICS 0x0010 // 0: Text mode +// 1: Graphics mode +// +#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_NOT_VGA 0x0020 // 0: VGA compatible mode +// 1: Not a VGA compatible mode +// +#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_NOT_WINDOWED 0x0040 // 0: VGA compatible windowed memory mode +// 1: Not a VGA compatible windowed memory mode +// +#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER 0x0080 // 0: No linear fram buffer mode available +// 1: Linear frame buffer mode available +// +#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_DOUBLE_SCAN 0x0100 // 0: No double scan mode available +// 1: Double scan mode available +// +#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_INTERLACED 0x0200 // 0: No interlaced mode is available +// 1: Interlaced mode is available +// +#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_NO_TRIPPLE_BUFFER 0x0400 // 0: No hardware triple buffer mode support available +// 1: Hardware triple buffer mode support available +// +#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_STEREOSCOPIC 0x0800 // 0: No hardware steroscopic display support +// 1: Hardware steroscopic display support +// +#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_DUAL_DISPLAY 0x1000 // 0: No dual display start address support +// 1: Dual display start address support +// +// Super VGA Mode Information Block WinAAttribite/WinBAttributes field bit defintions +// +#define VESA_BIOS_EXTENSIONS_WINX_ATTRIBUTE_RELOCATABLE 0x01 // 0: Single non-relocatable window only +// 1: Relocatable window(s) are supported +// +#define VESA_BIOS_EXTENSIONS_WINX_ATTRIBUTE_READABLE 0x02 // 0: Window is not readable +// 1: Window is readable +// +#define VESA_BIOS_EXTENSIONS_WINX_ATTRIBUTE_WRITABLE 0x04 // 0: Window is not writable +// 1: Window is writable +// +// Super VGA Mode Information Block DirectColorMode field bit defintions +// +#define VESA_BIOS_EXTENSIONS_DIRECT_COLOR_MODE_PROG_COLOR_RAMP 0x01 // 0: Color ram is fixed +// 1: Color ramp is programmable +// +#define VESA_BIOS_EXTENSIONS_DIRECT_COLOR_MODE_RSVD_USABLE 0x02 // 0: Bits in Rsvd field are reserved +// 1: Bits in Rsdv field are usable +// +// Super VGA Memory Models +// +typedef enum { + memPL = 3, // Planar memory model + memPK = 4, // Packed pixel memory model + memRGB= 6, // Direct color RGB memory model + memYUV= 7, // Direct color YUV memory model +} VESA_BIOS_EXTENSIONS_MEMORY_MODELS; + +// +// Super VGA CRTC Information Block +// +typedef struct { + UINT16 HorizontalTotal; // Horizontal total in pixels + UINT16 HorizontalSyncStart; // Horizontal sync start in pixels + UINT16 HorizontalSyncEnd; // Horizontal sync end in pixels + UINT16 VericalTotal; // Vertical total in pixels + UINT16 VericalSyncStart; // Vertical sync start in pixels + UINT16 VericalSyncEnd; // Vertical sync end in pixels + UINT8 Flags; // Flags (Interlaced/DoubleScan/etc). + UINT32 PixelClock; // Pixel clock in units of Hz + UINT16 RefreshRate; // Refresh rate in units of 0.01 Hz + UINT8 Reserved[40]; // Pad +} VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK; + +#define VESA_BIOS_EXTENSIONS_CRTC_FLAGS_DOUBLE_SCAN 0x01 // 0: Graphics mode is not souble scanned +// 1: Graphics mode is double scanned +// +#define VESA_BIOS_EXTENSIONS_CRTC_FLAGSINTERLACED 0x02 // 0: Graphics mode is not interlaced +// 1: Graphics mode is interlaced +// +#define VESA_BIOS_EXTENSIONS_CRTC_HORIZONTAL_SYNC_NEGATIVE 0x04 // 0: Horizontal sync polarity is positive(+) +// 0: Horizontal sync polarity is negative(-) +// +#define VESA_BIOS_EXTENSIONS_CRTC_VERITICAL_SYNC_NEGATIVE 0x08 // 0: Verical sync polarity is positive(+) +// 0: Verical sync polarity is negative(-) +// +// Turn off byte packing of data structures +// +#pragma pack() + +#endif diff --git a/Core/EM/CSM/thunk/CsmVideo/VgaClass.c b/Core/EM/CSM/thunk/CsmVideo/VgaClass.c new file mode 100644 index 0000000..1315bf5 --- /dev/null +++ b/Core/EM/CSM/thunk/CsmVideo/VgaClass.c @@ -0,0 +1,1349 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2013, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** + +/*++ + This file contains a 'Sample Driver' and is licensed as such + under the terms of your license agreement with Intel or your + vendor. This file may be modified by the user, subject to + the additional terms of the license agreement +--*/ +/*++ + +Copyright (c) 1999 - 2003 Intel Corporation. All rights reserved +This software and associated documentation (if any) is furnished +under a license and may only be used or copied in accordance +with the terms of the license. Except as permitted by such +license, no part of this software or documentation may be +reproduced, stored in a retrieval system, or transmitted in any +form or by any means without the express written consent of +Intel Corporation. + + +Module Name: + + VgaClass.c + +Abstract: + This driver produces a VGA console. + +--*/ +#include "VgaClass.h" +//*** AMI PORTING BEGIN ***// +#if INT10_SIMPLE_TEXT_SUPPORT==1 +//*** AMI PORTING END *****// + +// +// EFI Driver Binding Protocol for the VGA Class Driver +// +EFI_DRIVER_BINDING_PROTOCOL gVgaClassDriverBinding = { + VgaClassDriverBindingSupported, + VgaClassDriverBindingStart, + VgaClassDriverBindingStop, + 0x10, + NULL, + NULL +}; + +// +// Local variables +// +static CHAR16 CrLfString[3] = { CHAR_CARRIAGE_RETURN, CHAR_LINEFEED, CHAR_NULL }; + +typedef struct { + CHAR16 Unicode; + CHAR8 PcAnsi; + CHAR8 Ascii; +} UNICODE_TO_CHAR; + +// +// This list is used to define the valid extend chars. +// It also provides a mapping from Unicode to PCANSI or +// ASCII. The ASCII mapping we just made up. +// +// +STATIC UNICODE_TO_CHAR UnicodeToPcAnsiOrAscii[] = { + BOXDRAW_HORIZONTAL, + 0xc4, + L'-', + BOXDRAW_VERTICAL, + 0xb3, + L'|', + BOXDRAW_DOWN_RIGHT, + 0xda, + L'/', + BOXDRAW_DOWN_LEFT, + 0xbf, + L'\\', + BOXDRAW_UP_RIGHT, + 0xc0, + L'\\', + BOXDRAW_UP_LEFT, + 0xd9, + L'/', + BOXDRAW_VERTICAL_RIGHT, + 0xc3, + L'|', + BOXDRAW_VERTICAL_LEFT, + 0xb4, + L'|', + BOXDRAW_DOWN_HORIZONTAL, + 0xc2, + L'+', + BOXDRAW_UP_HORIZONTAL, + 0xc1, + L'+', + BOXDRAW_VERTICAL_HORIZONTAL, + 0xc5, + L'+', + BOXDRAW_DOUBLE_HORIZONTAL, + 0xcd, + L'-', + BOXDRAW_DOUBLE_VERTICAL, + 0xba, + L'|', + BOXDRAW_DOWN_RIGHT_DOUBLE, + 0xd5, + L'/', + BOXDRAW_DOWN_DOUBLE_RIGHT, + 0xd6, + L'/', + BOXDRAW_DOUBLE_DOWN_RIGHT, + 0xc9, + L'/', + BOXDRAW_DOWN_LEFT_DOUBLE, + 0xb8, + L'\\', + BOXDRAW_DOWN_DOUBLE_LEFT, + 0xb7, + L'\\', + BOXDRAW_DOUBLE_DOWN_LEFT, + 0xbb, + L'\\', + BOXDRAW_UP_RIGHT_DOUBLE, + 0xd4, + L'\\', + BOXDRAW_UP_DOUBLE_RIGHT, + 0xd3, + L'\\', + BOXDRAW_DOUBLE_UP_RIGHT, + 0xc8, + L'\\', + BOXDRAW_UP_LEFT_DOUBLE, + 0xbe, + L'/', + BOXDRAW_UP_DOUBLE_LEFT, + 0xbd, + L'/', + BOXDRAW_DOUBLE_UP_LEFT, + 0xbc, + L'/', + BOXDRAW_VERTICAL_RIGHT_DOUBLE, + 0xc6, + L'|', + BOXDRAW_VERTICAL_DOUBLE_RIGHT, + 0xc7, + L'|', + BOXDRAW_DOUBLE_VERTICAL_RIGHT, + 0xcc, + L'|', + BOXDRAW_VERTICAL_LEFT_DOUBLE, + 0xb5, + L'|', + BOXDRAW_VERTICAL_DOUBLE_LEFT, + 0xb6, + L'|', + BOXDRAW_DOUBLE_VERTICAL_LEFT, + 0xb9, + L'|', + BOXDRAW_DOWN_HORIZONTAL_DOUBLE, + 0xd1, + L'+', + BOXDRAW_DOWN_DOUBLE_HORIZONTAL, + 0xd2, + L'+', + BOXDRAW_DOUBLE_DOWN_HORIZONTAL, + 0xcb, + L'+', + BOXDRAW_UP_HORIZONTAL_DOUBLE, + 0xcf, + L'+', + BOXDRAW_UP_DOUBLE_HORIZONTAL, + 0xd0, + L'+', + BOXDRAW_DOUBLE_UP_HORIZONTAL, + 0xca, + L'+', + BOXDRAW_VERTICAL_HORIZONTAL_DOUBLE, + 0xd8, + L'+', + BOXDRAW_VERTICAL_DOUBLE_HORIZONTAL, + 0xd7, + L'+', + BOXDRAW_DOUBLE_VERTICAL_HORIZONTAL, + 0xce, + L'+', + + BLOCKELEMENT_FULL_BLOCK, + 0xdb, + L'*', + BLOCKELEMENT_LIGHT_SHADE, + 0xb0, + L'+', + + GEOMETRICSHAPE_UP_TRIANGLE, + 0x1e, + L'^', + GEOMETRICSHAPE_RIGHT_TRIANGLE, + 0x10, + L'>', + GEOMETRICSHAPE_DOWN_TRIANGLE, + 0x1f, + L'v', + GEOMETRICSHAPE_LEFT_TRIANGLE, + 0x11, + L'<', + + ARROW_LEFT, + 0x3c, + L'<', + + ARROW_UP, + 0x18, + L'^', + + ARROW_RIGHT, + 0x3e, + L'>', + + ARROW_DOWN, + 0x19, + L'v', + + 0x0000, + 0x00 +}; + +// +// Private worker functions +// +STATIC +VOID +SetVideoCursorPosition ( + IN VGA_CLASS_DEV *VgaClassDev, + IN UINTN Column, + IN UINTN Row, + IN UINTN MaxColumn + ); + +STATIC +VOID +WriteCrtc ( + IN VGA_CLASS_DEV *VgaClassDev, + IN UINT16 Address, + IN UINT8 Data + ); + +STATIC +BOOLEAN +LibIsValidTextGraphics ( + IN CHAR16 Graphic, + OUT CHAR8 *PcAnsi, OPTIONAL + OUT CHAR8 *Ascii OPTIONAL + ); + +STATIC +BOOLEAN +IsValidAscii ( + IN CHAR16 Ascii + ); + +STATIC +BOOLEAN +IsValidEfiCntlChar ( + IN CHAR16 c + ); + +// +// Driver Entry Point +// +EFI_DRIVER_ENTRY_POINT (VgaClassDriverEntryPoint) + +EFI_STATUS +EFIAPI +VgaClassDriverEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + + Routine Description: + + Driver Entry Point. + + Arguments: + + (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT) + + Returns: + EFI_STATUS +--*/ +// GC_TODO: ImageHandle - add argument and description to function comment +// GC_TODO: SystemTable - add argument and description to function comment +{ + return INSTALL_ALL_DRIVER_PROTOCOLS ( + ImageHandle, + SystemTable, + &gVgaClassDriverBinding, + ImageHandle, +//*** AMI PORTING BEGIN ***// + NULL, +// &gVgaClassComponentName, +//*** AMI PORTING END *****// + NULL, + NULL + ); +} + +EFI_STATUS +EFIAPI +VgaClassDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + + Routine Description: + + Supported. + + Arguments: + + (Standard DriverBinding Protocol Supported() function) + + Returns: + + EFI_STATUS + +--*/ +// GC_TODO: This - add argument and description to function comment +// GC_TODO: Controller - add argument and description to function comment +// GC_TODO: RemainingDevicePath - add argument and description to function comment +{ + EFI_STATUS Status; + EFI_VGA_MINI_PORT_PROTOCOL *VgaMiniPort; + + // + // Open the IO Abstraction(s) needed to perform the supported test + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiVgaMiniPortProtocolGuid, + (VOID **) &VgaMiniPort, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Open the IO Abstraction(s) needed to perform the supported test + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + NULL, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + return Status; +} + +EFI_STATUS +EFIAPI +VgaClassDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + + Routine Description: + + Layers the Simple Text Output Protocol on top of the + VGA Mini Port Protocol + + Arguments: + + (Standard DriverBinding Protocol Start() function) + + Returns: + + EFI_STATUS + +--*/ +// GC_TODO: This - add argument and description to function comment +// GC_TODO: Controller - add argument and description to function comment +// GC_TODO: RemainingDevicePath - add argument and description to function comment +// GC_TODO: EFI_OUT_OF_RESOURCES - add return value to function comment +{ + EFI_STATUS Status; + EFI_VGA_MINI_PORT_PROTOCOL *VgaMiniPort; + EFI_PCI_IO_PROTOCOL *PciIo; + VGA_CLASS_DEV *VgaClassPrivate; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + Status = gBS->HandleProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + &DevicePath + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Report that VGA Class driver is being enabled + // + ReportStatusCodeWithDevicePath ( + EFI_PROGRESS_CODE, + EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_PC_ENABLE, + 0, + &gEfiCallerIdGuid, + DevicePath + ); + + // + // Open the IO Abstraction(s) needed + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gBS->OpenProtocol ( + Controller, + &gEfiVgaMiniPortProtocolGuid, + (VOID **) &VgaMiniPort, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Allocate the private device structure + // + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (VGA_CLASS_DEV), + &VgaClassPrivate + ); + if (EFI_ERROR (Status)) { + gBS->CloseProtocol ( + Controller, + &gEfiVgaMiniPortProtocolGuid, + This->DriverBindingHandle, + Controller + ); + return EFI_OUT_OF_RESOURCES; + } + + EfiZeroMem (VgaClassPrivate, sizeof (VGA_CLASS_DEV)); + + // + // Initialize the private device structure + // + VgaClassPrivate->Signature = VGA_CLASS_DEV_SIGNATURE; + VgaClassPrivate->Handle = Controller; + VgaClassPrivate->VgaMiniPort = VgaMiniPort; + VgaClassPrivate->PciIo = PciIo; + + VgaClassPrivate->SimpleTextOut.Reset = VgaClassReset; + VgaClassPrivate->SimpleTextOut.OutputString = VgaClassOutputString; + VgaClassPrivate->SimpleTextOut.TestString = VgaClassTestString; + VgaClassPrivate->SimpleTextOut.ClearScreen = VgaClassClearScreen; + VgaClassPrivate->SimpleTextOut.SetAttribute = VgaClassSetAttribute; + VgaClassPrivate->SimpleTextOut.SetCursorPosition = VgaClassSetCursorPosition; + VgaClassPrivate->SimpleTextOut.EnableCursor = VgaClassEnableCursor; + VgaClassPrivate->SimpleTextOut.QueryMode = VgaClassQueryMode; + VgaClassPrivate->SimpleTextOut.SetMode = VgaClassSetMode; + + VgaClassPrivate->SimpleTextOut.Mode = &VgaClassPrivate->SimpleTextOutputMode; + VgaClassPrivate->SimpleTextOutputMode.MaxMode = VgaMiniPort->MaxMode; + VgaClassPrivate->DevicePath = DevicePath; + + Status = VgaClassPrivate->SimpleTextOut.SetAttribute ( + &VgaClassPrivate->SimpleTextOut, + EFI_TEXT_ATTR (EFI_WHITE, + EFI_BLACK) + ); + if (EFI_ERROR (Status)) { + goto ErrorExit; + } + + Status = VgaClassPrivate->SimpleTextOut.Reset ( + &VgaClassPrivate->SimpleTextOut, + FALSE + ); + if (EFI_ERROR (Status)) { + goto ErrorExit; + } + + Status = VgaClassPrivate->SimpleTextOut.EnableCursor ( + &VgaClassPrivate->SimpleTextOut, + TRUE + ); + if (EFI_ERROR (Status)) { + goto ErrorExit; + } + + Status = gBS->InstallMultipleProtocolInterfaces ( + &Controller, + &gEfiSimpleTextOutProtocolGuid, + &VgaClassPrivate->SimpleTextOut, + NULL + ); + + return Status; + +ErrorExit: + ReportStatusCodeWithDevicePath ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_CONTROLLER_ERROR, + 0, + &gEfiCallerIdGuid, + DevicePath + ); + + return Status; + +} + +EFI_STATUS +EFIAPI +VgaClassDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +/*++ + + Routine Description: + + Stop. + + Arguments: + + (Standard DriverBinding Protocol Stop() function) + + Returns: + + EFI_STATUS + +--*/ +// GC_TODO: This - add argument and description to function comment +// GC_TODO: Controller - add argument and description to function comment +// GC_TODO: NumberOfChildren - add argument and description to function comment +// GC_TODO: ChildHandleBuffer - add argument and description to function comment +// GC_TODO: EFI_SUCCESS - add return value to function comment +{ + EFI_STATUS Status; + EFI_SIMPLE_TEXT_OUT_PROTOCOL *SimpleTextOut; + VGA_CLASS_DEV *VgaClassPrivate; + + Status = gBS->OpenProtocol ( + Controller, + &gEfiSimpleTextOutProtocolGuid, + (VOID **) &SimpleTextOut, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + VgaClassPrivate = VGA_CLASS_DEV_FROM_THIS (SimpleTextOut); + + // + // Report that VGA Class driver is being disabled + // + ReportStatusCodeWithDevicePath ( + EFI_PROGRESS_CODE, + EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_PC_DISABLE, + 0, + &gEfiCallerIdGuid, + VgaClassPrivate->DevicePath + ); + + Status = gBS->UninstallProtocolInterface ( + Controller, + &gEfiSimpleTextOutProtocolGuid, + &VgaClassPrivate->SimpleTextOut + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Release PCI I/O and VGA Mini Port Protocols on the controller handle. + // + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + gBS->CloseProtocol ( + Controller, + &gEfiVgaMiniPortProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + gBS->FreePool (VgaClassPrivate); + + return EFI_SUCCESS; +} +// +// Simple Text Output Protocol Functions +// +EFI_STATUS +EFIAPI +VgaClassReset ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + This - GC_TODO: add argument description + ExtendedVerification - GC_TODO: add argument description + +Returns: + + GC_TODO: add return values + +--*/ +{ + EFI_STATUS Status; + VGA_CLASS_DEV *VgaClassPrivate; + + VgaClassPrivate = VGA_CLASS_DEV_FROM_THIS (This); + + ReportStatusCodeWithDevicePath ( + EFI_PROGRESS_CODE, + EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_PC_RESET, + 0, + &gEfiCallerIdGuid, + VgaClassPrivate->DevicePath + ); + + This->SetAttribute (This, EFI_TEXT_ATTR (This->Mode->Attribute & 0x0F, EFI_BACKGROUND_BLACK)); + + Status = This->SetMode (This, 0); + if (EFI_ERROR (Status)) { + return Status; + } + + return This->ClearScreen (This); +} + +EFI_STATUS +EFIAPI +VgaClassOutputString ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN CHAR16 *WString + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + This - GC_TODO: add argument description + WString - GC_TODO: add argument description + +Returns: + + EFI_SUCCESS - GC_TODO: Add description for return value + +--*/ +{ + EFI_STATUS Status; + VGA_CLASS_DEV *VgaClassDev; + EFI_SIMPLE_TEXT_OUTPUT_MODE *Mode; + UINTN MaxColumn; + UINTN MaxRow; + CHAR16 *SavedWString; + UINT32 VideoChar; + CHAR8 GraphicChar; + + VgaClassDev = VGA_CLASS_DEV_FROM_THIS (This); + + Mode = This->Mode; + + Status = This->QueryMode ( + This, + Mode->Mode, + &MaxColumn, + &MaxRow + ); + if (EFI_ERROR (Status)) { + return Status; + } + + SavedWString = WString; + for (; *WString != CHAR_NULL; WString++) { + + switch (*WString) { + case CHAR_BACKSPACE: + if (Mode->CursorColumn > 0) { + Mode->CursorColumn--; + } + break; + + case CHAR_LINEFEED: + if (Mode->CursorRow == (INT32) (MaxRow - 1)) { + // + // Scroll the screen by copying the contents + // of the VGA display up one line + // + VgaClassDev->PciIo->CopyMem ( + VgaClassDev->PciIo, + EfiPciIoWidthUint32, + VgaClassDev->VgaMiniPort->VgaMemoryBar, + VgaClassDev->VgaMiniPort->VgaMemoryOffset, + VgaClassDev->VgaMiniPort->VgaMemoryBar, + VgaClassDev->VgaMiniPort->VgaMemoryOffset + MaxColumn * 2, + ((MaxRow - 1) * MaxColumn) >> 1 + ); + + // + // Print Blank Line of spaces with the current color attributes + // + VideoChar = (Mode->Attribute << 8) | ' '; + VideoChar = (VideoChar << 16) | VideoChar; + VgaClassDev->PciIo->Mem.Write ( + VgaClassDev->PciIo, + EfiPciIoWidthFillUint32, + VgaClassDev->VgaMiniPort->VgaMemoryBar, + VgaClassDev->VgaMiniPort->VgaMemoryOffset + (MaxRow - 1) * MaxColumn * 2, + MaxColumn >> 1, + &VideoChar + ); + } + + if (Mode->CursorRow < (INT32) (MaxRow - 1)) { + Mode->CursorRow++; + } + break; + + case CHAR_CARRIAGE_RETURN: + Mode->CursorColumn = 0; + break; + + default: + if (!LibIsValidTextGraphics (*WString, &GraphicChar, NULL)) { + // + // Just convert to ASCII + // + GraphicChar = (CHAR8) *WString; + if (!IsValidAscii (GraphicChar)) { + // + // Keep the API from supporting PCANSI Graphics chars + // + GraphicChar = '?'; + } + } + + VideoChar = (Mode->Attribute << 8) | GraphicChar; + VgaClassDev->PciIo->Mem.Write ( + VgaClassDev->PciIo, + EfiPciIoWidthUint16, + VgaClassDev->VgaMiniPort->VgaMemoryBar, + VgaClassDev->VgaMiniPort->VgaMemoryOffset + ((Mode->CursorRow * MaxColumn + Mode->CursorColumn) * 2), + 1, + &VideoChar + ); + + if (Mode->CursorColumn >= (INT32) (MaxColumn - 1)) { + This->OutputString (This, CrLfString); + } else { + Mode->CursorColumn++; + } + break; + } + } + + SetVideoCursorPosition ( + VgaClassDev, + (UINTN) Mode->CursorColumn, + (UINTN) Mode->CursorRow, + MaxColumn + ); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +VgaClassTestString ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN CHAR16 *WString + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + This - GC_TODO: add argument description + WString - GC_TODO: add argument description + +Returns: + + EFI_UNSUPPORTED - GC_TODO: Add description for return value + EFI_SUCCESS - GC_TODO: Add description for return value + +--*/ +{ + while (*WString != 0x0000) { + if (!(IsValidAscii (*WString) || IsValidEfiCntlChar (*WString) || LibIsValidTextGraphics (*WString, NULL, NULL))) { + return EFI_UNSUPPORTED; + } + + WString++; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +VgaClassClearScreen ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + This - GC_TODO: add argument description + +Returns: + + EFI_SUCCESS - GC_TODO: Add description for return value + +--*/ +{ + EFI_STATUS Status; + VGA_CLASS_DEV *VgaClassDev; + UINTN MaxRow; + UINTN MaxColumn; + UINT32 VideoChar; + + VgaClassDev = VGA_CLASS_DEV_FROM_THIS (This); + + Status = This->QueryMode ( + This, + This->Mode->Mode, + &MaxColumn, + &MaxRow + ); + if (EFI_ERROR (Status)) { + return Status; + } + + VideoChar = (This->Mode->Attribute << 8) | ' '; + VideoChar = (VideoChar << 16) | VideoChar; + VgaClassDev->PciIo->Mem.Write ( + VgaClassDev->PciIo, + EfiPciIoWidthFillUint32, + VgaClassDev->VgaMiniPort->VgaMemoryBar, + VgaClassDev->VgaMiniPort->VgaMemoryOffset, + (MaxRow * MaxColumn) >> 1, + &VideoChar + ); + + This->SetCursorPosition (This, 0, 0); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +VgaClassSetAttribute ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN UINTN Attribute + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + This - GC_TODO: add argument description + Attribute - GC_TODO: add argument description + +Returns: + + EFI_SUCCESS - GC_TODO: Add description for return value + EFI_UNSUPPORTED - GC_TODO: Add description for return value + +--*/ +{ +//*** AMI PORTING BEGIN ***// +// Comparison of unsigned value with zero +// if (Attribute >= 0 && Attribute <= EFI_MAX_ATTRIBUTE) { + if (Attribute <= EFI_MAX_ATTRIBUTE) { +//*** AMI PORTING END *****// + This->Mode->Attribute = (INT32) Attribute; + return EFI_SUCCESS; + } + + return EFI_UNSUPPORTED; +} + +EFI_STATUS +EFIAPI +VgaClassSetCursorPosition ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN UINTN Column, + IN UINTN Row + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + This - GC_TODO: add argument description + Column - GC_TODO: add argument description + Row - GC_TODO: add argument description + +Returns: + + EFI_UNSUPPORTED - GC_TODO: Add description for return value + EFI_SUCCESS - GC_TODO: Add description for return value + +--*/ +{ + EFI_STATUS Status; + VGA_CLASS_DEV *VgaClassDev; + UINTN MaxColumn; + UINTN MaxRow; + + VgaClassDev = VGA_CLASS_DEV_FROM_THIS (This); + + Status = This->QueryMode ( + This, + This->Mode->Mode, + &MaxColumn, + &MaxRow + ); + if (EFI_ERROR (Status)) { + return Status; + } + + if (Column >= MaxColumn || Row >= MaxRow) { + return EFI_UNSUPPORTED; + } + + SetVideoCursorPosition (VgaClassDev, Column, Row, MaxColumn); + + This->Mode->CursorColumn = (INT32) Column; + This->Mode->CursorRow = (INT32) Row; + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +VgaClassEnableCursor ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN BOOLEAN Visible + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + This - GC_TODO: add argument description + Visible - GC_TODO: add argument description + +Returns: + + EFI_SUCCESS - GC_TODO: Add description for return value + +--*/ +{ + VGA_CLASS_DEV *VgaClassDev; + + VgaClassDev = VGA_CLASS_DEV_FROM_THIS (This); + if (Visible) { + switch (This->Mode->Mode) { + case 1: + WriteCrtc (VgaClassDev, CRTC_CURSOR_START, 0x06); + WriteCrtc (VgaClassDev, CRTC_CURSOR_END, 0x07); + break; + + default: + WriteCrtc (VgaClassDev, CRTC_CURSOR_START, 0x0e); + WriteCrtc (VgaClassDev, CRTC_CURSOR_END, 0x0f); + break; + } + } else { + WriteCrtc (VgaClassDev, CRTC_CURSOR_START, 0x20); + } + + This->Mode->CursorVisible = Visible; + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +VgaClassQueryMode ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN UINTN ModeNumber, + OUT UINTN *Columns, + OUT UINTN *Rows + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + This - GC_TODO: add argument description + ModeNumber - GC_TODO: add argument description + Columns - GC_TODO: add argument description + Rows - GC_TODO: add argument description + +Returns: + + EFI_UNSUPPORTED - GC_TODO: Add description for return value + EFI_UNSUPPORTED - GC_TODO: Add description for return value + EFI_SUCCESS - GC_TODO: Add description for return value + +--*/ +{ + VGA_CLASS_DEV *VgaClassDev; + + VgaClassDev = VGA_CLASS_DEV_FROM_THIS (This); + + if ((INT32) ModeNumber >= This->Mode->MaxMode) { + *Columns = 0; + *Rows = 0; + return EFI_UNSUPPORTED; + } + + switch (ModeNumber) { + case 0: + *Columns = 80; + *Rows = 25; + break; + + case 1: + *Columns = 80; + *Rows = 50; + break; + + default: + *Columns = 0; + *Rows = 0; + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +VgaClassSetMode ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN UINTN ModeNumber + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + This - GC_TODO: add argument description + ModeNumber - GC_TODO: add argument description + +Returns: + + EFI_UNSUPPORTED - GC_TODO: Add description for return value + +--*/ +{ + EFI_STATUS Status; + VGA_CLASS_DEV *VgaClassDev; + + VgaClassDev = VGA_CLASS_DEV_FROM_THIS (This); + + if ((INT32) ModeNumber >= This->Mode->MaxMode) { + return EFI_UNSUPPORTED; + } + + This->ClearScreen (This); + + This->Mode->Mode = (INT32) ModeNumber; + + Status = VgaClassDev->VgaMiniPort->SetMode (VgaClassDev->VgaMiniPort, ModeNumber); + + return Status; +} +// +// Private Worker Functions +// +STATIC +VOID +SetVideoCursorPosition ( + IN VGA_CLASS_DEV *VgaClassDev, + IN UINTN Column, + IN UINTN Row, + IN UINTN MaxColumn + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + VgaClassDev - GC_TODO: add argument description + Column - GC_TODO: add argument description + Row - GC_TODO: add argument description + MaxColumn - GC_TODO: add argument description + +Returns: + + GC_TODO: add return values + +--*/ +{ + Column = Column & 0xff; + Row = Row & 0xff; + MaxColumn = MaxColumn & 0xff; + WriteCrtc ( + VgaClassDev, + CRTC_CURSOR_LOCATION_HIGH, + (UINT8) ((Row * MaxColumn + Column) >> 8) + ); + WriteCrtc ( + VgaClassDev, + CRTC_CURSOR_LOCATION_LOW, + (UINT8) ((Row * MaxColumn + Column) & 0xff) + ); +} + +STATIC +VOID +WriteCrtc ( + IN VGA_CLASS_DEV *VgaClassDev, + IN UINT16 Address, + IN UINT8 Data + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + VgaClassDev - GC_TODO: add argument description + Address - GC_TODO: add argument description + Data - GC_TODO: add argument description + +Returns: + + GC_TODO: add return values + +--*/ +{ + VgaClassDev->PciIo->Io.Write ( + VgaClassDev->PciIo, + EfiPciIoWidthUint8, + VgaClassDev->VgaMiniPort->CrtcAddressRegisterBar, + VgaClassDev->VgaMiniPort->CrtcAddressRegisterOffset, + 1, + &Address + ); + + VgaClassDev->PciIo->Io.Write ( + VgaClassDev->PciIo, + EfiPciIoWidthUint8, + VgaClassDev->VgaMiniPort->CrtcDataRegisterBar, + VgaClassDev->VgaMiniPort->CrtcDataRegisterOffset, + 1, + &Data + ); +} + +STATIC +BOOLEAN +LibIsValidTextGraphics ( + IN CHAR16 Graphic, + OUT CHAR8 *PcAnsi, OPTIONAL + OUT CHAR8 *Ascii OPTIONAL + ) +/*++ + +Routine Description: + + Detects if a Unicode char is for Box Drawing text graphics. + +Arguments: + + Grphic - Unicode char to test. + + PcAnsi - Optional pointer to return PCANSI equivalent of Graphic. + + Asci - Optional pointer to return Ascii equivalent of Graphic. + +Returns: + + TRUE if Gpaphic is a supported Unicode Box Drawing character. + +--*/ +// GC_TODO: Graphic - add argument and description to function comment +{ + UNICODE_TO_CHAR *Table; + + if ((((Graphic & 0xff00) != 0x2500) && ((Graphic & 0xff00) != 0x2100))) { + // + // Unicode drawing code charts are all in the 0x25xx range, + // arrows are 0x21xx + // + return FALSE; + } + + for (Table = UnicodeToPcAnsiOrAscii; Table->Unicode != 0x0000; Table++) { + if (Graphic == Table->Unicode) { + if (PcAnsi) { + *PcAnsi = Table->PcAnsi; + } + + if (Ascii) { + *Ascii = Table->Ascii; + } + + return TRUE; + } + } + + return FALSE; +} + +STATIC +BOOLEAN +IsValidAscii ( + IN CHAR16 Ascii + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + Ascii - GC_TODO: add argument description + +Returns: + + GC_TODO: add return values + +--*/ +{ + if ((Ascii >= 0x20) && (Ascii <= 0x7f)) { + return TRUE; + } + + return FALSE; +} + +STATIC +BOOLEAN +IsValidEfiCntlChar ( + IN CHAR16 c + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + c - GC_TODO: add argument description + +Returns: + + GC_TODO: add return values + +--*/ +{ + if (c == CHAR_NULL || c == CHAR_BACKSPACE || c == CHAR_LINEFEED || c == CHAR_CARRIAGE_RETURN) { + return TRUE; + } + + return FALSE; +} +//*** AMI PORTING BEGIN ***// +#endif //if INT10_SIMPLE_TEXT_SUPPORT==1 +//*** AMI PORTING END *****//
\ No newline at end of file diff --git a/Core/EM/CSM/thunk/CsmVideo/VgaClass.h b/Core/EM/CSM/thunk/CsmVideo/VgaClass.h new file mode 100644 index 0000000..fd184de --- /dev/null +++ b/Core/EM/CSM/thunk/CsmVideo/VgaClass.h @@ -0,0 +1,418 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2013, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** + +// +// This file contains a 'Sample Driver' and is licensed as such +// under the terms of your license agreement with Intel or your +// vendor. This file may be modified by the user, subject to +// the additional terms of the license agreement +// +/*++ + +Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved +This software and associated documentation (if any) is furnished +under a license and may only be used or copied in accordance +with the terms of the license. Except as permitted by such +license, no part of this software or documentation may be +reproduced, stored in a retrieval system, or transmitted in any +form or by any means without the express written consent of +Intel Corporation. + + +Module Name: + + VgaClass.h + +Abstract: + + +Revision History +--*/ + +#ifndef _VGA_CLASS_H +#define _VGA_CLASS_H + +//*** AMI PORTING BEGIN ***// +#include "AmiMapping.h" +//#include "Tiano.h" +//#include "EfiDriverLib.h" +//*** AMI PORTING END *****// +#include "Pci22.h" +//*** AMI PORTING BEGIN ***// +//#include "EfiStatusCode.h" +//#include "EfiCompNameSupport.h" +//#include "ComponentName.h" +//*** AMI PORTING END *****// + +// +// Driver Consumed Protocol Prototypes +// +#include EFI_PROTOCOL_DEFINITION (DevicePath) +#include EFI_PROTOCOL_DEFINITION (PciIo) +//*** AMI PORTING BEGIN ***// +//#include EFI_PROTOCOL_DEFINITION (VgaMiniPort) +#include "VgaMiniPort.h" +//*** AMI PORTING END *****// +#include EFI_PROTOCOL_DEFINITION (SimpleTextIn) +//*** AMI PORTING BEGIN ***// +//#include EFI_GUID_DEFINITION (StatusCodeCallerId) +//#include EFI_GUID_DEFINITION (StatusCodeDataTypeId) +//*** AMI PORTING END *****// + +// +// Driver Produced Protocol Prototypes +// +#include EFI_PROTOCOL_DEFINITION (DriverBinding) +#include EFI_PROTOCOL_DEFINITION (SimpleTextOut) + +// +// VGA specific registers +// +#define CRTC_CURSOR_START 0xA +#define CRTC_CURSOR_END 0xB + +#define CRTC_CURSOR_LOCATION_HIGH 0xE +#define CRTC_CURSOR_LOCATION_LOW 0xF + +#define EFI_MAX_ATTRIBUTE 0x7f + +// +// VGA Class Device Structure +// +#define VGA_CLASS_DEV_SIGNATURE EFI_SIGNATURE_32 ('V', 'G', 'A', 'C') + +typedef struct { + UINTN Signature; + EFI_HANDLE Handle; + EFI_SIMPLE_TEXT_OUT_PROTOCOL SimpleTextOut; + EFI_SIMPLE_TEXT_OUTPUT_MODE SimpleTextOutputMode; + EFI_VGA_MINI_PORT_PROTOCOL *VgaMiniPort; + EFI_PCI_IO_PROTOCOL *PciIo; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; +} VGA_CLASS_DEV; + +#define VGA_CLASS_DEV_FROM_THIS(a) CR (a, VGA_CLASS_DEV, SimpleTextOut, VGA_CLASS_DEV_SIGNATURE) + +// +// Global Variables +// +extern EFI_DRIVER_BINDING_PROTOCOL gVgaClassDriverBinding; + +// +// Driver Binding Protocol functions +// +EFI_STATUS +EFIAPI +VgaClassDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + This - GC_TODO: add argument description + Controller - GC_TODO: add argument description + RemainingDevicePath - GC_TODO: add argument description + +Returns: + + GC_TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +VgaClassDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + This - GC_TODO: add argument description + Controller - GC_TODO: add argument description + RemainingDevicePath - GC_TODO: add argument description + +Returns: + + GC_TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +VgaClassDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + This - GC_TODO: add argument description + Controller - GC_TODO: add argument description + NumberOfChildren - GC_TODO: add argument description + ChildHandleBuffer - GC_TODO: add argument description + +Returns: + + GC_TODO: add return values + +--*/ +; + +// +// Simple Text Output Protocol functions +// +EFI_STATUS +EFIAPI +VgaClassReset ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + This - GC_TODO: add argument description + ExtendedVerification - GC_TODO: add argument description + +Returns: + + GC_TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +VgaClassOutputString ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN CHAR16 *WString + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + This - GC_TODO: add argument description + WString - GC_TODO: add argument description + +Returns: + + GC_TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +VgaClassTestString ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN CHAR16 *WString + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + This - GC_TODO: add argument description + WString - GC_TODO: add argument description + +Returns: + + GC_TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +VgaClassClearScreen ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + This - GC_TODO: add argument description + +Returns: + + GC_TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +VgaClassSetAttribute ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN UINTN Attribute + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + This - GC_TODO: add argument description + Attribute - GC_TODO: add argument description + +Returns: + + GC_TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +VgaClassSetCursorPosition ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN UINTN Column, + IN UINTN Row + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + This - GC_TODO: add argument description + Column - GC_TODO: add argument description + Row - GC_TODO: add argument description + +Returns: + + GC_TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +VgaClassEnableCursor ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN BOOLEAN Visible + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + This - GC_TODO: add argument description + Visible - GC_TODO: add argument description + +Returns: + + GC_TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +VgaClassQueryMode ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN UINTN ModeNumber, + OUT UINTN *Columns, + OUT UINTN *Rows + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + This - GC_TODO: add argument description + ModeNumber - GC_TODO: add argument description + Columns - GC_TODO: add argument description + Rows - GC_TODO: add argument description + +Returns: + + GC_TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +VgaClassSetMode ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN UINTN ModeNumber + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + This - GC_TODO: add argument description + ModeNumber - GC_TODO: add argument description + +Returns: + + GC_TODO: add return values + +--*/ +; + +#endif diff --git a/Core/EM/CSM/thunk/CsmVideo/VgaMiniPort.h b/Core/EM/CSM/thunk/CsmVideo/VgaMiniPort.h new file mode 100644 index 0000000..e21a894 --- /dev/null +++ b/Core/EM/CSM/thunk/CsmVideo/VgaMiniPort.h @@ -0,0 +1,78 @@ +// +// This file contains 'Framework Code' and is licensed as such +// under the terms of your license agreement with Intel or your +// vendor. This file may not be modified, except as allowed by +// additional terms of your license agreement. +// +/*++ + +Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved +This software and associated documentation (if any) is furnished +under a license and may only be used or copied in accordance +with the terms of the license. Except as permitted by such +license, no part of this software or documentation may be +reproduced, stored in a retrieval system, or transmitted in any +form or by any means without the express written consent of +Intel Corporation. + + +Module Name: + + VgaMiniPort.h + +Abstract: + + Vga Mini port binding for a VGA controller + +Revision History + +--*/ + +#ifndef _VGA_MINI_PORT_H +#define _VGA_MINI_PORT_H + +#define EFI_VGA_MINI_PORT_PROTOCOL_GUID \ + { \ + 0xc7735a2f, 0x88f5, 0x4882, 0xae, 0x63, 0xfa, 0xac, 0x8c, 0x8b, 0x86, 0xb3 \ + } + +EFI_FORWARD_DECLARATION (EFI_VGA_MINI_PORT_PROTOCOL); + +typedef +EFI_STATUS +(EFIAPI *EFI_VGA_MINI_PORT_SET_MODE) ( + IN EFI_VGA_MINI_PORT_PROTOCOL * This, + IN UINTN ModeNumber + ); + +/*++ + + Routine Description: + Sets the text display mode of a VGA controller + + Arguments: + This - Protocol instance pointer. + Mode - Mode number. 0 - 80x25 1-80x50 + + Returns: + EFI_SUCCESS - The mode was set + EFI_DEVICE_ERROR - The device is not functioning properly. + +--*/ +typedef struct _EFI_VGA_MINI_PORT_PROTOCOL { + EFI_VGA_MINI_PORT_SET_MODE SetMode; + + UINT64 VgaMemoryOffset; + UINT64 CrtcAddressRegisterOffset; + UINT64 CrtcDataRegisterOffset; + + UINT8 VgaMemoryBar; + UINT8 CrtcAddressRegisterBar; + UINT8 CrtcDataRegisterBar; + + UINT8 MaxMode; +} EFI_VGA_MINI_PORT_PROTOCOL; + +extern EFI_GUID gEfiVgaMiniPortProtocolGuid; + +#endif diff --git a/Core/EM/CSM/thunk/CsmVideo/pci22.h b/Core/EM/CSM/thunk/CsmVideo/pci22.h new file mode 100644 index 0000000..1c8ccd0 --- /dev/null +++ b/Core/EM/CSM/thunk/CsmVideo/pci22.h @@ -0,0 +1,621 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2013, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** + +/*++ + +Copyright (c) 2004 - 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + pci22.h + +Abstract: + Support for PCI 2.2 standard. + +Revision History + +--*/ + +#ifndef _PCI22_H +#define _PCI22_H + +#define PCI_MAX_SEGMENT 0 + +#define PCI_MAX_BUS 255 + +#define PCI_MAX_DEVICE 31 +#define PCI_MAX_FUNC 7 + +// +// Command +// +#define PCI_VGA_PALETTE_SNOOP_DISABLED 0x20 + +#pragma pack(push, 1) +typedef struct { + UINT16 VendorId; + UINT16 DeviceId; + UINT16 Command; + UINT16 Status; + UINT8 RevisionID; + UINT8 ClassCode[3]; + UINT8 CacheLineSize; + UINT8 LatencyTimer; + UINT8 HeaderType; + UINT8 BIST; +} PCI_DEVICE_INDEPENDENT_REGION; + +typedef struct { + UINT32 Bar[6]; + UINT32 CISPtr; + UINT16 SubsystemVendorID; + UINT16 SubsystemID; + UINT32 ExpansionRomBar; + UINT8 CapabilityPtr; + UINT8 Reserved1[3]; + UINT32 Reserved2; + UINT8 InterruptLine; + UINT8 InterruptPin; + UINT8 MinGnt; + UINT8 MaxLat; +} PCI_DEVICE_HEADER_TYPE_REGION; + +typedef struct { + PCI_DEVICE_INDEPENDENT_REGION Hdr; + PCI_DEVICE_HEADER_TYPE_REGION Device; +} PCI_TYPE00; + +typedef struct { + UINT32 Bar[2]; + UINT8 PrimaryBus; + UINT8 SecondaryBus; + UINT8 SubordinateBus; + UINT8 SecondaryLatencyTimer; + UINT8 IoBase; + UINT8 IoLimit; + UINT16 SecondaryStatus; + UINT16 MemoryBase; + UINT16 MemoryLimit; + UINT16 PrefetchableMemoryBase; + UINT16 PrefetchableMemoryLimit; + UINT32 PrefetchableBaseUpper32; + UINT32 PrefetchableLimitUpper32; + UINT16 IoBaseUpper16; + UINT16 IoLimitUpper16; + UINT8 CapabilityPtr; + UINT8 Reserved[3]; + UINT32 ExpansionRomBAR; + UINT8 InterruptLine; + UINT8 InterruptPin; + UINT16 BridgeControl; +} PCI_BRIDGE_CONTROL_REGISTER; + +typedef struct { + PCI_DEVICE_INDEPENDENT_REGION Hdr; + PCI_BRIDGE_CONTROL_REGISTER Bridge; +} PCI_TYPE01; + +typedef union { + PCI_TYPE00 Device; + PCI_TYPE01 Bridge; +} PCI_TYPE_GENERIC; + +typedef struct { + UINT32 CardBusSocketReg; // Cardus Socket/ExCA Base + // Address Register + // + UINT16 Reserved; + UINT16 SecondaryStatus; // Secondary Status + UINT8 PciBusNumber; // PCI Bus Number + UINT8 CardBusBusNumber; // CardBus Bus Number + UINT8 SubordinateBusNumber; // Subordinate Bus Number + UINT8 CardBusLatencyTimer; // CardBus Latency Timer + UINT32 MemoryBase0; // Memory Base Register 0 + UINT32 MemoryLimit0; // Memory Limit Register 0 + UINT32 MemoryBase1; + UINT32 MemoryLimit1; + UINT32 IoBase0; + UINT32 IoLimit0; // I/O Base Register 0 + UINT32 IoBase1; // I/O Limit Register 0 + UINT32 IoLimit1; + UINT8 InterruptLine; // Interrupt Line + UINT8 InterruptPin; // Interrupt Pin + UINT16 BridgeControl; // Bridge Control +} PCI_CARDBUS_CONTROL_REGISTER; + +// +// Definitions of PCI class bytes and manipulation macros. +// +#define PCI_CLASS_OLD 0x00 +#define PCI_CLASS_OLD_OTHER 0x00 +#define PCI_CLASS_OLD_VGA 0x01 + +#define PCI_CLASS_MASS_STORAGE 0x01 +#define PCI_CLASS_MASS_STORAGE_SCSI 0x00 +#define PCI_CLASS_MASS_STORAGE_IDE 0x01 // obsolete +#define PCI_CLASS_IDE 0x01 +#define PCI_CLASS_MASS_STORAGE_FLOPPY 0x02 +#define PCI_CLASS_MASS_STORAGE_IPI 0x03 +#define PCI_CLASS_MASS_STORAGE_RAID 0x04 +#define PCI_CLASS_MASS_STORAGE_OTHER 0x80 + +#define PCI_CLASS_NETWORK 0x02 +#define PCI_CLASS_NETWORK_ETHERNET 0x00 +#define PCI_CLASS_ETHERNET 0x00 // obsolete +#define PCI_CLASS_NETWORK_TOKENRING 0x01 +#define PCI_CLASS_NETWORK_FDDI 0x02 +#define PCI_CLASS_NETWORK_ATM 0x03 +#define PCI_CLASS_NETWORK_ISDN 0x04 +#define PCI_CLASS_NETWORK_OTHER 0x80 + +#define PCI_CLASS_DISPLAY 0x03 +#define PCI_CLASS_DISPLAY_CTRL 0x03 // obsolete +#define PCI_CLASS_DISPLAY_VGA 0x00 +#define PCI_CLASS_VGA 0x00 // obsolete +#define PCI_CLASS_DISPLAY_XGA 0x01 +#define PCI_CLASS_DISPLAY_3D 0x02 +#define PCI_CLASS_DISPLAY_OTHER 0x80 +#define PCI_CLASS_DISPLAY_GFX 0x80 +#define PCI_CLASS_GFX 0x80 // obsolete +#define PCI_CLASS_BRIDGE 0x06 +#define PCI_CLASS_BRIDGE_HOST 0x00 +#define PCI_CLASS_BRIDGE_ISA 0x01 +#define PCI_CLASS_ISA 0x01 // obsolete +#define PCI_CLASS_BRIDGE_EISA 0x02 +#define PCI_CLASS_BRIDGE_MCA 0x03 +#define PCI_CLASS_BRIDGE_P2P 0x04 +#define PCI_CLASS_BRIDGE_PCMCIA 0x05 +#define PCI_CLASS_BRIDGE_NUBUS 0x06 +#define PCI_CLASS_BRIDGE_CARDBUS 0x07 +#define PCI_CLASS_BRIDGE_RACEWAY 0x08 +#define PCI_CLASS_BRIDGE_ISA_PDECODE 0x80 +#define PCI_CLASS_ISA_POSITIVE_DECODE 0x80 // obsolete + +#define PCI_CLASS_SCC 0x07 // Simple communications controllers +#define PCI_SUBCLASS_SERIAL 0x00 +#define PCI_IF_GENERIC_XT 0x00 +#define PCI_IF_16450 0x01 +#define PCI_IF_16550 0x02 +#define PCI_IF_16650 0x03 +#define PCI_IF_16750 0x04 +#define PCI_IF_16850 0x05 +#define PCI_IF_16950 0x06 +#define PCI_SUBCLASS_PARALLEL 0x01 +#define PCI_IF_PARALLEL_PORT 0x00 +#define PCI_IF_BI_DIR_PARALLEL_PORT 0x01 +#define PCI_IF_ECP_PARALLEL_PORT 0x02 +#define PCI_IF_1284_CONTROLLER 0x03 +#define PCI_IF_1284_DEVICE 0xFE +#define PCI_SUBCLASS_MULTIPORT_SERIAL 0x02 +#define PCI_SUBCLASS_MODEM 0x03 +#define PCI_IF_GENERIC_MODEM 0x00 +#define PCI_IF_16450_MODEM 0x01 +#define PCI_IF_16550_MODEM 0x02 +#define PCI_IF_16650_MODEM 0x03 +#define PCI_IF_16750_MODEM 0x04 +#define PCI_SUBCLASS_OTHER 0x80 + +#define PCI_CLASS_SYSTEM_PERIPHERAL 0x08 +#define PCI_SUBCLASS_PIC 0x00 +#define PCI_IF_8259_PIC 0x00 +#define PCI_IF_ISA_PIC 0x01 +#define PCI_IF_EISA_PIC 0x02 +#define PCI_IF_APIC_CONTROLLER 0x10 // I/O APIC interrupt controller , 32 bye none-prefectable memory. +#define PCI_IF_APIC_CONTROLLER2 0x20 +#define PCI_SUBCLASS_TIMER 0x02 +#define PCI_IF_8254_TIMER 0x00 +#define PCI_IF_ISA_TIMER 0x01 +#define PCI_EISA_TIMER 0x02 +#define PCI_SUBCLASS_RTC 0x03 +#define PCI_IF_GENERIC_RTC 0x00 +#define PCI_IF_ISA_RTC 0x00 +#define PCI_SUBCLASS_PNP_CONTROLLER 0x04 // HotPlug Controller + +#define PCI_CLASS_INPUT_DEVICE 0x09 +#define PCI_SUBCLASS_KEYBOARD 0x00 +#define PCI_SUBCLASS_PEN 0x01 +#define PCI_SUBCLASS_MOUSE_CONTROLLER 0x02 +#define PCI_SUBCLASS_SCAN_CONTROLLER 0x03 +#define PCI_SUBCLASS_GAMEPORT 0x04 + +#define PCI_CLASS_DOCKING_STATION 0x0A + +#define PCI_CLASS_PROCESSOR 0x0B +#define PCI_SUBCLASS_PROC_386 0x00 +#define PCI_SUBCLASS_PROC_486 0x01 +#define PCI_SUBCLASS_PROC_PENTIUM 0x02 +#define PCI_SUBCLASS_PROC_ALPHA 0x10 +#define PCI_SUBCLASS_PROC_POWERPC 0x20 +#define PCI_SUBCLASS_PROC_MIPS 0x30 +#define PCI_SUBCLASS_PROC_CO_PORC 0x40 // Co-Processor + +#define PCI_CLASS_SERIAL 0x0C +#define PCI_CLASS_SERIAL_FIREWIRE 0x00 +#define PCI_CLASS_SERIAL_ACCESS_BUS 0x01 +#define PCI_CLASS_SERIAL_SSA 0x02 +#define PCI_CLASS_SERIAL_USB 0x03 +#define PCI_CLASS_SERIAL_FIBRECHANNEL 0x04 +#define PCI_CLASS_SERIAL_SMB 0x05 + +#define PCI_CLASS_WIRELESS 0x0D +#define PCI_SUBCLASS_IRDA 0x00 +#define PCI_SUBCLASS_IR 0x01 +#define PCI_SUBCLASS_RF 0x02 + +#define PCI_CLASS_INTELLIGENT_IO 0x0E + +#define PCI_CLASS_SATELLITE 0x0F +#define PCI_SUBCLASS_TV 0x01 +#define PCI_SUBCLASS_AUDIO 0x02 +#define PCI_SUBCLASS_VOICE 0x03 +#define PCI_SUBCLASS_DATA 0x04 + +#define PCI_SECURITY_CONTROLLER 0x10 // Encryption and decryption controller +#define PCI_SUBCLASS_NET_COMPUT 0x00 +#define PCI_SUBCLASS_ENTERTAINMENT 0x10 + +#define PCI_CLASS_DPIO 0x11 + +#define IS_CLASS1(_p, c) ((_p)->Hdr.ClassCode[2] == (c)) +#define IS_CLASS2(_p, c, s) (IS_CLASS1 (_p, c) && ((_p)->Hdr.ClassCode[1] == (s))) +#define IS_CLASS3(_p, c, s, p) (IS_CLASS2 (_p, c, s) && ((_p)->Hdr.ClassCode[0] == (p))) + +#define IS_PCI_DISPLAY(_p) IS_CLASS1 (_p, PCI_CLASS_DISPLAY) +#define IS_PCI_VGA(_p) IS_CLASS3 (_p, PCI_CLASS_DISPLAY, PCI_CLASS_DISPLAY_VGA, 0) +#define IS_PCI_8514(_p) IS_CLASS3 (_p, PCI_CLASS_DISPLAY, PCI_CLASS_DISPLAY_VGA, 1) +#define IS_PCI_GFX(_p) IS_CLASS3 (_p, PCI_CLASS_DISPLAY, PCI_CLASS_DISPLAY_GFX, 0) +#define IS_PCI_OLD(_p) IS_CLASS1 (_p, PCI_CLASS_OLD) +#define IS_PCI_OLD_VGA(_p) IS_CLASS2 (_p, PCI_CLASS_OLD, PCI_CLASS_OLD_VGA) +#define IS_PCI_IDE(_p) IS_CLASS2 (_p, PCI_CLASS_MASS_STORAGE, PCI_CLASS_MASS_STORAGE_IDE) +#define IS_PCI_SCSI(_p) IS_CLASS3 (_p, PCI_CLASS_MASS_STORAGE, PCI_CLASS_MASS_STORAGE_SCSI, 0) +#define IS_PCI_RAID(_p) IS_CLASS3 (_p, PCI_CLASS_MASS_STORAGE, PCI_CLASS_MASS_STORAGE_RAID, 0) +#define IS_PCI_LPC(_p) IS_CLASS3 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_ISA, 0) +#define IS_PCI_P2P(_p) IS_CLASS3 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_P2P, 0) +#define IS_PCI_P2P_SUB(_p) IS_CLASS3 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_P2P, 1) +#define IS_PCI_USB(_p) IS_CLASS2 (_p, PCI_CLASS_SERIAL, PCI_CLASS_SERIAL_USB) + +#define HEADER_TYPE_DEVICE 0x00 +#define HEADER_TYPE_PCI_TO_PCI_BRIDGE 0x01 +#define HEADER_TYPE_CARDBUS_BRIDGE 0x02 + +#define HEADER_TYPE_MULTI_FUNCTION 0x80 +#define HEADER_LAYOUT_CODE 0x7f + +#define IS_PCI_BRIDGE(_p) (((_p)->Hdr.HeaderType & HEADER_LAYOUT_CODE) == (HEADER_TYPE_PCI_TO_PCI_BRIDGE)) +#define IS_CARDBUS_BRIDGE(_p) (((_p)->Hdr.HeaderType & HEADER_LAYOUT_CODE) == (HEADER_TYPE_CARDBUS_BRIDGE)) +#define IS_PCI_MULTI_FUNC(_p) ((_p)->Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION) + +#define PCI_DEVICE_ROMBAR 0x30 +#define PCI_BRIDGE_ROMBAR 0x38 + +#define PCI_MAX_BAR 0x0006 +#define PCI_MAX_CONFIG_OFFSET 0x0100 + +#define PCI_VENDOR_ID_OFFSET 0x00 +#define PCI_DEVICE_ID_OFFSET 0x02 +#define PCI_COMMAND_OFFSET 0x04 +#define PCI_PRIMARY_STATUS_OFFSET 0x06 +#define PCI_REVISION_ID_OFFSET 0x08 +#define PCI_CLASSCODE_OFFSET 0x09 +#define PCI_CACHELINE_SIZE_OFFSET 0x0C +#define PCI_LATENCY_TIMER_OFFSET 0x0D +#define PCI_HEADER_TYPE_OFFSET 0x0E +#define PCI_BIST_OFFSET 0x0F +#define PCI_BASE_ADDRESSREG_OFFSET 0x10 +#define PCI_CARDBUS_CIS_OFFSET 0x28 +#define PCI_SVID_OFFSET 0x2C // SubSystem Vendor id +#define PCI_SUBSYSTEM_VENDOR_ID_OFFSET 0x2C +#define PCI_SID_OFFSET 0x2E // SubSystem ID +#define PCI_SUBSYSTEM_ID_OFFSET 0x2E +#define PCI_EXPANSION_ROM_BASE 0x30 +#define PCI_CAPBILITY_POINTER_OFFSET 0x34 +#define PCI_INT_LINE_OFFSET 0x3C // Interrupt Line Register +#define PCI_INT_PIN_OFFSET 0x3D // Interrupt Pin Register +#define PCI_MAXGNT_OFFSET 0x3E // Max Grant Register +#define PCI_MAXLAT_OFFSET 0x3F // Max Latency Register + +#define PCI_BRIDGE_CONTROL_REGISTER_OFFSET 0x3E +#define PCI_BRIDGE_STATUS_REGISTER_OFFSET 0x1E + +#define PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET 0x18 +#define PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET 0x19 +#define PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET 0x1a + +typedef struct { + UINT32 Reg : 8; + UINT32 Func : 3; + UINT32 Dev : 5; + UINT32 Bus : 8; + UINT32 Reserved : 7; + UINT32 Enable : 1; +} PCI_CONFIG_ACCESS_CF8; + +#pragma pack() + +#define PCI_EXPANSION_ROM_HEADER_SIGNATURE 0xaa55 +#define PCI_DATA_STRUCTURE_SIGNATURE EFI_SIGNATURE_32 ('P', 'C', 'I', 'R') +#define PCI_CODE_TYPE_PCAT_IMAGE 0x00 +#define PCI_CODE_TYPE_EFI_IMAGE 0x03 +#define EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED 0x0001 + +#define EFI_PCI_COMMAND_IO_SPACE 0x0001 +#define EFI_PCI_COMMAND_MEMORY_SPACE 0x0002 +#define EFI_PCI_COMMAND_BUS_MASTER 0x0004 +#define EFI_PCI_COMMAND_SPECIAL_CYCLE 0x0008 +#define EFI_PCI_COMMAND_MEMORY_WRITE_AND_INVALIDATE 0x0010 +#define EFI_PCI_COMMAND_VGA_PALETTE_SNOOP 0x0020 +#define EFI_PCI_COMMAND_PARITY_ERROR_RESPOND 0x0040 +#define EFI_PCI_COMMAND_STEPPING_CONTROL 0x0080 +#define EFI_PCI_COMMAND_SERR 0x0100 +#define EFI_PCI_COMMAND_FAST_BACK_TO_BACK 0x0200 + +#define EFI_PCI_BRIDGE_CONTROL_PARITY_ERROR_RESPONSE 0x0001 +#define EFI_PCI_BRIDGE_CONTROL_SERR 0x0002 +#define EFI_PCI_BRIDGE_CONTROL_ISA 0x0004 +#define EFI_PCI_BRIDGE_CONTROL_VGA 0x0008 +#define EFI_PCI_BRIDGE_CONTROL_VGA_16 0x0010 +#define EFI_PCI_BRIDGE_CONTROL_MASTER_ABORT 0x0020 +#define EFI_PCI_BRIDGE_CONTROL_RESET_SECONDARY_BUS 0x0040 +#define EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK 0x0080 +#define EFI_PCI_BRIDGE_CONTROL_PRIMARY_DISCARD_TIMER 0x0100 +#define EFI_PCI_BRIDGE_CONTROL_SECONDARY_DISCARD_TIMER 0x0200 +#define EFI_PCI_BRIDGE_CONTROL_TIMER_STATUS 0x0400 +#define EFI_PCI_BRIDGE_CONTROL_DISCARD_TIMER_SERR 0x0800 + +// +// Following are the PCI-CARDBUS bridge control bit +// +#define EFI_PCI_BRIDGE_CONTROL_IREQINT_ENABLE 0x0080 +#define EFI_PCI_BRIDGE_CONTROL_RANGE0_MEMORY_TYPE 0x0100 +#define EFI_PCI_BRIDGE_CONTROL_RANGE1_MEMORY_TYPE 0x0200 +#define EFI_PCI_BRIDGE_CONTROL_WRITE_POSTING_ENABLE 0x0400 + +// +// Following are the PCI status control bit +// +#define EFI_PCI_STATUS_CAPABILITY 0x0010 +#define EFI_PCI_STATUS_66MZ_CAPABLE 0x0020 +#define EFI_PCI_FAST_BACK_TO_BACK_CAPABLE 0x0080 +#define EFI_PCI_MASTER_DATA_PARITY_ERROR 0x0100 + +#define EFI_PCI_CAPABILITY_PTR 0x34 +#define EFI_PCI_CARDBUS_BRIDGE_CAPABILITY_PTR 0x14 + +#pragma pack(1) +typedef struct { + UINT16 Signature; // 0xaa55 + UINT8 Reserved[0x16]; + UINT16 PcirOffset; +} PCI_EXPANSION_ROM_HEADER; + +typedef struct { + UINT16 Signature; // 0xaa55 + UINT8 Size512; + UINT8 InitEntryPoint[3]; + UINT8 Reserved[0x12]; + UINT16 PcirOffset; +} EFI_LEGACY_EXPANSION_ROM_HEADER; + +typedef struct { + UINT32 Signature; // "PCIR" + UINT16 VendorId; + UINT16 DeviceId; + UINT16 Reserved0; + UINT16 Length; + UINT8 Revision; + UINT8 ClassCode[3]; + UINT16 ImageLength; + UINT16 CodeRevision; + UINT8 CodeType; + UINT8 Indicator; + UINT16 Reserved1; +} PCI_DATA_STRUCTURE; + +// +// PCI Capability List IDs and records +// +#define EFI_PCI_CAPABILITY_ID_PMI 0x01 +#define EFI_PCI_CAPABILITY_ID_AGP 0x02 +#define EFI_PCI_CAPABILITY_ID_VPD 0x03 +#define EFI_PCI_CAPABILITY_ID_SLOTID 0x04 +#define EFI_PCI_CAPABILITY_ID_MSI 0x05 +#define EFI_PCI_CAPABILITY_ID_HOTPLUG 0x06 +#define EFI_PCI_CAPABILITY_ID_PCIX 0x07 + +typedef struct { + UINT8 CapabilityID; + UINT8 NextItemPtr; +} EFI_PCI_CAPABILITY_HDR; + +// +// Capability EFI_PCI_CAPABILITY_ID_PMI +// +typedef struct { + EFI_PCI_CAPABILITY_HDR Hdr; + UINT16 PMC; + UINT16 PMCSR; + UINT8 BridgeExtention; + UINT8 Data; +} EFI_PCI_CAPABILITY_PMI; + +// +// Capability EFI_PCI_CAPABILITY_ID_AGP +// +typedef struct { + EFI_PCI_CAPABILITY_HDR Hdr; + UINT8 Rev; + UINT8 Reserved; + UINT32 Status; + UINT32 Command; +} EFI_PCI_CAPABILITY_AGP; + +// +// Capability EFI_PCI_CAPABILITY_ID_VPD +// +typedef struct { + EFI_PCI_CAPABILITY_HDR Hdr; + UINT16 AddrReg; + UINT32 DataReg; +} EFI_PCI_CAPABILITY_VPD; + +// +// Capability EFI_PCI_CAPABILITY_ID_SLOTID +// +typedef struct { + EFI_PCI_CAPABILITY_HDR Hdr; + UINT8 ExpnsSlotReg; + UINT8 ChassisNo; +} EFI_PCI_CAPABILITY_SLOTID; + +// +// Capability EFI_PCI_CAPABILITY_ID_MSI +// +typedef struct { + EFI_PCI_CAPABILITY_HDR Hdr; + UINT16 MsgCtrlReg; + UINT32 MsgAddrReg; + UINT16 MsgDataReg; +} EFI_PCI_CAPABILITY_MSI32; + +typedef struct { + EFI_PCI_CAPABILITY_HDR Hdr; + UINT16 MsgCtrlReg; + UINT32 MsgAddrRegLsdw; + UINT32 MsgAddrRegMsdw; + UINT16 MsgDataReg; +} EFI_PCI_CAPABILITY_MSI64; + +// +// Capability EFI_PCI_CAPABILITY_ID_HOTPLUG +// +typedef struct { + EFI_PCI_CAPABILITY_HDR Hdr; + // + // not finished - fields need to go here + // +} EFI_PCI_CAPABILITY_HOTPLUG; + +// +// Capability EFI_PCI_CAPABILITY_ID_PCIX +// +typedef struct { + EFI_PCI_CAPABILITY_HDR Hdr; + UINT16 CommandReg; + UINT32 StatusReg; +} EFI_PCI_CAPABILITY_PCIX; + +typedef struct { + EFI_PCI_CAPABILITY_HDR Hdr; + UINT16 SecStatusReg; + UINT32 StatusReg; + UINT32 SplitTransCtrlRegUp; + UINT32 SplitTransCtrlRegDn; +} EFI_PCI_CAPABILITY_PCIX_BRDG; + +#define DEVICE_ID_NOCARE 0xFFFF + +#define PCI_ACPI_UNUSED 0 +#define PCI_BAR_NOCHANGE 0 +#define PCI_BAR_OLD_ALIGN 0xFFFFFFFFFFFFFFFF +#define PCI_BAR_EVEN_ALIGN 0xFFFFFFFFFFFFFFFE +#define PCI_BAR_SQUAD_ALIGN 0xFFFFFFFFFFFFFFFD +#define PCI_BAR_DQUAD_ALIGN 0xFFFFFFFFFFFFFFFC + +#define PCI_BAR_IDX0 0x00 +#define PCI_BAR_IDX1 0x01 +#define PCI_BAR_IDX2 0x02 +#define PCI_BAR_IDX3 0x03 +#define PCI_BAR_IDX4 0x04 +#define PCI_BAR_IDX5 0x05 +#define PCI_BAR_ALL 0xFF + +#pragma pack(pop) + +// +// NOTE: The following header files are included here for +// compatibility consideration. +// +//*** AMI PORTING BEGIN ***// +//Include content +//#include "pci23.h" +#define PCI_EXP_MAX_CONFIG_OFFSET 0x1000 +#define EFI_PCI_CAPABILITY_ID_PCIEXP 0x10 + +//#include "pci30.h" +#define PCI_CLASS_MASS_STORAGE_SATADPA 0x06 + +#pragma pack(push, 1) + +typedef struct { + UINT32 Signature; // "PCIR" + UINT16 VendorId; + UINT16 DeviceId; + UINT16 DeviceListOffset; + UINT16 Length; + UINT8 Revision; + UINT8 ClassCode[3]; + UINT16 ImageLength; + UINT16 CodeRevision; + UINT8 CodeType; + UINT8 Indicator; + UINT16 MaxRuntimeImageLength; + UINT16 ConfigUtilityCodeHeaderOffset; + UINT16 DMTFCLPEntryPointOffset; +} PCI_3_0_DATA_STRUCTURE; + +#pragma pack(pop) + +//#include "EfiPci.h" +#pragma pack(push, 1) + +typedef struct { + UINT8 Register; + UINT8 Function; + UINT8 Device; + UINT8 Bus; + UINT8 Reserved[4]; +} DEFIO_PCI_ADDR; + +#define EFI_ROOT_BRIDGE_LIST 'eprb' +#define EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE 0x0EF1 + +typedef struct { + UINT16 Signature; // 0xaa55 + UINT16 InitializationSize; + UINT32 EfiSignature; // 0x0EF1 + UINT16 EfiSubsystem; + UINT16 EfiMachineType; + UINT16 CompressionType; + UINT8 Reserved[8]; + UINT16 EfiImageHeaderOffset; + UINT16 PcirOffset; +} EFI_PCI_EXPANSION_ROM_HEADER; + +typedef union { + UINT8 *Raw; + PCI_EXPANSION_ROM_HEADER *Generic; + EFI_PCI_EXPANSION_ROM_HEADER *Efi; + EFI_LEGACY_EXPANSION_ROM_HEADER *PcAt; +} EFI_PCI_ROM_HEADER; + +#pragma pack(pop) +//*** AMI PORTING END *****// +#endif diff --git a/Core/EM/CSM/thunk/Snp16/snp16.cif b/Core/EM/CSM/thunk/Snp16/snp16.cif new file mode 100644 index 0000000..632b1c5 --- /dev/null +++ b/Core/EM/CSM/thunk/Snp16/snp16.cif @@ -0,0 +1,8 @@ +<component> + name = "SNP16" + category = ModulePart + LocalRoot = "core\em\csm\thunk\Snp16" + RefName = "BIOSSNP16" +[files] +[parts] +<endComponent> diff --git a/Core/EM/CSM/thunk/thunk.cif b/Core/EM/CSM/thunk/thunk.cif new file mode 100644 index 0000000..4e0af2e --- /dev/null +++ b/Core/EM/CSM/thunk/thunk.cif @@ -0,0 +1,11 @@ +<component> + name = "CSM Thunk" + category = ModulePart + LocalRoot = "core\em\csm\thunk" + RefName = "THUNK" +[parts] +"X86THUNK" +"BIOSBLKIO" +"BIOSSNP16" +"CsmVideo" +<endComponent> diff --git a/Core/EM/CSM/thunk/x86/thunk.c b/Core/EM/CSM/thunk/x86/thunk.c new file mode 100644 index 0000000..57233e4 --- /dev/null +++ b/Core/EM/CSM/thunk/x86/thunk.c @@ -0,0 +1,793 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (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/Thunk/x86/thunk.c 49 10/07/13 9:41a Olegi $ +// +// $Revision: 49 $ +// +// $Date: 10/07/13 9:41a $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Modules/CSM/Generic/Thunk/x86/thunk.c $ +// +// 49 10/07/13 9:41a Olegi +// Undone previous checkin related to EIP125856 as it is causing assert +// during boot. +// +// 48 8/30/13 4:25a Srikantakumarp +// [TAG] EIP125856 +// [Category] Bug Fix +// [Severity] Normal +// [Symptom] Assert came in SetKbcPresenceInMiscInfo() when FarCall86() +// function is called first time in POST. +// [RootCause] BiosLessThan1MB value is used in +// SetKbcPresenceInMiscInfo(); and this has been initialized only after +// the function 0 csm16 call. +// [Solution] Returned from SetKbcPresenceInMiscInfo() if +// BiosLessThan1MB value is not initialized. +// [Files] thunk.c +// +// 47 9/12/12 1:45a Srikantakumarp +// [TAG] EIP99561 +// [Category] Bug Fix +// [Severity] Normal +// [Symptom] KbcEmulation enabled in Int86 call but NO_KBC_PRESENT_BIT +// bit not set properly. +// [RootCause] Incase of INT86 , it directly calls the interrupt service +// routine and it might be that the NO_KBC_PRESENT_BIT is not set +// according to the KbcEmulation enabled or disabled. +// [Solution] The NO_KBC_PRESENT_BIT is set according to the +// KbcEmulation enabled or disabled before the call to thunk in Int86 +// function in thunk.c. +// [Files] thunk.c +// +// 46 3/02/12 3:24a Rameshr +// [TAG] EIP81041 +// [Category] Improvement +// [Description] Re-entrance support for Farcall86 and Int86 protocol +// function +// [Files] thunk.c +// +// 45 10/19/11 3:31p Olegi +// [TAG] EIP72642, 72645, 72810 +// [Category] Bug Fix +// [Severity] Important +// [Symptom] Adaptec x805 SAS Option ROM code hangs +// [RootCause] Adaptec ROM has a code that directly access KBC during +// INT handler. We did not have KBC emulation enabled for Int86 function. +// [Solution] Added enabling KBC emulation in Int86 function. +// [Files] thunk.c +// +// 44 9/29/11 11:00a Olegi +// [TAG] EIP70382 +// [Category] Improvement +// [Description] Clear keyboard status in BDA after FarCall86 execution. +// [Files] thunk.c +// +// 43 12/14/10 4:46p Olegi +// [TAG] EIP50111 +// [Category] Bug Fix +// [Severity] Important +// [Symptom] TPL asserts in some cases during LegacyBoot +// [RootCause] TPL.C asserts during LocateHandleBuffer call executed +// during LegacyBoot from FarCall86. +// [Solution] removed a call GetPs2SimpleTextInProtocolInterface +// execution during FarCall86. The existing handle of Ps2SimpleTextIn will +// be used. +// [Files] thunk.c +// +// 42 10/23/10 3:22p Olegi +// Undone the changes related to moving TPL raising/lowering outside of +// FarCall86. This made the IF to be active during thunk that caused +// various problems. +// +// 41 8/17/10 2:26p Olegi +// Reset PS/2 keyboard before legacy boot. EIP40711 +// +// 40 7/25/10 2:43p Olegi +// RaiseTPL/RestroreTPL are moved from FarCall86 to the ASM area. +// +// 39 7/19/10 4:44p Olegi +// +// 38 6/28/10 5:04p Olegi +// EIP26277: Added a callback notification on +// NonSmmEmul6064TrapProtocolGuid installation. +// +// 37 6/19/10 12:32p Olegi +// Temporary undone the resolution for EIP26277 until the final resolution +// is found. Current changes causes ASSERT due to LocateHandle is executed +// on TPL_LEVEL_HIGH. +// +// 36 2/22/10 9:46a Olegi +// Fixed the problem where some keys pressed on USB keyboard are lost +// during the transition to OpROM. EIP26277 +// +// 35 1/18/10 3:41a Rameshr +// NumLock,Capslock,Scroll Lock LED's synced properly between EFI and +// Legacy Mode. +// EIP 27917 +// +// 34 1/12/10 11:47a Olegi +// Copyright message updated. +// +// 33 9/23/09 11:13a Olegi +// Changed the global variable name according to the coding standard. +// +// 32 9/09/09 3:11p Davidd +// Fixed hanging problem when USB is disabled by the newly added "USB +// Support" setup question - EIP 25360 +// +// 31 2/05/09 12:28p Olegi +// +// 30 2/04/09 5:30p Olegi +// Several modifications in FarCall86: +// - PIC SetMode is moved after raising TPL to highest level (cli) +// - Set Pmode interrupt mask to FF before setting Rmode mask. That avoids +// the problem where IVT is not yet set in real mode (before Func#0) and +// some HW interrupt is pending. +// +// 29 11/13/08 10:00a Olegi +// Reverse thunk implementation started. +// +// 28 11/07/08 4:04p Rameshraju +// Removed unused code. +// +// 27 11/07/08 4:01p Rameshraju +// BugFix- Sometime system hangs on S4 resume. +// Fix Reason : If the Timer interrupt generates between CLI and Timer +// Interrupt mask code, Next STI instruction try to services the Timer +// interrupt.In this case before setting IVT system will hang +// EIP:17401 +// +// 26 6/12/08 8:14a Olegi +// Modified FarCall86 to execute USB keyboard change mode code for CSM16 +// function #5 (EIP14051). +// +// 25 8/27/07 12:44p Olegi +// +// 23 6/28/07 4:14p Olegi +// +// 22 6/25/07 12:27p Olegi +// +// 21 6/18/07 5:54p Olegi +// +// 20 5/29/07 6:17p Olegi +// Added UsbChangeEfiToLegacy call. +// +// 19 4/27/07 5:14p Olegi +// CSM.CHM file preparation. +// +// 18 8/24/06 6:56p Felixp +// +// 17 8/24/06 6:55p Felixp +// x64 support (warnings/errors fixed) +// +// 16 8/24/06 3:11p Felixp +// Preliminary x64 support (work in progress) +// +// 15 7/28/06 4:45p Olegi +// +// 14 5/19/06 11:22p Felixp +// Device Path code updated to use NEXT_NODE/NODE_LENGTH/SET_NODE_LENGTH +// macros to remove direct access to the Length field +// +// 13 3/13/06 2:35p Felixp +// +// 12 10/13/05 6:19p Olegi +// Added condition to a previous change. +// +// 11 10/11/05 4:20p Srinin +// PS2 KBD reset function is called after CM16 function 2, 3 and 5 are +// called. +// +// 10 8/25/05 10:28a Olegi +// Previous changes undone - instead the vector base for the master 8259 +// is changed from 0x68 to 0x58; with this there is no need to preserve +// and restore IVT. +// +// 8 3/04/05 1:47p Mandal +// +//********************************************************************** +//<AMI_FHDR_START> +// +// Name: Thunk.c +// +// Description: 32/64 bit to 16 bit code thunk implementation +// +//<AMI_FHDR_END> +//********************************************************************** + +#include <Protocol\DevicePath.h> +#include <Protocol\LegacyBios.h> +#include <Protocol\Legacy8259.h> +#include <Protocol\SimpleTextin.h> +#include <protocol\FirmwareVolume.h > +#include <Ffs.h> +#include "csm.h" +#include <AmiDxeLib.h> +#include "token.h" +#if defined(AMIUSB_SUPPORT) +#include <protocol\amiusbcontroller.h> +#endif +#include <Protocol\SimpleTextInEx.h> +#include <Protocol\AmiKeycode.h> + + +#pragma pack(1) +typedef struct { + UINT16 Offset; + UINT16 Segment; +} FAR_CALL_PTR_16; + +typedef struct { + UINT32 Stack; + UINT32 StackSize; +} STACK; + +typedef struct { + FAR_CALL_PTR_16 FarCall; + EFI_IA32_REGISTER_SET Regs; + STACK Stack; + BOOLEAN isFarCall; //if false, then INT86. + UINT8 BiosInt; +} THUNK_DATA; + +typedef struct _ACPI_PNPID { + UINT32 Signature :16; + UINT32 PnpID :16; +} ACPI_PNPID; +#pragma pack() + + +#if defined(AMIUSB_SUPPORT) +EFI_USB_PROTOCOL *gUsbProtocol = NULL; +#endif +AMI_EFIKEYCODE_PROTOCOL *pKeyCodeProtocol=NULL; + +EFI_SIMPLE_TEXT_INPUT_PROTOCOL *gPS2KBDInterface = NULL; +EFI_GUID gCsmThunkGuid = { + 0xA08276EC,0xA0FE,0x4e06,0x86,0x70,0x38,0x53,0x36,0xC7,0xD0,0x93 +}; + +EFI_LEGACY_8259_PROTOCOL *gLegacy8259; +extern BIOS_INFO *CoreBiosInfo; + +UINTN gThunkAsmAddr; +extern BOOLEAN gIsBootPrepared; +BOOLEAN gInsideThunk = FALSE; + +EFI_STATUS GetPs2SimpleTextInProtocolInterface( + BIOS_INFO *This, + EFI_SIMPLE_TEXT_INPUT_PROTOCOL **PS2KBDInterface +); + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: SetKbcPresenceInMiscInfo +// +// Description: Updates CSM16_NO_KBC_PRESENT_BIT of MiscInfoAddress accordingly +// by checking if the KbcEmulation is Enabled or Disabled. +// +// Input: +// +// Output: +// EFI_STATUS +// +// Referrals: +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID SetKbcPresenceInMiscInfo() +{ + EFI_TO_COMPATIBILITY16_INIT_TABLE *Csm16InitTable; + LEGACY16_TO_EFI_DATA_TABLE_STRUC *Csm16Data; + UINT8 KbcSupport,KbcCheck=0; + EFI_STATUS Status; + + // + // Retrieving the Data at MiscInfoAddress + // + Csm16InitTable = &CoreBiosInfo->Thunk->Csm16InitTable; + Csm16Data = (LEGACY16_TO_EFI_DATA_TABLE_STRUC*)(UINTN)Csm16InitTable->BiosLessThan1MB; + + KbcCheck = *(UINT8*)(UINTN)Csm16Data->MiscInfoAddress; + + // + // Setting/Resetting the CSM16_NO_KBC_PRESENT_BIT according to the KbcEmulation + // + KbcSupport = IoRead8(0x64); + if (KbcSupport != 0xff) { + KbcCheck &= ~(CSM16_NO_KBC_PRESENT_BIT); + } + else { + KbcCheck |= (CSM16_NO_KBC_PRESENT_BIT); + } + // + // Checking if the Data at MiscInfoAddress is already updated + // + if((*(UINT8*)(UINTN)Csm16Data->MiscInfoAddress) != KbcCheck){ + // + // Checking if F0000 region is writable + // + *(UINT8*)(UINTN)Csm16Data->MiscInfoAddress = KbcCheck; + + if((*(UINT8*)(UINTN)Csm16Data->MiscInfoAddress) == KbcCheck){ + return; + } + else{ + // + // Unlocking the region 0xE0000 - 0xFFFFF + // + Status = CoreBiosInfo->iRegion->UnLock (CoreBiosInfo->iRegion, + 0xE0000, + 0x20000, + NULL); + ASSERT_EFI_ERROR(Status); + + // + // Updating the Data at MiscInfoAddress + // + *(UINT8*)(UINTN)Csm16Data->MiscInfoAddress = KbcCheck; + + // + // Locking the region 0xE0000 - 0xFFFFF + // + CoreBiosInfo->iRegion->Lock (CoreBiosInfo->iRegion, + 0xE0000, + 0x20000, + NULL); + } + } +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: Int86 +// +// Description: Executes BIOS interrupt routine +// +// Input: +// LegacyBios protocol instance pointer +// BiosInt Interrupt number +// Regs CPU register values to pass to the interrupt handler +// +// Output: +// TRUE Interrupt was not executed +// FALSE INT completed. Caller will see Regs for status +// +// Referrals: EFI_IA32_REGISTER_SET +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +BOOLEAN Int86( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN UINT8 BiosInt, + IN OUT EFI_IA32_REGISTER_SET *Regs +) +{ + EFI_TPL OldTpl; + + THUNK_DATA *ThunkData = (THUNK_DATA*)(gThunkAsmAddr+6); + // + // To avoid reentrance in Int86 + // + if(gInsideThunk){ + return FALSE; + } + gInsideThunk = TRUE; + ThunkData->isFarCall = FALSE; + ThunkData->BiosInt = BiosInt; + ThunkData->Stack.StackSize = 0; //This is required + + + //Copy thunk registers. + ThunkData->Regs = *Regs; + +#if defined(AMIUSB_SUPPORT) +{ + EFI_STATUS Status; + + if (gUsbProtocol == NULL) { + Status = pBS->LocateProtocol(&gEfiUsbProtocolGuid, NULL, &gUsbProtocol); + if (EFI_ERROR(Status)) { + gUsbProtocol=NULL; // To be used later, after returning from INT + } + } + if (gUsbProtocol != NULL) { + gUsbProtocol->UsbChangeEfiToLegacy(1); + } +} +#endif + + OldTpl = pBS->RaiseTPL(TPL_HIGH_LEVEL); + gLegacy8259->SetMode(gLegacy8259,Efi8259LegacyMode,NULL,NULL); + + SetKbcPresenceInMiscInfo(); + + ((void(*)(UINTN))gThunkAsmAddr)(gThunkAsmAddr); + +#if defined(AMIUSB_SUPPORT) + if (gUsbProtocol) { + gUsbProtocol->UsbChangeEfiToLegacy(0); + } +#endif + + gLegacy8259->SetMode(gLegacy8259,Efi8259ProtectedMode,NULL,NULL); + pBS->RestoreTPL(OldTpl); + + //Restore thunk registers. + *Regs = ThunkData->Regs; + gInsideThunk = FALSE; + + return FALSE; // INT completed. Caller will see Regs for status. +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: FarCall86 +// +// Description: Executes 16 bit code starting from a given address +// +// Input: +// This LegacyBiosProtocol instance pointer +// Segment, Offset Starting address of the 16 bit routine +// Regs CPU register values to pass to the routine +// Stack Stack pointer with the possible data to be passed to the routine +// StackSize Size of the stack passed to the routine +// +// Output: +// TRUE Call was not executed +// FALSE Call completed. Caller will see Regs for status +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +BOOLEAN FarCall86( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN UINT16 Segment, + IN UINT16 Offset, + IN EFI_IA32_REGISTER_SET *Regs, + IN VOID *Stack, + IN UINTN StackSize +) +{ + EFI_TPL OldTpl; + UINT16 IrqMask, SaveIrqMask; + UINT16 ProtectedIrqMask, ProtectedSaveIrqMask; + THUNK_DATA *ThunkData = (THUNK_DATA*)(gThunkAsmAddr+6); + UINT16 FuncNumber; + BOOLEAN IsCsm16Call = + Segment == CoreBiosInfo->Csm16EntrySeg && + CoreBiosInfo->Csm16EntryOfs == Offset; + BOOLEAN IsCsm16DispatchOpRom = IsCsm16Call && + Regs->X.AX == Compatibility16DispatchOprom; + + BOOLEAN IsCsm16LegacyBoot = IsCsm16Call && + Regs->X.AX == Compatibility16Boot; + + EFI_STATUS Status = EFI_SUCCESS; + EFI_KEY_TOGGLE_STATE KeyToggleState=0; + // + // To avoid reentrance in FarCall86 + // + if(gInsideThunk){ + return FALSE; + } + + gInsideThunk = TRUE; + + // + // Change USB operation mode indicator from EFI to Legacy + // +#if defined(AMIUSB_SUPPORT) + if (IsCsm16LegacyBoot == FALSE) { + if (gUsbProtocol == NULL) { + Status = pBS->LocateProtocol(&gEfiUsbProtocolGuid, NULL, &gUsbProtocol); + if (EFI_ERROR(Status)) { + gUsbProtocol=NULL; // To be used later, after FarCall execution + } + } + } + if (gUsbProtocol != NULL) { + gUsbProtocol->UsbChangeEfiToLegacy(1); + } +#endif + + ThunkData->isFarCall = TRUE; + + //Copy address for thunk. + ThunkData->FarCall.Segment = Segment; + ThunkData->FarCall.Offset = Offset; + + //Copy address for stack + if (Stack) + { + ThunkData->Stack.Stack = (UINT32)Stack; + ThunkData->Stack.StackSize = (UINT32)StackSize; + } else ThunkData->Stack.StackSize = 0; + + //Copy thunk registers. + ThunkData->Regs = *Regs; + + // Reset the PS/2 keyboard before legacy boot + if (IsCsm16LegacyBoot == TRUE) { + if (gPS2KBDInterface) gPS2KBDInterface->Reset(gPS2KBDInterface, FALSE); + } + + FuncNumber = Regs->X.AX; + + if (IsCsm16Call) { + if (FuncNumber != 05 && FuncNumber != 02 && FuncNumber != 03) { + gLegacy8259->GetMask(gLegacy8259, &SaveIrqMask, NULL, NULL, NULL); // Save current Mask + + IrqMask = -1; + gLegacy8259->SetMask(gLegacy8259, &IrqMask, NULL, NULL, NULL); // Set new Mask + } + } + + // + // Mask all HW interrupts for real mode for CSM16 function #0 (InitializeYourself). + // This is needed since IVT is not installed before executing function #0. + // + // TODO: Explore the possibility of IVT installation from CSM32; in this case the + // code that is updating and using ProtectedIrqMask can be removed. + // + if (IsCsm16Call && FuncNumber == 00 ) { + gLegacy8259->GetMask(gLegacy8259, NULL, NULL, &ProtectedSaveIrqMask, NULL); // Save current Mask + ProtectedIrqMask = -1; + gLegacy8259->SetMask(gLegacy8259, NULL , NULL, &ProtectedIrqMask, NULL); // Set new Mask + } + + OldTpl = pBS->RaiseTPL(TPL_HIGH_LEVEL); + // + // The following call will change the PIC settings to real mode; this includes + // unmasking all real mode interrupts. Note, that at this point HW interrupts + // must be disabled. This is done by the previous RaiseTPL call. + // + gLegacy8259->SetMode(gLegacy8259,Efi8259LegacyMode,NULL,NULL); + + ((void(*)(UINTN))gThunkAsmAddr)(gThunkAsmAddr); + +#if defined(AMIUSB_SUPPORT) + if (gUsbProtocol) { + gUsbProtocol->UsbChangeEfiToLegacy(0); + } +#endif + + if (IsCsm16Call && FuncNumber == 00 ) { + gLegacy8259->SetMask(gLegacy8259, NULL , NULL, &ProtectedSaveIrqMask, NULL); // Set new Mask + } + + gLegacy8259->SetMode(gLegacy8259,Efi8259ProtectedMode,NULL,NULL); + + //Restore thunk registers. + *Regs = ThunkData->Regs; + pBS->RestoreTPL(OldTpl); + + // + // Change USB operation mode indicator back to EFI + // + + if (!IsCsm16Call || + (IsCsm16Call && + (FuncNumber == 05 || FuncNumber == 02 || FuncNumber == 03))) { +// Reset PS2 Mouse + if (!gPS2KBDInterface) { + GetPs2SimpleTextInProtocolInterface((BIOS_INFO *)This, &gPS2KBDInterface); + } + + if (gPS2KBDInterface) gPS2KBDInterface->Reset(gPS2KBDInterface, FALSE); + + } + else gLegacy8259->SetMask(gLegacy8259, &SaveIrqMask, NULL, NULL, NULL); // Restore mask + + if(IsCsm16DispatchOpRom) { + if((pKeyCodeProtocol == NULL && IsCsm16LegacyBoot == FALSE)) { + pBS->HandleProtocol(pST->ConsoleInHandle, &gAmiEfiKeycodeProtocolGuid, (void*)&pKeyCodeProtocol); + } + if(pKeyCodeProtocol != NULL) { + UINT8 KeyState; + KeyState = *(UINT8*)(UINTN)0x417; + if(KeyState & 0x10) { + KeyToggleState |= SCROLL_LOCK_ACTIVE; + } + if(KeyState & 0x20) { + KeyToggleState |= NUM_LOCK_ACTIVE; + } + if(KeyState & 0x40) { + KeyToggleState |= CAPS_LOCK_ACTIVE; + } + KeyToggleState |= TOGGLE_STATE_VALID; + pKeyCodeProtocol->SetState((EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL*)pKeyCodeProtocol,&KeyToggleState); + } + } + + *(UINT8*)(UINTN)0x417 &= 0x70; // Clear key modifiers status in BDA + + gInsideThunk = FALSE; + + return FALSE; // CALL completed. Caller will see Regs for status. +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: LoadRealModeFile +// +// Description: Code that loads 16-bit thunk code at a particular address +// +// Input: +// 16-bit binary file GUID +// Address to load the binary to +// +// Output: +// Status of the load operation +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS LoadRealModeFile(EFI_GUID *Guid, VOID *Address) +{ + EFI_FIRMWARE_VOLUME_PROTOCOL *Fv; + UINT32 Authentication; + VOID *BufferAddr=0; + UINTN BufferSize=0; + EFI_STATUS Status; + UINTN NumHandles; + EFI_HANDLE *HandleBuffer; + UINTN i; + + Status = pBS->LocateHandleBuffer(ByProtocol,&gEfiFirmwareVolumeProtocolGuid,NULL,&NumHandles,&HandleBuffer); + if (EFI_ERROR(Status)) return Status; + + for (i = 0; i< NumHandles; ++i) + { + Status = pBS->HandleProtocol(HandleBuffer[i],&guidFV,&Fv); + if (EFI_ERROR(Status)) continue; + + Status = Fv->ReadSection(Fv, + Guid, + EFI_SECTION_RAW, + 0, + &BufferAddr, + &BufferSize, + &Authentication); + + if (Status == EFI_SUCCESS) + { + MemCpy( + Address, + (UINT8*)BufferAddr, + BufferSize + ); + pBS->FreePool(BufferAddr); + break; + } + } + + pBS->FreePool(HandleBuffer); + + return Status; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: InitializeThunk +// +// Description: 16-bit thunk initialization routine. It calls 16 bit code to +// do the address fixups within 16-bit code. +// +// Input: The instance of BIOS_INFO pointer +// +// Output: Status of the initialization completion +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS InitializeThunk( + BIOS_INFO* CoreBiosInfo +) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS Thunkaddr = (EFI_PHYSICAL_ADDRESS)CoreBiosInfo->Thunk; + UINT16 ThunkFixupsOffset; + + //Locate Legacy8259 Protocol + gLegacy8259 = CoreBiosInfo->i8259; + + //Copy ThunkAsm to memory. + Status = LoadRealModeFile(&gCsmThunkGuid, (VOID*)Thunkaddr); + if (EFI_ERROR(Status)) return Status; + + gThunkAsmAddr = (UINT32)Thunkaddr; + + //Call fixups + ThunkFixupsOffset = *(UINT16*)(gThunkAsmAddr+2); + ((void(*)(UINTN))(gThunkAsmAddr+ThunkFixupsOffset))(gThunkAsmAddr); + + return Status; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: GetPs2SimpleTextInProtocolInterface +// +// Description: This function returns the SimpleTextIn protocol interface +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS GetPs2SimpleTextInProtocolInterface( + BIOS_INFO *This, + EFI_SIMPLE_TEXT_INPUT_PROTOCOL **PS2KBDInterface +) +{ + EFI_STATUS Status; + UINTN i,cnt; + ACPI_HID_DEVICE_PATH *siodp; + ACPI_PNPID *pnpid; + EFI_HANDLE *hbuff = NULL; + EFI_DEVICE_PATH_PROTOCOL *dp; + BOOLEAN bIsConnected = FALSE; + + Status = pBS->LocateHandleBuffer(ByProtocol,&gEfiSimpleTextInProtocolGuid, NULL, &cnt, &hbuff); + + if (EFI_ERROR(Status)) return Status; + + for(i=0; i<cnt; i++){ + Status=pBS->HandleProtocol(hbuff[i],&gEfiDevicePathProtocolGuid,&dp); + if(EFI_ERROR(Status)) continue; + + siodp=DPGetLastNode(dp); + if(siodp->Header.Type!=ACPI_DEVICE_PATH + || siodp->Header.SubType!=ACPI_DP + || NODE_LENGTH(&siodp->Header) != ACPI_DEVICE_PATH_LENGTH) continue; + + pnpid=(ACPI_PNPID*)&siodp->HID; + if (pnpid->PnpID == 0x0303) { +// Status = pBS->OpenProtocol (hbuff[i], &gEfiSimpleTextInProtocolGuid, &PS2KBDInterface, This->hBios, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); + Status = pBS->HandleProtocol(hbuff[i],&gEfiSimpleTextInProtocolGuid, PS2KBDInterface); + break; + } + Status = EFI_NOT_FOUND; + } + pBS->FreePool(hbuff); + return Status; +} +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2010, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** diff --git a/Core/EM/CSM/thunk/x86/x86thunk.asm b/Core/EM/CSM/thunk/x86/x86thunk.asm new file mode 100644 index 0000000..9a5a781 --- /dev/null +++ b/Core/EM/CSM/thunk/x86/x86thunk.asm @@ -0,0 +1,828 @@ +;********************************************************************** +;********************************************************************** +;** ** +;** (C)Copyright 1985-2012, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;********************************************************************** +;********************************************************************** + +;********************************************************************** +; $Header: /Alaska/SOURCE/Modules/CSM/Generic/Thunk/x86/x86thunk.asm 37 10/07/13 9:01a Olegi $ +; +; $Revision: 37 $ +; +; $Date: 10/07/13 9:01a $ +;********************************************************************** +; Revision History +; ---------------- +; $Log: /Alaska/SOURCE/Modules/CSM/Generic/Thunk/x86/x86thunk.asm $ +; +; 37 10/07/13 9:01a Olegi +; EIP135289 +; Legacy2Efi changes - CR4 save/restore +; +; 36 12/14/12 6:19p Olegi +; [TAG] EIP109554 +; [Category] Improvement +; [Description] Aptio4: Update CSM thunk to use private GDT instead of +; GDT on entry point +; [Files] x86thunk.asm +; +; 35 7/23/12 12:59p Olegi +; [TAG] EIP95386 +; [Category] Improvement +; [Description] CR3 register save/restore +; +; 34 6/13/12 12:49p Olegi +; [TAG] EIP92524 +; [Category] Improvement +; [Description] IDT location is limited to 4GB in CSM thunk +; +; 33 12/05/11 5:53p Olegi +; [TAG] EIP77045 +; [Category] Improvement +; [Description] Changed the values to be loaded to the segment +; registers from static number (8) to a dynamic number that represents a +; valid descriptor. +; [Files] x86thunk.asm +; +; 32 12/01/10 9:37a Olegi +; FarCall86 is modified to return data in stack when expected. +; +; 31 11/15/10 6:21p Olegi +; [TAG] EIP48242 +; [Category] Bug Fix +; [Severity] Critical +; [Symptom] thunk problems for IA32 projects +; [RootCause] wrong paths in thunk code for IA32 projects +; [Solution] fixed the thunk code +; [Files] x86thunk.asm +; +; 30 9/15/10 1:40p Olegi +; Reverse thunk stack usage modified: stack for the PM operations will be +; allocated externally. +; +; 29 9/13/10 5:26p Vyacheslava +; Added variable PmStackPtr to use a new stack space. +; +; 28 9/08/10 6:16p Vyacheslava +; Bugfix in reverse thunk: there was wrong assumption about stack +; re-assignment. When caller (OptionROM) reassignes stack, reverse thunk +; was failing. +; +; 27 7/26/10 2:23p Vyacheslava +; +; 26 7/25/10 2:44p Olegi +; +; 25 7/25/10 1:07p Olegi +; Bugfixes in the reverse thunk implementation. +; +; 24 7/24/10 12:38p Olegi +; +; 23 7/23/10 4:09p Olegi +; Initial reverse thunk implementation. +; +; 22 7/19/10 4:44p Olegi +; +; 21 1/12/10 11:47a Olegi +; Copyright message updated. +; +; 20 11/12/08 5:02p Olegi +; +; 19 5/11/07 11:12a Markw +; Save ss and set it to a flat descriptor in 64-bit mode. +; +; 18 4/27/07 5:14p Olegi +; CSM.CHM file preparation. +; +; 17 9/15/06 12:02p Markw +; Disable PAE when thunking because windows expects PAE in CR4 to be +; disabled after calling INT19h to boot. +; +; 16 8/24/06 3:11p Felixp +; Preliminary x64 support (work in progress) +; +; 15 5/25/06 2:23p Olegi +; +; 14 3/03/06 11:09a Markw +; Removed some duplicate code. +; +; 13 10/14/05 10:16a Markw +; Removed previous changes. +; +; 11 8/02/05 4:24p Markw +; Removed some db66 from sgdt and sidt. It was instructing the CPU to do +; a 24-bit load. However, the CPU was loading 32-bit that was needed, so +; it worked even though the spec described the operation differently. +; +; 10 5/12/05 12:57p Markw +; Fixed lidt in portected mode. It was only loading 24 of 32 bits. +; +; 9 4/18/05 10:54a Markw +; Remove pushing/popping ebx (entry point). +; make segments equal segement instead of fixup. +; +; 8 3/04/05 1:48p Mandal +; +;********************************************************************** +;<AMI_FHDR_START> +; +; Name: x86Thunk.asm +; +; Description: x86 CPU thunk functions +; +;<AMI_FHDR_END> +;********************************************************************** + +.586P +.model small + +;STACK_SIZE equ 8192 +STACK_TOP equ (4096 * 3) + +FAR_CALL_PTR_16 struct + ptr_offset dw ? + seg_offset dw ? +FAR_CALL_PTR_16 ends + +REGISTERS struct + reg_eax dd ? + reg_ebx dd ? + reg_ecx dd ? + reg_edx dd ? + reg_esi dd ? + reg_edi dd ? + reg_eflags dd ? + reg_es dw ? + reg_cs dw ? + reg_ss dw ? + reg_ds dw ? + reg_fs dw ? + reg_gs dw ? + reg_ebp dd ? +REGISTERS ends + +STACK_PARAM struct + StackPtr dd ? + StackSize dd ? +STACK_PARAM ends + +THUNK_DATA struct + FarCallPtr16 FAR_CALL_PTR_16 <> + Regs REGISTERS <> + StackParm STACK_PARAM<> + isFarCall db 0 + BiosInt db 0 +THUNK_DATA ends + + +ASSUME ds:THUNK_SEG + +THUNK_SEG SEGMENT USE32 'CODE' + +THUNK proc + jmp over_data +; The following data must be here. Don't move. These are used by the Thunk C driver. + dw LOWWORD offset Fixups + dw LOWWORD offset ReverseThunk + ThunkData THUNK_DATA <> +over_data: + cli +;-------------------------------------------------------------------------------- +; The following code switches from protected mode (from x64 if EFIx64 is defined, +; otherwise from 32-bit protected mode) to 16-bit real mode. +;-------------------------------------------------------------------------------- +; Calculate entry point and load EBX/RBX with it. + + push ebx + + call @f +@@: + pop ebx + sub ebx, @b ; RBX/EBX - physical address of CSM16 entry point + + mov DWORD PTR [RtReturnResult+ebx], eax + + sidt fword ptr [IdtSave+ebx] ;Save IDT + sgdt fword ptr [GdtSave+ebx] ;Save GDT + lgdt fword ptr [GdtDescriptor+ebx] + + mov eax, cr3 ;;Save CR3, CR4 + mov [CR3Save+ebx], eax + mov eax, cr4 + mov [CR4Save+ebx], eax + + ;Save segement registers. + mov ax, ds + push eax ;64-bit doesn't support push ds, es, ss + mov ax, es + push eax + mov ax, ss + push eax + push fs + push gs + mov ax, cs ;This must be last for cs restore. + push eax + + mov eax, DATA_SEL ;make sure segments are approriate for 32-bit mode. + mov ds, ax ; Load SS with the known descriptor value + mov es, ax + mov ss, ax + mov fs, ax + mov gs, ax + + +ifdef EFIx64 +;---Jump from long mode to compatiblity mode--- + ;jmp far ptr [ComModeAdr] + db 0ffh,2dh + dd ComModeAdr - $ - 4 + +ComMode: +;---Go to protected mode--- + mov eax, cr0 + btr eax, 31 + mov cr0, eax ;Now in protected mode. + jmp $+2 + + mov ecx, 0c0000080h + rdmsr + btr eax, 8 + wrmsr + + mov eax, cr4 + btr eax, 5 + mov cr4, eax ;Turn off PAE bit. Windows expects when calling INT19h. +endif + + cmp BYTE PTR [IsReverseThunk+ebx], 1 + je no_stack_to_copy + + pushad + pushfd + +;--Save Data-- + mov [StackSave+ebx], esp ;Save 32 bit stack address of this module. + + ;---Copy Stack parameters of LegacyBiosFarCall--- + mov ecx, [ThunkData.StackParm.StackSize+ebx] + or ecx, ecx + jz no_stack_to_copy + + mov esi, [ThunkData.StackParm.StackPtr+ebx] + mov edi, ebx + add edi, STACK_TOP + sub edi, ecx + rep movsb +no_stack_to_copy: +;--Switch to real mode-- + lidt fword ptr [LegacyLdtDescriptor+ebx] + + mov ax, DATA_SEL_16 + mov ds, ax + mov es, ax + mov ss, ax + mov fs, ax + mov gs, ax + + ;jmp CODE_SEL_16:next + db 0eah + dd offset next + dw CODE_SEL_16 +next: + mov eax, cr0 + and al, 0feh + mov cr0, eax + + ;--ITP doesn't display disassebly correctly until jump to real mode. + + ;jmp CS_SEGMENT:RealModeAddr + db 0eah + dw LOWWORD offset RealMode +RealModeFixUp: + dw 0 +RealMode: + db 8ch, 0c8h ;mov ax, cs + db 8eh, 0d8h ;mov ds, ax + db 8eh, 0c0h ;mov es, ax + db 8eh, 0d0h ;mov ss, ax + db 8eh, 0e0h ;mov fs, ax + db 8eh, 0e8h ;mov gs, ax + +; sti +;---------------Real mode operations----------- + db 2eh, 80h, 3eh + dw LOWWORD offset IsReverseThunk + db 1 ;cmp cs:IsReverseThunk, 1 + + jnz @f + + db 2eh, 0c6h, 6 + dw LOWWORD offset IsReverseThunk + db 0 ;mov cs:IsReverseThunk, 0 + + ; Restore the registers from RtRegs + push cs + pop ss + + db 0bch ; mov sp, LOWWORD OFFSET RtRegs + dw LOWWORD OFFSET RtRegs + + pop gs + pop fs + pop es + pop ds + db 66h, 61h ; popad + + ; Restore stack pointer and its contents + + db 2eh, 8eh, 16h ;mov cs:RtStackSave+4, ss + dw LOWWORD offset RtStackSave+4 + + db 66h, 2eh, 8bh, 26h ;mov sp, cs:RtStackSave + dw LOWWORD offset RtStackSave + + ; Restore flags + db 66h, 2eh, 0ffh, 36h ; push DWORD PTR cs:RtSavedFlags + dw LOWWORD OFFSET RtSavedFlags + db 66h, 9dh ; popfd + + db 83h, 0c4h, 4 ; add sp, 4: prepare stack for a push + + db 66h, 2eh, 0ffh, 36h ; push dword ptr cs:RtRetAddressSave + dw LOWWORD offset RtRetAddressSave + + db 66h, 2eh, 0a1h ;mov eax, RtReturnResult + dw LOWWORD offset RtReturnResult + + db 0cbh ;retf ; reverse thunk call returns control + +@@: + db 66h + mov esp, STACK_TOP ;This is the top stack for real mode. + + db 2bh, 26h ;sub sp, word ptr ThunkData.StackParm.StackSize + dw LOWWORD offset ThunkData.StackParm.StackSize + + ;---copy registers for FarCall and BIOS INT--- + + db 66h, 8bh, 1eh ;mov ebx, ThunkData.regs.reg_ebx + dw LOWWORD offset ThunkData.regs.reg_ebx + db 66h, 8bh, 0eh ;mov ecx, ThunkData.regs.reg_ecx + dw LOWWORD offset ThunkData.regs.reg_ecx + db 66h, 8bh, 16h ;mov edx, ThunkData.regs.reg_edx + dw LOWWORD offset ThunkData.regs.reg_edx + db 66h, 8bh, 36h ;mov esi, ThunkData.regs.reg_esi + dw LOWWORD offset ThunkData.regs.reg_esi + db 66h, 8bh, 3eh ;mov edi, ThunkData.regs.reg_edi + dw LOWWORD offset ThunkData.regs.reg_edi + db 66h, 8bh, 2eh ;mov ebp, ThunkData.regs.reg_ebp + dw LOWWORD offset ThunkData.regs.reg_ebp + + db 0a1h ;mov ax, ThunkData.regs.reg_es + dw LOWWORD offset ThunkData.regs.reg_es + + db 08eh, 0c0h ;mov es, ax + + db 66h, 0a1h ;mov eax, ThunkData.regs.reg_eax + dw LOWWORD offset ThunkData.regs.reg_eax + + ;Change ds last, since above operations depend on ds. + db 0ffh, 36h ;push ThunkData.regs.reg_ds + dw LOWWORD offset ThunkData.regs.reg_ds + pop ds + + ;Don't load the flags! They aren't needed, and if they aren't + ;initialized properly, the system hangs. + + ;--Call real mode function or interrupt-- + sti + + db 2eh, 80h, 3eh ;cmp cs:ThunkData.isFarCall, 0 + dw LOWWORD offset ThunkData.isFarCall + db 0 + + jnz FarCall + + db 66h + pushad + + db 2eh, 0a0h ;mov al, cs:ThunkData.BiosInt + dw LOWWORD offset ThunkData.BiosInt + + db 2eh, 0a2h ;mov cs:intxx, al ;Sets the intermediate value for intxx below. + dw LOWWORD offset intxx + + db 66h + mov eax, 1 + cpuid ;serializing instruction because of runtime code modification. + + db 66h + popad + + db 0cdh ;Execute int x +intxx label byte + db 0 + + jmp @f +FarCall: + ;call dword ptr cs:[ThunkData.FarCallPtr16] + db 02eh, 0ffh, 1eh ;Execute far call + dw LOWWORD offset ThunkData.FarCallPtr16 +@@: + + cli + ;--Copy registers back for FarCall and BIOS INT--- + + db 66h, 2eh, 0a3h ;mov cs:ThunkData.regs.reg_eax, eax + dw LOWWORD offset ThunkData.regs.reg_eax + + push ds + + db 2eh, 08fh, 6 ;pop cs:ThunkData.regs.reg_ds + dw LOWWORD offset ThunkData.regs.reg_ds + + db 8ch, 0c8h ;mov ax, cs + db 8eh, 0d8h ;mov ds, ax + + db 66h, 89h, 1eh ;mov ThunkData.regs.reg_ebx, ebx + dw LOWWORD offset ThunkData.regs.reg_ebx + + db 66h, 89h, 0eh ;mov ThunkData.regs.reg_ecx, ecx + dw LOWWORD offset ThunkData.regs.reg_ecx + + db 66h, 89h, 16h ;mov ThunkData.regs.reg_edx, edx + dw LOWWORD offset ThunkData.regs.reg_edx + + db 66h, 89h, 36h ;mov ThunkData.regs.reg_esi, esi + dw LOWWORD offset ThunkData.regs.reg_esi + + db 66h, 89h, 3eh ;mov ThunkData.regs.reg_edi, edi + dw LOWWORD offset ThunkData.regs.reg_edi + + db 66h, 89h, 2eh ;mov ThunkData.regs.reg_ebp, ebp + dw LOWWORD offset ThunkData.regs.reg_ebp + + db 08ch ,0c0h ;mov ax, es + + db 0a3h ;mov ThunkData.regs.reg_es, ax + dw LOWWORD offset ThunkData.regs.reg_es + + db 09ch ;pushf + db 08fh, 6 ;pop ThunkData.regs.reg_eflags + dw LOWWORD offset ThunkData.regs.reg_eflags + +;--------------End Real Mode operations--------- +RealToPm: + db 66h + xor ebx, ebx + db 8ch, 0cbh ;mov bx, cs + db 66h + shl ebx, 4 ;ebx = entry point + + ;--Switch to protected mode-- +; cli + + ;Reload GDT in case it was changed. + ;lgdt fword ptr cs:[GdtDescriptor] + db 66h,02eh,0fh,1,16h + dw LOWWORD offset GdtDescriptor + + mov eax, cr0 + or al, 1 ;Set PE bit + mov cr0, eax ;Turn on Protected Mode + + ;jmp CODE_SEL:P32MODE + db 66h, 0eah +P32ModeFixUp: + dd offset P32Mode + dw CODE_SEL + +P32Mode:: + mov ax, DATA_SEL + mov ds, ax + mov es, ax + mov ss, ax + mov fs, ax + mov gs, ax + cmp BYTE PTR [IsReverseThunk + ebx], 1 + je CreateReverseThunkESP + mov esp, [StackSave + ebx] ;Get original stack back. + ;---Copy Stack parameters of LegacyBiosFarCall---; + mov ecx, [ThunkData.StackParm.StackSize+ebx] + or ecx, ecx + jz @F + mov edi, [ThunkData.StackParm.StackPtr+ebx] + mov esi, ebx + add esi, STACK_TOP + sub esi, ecx + rep movsb +@@: + popfd + popad + jmp DonePreparingESP + +CreateReverseThunkESP: ; EBX = ThunkStart code segment << 4 + mov [ThunkStart + ebx], ebx + mov esp, [PmStackPtr + ebx] + +ifdef EFIx64 + sub esp, 20h ; allocate 20h bytes in stack (x64 calling convention) +endif + mov [esp], ebx +ifdef EFIx64 + mov DWORD PTR [esp+4], 0 +endif + sub esp, 4 + mov [esp], esi ; Function pointer (DWORD) +ifdef EFIx64 + mov DWORD PTR [esp], 0 + sub esp, 4 + mov [esp], esi ; Function pointer (QWORD) +endif + +DonePreparingESP: + xor eax, eax ; short/quick way to set EAX = 0 + lldt ax ; (source operand == 0) => LDTR is invalid + +ifdef EFIx64 + mov eax, cr4 + bts eax, 5 + mov cr4, eax ;Enable PAE + + mov ecx, 0c0000080h + rdmsr + bts eax, 8 + wrmsr + + mov eax, cr0 + bts eax, 31 + mov cr0, eax ;Now in compatibility mode. + jmp $+2 + + pushd CODE_SEL_64 + call @f ;push rip/eip +@@: + add dword ptr [esp], @f - $ + retf +@@: + + ;--In long mode. +endif + + lgdt fword ptr [GdtSave + ebx] ;Restore GDT + lidt fword ptr [IdtSave+ebx] ;Restore IDT + + ;restore original cs + ;rsp/esp = cs + call @f ;push rip/eip +@@: + add dword ptr [esp], @f - $ +ifdef EFIx64 + db 48h +endif + retf ;pop cs and eip. +@@: + + pop gs + pop fs + pop eax + mov ss, ax + pop eax + mov es, ax + pop eax + mov ds, ax + +ifdef EFIx64 + ;TODO: Double check Reverse Thunk code. + cmp BYTE PTR [IsReverseThunk+ebx], 1 + jne @f +; Reverse thunk - copy parameters to RCX, RDX, R8, R9 + db 48h, 8bh, 4ch, 24h, 28h ; mov rcx, [rsp + 28h] + db 48h, 8bh, 54h, 24h, 30h ; mov rdx, [rsp + 30h] + db 67h, 4ch, 8bh, 44h, 24h, 38h ; mov r8d, [rsp + 38h] + db 67h, 4ch, 8bh, 4ch, 24h, 40h ; mov r9d, [rsp + 40h] + + jmp RealToPm_Exit +@@: +endif + + mov eax, cs:[CR3Save + ebx] + mov cr3, eax + mov eax, cs:[CR4Save + ebx] + mov cr4, eax + pop ebx +RealToPm_Exit: + ret + +;----------------------------------------------------------- +ReverseThunk: + ; Save flags + db 66h, 9ch ; pushfd + db 66h, 2eh, 8fh, 6 ; pop DWORD PTR cs:RtSavedFlags + dw LOWWORD OFFSET RtSavedFlags + + cli + + db 66h, 2eh, 89h, 26h ;mov cs:RtStackSave, esp + dw LOWWORD offset RtStackSave + + db 2eh, 8ch, 16h ;mov cs:RtStackSave+4, ss + dw LOWWORD offset RtStackSave+4 + + ; Get the PM stack pointer from the stack + db 89h, 0e5h ; mov bp, sp + db 66h, 8bh, 46h, 4 ; mov eax, [bp+4] + db 66h, 2eh, 0a3h ; mov cs:PmStackPtr, eax + dw LOWWORD offset PmStackPtr + + ; Get return address and store it in cs:RtRetAddressSave + db 66h, 8bh, 46h, 0 ; mov eax, [bp+0] + db 66h, 2eh, 0a3h ; mov cs:RtRetAddressSave, eax + dw LOWWORD offset RtRetAddressSave + + ; Save the registers in RtRegs + push cs + pop ss + + db 0bch ; mov sp, LOWWORD OFFSET RtRegs+28h + dw LOWWORD OFFSET RtRegs+28h + + db 66h, 60h ; pushad + push ds + push es + push fs + push gs + + ; Restore SS:ESP + db 66h, 2eh, 8bh, 26h ;mov esp, cs:RtStackSave + dw LOWWORD offset RtStackSave + + db 2eh, 8eh, 16h ;mov ss, cs:RtStackSave+4 + dw LOWWORD offset RtStackSave+4 + + db 2eh, 0c6h, 06h ;mov cs:[IsReverseThunk], 1 + dw LOWWORD offset IsReverseThunk + db 1 + + db 0e9h + dw RealToPm - ($+2) ;jmp NEAR RealToPm + +;----------------------------------------------------------- + reg_gs dw ? + reg_fs dw ? + reg_es dw ? + reg_ds dw ? + reg_eflags dd ? + +Fixups: +ifdef EFIx64 + ;In 64 bit mode, but compiled under 32-bit mode. + push ebx ;(push rbx) cpuid changes ebx + mov edx, ecx + shr edx, 4 ;Get segment + +;--Fixups--- + ;add ComModeFixup, ecx + db 01, 0dh + dd ComModeFixup - $ - 4 + ;add P32ModeFixUp, ecx + db 01, 0dh + dd P32ModeFixUp - $ - 4 + ;add GdtDescriptorFixUp, ecx + db 01, 0dh + dd GdtDescriptorFixUp - $ - 4 +; add CODE_SEL_BASE_FIXUP, ecx ;must use add because upper 8 bit shouldn't change. Only 20 bit number. + db 01, 0dh + dd CODE_SEL_BASE_FIXUP - $ - 4 +; mov word ptr RealModeFixUp, dx + db 66h, 89h, 15h + dd RealModeFixUp - $ - 4 + mov eax, 1 + cpuid ;serialization for fixups + pop ebx ;pop rbx +else + push ebp + mov ebp, esp + + push ebx + push edx + + mov ebx, [ebp+8] ;Get base address of this module + mov edx, ebx + shr edx, 4 ;Get segment + +;--Fixups--- + add [P32ModeFixUp+ebx], ebx + add [GdtDescriptorFixUp+ebx], ebx + add [CODE_SEL_BASE_FIXUP+ebx], ebx ;must use add because upper 8 bit shouldn't change. Only 20 bit number. + mov word ptr [RealModeFixUp+ebx], dx + + mov eax, 1 + cpuid ;serialization for fixups + mov ebx, [ebp + 8] ;restore ebx + + pop edx + pop ebx + pop ebp +endif + ret + +align 16 +GDT_BASE: +NULL_SEL equ $-GDT_BASE ;NULL Selector 0 + dq 0 +DATA_SEL equ $-GDT_BASE + dq 00cf93000000ffffh +CODE_SEL equ $-GDT_BASE + dq 00cf9b000000ffffh +CODE_SEL_64 equ $-GDT_BASE + dq 00af9b000000ffffh +DATA_SEL_16 equ $-GDT_BASE + dq 008f93000000ffffh + +CODE_SEL_16 equ $-GDT_BASE + dw 0ffffh +CODE_SEL_BASE_FIXUP: ;Only 20 bits max + dw 0 + db 0 + + db 09ah + db 0 + db 0 + +GDT_SIZE equ $-GDT_BASE ;Size of Descriptor Table +GdtDescriptor: + dw GDT_SIZE - 1 ; GDT limit +GdtDescriptorFixUp: + dq OFFSET GDT_BASE ; GDT base + +ifdef EFIx64 +align 8 +ComModeFixup equ $ +ComModeAdr equ $ + dd offset ComMode + dw CODE_SEL +endif + + public StackSave +StackSave label dword + dd 0 +align 8 + public CR3Save +CR3Save label dword + dq 0 +align 8 + public CR4Save +CR4Save label dword + dq 0 +align 8 + public GdtSave +GdtSave label fword + dw 0 + dq 0 + +align 8 + public IdtSave +IdtSave label fword + dw 0 + dq 0 +align 8 + public LegacyLdtDescriptor +LegacyLdtDescriptor label fword + dw 3ffh + dq 0 + +;------Reverse thunk data------------ +IsReverseThunk db 0 +RtReturnResult dd 0 +RtSavedFlags dd 0 +RtStackSave db 6 dup (0) ; DW for SS, DD for ESP +PmStackPtr dd 0 +RtRetAddressSave dd 0 +ThunkStart dd 0 +RtRegs REGISTERS <> + +THUNK endp +THUNK_SEG ENDS +end + +;********************************************************************** +;********************************************************************** +;** ** +;** (C)Copyright 1985-2012, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;********************************************************************** +;********************************************************************** diff --git a/Core/EM/CSM/thunk/x86/x86thunk.cif b/Core/EM/CSM/thunk/x86/x86thunk.cif new file mode 100644 index 0000000..61600c3 --- /dev/null +++ b/Core/EM/CSM/thunk/x86/x86thunk.cif @@ -0,0 +1,10 @@ +<component> + name = "x86Thunk" + category = ModulePart + LocalRoot = "core\em\csm\thunk\x86" + RefName = "x86THUNK" +[files] +"\thunk.c" +"\x86thunk.asm" +"\x86thunk.mak" +<endComponent> diff --git a/Core/EM/CSM/thunk/x86/x86thunk.mak b/Core/EM/CSM/thunk/x86/x86thunk.mak new file mode 100644 index 0000000..724023f --- /dev/null +++ b/Core/EM/CSM/thunk/x86/x86thunk.mak @@ -0,0 +1,67 @@ +#********************************************************************** +#********************************************************************** +#** ** +#** (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/Thunk/x86/x86thunk.mak 7 1/12/10 11:47a Olegi $ +# +# $Revision: 7 $ +# +# $Date: 1/12/10 11:47a $ +#********************************************************************** + +#********************************************************************** +#<AMI_FHDR_START> +# +# Name: x86Thunk.mak +# +# Description: This file has a set of rules to create a binary that will +# be copied into lower memory that will give control to CSM16 +# code. +# +#<AMI_FHDR_END> +#********************************************************************** + +all: CREATE_THUNK_FFS + +CREATE_THUNK_FFS: $(BUILD_DIR)\x86Thunk.ffs + +$(BUILD_DIR)\x86Thunk.ffs : $(BUILD_DIR)\x86Thunk.bin + $(MAKE) /f Core\FFS.mak \ + BUILD_DIR=$(BUILD_DIR) SOURCE_DIR=$(CSM_THUNKASM_DIR) \ + GUID=A08276EC-A0FE-4e06-8670-385336C7D093 \ + TYPE=EFI_FV_FILETYPE_FREEFORM \ + BINFILE=$** FFSFILE=$@ COMPRESS=0 NAME=$(**B) + +$(BUILD_DIR)\x86Thunk.bin: $(X86THUNK_DIR)\x86Thunk.asm +!IF "$(x64_BUILD)"=="1" + $(ASM) /c /nologo /DEFIx64 /Fo$(BUILD_DIR)\x86thunk.obj $(X86THUNK_DIR)\x86Thunk.asm +!ELSE + $(ASM) /c /nologo /Fo$(BUILD_DIR)\x86thunk.obj $(X86THUNK_DIR)\x86Thunk.asm +!ENDIF + $(ASMLINK) /MAP $(BUILD_DIR)\x86thunk.obj, $(BUILD_DIR)\x86thunk.exe, $(BUILD_DIR)\x86thunk.map,,, + exe2bin $(BUILD_DIR)\x86thunk.exe $(BUILD_DIR)\x86Thunk.bin + +#********************************************************************** +#********************************************************************** +#** ** +#** (C)Copyright 1985-2010, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#********************************************************************** +#********************************************************************** |