1 /* SPDX-License-Identifier: GPL-2.0-only */
2
3 #include <cpu/x86/lapic.h>
4 #include <console/console.h>
5 #include <stdint.h>
6 #include <string.h>
7 #include <timestamp.h>
8
9 #include <northbridge/amd/agesa/state_machine.h>
10 #include <northbridge/amd/agesa/BiosCallOuts.h>
11 #include <amdlib.h>
12 #include <debug_util.h>
13 #include <AGESA.h>
14 #include <AMD.h>
15
16 static const char undefined[] = "undefined";
17
18 struct agesa_mapping
19 {
20 AGESA_STRUCT_NAME func;
21 const char *name;
22 uint32_t entry_id;
23 uint32_t exit_id;
24 };
25
26 static const struct agesa_mapping entrypoint[] = {
27 {
28 .func = AMD_INIT_RESET,
29 .name = "AmdInitReset",
30 .entry_id = TS_AGESA_INIT_RESET_START,
31 .exit_id = TS_AGESA_INIT_RESET_END,
32 },
33 {
34 .func = AMD_INIT_EARLY,
35 .name = "AmdInitEarly",
36 .entry_id = TS_AGESA_INIT_EARLY_START,
37 .exit_id = TS_AGESA_INIT_EARLY_END,
38 },
39 {
40 .func = AMD_INIT_POST,
41 .name = "AmdInitPost",
42 .entry_id = TS_AGESA_INIT_POST_START,
43 .exit_id = TS_AGESA_INIT_POST_END,
44 },
45 {
46 .func = AMD_INIT_RESUME,
47 .name = "AmdInitResume",
48 .entry_id = TS_AGESA_INIT_RESUME_START,
49 .exit_id = TS_AGESA_INIT_RESUME_END,
50 },
51 {
52 .func = AMD_INIT_ENV,
53 .name = "AmdInitEnv",
54 .entry_id = TS_AGESA_INIT_ENV_START,
55 .exit_id = TS_AGESA_INIT_ENV_END,
56 },
57 {
58 .func = AMD_INIT_MID,
59 .name = "AmdInitMid",
60 .entry_id = TS_AGESA_INIT_MID_START,
61 .exit_id = TS_AGESA_INIT_MID_END,
62 },
63 {
64 .func = AMD_INIT_LATE,
65 .name = "AmdInitLate",
66 .entry_id = TS_AGESA_INIT_LATE_START,
67 .exit_id = TS_AGESA_INIT_LATE_END,
68 },
69 {
70 .func = AMD_S3LATE_RESTORE,
71 .name = "AmdS3LateRestore",
72 .entry_id = TS_AGESA_S3_LATE_START,
73 .exit_id = TS_AGESA_S3_LATE_END,
74 },
75 #if !defined(AMD_S3_SAVE_REMOVED)
76 {
77 .func = AMD_S3_SAVE,
78 .name = "AmdS3Save",
79 .entry_id = TS_AGESA_INIT_RTB_START,
80 .exit_id = TS_AGESA_INIT_RTB_END,
81 },
82 #endif
83 {
84 .func = AMD_S3FINAL_RESTORE,
85 .name = "AmdS3FinalRestore",
86 .entry_id = TS_AGESA_S3_FINAL_START,
87 .exit_id = TS_AGESA_S3_FINAL_END,
88 },
89 {
90 .func = AMD_INIT_RTB,
91 .name = "AmdInitRtb",
92 .entry_id = TS_AGESA_INIT_RTB_START,
93 .exit_id = TS_AGESA_INIT_RTB_END,
94 },
95 };
96
agesa_state_on_entry(struct agesa_state * task,AGESA_STRUCT_NAME func)97 void agesa_state_on_entry(struct agesa_state *task, AGESA_STRUCT_NAME func)
98 {
99 int i;
100
101 task->apic_id = (u8)initial_lapicid();
102 task->func = func;
103 task->function_name = undefined;
104
105 for (i = 0; i < ARRAY_SIZE(entrypoint); i++) {
106 if (task->func == entrypoint[i].func) {
107 task->function_name = entrypoint[i].name;
108 task->ts_entry_id = entrypoint[i].entry_id;
109 task->ts_exit_id = entrypoint[i].exit_id;
110 break;
111 }
112 }
113
114 printk(BIOS_DEBUG, "\nAPIC %02d: ** Enter %s [%08x]\n",
115 task->apic_id, task->function_name, task->func);
116 }
117
agesa_state_on_exit(struct agesa_state * task,AMD_CONFIG_PARAMS * StdHeader)118 void agesa_state_on_exit(struct agesa_state *task,
119 AMD_CONFIG_PARAMS *StdHeader)
120 {
121 printk(BIOS_DEBUG, "APIC %02d: Heap in %s (%d) at 0x%08x\n",
122 task->apic_id, heap_status_name(StdHeader->HeapStatus),
123 StdHeader->HeapStatus, (u32)StdHeader->HeapBasePtr);
124
125 printk(BIOS_DEBUG, "APIC %02d: ** Exit %s [%08x]\n",
126 task->apic_id, task->function_name, task->func);
127 }
128
129 /*
130 * Possible AGESA_STATUS values:
131 *
132 * 0x0 = AGESA_SUCCESS
133 * 0x1 = AGESA_UNSUPPORTED
134 * 0x2 = AGESA_BOUNDS_CHK
135 * 0x3 = AGESA_ALERT
136 * 0x4 = AGESA_WARNING
137 * 0x5 = AGESA_ERROR
138 * 0x6 = AGESA_CRITICAL
139 * 0x7 = AGESA_FATAL
140 */
decodeAGESA_STATUS(AGESA_STATUS sret)141 static const char *decodeAGESA_STATUS(AGESA_STATUS sret)
142 {
143 const char *statusStrings[] = { "AGESA_SUCCESS", "AGESA_UNSUPPORTED",
144 "AGESA_BOUNDS_CHK", "AGESA_ALERT",
145 "AGESA_WARNING", "AGESA_ERROR",
146 "AGESA_CRITICAL", "AGESA_FATAL"
147 };
148 if (sret > 7) return "unknown"; /* Non-AGESA error code */
149 return statusStrings[sret];
150 }
151
show_event(EVENT_PARAMS * Event)152 static void show_event(EVENT_PARAMS *Event)
153 {
154 printk(BIOS_DEBUG, "\nEventLog: EventClass = %x, EventInfo = %x.\n",
155 (unsigned int)Event->EventClass,
156 (unsigned int)Event->EventInfo);
157 printk(BIOS_DEBUG, " Param1 = %x, Param2 = %x.\n",
158 (unsigned int)Event->DataParam1,
159 (unsigned int)Event->DataParam2);
160 printk(BIOS_DEBUG, " Param3 = %x, Param4 = %x.\n",
161 (unsigned int)Event->DataParam3,
162 (unsigned int)Event->DataParam4);
163 }
164
165 #define MAX_LOG_ENTRIES 100
166
amd_flush_eventlog(EVENT_PARAMS * Event)167 static void amd_flush_eventlog(EVENT_PARAMS *Event)
168 {
169 int i = 0;
170
171 do {
172 AGESA_STATUS status;
173 status = module_dispatch(AMD_READ_EVENT_LOG, &Event->StdHeader);
174 if (status != AGESA_SUCCESS)
175 return;
176 if (Event->EventClass == 0)
177 return;
178 show_event(Event);
179 } while (++i < MAX_LOG_ENTRIES);
180 }
181
agesawrapper_trace(AGESA_STATUS ret,AMD_CONFIG_PARAMS * StdHeader,const char * func)182 void agesawrapper_trace(AGESA_STATUS ret, AMD_CONFIG_PARAMS *StdHeader,
183 const char *func)
184 {
185 EVENT_PARAMS AmdEventParams;
186
187 printk(BIOS_DEBUG, "%s() returned %s\n", func, decodeAGESA_STATUS(ret));
188 if (ret == AGESA_SUCCESS)
189 return;
190
191 memset(&AmdEventParams, 0, sizeof(EVENT_PARAMS));
192 memcpy(&AmdEventParams.StdHeader, StdHeader, sizeof(*StdHeader));
193
194 amd_flush_eventlog(&AmdEventParams);
195 }
196
agesawrapper_amdreadeventlog(UINT8 HeapStatus)197 AGESA_STATUS agesawrapper_amdreadeventlog(UINT8 HeapStatus)
198 {
199 EVENT_PARAMS AmdEventParams;
200
201 memset(&AmdEventParams, 0, sizeof(EVENT_PARAMS));
202
203 AmdEventParams.StdHeader.AltImageBasePtr = 0;
204 AmdEventParams.StdHeader.CalloutPtr = &GetBiosCallout;
205 AmdEventParams.StdHeader.Func = 0;
206 AmdEventParams.StdHeader.ImageBasePtr = 0;
207 AmdEventParams.StdHeader.HeapStatus = HeapStatus;
208
209 amd_flush_eventlog(&AmdEventParams);
210
211 return AGESA_SUCCESS;
212 }
213