xref: /aosp_15_r20/external/coreboot/src/drivers/amd/agesa/state_machine.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <stdint.h>
4 #include <string.h>
5 #include <acpi/acpi.h>
6 #include <bootstate.h>
7 #include <cbfs.h>
8 #include <timestamp.h>
9 
10 #include <northbridge/amd/agesa/state_machine.h>
11 #include <northbridge/amd/agesa/agesa_helper.h>
12 #include <northbridge/amd/agesa/BiosCallOuts.h>
13 #include <amdlib.h>
14 
15 #include <AMD.h>
16 
17 #if ENV_RAMINIT
18 #include <PlatformMemoryConfiguration.h>
19 CONST PSO_ENTRY ROMDATA DefaultPlatformMemoryConfiguration[] = {PSO_END};
20 #endif
21 
agesa_locate_image(AMD_CONFIG_PARAMS * StdHeader)22 static void agesa_locate_image(AMD_CONFIG_PARAMS *StdHeader)
23 {
24 	const char ModuleIdentifier[] = AGESA_ID;
25 	const void *agesa, *image;
26 	size_t file_size;
27 
28 	agesa = cbfs_map((const char *)CONFIG_AGESA_CBFS_NAME, &file_size);
29 	if (agesa == NULL)
30 		return;
31 
32 	image = LibAmdLocateImage(agesa, agesa + file_size, 4096,
33 		ModuleIdentifier);
34 	StdHeader->ImageBasePtr = (void *)image;
35 }
36 
agesa_set_interface(struct sysinfo * cb)37 void agesa_set_interface(struct sysinfo *cb)
38 {
39 	memset(&cb->StdHeader, 0, sizeof(AMD_CONFIG_PARAMS));
40 
41 	cb->StdHeader.CalloutPtr = GetBiosCallout;
42 
43 	agesa_locate_image(&cb->StdHeader);
44 	AMD_IMAGE_HEADER *image =
45 		(void *)(uintptr_t)cb->StdHeader.ImageBasePtr;
46 	ASSERT(image);
47 	AMD_MODULE_HEADER *module =
48 		(void *)(uintptr_t)image->ModuleInfoOffset;
49 	ASSERT(module && module->ModuleDispatcher);
50 }
51 
module_dispatch(AGESA_STRUCT_NAME func,AMD_CONFIG_PARAMS * StdHeader)52 AGESA_STATUS module_dispatch(AGESA_STRUCT_NAME func,
53 	AMD_CONFIG_PARAMS *StdHeader)
54 {
55 	MODULE_ENTRY dispatcher;
56 
57 	AMD_IMAGE_HEADER *image = (void *)(uintptr_t)StdHeader->ImageBasePtr;
58 	AMD_MODULE_HEADER *module = (void *)(uintptr_t)image->ModuleInfoOffset;
59 	dispatcher = module->ModuleDispatcher;
60 
61 	StdHeader->Func = func;
62 	return dispatcher(StdHeader);
63 }
64 
amd_create_struct(AMD_INTERFACE_PARAMS * aip,AGESA_STRUCT_NAME func,void * buf,size_t len)65 static AGESA_STATUS amd_create_struct(AMD_INTERFACE_PARAMS *aip,
66 	AGESA_STRUCT_NAME func, void *buf, size_t len)
67 {
68 	aip->AgesaFunctionName = func;
69 	aip->AllocationMethod = 0;
70 	aip->NewStructPtr = buf;
71 	aip->NewStructSize = len;
72 	if (buf != NULL && len != 0)
73 		aip->AllocationMethod = ByHost;
74 
75 	return module_dispatch(AMD_CREATE_STRUCT, &aip->StdHeader);
76 }
77 
amd_release_struct(AMD_INTERFACE_PARAMS * aip)78 static AGESA_STATUS amd_release_struct(AMD_INTERFACE_PARAMS *aip)
79 {
80 	/* Cannot release AMD_LATE_PARAMS until ACPI tables are done. */
81 	if (aip->AgesaFunctionName == AMD_INIT_LATE)
82 		return AGESA_SUCCESS;
83 
84 	return module_dispatch(AMD_RELEASE_STRUCT, &aip->StdHeader);
85 }
86 
87 /* By design, for each valid AGESA_STRUCT_NAME, AMD_CONFIG_PARAMS
88  * can be evaluated to apply correct typecast based on Func field.
89  */
90 
romstage_dispatch(struct sysinfo * cb,AGESA_STRUCT_NAME func,AMD_CONFIG_PARAMS * StdHeader)91 static AGESA_STATUS romstage_dispatch(struct sysinfo *cb,
92 	AGESA_STRUCT_NAME func, AMD_CONFIG_PARAMS *StdHeader)
93 {
94 	AGESA_STATUS status = AGESA_UNSUPPORTED;
95 
96 	switch (func)
97 	{
98 		case AMD_INIT_RESET:
99 		{
100 			AMD_RESET_PARAMS *param = (void *)StdHeader;
101 			platform_BeforeInitReset(cb, param);
102 			board_BeforeInitReset(cb, param);
103 			status = module_dispatch(func, StdHeader);
104 			break;
105 		}
106 
107 		case AMD_INIT_EARLY:
108 		{
109 			AMD_EARLY_PARAMS *param = (void *)StdHeader;
110 			platform_BeforeInitEarly(cb, param);
111 			board_BeforeInitEarly(cb, param);
112 			status = module_dispatch(func, StdHeader);
113 			break;
114 		}
115 
116 		case AMD_INIT_POST:
117 		{
118 			AMD_POST_PARAMS *param = (void *)StdHeader;
119 			platform_BeforeInitPost(cb, param);
120 			board_BeforeInitPost(cb, param);
121 			status = module_dispatch(func, StdHeader);
122 
123 			/* FIXME: Detect if TSC frequency really
124 			 * changed during raminit? */
125 			timestamp_rescale_table(1, 4);
126 
127 			platform_AfterInitPost(cb, param);
128 			break;
129 		}
130 
131 		case AMD_INIT_RESUME:
132 		{
133 			AMD_RESUME_PARAMS *param = (void *)StdHeader;
134 			platform_BeforeInitResume(cb, param);
135 			status = module_dispatch(func, StdHeader);
136 
137 			/* FIXME: Detect if TSC frequency really
138 			 * changed during raminit? */
139 			timestamp_rescale_table(1, 4);
140 
141 			platform_AfterInitResume(cb, param);
142 			break;
143 		}
144 
145 		default:
146 		{
147 			break;
148 		}
149 	}
150 	return status;
151 }
152 
ramstage_dispatch(struct sysinfo * cb,AGESA_STRUCT_NAME func,AMD_CONFIG_PARAMS * StdHeader)153 static AGESA_STATUS ramstage_dispatch(struct sysinfo *cb,
154 	AGESA_STRUCT_NAME func, AMD_CONFIG_PARAMS *StdHeader)
155 {
156 	AGESA_STATUS status = AGESA_UNSUPPORTED;
157 
158 	switch (func)
159 	{
160 		case AMD_INIT_ENV:
161 		{
162 			AMD_ENV_PARAMS *param = (void *)StdHeader;
163 			platform_BeforeInitEnv(cb, param);
164 			board_BeforeInitEnv(cb, param);
165 			status = module_dispatch(func, StdHeader);
166 			platform_AfterInitEnv(cb, param);
167 			break;
168 		}
169 
170 		case AMD_S3LATE_RESTORE:
171 		{
172 			AMD_S3LATE_PARAMS *param = (void *)StdHeader;
173 			platform_BeforeS3LateRestore(cb, param);
174 			status = module_dispatch(func, StdHeader);
175 			platform_AfterS3LateRestore(cb, param);
176 			break;
177 		}
178 
179 		case AMD_INIT_MID:
180 		{
181 			AMD_MID_PARAMS *param = (void *)StdHeader;
182 			platform_BeforeInitMid(cb, param);
183 			board_BeforeInitMid(cb, param);
184 			status = module_dispatch(func, StdHeader);
185 			break;
186 		}
187 
188 		case AMD_S3_SAVE:
189 		{
190 			AMD_S3SAVE_PARAMS *param = (void *)StdHeader;
191 			status = module_dispatch(func, StdHeader);
192 			platform_AfterS3Save(cb, param);
193 			break;
194 		}
195 
196 		case AMD_INIT_LATE:
197 		{
198 			AMD_LATE_PARAMS *param = (void *)StdHeader;
199 			platform_BeforeInitLate(cb, param);
200 			board_BeforeInitLate(cb, param);
201 			status = module_dispatch(func, StdHeader);
202 			platform_AfterInitLate(cb, param);
203 			completion_InitLate(cb, param);
204 			break;
205 		}
206 
207 		default:
208 		{
209 			break;
210 		}
211 	}
212 	return status;
213 }
214 
agesa_execute_state(struct sysinfo * cb,AGESA_STRUCT_NAME func)215 int agesa_execute_state(struct sysinfo *cb, AGESA_STRUCT_NAME func)
216 {
217 	AMD_INTERFACE_PARAMS aip;
218 	union {
219 		AMD_RESET_PARAMS reset;
220 		AMD_S3LATE_PARAMS s3late;
221 	} agesa_params;
222 	void *buf = NULL;
223 	size_t len = 0;
224 
225 	AGESA_STATUS status, final;
226 
227 	struct agesa_state task;
228 	memset(&task, 0, sizeof(task));
229 	agesa_state_on_entry(&task, func);
230 
231 	aip.StdHeader = cb->StdHeader;
232 
233 	/* For these calls, heap is not available. */
234 	if (func == AMD_INIT_RESET || func == AMD_S3LATE_RESTORE) {
235 		buf = (void *)&agesa_params;
236 		len = sizeof(agesa_params);
237 		memcpy(buf, &cb->StdHeader, sizeof(cb->StdHeader));
238 	}
239 
240 	status = amd_create_struct(&aip, func, buf, len);
241 	ASSERT(status == AGESA_SUCCESS);
242 
243 	/* Must call the function buffer was allocated for.*/
244 	AMD_CONFIG_PARAMS *StdHeader = aip.NewStructPtr;
245 	ASSERT(StdHeader != NULL && StdHeader->Func == func);
246 
247 	if (CONFIG(AGESA_EXTRA_TIMESTAMPS) && task.ts_entry_id)
248 		timestamp_add_now(task.ts_entry_id);
249 
250 	if (ENV_RAMINIT)
251 		final = romstage_dispatch(cb, func, StdHeader);
252 
253 	if (ENV_RAMSTAGE)
254 		final = ramstage_dispatch(cb, func, StdHeader);
255 
256 	if (CONFIG(AGESA_EXTRA_TIMESTAMPS) && task.ts_exit_id)
257 		timestamp_add_now(task.ts_exit_id);
258 
259 	agesawrapper_trace(final, StdHeader, task.function_name);
260 	ASSERT(final < AGESA_FATAL);
261 
262 	status = amd_release_struct(&aip);
263 	ASSERT(status == AGESA_SUCCESS);
264 
265 	agesa_state_on_exit(&task, &aip.StdHeader);
266 
267 	return (final < AGESA_FATAL) ? 0 : -1;
268 }
269 
270 #if ENV_RAMSTAGE
271 
amd_bs_ramstage_init(void * arg)272 static void amd_bs_ramstage_init(void *arg)
273 {
274 	struct sysinfo *cb = arg;
275 
276 	agesa_set_interface(cb);
277 
278 	if (!acpi_is_wakeup_s3())
279 		agesa_execute_state(cb, AMD_INIT_ENV);
280 	else {
281 		agesa_execute_state(cb, AMD_S3LATE_RESTORE);
282 		fchs3earlyrestore(&cb->StdHeader);
283 	}
284 }
285 
286 void sb_After_Pci_Restore_Init(void);
287 
amd_bs_dev_enable(void * arg)288 static void amd_bs_dev_enable(void *arg)
289 {
290 	struct sysinfo *cb = arg;
291 
292 	if (!acpi_is_wakeup_s3())
293 		agesa_execute_state(cb, AMD_INIT_MID);
294 }
295 
amd_bs_post_device(void * arg)296 static void amd_bs_post_device(void *arg)
297 {
298 	struct sysinfo *cb = arg;
299 
300 	if (acpi_is_wakeup_s3()) {
301 		fchs3laterestore(&cb->StdHeader);
302 		return;
303 	}
304 
305 	agesa_execute_state(cb, AMD_INIT_LATE);
306 
307 	if (!acpi_s3_resume_allowed())
308 		return;
309 
310 	agesa_execute_state(cb, AMD_S3_SAVE);
311 }
312 
313 static struct sysinfo state_machine;
314 
315 BOOT_STATE_INIT_ENTRY(BS_PRE_DEVICE, BS_ON_ENTRY, amd_bs_ramstage_init,
316 	&state_machine);
317 
318 BOOT_STATE_INIT_ENTRY(BS_DEV_ENABLE, BS_ON_ENTRY, amd_bs_dev_enable,
319 	&state_machine);
320 
321 BOOT_STATE_INIT_ENTRY(BS_POST_DEVICE, BS_ON_EXIT, amd_bs_post_device,
322 	&state_machine);
323 
324 #endif /* ENV_RAMSTAGE */
325 
326 /* Empty stubs for cases board does not need to override anything. */
327 void __weak
board_BeforeInitReset(struct sysinfo * cb,AMD_RESET_PARAMS * Reset)328 board_BeforeInitReset(struct sysinfo *cb, AMD_RESET_PARAMS *Reset) { }
329 void __weak
board_BeforeInitEarly(struct sysinfo * cb,AMD_EARLY_PARAMS * Early)330 board_BeforeInitEarly(struct sysinfo *cb, AMD_EARLY_PARAMS *Early) { }
331 void __weak
board_BeforeInitPost(struct sysinfo * cb,AMD_POST_PARAMS * Post)332 board_BeforeInitPost(struct sysinfo *cb, AMD_POST_PARAMS *Post) { }
333 void __weak
board_BeforeInitEnv(struct sysinfo * cb,AMD_ENV_PARAMS * Env)334 board_BeforeInitEnv(struct sysinfo *cb, AMD_ENV_PARAMS *Env) { }
335 void __weak
board_BeforeInitMid(struct sysinfo * cb,AMD_MID_PARAMS * Mid)336 board_BeforeInitMid(struct sysinfo *cb, AMD_MID_PARAMS *Mid) { }
337 void __weak
board_BeforeInitLate(struct sysinfo * cb,AMD_LATE_PARAMS * Late)338 board_BeforeInitLate(struct sysinfo *cb, AMD_LATE_PARAMS *Late) { }
339 
340 AGESA_STATUS __weak
fchs3earlyrestore(AMD_CONFIG_PARAMS * StdHeader)341 fchs3earlyrestore(AMD_CONFIG_PARAMS *StdHeader)
342 {
343 	return AGESA_SUCCESS;
344 }
345 
346 AGESA_STATUS __weak
fchs3laterestore(AMD_CONFIG_PARAMS * StdHeader)347 fchs3laterestore(AMD_CONFIG_PARAMS *StdHeader)
348 {
349 	return AGESA_SUCCESS;
350 }
351