| /* |
| * This file is part of the coreboot project. |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation; version 2 of the License. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| */ |
| |
| #include <console/console.h> |
| #include <stdint.h> |
| #include <string.h> |
| |
| #include <northbridge/amd/agesa/state_machine.h> |
| #include <northbridge/amd/agesa/BiosCallOuts.h> |
| #include "amdlib.h" |
| #include "AGESA.h" |
| #include "AMD.h" |
| |
| #include <heapManager.h> |
| |
| static const char undefined[] = "undefined"; |
| |
| /* Match order of enum AGESA_STRUCT_NAME. */ |
| static const char *AgesaFunctionNameStr[] = { |
| "AmdInitRecovery", "AmdCreateStruct", "AmdInitEarly", "AmdInitEnv", "AmdInitLate", |
| "AmdInitMid", "AmdInitPost", "AmdInitReset", "AmdInitResume", "AmdReleaseStruct", |
| "AmdS3LateRestore","AmdS3Save", "AmdGetApicId", "AmdGetPciAddress", "AmdIdentifyCore", |
| "AmdReadEventLog", "AmdGetAvailableExeCacheSize", "AmdLateRunApTask", "AmdIdentifyDimm", |
| }; |
| |
| /* heapManager.h */ |
| static const char *HeapStatusStr[] = { |
| "DoNotExistYet", "LocalCache", "TempMem", "SystemMem", "DoNotExistAnymore","S3Resume" |
| }; |
| |
| /* This function has to match with enumeration of AGESA_STRUCT_NAME defined |
| * inside AMD.h header file. Unfortunately those are different across |
| * different vendorcode subtrees. |
| * |
| * TBD: Fix said header or move this function together with the strings above |
| * under vendorcode/ tree. |
| */ |
| |
| const char *agesa_struct_name(int state) |
| { |
| #if IS_ENABLED(CONFIG_CPU_AMD_AGESA_OPENSOURCE) |
| if ((state < AMD_INIT_RECOVERY) || (state > AMD_IDENTIFY_DIMMS)) |
| return undefined; |
| |
| int index = state - AMD_INIT_RECOVERY; |
| #else |
| state >>= 12; |
| if ((state < AMD_INIT_RECOVERY >> 12) || (state > AMD_IDENTIFY_DIMMS >> 12)) |
| return undefined; |
| |
| int index = state - (AMD_INIT_RECOVERY >> 12); |
| #endif |
| return AgesaFunctionNameStr[index]; |
| } |
| |
| const char *heap_status_name(int status) |
| { |
| if ((status < HEAP_DO_NOT_EXIST_YET) || (status > HEAP_S3_RESUME)) |
| return undefined; |
| |
| int index = status - HEAP_DO_NOT_EXIST_YET; |
| return HeapStatusStr[index]; |
| } |
| |
| /* |
| * Possible AGESA_STATUS values: |
| * |
| * 0x0 = AGESA_SUCCESS |
| * 0x1 = AGESA_UNSUPPORTED |
| * 0x2 = AGESA_BOUNDS_CHK |
| * 0x3 = AGESA_ALERT |
| * 0x4 = AGESA_WARNING |
| * 0x5 = AGESA_ERROR |
| * 0x6 = AGESA_CRITICAL |
| * 0x7 = AGESA_FATAL |
| */ |
| static const char * decodeAGESA_STATUS(AGESA_STATUS sret) |
| { |
| const char* statusStrings[] = { "AGESA_SUCCESS", "AGESA_UNSUPPORTED", |
| "AGESA_BOUNDS_CHK", "AGESA_ALERT", |
| "AGESA_WARNING", "AGESA_ERROR", |
| "AGESA_CRITICAL", "AGESA_FATAL" |
| }; |
| if (sret > 7) return "unknown"; /* Non-AGESA error code */ |
| return statusStrings[sret]; |
| } |
| |
| static void show_event(EVENT_PARAMS *Event) |
| { |
| printk(BIOS_DEBUG,"\nEventLog: EventClass = %x, EventInfo = %x.\n", |
| (unsigned int)Event->EventClass, |
| (unsigned int)Event->EventInfo); |
| printk(BIOS_DEBUG," Param1 = %x, Param2 = %x.\n", |
| (unsigned int)Event->DataParam1, |
| (unsigned int)Event->DataParam2); |
| printk(BIOS_DEBUG," Param3 = %x, Param4 = %x.\n", |
| (unsigned int)Event->DataParam3, |
| (unsigned int)Event->DataParam4); |
| } |
| |
| #define MAX_LOG_ENTRIES 100 |
| |
| static void amd_flush_eventlog(EVENT_PARAMS *Event) |
| { |
| int i = 0; |
| |
| do { |
| AGESA_STATUS status; |
| #if HAS_LEGACY_WRAPPER |
| status = AmdReadEventLog(Event); |
| #else |
| status = module_dispatch(AMD_READ_EVENT_LOG, &Event->StdHeader); |
| #endif |
| if (status != AGESA_SUCCESS) |
| return; |
| if (Event->EventClass == 0) |
| return; |
| show_event(Event); |
| } while (++i < MAX_LOG_ENTRIES); |
| } |
| |
| void agesawrapper_trace(AGESA_STATUS ret, AMD_CONFIG_PARAMS *StdHeader, |
| const char *func) |
| { |
| EVENT_PARAMS AmdEventParams; |
| |
| printk(BIOS_DEBUG, "%s() returned %s\n", func, decodeAGESA_STATUS(ret)); |
| if (ret == AGESA_SUCCESS) |
| return; |
| |
| memset(&AmdEventParams, 0, sizeof(EVENT_PARAMS)); |
| |
| if (HAS_LEGACY_WRAPPER) { |
| AmdEventParams.StdHeader.AltImageBasePtr = 0; |
| AmdEventParams.StdHeader.CalloutPtr = &GetBiosCallout; |
| AmdEventParams.StdHeader.Func = 0; |
| AmdEventParams.StdHeader.ImageBasePtr = 0; |
| AmdEventParams.StdHeader.HeapStatus = StdHeader->HeapStatus; |
| } else { |
| memcpy(&AmdEventParams.StdHeader, StdHeader, sizeof(*StdHeader)); |
| } |
| |
| amd_flush_eventlog(&AmdEventParams); |
| } |
| |
| AGESA_STATUS agesawrapper_amdreadeventlog (UINT8 HeapStatus) |
| { |
| EVENT_PARAMS AmdEventParams; |
| |
| memset(&AmdEventParams, 0, sizeof(EVENT_PARAMS)); |
| |
| AmdEventParams.StdHeader.AltImageBasePtr = 0; |
| AmdEventParams.StdHeader.CalloutPtr = &GetBiosCallout; |
| AmdEventParams.StdHeader.Func = 0; |
| AmdEventParams.StdHeader.ImageBasePtr = 0; |
| AmdEventParams.StdHeader.HeapStatus = HeapStatus; |
| |
| amd_flush_eventlog(&AmdEventParams); |
| |
| return AGESA_SUCCESS; |
| } |