[coreboot-gerrit] Patch set updated for coreboot: AGESA: Introduce AGESA_LEGACY_WRAPPER and its counterpart

Kyösti Mälkki (kyosti.malkki@gmail.com) gerrit at coreboot.org
Tue Mar 7 18:05:15 CET 2017


Kyösti Mälkki (kyosti.malkki at gmail.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/18628

-gerrit

commit dc44d84863c930e60ca5ee52b3473a9552e65ba1
Author: Kyösti Mälkki <kyosti.malkki at gmail.com>
Date:   Fri Nov 25 11:21:02 2016 +0200

    AGESA: Introduce AGESA_LEGACY_WRAPPER and its counterpart
    
    We define AGESA_LEGACY_WRAPPER a method of calling AGESA
    via functions in agesawrapper.c file. The approach implemented
    there makes it very inconvenient to do board-specific
    customisation or present common platform-specific features.
    Seems like it also causes assertion errors on AGESA side.
    The flag is applied here to all boards and then individually
    removed one at a time, as things get tested.
    
    New method is not to call AGESA internal functions directly,
    but via the dispatcher. AGESA call parameters are routed to
    hooks in both platform and board -directories, to allow for
    easy capture or modification as needed.
    
    For each AGESA dispatcher call made, eventlog entries are
    replayed to the console log. Also relocations of AGESA heap
    that took place are recorded.
    
    New method is expected to be compatible with binaryPI.
    
    Change-Id: Iac3d7f8b0354e9f02c2625576f36fe06b05eb4ce
    Signed-off-by: Kyösti Mälkki <kyosti.malkki at gmail.com>
---
 src/cpu/amd/agesa/Kconfig                          |   4 +
 src/cpu/amd/agesa/Makefile.inc                     |   2 +-
 src/cpu/amd/agesa/romstage.c                       |  26 +-
 src/mainboard/amd/olivehill/Kconfig                |   1 +
 src/mainboard/asrock/e350m1/Kconfig                |   1 +
 src/mainboard/asrock/imb-a180/Kconfig              |   1 +
 src/mainboard/asus/f2a85-m/Kconfig                 |   1 +
 src/mainboard/bap/ode_e20XX/Kconfig                |   1 +
 src/mainboard/elmex/pcm205400/Kconfig              |   1 +
 src/mainboard/gizmosphere/gizmo/Kconfig            |   1 +
 src/mainboard/lenovo/g505s/Kconfig                 |   1 +
 src/mainboard/msi/ms7721/Kconfig                   |   1 +
 src/mainboard/pcengines/apu1/Kconfig               |   1 +
 src/northbridge/amd/agesa/Makefile.inc             |  12 +-
 src/northbridge/amd/agesa/agesawrapper.c           |   1 +
 src/northbridge/amd/agesa/agesawrapper.h           |  18 +-
 src/northbridge/amd/agesa/def_callouts.c           |   2 +-
 src/northbridge/amd/agesa/family12/Makefile.inc    |   5 +
 src/northbridge/amd/agesa/family12/northbridge.c   |   4 +
 src/northbridge/amd/agesa/family12/state_machine.c |  90 +++++
 src/northbridge/amd/agesa/family14/Makefile.inc    |   5 +
 src/northbridge/amd/agesa/family14/northbridge.c   |  10 +-
 src/northbridge/amd/agesa/family14/state_machine.c |  86 +++++
 src/northbridge/amd/agesa/family15/Makefile.inc    |   3 +
 src/northbridge/amd/agesa/family15/northbridge.c   |   4 +-
 src/northbridge/amd/agesa/family15/state_machine.c |  78 +++++
 src/northbridge/amd/agesa/family15rl/Makefile.inc  |   5 +
 src/northbridge/amd/agesa/family15rl/northbridge.c |   3 +
 .../amd/agesa/family15rl/state_machine.c           |  84 +++++
 src/northbridge/amd/agesa/family15tn/Makefile.inc  |   5 +
 src/northbridge/amd/agesa/family15tn/northbridge.c |   3 +
 .../amd/agesa/family15tn/state_machine.c           |  84 +++++
 src/northbridge/amd/agesa/family16kb/Makefile.inc  |   5 +
 src/northbridge/amd/agesa/family16kb/northbridge.c |   3 +
 .../amd/agesa/family16kb/state_machine.c           |  84 +++++
 src/northbridge/amd/agesa/oem_s3.c                 |   1 +
 src/northbridge/amd/agesa/state_machine.c          | 372 +++++++++++++++++++++
 src/northbridge/amd/agesa/state_machine.h          |  46 +++
 src/southbridge/amd/agesa/hudson/Makefile.inc      |   2 +-
 39 files changed, 1043 insertions(+), 14 deletions(-)

diff --git a/src/cpu/amd/agesa/Kconfig b/src/cpu/amd/agesa/Kconfig
index cd14975..e43d4b0 100644
--- a/src/cpu/amd/agesa/Kconfig
+++ b/src/cpu/amd/agesa/Kconfig
@@ -37,6 +37,10 @@ if CPU_AMD_AGESA
 config AGESA_LEGACY
 	def_bool n
 
+config AGESA_LEGACY_WRAPPER
+	bool
+	default AGESA_LEGACY
+
 config AGESA_NO_LEGACY
 	bool
 	default !AGESA_LEGACY
diff --git a/src/cpu/amd/agesa/Makefile.inc b/src/cpu/amd/agesa/Makefile.inc
index 19f7975..b5bb8d9 100644
--- a/src/cpu/amd/agesa/Makefile.inc
+++ b/src/cpu/amd/agesa/Makefile.inc
@@ -32,7 +32,7 @@ endif
 
 romstage-y += heapmanager.c
 ramstage-y += heapmanager.c
-ramstage-y += amd_late_init.c
+ramstage-$(CONFIG_AGESA_LEGACY_WRAPPER) += amd_late_init.c
 
 ifeq ($(CONFIG_HAVE_ACPI_RESUME), y)
 
diff --git a/src/cpu/amd/agesa/romstage.c b/src/cpu/amd/agesa/romstage.c
index 922371a..802d8ae 100644
--- a/src/cpu/amd/agesa/romstage.c
+++ b/src/cpu/amd/agesa/romstage.c
@@ -30,6 +30,9 @@ static void fill_sysinfo(struct sysinfo *cb)
 {
 	memset(cb, 0, sizeof(*cb));
 	cb->s3resume = acpi_is_wakeup_s3();
+
+	if (!IS_ENABLED(CONFIG_AGESA_LEGACY_WRAPPER))
+		agesa_set_interface(cb);
 }
 
 void * asmlinkage romstage_main(unsigned long bist)
@@ -54,7 +57,21 @@ void * asmlinkage romstage_main(unsigned long bist)
 	post_code(0x34);
 	report_bist_failure(bist);
 
-	agesa_main(cb);
+	if (!IS_ENABLED(CONFIG_AGESA_LEGACY_WRAPPER)) {
+		agesa_execute_state(cb, AMD_INIT_RESET);
+
+		agesa_execute_state(cb, AMD_INIT_EARLY);
+
+		if (!cb->s3resume)
+			agesa_execute_state(cb, AMD_INIT_POST);
+		else
+			agesa_execute_state(cb, AMD_INIT_RESUME);
+
+	} else {
+
+		agesa_main(cb);
+
+	}
 
 	uintptr_t stack_top = CACHE_TMP_RAMTOP;
 	if (cb->s3resume) {
@@ -80,6 +97,13 @@ void asmlinkage romstage_after_car(void)
 
 	fill_sysinfo(cb);
 
+	if (!IS_ENABLED(CONFIG_AGESA_LEGACY_WRAPPER)) {
+		if (!cb->s3resume)
+			agesa_execute_state(cb, AMD_INIT_ENV);
+		else
+			agesa_execute_state(cb, AMD_S3LATE_RESTORE);
+	}
+
 	if (cb->s3resume)
 		set_resume_cache();
 
diff --git a/src/mainboard/amd/olivehill/Kconfig b/src/mainboard/amd/olivehill/Kconfig
index 37fb43f..462d221 100644
--- a/src/mainboard/amd/olivehill/Kconfig
+++ b/src/mainboard/amd/olivehill/Kconfig
@@ -17,6 +17,7 @@ if BOARD_AMD_OLIVEHILL
 
 config BOARD_SPECIFIC_OPTIONS # dummy
 	def_bool y
+	select AGESA_LEGACY_WRAPPER
 	select CPU_AMD_AGESA_FAMILY16_KB
 	select NORTHBRIDGE_AMD_AGESA_FAMILY16_KB
 	select SOUTHBRIDGE_AMD_AGESA_YANGTZE
diff --git a/src/mainboard/asrock/e350m1/Kconfig b/src/mainboard/asrock/e350m1/Kconfig
index 1c53212..8dc53ae 100644
--- a/src/mainboard/asrock/e350m1/Kconfig
+++ b/src/mainboard/asrock/e350m1/Kconfig
@@ -17,6 +17,7 @@ if BOARD_ASROCK_E350M1
 
 config BOARD_SPECIFIC_OPTIONS # dummy
 	def_bool y
+	select AGESA_LEGACY_WRAPPER
 	select CPU_AMD_AGESA_FAMILY14
 	select NORTHBRIDGE_AMD_AGESA_FAMILY14
 	select SOUTHBRIDGE_AMD_CIMX_SB800
diff --git a/src/mainboard/asrock/imb-a180/Kconfig b/src/mainboard/asrock/imb-a180/Kconfig
index e118bfb..c50ea46 100644
--- a/src/mainboard/asrock/imb-a180/Kconfig
+++ b/src/mainboard/asrock/imb-a180/Kconfig
@@ -17,6 +17,7 @@ if BOARD_ASROCK_IMB_A180
 
 config BOARD_SPECIFIC_OPTIONS # dummy
 	def_bool y
+	select AGESA_LEGACY_WRAPPER
 	select CPU_AMD_AGESA_FAMILY16_KB
 	select NORTHBRIDGE_AMD_AGESA_FAMILY16_KB
 	select SOUTHBRIDGE_AMD_AGESA_YANGTZE
diff --git a/src/mainboard/asus/f2a85-m/Kconfig b/src/mainboard/asus/f2a85-m/Kconfig
index f3b2d7d..651c107 100644
--- a/src/mainboard/asus/f2a85-m/Kconfig
+++ b/src/mainboard/asus/f2a85-m/Kconfig
@@ -18,6 +18,7 @@ if BOARD_ASUS_F2A85_M || BOARD_ASUS_F2A85_M_PRO || BOARD_ASUS_F2A85_M_LE
 
 config BOARD_SPECIFIC_OPTIONS # dummy
 	def_bool y
+	select AGESA_LEGACY_WRAPPER
 	select CPU_AMD_AGESA_FAMILY15_TN
 	select NORTHBRIDGE_AMD_AGESA_FAMILY15_TN
 	select SOUTHBRIDGE_AMD_AGESA_HUDSON
diff --git a/src/mainboard/bap/ode_e20XX/Kconfig b/src/mainboard/bap/ode_e20XX/Kconfig
index 6631ac8..ea9fec5 100644
--- a/src/mainboard/bap/ode_e20XX/Kconfig
+++ b/src/mainboard/bap/ode_e20XX/Kconfig
@@ -18,6 +18,7 @@ if BOARD_ODE_E20XX
 
 config BOARD_SPECIFIC_OPTIONS # dummy
 	def_bool y
+	select AGESA_LEGACY_WRAPPER
 	select CPU_AMD_AGESA_FAMILY16_KB
 	select NORTHBRIDGE_AMD_AGESA_FAMILY16_KB
 	select SOUTHBRIDGE_AMD_AGESA_YANGTZE
diff --git a/src/mainboard/elmex/pcm205400/Kconfig b/src/mainboard/elmex/pcm205400/Kconfig
index a901301..9da780c 100644
--- a/src/mainboard/elmex/pcm205400/Kconfig
+++ b/src/mainboard/elmex/pcm205400/Kconfig
@@ -29,6 +29,7 @@ if BOARD_ELMEX_PCM205400 || BOARD_ELMEX_PCM205401
 
 config BOARD_SPECIFIC_OPTIONS # dummy
 	def_bool y
+	select AGESA_LEGACY_WRAPPER
 	select CPU_AMD_AGESA_FAMILY14
 	select NORTHBRIDGE_AMD_AGESA_FAMILY14
 	select SOUTHBRIDGE_AMD_CIMX_SB800
diff --git a/src/mainboard/gizmosphere/gizmo/Kconfig b/src/mainboard/gizmosphere/gizmo/Kconfig
index 4177b1d..766b3b9 100644
--- a/src/mainboard/gizmosphere/gizmo/Kconfig
+++ b/src/mainboard/gizmosphere/gizmo/Kconfig
@@ -18,6 +18,7 @@ if BOARD_GIZMOSPHERE_GIZMO
 
 config BOARD_SPECIFIC_OPTIONS # dummy
 	def_bool y
+	select AGESA_LEGACY_WRAPPER
 	select CPU_AMD_AGESA_FAMILY14
 	select NORTHBRIDGE_AMD_AGESA_FAMILY14
 	select SOUTHBRIDGE_AMD_CIMX_SB800
diff --git a/src/mainboard/lenovo/g505s/Kconfig b/src/mainboard/lenovo/g505s/Kconfig
index aac3a84..07dbd1f 100644
--- a/src/mainboard/lenovo/g505s/Kconfig
+++ b/src/mainboard/lenovo/g505s/Kconfig
@@ -18,6 +18,7 @@ if BOARD_LENOVO_G505S
 config BOARD_SPECIFIC_OPTIONS # dummy
 	def_bool y
 	select SYSTEM_TYPE_LAPTOP
+	select AGESA_LEGACY_WRAPPER
 	select CPU_AMD_AGESA_FAMILY15_RL
 	select NORTHBRIDGE_AMD_AGESA_FAMILY15_RL
 	select SOUTHBRIDGE_AMD_AGESA_HUDSON
diff --git a/src/mainboard/msi/ms7721/Kconfig b/src/mainboard/msi/ms7721/Kconfig
index 7a2623b..8187dbe 100644
--- a/src/mainboard/msi/ms7721/Kconfig
+++ b/src/mainboard/msi/ms7721/Kconfig
@@ -20,6 +20,7 @@ if BOARD_MSI_MS7721
 
 config BOARD_SPECIFIC_OPTIONS # dummy
 	def_bool y
+	select AGESA_LEGACY_WRAPPER
 	select CPU_AMD_AGESA_FAMILY15_TN
 	select NORTHBRIDGE_AMD_AGESA_FAMILY15_TN
 	select SOUTHBRIDGE_AMD_AGESA_HUDSON
diff --git a/src/mainboard/pcengines/apu1/Kconfig b/src/mainboard/pcengines/apu1/Kconfig
index 5e927cc..8edb36c 100644
--- a/src/mainboard/pcengines/apu1/Kconfig
+++ b/src/mainboard/pcengines/apu1/Kconfig
@@ -18,6 +18,7 @@ if BOARD_PCENGINES_APU1
 
 config BOARD_SPECIFIC_OPTIONS # dummy
 	def_bool y
+	select AGESA_LEGACY_WRAPPER
 	select CPU_AMD_AGESA_FAMILY14
 	select NORTHBRIDGE_AMD_AGESA_FAMILY14
 	select SOUTHBRIDGE_AMD_CIMX_SB800
diff --git a/src/northbridge/amd/agesa/Makefile.inc b/src/northbridge/amd/agesa/Makefile.inc
index 62a5df1..992ac55 100644
--- a/src/northbridge/amd/agesa/Makefile.inc
+++ b/src/northbridge/amd/agesa/Makefile.inc
@@ -23,8 +23,16 @@ subdirs-$(CONFIG_NORTHBRIDGE_AMD_AGESA_FAMILY15_TN) += family15tn
 subdirs-$(CONFIG_NORTHBRIDGE_AMD_AGESA_FAMILY15_RL) += family15rl
 subdirs-$(CONFIG_NORTHBRIDGE_AMD_AGESA_FAMILY16_KB) += family16kb
 
-romstage-y += def_callouts.c agesawrapper.c eventlog.c
-ramstage-y += def_callouts.c agesawrapper.c eventlog.c
+romstage-y += def_callouts.c eventlog.c
+ramstage-y += def_callouts.c eventlog.c
+
+ifeq ($(CONFIG_AGESA_LEGACY_WRAPPER), y)
+romstage-y += agesawrapper.c
+ramstage-y += agesawrapper.c
+else
+romstage-y += state_machine.c
+ramstage-y += state_machine.c
+endif
 
 romstage-y += oem_s3.c
 ramstage-y += oem_s3.c
diff --git a/src/northbridge/amd/agesa/agesawrapper.c b/src/northbridge/amd/agesa/agesawrapper.c
index 17fdbea..61c6bf8 100644
--- a/src/northbridge/amd/agesa/agesawrapper.c
+++ b/src/northbridge/amd/agesa/agesawrapper.c
@@ -18,6 +18,7 @@
 
 #include <northbridge/amd/agesa/state_machine.h>
 #include <northbridge/amd/agesa/agesa_helper.h>
+#include <northbridge/amd/agesa/state_machine.h>
 #include <northbridge/amd/agesa/agesawrapper.h>
 #include <northbridge/amd/agesa/BiosCallOuts.h>
 #include "amdlib.h"
diff --git a/src/northbridge/amd/agesa/agesawrapper.h b/src/northbridge/amd/agesa/agesawrapper.h
index adc31c1..40b5f22 100644
--- a/src/northbridge/amd/agesa/agesawrapper.h
+++ b/src/northbridge/amd/agesa/agesawrapper.h
@@ -16,6 +16,8 @@
 #ifndef _AGESAWRAPPER_H_
 #define _AGESAWRAPPER_H_
 
+#if IS_ENABLED(CONFIG_AGESA_LEGACY_WRAPPER)
+
 #include <stdint.h>
 #include "Porting.h"
 #include "AGESA.h"
@@ -30,7 +32,6 @@ AGESA_STATUS agesawrapper_amdinitmid(void);
 AGESA_STATUS agesawrapper_amdinitresume(void);
 AGESA_STATUS agesawrapper_amdS3Save(void);
 AGESA_STATUS agesawrapper_amds3laterestore(void);
-AGESA_STATUS agesawrapper_amdlaterunaptask (UINT32 Func, UINT32 Data, VOID *ConfigPtr);
 
 AGESA_STATUS agesawrapper_fchs3earlyrestore(void);
 AGESA_STATUS agesawrapper_fchs3laterestore(void);
@@ -50,9 +51,16 @@ struct OEM_HOOK
 
 extern const struct OEM_HOOK OemCustomize;
 
-/* For suspend-to-ram support. */
-AGESA_STATUS OemInitResume(AMD_RESUME_PARAMS *ResumeParams);
-AGESA_STATUS OemS3LateRestore(AMD_S3LATE_PARAMS *S3LateParams);
-AGESA_STATUS OemS3Save(AMD_S3SAVE_PARAMS *S3SaveParams);
+#else
+
+/* Defined to make unused agesa_main() build. */
+static inline int agesawrapper_amdinitreset(void) { return -1; }
+static inline int agesawrapper_amdinitearly(void) { return -1; }
+static inline int agesawrapper_amdinitenv(void) { return -1; }
+static inline int agesawrapper_amdinitpost(void) { return -1; }
+static inline int agesawrapper_amdinitresume(void) { return -1; }
+static inline int agesawrapper_amds3laterestore(void) { return -1; }
+
+#endif /* IS_ENABLED(CONFIG_AGESA_LEGACY_WRAPPER) */
 
 #endif /* _AGESAWRAPPER_H_ */
diff --git a/src/northbridge/amd/agesa/def_callouts.c b/src/northbridge/amd/agesa/def_callouts.c
index 0805c02..3d97c30 100644
--- a/src/northbridge/amd/agesa/def_callouts.c
+++ b/src/northbridge/amd/agesa/def_callouts.c
@@ -20,7 +20,7 @@
 #include "AGESA.h"
 #include "amdlib.h"
 #include "Ids.h"
-#include <northbridge/amd/agesa/agesawrapper.h>
+#include <northbridge/amd/agesa/state_machine.h>
 #include "BiosCallOuts.h"
 #include "dimmSpd.h"
 
diff --git a/src/northbridge/amd/agesa/family12/Makefile.inc b/src/northbridge/amd/agesa/family12/Makefile.inc
index 6b2ca78..41c40c3 100644
--- a/src/northbridge/amd/agesa/family12/Makefile.inc
+++ b/src/northbridge/amd/agesa/family12/Makefile.inc
@@ -16,3 +16,8 @@
 romstage-y += dimmSpd.c
 
 ramstage-y += northbridge.c
+
+ifneq ($(CONFIG_AGESA_LEGACY_WRAPPER), y)
+romstage-y += state_machine.c
+ramstage-y += state_machine.c
+endif
diff --git a/src/northbridge/amd/agesa/family12/northbridge.c b/src/northbridge/amd/agesa/family12/northbridge.c
index 668e1bb..d272d7f 100644
--- a/src/northbridge/amd/agesa/family12/northbridge.c
+++ b/src/northbridge/amd/agesa/family12/northbridge.c
@@ -32,7 +32,9 @@
 #include <cpu/amd/mtrr.h>
 
 #include "sb_cimx.h"
+
 #include <northbridge/amd/agesa/agesawrapper.h>
+#include <northbridge/amd/agesa/state_machine.h>
 #include <northbridge/amd/agesa/agesa_helper.h>
 
 #define FX_DEVS 1
@@ -635,6 +637,7 @@ static void domain_set_resources(device_t dev)
 
 static void domain_enable_resources(device_t dev)
 {
+#if IS_ENABLED(CONFIG_AGESA_LEGACY_WRAPPER)
 	printk(BIOS_DEBUG, "\nFam12h - northbridge.c - %s - Start.\n",__func__);
 
 	/* Must be called after PCI enumeration and resource allocation */
@@ -648,6 +651,7 @@ static void domain_enable_resources(device_t dev)
 
 	agesawrapper_amdinitmid();
 	printk(BIOS_DEBUG, "Fam12h - northbridge.c - %s - End.\n",__func__);
+#endif
 }
 
 
diff --git a/src/northbridge/amd/agesa/family12/state_machine.c b/src/northbridge/amd/agesa/family12/state_machine.c
new file mode 100644
index 0000000..2fd6617
--- /dev/null
+++ b/src/northbridge/amd/agesa/family12/state_machine.c
@@ -0,0 +1,90 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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 "Porting.h"
+#include "AGESA.h"
+
+#include <northbridge/amd/agesa/state_machine.h>
+#include <northbridge/amd/agesa/agesa_helper.h>
+
+#include <cpu/amd/agesa/s3_resume.h>
+
+#include <sb_cimx.h>
+
+void platform_BeforeInitReset(struct sysinfo *cb, AMD_RESET_PARAMS *Reset)
+{
+}
+
+void platform_BeforeInitEarly(struct sysinfo *cb, AMD_EARLY_PARAMS *Early)
+{
+}
+
+void platform_BeforeInitPost(struct sysinfo *cb, AMD_POST_PARAMS *Post)
+{
+	/* We use AMD_S3LATE_RESTORE instead. */
+	Post->MemConfig.SaveMemContextCtl = 0;
+	Post->MemConfig.MemRestoreCtl = 0;
+}
+
+void platform_AfterInitPost(struct sysinfo *cb, AMD_POST_PARAMS *Post)
+{
+	EmptyHeap();
+
+	sb_before_pci_init();
+}
+
+void platform_BeforeInitResume(struct sysinfo *cb, AMD_RESUME_PARAMS *Resume)
+{
+}
+
+void platform_AfterInitResume(struct sysinfo *cb, AMD_RESUME_PARAMS *Resume)
+{
+}
+
+void platform_BeforeInitEnv(struct sysinfo *cb, AMD_ENV_PARAMS *Env)
+{
+}
+
+void platform_AfterInitEnv(struct sysinfo *cb, AMD_ENV_PARAMS *Env)
+{
+	sb_After_Pci_Init();
+}
+
+void platform_BeforeS3LateRestore(struct sysinfo *cb, AMD_S3LATE_PARAMS *S3Late)
+{
+}
+
+void platform_AfterS3LateRestore(struct sysinfo *cb, AMD_S3LATE_PARAMS *S3Late)
+{
+	OemS3LateRestore(S3Late);
+}
+
+void platform_BeforeInitMid(struct sysinfo *cb, AMD_MID_PARAMS *Mid)
+{
+	sb_Mid_Post_Init();
+
+	amd_initcpuio();
+}
+
+void platform_AfterInitLate(struct sysinfo *cb, AMD_LATE_PARAMS *Late)
+{
+	sb_Late_Post();
+}
+
+void platform_AfterS3Save(struct sysinfo *cb, AMD_S3SAVE_PARAMS *S3Save)
+{
+	OemS3Save(S3Save);
+}
+
diff --git a/src/northbridge/amd/agesa/family14/Makefile.inc b/src/northbridge/amd/agesa/family14/Makefile.inc
index 6b2ca78..41c40c3 100644
--- a/src/northbridge/amd/agesa/family14/Makefile.inc
+++ b/src/northbridge/amd/agesa/family14/Makefile.inc
@@ -16,3 +16,8 @@
 romstage-y += dimmSpd.c
 
 ramstage-y += northbridge.c
+
+ifneq ($(CONFIG_AGESA_LEGACY_WRAPPER), y)
+romstage-y += state_machine.c
+ramstage-y += state_machine.c
+endif
diff --git a/src/northbridge/amd/agesa/family14/northbridge.c b/src/northbridge/amd/agesa/family14/northbridge.c
index b35599e..872d14c 100644
--- a/src/northbridge/amd/agesa/family14/northbridge.c
+++ b/src/northbridge/amd/agesa/family14/northbridge.c
@@ -32,9 +32,12 @@
 #include <cpu/amd/mtrr.h>
 
 #include <northbridge/amd/agesa/agesawrapper.h>
+#include <northbridge/amd/agesa/state_machine.h>
 #include <northbridge/amd/agesa/agesa_helper.h>
 
+#if CONFIG_AMD_SB_CIMX
 #include <sb_cimx.h>
+#endif
 
 #define FX_DEVS 1
 
@@ -616,6 +619,10 @@ static void domain_set_resources(device_t dev)
 
 static void domain_enable_resources(device_t dev)
 {
+#if IS_ENABLED(CONFIG_AGESA_LEGACY_WRAPPER)
+	/* Must be called after PCI enumeration and resource allocation */
+	printk(BIOS_DEBUG, "\nFam14h - %s\n", __func__);
+
 #if CONFIG_AMD_SB_CIMX
 	if (!acpi_is_wakeup_s3()) {
 		sb_After_Pci_Init();
@@ -625,8 +632,6 @@ static void domain_enable_resources(device_t dev)
 	}
 #endif
 
-	/* Must be called after PCI enumeration and resource allocation */
-	printk(BIOS_DEBUG, "\nFam14h - %s\n", __func__);
 
 	if (!acpi_is_wakeup_s3()) {
 		/* Enable MMIO on AMD CPU Address Map Controller */
@@ -636,6 +641,7 @@ static void domain_enable_resources(device_t dev)
 	}
 
 	printk(BIOS_DEBUG, "  ader - leaving domain_enable_resources.\n");
+#endif
 }
 
 static const char *domain_acpi_name(struct device *dev)
diff --git a/src/northbridge/amd/agesa/family14/state_machine.c b/src/northbridge/amd/agesa/family14/state_machine.c
new file mode 100644
index 0000000..b9af710
--- /dev/null
+++ b/src/northbridge/amd/agesa/family14/state_machine.c
@@ -0,0 +1,86 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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 "Porting.h"
+#include "AGESA.h"
+
+#include <northbridge/amd/agesa/state_machine.h>
+#include <northbridge/amd/agesa/agesa_helper.h>
+
+#include <sb_cimx.h>
+
+void platform_BeforeInitReset(struct sysinfo *cb, AMD_RESET_PARAMS *Reset)
+{
+}
+
+void platform_BeforeInitEarly(struct sysinfo *cb, AMD_EARLY_PARAMS *Early)
+{
+}
+
+void platform_BeforeInitPost(struct sysinfo *cb, AMD_POST_PARAMS *Post)
+{
+}
+
+void platform_AfterInitPost(struct sysinfo *cb, AMD_POST_PARAMS *Post)
+{
+	EmptyHeap();
+}
+
+void platform_BeforeInitResume(struct sysinfo *cb, AMD_RESUME_PARAMS *Resume)
+{
+	OemInitResume(Resume);
+}
+
+void platform_AfterInitResume(struct sysinfo *cb, AMD_RESUME_PARAMS *Resume)
+{
+}
+
+void platform_BeforeInitEnv(struct sysinfo *cb, AMD_ENV_PARAMS *Env)
+{
+}
+
+void platform_AfterInitEnv(struct sysinfo *cb, AMD_ENV_PARAMS *Env)
+{
+	amd_initenv();
+}
+
+void platform_BeforeS3LateRestore(struct sysinfo *cb, AMD_S3LATE_PARAMS *S3Late)
+{
+}
+
+void platform_AfterS3LateRestore(struct sysinfo *cb, AMD_S3LATE_PARAMS *S3Late)
+{
+	OemS3LateRestore(S3Late);
+
+	sb_After_Pci_Restore_Init();
+}
+
+void platform_BeforeInitMid(struct sysinfo *cb, AMD_MID_PARAMS *Mid)
+{
+	sb_After_Pci_Init();
+	sb_Mid_Post_Init();
+
+	amd_initcpuio();
+}
+
+void platform_AfterInitLate(struct sysinfo *cb, AMD_LATE_PARAMS *Late)
+{
+	sb_Late_Post();
+}
+
+void platform_AfterS3Save(struct sysinfo *cb, AMD_S3SAVE_PARAMS *S3Save)
+{
+	OemS3Save(S3Save);
+}
diff --git a/src/northbridge/amd/agesa/family15/Makefile.inc b/src/northbridge/amd/agesa/family15/Makefile.inc
index 3cf4ed1..3021ef4 100644
--- a/src/northbridge/amd/agesa/family15/Makefile.inc
+++ b/src/northbridge/amd/agesa/family15/Makefile.inc
@@ -16,3 +16,6 @@
 romstage-y += dimmSpd.c
 
 ramstage-y += northbridge.c
+
+romstage-y += state_machine.c
+ramstage-y += state_machine.c
diff --git a/src/northbridge/amd/agesa/family15/northbridge.c b/src/northbridge/amd/agesa/family15/northbridge.c
index 77db054..44c1b82 100644
--- a/src/northbridge/amd/agesa/family15/northbridge.c
+++ b/src/northbridge/amd/agesa/family15/northbridge.c
@@ -39,8 +39,8 @@
 #include <cpuRegisters.h>
 
 #include <northbridge/amd/agesa/agesawrapper.h>
+#include <northbridge/amd/agesa/state_machine.h>
 #include <northbridge/amd/agesa/agesa_helper.h>
-
 #include "sb_cimx.h"
 
 #define MAX_NODE_NUMS (MAX_NODES * MAX_DIES)
@@ -637,6 +637,7 @@ static void domain_read_resources(device_t dev)
 
 static void domain_enable_resources(device_t dev)
 {
+#if IS_ENABLED(CONFIG_AGESA_LEGACY_WRAPPER)
 	/* Must be called after PCI enumeration and resource allocation */
 	printk(BIOS_DEBUG, "\nFam15 - %s: AmdInitMid.\n", __func__);
 
@@ -648,6 +649,7 @@ static void domain_enable_resources(device_t dev)
 
 	agesawrapper_amdinitmid();
 	printk(BIOS_DEBUG, "  Fam15 - leaving %s.\n", __func__);
+#endif
 }
 
 #if CONFIG_HW_MEM_HOLE_SIZEK != 0
diff --git a/src/northbridge/amd/agesa/family15/state_machine.c b/src/northbridge/amd/agesa/family15/state_machine.c
new file mode 100644
index 0000000..60d1810
--- /dev/null
+++ b/src/northbridge/amd/agesa/family15/state_machine.c
@@ -0,0 +1,78 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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 "Porting.h"
+#include "AGESA.h"
+
+#include <northbridge/amd/agesa/state_machine.h>
+#include <northbridge/amd/agesa/agesa_helper.h>
+
+void platform_BeforeInitReset(struct sysinfo *cb, AMD_RESET_PARAMS *Reset)
+{
+}
+
+void platform_BeforeInitEarly(struct sysinfo *cb, AMD_EARLY_PARAMS *Early)
+{
+}
+
+void platform_BeforeInitPost(struct sysinfo *cb, AMD_POST_PARAMS *Post)
+{
+	/* We use AMD_S3LATE_RESTORE instead. */
+	Post->MemConfig.SaveMemContextCtl = 0;
+	Post->MemConfig.MemRestoreCtl = 0;
+}
+
+void platform_AfterInitPost(struct sysinfo *cb, AMD_POST_PARAMS *Post)
+{
+	EmptyHeap();
+}
+
+void platform_BeforeInitResume(struct sysinfo *cb, AMD_RESUME_PARAMS *Resume)
+{
+	OemInitResume(Resume);
+}
+
+void platform_AfterInitResume(struct sysinfo *cb, AMD_RESUME_PARAMS *Resume)
+{
+}
+
+void platform_BeforeInitEnv(struct sysinfo *cb, AMD_ENV_PARAMS *Env)
+{
+}
+
+void platform_AfterInitEnv(struct sysinfo *cb, AMD_ENV_PARAMS *Env)
+{
+}
+
+void platform_BeforeS3LateRestore(struct sysinfo *cb, AMD_S3LATE_PARAMS *S3Late)
+{
+}
+
+void platform_AfterS3LateRestore(struct sysinfo *cb, AMD_S3LATE_PARAMS *S3Late)
+{
+}
+
+void platform_BeforeInitMid(struct sysinfo *cb, AMD_MID_PARAMS *Mid)
+{
+}
+void platform_AfterInitLate(struct sysinfo *cb, AMD_LATE_PARAMS *Late)
+{
+}
+
+void platform_AfterS3Save(struct sysinfo *cb, AMD_S3SAVE_PARAMS *S3Save)
+{
+	OemS3Save(S3Save);
+}
+
diff --git a/src/northbridge/amd/agesa/family15rl/Makefile.inc b/src/northbridge/amd/agesa/family15rl/Makefile.inc
index a188a91..d6cbc1f 100644
--- a/src/northbridge/amd/agesa/family15rl/Makefile.inc
+++ b/src/northbridge/amd/agesa/family15rl/Makefile.inc
@@ -17,3 +17,8 @@ romstage-y += dimmSpd.c
 
 ramstage-y += iommu.c
 ramstage-y += northbridge.c
+
+ifneq ($(CONFIG_AGESA_LEGACY_WRAPPER), y)
+romstage-y += state_machine.c
+ramstage-y += state_machine.c
+endif
diff --git a/src/northbridge/amd/agesa/family15rl/northbridge.c b/src/northbridge/amd/agesa/family15rl/northbridge.c
index c87ef48..255e7d2 100644
--- a/src/northbridge/amd/agesa/family15rl/northbridge.c
+++ b/src/northbridge/amd/agesa/family15rl/northbridge.c
@@ -40,6 +40,7 @@
 #include <cpuRegisters.h>
 
 #include <northbridge/amd/agesa/agesawrapper.h>
+#include <northbridge/amd/agesa/state_machine.h>
 #include <northbridge/amd/agesa/agesa_helper.h>
 
 #define MAX_NODE_NUMS (MAX_NODES * MAX_DIES)
@@ -633,6 +634,7 @@ static void domain_read_resources(struct device *dev)
 
 static void domain_enable_resources(struct device *dev)
 {
+#if IS_ENABLED(CONFIG_AGESA_LEGACY_WRAPPER)
 	if (acpi_is_wakeup_s3())
 		agesawrapper_fchs3laterestore();
 
@@ -644,6 +646,7 @@ static void domain_enable_resources(struct device *dev)
 		agesawrapper_amdinitmid();
 	}
 	printk(BIOS_DEBUG, "  ader - leaving %s.\n", __func__);
+#endif
 }
 
 #if CONFIG_HW_MEM_HOLE_SIZEK != 0
diff --git a/src/northbridge/amd/agesa/family15rl/state_machine.c b/src/northbridge/amd/agesa/family15rl/state_machine.c
new file mode 100644
index 0000000..ce6baee
--- /dev/null
+++ b/src/northbridge/amd/agesa/family15rl/state_machine.c
@@ -0,0 +1,84 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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 "Porting.h"
+#include "AGESA.h"
+
+#include <northbridge/amd/agesa/state_machine.h>
+#include <northbridge/amd/agesa/agesa_helper.h>
+
+void platform_BeforeInitReset(struct sysinfo *cb, AMD_RESET_PARAMS *Reset)
+{
+}
+
+void platform_BeforeInitEarly(struct sysinfo *cb, AMD_EARLY_PARAMS *Early)
+{
+}
+
+void platform_BeforeInitPost(struct sysinfo *cb, AMD_POST_PARAMS *Post)
+{
+}
+
+void platform_AfterInitPost(struct sysinfo *cb, AMD_POST_PARAMS *Post)
+{
+	EmptyHeap();
+}
+
+void platform_BeforeInitResume(struct sysinfo *cb, AMD_RESUME_PARAMS *Resume)
+{
+	OemInitResume(Resume);
+}
+
+void platform_AfterInitResume(struct sysinfo *cb, AMD_RESUME_PARAMS *Resume)
+{
+}
+
+void platform_BeforeInitEnv(struct sysinfo *cb, AMD_ENV_PARAMS *Env)
+{
+}
+
+void platform_AfterInitEnv(struct sysinfo *cb, AMD_ENV_PARAMS *Env)
+{
+}
+
+void platform_BeforeS3LateRestore(struct sysinfo *cb, AMD_S3LATE_PARAMS *S3Late)
+{
+}
+
+void platform_AfterS3LateRestore(struct sysinfo *cb, AMD_S3LATE_PARAMS *S3Late)
+{
+	amd_initcpuio();
+
+	OemS3LateRestore(S3Late);
+
+	fchs3earlyrestore();
+}
+
+void platform_BeforeInitMid(struct sysinfo *cb, AMD_MID_PARAMS *Mid)
+{
+	amd_initcpuio();
+}
+
+void platform_AfterInitLate(struct sysinfo *cb, AMD_LATE_PARAMS *Late)
+{
+	/* FIXME: not reached S3 path */
+	if (cb->s3resume)
+		fchs3laterestore();
+}
+
+void platform_AfterS3Save(struct sysinfo *cb, AMD_S3SAVE_PARAMS *S3Save)
+{
+	OemS3Save(S3Save);
+}
diff --git a/src/northbridge/amd/agesa/family15tn/Makefile.inc b/src/northbridge/amd/agesa/family15tn/Makefile.inc
index a188a91..d6cbc1f 100644
--- a/src/northbridge/amd/agesa/family15tn/Makefile.inc
+++ b/src/northbridge/amd/agesa/family15tn/Makefile.inc
@@ -17,3 +17,8 @@ romstage-y += dimmSpd.c
 
 ramstage-y += iommu.c
 ramstage-y += northbridge.c
+
+ifneq ($(CONFIG_AGESA_LEGACY_WRAPPER), y)
+romstage-y += state_machine.c
+ramstage-y += state_machine.c
+endif
diff --git a/src/northbridge/amd/agesa/family15tn/northbridge.c b/src/northbridge/amd/agesa/family15tn/northbridge.c
index c8909fb..6eaaa61 100644
--- a/src/northbridge/amd/agesa/family15tn/northbridge.c
+++ b/src/northbridge/amd/agesa/family15tn/northbridge.c
@@ -39,6 +39,7 @@
 #include <cpuRegisters.h>
 
 #include <northbridge/amd/agesa/agesawrapper.h>
+#include <northbridge/amd/agesa/state_machine.h>
 #include <northbridge/amd/agesa/agesa_helper.h>
 
 #define MAX_NODE_NUMS (MAX_NODES * MAX_DIES)
@@ -632,6 +633,7 @@ static void domain_read_resources(device_t dev)
 
 static void domain_enable_resources(device_t dev)
 {
+#if IS_ENABLED(CONFIG_AGESA_LEGACY_WRAPPER)
 	if (acpi_is_wakeup_s3())
 		agesawrapper_fchs3laterestore();
 
@@ -643,6 +645,7 @@ static void domain_enable_resources(device_t dev)
 		agesawrapper_amdinitmid();
 	}
 	printk(BIOS_DEBUG, "  ader - leaving %s.\n", __func__);
+#endif
 }
 
 #if CONFIG_HW_MEM_HOLE_SIZEK != 0
