| /** |
| * @file |
| * |
| * Debug out functions. |
| * |
| * |
| * |
| * @xrefitem bom "File Content Label" "Release Content" |
| * @e project: Common Library |
| * @e sub-project: |
| * @e \$Revision:$ @e \$Date:$ |
| * |
| */ |
| /***************************************************************************** |
| * |
| * Copyright (C) 2012 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 "amdlib.h" |
| #include "amdDebugOutLib.h" |
| /*---------------------------------------------------------------------------------------- |
| * D E F I N I T I O N S A N D M A C R O S |
| *---------------------------------------------------------------------------------------- |
| */ |
| #define COM_BASE_ADDRESS 0x3f8 |
| #define DIVISOR 115200 |
| #define LF 0x0a |
| #define CR 0x0d |
| |
| typedef CHAR8 *va_list; |
| #ifndef _INTSIZEOF |
| #define _INTSIZEOF(n)( (sizeof(n) + sizeof(UINTN) - 1) & ~(sizeof(UINTN) - 1) ) |
| #endif |
| #ifndef va_start |
| #define va_start(ap, v) ( ap = (va_list)&(v) + _INTSIZEOF(v) ) |
| #endif |
| #ifndef va_arg |
| #define va_arg(ap, t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) ) |
| #endif |
| #ifndef va_end |
| #define va_end(ap) ( ap = (va_list)0 ) |
| #endif |
| |
| /*---------------------------------------------------------------------------------------- |
| * T Y P E D E F S A N D S T R U C T U R E S |
| *---------------------------------------------------------------------------------------- |
| */ |
| |
| typedef struct { |
| UINT8 Index; |
| CHAR8 Buffer[256]; |
| } StringBuffer; |
| |
| /*---------------------------------------------------------------------------------------- |
| * P R O T O T Y P E S O F L O C A L F U N C T I O N S |
| *---------------------------------------------------------------------------------------- |
| */ |
| |
| VOID |
| SendByteToBuffer ( |
| IN OUT StringBuffer *Buffer, |
| IN CHAR8 Data |
| ); |
| |
| VOID |
| SendStringToBuffer ( |
| OUT StringBuffer *Buffer, |
| IN CHAR8 *pstr |
| ); |
| |
| VOID |
| SendBufferToDebugOut ( |
| IN CHAR8* Buffer |
| ); |
| |
| VOID |
| ItoA ( |
| IN UINT32 Value, |
| IN UINTN Radix, |
| OUT CHAR8 *pstr |
| ); |
| |
| VOID |
| SendBufferToHdtOut ( |
| IN CHAR8* Buffer |
| ); |
| |
| VOID |
| SendBufferToSerialOut ( |
| IN CHAR8* Buffer |
| ); |
| |
| VOID |
| InitDebugOut (VOID); |
| |
| VOID |
| InitSerialOut (VOID); |
| |
| /*---------------------------------------------------------------------------------------- |
| * E X P O R T E D F U N C T I O N S |
| *---------------------------------------------------------------------------------------- |
| */ |
| |
| |
| /*----------------------------------------------------------------------------------------*/ |
| /** |
| * Send format string to debug out |
| * |
| * |
| * |
| * @param[in] pConfig |
| * |
| */ |
| |
| VOID |
| LibAmdTraceDebug ( |
| IN UINT32 Level, |
| IN CHAR8 *Format, |
| IN ... |
| ) |
| { |
| CHAR8 TemBuffer[16]; |
| UINT8 Index; |
| StringBuffer Buffer; |
| va_list ArgList; |
| if (Level == 0) { |
| return; |
| } |
| Buffer.Index = 0; |
| Index = 1; |
| va_start (ArgList, Format); |
| while (Index != 0) { |
| if (*Format == 0) break; |
| if (*Format == '%') { |
| INT32 Radix; |
| Radix = 0; |
| if (*(Format + 1) == 'd' || *(Format + 1) == 'D') { |
| Radix = 10; |
| } |
| if (*(Format + 1) == 'x' || *(Format + 1) == 'X' ) { |
| Radix = 16; |
| } |
| if (Radix != 0) { |
| ItoA (va_arg (ArgList, INT32), Radix, TemBuffer); |
| SendStringToBuffer (&Buffer, TemBuffer); |
| Format += 2; |
| continue; |
| } |
| } |
| SendByteToBuffer (&Buffer, *Format); |
| if (*(Format) == 0x0a) SendByteToBuffer (&Buffer, 0x0d); |
| Format++; |
| } |
| SendBufferToDebugOut (&Buffer.Buffer[0]); |
| va_end (ArgList); |
| } |
| |
| |
| /*----------------------------------------------------------------------------------------*/ |
| /** |
| * Write string to message buffer |
| * |
| * |
| * |
| * @param[in] pConfig |
| * |
| */ |
| |
| VOID |
| SendStringToBuffer ( |
| OUT StringBuffer *Buffer, |
| IN CHAR8 *pstr |
| ) |
| { |
| while (*pstr != 0) { |
| SendByteToBuffer (Buffer, *pstr); |
| pstr++; |
| } |
| } |
| |
| /*----------------------------------------------------------------------------------------*/ |
| /** |
| * Write byte to message buffer |
| * |
| * |
| * |
| * @param[in] pConfig |
| * |
| */ |
| |
| VOID |
| SendByteToBuffer ( |
| IN OUT StringBuffer *Buffer, |
| IN CHAR8 Data |
| ) |
| { |
| if (Buffer->Index < 255) { |
| Buffer->Buffer[Buffer->Index] = Data; |
| Buffer->Buffer[++Buffer->Index] = 0; |
| } else { |
| SendBufferToDebugOut (Buffer->Buffer); |
| Buffer->Index = 0; |
| } |
| } |
| |
| /*----------------------------------------------------------------------------------------*/ |
| /** |
| * Integer To String |
| * |
| * |
| * |
| * @param[in] pConfig |
| * |
| */ |
| |
| VOID |
| ItoA ( |
| IN UINT32 Value, |
| IN UINTN Radix, |
| OUT CHAR8 *pstr |
| ) |
| { |
| CHAR8 *tsptr; |
| CHAR8 *rsptr; |
| CHAR8 ch1; |
| CHAR8 ch2; |
| UINTN Reminder; |
| |
| tsptr = pstr; |
| rsptr = pstr; |
| //Create String |
| do { |
| Reminder = Value % Radix; |
| Value = Value / Radix; |
| if (Reminder < 0xa) { |
| *tsptr = (UINT8)Reminder + '0'; |
| } else { |
| *tsptr = (UINT8)Reminder - 0xa + 'a'; |
| } |
| tsptr++; |
| } while (Value != 0); |
| //Reverse String |
| *tsptr = 0; |
| tsptr--; |
| while (tsptr > rsptr) { |
| ch1 = *tsptr; |
| ch2 = *rsptr; |
| *rsptr = ch1; |
| *tsptr = ch2; |
| tsptr--; |
| rsptr++; |
| } |
| } |
| |
| /*----------------------------------------------------------------------------------------*/ |
| /** |
| * Init debug Output |
| * |
| * |
| * |
| * @param[in] pConfig |
| * |
| */ |
| VOID |
| InitDebugOut ( |
| VOID |
| ) |
| { |
| #ifdef SERIAL_OUT_SUPPORT |
| InitSerialOut (); |
| #endif |
| } |
| |
| /*----------------------------------------------------------------------------------------*/ |
| /** |
| * Init Serial Output |
| * |
| * |
| * |
| * @param[in] pConfig |
| * |
| */ |
| VOID |
| InitSerialOut ( |
| VOID |
| ) |
| { |
| UINT8 Data; |
| UINT16 Divisor; |
| |
| Data = 0x87; |
| LibAmdIoWrite (AccessWidth8, COM_BASE_ADDRESS + 0x3, &Data, NULL); |
| Divisor = 115200 / DIVISOR; |
| Data = (UINT8) (Divisor & 0xFF); |
| LibAmdIoWrite (AccessWidth8 , COM_BASE_ADDRESS + 0x00, &Data, NULL); |
| Data = (UINT8) (Divisor >> 8); |
| LibAmdIoWrite (AccessWidth8, COM_BASE_ADDRESS + 0x01, &Data, NULL); |
| Data = 0x07; |
| LibAmdIoWrite (AccessWidth8, COM_BASE_ADDRESS + 0x3, &Data, NULL); |
| } |
| |
| /*----------------------------------------------------------------------------------------*/ |
| /** |
| * Init HDT Output |
| * |
| * |
| * |
| * @param[in] pConfig |
| * |
| */ |
| |
| |
| /*----------------------------------------------------------------------------------------*/ |
| /** |
| * Send Buffer to debug Output |
| * |
| * |
| * |
| * @param[in] pConfig |
| * |
| */ |
| VOID |
| SendBufferToDebugOut ( |
| IN CHAR8* Buffer |
| ) |
| { |
| #ifdef HDT_OUT_SUPPORT |
| SendBufferToHdtOut (Buffer); |
| #endif |
| |
| #ifdef SERIAL_OUT_SUPPORT |
| SendBufferToSerialOut (Buffer); |
| #endif |
| } |
| |
| #ifdef HDT_OUT_SUPPORT |
| /*----------------------------------------------------------------------------------------*/ |
| /** |
| * Send Buffer to debug Output |
| * |
| * |
| * |
| * @param[in] pConfig |
| * |
| */ |
| VOID |
| SendBufferToHdtOut ( |
| IN CHAR8* Buffer |
| ) |
| { |
| UINT32 Dr0Reg; |
| UINT32 Dr7Reg; |
| UINT32 Cr4Reg; |
| UINT64 MsrCurrentValue; |
| UINT64 MsrNewValue; |
| |
| // Save the CPU debug registers for restoration at the end of the routine |
| LibAmdMsrRead (0xC001100A, &MsrCurrentValue, NULL); |
| LibAmdReadCpuReg (DR0_REG, &Dr0Reg); |
| LibAmdReadCpuReg (DR7_REG, &Dr7Reg); |
| LibAmdReadCpuReg (CR4_REG, &Cr4Reg); |
| |
| //Modify the registers for HDT out |
| LibAmdWriteCpuReg (DR0_REG, 0x8F0); |
| LibAmdWriteCpuReg (DR7_REG, 0x20402); |
| LibAmdWriteCpuReg (CR4_REG, Cr4Reg | 0x8); |
| MsrNewValue = MsrCurrentValue | BIT0; |
| LibAmdMsrWrite (0xC001100A, &MsrNewValue, NULL); |
| |
| //HDT out |
| LibAmdIoWrite (AccessWidth32, 0x8F0, &Buffer, NULL); |
| |
| // Restore the CPU debug registers |
| LibAmdWriteCpuReg (CR4_REG, Cr4Reg); |
| LibAmdWriteCpuReg (DR7_REG, Dr7Reg); |
| LibAmdWriteCpuReg (DR0_REG, Dr0Reg); |
| LibAmdMsrWrite (0xC001100A, &MsrCurrentValue, NULL); |
| } |
| #endif |
| /*----------------------------------------------------------------------------------------*/ |
| /** |
| * Send Buffer to debug Output |
| * |
| * |
| * |
| * @param[in] pConfig |
| * |
| */ |
| VOID |
| SendBufferToSerialOut ( |
| IN CHAR8* Buffer |
| ) |
| { |
| UINT8 Status; |
| UINT32 Count; |
| |
| Count = 10000; |
| while (*Buffer != 0) { |
| do { |
| LibAmdIoRead (AccessWidth8, COM_BASE_ADDRESS + 0x05, &Status, NULL); |
| if (Status == 0xff) return; |
| // Loop port is ready |
| } while ((Status & 0x20) == 0 && (--Count) != 0); |
| LibAmdIoWrite (AccessWidth8, COM_BASE_ADDRESS + 0x00, Buffer, NULL); |
| Buffer++; |
| } |
| } |