summaryrefslogtreecommitdiffstats
path: root/src/soc/amd/common/pi/refcode_loader.c
blob: d9704e054840f581f51b059ddca5571133cb1202 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
/* SPDX-License-Identifier: GPL-2.0-only */

#include <acpi/acpi.h>
#include <cbfs.h>
#include <cbmem.h>
#include <console/console.h>
#include <rmodule.h>
#include <stage_cache.h>
#include <amdblocks/agesawrapper.h>
#include <amdblocks/image.h>

static void *agesa_map_raw_file(const char *name, size_t *size)
{
	enum cbfs_type type = CBFS_TYPE_RAW;
	return cbfs_type_map(name, size, &type);
}

static void *agesa_map_stage_file_early(const char *name, size_t *size)
{
	enum cbfs_type type = CBFS_TYPE_STAGE;
	return cbfs_type_map(name, size, &type);
}

static void *agesa_map_stage_file_ramstage(const char *name, size_t *size)
{
	struct prog prog = PROG_INIT(PROG_REFCODE, name);
	struct rmod_stage_load rmod_agesa = {
		.cbmem_id = CBMEM_ID_REFCODE,
		.prog = &prog,
	};

	if (resume_from_stage_cache()) {
		stage_cache_load_stage(STAGE_REFCODE, &prog);
	} else {
		if (rmodule_stage_load(&rmod_agesa) < 0)
			return NULL;

		stage_cache_add(STAGE_REFCODE, &prog);
	}

	*size = prog_size(&prog);
	return prog_start(&prog);
}

static void *agesa_map_stage_file(const char *name, size_t *size)
{
	if (!ENV_RAMSTAGE || !CONFIG(AGESA_SPLIT_MEMORY_FILES))
		return agesa_map_stage_file_early(name, size);
	return agesa_map_stage_file_ramstage(name, size);
}

static const char *get_agesa_cbfs_name(void)
{
	if (!CONFIG(AGESA_SPLIT_MEMORY_FILES))
		return CONFIG_AGESA_CBFS_NAME;
	if (!ENV_RAMSTAGE)
		return CONFIG_AGESA_PRE_MEMORY_CBFS_NAME;
	return CONFIG_AGESA_POST_MEMORY_CBFS_NAME;
}

const void *agesawrapper_locate_module(const char name[8])
{
	const void *agesa;
	const AMD_IMAGE_HEADER *image;
	size_t file_size;
	const char *fname;

	/* Assume boot device is memory mapped so the mapping can leak. */
	assert(CONFIG(BOOT_DEVICE_MEMORY_MAPPED));

	fname = get_agesa_cbfs_name();

	if (CONFIG(AGESA_BINARY_PI_AS_STAGE))
		agesa = agesa_map_stage_file(fname, &file_size);
	else
		agesa = agesa_map_raw_file(fname, &file_size);

	if (!agesa)
		return NULL;

	image =  amd_find_image(agesa, agesa + file_size, 4096, name);

	if (!image)
		return NULL;

	return (AMD_MODULE_HEADER *)image->ModuleInfoOffset;
}

static MODULE_ENTRY agesa_dispatcher;

MODULE_ENTRY agesa_get_dispatcher(void)
{
	const AMD_MODULE_HEADER *module;
	static const char id[8] = AGESA_ID;

	if (agesa_dispatcher != NULL)
		return agesa_dispatcher;

	module = agesawrapper_locate_module(id);
	if (!module)
		return NULL;

	agesa_dispatcher = module->ModuleDispatcher;
	return agesa_dispatcher;
}