blob: 354342d41b6095b0aa99ec599684ec0c10b095f6 [file] [log] [blame]
Aaron Durbinbd74a4b2015-03-06 23:17:33 -06001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright 2015 Google Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
Aaron Durbinbd74a4b2015-03-06 23:17:33 -060014 */
15
16#include <arch/early_variables.h>
17#include <bootstate.h>
18#include <cbmem.h>
19#include <console/console.h>
20#include <imd.h>
Aaron Durbinbd74a4b2015-03-06 23:17:33 -060021#include <stage_cache.h>
22#include <string.h>
23
24static struct imd imd_stage_cache CAR_GLOBAL = { };
25
26static inline struct imd *imd_get(void)
27{
28 return car_get_var_ptr(&imd_stage_cache);
29}
30
Aaron Durbin42e68562015-06-09 13:55:51 -050031static void stage_cache_create_empty(void)
Aaron Durbinbd74a4b2015-03-06 23:17:33 -060032{
33 struct imd *imd;
34 void *base;
35 size_t size;
36
37 imd = imd_get();
38 stage_cache_external_region(&base, &size);
39 imd_handle_init(imd, (void *)(size + (uintptr_t)base));
40
41 printk(BIOS_DEBUG, "External stage cache:\n");
42 imd_create_tiered_empty(imd, 4096, 4096, 1024, 32);
43 if (imd_limit_size(imd, size))
44 printk(BIOS_DEBUG, "Could not limit stage cache size.\n");
45}
46
Aaron Durbin42e68562015-06-09 13:55:51 -050047static void stage_cache_recover(void)
Aaron Durbinbd74a4b2015-03-06 23:17:33 -060048{
49 struct imd *imd;
50 void *base;
51 size_t size;
52
53 imd = imd_get();
54 stage_cache_external_region(&base, &size);
55 imd_handle_init(imd, (void *)(size + (uintptr_t)base));
56 if (imd_recover(imd))
57 printk(BIOS_DEBUG, "Unable to recover external stage cache.\n");
58}
59
Aaron Durbin54546c92015-08-05 00:52:13 -050060void stage_cache_add(int stage_id, const struct prog *stage)
Aaron Durbinbd74a4b2015-03-06 23:17:33 -060061{
62 struct imd *imd;
63 const struct imd_entry *e;
64 struct stage_cache *meta;
65 void *c;
66
67 imd = imd_get();
68 e = imd_entry_add(imd, CBMEM_ID_STAGEx_META + stage_id, sizeof(*meta));
69
Marshall Dawson0876caa2018-01-30 15:54:52 -070070 if (e == NULL) {
71 printk(BIOS_DEBUG, "Error: Can't add %x metadata to imd\n",
72 CBMEM_ID_STAGEx_META + stage_id);
Aaron Durbinbd74a4b2015-03-06 23:17:33 -060073 return;
Marshall Dawson0876caa2018-01-30 15:54:52 -070074 }
Aaron Durbinbd74a4b2015-03-06 23:17:33 -060075
76 meta = imd_entry_at(imd, e);
77
78 meta->load_addr = (uintptr_t)prog_start(stage);
79 meta->entry_addr = (uintptr_t)prog_entry(stage);
Aaron Durbin3b16e782018-04-23 14:47:07 -060080 meta->arg = (uintptr_t)prog_entry_arg(stage);
Aaron Durbinbd74a4b2015-03-06 23:17:33 -060081
82 e = imd_entry_add(imd, CBMEM_ID_STAGEx_CACHE + stage_id,
83 prog_size(stage));
84
Marshall Dawson0876caa2018-01-30 15:54:52 -070085 if (e == NULL) {
86 printk(BIOS_DEBUG, "Error: Can't add stage_cache %x to imd\n",
87 CBMEM_ID_STAGEx_CACHE + stage_id);
Aaron Durbinbd74a4b2015-03-06 23:17:33 -060088 return;
Marshall Dawson0876caa2018-01-30 15:54:52 -070089 }
Aaron Durbinbd74a4b2015-03-06 23:17:33 -060090
91 c = imd_entry_at(imd, e);
92
93 memcpy(c, prog_start(stage), prog_size(stage));
94}
95
Marshall Dawson8d6e0e02018-01-30 15:33:23 -070096void stage_cache_add_raw(int stage_id, const void *base, const size_t size)
97{
98 struct imd *imd;
99 const struct imd_entry *e;
100 void *c;
101
102 imd = imd_get();
103 e = imd_entry_add(imd, CBMEM_ID_STAGEx_RAW + stage_id, size);
104 if (e == NULL) {
105 printk(BIOS_DEBUG, "Error: Can't add %x raw data to imd\n",
106 CBMEM_ID_STAGEx_RAW + stage_id);
107 return;
108 }
109
110 c = imd_entry_at(imd, e);
111 if (c == NULL) {
112 printk(BIOS_DEBUG, "Error: Can't get %x raw entry in imd\n",
113 CBMEM_ID_STAGEx_RAW + stage_id);
114 return;
115 }
116
117 memcpy(c, base, size);
118}
119
120void stage_cache_get_raw(int stage_id, void **base, size_t *size)
121{
122 struct imd *imd;
123 const struct imd_entry *e;
124
125 imd = imd_get();
126 e = imd_entry_find(imd, CBMEM_ID_STAGEx_RAW + stage_id);
127 if (e == NULL) {
128 printk(BIOS_DEBUG, "Error: Can't find %x raw data to imd\n",
129 CBMEM_ID_STAGEx_RAW + stage_id);
130 return;
131 }
132
133 *base = imd_entry_at(imd, e);
134 *size = imd_entry_size(imd, e);
135}
136
Aaron Durbinbd74a4b2015-03-06 23:17:33 -0600137void stage_cache_load_stage(int stage_id, struct prog *stage)
138{
139 struct imd *imd;
140 struct stage_cache *meta;
141 const struct imd_entry *e;
142 void *c;
143 size_t size;
144
145 imd = imd_get();
146 e = imd_entry_find(imd, CBMEM_ID_STAGEx_META + stage_id);
Marshall Dawson0876caa2018-01-30 15:54:52 -0700147 if (e == NULL) {
148 printk(BIOS_DEBUG, "Error: Can't find %x metadata in imd\n",
149 CBMEM_ID_STAGEx_META + stage_id);
Aaron Durbinbd74a4b2015-03-06 23:17:33 -0600150 return;
Marshall Dawson0876caa2018-01-30 15:54:52 -0700151 }
Aaron Durbinbd74a4b2015-03-06 23:17:33 -0600152
153 meta = imd_entry_at(imd, e);
154
155 e = imd_entry_find(imd, CBMEM_ID_STAGEx_CACHE + stage_id);
156
Marshall Dawson0876caa2018-01-30 15:54:52 -0700157 if (e == NULL) {
158 printk(BIOS_DEBUG, "Error: Can't find stage_cache %x in imd\n",
159 CBMEM_ID_STAGEx_CACHE + stage_id);
Aaron Durbinbd74a4b2015-03-06 23:17:33 -0600160 return;
Marshall Dawson0876caa2018-01-30 15:54:52 -0700161 }
Aaron Durbinbd74a4b2015-03-06 23:17:33 -0600162
163 c = imd_entry_at(imd, e);
164 size = imd_entry_size(imd, e);
165
166 memcpy((void *)(uintptr_t)meta->load_addr, c, size);
167
168 prog_set_area(stage, (void *)(uintptr_t)meta->load_addr, size);
Aaron Durbin3b16e782018-04-23 14:47:07 -0600169 prog_set_entry(stage, (void *)(uintptr_t)meta->entry_addr,
170 (void *)(uintptr_t)meta->arg);
Aaron Durbinbd74a4b2015-03-06 23:17:33 -0600171}
172
Aaron Durbin42e68562015-06-09 13:55:51 -0500173static void stage_cache_setup(int is_recovery)
Aaron Durbinbd74a4b2015-03-06 23:17:33 -0600174{
Aaron Durbin42e68562015-06-09 13:55:51 -0500175 if (is_recovery)
176 stage_cache_recover();
177 else
178 stage_cache_create_empty();
Aaron Durbinbd74a4b2015-03-06 23:17:33 -0600179}
Aaron Durbin42e68562015-06-09 13:55:51 -0500180
181ROMSTAGE_CBMEM_INIT_HOOK(stage_cache_setup)
182RAMSTAGE_CBMEM_INIT_HOOK(stage_cache_setup)
Brandon Breitenstein135eae92016-09-30 13:57:12 -0700183POSTCAR_CBMEM_INIT_HOOK(stage_cache_setup)