diff --git a/src/northbridge/amd/agesa/family15tn/state_machine.c b/src/northbridge/amd/agesa/family15tn/state_machine.c
new file mode 100644
index 0000000..ce6baee
--- /dev/null
+++ b/src/northbridge/amd/agesa/family15tn/state_machine.c
@@ -0,0 +1,84 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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 "Porting.h"
+#include "AGESA.h"
+
+#include <northbridge/amd/agesa/state_machine.h>
+#include <northbridge/amd/agesa/agesa_helper.h>
+
+void platform_BeforeInitReset(struct sysinfo *cb, AMD_RESET_PARAMS *Reset)
+{
+}
+
+void platform_BeforeInitEarly(struct sysinfo *cb, AMD_EARLY_PARAMS *Early)
+{
+}
+
+void platform_BeforeInitPost(struct sysinfo *cb, AMD_POST_PARAMS *Post)
+{
+}
+
+void platform_AfterInitPost(struct sysinfo *cb, AMD_POST_PARAMS *Post)
+{
+	EmptyHeap();
+}
+
+void platform_BeforeInitResume(struct sysinfo *cb, AMD_RESUME_PARAMS *Resume)
+{
+	OemInitResume(Resume);
+}
+
+void platform_AfterInitResume(struct sysinfo *cb, AMD_RESUME_PARAMS *Resume)
+{
+}
+
+void platform_BeforeInitEnv(struct sysinfo *cb, AMD_ENV_PARAMS *Env)
+{
+}
+
+void platform_AfterInitEnv(struct sysinfo *cb, AMD_ENV_PARAMS *Env)
+{
+}
+
+void platform_BeforeS3LateRestore(struct sysinfo *cb, AMD_S3LATE_PARAMS *S3Late)
+{
+}
+
+void platform_AfterS3LateRestore(struct sysinfo *cb, AMD_S3LATE_PARAMS *S3Late)
+{
+	amd_initcpuio();
+
+	OemS3LateRestore(S3Late);
+
+	fchs3earlyrestore();
+}
+
+void platform_BeforeInitMid(struct sysinfo *cb, AMD_MID_PARAMS *Mid)
+{
+	amd_initcpuio();
+}
+
+void platform_AfterInitLate(struct sysinfo *cb, AMD_LATE_PARAMS *Late)
+{
+	/* FIXME: not reached S3 path */
+	if (cb->s3resume)
+		fchs3laterestore();
+}
+
+void platform_AfterS3Save(struct sysinfo *cb, AMD_S3SAVE_PARAMS *S3Save)
+{
+	OemS3Save(S3Save);
+}
diff --git a/src/northbridge/amd/agesa/family16kb/Makefile.inc b/src/northbridge/amd/agesa/family16kb/Makefile.inc
index 3cf4ed1..25e3cc8 100644
--- a/src/northbridge/amd/agesa/family16kb/Makefile.inc
+++ b/src/northbridge/amd/agesa/family16kb/Makefile.inc
@@ -16,3 +16,8 @@
 romstage-y += dimmSpd.c
 
 ramstage-y += northbridge.c
