blob: 2a991889f4d18cee75036a1381bf67b1358cf80f [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>
21#include <rules.h>
22#include <stage_cache.h>
23#include <string.h>
24
25static struct imd imd_stage_cache CAR_GLOBAL = { };
26
27static inline struct imd *imd_get(void)
28{
29 return car_get_var_ptr(&imd_stage_cache);
30}
31
Aaron Durbin42e68562015-06-09 13:55:51 -050032static void stage_cache_create_empty(void)
Aaron Durbinbd74a4b2015-03-06 23:17:33 -060033{
34 struct imd *imd;
35 void *base;
36 size_t size;
37
38 imd = imd_get();
39 stage_cache_external_region(&base, &size);
40 imd_handle_init(imd, (void *)(size + (uintptr_t)base));
41
42 printk(BIOS_DEBUG, "External stage cache:\n");
43 imd_create_tiered_empty(imd, 4096, 4096, 1024, 32);
44 if (imd_limit_size(imd, size))
45 printk(BIOS_DEBUG, "Could not limit stage cache size.\n");
46}
47
Aaron Durbin42e68562015-06-09 13:55:51 -050048static void stage_cache_recover(void)
Aaron Durbinbd74a4b2015-03-06 23:17:33 -060049{
50 struct imd *imd;
51 void *base;
52 size_t size;
53
54 imd = imd_get();
55 stage_cache_external_region(&base, &size);
56 imd_handle_init(imd, (void *)(size + (uintptr_t)base));
57 if (imd_recover(imd))
58 printk(BIOS_DEBUG, "Unable to recover external stage cache.\n");
59}
60
Aaron Durbin54546c92015-08-05 00:52:13 -050061void stage_cache_add(int stage_id, const struct prog *stage)
Aaron Durbinbd74a4b2015-03-06 23:17:33 -060062{
63 struct imd *imd;
64 const struct imd_entry *e;
65 struct stage_cache *meta;
66 void *c;
67
68 imd = imd_get();
69 e = imd_entry_add(imd, CBMEM_ID_STAGEx_META + stage_id, sizeof(*meta));
70
71 if (e == NULL)
72 return;
73
74 meta = imd_entry_at(imd, e);
75
76 meta->load_addr = (uintptr_t)prog_start(stage);
77 meta->entry_addr = (uintptr_t)prog_entry(stage);
78
79 e = imd_entry_add(imd, CBMEM_ID_STAGEx_CACHE + stage_id,
80 prog_size(stage));
81
82 if (e == NULL)
83 return;
84
85 c = imd_entry_at(imd, e);
86
87 memcpy(c, prog_start(stage), prog_size(stage));
88}
89
90void stage_cache_load_stage(int stage_id, struct prog *stage)
91{
92 struct imd *imd;
93 struct stage_cache *meta;
94 const struct imd_entry *e;
95 void *c;
96 size_t size;
97
98 imd = imd_get();
99 e = imd_entry_find(imd, CBMEM_ID_STAGEx_META + stage_id);
100 if (e == NULL)
101 return;
102
103 meta = imd_entry_at(imd, e);
104
105 e = imd_entry_find(imd, CBMEM_ID_STAGEx_CACHE + stage_id);
106
107 if (e == NULL)
108 return;
109
110 c = imd_entry_at(imd, e);
111 size = imd_entry_size(imd, e);
112
113 memcpy((void *)(uintptr_t)meta->load_addr, c, size);
114
115 prog_set_area(stage, (void *)(uintptr_t)meta->load_addr, size);
116 prog_set_entry(stage, (void *)(uintptr_t)meta->entry_addr, NULL);
117}
118
Aaron Durbin42e68562015-06-09 13:55:51 -0500119static void stage_cache_setup(int is_recovery)
Aaron Durbinbd74a4b2015-03-06 23:17:33 -0600120{
Aaron Durbin42e68562015-06-09 13:55:51 -0500121 if (is_recovery)
122 stage_cache_recover();
123 else
124 stage_cache_create_empty();
Aaron Durbinbd74a4b2015-03-06 23:17:33 -0600125}
Aaron Durbin42e68562015-06-09 13:55:51 -0500126
127ROMSTAGE_CBMEM_INIT_HOOK(stage_cache_setup)
128RAMSTAGE_CBMEM_INIT_HOOK(stage_cache_setup)
Brandon Breitenstein135eae92016-09-30 13:57:12 -0700129POSTCAR_CBMEM_INIT_HOOK(stage_cache_setup)