summaryrefslogtreecommitdiff
path: root/Core/EM/CSM
diff options
context:
space:
mode:
authorraywu <raywu0301@gmail.com>2018-06-15 00:00:50 +0800
committerraywu <raywu0301@gmail.com>2018-06-15 00:00:50 +0800
commitb7c51c9cf4864df6aabb99a1ae843becd577237c (patch)
treeeebe9b0d0ca03062955223097e57da84dd618b9a /Core/EM/CSM
downloadzprj-b7c51c9cf4864df6aabb99a1ae843becd577237c.tar.xz
init. 1AQQW051HEADmaster
Diffstat (limited to 'Core/EM/CSM')
-rw-r--r--Core/EM/CSM/BiosData.h179
-rw-r--r--Core/EM/CSM/CSM.c2926
-rw-r--r--Core/EM/CSM/CSM.dxs62
-rw-r--r--Core/EM/CSM/CSM.h1089
-rw-r--r--Core/EM/CSM/CSM.mak174
-rw-r--r--Core/EM/CSM/CsmBsp.c1295
-rw-r--r--Core/EM/CSM/CsmHwInfo.c2063
-rw-r--r--Core/EM/CSM/CsmLib.c1617
-rw-r--r--Core/EM/CSM/CsmOpROM.c2726
-rw-r--r--Core/EM/CSM/CsmSimpleIn.c604
-rw-r--r--Core/EM/CSM/OemPir.dat227
-rw-r--r--Core/EM/CSM/PciInfo.asm83
-rw-r--r--Core/EM/CSM/PciInterrupts.c1136
-rw-r--r--Core/EM/CSM/csmcore.cif23
-rw-r--r--Core/EM/CSM/thunk/BlockIo/CsmBlkIoComponentName.c260
-rw-r--r--Core/EM/CSM/thunk/BlockIo/CsmBlockIo.c1076
-rw-r--r--Core/EM/CSM/thunk/BlockIo/CsmBlockIo.h277
-rw-r--r--Core/EM/CSM/thunk/BlockIo/CsmBlockIo.sdl25
-rw-r--r--Core/EM/CSM/thunk/BlockIo/CsmEdd.h407
-rw-r--r--Core/EM/CSM/thunk/BlockIo/CsmInt13.c1525
-rw-r--r--Core/EM/CSM/thunk/BlockIo/biosblkio.dxs46
-rw-r--r--Core/EM/CSM/thunk/BlockIo/biosblkio.mak63
-rw-r--r--Core/EM/CSM/thunk/BlockIo/int13thunk.cif15
-rw-r--r--Core/EM/CSM/thunk/CsmVideo/AmiMapping.c162
-rw-r--r--Core/EM/CSM/thunk/CsmVideo/AmiMapping.h153
-rw-r--r--Core/EM/CSM/thunk/CsmVideo/ComponentName.c324
-rw-r--r--Core/EM/CSM/thunk/CsmVideo/CsmVideo.cif20
-rw-r--r--Core/EM/CSM/thunk/CsmVideo/CsmVideo.dxs46
-rw-r--r--Core/EM/CSM/thunk/CsmVideo/CsmVideo.mak66
-rw-r--r--Core/EM/CSM/thunk/CsmVideo/CsmVideo.sdl58
-rw-r--r--Core/EM/CSM/thunk/CsmVideo/UefiBiosVideo.c3886
-rw-r--r--Core/EM/CSM/thunk/CsmVideo/UefiBiosVideo.h597
-rw-r--r--Core/EM/CSM/thunk/CsmVideo/VesaBiosExtensions.h463
-rw-r--r--Core/EM/CSM/thunk/CsmVideo/VgaClass.c1349
-rw-r--r--Core/EM/CSM/thunk/CsmVideo/VgaClass.h418
-rw-r--r--Core/EM/CSM/thunk/CsmVideo/VgaMiniPort.h78
-rw-r--r--Core/EM/CSM/thunk/CsmVideo/pci22.h621
-rw-r--r--Core/EM/CSM/thunk/Snp16/snp16.cif8
-rw-r--r--Core/EM/CSM/thunk/thunk.cif11
-rw-r--r--Core/EM/CSM/thunk/x86/thunk.c793
-rw-r--r--Core/EM/CSM/thunk/x86/x86thunk.asm828
-rw-r--r--Core/EM/CSM/thunk/x86/x86thunk.cif10
-rw-r--r--Core/EM/CSM/thunk/x86/x86thunk.mak67
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, &reg_); // 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 **
+#** **
+#**********************************************************************
+#**********************************************************************