blob: 299cb00dcffaff94fba982c49d90e35129c494ba [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 <cbmem.h>
18#include <stage_cache.h>
19#include <string.h>
Marshall Dawson0876caa2018-01-30 15:54:52 -070020#include <console/console.h>
Aaron Durbinbd74a4b2015-03-06 23:17:33 -060021
Aaron Durbinbd74a4b2015-03-06 23:17:33 -060022/* Stage cache uses cbmem. */
Aaron Durbin54546c92015-08-05 00:52:13 -050023void stage_cache_add(int stage_id, const struct prog *stage)
Aaron Durbinbd74a4b2015-03-06 23:17:33 -060024{
25 struct stage_cache *meta;
26 void *c;
27
28 meta = cbmem_add(CBMEM_ID_STAGEx_META + stage_id, sizeof(*meta));
Marshall Dawson0876caa2018-01-30 15:54:52 -070029 if (meta == NULL) {
30 printk(BIOS_ERR, "Error: Can't add %x metadata to cbmem\n",
31 CBMEM_ID_STAGEx_META + stage_id);
Aaron Durbinbd74a4b2015-03-06 23:17:33 -060032 return;
Marshall Dawson0876caa2018-01-30 15:54:52 -070033 }
Aaron Durbinbd74a4b2015-03-06 23:17:33 -060034 meta->load_addr = (uintptr_t)prog_start(stage);
35 meta->entry_addr = (uintptr_t)prog_entry(stage);
Kyösti Mälkkid87e4b32017-09-05 22:43:05 +030036 meta->arg = (uintptr_t)prog_entry_arg(stage);
Aaron Durbinbd74a4b2015-03-06 23:17:33 -060037
38 c = cbmem_add(CBMEM_ID_STAGEx_CACHE + stage_id, prog_size(stage));
Marshall Dawson0876caa2018-01-30 15:54:52 -070039 if (c == NULL) {
40 printk(BIOS_ERR, "Error: Can't add stage_cache %x to cbmem\n",
41 CBMEM_ID_STAGEx_CACHE + stage_id);
Aaron Durbinbd74a4b2015-03-06 23:17:33 -060042 return;
Marshall Dawson0876caa2018-01-30 15:54:52 -070043 }
Aaron Durbinbd74a4b2015-03-06 23:17:33 -060044
45 memcpy(c, prog_start(stage), prog_size(stage));
46}
47
Marshall Dawson8d6e0e02018-01-30 15:33:23 -070048void stage_cache_add_raw(int stage_id, const void *base, const size_t size)
49{
50 void *c;
51
52 c = cbmem_add(CBMEM_ID_STAGEx_RAW + stage_id, size);
53 if (c == NULL) {
54 printk(BIOS_DEBUG, "Error: Can't add %x raw data to cbmem\n",
55 CBMEM_ID_STAGEx_RAW + stage_id);
56 return;
57 }
58
59 memcpy(c, base, size);
60}
61
62void stage_cache_get_raw(int stage_id, void **base, size_t *size)
63{
64 const struct cbmem_entry *e;
65
66 e = cbmem_entry_find(CBMEM_ID_STAGEx_RAW + stage_id);
67 if (e == NULL) {
68 printk(BIOS_ERR, "Error: Can't find raw %x data in cbmem\n",
69 CBMEM_ID_STAGEx_RAW + stage_id);
70 return;
71 }
72
73 *base = cbmem_entry_start(e);
74 *size = cbmem_entry_size(e);
75}
76
Aaron Durbinbd74a4b2015-03-06 23:17:33 -060077void stage_cache_load_stage(int stage_id, struct prog *stage)
78{
79 struct stage_cache *meta;
80 const struct cbmem_entry *e;
81 void *c;
82 size_t size;
83 void *load_addr;
84
85 prog_set_entry(stage, NULL, NULL);
86
87 meta = cbmem_find(CBMEM_ID_STAGEx_META + stage_id);
Marshall Dawson0876caa2018-01-30 15:54:52 -070088 if (meta == NULL) {
89 printk(BIOS_ERR, "Error: Can't find %x metadata in cbmem\n",
90 CBMEM_ID_STAGEx_META + stage_id);
Aaron Durbinbd74a4b2015-03-06 23:17:33 -060091 return;
Marshall Dawson0876caa2018-01-30 15:54:52 -070092 }
Aaron Durbinbd74a4b2015-03-06 23:17:33 -060093
94 e = cbmem_entry_find(CBMEM_ID_STAGEx_CACHE + stage_id);
95
Marshall Dawson0876caa2018-01-30 15:54:52 -070096 if (e == NULL) {
97 printk(BIOS_ERR, "Error: Can't find stage_cache %x in cbmem\n",
98 CBMEM_ID_STAGEx_CACHE + stage_id);
Aaron Durbinbd74a4b2015-03-06 23:17:33 -060099 return;
Marshall Dawson0876caa2018-01-30 15:54:52 -0700100 }
Aaron Durbinbd74a4b2015-03-06 23:17:33 -0600101
102 c = cbmem_entry_start(e);
103 size = cbmem_entry_size(e);
104 load_addr = (void *)(uintptr_t)meta->load_addr;
105
106 memcpy(load_addr, c, size);
107
108 prog_set_area(stage, load_addr, size);
Kyösti Mälkkid87e4b32017-09-05 22:43:05 +0300109 prog_set_entry(stage, (void *)(uintptr_t)meta->entry_addr,
110 (void *)(uintptr_t)meta->arg);
Aaron Durbinbd74a4b2015-03-06 23:17:33 -0600111}