blob: 462a635dc82aaf36000930efbc66704c9668b0d4 [file] [log] [blame]
Angel Pons118a9c72020-04-02 23:48:34 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Aaron Durbinbd74a4b2015-03-06 23:17:33 -06002
Aaron Durbinbd74a4b2015-03-06 23:17:33 -06003#include <cbmem.h>
4#include <console/console.h>
5#include <imd.h>
Aaron Durbinbd74a4b2015-03-06 23:17:33 -06006#include <stage_cache.h>
7#include <string.h>
8
Arthur Heymans7c2994b2019-11-20 20:01:11 +01009static struct imd imd_stage_cache;
Aaron Durbinbd74a4b2015-03-06 23:17:33 -060010
Aaron Durbin42e68562015-06-09 13:55:51 -050011static void stage_cache_create_empty(void)
Aaron Durbinbd74a4b2015-03-06 23:17:33 -060012{
13 struct imd *imd;
14 void *base;
15 size_t size;
16
Arthur Heymans7c2994b2019-11-20 20:01:11 +010017 imd = &imd_stage_cache;
Aaron Durbinbd74a4b2015-03-06 23:17:33 -060018 stage_cache_external_region(&base, &size);
19 imd_handle_init(imd, (void *)(size + (uintptr_t)base));
20
21 printk(BIOS_DEBUG, "External stage cache:\n");
22 imd_create_tiered_empty(imd, 4096, 4096, 1024, 32);
23 if (imd_limit_size(imd, size))
24 printk(BIOS_DEBUG, "Could not limit stage cache size.\n");
25}
26
Aaron Durbin42e68562015-06-09 13:55:51 -050027static void stage_cache_recover(void)
Aaron Durbinbd74a4b2015-03-06 23:17:33 -060028{
29 struct imd *imd;
30 void *base;
31 size_t size;
32
Arthur Heymans7c2994b2019-11-20 20:01:11 +010033 imd = &imd_stage_cache;
Aaron Durbinbd74a4b2015-03-06 23:17:33 -060034 stage_cache_external_region(&base, &size);
35 imd_handle_init(imd, (void *)(size + (uintptr_t)base));
36 if (imd_recover(imd))
37 printk(BIOS_DEBUG, "Unable to recover external stage cache.\n");
38}
39
Aaron Durbin54546c92015-08-05 00:52:13 -050040void stage_cache_add(int stage_id, const struct prog *stage)
Aaron Durbinbd74a4b2015-03-06 23:17:33 -060041{
42 struct imd *imd;
43 const struct imd_entry *e;
44 struct stage_cache *meta;
45 void *c;
46
Arthur Heymans7c2994b2019-11-20 20:01:11 +010047 imd = &imd_stage_cache;
Aaron Durbinbd74a4b2015-03-06 23:17:33 -060048 e = imd_entry_add(imd, CBMEM_ID_STAGEx_META + stage_id, sizeof(*meta));
49
Marshall Dawson0876caa2018-01-30 15:54:52 -070050 if (e == NULL) {
51 printk(BIOS_DEBUG, "Error: Can't add %x metadata to imd\n",
52 CBMEM_ID_STAGEx_META + stage_id);
Aaron Durbinbd74a4b2015-03-06 23:17:33 -060053 return;
Marshall Dawson0876caa2018-01-30 15:54:52 -070054 }
Aaron Durbinbd74a4b2015-03-06 23:17:33 -060055
56 meta = imd_entry_at(imd, e);
57
58 meta->load_addr = (uintptr_t)prog_start(stage);
59 meta->entry_addr = (uintptr_t)prog_entry(stage);
Aaron Durbin3b16e782018-04-23 14:47:07 -060060 meta->arg = (uintptr_t)prog_entry_arg(stage);
Aaron Durbinbd74a4b2015-03-06 23:17:33 -060061
Patrick Georgied0647a2023-12-13 17:57:34 +010062 unsigned int p_size = prog_size(stage);
63 if (stage_id == STAGE_RAMSTAGE) {
64 /* heap resides at the end of the image and will be
65 * reinitialized, so it doesn't make sense to copy it around.
66 */
67 p_size -= CONFIG_HEAP_SIZE;
68 }
69
70 e = imd_entry_add(imd, CBMEM_ID_STAGEx_CACHE + stage_id, p_size);
Aaron Durbinbd74a4b2015-03-06 23:17:33 -060071
Marshall Dawson0876caa2018-01-30 15:54:52 -070072 if (e == NULL) {
73 printk(BIOS_DEBUG, "Error: Can't add stage_cache %x to imd\n",
74 CBMEM_ID_STAGEx_CACHE + stage_id);
Aaron Durbinbd74a4b2015-03-06 23:17:33 -060075 return;
Marshall Dawson0876caa2018-01-30 15:54:52 -070076 }
Aaron Durbinbd74a4b2015-03-06 23:17:33 -060077
78 c = imd_entry_at(imd, e);
79
Patrick Georgied0647a2023-12-13 17:57:34 +010080 memcpy(c, prog_start(stage), p_size);
Aaron Durbinbd74a4b2015-03-06 23:17:33 -060081}
82
Marshall Dawson8d6e0e02018-01-30 15:33:23 -070083void stage_cache_add_raw(int stage_id, const void *base, const size_t size)
84{
85 struct imd *imd;
86 const struct imd_entry *e;
87 void *c;
88
Arthur Heymans7c2994b2019-11-20 20:01:11 +010089 imd = &imd_stage_cache;
Marshall Dawson8d6e0e02018-01-30 15:33:23 -070090 e = imd_entry_add(imd, CBMEM_ID_STAGEx_RAW + stage_id, size);
91 if (e == NULL) {
92 printk(BIOS_DEBUG, "Error: Can't add %x raw data to imd\n",
93 CBMEM_ID_STAGEx_RAW + stage_id);
94 return;
95 }
96
97 c = imd_entry_at(imd, e);
98 if (c == NULL) {
99 printk(BIOS_DEBUG, "Error: Can't get %x raw entry in imd\n",
100 CBMEM_ID_STAGEx_RAW + stage_id);
101 return;
102 }
103
104 memcpy(c, base, size);
105}
106
107void stage_cache_get_raw(int stage_id, void **base, size_t *size)
108{
109 struct imd *imd;
110 const struct imd_entry *e;
111
Arthur Heymans7c2994b2019-11-20 20:01:11 +0100112 imd = &imd_stage_cache;
Marshall Dawson8d6e0e02018-01-30 15:33:23 -0700113 e = imd_entry_find(imd, CBMEM_ID_STAGEx_RAW + stage_id);
114 if (e == NULL) {
115 printk(BIOS_DEBUG, "Error: Can't find %x raw data to imd\n",
116 CBMEM_ID_STAGEx_RAW + stage_id);
117 return;
118 }
119
120 *base = imd_entry_at(imd, e);
Anna Karas215e7fc2020-07-16 14:12:30 +0200121 *size = imd_entry_size(e);
Marshall Dawson8d6e0e02018-01-30 15:33:23 -0700122}
123
Aaron Durbinbd74a4b2015-03-06 23:17:33 -0600124void stage_cache_load_stage(int stage_id, struct prog *stage)
125{
126 struct imd *imd;
127 struct stage_cache *meta;
128 const struct imd_entry *e;
129 void *c;
130 size_t size;
131
Arthur Heymans7c2994b2019-11-20 20:01:11 +0100132 imd = &imd_stage_cache;
Aaron Durbinbd74a4b2015-03-06 23:17:33 -0600133 e = imd_entry_find(imd, CBMEM_ID_STAGEx_META + stage_id);
Marshall Dawson0876caa2018-01-30 15:54:52 -0700134 if (e == NULL) {
135 printk(BIOS_DEBUG, "Error: Can't find %x metadata in imd\n",
136 CBMEM_ID_STAGEx_META + stage_id);
Aaron Durbinbd74a4b2015-03-06 23:17:33 -0600137 return;
Marshall Dawson0876caa2018-01-30 15:54:52 -0700138 }
Aaron Durbinbd74a4b2015-03-06 23:17:33 -0600139
140 meta = imd_entry_at(imd, e);
141
142 e = imd_entry_find(imd, CBMEM_ID_STAGEx_CACHE + stage_id);
143
Marshall Dawson0876caa2018-01-30 15:54:52 -0700144 if (e == NULL) {
145 printk(BIOS_DEBUG, "Error: Can't find stage_cache %x in imd\n",
146 CBMEM_ID_STAGEx_CACHE + stage_id);
Aaron Durbinbd74a4b2015-03-06 23:17:33 -0600147 return;
Marshall Dawson0876caa2018-01-30 15:54:52 -0700148 }
Aaron Durbinbd74a4b2015-03-06 23:17:33 -0600149
150 c = imd_entry_at(imd, e);
Anna Karas215e7fc2020-07-16 14:12:30 +0200151 size = imd_entry_size(e);
Aaron Durbinbd74a4b2015-03-06 23:17:33 -0600152
153 memcpy((void *)(uintptr_t)meta->load_addr, c, size);
154
155 prog_set_area(stage, (void *)(uintptr_t)meta->load_addr, size);
Aaron Durbin3b16e782018-04-23 14:47:07 -0600156 prog_set_entry(stage, (void *)(uintptr_t)meta->entry_addr,
157 (void *)(uintptr_t)meta->arg);
Aaron Durbinbd74a4b2015-03-06 23:17:33 -0600158}
159
Aaron Durbin42e68562015-06-09 13:55:51 -0500160static void stage_cache_setup(int is_recovery)
Aaron Durbinbd74a4b2015-03-06 23:17:33 -0600161{
Aaron Durbin42e68562015-06-09 13:55:51 -0500162 if (is_recovery)
163 stage_cache_recover();
164 else
165 stage_cache_create_empty();
Aaron Durbinbd74a4b2015-03-06 23:17:33 -0600166}
Aaron Durbin42e68562015-06-09 13:55:51 -0500167
Kyösti Mälkkifa3bc042022-03-31 07:40:10 +0300168CBMEM_READY_HOOK(stage_cache_setup);