5 * AMD Event (Error) Log APIs, and related functions.
7 * Contains code that records and returns the events and errors.
9 * @xrefitem bom "File Content Label" "Release Content"
12 * @e \$Revision: 56279 $ @e \$Date: 2011-07-11 13:11:28 -0600 (Mon, 11 Jul 2011) $
15 /*****************************************************************************
17 * Copyright (C) 2012 Advanced Micro Devices, Inc.
18 * All rights reserved.
20 * Redistribution and use in source and binary forms, with or without
21 * modification, are permitted provided that the following conditions are met:
22 * * Redistributions of source code must retain the above copyright
23 * notice, this list of conditions and the following disclaimer.
24 * * Redistributions in binary form must reproduce the above copyright
25 * notice, this list of conditions and the following disclaimer in the
26 * documentation and/or other materials provided with the distribution.
27 * * Neither the name of Advanced Micro Devices, Inc. nor the names of
28 * its contributors may be used to endorse or promote products derived
29 * from this software without specific prior written permission.
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
32 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
33 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
34 * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
35 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
36 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
37 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
38 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
39 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
40 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42 ******************************************************************************
45 /*----------------------------------------------------------------------------------------
46 * M O D U L E S U S E D
47 *----------------------------------------------------------------------------------------
52 #include "heapManager.h"
53 #include "GeneralServices.h"
59 #define FILECODE PROC_CPU_CPUEVENTLOG_FILECODE
60 /*----------------------------------------------------------------------------------------
61 * D E F I N I T I O N S A N D M A C R O S
62 *----------------------------------------------------------------------------------------
64 #define TOTAL_EVENT_LOG_BUFFERS 16
66 /*----------------------------------------------------------------------------------------
67 * T Y P E D E F S A N D S T R U C T U R E S
68 *----------------------------------------------------------------------------------------
72 * A wrapper for each Event Log entry.
75 UINT16 Count; ///< Entry number
76 AGESA_EVENT AgesaEvent; ///< The entry itself.
83 UINT16 ReadWriteFlag; ///< Read Write flag.
84 UINT16 Count; ///< The total number of active entries.
85 UINT16 ReadRecordPtr; ///< The next entry to read.
86 UINT16 WriteRecordPtr; ///< The next entry to write.
87 AGESA_EVENT_STRUCT AgesaEventStruct[TOTAL_EVENT_LOG_BUFFERS]; ///< The entries.
88 } AGESA_STRUCT_BUFFER;
90 /*----------------------------------------------------------------------------------------
91 * 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
92 *----------------------------------------------------------------------------------------
96 GetEventLogHeapPointer (
97 OUT AGESA_STRUCT_BUFFER **EventLog,
98 IN AMD_CONFIG_PARAMS *StdHeader
101 /*---------------------------------------------------------------------------------------*/
103 * External AGESA interface to read an Event from the Event Log.
105 * This is the implementation of the external AGESA interface entry, as a thin wrapper
106 * around the internal log services.
108 * @param[in] Event The event class, id, and any associated data.
110 * @retval AGESA_SUCCESS Always Succeeds.
114 IN EVENT_PARAMS *Event
117 AGESA_EVENT LogEvent;
120 AGESA_TESTPOINT (TpIfAmdReadEventLogEntry, &Event->StdHeader);
122 ASSERT (Event != NULL);
123 Event->StdHeader.HeapBasePtr = HeapGetBaseAddress (&Event->StdHeader);
124 Status = GetEventLog (&LogEvent, &Event->StdHeader);
126 Event->EventClass = LogEvent.EventClass;
127 Event->EventInfo = LogEvent.EventInfo;
128 Event->DataParam1 = LogEvent.DataParam1;
129 Event->DataParam2 = LogEvent.DataParam2;
130 Event->DataParam3 = LogEvent.DataParam3;
131 Event->DataParam4 = LogEvent.DataParam4;
133 AGESA_TESTPOINT (TpIfAmdReadEventLogExit, &Event->StdHeader);
138 /*---------------------------------------------------------------------------------------*/
141 * This function prepares the Event Log for use.
143 * Allocate the memory for an event log on the heap. Set the read pointer, write pointer,
144 * and count to reflect the log is empty.
146 * @param[in] StdHeader Our configuration, for passing to services.
148 * @retval AGESA_SUCCESS The event log is initialized.
149 * @retval AGESA_ERROR Allocate Heap Buffer returned an error.
153 EventLogInitialization (
154 IN AMD_CONFIG_PARAMS *StdHeader
157 ALLOCATE_HEAP_PARAMS AllocateHeapParams;
158 AGESA_STRUCT_BUFFER *AgesaEventAlloc;
161 AllocateHeapParams.BufferHandle = EVENT_LOG_BUFFER_HANDLE;
162 AllocateHeapParams.RequestedBufferSize = sizeof (AGESA_STRUCT_BUFFER);
163 AllocateHeapParams.Persist = HEAP_SYSTEM_MEM;
164 Status = HeapAllocateBuffer (&AllocateHeapParams, StdHeader);
165 AgesaEventAlloc = (AGESA_STRUCT_BUFFER *) AllocateHeapParams.BufferPtr;
166 AgesaEventAlloc->Count = 0;
167 AgesaEventAlloc->ReadRecordPtr = 0;
168 AgesaEventAlloc->WriteRecordPtr = 0;
169 AgesaEventAlloc->ReadWriteFlag = 1;
175 /*---------------------------------------------------------------------------------------*/
178 * This function logs AGESA events into the event log.
180 * It will put the information in a circular buffer consisting of 16 such log
181 * entries. If the buffer gets full, then the next event log entry will be written
182 * over the oldest event log entry.
184 * @param[in] EventClass The severity of the event, its associated AGESA_STATUS.
185 * @param[in] EventInfo Uniquely identifies the event.
186 * @param[in] DataParam1 Event specific additional data
187 * @param[in] DataParam2 Event specific additional data
188 * @param[in] DataParam3 Event specific additional data
189 * @param[in] DataParam4 Event specific additional data
190 * @param[in] StdHeader Header for library and services
195 IN AGESA_STATUS EventClass,
197 IN UINT32 DataParam1,
198 IN UINT32 DataParam2,
199 IN UINT32 DataParam3,
200 IN UINT32 DataParam4,
201 IN AMD_CONFIG_PARAMS *StdHeader
205 AGESA_STRUCT_BUFFER *AgesaEventAlloc;
207 IDS_HDT_CONSOLE (MAIN_FLOW, "\n * %s Event: %08x Data: %x, %x, %x, %x\n\n",
208 (EventClass == AGESA_FATAL) ? "FATAL" :
209 (EventClass == AGESA_CRITICAL) ? "CRITICAL" :
210 (EventClass == AGESA_ERROR) ? "ERROR" :
211 (EventClass == AGESA_WARNING) ? "WARNING" :
212 (EventClass == AGESA_ALERT) ? "ALERT" :
213 (EventClass == AGESA_BOUNDS_CHK) ? "BOUNDS_CHK" :
214 (EventClass == AGESA_UNSUPPORTED) ? "UNSUPPORTED" :
215 "SUCCESS", EventInfo, DataParam1, DataParam2, DataParam3, DataParam4);
217 AgesaEventAlloc = NULL;
218 GetEventLogHeapPointer (&AgesaEventAlloc, StdHeader);
219 ASSERT (AgesaEventAlloc != NULL);
220 Index = AgesaEventAlloc->WriteRecordPtr;
222 // Add the new event log data into a circular buffer
223 AgesaEventAlloc->AgesaEventStruct[Index].AgesaEvent.EventClass = EventClass;
224 AgesaEventAlloc->AgesaEventStruct[Index].AgesaEvent.EventInfo = EventInfo;
225 AgesaEventAlloc->AgesaEventStruct[Index].AgesaEvent.DataParam1 = DataParam1;
226 AgesaEventAlloc->AgesaEventStruct[Index].AgesaEvent.DataParam2 = DataParam2;
227 AgesaEventAlloc->AgesaEventStruct[Index].AgesaEvent.DataParam3 = DataParam3;
228 AgesaEventAlloc->AgesaEventStruct[Index].AgesaEvent.DataParam4 = DataParam4;
230 if ((AgesaEventAlloc->WriteRecordPtr == AgesaEventAlloc->ReadRecordPtr) &&
231 (AgesaEventAlloc->ReadWriteFlag == 0)) {
232 AgesaEventAlloc->WriteRecordPtr += 1;
233 AgesaEventAlloc->ReadRecordPtr += 1;
234 if (AgesaEventAlloc->WriteRecordPtr == TOTAL_EVENT_LOG_BUFFERS) {
235 AgesaEventAlloc->WriteRecordPtr = 0;
236 AgesaEventAlloc->ReadRecordPtr = 0;
239 AgesaEventAlloc->WriteRecordPtr += 1;
240 if (AgesaEventAlloc->WriteRecordPtr == TOTAL_EVENT_LOG_BUFFERS) {
241 AgesaEventAlloc->WriteRecordPtr = 0;
243 AgesaEventAlloc->ReadWriteFlag = 0;
245 AgesaEventAlloc->Count = AgesaEventAlloc->Count + 1;
247 if (AgesaEventAlloc->Count <= TOTAL_EVENT_LOG_BUFFERS) {
248 AgesaEventAlloc->AgesaEventStruct[Index].Count = Index;
253 /*---------------------------------------------------------------------------------------*/
256 * This function gets event logs from the circular buffer.
258 * It will read the oldest entry from the circular buffer and place that information to the structure
259 * pointed to by the parameter. The read pointers will be incremented to remove the entry from buffer
260 * so that a subsequent call will return the next entry from the buffer. If the buffer is empty the
261 * returned log event will have EventInfo zero, which is not a valid event id.
263 * @param[out] EventRecord The next log event.
264 * @param[in] StdHeader Header for library and services
266 * @retval AGESA_SUCCESS Always succeeds.
271 OUT AGESA_EVENT *EventRecord,
272 IN AMD_CONFIG_PARAMS *StdHeader
276 AGESA_STRUCT_BUFFER *AgesaEventAlloc;
278 AgesaEventAlloc = NULL;
280 GetEventLogHeapPointer (&AgesaEventAlloc, StdHeader);
281 ASSERT (AgesaEventAlloc != NULL);
283 if ((AgesaEventAlloc->ReadRecordPtr == AgesaEventAlloc->WriteRecordPtr) &&
284 (AgesaEventAlloc->ReadWriteFlag == 1)) {
285 // EventInfo == zero, means no more data.
286 LibAmdMemFill (EventRecord, 0, sizeof (AGESA_EVENT), StdHeader);
288 Index = AgesaEventAlloc->ReadRecordPtr;
289 EventRecord->EventClass = AgesaEventAlloc->AgesaEventStruct[Index].AgesaEvent.EventClass;
290 EventRecord->EventInfo = AgesaEventAlloc->AgesaEventStruct[Index].AgesaEvent.EventInfo;
291 EventRecord->DataParam1 = AgesaEventAlloc->AgesaEventStruct[Index].AgesaEvent.DataParam1;
292 EventRecord->DataParam2 = AgesaEventAlloc->AgesaEventStruct[Index].AgesaEvent.DataParam2;
293 EventRecord->DataParam3 = AgesaEventAlloc->AgesaEventStruct[Index].AgesaEvent.DataParam3;
294 EventRecord->DataParam4 = AgesaEventAlloc->AgesaEventStruct[Index].AgesaEvent.DataParam4;
295 if (AgesaEventAlloc->ReadRecordPtr == (TOTAL_EVENT_LOG_BUFFERS - 1)) {
296 AgesaEventAlloc->ReadRecordPtr = 0;
298 AgesaEventAlloc->ReadRecordPtr = AgesaEventAlloc->ReadRecordPtr + 1;
300 if (AgesaEventAlloc->ReadRecordPtr == AgesaEventAlloc->WriteRecordPtr) {
301 AgesaEventAlloc->ReadWriteFlag = 1;
304 return (AGESA_SUCCESS);
307 /*---------------------------------------------------------------------------------------*/
310 * This function gets event logs from the circular buffer without flushing the entry.
312 * It will read the desired entry from the circular buffer and place that information to the structure
313 * pointed to by the parameter. The read pointers will not be incremented to remove the entry from the
314 * buffer. If the buffer is empty, or the desired entry does not exist, FALSE will be returned.
316 * @param[out] EventRecord The next log event.
317 * @param[in] Index Zero-based unread entry index
318 * @param[in] StdHeader Header for library and services
320 * @retval TRUE Entry exists
321 * @retval FALSE Entry does not exist
326 OUT AGESA_EVENT *EventRecord,
328 IN AMD_CONFIG_PARAMS *StdHeader
332 UINT16 UnreadEntries;
333 AGESA_STRUCT_BUFFER *AgesaEventAlloc;
335 AgesaEventAlloc = NULL;
337 GetEventLogHeapPointer (&AgesaEventAlloc, StdHeader);
338 ASSERT (AgesaEventAlloc != NULL);
340 if ((AgesaEventAlloc->ReadRecordPtr == AgesaEventAlloc->WriteRecordPtr) &&
341 (AgesaEventAlloc->ReadWriteFlag == 1)) {
342 // EventInfo == zero, means no more data.
345 if (AgesaEventAlloc->ReadRecordPtr < AgesaEventAlloc->WriteRecordPtr) {
346 UnreadEntries = AgesaEventAlloc->WriteRecordPtr - AgesaEventAlloc->ReadRecordPtr;
348 UnreadEntries = TOTAL_EVENT_LOG_BUFFERS - (AgesaEventAlloc->ReadRecordPtr - AgesaEventAlloc->WriteRecordPtr);
350 if (Index >= UnreadEntries) {
353 ActualIndex = Index + AgesaEventAlloc->ReadRecordPtr;
354 if (ActualIndex >= TOTAL_EVENT_LOG_BUFFERS) {
355 ActualIndex -= TOTAL_EVENT_LOG_BUFFERS;
358 EventRecord->EventClass = AgesaEventAlloc->AgesaEventStruct[ActualIndex].AgesaEvent.EventClass;
359 EventRecord->EventInfo = AgesaEventAlloc->AgesaEventStruct[ActualIndex].AgesaEvent.EventInfo;
360 EventRecord->DataParam1 = AgesaEventAlloc->AgesaEventStruct[ActualIndex].AgesaEvent.DataParam1;
361 EventRecord->DataParam2 = AgesaEventAlloc->AgesaEventStruct[ActualIndex].AgesaEvent.DataParam2;
362 EventRecord->DataParam3 = AgesaEventAlloc->AgesaEventStruct[ActualIndex].AgesaEvent.DataParam3;
363 EventRecord->DataParam4 = AgesaEventAlloc->AgesaEventStruct[ActualIndex].AgesaEvent.DataParam4;
369 /*---------------------------------------------------------------------------------------*/
372 * This function gets the Event Log pointer.
374 * It will locate the Event Log on the heap using the heap locate service. If the Event
375 * Log is not located, NULL is returned.
377 * @param[out] EventLog Pointer to the Event Log, or NULL.
378 * @param[in] StdHeader Our Configuration, for passing to services.
383 GetEventLogHeapPointer (
384 OUT AGESA_STRUCT_BUFFER **EventLog,
385 IN AMD_CONFIG_PARAMS *StdHeader
388 LOCATE_HEAP_PTR LocateHeapStruct;
390 LocateHeapStruct.BufferHandle = EVENT_LOG_BUFFER_HANDLE;
391 LocateHeapStruct.BufferPtr = NULL;
392 if ((HeapLocateBuffer (&LocateHeapStruct, StdHeader)) == AGESA_SUCCESS) {
393 *EventLog = (AGESA_STRUCT_BUFFER *)LocateHeapStruct.BufferPtr;