blob: 7154c951552a6b1caefd4604cc9f5ab18d2a447f [file] [log] [blame]
/* SPDX-License-Identifier: GPL-2.0-only */
#include <cpu/x86/lapic.h>
#include <console/console.h>
#include <stdint.h>
#include <string.h>
#include <timestamp.h>
#include <northbridge/amd/agesa/state_machine.h>
#include <northbridge/amd/agesa/BiosCallOuts.h>
#include <amdlib.h>
#include <debug_util.h>
#include <AGESA.h>
#include <AMD.h>
static const char undefined[] = "undefined";
struct agesa_mapping
{
AGESA_STRUCT_NAME func;
const char *name;
uint32_t entry_id;
uint32_t exit_id;
};
static const struct agesa_mapping entrypoint[] = {
{
.func = AMD_INIT_RESET,
.name = "AmdInitReset",
.entry_id = TS_AGESA_INIT_RESET_START,
.exit_id = TS_AGESA_INIT_RESET_END,
},
{
.func = AMD_INIT_EARLY,
.name = "AmdInitEarly",
.entry_id = TS_AGESA_INIT_EARLY_START,
.exit_id = TS_AGESA_INIT_EARLY_END,
},
{
.func = AMD_INIT_POST,
.name = "AmdInitPost",
.entry_id = TS_AGESA_INIT_POST_START,
.exit_id = TS_AGESA_INIT_POST_END,
},
{
.func = AMD_INIT_RESUME,
.name = "AmdInitResume",
.entry_id = TS_AGESA_INIT_RESUME_START,
.exit_id = TS_AGESA_INIT_RESUME_END,
},
{
.func = AMD_INIT_ENV,
.name = "AmdInitEnv",
.entry_id = TS_AGESA_INIT_ENV_START,
.exit_id = TS_AGESA_INIT_ENV_END,
},
{
.func = AMD_INIT_MID,
.name = "AmdInitMid",
.entry_id = TS_AGESA_INIT_MID_START,
.exit_id = TS_AGESA_INIT_MID_END,
},
{
.func = AMD_INIT_LATE,
.name = "AmdInitLate",
.entry_id = TS_AGESA_INIT_LATE_START,
.exit_id = TS_AGESA_INIT_LATE_END,
},
{
.func = AMD_S3LATE_RESTORE,
.name = "AmdS3LateRestore",
.entry_id = TS_AGESA_S3_LATE_START,
.exit_id = TS_AGESA_S3_LATE_END,
},
#if !defined(AMD_S3_SAVE_REMOVED)
{
.func = AMD_S3_SAVE,
.name = "AmdS3Save",
.entry_id = TS_AGESA_INIT_RTB_START,
.exit_id = TS_AGESA_INIT_RTB_END,
},
#endif
{
.func = AMD_S3FINAL_RESTORE,
.name = "AmdS3FinalRestore",
.entry_id = TS_AGESA_S3_FINAL_START,
.exit_id = TS_AGESA_S3_FINAL_END,
},
{
.func = AMD_INIT_RTB,
.name = "AmdInitRtb",
.entry_id = TS_AGESA_INIT_RTB_START,
.exit_id = TS_AGESA_INIT_RTB_END,
},
};
void agesa_state_on_entry(struct agesa_state *task, AGESA_STRUCT_NAME func)
{
int i;
task->apic_id = (u8)initial_lapicid();
task->func = func;
task->function_name = undefined;
for (i = 0; i < ARRAY_SIZE(entrypoint); i++) {
if (task->func == entrypoint[i].func) {
task->function_name = entrypoint[i].name;
task->ts_entry_id = entrypoint[i].entry_id;
task->ts_exit_id = entrypoint[i].exit_id;
break;
}
}
printk(BIOS_DEBUG, "\nAPIC %02d: ** Enter %s [%08x]\n",
task->apic_id, task->function_name, task->func);
}
void agesa_state_on_exit(struct agesa_state *task,
AMD_CONFIG_PARAMS *StdHeader)
{
printk(BIOS_DEBUG, "APIC %02d: Heap in %s (%d) at 0x%08x\n",
task->apic_id, heap_status_name(StdHeader->HeapStatus),
StdHeader->HeapStatus, (u32)StdHeader->HeapBasePtr);
printk(BIOS_DEBUG, "APIC %02d: ** Exit %s [%08x]\n",
task->apic_id, task->function_name, task->func);
}
/*
* 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;
status = module_dispatch(AMD_READ_EVENT_LOG, &Event->StdHeader);
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));
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;
}