blob: 841c39f815b7109f9ca991466ee2a76476d73927 [file] [log] [blame]
Frank Vibrans2b4c8312011-02-14 18:30:54 +00001/* $NoKeywords:$ */
2/**
3 * @file
4 *
5 * AMD Event (Error) Log APIs, and related functions.
6 *
7 * Contains code that records and returns the events and errors.
8 *
9 * @xrefitem bom "File Content Label" "Release Content"
10 * @e project: AGESA
11 * @e sub-project: CPU
12 * @e \$Revision: 35136 $ @e \$Date: 2010-07-16 11:29:48 +0800 (Fri, 16 Jul 2010) $
13 *
14 */
15/*
16 *****************************************************************************
17 *
18 * Copyright (c) 2011, Advanced Micro Devices, Inc.
19 * All rights reserved.
Edward O'Callaghan1542a6f2014-07-06 19:24:06 +100020 *
Frank Vibrans2b4c8312011-02-14 18:30:54 +000021 * Redistribution and use in source and binary forms, with or without
22 * modification, are permitted provided that the following conditions are met:
23 * * Redistributions of source code must retain the above copyright
24 * notice, this list of conditions and the following disclaimer.
25 * * Redistributions in binary form must reproduce the above copyright
26 * notice, this list of conditions and the following disclaimer in the
27 * documentation and/or other materials provided with the distribution.
Edward O'Callaghan1542a6f2014-07-06 19:24:06 +100028 * * Neither the name of Advanced Micro Devices, Inc. nor the names of
29 * its contributors may be used to endorse or promote products derived
Frank Vibrans2b4c8312011-02-14 18:30:54 +000030 * from this software without specific prior written permission.
Edward O'Callaghan1542a6f2014-07-06 19:24:06 +100031 *
Frank Vibrans2b4c8312011-02-14 18:30:54 +000032 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
33 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
34 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
35 * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
36 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
37 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
38 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
39 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
40 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
41 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Edward O'Callaghan1542a6f2014-07-06 19:24:06 +100042 *
Frank Vibrans2b4c8312011-02-14 18:30:54 +000043 * ***************************************************************************
44 *
45 */
46
47/*----------------------------------------------------------------------------------------
48 * M O D U L E S U S E D
49 *----------------------------------------------------------------------------------------
50 */
51
52#include "AGESA.h"
53#include "amdlib.h"
54#include "heapManager.h"
55#include "GeneralServices.h"
56#include "Ids.h"
57#include "Filecode.h"
58CODE_GROUP (G1_PEICC)
59RDATA_GROUP (G1_PEICC)
60
61#define FILECODE PROC_CPU_CPUEVENTLOG_FILECODE
62/*----------------------------------------------------------------------------------------
63 * D E F I N I T I O N S A N D M A C R O S
64 *----------------------------------------------------------------------------------------
65 */
66#define TOTAL_EVENT_LOG_BUFFERS 16
67
68/*----------------------------------------------------------------------------------------
69 * T Y P E D E F S A N D S T R U C T U R E S
70 *----------------------------------------------------------------------------------------
71 */
72
73/**
74 * A wrapper for each Event Log entry.
75 */
76typedef struct {
77 UINT16 Count; ///< Entry number
78 AGESA_EVENT AgesaEvent; ///< The entry itself.
79} AGESA_EVENT_STRUCT;
80
81/**
82 * The Event Log.
83 */
84typedef struct {
85 UINT16 ReadWriteFlag; ///< Read Write flag.
86 UINT16 Count; ///< The total number of active entries.
87 UINT16 ReadRecordPtr; ///< The next entry to read.
88 UINT16 WriteRecordPtr; ///< The next entry to write.
89 AGESA_EVENT_STRUCT AgesaEventStruct[TOTAL_EVENT_LOG_BUFFERS]; ///< The entries.
90} AGESA_STRUCT_BUFFER;
91
92/*----------------------------------------------------------------------------------------
93 * 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
94 *----------------------------------------------------------------------------------------
95 */
96VOID
97STATIC
98GetEventLogHeapPointer (
99 OUT AGESA_STRUCT_BUFFER **EventLog,
100 IN AMD_CONFIG_PARAMS *StdHeader
101 );
102
103/*---------------------------------------------------------------------------------------*/
104/**
105 * External AGESA interface to read an Event from the Event Log.
106 *
107 * This is the implementation of the external AGESA interface entry, as a thin wrapper
108 * around the internal log services.
109 *
110 * @param[in] Event The event class, id, and any associated data.
111 *
112 * @retval AGESA_SUCCESS Always Succeeds.
113 */
114AGESA_STATUS
115AmdReadEventLog (
116 IN EVENT_PARAMS *Event
117 )
118{
119 AGESA_EVENT LogEvent;
120 AGESA_STATUS Status;
121
122 AGESA_TESTPOINT (TpIfAmdReadEventLogEntry, &Event->StdHeader);
123
124 ASSERT (Event != NULL);
125 Event->StdHeader.HeapBasePtr = HeapGetBaseAddress (&Event->StdHeader);
126 Status = GetEventLog (&LogEvent, &Event->StdHeader);
Kyösti Mälkkibfa72ce2017-03-02 13:52:54 +0200127 if (Status != AGESA_SUCCESS)
128 return Status;
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000129
130 Event->EventClass = LogEvent.EventClass;
131 Event->EventInfo = LogEvent.EventInfo;
132 Event->DataParam1 = LogEvent.DataParam1;
133 Event->DataParam2 = LogEvent.DataParam2;
134 Event->DataParam3 = LogEvent.DataParam3;
135 Event->DataParam4 = LogEvent.DataParam4;
136
137 AGESA_TESTPOINT (TpIfAmdReadEventLogExit, &Event->StdHeader);
138 return Status;
139}
140
141
142/*---------------------------------------------------------------------------------------*/
143/**
144 *
145 * This function prepares the Event Log for use.
146 *
147 * Allocate the memory for an event log on the heap. Set the read pointer, write pointer,
148 * and count to reflect the log is empty.
149 *
150 * @param[in] StdHeader Our configuration, for passing to services.
151 *
152 * @retval AGESA_SUCCESS The event log is initialized.
153 * @retval AGESA_ERROR Allocate Heap Buffer returned an error.
154 *
155 */
156AGESA_STATUS
157EventLogInitialization (
158 IN AMD_CONFIG_PARAMS *StdHeader
159 )
160{
161 ALLOCATE_HEAP_PARAMS AllocateHeapParams;
162 AGESA_STRUCT_BUFFER *AgesaEventAlloc;
163 AGESA_STATUS Status;
164
165 AllocateHeapParams.BufferHandle = EVENT_LOG_BUFFER_HANDLE;
166 AllocateHeapParams.RequestedBufferSize = sizeof (AGESA_STRUCT_BUFFER);
167 AllocateHeapParams.Persist = HEAP_SYSTEM_MEM;
168 Status = HeapAllocateBuffer (&AllocateHeapParams, StdHeader);
169 AgesaEventAlloc = (AGESA_STRUCT_BUFFER *) AllocateHeapParams.BufferPtr;
170 AgesaEventAlloc->Count = 0;
171 AgesaEventAlloc->ReadRecordPtr = 0;
172 AgesaEventAlloc->WriteRecordPtr = 0;
173 AgesaEventAlloc->ReadWriteFlag = 1;
174
175 return Status;
176}
177
178
179/*---------------------------------------------------------------------------------------*/
180/**
181 *
182 * This function logs AGESA events into the event log.
183 *
184 * It will put the information in a circular buffer consisting of 16 such log
185 * entries. If the buffer gets full, then the next event log entry will be written
186 * over the oldest event log entry.
187 *
188 * @param[in] EventClass The severity of the event, its associated AGESA_STATUS.
189 * @param[in] EventInfo Uniquely identifies the event.
190 * @param[in] DataParam1 Event specific additional data
191 * @param[in] DataParam2 Event specific additional data
192 * @param[in] DataParam3 Event specific additional data
193 * @param[in] DataParam4 Event specific additional data
194 * @param[in] StdHeader Header for library and services
195 *
196 */
197VOID
198PutEventLog (
199 IN AGESA_STATUS EventClass,
200 IN UINT32 EventInfo,
201 IN UINT32 DataParam1,
202 IN UINT32 DataParam2,
203 IN UINT32 DataParam3,
204 IN UINT32 DataParam4,
205 IN AMD_CONFIG_PARAMS *StdHeader
206 )
207{
208 UINT16 Index;
209 AGESA_STRUCT_BUFFER *AgesaEventAlloc;
210
211 IDS_HDT_CONSOLE (MAIN_FLOW, "\n * %s Event: %08x Data: %x, %x, %x, %x\n\n",
212 (EventClass == AGESA_FATAL) ? "FATAL" :
213 (EventClass == AGESA_CRITICAL) ? "CRITICAL" :
214 (EventClass == AGESA_ERROR) ? "ERROR" :
215 (EventClass == AGESA_WARNING) ? "WARNING" :
216 (EventClass == AGESA_ALERT) ? "ALERT" :
217 (EventClass == AGESA_BOUNDS_CHK) ? "BOUNDS_CHK" :
218 (EventClass == AGESA_UNSUPPORTED) ? "UNSUPPORTED" :
219 "SUCCESS", EventInfo, DataParam1, DataParam2, DataParam3, DataParam4);
220
Kyösti Mälkki4f74c892017-03-02 13:53:21 +0200221 if (EventClass < AGESA_STATUS_LOG_LEVEL)
222 return;
223
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000224 AgesaEventAlloc = NULL;
225 GetEventLogHeapPointer (&AgesaEventAlloc, StdHeader);
226 ASSERT (AgesaEventAlloc != NULL);
Kyösti Mälkkibfa72ce2017-03-02 13:52:54 +0200227 if (AgesaEventAlloc == NULL)
228 return;
229
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000230 Index = AgesaEventAlloc->WriteRecordPtr;
231
232 // Add the new event log data into a circular buffer
233 AgesaEventAlloc->AgesaEventStruct[Index].AgesaEvent.EventClass = EventClass;
234 AgesaEventAlloc->AgesaEventStruct[Index].AgesaEvent.EventInfo = EventInfo;
235 AgesaEventAlloc->AgesaEventStruct[Index].AgesaEvent.DataParam1 = DataParam1;
236 AgesaEventAlloc->AgesaEventStruct[Index].AgesaEvent.DataParam2 = DataParam2;
237 AgesaEventAlloc->AgesaEventStruct[Index].AgesaEvent.DataParam3 = DataParam3;
238 AgesaEventAlloc->AgesaEventStruct[Index].AgesaEvent.DataParam4 = DataParam4;
239
240 if ((AgesaEventAlloc->WriteRecordPtr == AgesaEventAlloc->ReadRecordPtr) &&
241 (AgesaEventAlloc->ReadWriteFlag == 0)) {
242 AgesaEventAlloc->WriteRecordPtr += 1;
243 AgesaEventAlloc->ReadRecordPtr += 1;
244 if (AgesaEventAlloc->WriteRecordPtr == TOTAL_EVENT_LOG_BUFFERS) {
245 AgesaEventAlloc->WriteRecordPtr = 0;
246 AgesaEventAlloc->ReadRecordPtr = 0;
247 }
248 } else {
249 AgesaEventAlloc->WriteRecordPtr += 1;
250 if (AgesaEventAlloc->WriteRecordPtr == TOTAL_EVENT_LOG_BUFFERS) {
251 AgesaEventAlloc->WriteRecordPtr = 0;
252 }
253 AgesaEventAlloc->ReadWriteFlag = 0;
254 }
255 AgesaEventAlloc->Count = AgesaEventAlloc->Count + 1;
256
257 if (AgesaEventAlloc->Count <= TOTAL_EVENT_LOG_BUFFERS) {
258 AgesaEventAlloc->AgesaEventStruct[Index].Count = Index;
259 }
260}
261
262
263/*---------------------------------------------------------------------------------------*/
264/**
265 *
266 * This function gets event logs from the circular buffer.
267 *
268 * It will read the oldest entry from the circular buffer and place that information to the structure
269 * pointed to by the parameter. The read pointers will be incremented to remove the entry from buffer
270 * so that a subsequent call will return the next entry from the buffer. If the buffer is empty the
271 * returned log event will have EventInfo zero, which is not a valid event id.
272 *
273 * @param[out] EventRecord The next log event.
274 * @param[in] StdHeader Header for library and services
275 *
276 * @retval AGESA_SUCCESS Always succeeds.
277 *
278 */
279AGESA_STATUS
280GetEventLog (
281 OUT AGESA_EVENT *EventRecord,
282 IN AMD_CONFIG_PARAMS *StdHeader
283 )
284{
285 UINT16 Index;
286 AGESA_STRUCT_BUFFER *AgesaEventAlloc;
287
288 AgesaEventAlloc = NULL;
289
290 GetEventLogHeapPointer (&AgesaEventAlloc, StdHeader);
291 ASSERT (AgesaEventAlloc != NULL);
Kyösti Mälkkibfa72ce2017-03-02 13:52:54 +0200292 if (AgesaEventAlloc == NULL)
293 return AGESA_BOUNDS_CHK;
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000294
295 if ((AgesaEventAlloc->ReadRecordPtr == AgesaEventAlloc->WriteRecordPtr) &&
296 (AgesaEventAlloc->ReadWriteFlag == 1)) {
297 // EventInfo == zero, means no more data.
298 LibAmdMemFill (EventRecord, 0, sizeof (AGESA_EVENT), StdHeader);
299 } else {
300 Index = AgesaEventAlloc->ReadRecordPtr;
301 EventRecord->EventClass = AgesaEventAlloc->AgesaEventStruct[Index].AgesaEvent.EventClass;
302 EventRecord->EventInfo = AgesaEventAlloc->AgesaEventStruct[Index].AgesaEvent.EventInfo;
303 EventRecord->DataParam1 = AgesaEventAlloc->AgesaEventStruct[Index].AgesaEvent.DataParam1;
304 EventRecord->DataParam2 = AgesaEventAlloc->AgesaEventStruct[Index].AgesaEvent.DataParam2;
305 EventRecord->DataParam3 = AgesaEventAlloc->AgesaEventStruct[Index].AgesaEvent.DataParam3;
306 EventRecord->DataParam4 = AgesaEventAlloc->AgesaEventStruct[Index].AgesaEvent.DataParam4;
307 if (AgesaEventAlloc->ReadRecordPtr == (TOTAL_EVENT_LOG_BUFFERS - 1)) {
308 AgesaEventAlloc->ReadRecordPtr = 0;
309 } else {
310 AgesaEventAlloc->ReadRecordPtr = AgesaEventAlloc->ReadRecordPtr + 1;
311 }
312 if (AgesaEventAlloc->ReadRecordPtr == AgesaEventAlloc->WriteRecordPtr) {
313 AgesaEventAlloc->ReadWriteFlag = 1;
314 }
315 }
316 return (AGESA_SUCCESS);
317}
318
319/*---------------------------------------------------------------------------------------*/
320/**
321 *
322 * This function gets event logs from the circular buffer without flushing the entry.
323 *
324 * It will read the desired entry from the circular buffer and place that information to the structure
325 * pointed to by the parameter. The read pointers will not be incremented to remove the entry from the
326 * buffer. If the buffer is empty, or the desired entry does not exist, FALSE will be returned.
327 *
328 * @param[out] EventRecord The next log event.
329 * @param[in] Index Zero-based unread entry index
330 * @param[in] StdHeader Header for library and services
331 *
332 * @retval TRUE Entry exists
333 * @retval FALSE Entry does not exist
334 *
335 */
336BOOLEAN
337PeekEventLog (
338 OUT AGESA_EVENT *EventRecord,
339 IN UINT16 Index,
340 IN AMD_CONFIG_PARAMS *StdHeader
341 )
342{
343 UINT16 ActualIndex;
344 UINT16 UnreadEntries;
345 AGESA_STRUCT_BUFFER *AgesaEventAlloc;
346
347 AgesaEventAlloc = NULL;
348
349 GetEventLogHeapPointer (&AgesaEventAlloc, StdHeader);
350 ASSERT (AgesaEventAlloc != NULL);
Kyösti Mälkkibfa72ce2017-03-02 13:52:54 +0200351 if (AgesaEventAlloc == NULL)
352 return FALSE;
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000353
354 if ((AgesaEventAlloc->ReadRecordPtr == AgesaEventAlloc->WriteRecordPtr) &&
355 (AgesaEventAlloc->ReadWriteFlag == 1)) {
356 // EventInfo == zero, means no more data.
357 return FALSE;
358 }
359 if (AgesaEventAlloc->ReadRecordPtr < AgesaEventAlloc->WriteRecordPtr) {
360 UnreadEntries = AgesaEventAlloc->WriteRecordPtr - AgesaEventAlloc->ReadRecordPtr;
361 } else {
362 UnreadEntries = TOTAL_EVENT_LOG_BUFFERS - (AgesaEventAlloc->ReadRecordPtr - AgesaEventAlloc->WriteRecordPtr);
363 }
364 if (Index >= UnreadEntries) {
365 return FALSE;
366 }
367 ActualIndex = Index + AgesaEventAlloc->ReadRecordPtr;
368 if (ActualIndex >= TOTAL_EVENT_LOG_BUFFERS) {
369 ActualIndex -= TOTAL_EVENT_LOG_BUFFERS;
370 }
371
372 EventRecord->EventClass = AgesaEventAlloc->AgesaEventStruct[ActualIndex].AgesaEvent.EventClass;
373 EventRecord->EventInfo = AgesaEventAlloc->AgesaEventStruct[ActualIndex].AgesaEvent.EventInfo;
374 EventRecord->DataParam1 = AgesaEventAlloc->AgesaEventStruct[ActualIndex].AgesaEvent.DataParam1;
375 EventRecord->DataParam2 = AgesaEventAlloc->AgesaEventStruct[ActualIndex].AgesaEvent.DataParam2;
376 EventRecord->DataParam3 = AgesaEventAlloc->AgesaEventStruct[ActualIndex].AgesaEvent.DataParam3;
377 EventRecord->DataParam4 = AgesaEventAlloc->AgesaEventStruct[ActualIndex].AgesaEvent.DataParam4;
378
379 return TRUE;
380}
381
382
383/*---------------------------------------------------------------------------------------*/
384/**
385 *
386 * This function gets the Event Log pointer.
387 *
388 * It will locate the Event Log on the heap using the heap locate service. If the Event
389 * Log is not located, NULL is returned.
390 *
391 * @param[out] EventLog Pointer to the Event Log, or NULL.
392 * @param[in] StdHeader Our Configuration, for passing to services.
393 *
394 */
395VOID
396STATIC
397GetEventLogHeapPointer (
398 OUT AGESA_STRUCT_BUFFER **EventLog,
399 IN AMD_CONFIG_PARAMS *StdHeader
400 )
401{
402 LOCATE_HEAP_PTR LocateHeapStruct;
403
404 LocateHeapStruct.BufferHandle = EVENT_LOG_BUFFER_HANDLE;
405 LocateHeapStruct.BufferPtr = NULL;
406 if ((HeapLocateBuffer (&LocateHeapStruct, StdHeader)) == AGESA_SUCCESS) {
407 *EventLog = (AGESA_STRUCT_BUFFER *)LocateHeapStruct.BufferPtr;
408 } else {
409 *EventLog = NULL;
410 }
411}