+
+ifneq ($(CONFIG_AGESA_LEGACY_WRAPPER), y)
+romstage-y += state_machine.c
+ramstage-y += state_machine.c
+endif
diff --git a/src/northbridge/amd/agesa/family16kb/northbridge.c b/src/northbridge/amd/agesa/family16kb/northbridge.c
index 5b475fe..e7b07e8 100644
--- a/src/northbridge/amd/agesa/family16kb/northbridge.c
+++ b/src/northbridge/amd/agesa/family16kb/northbridge.c
@@ -39,6 +39,7 @@
 #include <cpuRegisters.h>
 
 #include <northbridge/amd/agesa/agesawrapper.h>
+#include <northbridge/amd/agesa/state_machine.h>
 #include <northbridge/amd/agesa/agesa_helper.h>
 
 #define MAX_NODE_NUMS (MAX_NODES * MAX_DIES)
@@ -647,6 +648,7 @@ static void domain_read_resources(device_t dev)
 
 static void domain_enable_resources(device_t dev)
 {
+#if IS_ENABLED(CONFIG_AGESA_LEGACY_WRAPPER)
 	if (acpi_is_wakeup_s3())
 		agesawrapper_fchs3laterestore();
 
@@ -658,6 +660,7 @@ static void domain_enable_resources(device_t dev)
 		agesawrapper_amdinitmid();
 	}
 	printk(BIOS_DEBUG, "  ader - leaving domain_enable_resources.\n");
