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: 44324 $ @e \$Date: 2010-12-22 17:16:51 +0800 (Wed, 22 Dec 2010) $
15 /*****************************************************************************
17 * Copyright (c) 2011, 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.
41 ******************************************************************************
44 /*----------------------------------------------------------------------------------------
45 * M O D U L E S U S E D
46 *----------------------------------------------------------------------------------------
51 #include "heapManager.h"
52 #include "GeneralServices.h"
56 RDATA_GROUP (G1_PEICC)
58 #define FILECODE PROC_CPU_CPUEVENTLOG_FILECODE
59 /*----------------------------------------------------------------------------------------
60 * D E F I N I T I O N S A N D M A C R O S
61 *----------------------------------------------------------------------------------------
63 #define TOTAL_EVENT_LOG_BUFFERS 16
65 /*----------------------------------------------------------------------------------------
66 * T Y P E D E F S A N D S T R U C T U R E S
67 *----------------------------------------------------------------------------------------
71 * A wrapper for each Event Log entry.
74 UINT16 Count; ///< Entry number
75 AGESA_EVENT AgesaEvent; ///< The entry itself.
82 UINT16 ReadWriteFlag; ///< Read Write flag.
83 UINT16 Count; ///< The total number of active entries.
84 UINT16 ReadRecordPtr; ///< The next entry to read.
85 UINT16 WriteRecordPtr; ///< The next entry to write.
86 AGESA_EVENT_STRUCT AgesaEventStruct[TOTAL_EVENT_LOG_BUFFERS]; ///< The entries.
87 } AGESA_STRUCT_BUFFER;
89 /*----------------------------------------------------------------------------------------
90 * 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
91 *----------------------------------------------------------------------------------------
95 GetEventLogHeapPointer (
96 OUT AGESA_STRUCT_BUFFER **EventLog,
97 IN AMD_CONFIG_PARAMS *StdHeader
100 /*---------------------------------------------------------------------------------------*/
102 * External AGESA interface to read an Event from the Event Log.
104 * This is the implementation of the external AGESA interface entry, as a thin wrapper
105 * around the internal log services.
107 * @param[in] Event The event class, id, and any associated data.
109 * @retval AGESA_SUCCESS Always Succeeds.
113 IN EVENT_PARAMS *Event
116 AGESA_EVENT LogEvent;
119 AGESA_TESTPOINT (TpIfAmdReadEventLogEntry, &Event->StdHeader);
121 ASSERT (Event != NULL);
122 Event->StdHeader.HeapBasePtr = HeapGetBaseAddress (&Event->StdHeader);
123 Status = GetEventLog (&LogEvent, &Event->StdHeader);
125 Event->EventClass = LogEvent.EventClass;
126 Event->EventInfo = LogEvent.EventInfo;
127 Event->DataParam1 = LogEvent.DataParam1;
128 Event->DataParam2 = LogEvent.DataParam2;
129 Event->DataParam3 = LogEvent.DataParam3;
130 Event->DataParam4 = LogEvent.DataParam4;
132 AGESA_TESTPOINT (TpIfAmdReadEventLogExit, &Event->StdHeader);
137 /*---------------------------------------------------------------------------------------*/
140 * This function prepares the Event Log for use.
142 * Allocate the memory for an event log on the heap. Set the read pointer, write pointer,
143 * and count to reflect the log is empty.
145 * @param[in] StdHeader Our configuration, for passing to services.
147 * @retval AGESA_SUCCESS The event log is initialized.
148 * @retval AGESA_ERROR Allocate Heap Buffer returned an error.
152 EventLogInitialization (
153 IN AMD_CONFIG_PARAMS *StdHeader
156 ALLOCATE_HEAP_PARAMS AllocateHeapParams;
157 AGESA_STRUCT_BUFFER *AgesaEventAlloc;
160 AllocateHeapParams.BufferHandle = EVENT_LOG_BUFFER_HANDLE;
161 AllocateHeapParams.RequestedBufferSize = sizeof (AGESA_STRUCT_BUFFER);
162 AllocateHeapParams.Persist = HEAP_SYSTEM_MEM;
163 Status = HeapAllocateBuffer (&AllocateHeapParams, StdHeader);
164 AgesaEventAlloc = (AGESA_STRUCT_BUFFER *) AllocateHeapParams.BufferPtr;
165 AgesaEventAlloc->Count = 0;
166 AgesaEventAlloc->ReadRecordPtr = 0;
167 AgesaEventAlloc->WriteRecordPtr = 0;
168 AgesaEventAlloc->ReadWriteFlag = 1;
174 /*---------------------------------------------------------------------------------------*/
177 * This function logs AGESA events into the event log.
179 * It will put the information in a circular buffer consisting of 16 such log
180 * entries. If the buffer gets full, then the next event log entry will be written
181 * over the oldest event log entry.
183 * @param[in] EventClass The severity of the event, its associated AGESA_STATUS.
184 * @param[in] EventInfo Uniquely identifies the event.
185 * @param[in] DataParam1 Event specific additional data
186 * @param[in] DataParam2 Event specific additional data
187 * @param[in] DataParam3 Event specific additional data
188 * @param[in] DataParam4 Event specific additional data
189 * @param[in] StdHeader Header for library and services
194 IN AGESA_STATUS EventClass,
196 IN UINT32 DataParam1,
197 IN UINT32 DataParam2,
198 IN UINT32 DataParam3,
199 IN UINT32 DataParam4,
200 IN AMD_CONFIG_PARAMS *StdHeader
204 AGESA_STRUCT_BUFFER *AgesaEventAlloc;
206 IDS_HDT_CONSOLE (MAIN_FLOW, "\n * %s Event: %08x Data: %x, %x, %x, %x\n\n",
207 (EventClass == AGESA_FATAL) ? "FATAL" :
208 (EventClass == AGESA_CRITICAL) ? "CRITICAL" :
209 (EventClass == AGESA_ERROR) ? "ERROR" :
210 (EventClass == AGESA_WARNING) ? "WARNING" :
211 (EventClass == AGESA_ALERT) ? "ALERT" :
212 (EventClass == AGESA_BOUNDS_CHK) ? "BOUNDS_CHK" :
213 (EventClass == AGESA_UNSUPPORTED) ? "UNSUPPORTED" :
214 "SUCCESS", EventInfo, DataParam1, DataParam2, DataParam3, DataParam4);
216 AgesaEventAlloc = NULL;
217 GetEventLogHeapPointer (&AgesaEventAlloc, StdHeader);
218 ASSERT (AgesaEventAlloc != NULL);
219 Index = AgesaEventAlloc->WriteRecordPtr;
221 // Add the new event log data into a circular buffer
222 AgesaEventAlloc->AgesaEventStruct[Index].AgesaEvent.EventClass = EventClass;
223 AgesaEventAlloc->AgesaEventStruct[Index].AgesaEvent.EventInfo = EventInfo;
224 AgesaEventAlloc->AgesaEventStruct[Index].AgesaEvent.DataParam1 = DataParam1;
225 AgesaEventAlloc->AgesaEventStruct[Index].AgesaEvent.DataParam2 = DataParam2;
226 AgesaEventAlloc->AgesaEventStruct[Index].AgesaEvent.DataParam3 = DataParam3;
227 AgesaEventAlloc->AgesaEventStruct[Index].AgesaEvent.DataParam4 = DataParam4;
229 if ((AgesaEventAlloc->WriteRecordPtr == AgesaEventAlloc->ReadRecordPtr) &&
230 (AgesaEventAlloc->ReadWriteFlag == 0)) {
231 AgesaEventAlloc->WriteRecordPtr += 1;
232 AgesaEventAlloc->ReadRecordPtr += 1;
233 if (AgesaEventAlloc->WriteRecordPtr == TOTAL_EVENT_LOG_BUFFERS) {
234 AgesaEventAlloc->WriteRecordPtr = 0;
235 AgesaEventAlloc->ReadRecordPtr = 0;
238 AgesaEventAlloc->WriteRecordPtr += 1;
239 if (AgesaEventAlloc->WriteRecordPtr == TOTAL_EVENT_LOG_BUFFERS) {
240 AgesaEventAlloc->WriteRecordPtr = 0;
242 AgesaEventAlloc->ReadWriteFlag = 0;
244 AgesaEventAlloc->Count = AgesaEventAlloc->Count + 1;
246 if (AgesaEventAlloc->Count <= TOTAL_EVENT_LOG_BUFFERS) {
247 AgesaEventAlloc->AgesaEventStruct[Index].Count = Index;
252 /*---------------------------------------------------------------------------------------*/
255 * This function gets event logs from the circular buffer.
257 * It will read the oldest entry from the circular buffer and place that information to the structure
258 * pointed to by the parameter. The read pointers will be incremented to remove the entry from buffer
259 * so that a subsequent call will return the next entry from the buffer. If the buffer is empty the
260 * returned log event will have EventInfo zero, which is not a valid event id.
262 * @param[out] EventRecord The next log event.
263 * @param[in] StdHeader Header for library and services
265 * @retval AGESA_SUCCESS Always succeeds.
270 OUT AGESA_EVENT *EventRecord,
271 IN AMD_CONFIG_PARAMS *StdHeader
275 AGESA_STRUCT_BUFFER *AgesaEventAlloc;
277 AgesaEventAlloc = NULL;
279 GetEventLogHeapPointer (&AgesaEventAlloc, StdHeader);
280 ASSERT (AgesaEventAlloc != NULL);
282 if ((AgesaEventAlloc->ReadRecordPtr == AgesaEventAlloc->WriteRecordPtr) &&
283 (AgesaEventAlloc->ReadWriteFlag == 1)) {
284 // EventInfo == zero, means no more data.
285 LibAmdMemFill (EventRecord, 0, sizeof (AGESA_EVENT), StdHeader);
287 Index = AgesaEventAlloc->ReadRecordPtr;
288 EventRecord->EventClass = AgesaEventAlloc->AgesaEventStruct[Index].AgesaEvent.EventClass;
289 EventRecord->EventInfo = AgesaEventAlloc->AgesaEventStruct[Index].AgesaEvent.EventInfo;
290 EventRecord->DataParam1 = AgesaEventAlloc->AgesaEventStruct[Index].AgesaEvent.DataParam1;
291 EventRecord->DataParam2 = AgesaEventAlloc->AgesaEventStruct[Index].AgesaEvent.DataParam2;
292 EventRecord->DataParam3 = AgesaEventAlloc->AgesaEventStruct[Index].AgesaEvent.DataParam3;
293 EventRecord->DataParam4 = AgesaEventAlloc->AgesaEventStruct[Index].AgesaEvent.DataParam4;
294 if (AgesaEventAlloc->ReadRecordPtr == (TOTAL_EVENT_LOG_BUFFERS - 1)) {
295 AgesaEventAlloc->ReadRecordPtr = 0;
297 AgesaEventAlloc->ReadRecordPtr = AgesaEventAlloc->ReadRecordPtr + 1;
299 if (AgesaEventAlloc->ReadRecordPtr == AgesaEventAlloc->WriteRecordPtr) {
300 AgesaEventAlloc->ReadWriteFlag = 1;
303 return (AGESA_SUCCESS);
306 /*---------------------------------------------------------------------------------------*/
309 * This function gets event logs from the circular buffer without flushing the entry.
311 * It will read the desired entry from the circular buffer and place that information to the structure
312 * pointed to by the parameter. The read pointers will not be incremented to remove the entry from the
313 * buffer. If the buffer is empty, or the desired entry does not exist, FALSE will be returned.
315 * @param[out] EventRecord The next log event.
316 * @param[in] Index Zero-based unread entry index
317 * @param[in] StdHeader Header for library and services
319 * @retval TRUE Entry exists
320 * @retval FALSE Entry does not exist
325 OUT AGESA_EVENT *EventRecord,
327 IN AMD_CONFIG_PARAMS *StdHeader
331 UINT16 UnreadEntries;
332 AGESA_STRUCT_BUFFER *AgesaEventAlloc;
334 AgesaEventAlloc = NULL;
336 GetEventLogHeapPointer (&AgesaEventAlloc, StdHeader);
337 ASSERT (AgesaEventAlloc != NULL);
339 if ((AgesaEventAlloc->ReadRecordPtr == AgesaEventAlloc->WriteRecordPtr) &&
340 (AgesaEventAlloc->ReadWriteFlag == 1)) {
341 // EventInfo == zero, means no more data.
344 if (AgesaEventAlloc->ReadRecordPtr < AgesaEventAlloc->WriteRecordPtr) {
345 UnreadEntries = AgesaEventAlloc->WriteRecordPtr - AgesaEventAlloc->ReadRecordPtr;
347 UnreadEntries = TOTAL_EVENT_LOG_BUFFERS - (AgesaEventAlloc->ReadRecordPtr - AgesaEventAlloc->WriteRecordPtr);
349 if (Index >= UnreadEntries) {
352 ActualIndex = Index + AgesaEventAlloc->ReadRecordPtr;
353 if (ActualIndex >= TOTAL_EVENT_LOG_BUFFERS) {
354 ActualIndex -= TOTAL_EVENT_LOG_BUFFERS;
357 EventRecord->EventClass = AgesaEventAlloc->AgesaEventStruct[ActualIndex].AgesaEvent.EventClass;
358 EventRecord->EventInfo = AgesaEventAlloc->AgesaEventStruct[ActualIndex].AgesaEvent.EventInfo;
359 EventRecord->DataParam1 = AgesaEventAlloc->AgesaEventStruct[ActualIndex].AgesaEvent.DataParam1;
360 EventRecord->DataParam2 = AgesaEventAlloc->AgesaEventStruct[ActualIndex].AgesaEvent.DataParam2;
361 EventRecord->DataParam3 = AgesaEventAlloc->AgesaEventStruct[ActualIndex].AgesaEvent.DataParam3;
362 EventRecord->DataParam4 = AgesaEventAlloc->AgesaEventStruct[ActualIndex].AgesaEvent.DataParam4;
368 /*---------------------------------------------------------------------------------------*/
371 * This function gets the Event Log pointer.
373 * It will locate the Event Log on the heap using the heap locate service. If the Event
374 * Log is not located, NULL is returned.
376 * @param[out] EventLog Pointer to the Event Log, or NULL.
377 * @param[in] StdHeader Our Configuration, for passing to services.
382 GetEventLogHeapPointer (
383 OUT AGESA_STRUCT_BUFFER **EventLog,
384 IN AMD_CONFIG_PARAMS *StdHeader
387 LOCATE_HEAP_PTR LocateHeapStruct;
389 LocateHeapStruct.BufferHandle = EVENT_LOG_BUFFER_HANDLE;
390 LocateHeapStruct.BufferPtr = NULL;
391 if ((HeapLocateBuffer (&LocateHeapStruct, StdHeader)) == AGESA_SUCCESS) {
392 *EventLog = (AGESA_STRUCT_BUFFER *)LocateHeapStruct.BufferPtr;