blob: f28418ab2e7009507000e8bca40662a8ee1577ed [file] [log] [blame]
Angel Pons118a9c72020-04-02 23:48:34 +02001/* SPDX-License-Identifier: GPL-2.0-only */
2/* This file is part of the coreboot project. */
Aaron Durbinbd74a4b2015-03-06 23:17:33 -06003
Aaron Durbinbd74a4b2015-03-06 23:17:33 -06004#include <bootstate.h>
5#include <cbmem.h>
6#include <console/console.h>
7#include <imd.h>
Aaron Durbinbd74a4b2015-03-06 23:17:33 -06008#include <stage_cache.h>
9#include <string.h>
10
Arthur Heymans7c2994b2019-11-20 20:01:11 +010011static struct imd imd_stage_cache;
Aaron Durbinbd74a4b2015-03-06 23:17:33 -060012
Aaron Durbin42e68562015-06-09 13:55:51 -050013static void stage_cache_create_empty(void)
Aaron Durbinbd74a4b2015-03-06 23:17:33 -060014{
15 struct imd *imd;
16 void *base;
17 size_t size;
18
Arthur Heymans7c2994b2019-11-20 20:01:11 +010019 imd = &imd_stage_cache;
Aaron Durbinbd74a4b2015-03-06 23:17:33 -060020 stage_cache_external_region(&base, &size);
21 imd_handle_init(imd, (void *)(size + (uintptr_t)base));
22
23 printk(BIOS_DEBUG, "External stage cache:\n");
24 imd_create_tiered_empty(imd, 4096, 4096, 1024, 32);
25 if (imd_limit_size(imd, size))
26 printk(BIOS_DEBUG, "Could not limit stage cache size.\n");
27}
28
Aaron Durbin42e68562015-06-09 13:55:51 -050029static void stage_cache_recover(void)
Aaron Durbinbd74a4b2015-03-06 23:17:33 -060030{
31 struct imd *imd;
32 void *base;
33 size_t size;
34
Arthur Heymans7c2994b2019-11-20 20:01:11 +010035 imd = &imd_stage_cache;
Aaron Durbinbd74a4b2015-03-06 23:17:33 -060036 stage_cache_external_region(&base, &size);
37 imd_handle_init(imd, (void *)(size + (uintptr_t)base));
38 if (imd_recover(imd))
39 printk(BIOS_DEBUG, "Unable to recover external stage cache.\n");
40}
41
Aaron Durbin54546c92015-08-05 00:52:13 -050042void stage_cache_add(int stage_id, const struct prog *stage)
Aaron Durbinbd74a4b2015-03-06 23:17:33 -060043{
44 struct imd *imd;
45 const struct imd_entry *e;
46 struct stage_cache *meta;
47 void *c;
48
Arthur Heymans7c2994b2019-11-20 20:01:11 +010049 imd = &imd_stage_cache;
Aaron Durbinbd74a4b2015-03-06 23:17:33 -060050 e = imd_entry_add(imd, CBMEM_ID_STAGEx_META + stage_id, sizeof(*meta));
51
Marshall Dawson0876caa2018-01-30 15:54:52 -070052 if (e == NULL) {
53 printk(BIOS_DEBUG, "Error: Can't add %x metadata to imd\n",
54 CBMEM_ID_STAGEx_META + stage_id);
Aaron Durbinbd74a4b2015-03-06 23:17:33 -060055 return;
Marshall Dawson0876caa2018-01-30 15:54:52 -070056 }
Aaron Durbinbd74a4b2015-03-06 23:17:33 -060057
58 meta = imd_entry_at(imd, e);
59
60 meta->load_addr = (uintptr_t)prog_start(stage);
61 meta->entry_addr = (uintptr_t)prog_entry(stage);
Aaron Durbin3b16e782018-04-23 14:47:07 -060062 meta->arg = (uintptr_t)prog_entry_arg(stage);
Aaron Durbinbd74a4b2015-03-06 23:17:33 -060063
64 e = imd_entry_add(imd, CBMEM_ID_STAGEx_CACHE + stage_id,
65 prog_size(stage));
66
Marshall Dawson0876caa2018-01-30 15:54:52 -070067 if (e == NULL) {
68 printk(BIOS_DEBUG, "Error: Can't add stage_cache %x to imd\n",
69 CBMEM_ID_STAGEx_CACHE + stage_id);
Aaron Durbinbd74a4b2015-03-06 23:17:33 -060070 return;
Marshall Dawson0876caa2018-01-30 15:54:52 -070071 }
Aaron Durbinbd74a4b2015-03-06 23:17:33 -060072
73 c = imd_entry_at(imd, e);
74
75 memcpy(c, prog_start(stage), prog_size(stage));
76}
77
Marshall Dawson8d6e0e02018-01-30 15:33:23 -070078void stage_cache_add_raw(int stage_id, const void *base, const size_t size)
79{
80 struct imd *imd;
81 const struct imd_entry *e;
82 void *c;
83
Arthur Heymans7c2994b2019-11-20 20:01:11 +010084 imd = &imd_stage_cache;
Marshall Dawson8d6e0e02018-01-30 15:33:23 -070085 e = imd_entry_add(imd, CBMEM_ID_STAGEx_RAW + stage_id, size);
86 if (e == NULL) {
87 printk(BIOS_DEBUG, "Error: Can't add %x raw data to imd\n",
88 CBMEM_ID_STAGEx_RAW + stage_id);
89 return;
90 }
91
92 c = imd_entry_at(imd, e);
93 if (c == NULL) {
94 printk(BIOS_DEBUG, "Error: Can't get %x raw entry in imd\n",
95 CBMEM_ID_STAGEx_RAW + stage_id);
96 return;
97 }
98
99 memcpy(c, base, size);
100}
101
102void stage_cache_get_raw(int stage_id, void **base, size_t *size)
103{
104 struct imd *imd;
105 const struct imd_entry *e;
106
Arthur Heymans7c2994b2019-11-20 20:01:11 +0100107 imd = &imd_stage_cache;
Marshall Dawson8d6e0e02018-01-30 15:33:23 -0700108 e = imd_entry_find(imd, CBMEM_ID_STAGEx_RAW + stage_id);
109 if (e == NULL) {
110 printk(BIOS_DEBUG, "Error: Can't find %x raw data to imd\n",
111 CBMEM_ID_STAGEx_RAW + stage_id);
112 return;
113 }
114
115 *base = imd_entry_at(imd, e);
116 *size = imd_entry_size(imd, e);
117}
118
Aaron Durbinbd74a4b2015-03-06 23:17:33 -0600119void stage_cache_load_stage(int stage_id, struct prog *stage)
120{
121 struct imd *imd;
122 struct stage_cache *meta;
123 const struct imd_entry *e;
124 void *c;
125 size_t size;
126
Arthur Heymans7c2994b2019-11-20 20:01:11 +0100127 imd = &imd_stage_cache;
Aaron Durbinbd74a4b2015-03-06 23:17:33 -0600128 e = imd_entry_find(imd, CBMEM_ID_STAGEx_META + stage_id);
Marshall Dawson0876caa2018-01-30 15:54:52 -0700129 if (e == NULL) {
130 printk(BIOS_DEBUG, "Error: Can't find %x metadata in imd\n",
131 CBMEM_ID_STAGEx_META + stage_id);
Aaron Durbinbd74a4b2015-03-06 23:17:33 -0600132 return;
Marshall Dawson0876caa2018-01-30 15:54:52 -0700133 }
Aaron Durbinbd74a4b2015-03-06 23:17:33 -0600134
135 meta = imd_entry_at(imd, e);
136
137 e = imd_entry_find(imd, CBMEM_ID_STAGEx_CACHE + stage_id);
138
Marshall Dawson0876caa2018-01-30 15:54:52 -0700139 if (e == NULL) {
140 printk(BIOS_DEBUG, "Error: Can't find stage_cache %x in imd\n",
141 CBMEM_ID_STAGEx_CACHE + stage_id);
Aaron Durbinbd74a4b2015-03-06 23:17:33 -0600142 return;
Marshall Dawson0876caa2018-01-30 15:54:52 -0700143 }
Aaron Durbinbd74a4b2015-03-06 23:17:33 -0600144
145 c = imd_entry_at(imd, e);
146 size = imd_entry_size(imd, e);
147
148 memcpy((void *)(uintptr_t)meta->load_addr, c, size);
149
150 prog_set_area(stage, (void *)(uintptr_t)meta->load_addr, size);
Aaron Durbin3b16e782018-04-23 14:47:07 -0600151 prog_set_entry(stage, (void *)(uintptr_t)meta->entry_addr,
152 (void *)(uintptr_t)meta->arg);
Aaron Durbinbd74a4b2015-03-06 23:17:33 -0600153}
154
Aaron Durbin42e68562015-06-09 13:55:51 -0500155static void stage_cache_setup(int is_recovery)
Aaron Durbinbd74a4b2015-03-06 23:17:33 -0600156{
Aaron Durbin42e68562015-06-09 13:55:51 -0500157 if (is_recovery)
158 stage_cache_recover();
159 else
160 stage_cache_create_empty();
Aaron Durbinbd74a4b2015-03-06 23:17:33 -0600161}
Aaron Durbin42e68562015-06-09 13:55:51 -0500162
163ROMSTAGE_CBMEM_INIT_HOOK(stage_cache_setup)
164RAMSTAGE_CBMEM_INIT_HOOK(stage_cache_setup)
Brandon Breitenstein135eae92016-09-30 13:57:12 -0700165POSTCAR_CBMEM_INIT_HOOK(stage_cache_setup)