+#endif
 }
 
 #if CONFIG_HW_MEM_HOLE_SIZEK != 0
diff --git a/src/northbridge/amd/agesa/family16kb/state_machine.c b/src/northbridge/amd/agesa/family16kb/state_machine.c
new file mode 100644
index 0000000..ce6baee
--- /dev/null
+++ b/src/northbridge/amd/agesa/family16kb/state_machine.c
@@ -0,0 +1,84 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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 "Porting.h"
+#include "AGESA.h"
+
+#include <northbridge/amd/agesa/state_machine.h>
+#include <northbridge/amd/agesa/agesa_helper.h>
+
+void platform_BeforeInitReset(struct sysinfo *cb, AMD_RESET_PARAMS *Reset)
+{
+}
+
+void platform_BeforeInitEarly(struct sysinfo *cb, AMD_EARLY_PARAMS *Early)
+{
+}
+
+void platform_BeforeInitPost(struct sysinfo *cb, AMD_POST_PARAMS *Post)
+{
+}
+
+void platform_AfterInitPost(struct sysinfo *cb, AMD_POST_PARAMS *Post)
+{
+	EmptyHeap();
+}
+
+void platform_BeforeInitResume(struct sysinfo *cb, AMD_RESUME_PARAMS *Resume)
+{
+	OemInitResume(Resume);
+}
+
+void platform_AfterInitResume(struct sysinfo *cb, AMD_RESUME_PARAMS *Resume)
+{
+}
+
+void platform_BeforeInitEnv(struct sysinfo *cb, AMD_ENV_PARAMS *Env)
+{
+}
+
+void platform_AfterInitEnv(struct sysinfo *cb, AMD_ENV_PARAMS *Env)
+{
+}
+
+void platform_BeforeS3LateRestore(struct sysinfo *cb, AMD_S3LATE_PARAMS *S3Late)
+{
+}
+
+void platform_AfterS3LateRestore(struct sysinfo *cb, AMD_S3LATE_PARAMS *S3Late)
+{
+	amd_initcpuio();
+
+	OemS3LateRestore(S3Late);
+
+	fchs3earlyrestore();
+}
+
+void platform_BeforeInitMid(struct sysinfo *cb, AMD_MID_PARAMS *Mid)
+{
+	amd_initcpuio();
+}
+
+void platform_AfterInitLate(struct sysinfo *cb, AMD_LATE_PARAMS *Late)
+{
+	/* FIXME: not reached S3 path */
+	if (cb->s3resume)
+		fchs3laterestore();
+}
+
+void platform_AfterS3Save(struct sysinfo *cb, AMD_S3SAVE_PARAMS *S3Save)
+{
+	OemS3Save(S3Save);
+}
diff --git a/src/northbridge/amd/agesa/oem_s3.c b/src/northbridge/amd/agesa/oem_s3.c
index a9504ac..b149c10 100644
--- a/src/northbridge/amd/agesa/oem_s3.c
+++ b/src/northbridge/amd/agesa/oem_s3.c
@@ -20,6 +20,7 @@
 #include <program_loading.h>
 #include <cpu/amd/agesa/s3_resume.h>
 #include <northbridge/amd/agesa/agesawrapper.h>
