summaryrefslogtreecommitdiff
path: root/ReferenceCode/Chipset/SystemAgent/MemoryInit/Pei/MrcOemDebugPrint.c
diff options
context:
space:
mode:
Diffstat (limited to 'ReferenceCode/Chipset/SystemAgent/MemoryInit/Pei/MrcOemDebugPrint.c')
-rw-r--r--ReferenceCode/Chipset/SystemAgent/MemoryInit/Pei/MrcOemDebugPrint.c470
1 files changed, 470 insertions, 0 deletions
diff --git a/ReferenceCode/Chipset/SystemAgent/MemoryInit/Pei/MrcOemDebugPrint.c b/ReferenceCode/Chipset/SystemAgent/MemoryInit/Pei/MrcOemDebugPrint.c
new file mode 100644
index 0000000..dcae540
--- /dev/null
+++ b/ReferenceCode/Chipset/SystemAgent/MemoryInit/Pei/MrcOemDebugPrint.c
@@ -0,0 +1,470 @@
+/** @file
+ Output debug messages to the debug port.
+
+@copyright
+ Copyright (c) 1999 - 2012 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.
+
+ This file contains an 'Intel Peripheral Driver' and uniquely
+ identified as "Intel Reference Module" and is
+ licensed for Intel CPUs and chipsets under the terms of your
+ license agreement with Intel or your vendor. This file may
+ be modified by the user, subject to additional terms of the
+ license agreement.
+
+**/
+
+#include "MrcTypes.h"
+#ifdef MRC_MINIBIOS_BUILD
+#include "printf.h"
+#else
+#include "EdkIIGluePeim.h"
+#endif // MRC_MINIBIOS_BUILD
+#include "MrcDebugHook.h"
+#include "MrcGlobal.h"
+#include "MrcOemDebugPrint.h"
+#include "MrcOemMemory.h"
+
+#ifdef MRC_DEBUG_PRINT
+#define ASCII_ETX (3)
+
+/**
+@brief
+ Convert an unsigned integer to a string.
+
+ @param[in] Value - Value to work on.
+ @param[out] Str - The return string to print.
+ @param[in] Width - The width of string to print
+ @param[in] Flags - The flag type to print out, like '-' or '+'.
+ @param[in] Base - Number base to work on, as in 10, or 16.
+
+ @retval Number of characters in the resulting string.
+**/
+U32
+OemUintnToStr (
+ IN const U32 Value,
+ OUT char *Str,
+ IN const U32 Width,
+ IN const U32 Flags,
+ IN const U32 Base
+ )
+{
+ char *Ptr;
+ U32 Negative;
+ U32 Int;
+ U32 i;
+ char Prefix;
+ char c;
+ const char Hex[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+
+ Ptr = Str;
+ if ((Value > MRC_INT32_MAX) && (Flags & MRC_INT_SIGNED)) {
+ Int = ~Value + 1; /* -Value */
+ Negative = 1;
+ } else {
+ Int = Value;
+ Negative = 0;
+ }
+
+ i = 0;
+ do { /* Generate digits in reverse order */
+ i++;
+ *Ptr++ = Hex[Int % Base];
+ if (Flags & MRC_COMMA_TYPE) {
+ if (Base == 16) {
+ if (i % 4 == 0) {
+ *Ptr++ = ',';
+ }
+ } else if (Base == 10) {
+ if ((i % 3) == 0) {
+ *Ptr++ = ',';
+ }
+ }
+ }
+ } while ((Int /= Base) > 0);
+ if (*(Ptr - 1) == ',') {
+ Ptr--;
+ }
+
+ if (Negative) {
+ *Ptr++ = '-';
+ i++;
+ } else if (Flags & MRC_PREFIX_SIGN) {
+ *Ptr++ = '+';
+ i++;
+ }
+
+ if (Flags & MRC_PREFIX_ZERO) {
+ Prefix = '0';
+ } else if (!(Flags & MRC_LEFT_JUSTIFY)) {
+ Prefix = ' ';
+ } else {
+ Prefix = 0x00;
+ }
+
+ if (Prefix != 0x00) {
+ for (i = (int) (Ptr - Str); i < Width; i++) {
+ *Ptr++ = Prefix;
+ }
+ }
+
+ *Ptr = '\0';
+
+ /* Reverse string */
+ while (Str < --Ptr) {
+ c = *Str;
+ *Str++ = *Ptr;
+ *Ptr = c;
+ }
+
+ return i;
+}
+
+/**
+@brief
+ Convert a string to a number.
+
+ @param[in, out] String - String to convert.
+
+ @retval Returns the string in number.
+**/
+U32
+OemStrToNumber (
+ IN OUT char **String
+ )
+{
+ U32 Sum;
+ char *Str;
+
+ Str = *String;
+ if (*Str == '0') {
+ Str++;
+ }
+
+ Sum = 0;
+ while (MRC_ISDIGIT (*Str)) {
+ Sum = Sum * 10 + (*Str++ -'0');
+ }
+
+ *String = Str;
+ return Sum;
+}
+
+/*++
+@brief
+ Format string using specified format specifier. Limited support for sizes other than
+ unsigned 32-bit to save code space. Type overrides like {h | I | I64 | L}
+ are not supported.
+
+ @param[in] Format - String containing characters to print and formatting data.
+ %[flags][width]type
+ [flags] '-' left align
+ [flags] '+' prefix with sign (+ or -)
+ [flags] '0' zero pad numbers
+ [flags] ' ' prefix black in front of postive numbers
+ [width] non negative decimal integer that specifies the width to print a value.
+ [width] '*' get the width from a int argument on the stack.
+ type 'd'|'i' signed decimal integer
+ type 'u' unsigned integer
+ type 'x'|'X' hexidecimal using "ABCDEF"
+ type 'c' print character
+ type 'p' print a pointer to void
+ type 's' print a null terminated string
+ @param[in] Marker - Variable argument marker.
+ @param[in] BufferSize - Size of the buffer, in bytes.
+ @param[in] Buffer - The buffer.
+
+ @retval Number of characters printed.
+**/
+int
+StringFormatter (
+ IN const char *const Format,
+ IN MrcVaList Marker,
+ IN U32 BufferSize,
+ IN OUT U8 *Buffer
+ )
+{
+ char *p;
+ char *String;
+ U32 Width;
+ U32 Flags;
+ U32 CharCount;
+
+ CharCount = 0;
+ if (Format != NULL) {
+ for (p = (char *) Format; *p && (CharCount < BufferSize); p++) {
+ if (*p != '%') {
+ if (*p == MRC_CHAR_LF) {
+ //
+ // Make LF into CR LF
+ //
+ MRC_PUTCC (Buffer, MRC_CHAR_CR, CharCount);
+ }
+
+ MRC_PUTCC (Buffer, *p, CharCount);
+ } else {
+ p++;
+ //
+ // Check for flags
+ //
+ Flags = 0;
+ if (*p == '-') {
+ Flags |= MRC_LEFT_JUSTIFY;
+ } else if (*p == '+') {
+ Flags |= MRC_PREFIX_SIGN;
+ } else if (*p == ' ') {
+ Flags |= MRC_PREFIX_BLANK;
+ }
+
+ if (Flags != 0) {
+ p++;
+ }
+ //
+ // Check for width
+ //
+ if (MRC_ISDIGIT (*p)) {
+ if (*p == '0') {
+ Flags |= MRC_PREFIX_ZERO;
+ }
+
+ Width = OemStrToNumber (&p);
+ } else if (*p == '*') {
+ Width = VA_ARG (Marker, int);
+ p++;
+ } else {
+ Width = 0;
+ }
+
+ if (*p == ',') {
+ Flags |= MRC_COMMA_TYPE;
+ p++;
+ }
+ //
+ // Get type
+ //
+ switch (*p) {
+ case 'd':
+ case 'i':
+ //
+ // Always print as UINTN. Will need extra code to print different widths.
+ //
+ CharCount = CharCount + OemUintnToStr (
+ (U32) VA_ARG (Marker, U32 *),
+ (char *) &Buffer[CharCount],
+ Width,
+ Flags | MRC_INT_SIGNED,
+ 10
+ );
+ break;
+
+ case 'u':
+ //
+ // Always print as UINTN. Will need extra code to print different widths.
+ //
+ CharCount = CharCount + OemUintnToStr ((U32) VA_ARG (Marker, U32 *), (char *) &Buffer[CharCount], Width, Flags, 10);
+ break;
+
+ case 'x':
+ case 'X':
+ case 'p':
+ //
+ // Always print as UINTN. Will need extra code to print different widths.
+ //
+ CharCount = CharCount + OemUintnToStr ((U32) VA_ARG (Marker, U32 *), (char *) &Buffer[CharCount], Width, Flags, 16);
+ break;
+
+ case 'c':
+ MRC_PUTCC (Buffer, VA_ARG (Marker, char), CharCount);
+ Buffer[CharCount] = '\0';
+ break;
+
+ case 's':
+ String = (char *) VA_ARG (Marker, char *);
+ while (*String != '\0') {
+ MRC_PUTCC (Buffer, *String++, CharCount);
+ }
+ break;
+ }
+ }
+ }
+
+ if (CharCount < BufferSize) {
+ MRC_PUTCC (Buffer, '\0', CharCount);
+ } else {
+ Buffer[BufferSize - 1] = '\0';
+ }
+ }
+
+ return CharCount;
+}
+
+/*++
+
+@brief
+ Print to output stream/device. Limited support for sizes other than
+ unsigned 32-bit to save code space. Type overrides like {h | I | I64 | L}
+ are not supported.
+
+ @param[in] Debug - Location to store debug message print information for future use.
+ @param[in] Level - The debug level.
+ @param[in] Format - String containing characters to print and formatting data.
+ %[flags][width]type
+ [flags] '-' left align
+ [flags] '+' prefix with sign (+ or -)
+ [flags] '0' zero pad numbers
+ [flags] ' ' prefix black in front of postive numbers
+ [width] non negative decimal integer that specifies the width to print a value.
+ [width] '*' get the width from a int argument on the stack.
+ type 'd'|'i' signed decimal integer
+ type 'u' unsigned integer
+ type 'x'|'X' hexidecimal using "ABCDEF"
+ type 'c' print character
+ type 'p' print a pointer to void
+ type 's' print a null terminated string
+ @param[in] Marker - Variable argument marker
+
+ @retval Number of characters printed.
+**/
+int
+MrcOemPrintfVaList (
+ IN const MrcDebug *const Debug,
+ IN const MrcDebugMsgLevel Level,
+ IN const char *const Format,
+ IN MrcVaList Marker
+ )
+{
+ MrcDebug *Dbg;
+ U8 *String;
+ U32 CharCount;
+ U8 Buffer[MAX_STRING_LENGTH];
+
+ CharCount = 0;
+ if ((Format != NULL) && (Level != MSG_LEVEL_NEVER)) {
+ if (((Debug->Level == MSG_LEVEL_TIME) && (Level == MSG_LEVEL_TIME)) || ((Debug->Level != MSG_LEVEL_TIME) && (Level <= Debug->Level))) {
+ CharCount = StringFormatter (Format, Marker, sizeof (Buffer), Buffer);
+
+ //
+ // Write the string to the serial log buffer.
+ //
+ if (Debug->Current > 0) {
+ Dbg = (MrcDebug *) Debug;
+ String = Buffer;
+ while (*String != '\0') {
+ if (Dbg->Current >= Dbg->End) {
+ Dbg->Current = Dbg->Start;
+ }
+ *((U8 *) (Dbg->Current)) = *String++;
+ Dbg->Current++;
+ }
+ //
+ // Write a "end of text" marker to the buffer but don't increment the current pointer.
+ //
+ if (Dbg->Current >= Dbg->End) {
+ Dbg->Current = Dbg->Start;
+ }
+ *((U8 *) (Dbg->Current)) = ASCII_ETX;
+ }
+
+ if (Debug->Stream > 0) {
+#ifdef MRC_MINIBIOS_BUILD
+ puts ((char *) Buffer);
+#else
+ PEI_DEBUG (((void *) (Debug->Stream), EFI_D_ERROR, Buffer));
+#endif
+ }
+ }
+ }
+ return CharCount;
+}
+
+/**
+@brief
+ Print to output stream/device. Gets the start Marker for the variable arguments
+ and calls MrcOemPrintfVaList().
+
+ @param[in] Debug - Location to store debug message print information for future use.
+ @param[in] Level - The debug level.
+ @param[in] Format - String containing characters to print and formatting data.
+ %[flags][width]type
+ [flags] '-' left align
+ [flags] '+' prefix with sign (+ or -)
+ [flags] '0' zero pad numbers
+ [flags] ' ' prefix black in front of postive numbers
+ [width] non negative decimal integer that specifies the width to print a value.
+ [width] '*' get the width from a int argument on the stack.
+ type 'd'|'i' signed decimal integer
+ type 'u' unsigned integer
+ type 'x'|'X' hexidecimal using "ABCDEF"
+ type 'c' print character
+ type 'p' print a pointer to void
+ type 's' print a null terminated string
+ @param[in] ... - Variable number of arguments to print
+
+ @retval Number of characters printed.
+**/
+int
+MrcOemPrintf (
+ IN const MrcDebug *const Debug,
+ IN const MrcDebugMsgLevel Level,
+ IN const char *const Format,
+ ...
+ )
+{
+ MrcVaList Marker;
+
+ VA_START (Marker, Format);
+
+ return MrcOemPrintfVaList (Debug, Level, Format, Marker);
+}
+
+/**
+@brief
+ Save the output stream/device. This function must be called prior to debug
+ string output.
+
+ @param[out] Debug - Location to store debug message print information for future use.
+ @param[in] Level - The debug level to set. Messages at or above this level are printed.
+ @param[in] Stream - Pointer to the stream/device to use.
+ @param[in] Buffer - Pointer to the buffer that will be used to 'tee' the data to.
+ @param[in] Size - Size of the 'tee' buffer.
+
+ @retval Nothing.
+**/
+void
+MrcOemFopen (
+ OUT MrcDebug *const Debug,
+ IN const MrcDebugMsgLevel Level,
+ IN U32 Stream,
+ IN U32 Buffer,
+ IN U32 Size
+ )
+{
+ const U8 StringBegin[] = "ISV>";
+ const U8 StringEnd[] = "<ISV";
+
+ Debug->Level = Level;
+ Debug->Stream = Stream;
+ Debug->PostCode[0] = 0;
+ if ((Buffer > 0) && (Size > (sizeof (StringBegin) + sizeof (StringEnd)))) {
+ Debug->Start = Buffer + (sizeof (StringBegin) - 1);
+ Debug->End = Buffer + Size - (sizeof (StringEnd) - 1);
+ Debug->Current = Debug->Start;
+ MrcOemMemorySet ((U8 *) Debug->Start, ' ', Size - (sizeof (StringBegin) + sizeof (StringEnd) - 2));
+ MrcOemMemoryCpy ((U8 *) Buffer, (U8 *) StringBegin, sizeof (StringBegin) - 1);
+ MrcOemMemoryCpy ((U8 *) Debug->End, (U8 *) StringEnd, sizeof (StringEnd) - 1);
+ } else {
+ Debug->Start = 0;
+ Debug->End = 0;
+ Debug->Current = 0;
+ }
+
+ return;
+}
+
+#endif // MRC_DEBUG_PRINT