| /** |
| * @file |
| * |
| * AMD Integrated Debug Debug_library Routines |
| * |
| * Contains AMD AGESA debug macros and library functions |
| * |
| * @xrefitem bom "File Content Label" "Release Content" |
| * @e project: AGESA |
| * @e sub-project: IDS |
| * @e \$Revision: 44323 $ @e \$Date: 2010-12-22 01:24:58 -0700 (Wed, 22 Dec 2010) $ |
| */ |
| /***************************************************************************** |
| * Copyright (c) 2011, Advanced Micro Devices, Inc. |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are met: |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * * Neither the name of Advanced Micro Devices, Inc. nor the names of |
| * its contributors may be used to endorse or promote products derived |
| * from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
| * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY |
| * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| * |
| ****************************************************************************** |
| */ |
| |
| /*---------------------------------------------------------------------------------------- |
| * M O D U L E S U S E D |
| *---------------------------------------------------------------------------------------- |
| */ |
| #include "AGESA.h" |
| #include "Ids.h" |
| #include "IdsLib.h" |
| #include "amdlib.h" |
| #include "AMD.h" |
| #include "heapManager.h" |
| #include "cpuRegisters.h" |
| #include "Filecode.h" |
| #define FILECODE PROC_IDS_DEBUG_IDSDEBUG_FILECODE |
| |
| extern BUILD_OPT_CFG UserOptions; |
| typedef struct _IDS_CONSOLE IDS_CONSOLE; |
| |
| /*--------------------------------------------------------------------------------------*/ |
| /** |
| * IDS back-end code for AGESA_TESTPOINT |
| * |
| * @param[in] TestPoint Progress indicator value, see @ref AGESA_TP |
| * @param[in,out] StdHeader The Pointer of AGESA Header |
| * |
| **/ |
| /*--------------------------------------------------------------------------------------*/ |
| VOID |
| IdsAgesaTestPoint ( |
| IN AGESA_TP TestPoint, |
| IN OUT AMD_CONFIG_PARAMS *StdHeader |
| ) |
| { |
| LibAmdIoWrite (AccessWidth8, IDS_DEBUG_PORT, &TestPoint, StdHeader); |
| IDS_PERF_TIMESTAMP (StdHeader, TestPoint); |
| if (TestPoint == EndAgesaTps) { |
| IDS_PERF_ANALYSE (StdHeader); |
| } |
| } |
| |
| #define DEBUG_PRINT_INIT 0x10BF0000 |
| #define DEBUG_PRINT_EXIT 0xE0BF0000 |
| #define DEBUG_PRINT_COMMAND 0xC0BF0000 |
| #define DEBUG_PRINT_BREAKPOINT 0xB0BF0000 |
| #define DEBUG_PRINT_EVENT 0x1EBF0000 |
| |
| #define IDS_HDTOUT_BPFLAG_FORMAT_STR 0 |
| #define IDS_HDTOUT_BPFLAG_STATUS_STR 1 |
| |
| #define HDTOUT_BP_ACTION_HALT 1 |
| #define HDTOUT_BP_ACTION_PRINTON 2 |
| #define HDTOUT_BP_ACTION_PRINTONE 3 |
| #define HDTOUT_BP_ACTION_PRINTOFF 4 |
| |
| typedef struct _BREAKPOINT_UNIT { |
| UINT8 AndFlag : 1; ///< Next string is ANDed to current string |
| UINT8 BpFlag : 1; ///< Format string or Status string |
| UINT8 Action : 4; ///< Halt, start HDTOUT, or stop HDT,... |
| UINT8 BpStrOffset; ///< Offset from BreakpointList to the breakpoint string |
| } BREAKPOINT_UNIT; |
| |
| typedef enum { |
| IDS_STATE_OFF = 0xF0, |
| IDS_STATE_ON |
| } IDS_STATE_TYPE; |
| |
| typedef enum { |
| NON_CONSOLE = 0xD0, |
| HDT_CONSOLE, |
| IDS_CONSOLE_END |
| } IDS_CONSOLE_TYPE; |
| |
| // IDS HdtOut Event Level |
| typedef enum { |
| EVENT_OFF = 0x30, ///< Default,no event triggered. |
| EVENT_WARNING, ///< Event warning. |
| EVENT_ERROR, ///< Event error. |
| EVENT_FAIL_BUFFER_ALLOCATION, ///< Reserved, fail buffer allocation |
| EVENT_END ///< Event end sentinel. |
| } CONSOLE_EVENT_TYPE; |
| |
| #define _INT_SIZE_OF(n) ((sizeof (n) + sizeof (UINTN) - 1) &~(sizeof (UINTN) - 1)) |
| |
| // |
| // Also support coding convention rules for var arg macros |
| // |
| typedef CHAR8 *VA_LIST; |
| #define VA_START(ap, v) (ap = (VA_LIST) & (v) + _INT_SIZE_OF (v)) |
| #define VA_ARG(ap, t) (*(t *) ((ap += _INT_SIZE_OF (t)) - _INT_SIZE_OF (t))) |
| #define VA_END(ap) (ap = (VA_LIST) 0) |
| |
| #define LEFT_JUSTIFY 0x01 |
| #define PREFIX_SIGN 0x02 |
| #define PREFIX_BLANK 0x04 |
| #define COMMA_TYPE 0x08 |
| #define LONG_TYPE 0x10 |
| #define PREFIX_ZERO 0x20 |
| |
| /** |
| * Create console context |
| * |
| * Do hardware settings related with specific console context |
| * |
| * @param[in,out] IdsConsole The Pointer of IDS console |
| * |
| **/ |
| typedef VOID F_CREATE_CONSOLE_CONTEXT ( |
| IN OUT IDS_CONSOLE *IdsConsole |
| ); |
| /// Reference to a method. |
| typedef F_CREATE_CONSOLE_CONTEXT *PF_CREATE_CONSOLE_CONTEXT; |
| |
| /** |
| * Initialize console context |
| * |
| * Initilize preference settings related with specific console context |
| * |
| * @param[in,out] IdsConsole The Pointer of IDS console |
| * |
| **/ |
| typedef VOID F_INIT_CONSOLE_CONTEXT ( |
| IN OUT IDS_CONSOLE *IdsConsole |
| ); |
| /// Reference to a method. |
| typedef F_INIT_CONSOLE_CONTEXT *PF_INIT_CONSOLE_CONTEXT; |
| |
| /** |
| * Update console context |
| * |
| * Update preference settings related with specific console context |
| * |
| * @param[in,out] IdsConsole The Pointer of IDS console |
| * |
| **/ |
| typedef VOID F_UPDATE_CONSOLE_CONTEXT ( |
| IN OUT IDS_CONSOLE *IdsConsole |
| ); |
| /// Reference to a method. |
| typedef F_UPDATE_CONSOLE_CONTEXT *PF_UPDATE_CONSOLE_CONTEXT; |
| |
| /** |
| * Save console context |
| * |
| * Save console context snapshot |
| * |
| * @param[in,out] IdsConsole The Pointer of IDS console |
| * |
| **/ |
| typedef VOID F_SAVE_CONSOLE_CONTEXT ( |
| IN OUT IDS_CONSOLE *IdsConsole |
| ); |
| /// Reference to a method. |
| typedef F_SAVE_CONSOLE_CONTEXT *PF_SAVE_CONSOLE_CONTEXT; |
| |
| /** |
| * Destroy console context |
| * |
| * Destroy console context snapshot |
| * |
| * @param[in,out] IdsConsole The Pointer of IDS console |
| * |
| **/ |
| typedef VOID F_DESTROY_CONSOLE_CONTEXT ( |
| IN OUT IDS_CONSOLE *IdsConsole |
| ); |
| /// Reference to a method. |
| typedef F_DESTROY_CONSOLE_CONTEXT *PF_DESTROY_CONSOLE_CONTEXT; |
| |
| /** |
| * Print function |
| * |
| * Print function related with specific console |
| * |
| * @param[in] PrintType Print Type |
| * @param[in] ConsoleBufferAddress The address of console buffer |
| * @param[in] ConsoleBufferSize The size of console buffer |
| * @param[in,out] IdsConsole The Pointer of IDS console |
| * |
| **/ |
| typedef VOID F_PRINT ( |
| IN UINT32 PrintType, |
| IN UINT32 ConsoleBufferAddress, |
| IN UINT32 ConsoleBufferSize, |
| IN OUT IDS_CONSOLE *IdsConsole |
| ); |
| /// Reference to a method. |
| typedef F_PRINT *PF_PRINT; |
| |
| /// IDS Console Operations |
| typedef struct _IDS_CONSOLE_OPERATIONS { |
| PF_CREATE_CONSOLE_CONTEXT CreateConsoleContext; |
| PF_INIT_CONSOLE_CONTEXT InitConsoleContext; |
| PF_UPDATE_CONSOLE_CONTEXT UpdateConsoleContext; |
| PF_DESTROY_CONSOLE_CONTEXT DestroyConsoleContext; |
| PF_PRINT Print; |
| } IDS_CONSOLE_OPERATIONS; |
| |
| /// IDS Console Header |
| typedef struct _IDS_CONSOLE_HEADER { |
| UINT32 Signature; ///< Signature information. |
| UINT32 Version; ///< Version. |
| UINT8 ConsoleType; ///< Console type |
| UINT8 Event; ///< Event type. |
| UINT8 PrintState; ///< On or Off |
| UINT8 OutBufferMode; ///< Off:stack mode, On: heap mode |
| UINT16 OutBufferSize; ///< Buffer size |
| UINT16 OutBufferIndex; ///< Buffer index |
| UINT32 NumBreakpointUnit; ///< default 0 no bp unit others number of bp unit |
| } IDS_CONSOLE_HEADER; |
| |
| /// IDS Console |
| struct _IDS_CONSOLE |
| { |
| IDS_CONSOLE_HEADER Header; /**< IDS console header - 5 dwords */ |
| UINT32 FuncListAddr; /**< 32 bit address to the list of functions that script can execute */ |
| UINT8 Reserved[56 - 24]; /**< ----------------- New fields must be added here. */ |
| CHAR8 BreakpointList[300]; /**< Breakpoint list */ |
| CHAR8 StatusStr[156]; /**< Shows current node, DCT, CS,... */ |
| CHAR8 OutBuffer[2]; /**< Console Out content. Its size will be determined by BufferSize. */ |
| }; |
| |
| /** |
| * Create hdt console context |
| * |
| * Do hardware settings for hdt console context |
| * |
| * @param[in,out] IdsConsole The Pointer of IDS console |
| * |
| **/ |
| STATIC VOID |
| CreateHdtConsoleContext ( |
| IN OUT IDS_CONSOLE *IdsConsole |
| ) |
| { |
| UINT64 SMsr; |
| UINT32 CR4reg; |
| |
| LibAmdMsrRead (0xC001100A, (UINT64*)&SMsr, NULL); |
| SMsr |= 1; |
| LibAmdMsrWrite (0xC001100A, (UINT64*)&SMsr, NULL); |
| |
| LibAmdWriteCpuReg (DR2_REG, 0x99CC); |
| LibAmdWriteCpuReg (DR7_REG, 0x02000420); |
| |
| LibAmdReadCpuReg (CR4_REG, &CR4reg); |
| LibAmdWriteCpuReg (CR4_REG, CR4reg | ((UINT32)1 << 3)); |
| } |
| |
| /** |
| * Initialize hdt console context |
| * |
| * Initilize preference settings for hdt console context |
| * |
| * @param[in,out] IdsConsole The Pointer of IDS console |
| * |
| **/ |
| STATIC VOID |
| InitHdtConsoleContext ( |
| IN OUT IDS_CONSOLE *IdsConsole |
| ) |
| { |
| IDS_FUNCLIST_EXTERN (); |
| |
| IdsConsole->FuncListAddr = (UINT32) IDS_FUNCLIST_ADDR; |
| IdsConsole->StatusStr[0] = 0; |
| |
| } |
| |
| /** |
| * Update hdt console context |
| * |
| * Update preference settings for hdt console context |
| * |
| * @param[in,out] IdsConsole The Pointer of IDS console |
| * |
| **/ |
| STATIC VOID |
| UpdateHdtConsoleContext ( |
| IN OUT IDS_CONSOLE *IdsConsole |
| ) |
| { |
| if (IdsConsole->Header.OutBufferMode == IDS_STATE_OFF) { |
| IdsConsole->Header.OutBufferSize = 0; |
| } |
| |
| } |
| |
| /** |
| * Destroy hdt console context |
| * |
| * Save hdt console context snapshot |
| * |
| * @param[in,out] IdsConsole The Pointer of IDS console |
| * |
| **/ |
| STATIC VOID |
| DestroyHdtConsoleContext ( |
| IN OUT IDS_CONSOLE *IdsConsole |
| ) |
| { |
| UINT64 SMsr; |
| |
| LibAmdMsrRead (0xC001100A, (UINT64 *)&SMsr, NULL); |
| SMsr &= ~BIT0; |
| LibAmdMsrWrite (0xC001100A, (UINT64 *)&SMsr, NULL); |
| |
| LibAmdWriteCpuReg (DR2_REG, 0); |
| LibAmdWriteCpuReg (DR3_REG, 0); |
| LibAmdWriteCpuReg (DR7_REG, 0); |
| } |
| |
| /** |
| * Hdt console print function |
| * |
| * Print function related with hdt console |
| * |
| * @param[in] PrintType Print Type |
| * @param[in] ConsoleBufferAddress The address of console buffer |
| * @param[in] ConsoleBufferSize The size of console buffer |
| * @param[in,out] IdsConsole The Pointer of IDS console |
| * |
| **/ |
| STATIC VOID |
| HdtConsolePrint ( |
| IN UINT32 PrintType, |
| IN UINT32 ConsoleBufferAddress, |
| IN UINT32 ConsoleBufferSize, |
| IN OUT IDS_CONSOLE *IdsConsole |
| ) |
| { |
| IdsOutPort (PrintType | 0x99CC, ConsoleBufferAddress, ConsoleBufferSize); |
| } |
| |
| /// Initial construction data for HDT console header. |
| CONST IDS_CONSOLE_HEADER ROMDATA HdtConsoleHeader = |
| { |
| 0xDB1099CC, |
| 0x0100, |
| IDS_STATE_ON, |
| EVENT_OFF, |
| IDS_STATE_ON, |
| IDS_STATE_ON, |
| 0x1000, |
| 0x0, |
| 0, |
| }; |
| |
| #define OPTION_HDT_CONSOLE_HEADER &HdtConsoleHeader |
| |
| /// Initial construction data for HDT console operations. |
| CONST IDS_CONSOLE_OPERATIONS ROMDATA HdtConsoleOperations = |
| { |
| CreateHdtConsoleContext, |
| InitHdtConsoleContext, |
| UpdateHdtConsoleContext, |
| DestroyHdtConsoleContext, |
| HdtConsolePrint |
| }; |
| |
| #define OPTION_HDT_CONSOLE_OPERATIONS &HdtConsoleOperations |
| |
| /** |
| * Parses flag and width information from theFormat string and returns the next index |
| * into the Format string that needs to be parsed. See file headed for details of Flag and Width. |
| * |
| * @param[in] Format Current location in the AvSPrint format string. |
| * @param[out] Flags Returns flags |
| * @param[out] Width Returns width of element |
| * @param[out] Marker Vararg list that may be partially consumed and returned. |
| * |
| * @retval Pointer indexed into the Format string for all the information parsed by this routine. |
| * |
| **/ |
| STATIC CHAR8 * |
| GetFlagsAndWidth ( |
| IN CHAR8 *Format, |
| OUT UINTN *Flags, |
| OUT UINTN *Width, |
| IN OUT VA_LIST *Marker |
| ) |
| { |
| UINTN Count; |
| BOOLEAN Done; |
| |
| *Flags = 0; |
| *Width = 0; |
| for (Done = FALSE; !Done; ) { |
| Format++; |
| |
| switch (*Format) { |
| |
| case '-': |
| *Flags |= LEFT_JUSTIFY; |
| break; |
| case '+': |
| *Flags |= PREFIX_SIGN; |
| break; |
| case ' ': |
| *Flags |= PREFIX_BLANK; |
| break; |
| case ',': |
| *Flags |= COMMA_TYPE; |
| break; |
| case 'L': |
| case 'l': |
| *Flags |= LONG_TYPE; |
| break; |
| |
| case '*': |
| *Width = VA_ARG (*Marker, UINTN); |
| break; |
| |
| case '0': |
| *Flags |= PREFIX_ZERO; |
| break; |
| |
| case '1': |
| case '2': |
| case '3': |
| case '4': |
| case '5': |
| case '6': |
| case '7': |
| case '8': |
| case '9': |
| Count = 0; |
| do { |
| Count = (Count * 10) + *Format - '0'; |
| Format++; |
| } while ((*Format >= '0') && (*Format <= '9')); |
| Format--; |
| *Width = Count; |
| break; |
| |
| default: |
| Done = TRUE; |
| } |
| } |
| return Format; |
| } |
| |
| CHAR8 STATIC HexStr[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; |
| /** |
| * |
| * @param[in] Buffer Location to place ascii hex string of Value. |
| * @param[in] Value - Hex value to convert to a string in Buffer. |
| * @param[in] Flags - Flags to use in printing Hex string, see file header for details. |
| * @param[in] Width - Width of hex value. |
| * |
| * @retval Number of characters printed. |
| **/ |
| |
| STATIC UINTN |
| ValueTomHexStr ( |
| IN OUT CHAR8 *Buffer, |
| IN UINT64 Value, |
| IN UINTN Flags, |
| IN UINTN Width |
| ) |
| { |
| CHAR8 TempBuffer[30]; |
| CHAR8 *TempStr; |
| CHAR8 Prefix; |
| CHAR8 *BufferPtr; |
| UINTN Count; |
| UINTN Index; |
| |
| TempStr = TempBuffer; |
| BufferPtr = Buffer; |
| // |
| // Count starts at one since we will null terminate. Each iteration of the |
| // loop picks off one nibble. Oh yea TempStr ends up backwards |
| // |
| Count = 0; |
| do { |
| *(TempStr++) = HexStr[Value & 0x0f]; |
| Value >>= 4; |
| Count++; |
| } while (Value != 0); |
| |
| if (Flags & PREFIX_ZERO) { |
| Prefix = '0'; |
| } else if (!(Flags & LEFT_JUSTIFY)) { |
| Prefix = ' '; |
| } else { |
| Prefix = 0x00; |
| } |
| for (Index = Count; Index < Width; Index++) { |
| *(TempStr++) = Prefix; |
| } |
| |
| // |
| // Reverse temp string into Buffer. |
| // |
| while (TempStr != TempBuffer) { |
| *(BufferPtr++) = *(--TempStr); |
| } |
| |
| *BufferPtr = 0; |
| return Index; |
| } |
| |
| /** |
| * Prints a Value as a decimal number in Buffer |
| * |
| * @param[in] Buffer Location to place ascii decimal number string of Value. |
| * @param[in] Value Decimal value to convert to a string in Buffer. |
| * @param[in] Flags Flags to use in printing decimal string, see file header for details. |
| * |
| * @retval Number of characters printed. |
| * |
| **/ |
| |
| STATIC UINTN |
| ValueToString ( |
| IN OUT CHAR8 *Buffer, |
| IN INT32 Value, |
| IN UINTN Flags |
| ) |
| { |
| CHAR8 TempBuffer[30]; |
| CHAR8 *TempStr; |
| CHAR8 *BufferPtr; |
| UINTN Count; |
| UINTN Remainder; |
| |
| TempStr = TempBuffer; |
| BufferPtr = Buffer; |
| Count = 0; |
| |
| if (Value < 0) { |
| *(BufferPtr++) = '-'; |
| Value = - Value; |
| Count++; |
| } |
| |
| do { |
| Remainder = Value % 10; |
| Value /= 10; |
| *(TempStr++) = (CHAR8)(Remainder + '0'); |
| Count++; |
| if ((Flags & COMMA_TYPE) == COMMA_TYPE) { |
| if (Count % 3 == 0) { |
| *(TempStr++) = ','; |
| } |
| } |
| } while (Value != 0); |
| |
| // |
| // Reverse temp string into Buffer. |
| // |
| while (TempStr != TempBuffer) { |
| *(BufferPtr++) = *(--TempStr); |
| } |
| |
| *BufferPtr = 0; |
| return Count; |
| } |
| |
| /** |
| * Check if String contain the substring |
| * |
| * @param[in] String Pointer of string. |
| * @param[in] Substr Pointer of sub string. |
| * |
| * @retval TRUE S2 is substring of S1 |
| * @retval FALSE S2 isn't substring of S1 |
| * |
| **/ |
| STATIC BOOLEAN |
| AmdIdsSubStr ( |
| IN CHAR8 *String, |
| IN CHAR8 *Substr |
| ) |
| { |
| UINT16 i; |
| UINT16 j; |
| |
| for (i = 0; String[i] != 0 ; i++) { |
| for (j = 0; (Substr[j] != 0) && (Substr[j] == String[i + j]); j++) { |
| } |
| if (Substr[j] == 0) { |
| return TRUE; |
| } |
| } |
| |
| return FALSE; |
| } |
| |
| /** |
| * IDS Backend Function for Memory timeout control |
| * |
| * This function is used to override Memory timeout control. |
| * |
| * @param[in,out] DataPtr The Pointer of UINT8. |
| * |
| **/ |
| VOID |
| IdsMemTimeOut ( |
| IN OUT VOID *DataPtr |
| ) |
| { |
| UINT32 DR2reg; |
| |
| LibAmdReadCpuReg (DR2_REG, &DR2reg); |
| if (DR2reg == 0x99CC) { |
| // Turn timeout off if HDTout is on |
| *((UINT8 *)DataPtr) = (UINT8)0; |
| } |
| } |
| |
| /** |
| * |
| * IDS Debug Function to check the sentinels are intact |
| * |
| * This function complete heap walk and check to be performed at any time. |
| * |
| * @param[in] StdHeader Config handle for library and services. |
| * |
| * @retval TRUE No error |
| * |
| **/ |
| BOOLEAN |
| AmdHeapIntactCheck ( |
| IN AMD_CONFIG_PARAMS *StdHeader |
| ) |
| { |
| UINT8 *HeapBufferPtr; |
| BUFFER_NODE *StartOfBufferPtr; |
| BUFFER_NODE *EndOfBufferPtr; |
| HEAP_MANAGER *HeapManagerPtr; |
| BUFFER_NODE *HeadNodePtr; |
| BUFFER_NODE *CurrentNodePtr; |
| UINT32 AmdHeapRamAddress; |
| UINT32 SentinelBefore; |
| UINT32 SentinelAfter; |
| |
| ASSERT (StdHeader != NULL); |
| |
| AmdHeapRamAddress = (UINT32)UserOptions.CfgHeapDramAddress; |
| |
| if (StdHeader->HeapStatus == HEAP_LOCAL_CACHE) { |
| HeapBufferPtr = (UINT8 *) HeapGetCurrentBase (StdHeader); |
| } else if (StdHeader->HeapStatus == HEAP_TEMP_MEM) { |
| HeapBufferPtr = (UINT8 *) AmdHeapRamAddress; |
| } else { |
| return TRUE; |
| } |
| |
| HeapManagerPtr = (HEAP_MANAGER *) HeapBufferPtr; |
| HeadNodePtr = (BUFFER_NODE *) (HeapBufferPtr + sizeof (HEAP_MANAGER)); |
| CurrentNodePtr = HeadNodePtr; |
| |
| if (HeapManagerPtr->AvailableSize != AMD_HEAP_SIZE_PER_CORE - sizeof (HEAP_MANAGER)) { |
| while (CurrentNodePtr != NULL) { |
| StartOfBufferPtr = (BUFFER_NODE *) ((UINT8 *) CurrentNodePtr + sizeof (BUFFER_NODE) + CurrentNodePtr->BufferSize + 2 * SIZE_OF_SENTINEL); |
| EndOfBufferPtr = (BUFFER_NODE *) ((UINT8 *) HeadNodePtr + AMD_HEAP_SIZE_PER_CORE); |
| if (CurrentNodePtr->NextNodePtr != NULL) { |
| ASSERT ((CurrentNodePtr->NextNodePtr >= StartOfBufferPtr) && (CurrentNodePtr->NextNodePtr < EndOfBufferPtr)); |
| SentinelBefore = *(UINT32 *) ((UINT8 *) CurrentNodePtr + sizeof (BUFFER_NODE)); |
| SentinelAfter = *(UINT32 *) ((UINT8 *) CurrentNodePtr + sizeof (BUFFER_NODE) + SIZE_OF_SENTINEL + CurrentNodePtr->BufferSize); |
| |
| ASSERT ((SentinelBefore == SENTINEL_BEFORE_VALUE) && (SentinelAfter == SENTINEL_AFTER_VALUE)); |
| } else { |
| ASSERT ((UINT8 *) StartOfBufferPtr == HeapBufferPtr + AMD_HEAP_SIZE_PER_CORE - HeapManagerPtr->AvailableSize); |
| SentinelBefore = *(UINT32 *) ((UINT8 *) CurrentNodePtr + sizeof (BUFFER_NODE)); |
| SentinelAfter = *(UINT32 *) ((UINT8 *) CurrentNodePtr + sizeof (BUFFER_NODE) + SIZE_OF_SENTINEL + CurrentNodePtr->BufferSize); |
| ASSERT ((SentinelBefore == SENTINEL_BEFORE_VALUE) && (SentinelAfter == SENTINEL_AFTER_VALUE)); |
| } |
| CurrentNodePtr = CurrentNodePtr->NextNodePtr; |
| } |
| } |
| return TRUE; |
| } |
| |
| /** |
| * Determine whether IDS console is enabled. |
| * |
| * @param[in,out] IdsConsole The Pointer of Ids console data |
| * |
| * @retval TRUE Ids console is enabled. |
| * @retval FALSE Ids console is disabled. |
| * |
| **/ |
| BOOLEAN |
| STATIC |
| IsIdsConsoleEnabled ( |
| IN OUT UINTN *IdsConsole |
| ) |
| { |
| BOOLEAN Result; |
| UINT32 DR2reg; |
| |
| Result = FALSE; |
| |
| LibAmdReadCpuReg (DR2_REG, &DR2reg); |
| if (DR2reg == 0x99CC) { |
| Result = TRUE; |
| } |
| |
| return Result; |
| } |
| |
| /** |
| * Get IDS console. |
| * |
| * @param[in,out] IdsConsolePtr The Pointer of Ids console data |
| * |
| **/ |
| STATIC VOID |
| GetIdsConsole ( |
| IN OUT UINTN *IdsConsolePtr |
| ) |
| { |
| UINT32 DR3Reg; |
| |
| LibAmdReadCpuReg (DR3_REG, &DR3Reg); |
| *IdsConsolePtr = (UINTN) DR3Reg; |
| } |
| |
| /** |
| * Get IDS console operations. |
| * |
| * @param[in,out] IdsConsoleOperations The Pointer of Ids console operations |
| * |
| **/ |
| STATIC VOID |
| GetIdsConsoleHeader ( |
| IN OUT UINTN *IdsConsoleHeader |
| ) |
| { |
| IDS_CONSOLE_TYPE IdsConsoleType; |
| |
| IdsConsoleType = (IDS_CONSOLE_TYPE) OPTION_IDS_CONSOLE; |
| |
| if (IdsConsoleType == HDT_CONSOLE) { |
| *IdsConsoleHeader = (UINTN) OPTION_HDT_CONSOLE_HEADER; |
| } else { |
| ASSERT (FALSE); |
| } |
| } |
| |
| /** |
| * Get IDS console operations. |
| * |
| * @param[in,out] IdsConsoleOperations The Pointer of Ids console operations |
| * |
| **/ |
| STATIC VOID |
| GetIdsConsoleOperations ( |
| IN OUT UINTN *IdsConsoleOperations |
| ) |
| { |
| IDS_CONSOLE_TYPE IdsConsoleType; |
| |
| IdsConsoleType = (IDS_CONSOLE_TYPE) OPTION_IDS_CONSOLE; |
| |
| if (IdsConsoleType == HDT_CONSOLE) { |
| *IdsConsoleOperations = (UINTN) OPTION_HDT_CONSOLE_OPERATIONS; |
| } else { |
| ASSERT (FALSE); |
| } |
| } |
| |
| /** |
| * Create IDS console. |
| * |
| * @param[in,out] IdsConsole The Pointer of Ids console data |
| * @param[in,out] StdHeader The Pointer of AGESA Header |
| **/ |
| STATIC VOID |
| NewIdsConsole ( |
| IN OUT IDS_CONSOLE *IdsConsole, |
| IN OUT AMD_CONFIG_PARAMS *StdHeader |
| ) |
| { |
| IDS_CONSOLE_HEADER *IdsConsoleHeader; |
| UINTN IdsConsoleHeaderPtr; |
| |
| GetIdsConsoleHeader (&IdsConsoleHeaderPtr); |
| IdsConsoleHeader = &(IdsConsole->Header); |
| |
| LibAmdMemCopy ((VOID *)IdsConsoleHeader, (VOID *) (IdsConsoleHeaderPtr), (UINT32) sizeof (IDS_CONSOLE_HEADER), StdHeader); |
| } |
| |
| /** |
| * Destroy IDS console. |
| * |
| * @param[in,out] IdsConsole The Pointer of Ids console data |
| * @param[in,out] StdHeader The Pointer of AGESA Header |
| **/ |
| STATIC VOID |
| DestroyIdsConsole ( |
| IN OUT IDS_CONSOLE *IdsConsole, |
| IN OUT AMD_CONFIG_PARAMS *StdHeader |
| ) |
| { |
| HeapDeallocateBuffer (IDS_HDT_OUT_BUFFER_HANDLE, StdHeader); |
| } |
| |
| /** |
| * Save IDS console Snapshot. |
| * |
| * @param[in,out] IdsConsole The Pointer of Ids console data |
| * @param[in,out] StdHeader The Pointer of AGESA Header |
| **/ |
| STATIC VOID |
| SaveIdsConsole ( |
| IN OUT IDS_CONSOLE *IdsConsole, |
| IN OUT IDS_CONSOLE_OPERATIONS *IdsConsoleOps, |
| IN OUT AMD_CONFIG_PARAMS *StdHeader |
| ) |
| { |
| ALLOCATE_HEAP_PARAMS AllocHeapParams; |
| |
| do { |
| AllocHeapParams.RequestedBufferSize = IdsConsole->Header.OutBufferSize + sizeof (IDS_CONSOLE) - 2; |
| AllocHeapParams.BufferHandle = IDS_HDT_OUT_BUFFER_HANDLE; |
| AllocHeapParams.Persist = HEAP_SYSTEM_MEM; |
| if (HeapAllocateBuffer (&AllocHeapParams, StdHeader) == AGESA_SUCCESS) { |
| break; |
| } else { |
| IdsConsole->Header.OutBufferSize -= 256; |
| IdsConsole->Header.Event = EVENT_FAIL_BUFFER_ALLOCATION; |
| IdsConsoleOps->Print (DEBUG_PRINT_EVENT, (UINT32)IdsConsole, 0, IdsConsole); |
| } |
| } while ((IdsConsole->Header.OutBufferSize & 0x8000) == 0); |
| |
| if ((IdsConsole->Header.OutBufferSize & 0x8000) == 0) { |
| LibAmdWriteCpuReg (DR3_REG, (UINT32)AllocHeapParams.BufferPtr); |
| LibAmdMemCopy (AllocHeapParams.BufferPtr, (VOID *) IdsConsole, (UINT32) sizeof (IDS_CONSOLE) - 2, StdHeader); |
| } |
| } |
| |
| /** |
| * |
| * Initial function for IDS console. |
| * |
| * Create IDS console context, let Ids console function to be ready. |
| * |
| * @param[in,out] StdHeader The Pointer of AGESA Header |
| * |
| **/ |
| VOID |
| AmdIdsConsoleInit ( |
| IN OUT AMD_CONFIG_PARAMS *StdHeader |
| ) |
| { |
| IDS_CONSOLE IdsConsole; |
| IDS_CONSOLE_OPERATIONS *IdsConsoleOps; |
| UINTN IdsConsolePtr; |
| UINTN IdsConsoleOpsPtr; |
| |
| if (IsIdsConsoleEnabled (&IdsConsolePtr)) { |
| GetIdsConsoleOperations (&IdsConsoleOpsPtr); |
| IdsConsoleOps = (IDS_CONSOLE_OPERATIONS *) IdsConsoleOpsPtr; |
| NewIdsConsole (&IdsConsole, StdHeader); |
| |
| IdsConsoleOps->CreateConsoleContext (&IdsConsole); |
| IdsConsoleOps->InitConsoleContext (&IdsConsole); |
| IdsConsoleOps->Print (DEBUG_PRINT_INIT, (UINT32)&IdsConsole, 0, &IdsConsole); |
| IdsConsoleOps->UpdateConsoleContext (&IdsConsole); |
| |
| SaveIdsConsole (&IdsConsole, IdsConsoleOps, StdHeader); |
| } |
| } |
| |
| /** |
| * Prints string to debug host like printf in C |
| * |
| * @param[in] Format of string |
| * @param[in] ... Variable parameter |
| * |
| **/ |
| VOID |
| AmdIdsConsolePrint ( |
| IN CHAR8 *Format, |
| IN ... |
| ) |
| { |
| IDS_CONSOLE *IdsConsole; |
| UINTN IdsConsolePtr; |
| IDS_CONSOLE_OPERATIONS *IdsConsoleOps; |
| UINTN IdsConsoleOpsPtr; |
| VA_LIST Marker; |
| CHAR8 LocalBuffer[256]; |
| CHAR8 *ConsoleBuffer; |
| CHAR8 Null_Str[] = " < null string > "; |
| CHAR8 *AsciiStr; |
| UINTN Index; |
| UINTN Flags; |
| UINTN Width; |
| UINTN ConsoleBufferSize; |
| UINT64 Value; |
| UINT16 *Array; |
| UINT32 ArrayLength; |
| UINT32 ArrayIndex; |
| BOOLEAN SaveStatus; |
| UINT32 LastIndex; |
| UINT32 i; |
| UINT32 j; |
| UINT32 NumBpUnit; |
| BREAKPOINT_UNIT *Pbpunit; |
| CHAR8 *Pbpstr; |
| CHAR8 *PCmpStr; |
| CHAR8 *EventLevelStr; |
| BOOLEAN LastBpmatched; |
| BOOLEAN Bpmatched; |
| IDS_STATE_TYPE PrintCtrl; |
| |
| //Init the default Value |
| IdsConsole = NULL; |
| IdsConsolePtr = 0; |
| ConsoleBuffer = LocalBuffer; |
| Index = 0; |
| LastIndex = 0; |
| ConsoleBufferSize = 256; |
| NumBpUnit = 0; |
| PrintCtrl = IDS_STATE_ON; |
| |
| if (IsIdsConsoleEnabled (&IdsConsolePtr)) { |
| GetIdsConsole (&IdsConsolePtr); |
| IdsConsole = (IDS_CONSOLE *) IdsConsolePtr; |
| GetIdsConsoleOperations (&IdsConsoleOpsPtr); |
| IdsConsoleOps = (IDS_CONSOLE_OPERATIONS *) IdsConsoleOpsPtr; |
| |
| if (IdsConsole->Header.OutBufferMode == IDS_STATE_ON) { |
| ConsoleBuffer = IdsConsole->OutBuffer; |
| Index = IdsConsole->Header.OutBufferIndex; |
| ConsoleBufferSize = (UINTN) (IdsConsole->Header.OutBufferSize); |
| NumBpUnit = IdsConsole->Header.NumBreakpointUnit; |
| PrintCtrl = IdsConsole->Header.PrintState; |
| } |
| |
| if ((PrintCtrl != 0) || (NumBpUnit > 0)) { |
| VA_START(Marker,Format); //init marker to 1st dynamic parameters. |
| |
| LastIndex = (UINT32) Index; |
| |
| if (*Format != '@') { |
| if (*Format == '!') { |
| SaveStatus = TRUE; |
| Format++; |
| } else { |
| SaveStatus = FALSE; |
| } |
| |
| for (; *Format != '\0'; Format++) { |
| if (*Format != '%') { |
| ConsoleBuffer[Index++] = *Format; |
| } else { |
| Format = GetFlagsAndWidth (Format, &Flags, &Width, &Marker); |
| switch (*Format) { |
| // Using %[EventType] style to catch predefined event. |
| case '[': |
| EventLevelStr = Format; |
| EventLevelStr++; |
| if ((*EventLevelStr > EVENT_OFF) && (*EventLevelStr < EVENT_END)) { |
| EventLevelStr++; |
| if (*EventLevelStr == ']') { |
| EventLevelStr--; |
| IdsConsole->Header.Event = (UINT8) (CONSOLE_EVENT_TYPE) (*EventLevelStr); |
| } |
| } |
| break; |
| case 'X': |
| Flags |= PREFIX_ZERO; |
| Width = sizeof (UINT64) * 2; |
| // |
| // break skipped on purpose |
| // |
| case 'x': |
| if ((Flags & LONG_TYPE) == LONG_TYPE) { |
| Value = VA_ARG (Marker, UINT64); |
| } else { |
| Value = VA_ARG (Marker, UINTN); |
| } |
| Index += ValueTomHexStr (&ConsoleBuffer[Index], Value, Flags, Width); |
| break; |
| |
| case 'd': |
| Value = (UINTN)VA_ARG (Marker, UINT32); |
| Index += ValueToString (&ConsoleBuffer[Index], (UINT32)Value, Flags); |
| break; |
| |
| case 's': |
| case 'S': |
| AsciiStr = (CHAR8 *)VA_ARG (Marker, CHAR8 *); |
| if (AsciiStr == NULL) { |
| AsciiStr = Null_Str; //" < null string > "; |
| } |
| while (*AsciiStr != '\0') { |
| ConsoleBuffer[Index++] = *AsciiStr++; |
| } |
| break; |
| |
| case 'c': |
| ConsoleBuffer[Index++] = (CHAR8)VA_ARG (Marker, UINTN); |
| break; |
| |
| case 'a': |
| Array = (UINT16 *) VA_ARG (Marker, VOID *); |
| ArrayLength = (UINT32) VA_ARG (Marker, UINT32); |
| for (ArrayIndex = 0; ArrayIndex < ArrayLength; ArrayIndex++) { |
| // Only support hex format of an array of UINT16 for now. |
| Width = 2; |
| Flags = PREFIX_ZERO; |
| ConsoleBuffer[Index++] = ' '; |
| Index += ValueTomHexStr (&ConsoleBuffer[Index], Array[ArrayIndex] & 0xFF, Flags, Width); |
| |
| // If buffer is full |
| if (Index > (ConsoleBufferSize - 8)) { |
| if (IdsConsole != NULL) { |
| if (LastIndex != 0) { |
| // Stream all out except current string |
| if (PrintCtrl != 0) { |
| IdsConsoleOps->Print (DEBUG_PRINT_COMMAND, (UINT32)ConsoleBuffer, LastIndex, IdsConsole); |
| } |
| Index = Index - LastIndex; |
| // Move current string too top |
| for (i = 0; i < Index; i++) { |
| ConsoleBuffer[i] = ConsoleBuffer[LastIndex + i]; |
| } |
| LastIndex = 0; |
| } else { |
| // Buffer size is too small |
| ASSERT (FALSE); |
| } |
| } else { |
| break; |
| } |
| } |
| } |
| break; |
| |
| case 'v': |
| ConsoleBuffer[Index++] = '%'; |
| ConsoleBuffer[Index++] = 'v'; |
| Format++; |
| ConsoleBuffer[Index++] = *Format; |
| if (*Format == 'h') { |
| Format++; |
| ConsoleBuffer[Index++] = *Format; |
| } |
| break; |
| |
| case '%': |
| ConsoleBuffer[Index++] = *Format; |
| break; |
| |
| default: |
| // |
| // if the type is unknown print it to the screen |
| // |
| ConsoleBuffer[Index++] = '%'; |
| ConsoleBuffer[Index++] = *Format; |
| } |
| } |
| |
| // If buffer is full |
| if (Index > (ConsoleBufferSize - 32)) { |
| if (IdsConsole != NULL) { |
| if (LastIndex != 0) { |
| // Stream all out except current string |
| if (PrintCtrl != IDS_STATE_OFF) { |
| IdsConsoleOps->Print (DEBUG_PRINT_COMMAND, (UINT32)ConsoleBuffer, LastIndex, IdsConsole); |
| } |
| Index = Index - LastIndex; |
| // Move current string too top |
| for (i = 0; i < Index; i++) { |
| ConsoleBuffer[i] = ConsoleBuffer[LastIndex + i]; |
| } |
| LastIndex = 0; |
| } else { |
| // Buffer size is too small |
| ASSERT (FALSE); |
| } |
| } else { |
| break; |
| } |
| } |
| } |
| |
| if (IdsConsole->Header.OutBufferMode == IDS_STATE_OFF) { |
| IdsConsoleOps->Print (DEBUG_PRINT_COMMAND, (UINT32)ConsoleBuffer, (UINT32) Index, IdsConsole); |
| Index = 0; |
| } |
| |
| if ((IdsConsole->Header.Event > EVENT_OFF) && (IdsConsole->Header.Event < EVENT_END) ) { |
| // if HdtOut Buffer is on, flush hdtout buffer contents out. |
| if (IdsConsole->Header.OutBufferMode == IDS_STATE_ON) { |
| IdsConsoleOps->Print (DEBUG_PRINT_COMMAND, (UINT32)ConsoleBuffer, (UINT32) Index, IdsConsole); |
| Index = 0; |
| } |
| |
| IdsConsoleOps->Print (DEBUG_PRINT_EVENT, (UINT32)IdsConsole, 0, IdsConsole); |
| IdsConsole->Header.Event = EVENT_OFF; |
| } |
| |
| // |
| // Check breakpoint |
| // |
| if (NumBpUnit) { |
| Pbpunit = (BREAKPOINT_UNIT *) IdsConsole->BreakpointList; |
| LastBpmatched = TRUE; |
| Bpmatched = TRUE; |
| for (i = 0; i < NumBpUnit; i++) { |
| Pbpstr = IdsConsole->BreakpointList + Pbpunit[i].BpStrOffset; |
| if (Pbpunit[i].BpFlag == IDS_HDTOUT_BPFLAG_FORMAT_STR) { |
| PCmpStr = &ConsoleBuffer[LastIndex]; |
| ConsoleBuffer[Index] = 0; |
| } else { |
| PCmpStr = IdsConsole->StatusStr; |
| } |
| |
| if (LastBpmatched) { |
| Bpmatched = AmdIdsSubStr (PCmpStr, Pbpstr); |
| if (Bpmatched) { |
| if (Pbpunit[i].AndFlag == 0) { |
| // This is the last of matching string of an AND block, apply action here |
| switch (Pbpunit[i].Action) { |
| case HDTOUT_BP_ACTION_HALT: |
| IdsConsoleOps->Print (DEBUG_PRINT_BREAKPOINT, (UINT32)(ConsoleBuffer + LastIndex), ( i << 16) | (UINT32) Index, IdsConsole); |
| break; |
| case HDTOUT_BP_ACTION_PRINTON: |
| PrintCtrl = IDS_STATE_ON; |
| IdsConsole->Header.PrintState = IDS_STATE_ON; |
| break; |
| case HDTOUT_BP_ACTION_PRINTOFF: |
| if (IdsConsole->Header.PrintState != IDS_STATE_OFF) { |
| IdsConsole->Header.PrintState = IDS_STATE_OFF; |
| IdsConsoleOps->Print (DEBUG_PRINT_COMMAND, (UINT32)ConsoleBuffer, (UINT32)Index, IdsConsole); |
| } |
| break; |
| default: |
| ASSERT (FALSE); |
| } |
| break; |
| } |
| } |
| } |
| if (Pbpunit[i].AndFlag == 1) { |
| LastBpmatched = Bpmatched; |
| } else { |
| LastBpmatched = TRUE; |
| } |
| } |
| } |
| |
| // |
| // Store status fields |
| // |
| if (SaveStatus) { |
| // Look for the start of the first word |
| for (; LastIndex < Index; LastIndex++) { |
| if ((ConsoleBuffer[LastIndex] > 32) && (ConsoleBuffer[LastIndex] < 127)) { |
| break; |
| } |
| } |
| if (LastIndex < Index) { |
| // Match the first word in StatusStr |
| SaveStatus = FALSE; |
| j = LastIndex; |
| for (i = 0; !SaveStatus && (IdsConsole->StatusStr[i] != 0); i++) { |
| ArrayLength = 1; |
| for (j = LastIndex; ConsoleBuffer[j] == IdsConsole->StatusStr[i]; j++) { |
| i++; |
| ArrayLength++; |
| if ((j == (Index - 1)) || (ConsoleBuffer[j] == ' ')) { |
| // Find the length of this entry |
| ArrayIndex = i; |
| for (; IdsConsole->StatusStr[i] != '\n'; i++) { |
| ArrayLength++; |
| } |
| |
| // Remove old entry if it does not fit |
| if (ArrayLength != ((UINT32) Index - LastIndex)) { |
| for (i++; IdsConsole->StatusStr[i] != 0; i++) { |
| IdsConsole->StatusStr[i - ArrayLength] = IdsConsole->StatusStr[i]; |
| } |
| j = LastIndex; |
| i = i - ArrayLength - 1; |
| // Mark the end of string |
| IdsConsole->StatusStr[i + ((UINT32) Index - LastIndex) + 1] = 0; |
| } else { |
| i = ArrayIndex - 2; |
| } |
| |
| // Word match, exit for saving |
| SaveStatus = TRUE; |
| break; |
| } |
| } |
| } |
| |
| // Copy string to StatusStr |
| for (; j < Index; j++, i++) { |
| IdsConsole->StatusStr[i] = ConsoleBuffer[j]; |
| } |
| if (!SaveStatus) { |
| // Mark the end of string if not done so |
| IdsConsole->StatusStr[i] = 0; |
| } |
| } |
| } |
| |
| } |
| } |
| |
| if (IdsConsole != NULL) { |
| if (IdsConsole->Header.PrintState == IDS_STATE_OFF) { |
| Index = 0; // Clear buffer if the data will not be printed out. |
| } |
| IdsConsole->Header.OutBufferIndex = (UINT16) Index; |
| } else { |
| IdsConsoleOps->Print (DEBUG_PRINT_COMMAND, (UINT32)ConsoleBuffer, (UINT32)Index, IdsConsole); |
| } |
| } |
| } |
| |
| /** |
| * |
| * Exit function for IDS console Function. |
| * |
| * Restore debug register and Deallocate heap. |
| * |
| * @param[in,out] StdHeader The Pointer of AGESA Header |
| * |
| **/ |
| VOID |
| AmdIdsConsoleExit ( |
| IN OUT AMD_CONFIG_PARAMS *StdHeader |
| ) |
| { |
| IDS_CONSOLE *IdsConsole; |
| UINTN IdsConsolePtr; |
| IDS_CONSOLE_OPERATIONS *IdsConsoleOps; |
| UINTN IdsConsoleOpsPtr; |
| |
| if (IsIdsConsoleEnabled (&IdsConsolePtr)) { |
| GetIdsConsole (&IdsConsolePtr); |
| IdsConsole = (IDS_CONSOLE *) IdsConsolePtr; |
| GetIdsConsoleOperations (&IdsConsoleOpsPtr); |
| IdsConsoleOps = (IDS_CONSOLE_OPERATIONS *) IdsConsoleOpsPtr; |
| |
| if (IdsConsole != NULL) { |
| if (IdsConsole->Header.PrintState != IDS_STATE_OFF) { |
| IdsConsoleOps->Print (DEBUG_PRINT_COMMAND, (UINT32)(IdsConsole->OutBuffer), IdsConsole->Header.OutBufferIndex, IdsConsole); |
| } |
| |
| IdsConsoleOps->Print (DEBUG_PRINT_EXIT, (UINT32)IdsConsole, 0, IdsConsole); |
| |
| IdsConsoleOps->DestroyConsoleContext (IdsConsole); |
| DestroyIdsConsole (IdsConsole, StdHeader); |
| |
| } |
| } |
| } |
| /** |
| * Check for CAR Corruption, the performance monitor number three programed to log the CAR Corruption. |
| * Check to see if control register is enabled and then check the preformance counter and stop the system by executing |
| * IDS_ERROR_TRAP if counter has any value other than zero. |
| * |
| * @param[in,out] StdHeader The Pointer of Standard Header. |
| * |
| * |
| **/ |
| VOID |
| IdsCarCorruptionCheck ( |
| IN OUT AMD_CONFIG_PARAMS *StdHeader |
| ) |
| { |
| |
| UINT64 Perf_Msr; |
| |
| LibAmdMsrRead (MSR_PERF_CONTROL3, (UINT64*)&Perf_Msr, StdHeader); |
| if ((Perf_Msr & PERF_RESERVE_BIT_MASK) == PERF_CAR_CORRUPTION_EVENT) { |
| LibAmdMsrRead (MSR_PERF_COUNTER3, (UINT64*)&Perf_Msr, StdHeader); |
| if ((Perf_Msr != 0)) { |
| IDS_ERROR_TRAP; |
| } |
| } |
| } |