+#include <northbridge/amd/agesa/state_machine.h>
 #include <AGESA.h>
 #include <northbridge/amd/agesa/agesa_helper.h>
 
diff --git a/src/northbridge/amd/agesa/state_machine.c b/src/northbridge/amd/agesa/state_machine.c
new file mode 100644
index 0000000..3a6daaa
--- /dev/null
+++ b/src/northbridge/amd/agesa/state_machine.c
@@ -0,0 +1,372 @@
+/*
+ * 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 <stdint.h>
+#include <string.h>
+
+#include <arch/acpi.h>
+#include <bootstate.h>
+
+#include <northbridge/amd/agesa/state_machine.h>
+#include <northbridge/amd/agesa/agesa_helper.h>
+#include <northbridge/amd/agesa/BiosCallOuts.h>
+#include "amdlib.h"
+#include <cpu/amd/agesa/s3_resume.h>
+
+#include "AMD.h"
+#include "heapManager.h"
+#include "Dispatcher.h"
+
+
+#if ENV_ROMSTAGE
+#include <PlatformMemoryConfiguration.h>
+CONST PSO_ENTRY ROMDATA DefaultPlatformMemoryConfiguration[] = {PSO_END};
+#endif
+
+#if ENV_RAMSTAGE
+static void completion_InitLate(struct sysinfo *cb, AMD_LATE_PARAMS *Late);
+#endif
+
+struct agesa_state
+{
+	u8 apic_id;
+	AGESA_STATUS status;
+
+	u32 func;
+	const char *function_name;
+
+	struct sysinfo *sysinfo;
+	AMD_INTERFACE_PARAMS *aip;
+};
+
+static AGESA_STATUS amd_alloc(AMD_INTERFACE_PARAMS *aip, AGESA_STRUCT_NAME func)
+{
+	aip->StdHeader.Func = AMD_CREATE_STRUCT;
+	aip->AgesaFunctionName = func;
+	aip->AllocationMethod = 0;
+	aip->NewStructPtr = NULL;
+	aip->NewStructSize = 0;
+	return AmdAgesaDispatcher(aip);
+}
+
+static AGESA_STATUS amd_release(AMD_INTERFACE_PARAMS *aip, AGESA_STRUCT_NAME func)
+{
+	/* Cannot release AMD_LATE_PARAMS until ACPI tables are done. */
+	if (func == AMD_INIT_LATE)
+		return AGESA_SUCCESS;
+
+	aip->StdHeader.Func = AMD_RELEASE_STRUCT;
+	aip->AgesaFunctionName = func;
+	aip->AllocationMethod = 0;
+	return AmdAgesaDispatcher(aip);
+}
+
+static AGESA_STATUS amd_alloc_stack(AMD_INTERFACE_PARAMS *aip, AGESA_STRUCT_NAME func, void *buf, size_t len)
+{
+	/* By design, each valid AGESA_STRUCT_NAME
+	 * can be casted to AMD_CONFIG_PARAMS.
+	 */
+	AMD_CONFIG_PARAMS *call = buf;
+	memset(call, 0, len);
+
+	aip->StdHeader.Func = AMD_CREATE_STRUCT;
+	aip->AgesaFunctionName = func;
+	aip->AllocationMethod = ByHost;
+	aip->NewStructPtr = call;
+	aip->NewStructSize = len;
+
+	/* AMD_CREATE_STRUCT with ByHost skips this.  */
+	*call = aip->StdHeader;
+
+	return AmdAgesaDispatcher(aip);
+}
+
+static AGESA_STATUS amd_release_stack(AMD_INTERFACE_PARAMS *aip, AGESA_STRUCT_NAME func)
+{
+	aip->StdHeader.Func = AMD_RELEASE_STRUCT;
+	aip->AgesaFunctionName = func;
+	aip->AllocationMethod = ByHost;
+	return AmdAgesaDispatcher(aip);
+}
+
+static AGESA_STATUS amd_dispatch(struct agesa_state *task, AMD_CONFIG_PARAMS *call)
+{
+	struct sysinfo *cb = task->sysinfo;
+
+	/* By design, for each valid AGESA_STRUCT_NAME, AMD_CONFIG_PARAMS
+	 * can be evaluated to apply correct typecast based on Func field.
+	 */
+
+	switch (call->Func)
+	{
+#if ENV_ROMSTAGE
+		case AMD_INIT_RESET:
+		{
+			AMD_RESET_PARAMS *param = (void *)call;
+			platform_BeforeInitReset(cb, param);
+			task->status = AmdAgesaDispatcher(call);
+			break;
+		}
+
+		case AMD_INIT_EARLY:
+		{
+			AMD_EARLY_PARAMS *param = (void *)call;
+			platform_BeforeInitEarly(cb, param);
+			board_BeforeInitEarly(cb, param);
+			task->status = AmdAgesaDispatcher(call);
+			break;
+		}
+
+		case AMD_INIT_POST:
+		{
+			AMD_POST_PARAMS *param = (void *)call;
+			platform_BeforeInitPost(cb, param);
+			board_BeforeInitPost(cb, param);
+			task->status = AmdAgesaDispatcher(call);
+			platform_AfterInitPost(cb, param);
+			break;
+		}
+
+		case AMD_INIT_RESUME:
+		{
+			AMD_RESUME_PARAMS *param = (void *)call;
+			platform_BeforeInitResume(cb, param);
+			task->status = AmdAgesaDispatcher(call);
+			break;
+		}
+
+		case AMD_INIT_ENV:
+		{
+			AMD_ENV_PARAMS *param = (void *)call;
+			task->status = AmdAgesaDispatcher(call);
+			platform_AfterInitEnv(cb, param);
+			break;
+		}
+
+		case AMD_S3LATE_RESTORE:
+		{
+			AMD_S3LATE_PARAMS *param = (void *)call;
+			platform_BeforeS3LateRestore(cb, param);
+			task->status = AmdAgesaDispatcher(call);
+			break;
+		}
+#endif
+#if ENV_RAMSTAGE
+		case AMD_INIT_MID:
+		{
+			AMD_MID_PARAMS *param = (void *)call;
+			platform_BeforeInitMid(cb, param);
+			board_BeforeInitMid(cb, param);
+			task->status = AmdAgesaDispatcher(call);
+			break;
+		}
+
+		case AMD_S3_SAVE:
+		{
+			AMD_S3SAVE_PARAMS *param = (void *)call;
+			task->status = AmdAgesaDispatcher(call);
+			platform_AfterS3Save(cb, param);
+			break;
+		}
+		case AMD_INIT_LATE:
+		{
+			AMD_LATE_PARAMS *param = (void *)call;
+			task->status = AmdAgesaDispatcher(call);
+			platform_AfterInitLate(cb, param);
+			completion_InitLate(cb, param);
+			break;
+		}
+#endif
+		default:
+		{
+			task->status = AGESA_UNSUPPORTED;
+			break;
+		}
+
+	}
+	return task->status;
+}
+
+static void state_on_entry(struct sysinfo *cb,
+	struct agesa_state *params, AGESA_STRUCT_NAME func)
+{
+	memset(params, 0, sizeof(params));
+
+	params->aip = (AMD_INTERFACE_PARAMS *) cb->agesa_stash;
+	params->sysinfo = cb;
+
+	params->apic_id = (u8) (cpuid_ebx(1) >> 24);
+	params->func = func;
+	params->function_name = agesa_struct_name(func);
+
+	printk(BIOS_DEBUG, "\nAPIC %02d: ** Enter %s [%08x]\n",
+		params->apic_id, params->function_name, params->func);
+}
+
+static void state_on_exit(struct agesa_state *params)
+{
+	AMD_CONFIG_PARAMS *call = &params->aip->StdHeader;
+
+	agesawrapper_trace(params->status, call, params->function_name);
+
+	printk(BIOS_DEBUG, "APIC %02d: Heap in %s (%d) at 0x%08x\n",
+		params->apic_id, heap_status_name(call->HeapStatus), call->HeapStatus,
+		(u32)call->HeapBasePtr);
+
+	printk(BIOS_DEBUG, "APIC %02d: ** Exit  %s [%08x]\n",
+		params->apic_id, params->function_name, params->func);
+}
+
+static AGESA_STATUS agesa_task(struct sysinfo *cb, AGESA_STRUCT_NAME func)
+{
+	struct agesa_state params;
+	AMD_RESET_PARAMS reset;
+	AGESA_STATUS status;
+
+	state_on_entry(cb, &params, func);
+
+	AMD_INTERFACE_PARAMS *aip = params.aip;
+
+	if (func == AMD_INIT_RESET)
+		status = amd_alloc_stack(aip, func, &reset, sizeof(reset));
+	else
+		status = amd_alloc(aip, func);
+	ASSERT(status == AGESA_SUCCESS);
+
+	AMD_CONFIG_PARAMS *call = aip->NewStructPtr;
+	/* Must call the function buffer was allocated for.*/
+	ASSERT(call->Func == func);
+
+	status = amd_dispatch(&params, call);
+	ASSERT(status < AGESA_FATAL);
+
+	if (func == AMD_INIT_RESET)
+		status = amd_release_stack(aip, func);
+	else
+		status = amd_release(aip, func);
+	ASSERT(status == AGESA_SUCCESS);
+
+	state_on_exit(&params);
+	return params.status;
+}
+
+void agesa_set_interface(struct sysinfo *cb)
+{
+	AMD_INTERFACE_PARAMS *aip = (void *)cb->agesa_stash;
+
+	ASSERT (sizeof(AMD_INTERFACE_PARAMS) < AGESA_STASH_SIZE);
+	memset(aip, 0, sizeof(*aip));
+	aip->StdHeader.CalloutPtr = GetBiosCallout;
+}
+
+int agesa_execute_state(struct sysinfo *cb, int func)
+{
+	AGESA_STATUS ret = agesa_task(cb, (AGESA_STRUCT_NAME) func);
+	return (ret == AGESA_SUCCESS) ? 0 : -1;
+}
+
+#if ENV_RAMSTAGE
+
+static struct sysinfo state_machine;
+
+static void agesa_mid(void *unused)
+{
+	agesa_set_interface(&state_machine);
+
+	if (!acpi_is_wakeup_s3())
+		agesa_execute_state(&state_machine, AMD_INIT_MID);
+}
+
+BOOT_STATE_INIT_ENTRY(BS_DEV_ENABLE, BS_ON_EXIT, agesa_mid, NULL);
+
+static void agesa_late(void *unused)
+{
+	if (acpi_is_wakeup_s3())
+		return;
+
+	agesa_execute_state(&state_machine, AMD_INIT_LATE);
+
+	if (!acpi_s3_resume_allowed())
+		return;
+
+	agesa_execute_state(&state_machine, AMD_S3_SAVE);
+}
+
+BOOT_STATE_INIT_ENTRY(BS_POST_DEVICE, BS_ON_EXIT, agesa_late, NULL);
+
+
+/* We will reference AmdLateParams later to copy ACPI tables. */
+static AMD_LATE_PARAMS *AmdLateParams;
+
+static void completion_InitLate(struct sysinfo *cb, AMD_LATE_PARAMS *Late)
+{
+	AmdLateParams = Late;
+}
+
+void *agesawrapper_getlateinitptr(int pick)
+{
+	ASSERT(AmdLateParams != NULL);
+
+	switch (pick) {
+	case PICK_DMI:
+		return AmdLateParams->DmiTable;
+	case PICK_PSTATE:
+		return AmdLateParams->AcpiPState;
+	case PICK_SRAT:
+		return AmdLateParams->AcpiSrat;
+	case PICK_SLIT:
+		return AmdLateParams->AcpiSlit;
+	case PICK_WHEA_MCE:
+		return AmdLateParams->AcpiWheaMce;
+	case PICK_WHEA_CMC:
+		return AmdLateParams->AcpiWheaCmc;
+	case PICK_ALIB:
+		return AmdLateParams->AcpiAlib;
+	case PICK_IVRS:
+#if IS_ENABLED(CONFIG_CPU_AMD_AGESA_FAMILY14)
+		return NULL;
+#else
+		return AmdLateParams->AcpiIvrs;
+#endif
+	default:
+		return NULL;
+	}
+	return NULL;
+}
+
+#endif /* ENV_RAMSTAGE */
+
+AGESA_STATUS agesawrapper_amdlaterunaptask(UINT32 Func, UINT32 Data, VOID * ConfigPtr)
+{
+#if 0
+	AGESA_STATUS status;
+	AP_EXE_PARAMS ApExeParams;
+
+	memset(&ApExeParams, 0, sizeof(AP_EXE_PARAMS));
+	ApExeParams.StdHeader.CalloutPtr = &GetBiosCallout;
+
+	ApExeParams.FunctionNumber = Func;
+	ApExeParams.RelatedDataBlock = ConfigPtr;
+
+	status = AmdLateRunApTask(&ApExeParams);
+	AGESA_EVENTLOG(status, &ApExeParams.StdHeader);
+	ASSERT(status == AGESA_SUCCESS);
+
+	return status;
+#else
+	return AGESA_SUCCESS;
+#endif
+}
diff --git a/src/northbridge/amd/agesa/state_machine.h b/src/northbridge/amd/agesa/state_machine.h
index 7f0cb85..7c52a19 100644
--- a/src/northbridge/amd/agesa/state_machine.h
+++ b/src/northbridge/amd/agesa/state_machine.h
@@ -24,8 +24,22 @@ const char *agesa_struct_name(int state);
 const char *heap_status_name(int status);
 void agesawrapper_trace(AGESA_STATUS ret, AMD_CONFIG_PARAMS *StdHeader, const char *func);
 
