blob: a35ce37ccc17266d84835d07bfcd60856fbf1fe5 [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
62 e = imd_entry_add(imd, CBMEM_ID_STAGEx_CACHE + stage_id,
63 prog_size(stage));
64
Marshall Dawson0876caa2018-01-30 15:54:52 -070065 if (e == NULL) {
66 printk(BIOS_DEBUG, "Error: Can't add stage_cache %x to imd\n",
67 CBMEM_ID_STAGEx_CACHE + stage_id);
Aaron Durbinbd74a4b2015-03-06 23:17:33 -060068 return;
Marshall Dawson0876caa2018-01-30 15:54:52 -070069 }
Aaron Durbinbd74a4b2015-03-06 23:17:33 -060070
71 c = imd_entry_at(imd, e);
72
73 memcpy(c, prog_start(stage), prog_size(stage));
74}
75
Marshall Dawson8d6e0e02018-01-30 15:33:23 -070076void stage_cache_add_raw(int stage_id, const void *base, const size_t size)
77{
78 struct imd *imd;
79 const struct imd_entry *e;
80 void *c;
81
Arthur Heymans7c2994b2019-11-20 20:01:11 +010082 imd = &imd_stage_cache;
Marshall Dawson8d6e0e02018-01-30 15:33:23 -070083 e = imd_entry_add(imd, CBMEM_ID_STAGEx_RAW + stage_id, size);
84 if (e == NULL) {
85 printk(BIOS_DEBUG, "Error: Can't add %x raw data to imd\n",
86 CBMEM_ID_STAGEx_RAW + stage_id);
87 return;
88 }
89
90 c = imd_entry_at(imd, e);
91 if (c == NULL) {
92 printk(BIOS_DEBUG, "Error: Can't get %x raw entry in imd\n",
93 CBMEM_ID_STAGEx_RAW + stage_id);
94 return;
95 }
96
97 memcpy(c, base, size);
98}
99
100void stage_cache_get_raw(int stage_id, void **base, size_t *size)
101{
102 struct imd *imd;
103 const struct imd_entry *e;
104
Arthur Heymans7c2994b2019-11-20 20:01:11 +0100105 imd = &imd_stage_cache;
Marshall Dawson8d6e0e02018-01-30 15:33:23 -0700106 e = imd_entry_find(imd, CBMEM_ID_STAGEx_RAW + stage_id);
107 if (e == NULL) {
108 printk(BIOS_DEBUG, "Error: Can't find %x raw data to imd\n",
109 CBMEM_ID_STAGEx_RAW + stage_id);
110 return;
111 }
112
113 *base = imd_entry_at(imd, e);
Anna Karas215e7fc2020-07-16 14:12:30 +0200114 *size = imd_entry_size(e);
Marshall Dawson8d6e0e02018-01-30 15:33:23 -0700115}
116
Aaron Durbinbd74a4b2015-03-06 23:17:33 -0600117void stage_cache_load_stage(int stage_id, struct prog *stage)
118{
119 struct imd *imd;
120 struct stage_cache *meta;
121 const struct imd_entry *e;
122 void *c;
123 size_t size;
124
Arthur Heymans7c2994b2019-11-20 20:01:11 +0100125 imd = &imd_stage_cache;
Aaron Durbinbd74a4b2015-03-06 23:17:33 -0600126 e = imd_entry_find(imd, CBMEM_ID_STAGEx_META + stage_id);
Marshall Dawson0876caa2018-01-30 15:54:52 -0700127 if (e == NULL) {
128 printk(BIOS_DEBUG, "Error: Can't find %x metadata in imd\n",
129 CBMEM_ID_STAGEx_META + stage_id);
Aaron Durbinbd74a4b2015-03-06 23:17:33 -0600130 return;
Marshall Dawson0876caa2018-01-30 15:54:52 -0700131 }
Aaron Durbinbd74a4b2015-03-06 23:17:33 -0600132
133 meta = imd_entry_at(imd, e);
134
135 e = imd_entry_find(imd, CBMEM_ID_STAGEx_CACHE + stage_id);
136
Marshall Dawson0876caa2018-01-30 15:54:52 -0700137 if (e == NULL) {
138 printk(BIOS_DEBUG, "Error: Can't find stage_cache %x in imd\n",
139 CBMEM_ID_STAGEx_CACHE + stage_id);
Aaron Durbinbd74a4b2015-03-06 23:17:33 -0600140 return;
Marshall Dawson0876caa2018-01-30 15:54:52 -0700141 }
Aaron Durbinbd74a4b2015-03-06 23:17:33 -0600142
143 c = imd_entry_at(imd, e);
Anna Karas215e7fc2020-07-16 14:12:30 +0200144 size = imd_entry_size(e);
Aaron Durbinbd74a4b2015-03-06 23:17:33 -0600145
146 memcpy((void *)(uintptr_t)meta->load_addr, c, size);
147
148 prog_set_area(stage, (void *)(uintptr_t)meta->load_addr, size);
Aaron Durbin3b16e782018-04-23 14:47:07 -0600149 prog_set_entry(stage, (void *)(uintptr_t)meta->entry_addr,
150 (void *)(uintptr_t)meta->arg);
Aaron Durbinbd74a4b2015-03-06 23:17:33 -0600151}
152
Aaron Durbin42e68562015-06-09 13:55:51 -0500153static void stage_cache_setup(int is_recovery)
Aaron Durbinbd74a4b2015-03-06 23:17:33 -0600154{
Aaron Durbin42e68562015-06-09 13:55:51 -0500155 if (is_recovery)
156 stage_cache_recover();
157 else
158 stage_cache_create_empty();
Aaron Durbinbd74a4b2015-03-06 23:17:33 -0600159}
Aaron Durbin42e68562015-06-09 13:55:51 -0500160
Kyösti Mälkkifa3bc042022-03-31 07:40:10 +0300161CBMEM_READY_HOOK(stage_cache_setup);