From d4955f0ade18cafde4a3ea20885eb9fbdc5b4514 Mon Sep 17 00:00:00 2001 From: Kyösti Mälkki Date: Fri, 8 Sep 2017 07:14:17 +0300 Subject: AGESA: Move API interface under drivers/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit New AGESA support files will be used for binaryPI platforms as well. Furthermore, some of those should move from split nb/ sb/ directories to soc/, so move support files for the API under drivers/. Change-Id: I549788091de91f61de8b9adc223d52ffb5732235 Signed-off-by: Kyösti Mälkki Reviewed-on: https://review.coreboot.org/21455 Tested-by: build bot (Jenkins) Reviewed-by: Aaron Durbin --- src/drivers/amd/agesa/state_machine.c | 398 ++++++++++++++++++++++++++++++++++ 1 file changed, 398 insertions(+) create mode 100644 src/drivers/amd/agesa/state_machine.c (limited to 'src/drivers/amd/agesa/state_machine.c') diff --git a/src/drivers/amd/agesa/state_machine.c b/src/drivers/amd/agesa/state_machine.c new file mode 100644 index 0000000000..fdd2e6eeac --- /dev/null +++ b/src/drivers/amd/agesa/state_machine.c @@ -0,0 +1,398 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2011-2012 Advanced Micro Devices, Inc. + * Copyright (C) 2016 Kyösti Mälkki + * + * 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 +#include + +#include +#include +#include +#include + +#include +#include +#include +#include "amdlib.h" + +#include "AMD.h" + +#if IS_ENABLED(CONFIG_CPU_AMD_AGESA_OPENSOURCE) +#include "Dispatcher.h" +#endif + +#if ENV_ROMSTAGE +#include +CONST PSO_ENTRY ROMDATA DefaultPlatformMemoryConfiguration[] = {PSO_END}; +#endif + +static void agesa_locate_image(AMD_CONFIG_PARAMS *StdHeader) +{ +#if IS_ENABLED(CONFIG_CPU_AMD_AGESA_BINARY_PI) + const char ModuleIdentifier[] = AGESA_ID; + const void *agesa, *image; + size_t file_size; + + agesa = cbfs_boot_map_with_leak((const char *)CONFIG_AGESA_CBFS_NAME, + CBFS_TYPE_RAW, &file_size); + if (agesa == NULL) + return; + + image = LibAmdLocateImage(agesa, agesa + file_size, 4096, + ModuleIdentifier); + StdHeader->ImageBasePtr = (void*) image; +#endif +} + +void agesa_set_interface(struct sysinfo *cb) +{ + memset(&cb->StdHeader, 0, sizeof(AMD_CONFIG_PARAMS)); + + cb->StdHeader.CalloutPtr = GetBiosCallout; + + if (IS_ENABLED(CONFIG_CPU_AMD_AGESA_BINARY_PI)) { + agesa_locate_image(&cb->StdHeader); + AMD_IMAGE_HEADER *image = + (void*)(uintptr_t)cb->StdHeader.ImageBasePtr; + ASSERT(image); + AMD_MODULE_HEADER *module = + (void*)(uintptr_t)image->ModuleInfoOffset; + ASSERT(module && module->ModuleDispatcher); + } +} + +AGESA_STATUS module_dispatch(AGESA_STRUCT_NAME func, + AMD_CONFIG_PARAMS *StdHeader) +{ + MODULE_ENTRY dispatcher; + +#if IS_ENABLED(CONFIG_CPU_AMD_AGESA_OPENSOURCE) + dispatcher = AmdAgesaDispatcher; +#endif +#if IS_ENABLED(CONFIG_CPU_AMD_AGESA_BINARY_PI) + AMD_IMAGE_HEADER *image = (void*)(uintptr_t)StdHeader->ImageBasePtr; + AMD_MODULE_HEADER *module = (void*)(uintptr_t)image->ModuleInfoOffset; + dispatcher = module->ModuleDispatcher; +#endif + + StdHeader->Func = func; + return dispatcher(StdHeader); +} + +static AGESA_STATUS amd_create_struct(AMD_INTERFACE_PARAMS *aip, + AGESA_STRUCT_NAME func, void *buf, size_t len) +{ + aip->AgesaFunctionName = func; + aip->AllocationMethod = 0; + aip->NewStructPtr = buf; + aip->NewStructSize = len; + if (buf != NULL && len != 0) + aip->AllocationMethod = ByHost; + + return module_dispatch(AMD_CREATE_STRUCT, &aip->StdHeader); +} + +static AGESA_STATUS amd_release_struct(AMD_INTERFACE_PARAMS *aip) +{ + /* Cannot release AMD_LATE_PARAMS until ACPI tables are done. */ + if (aip->AgesaFunctionName == AMD_INIT_LATE) + return AGESA_SUCCESS; + + return module_dispatch(AMD_RELEASE_STRUCT, &aip->StdHeader); +} + +/* By design, for each valid AGESA_STRUCT_NAME, AMD_CONFIG_PARAMS + * can be evaluated to apply correct typecast based on Func field. + */ + +static AGESA_STATUS romstage_dispatch(struct sysinfo *cb, + AGESA_STRUCT_NAME func, AMD_CONFIG_PARAMS *StdHeader) +{ + AGESA_STATUS status = AGESA_UNSUPPORTED; + + switch (func) + { + case AMD_INIT_RESET: + { + AMD_RESET_PARAMS *param = (void *)StdHeader; + platform_BeforeInitReset(cb, param); + board_BeforeInitReset(cb, param); + status = module_dispatch(func, StdHeader); + break; + } + + case AMD_INIT_EARLY: + { + AMD_EARLY_PARAMS *param = (void *)StdHeader; + platform_BeforeInitEarly(cb, param); + board_BeforeInitEarly(cb, param); + status = module_dispatch(func, StdHeader); + break; + } + + case AMD_INIT_POST: + { + AMD_POST_PARAMS *param = (void *)StdHeader; + platform_BeforeInitPost(cb, param); + board_BeforeInitPost(cb, param); + status = module_dispatch(func, StdHeader); + platform_AfterInitPost(cb, param); + break; + } + + case AMD_INIT_RESUME: + { + AMD_RESUME_PARAMS *param = (void *)StdHeader; + platform_BeforeInitResume(cb, param); + status = module_dispatch(func, StdHeader); + platform_AfterInitResume(cb, param); + break; + } + + default: + { + break; + } + + } + return status; +} + +static AGESA_STATUS ramstage_dispatch(struct sysinfo *cb, + AGESA_STRUCT_NAME func, AMD_CONFIG_PARAMS *StdHeader) +{ + AGESA_STATUS status = AGESA_UNSUPPORTED; + + switch (func) + { + case AMD_INIT_ENV: + { + AMD_ENV_PARAMS *param = (void *)StdHeader; + platform_BeforeInitEnv(cb, param); + board_BeforeInitEnv(cb, param); + status = module_dispatch(func, StdHeader); + platform_AfterInitEnv(cb, param); + break; + } + + case AMD_S3LATE_RESTORE: + { + AMD_S3LATE_PARAMS *param = (void *)StdHeader; + platform_BeforeS3LateRestore(cb, param); + status = module_dispatch(func, StdHeader); + platform_AfterS3LateRestore(cb, param); + break; + } + + case AMD_INIT_MID: + { + AMD_MID_PARAMS *param = (void *)StdHeader; + platform_BeforeInitMid(cb, param); + board_BeforeInitMid(cb, param); + status = module_dispatch(func, StdHeader); + break; + } + + case AMD_S3_SAVE: + { + AMD_S3SAVE_PARAMS *param = (void *)StdHeader; + status = module_dispatch(func, StdHeader); + platform_AfterS3Save(cb, param); + break; + } + + case AMD_INIT_LATE: + { + AMD_LATE_PARAMS *param = (void *)StdHeader; + status = module_dispatch(func, StdHeader); + platform_AfterInitLate(cb, param); + completion_InitLate(cb, param); + break; + } + + default: + { + break; + } + + } + return status; +} + +/* DEBUG trace helper */ + +struct agesa_state +{ + u8 apic_id; + + AGESA_STRUCT_NAME func; + const char *function_name; +}; + +static void state_on_entry(struct agesa_state *task, AGESA_STRUCT_NAME func, + const char *struct_name) +{ + task->apic_id = (u8) (cpuid_ebx(1) >> 24); + task->func = func; + task->function_name = struct_name; + + printk(BIOS_DEBUG, "\nAPIC %02d: ** Enter %s [%08x]\n", + task->apic_id, task->function_name, task->func); +} + +static void 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); +} + +int agesa_execute_state(struct sysinfo *cb, AGESA_STRUCT_NAME func) +{ + AMD_INTERFACE_PARAMS aip; + union { + AMD_RESET_PARAMS reset; + AMD_S3LATE_PARAMS s3late; + } agesa_params; + void *buf = NULL; + size_t len = 0; + const char *state_name = agesa_struct_name(func); + + AGESA_STATUS status, final; + + struct agesa_state task; + memset(&task, 0, sizeof(task)); + state_on_entry(&task, func, state_name); + + aip.StdHeader = cb->StdHeader; + + /* For these calls, heap is not available. */ + if (func == AMD_INIT_RESET || func == AMD_S3LATE_RESTORE) { + buf = (void *) &agesa_params; + len = sizeof(agesa_params); + memcpy(buf, &cb->StdHeader, sizeof(cb->StdHeader)); + } + + status = amd_create_struct(&aip, func, buf, len); + ASSERT(status == AGESA_SUCCESS); + + /* Must call the function buffer was allocated for.*/ + AMD_CONFIG_PARAMS *StdHeader = aip.NewStructPtr; + ASSERT(StdHeader->Func == func); + + if (ENV_ROMSTAGE) + final = romstage_dispatch(cb, func, StdHeader); + + if (ENV_RAMSTAGE) + final = ramstage_dispatch(cb, func, StdHeader); + + agesawrapper_trace(final, StdHeader, state_name); + ASSERT(final < AGESA_FATAL); + + status = amd_release_struct(&aip); + ASSERT(status == AGESA_SUCCESS); + + state_on_exit(&task, &aip.StdHeader); + + return (final < AGESA_FATAL) ? 0 : -1; +} + +#if ENV_RAMSTAGE + +static void amd_bs_ramstage_init(void *arg) +{ + struct sysinfo *cb = arg; + + agesa_set_interface(cb); + + if (!acpi_is_wakeup_s3()) + agesa_execute_state(cb, AMD_INIT_ENV); + else { + agesa_execute_state(cb, AMD_S3LATE_RESTORE); + fchs3earlyrestore(&cb->StdHeader); + } +} + +void sb_After_Pci_Restore_Init(void); + +static void amd_bs_dev_enable(void *arg) +{ + struct sysinfo *cb = arg; + + if (!acpi_is_wakeup_s3()) + agesa_execute_state(cb, AMD_INIT_MID); + + /* FIXME */ + if (IS_ENABLED(CONFIG_AMD_SB_CIMX) && acpi_is_wakeup_s3()) + sb_After_Pci_Restore_Init(); +} + +static void amd_bs_post_device(void *arg) +{ + struct sysinfo *cb = arg; + + if (acpi_is_wakeup_s3()) { + fchs3laterestore(&cb->StdHeader); + return; + } + + agesa_execute_state(cb, AMD_INIT_LATE); + + if (!acpi_s3_resume_allowed()) + return; + + agesa_execute_state(cb, AMD_S3_SAVE); +} + +static struct sysinfo state_machine; + +BOOT_STATE_INIT_ENTRY(BS_PRE_DEVICE, BS_ON_ENTRY, amd_bs_ramstage_init, + &state_machine); + +BOOT_STATE_INIT_ENTRY(BS_DEV_ENABLE, BS_ON_ENTRY, amd_bs_dev_enable, + &state_machine); + +BOOT_STATE_INIT_ENTRY(BS_POST_DEVICE, BS_ON_EXIT, amd_bs_post_device, + &state_machine); + +#endif /* ENV_RAMSTAGE */ + +/* Empty stubs for cases board does not need to override anything. */ +void __attribute__((weak)) +board_BeforeInitReset(struct sysinfo *cb, AMD_RESET_PARAMS *Reset) { } +void __attribute__((weak)) +board_BeforeInitEarly(struct sysinfo *cb, AMD_EARLY_PARAMS *Early) { } +void __attribute__((weak)) +board_BeforeInitPost(struct sysinfo *cb, AMD_POST_PARAMS *Post) { } +void __attribute__((weak)) +board_BeforeInitEnv(struct sysinfo *cb, AMD_ENV_PARAMS *Env) { } +void __attribute__((weak)) +board_BeforeInitMid(struct sysinfo *cb, AMD_MID_PARAMS *Mid) { } + +AGESA_STATUS __attribute__((weak)) +fchs3earlyrestore(AMD_CONFIG_PARAMS *StdHeader) +{ + return AGESA_SUCCESS; +} + +AGESA_STATUS __attribute__((weak)) +fchs3laterestore(AMD_CONFIG_PARAMS *StdHeader) +{ + return AGESA_SUCCESS; +} -- cgit v1.2.3