+
+AGESA_STATUS agesawrapper_amdlaterunaptask (UINT32 Func, UINT32 Data, VOID *ConfigPtr);
+
+/* For suspend-to-ram support. */
+AGESA_STATUS OemInitResume(AMD_RESUME_PARAMS *Resume);
+AGESA_STATUS OemS3LateRestore(AMD_S3LATE_PARAMS *S3Late);
+AGESA_STATUS OemS3Save(AMD_S3SAVE_PARAMS *S3Save);
+
+/* For FCH */
+static inline void fchs3earlyrestore(void) { }
+static inline void fchs3laterestore(void) { }
+
+#define AGESA_STASH_SIZE 64
 struct sysinfo
 {
+	u8 agesa_stash[AGESA_STASH_SIZE];
 	int s3resume;
 };
 
@@ -34,4 +48,36 @@ void board_BeforeAgesa(struct sysinfo *cb);
 void platform_once(struct sysinfo *cb);
 void agesa_main(struct sysinfo *cb);
 
+void agesa_set_interface(struct sysinfo *cb);
+int agesa_execute_state(struct sysinfo *cb, int func);
+
+/* AGESA dispatchers */
+
+void platform_BeforeInitReset(struct sysinfo *cb, AMD_RESET_PARAMS *Reset);
+
+void platform_BeforeInitEarly(struct sysinfo *cb, AMD_EARLY_PARAMS *Early);
+void board_BeforeInitEarly(struct sysinfo *cb, AMD_EARLY_PARAMS *Early);
+
+/* Normal boot */
+void platform_BeforeInitPost(struct sysinfo *cb, AMD_POST_PARAMS *Post);
+void board_BeforeInitPost(struct sysinfo *cb, AMD_POST_PARAMS *Post);
+void platform_AfterInitPost(struct sysinfo *cb, AMD_POST_PARAMS *Post);
+
+void platform_BeforeInitEnv(struct sysinfo *cb, AMD_ENV_PARAMS *Env);
+void platform_AfterInitEnv(struct sysinfo *cb, AMD_ENV_PARAMS *Env);
+
+void platform_BeforeInitMid(struct sysinfo *cb, AMD_MID_PARAMS *Mid);
+void board_BeforeInitMid(struct sysinfo *cb, AMD_MID_PARAMS *Mid);
+
+void platform_AfterInitLate(struct sysinfo *cb, AMD_LATE_PARAMS *Late);
+
+/* S3 Resume */
+void platform_BeforeInitResume(struct sysinfo *cb, AMD_RESUME_PARAMS *Resume);
+void platform_AfterInitResume(struct sysinfo *cb, AMD_RESUME_PARAMS *Resume);
+
+void platform_BeforeS3LateRestore(struct sysinfo *cb, AMD_S3LATE_PARAMS *S3Late);
+void platform_AfterS3LateRestore(struct sysinfo *cb, AMD_S3LATE_PARAMS *S3Late);
+
+void platform_AfterS3Save(struct sysinfo *cb, AMD_S3SAVE_PARAMS *S3Save);
+
 #endif /* _STATE_MACHINE_H_ */
diff --git a/src/southbridge/amd/agesa/hudson/Makefile.inc b/src/southbridge/amd/agesa/hudson/Makefile.inc
index 7595889..b1c56cb 100644
--- a/src/southbridge/amd/agesa/hudson/Makefile.inc
+++ b/src/southbridge/amd/agesa/hudson/Makefile.inc
@@ -10,7 +10,7 @@ ramstage-y += pci.c
 ramstage-y += pcie.c
 ramstage-y += sd.c
 
-ramstage-y += agesawrapper.c
+ramstage-$(CONFIG_AGESA_LEGACY_WRAPPER) += agesawrapper.c
 
 ramstage-$(CONFIG_HAVE_ACPI_TABLES) += fadt.c
 ramstage-y += reset.c



More information about the coreboot-gerrit mailing list