blob: f17f12c892607f332b644cacaf4acb53361d4f1e [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
48void stage_cache_load_stage(int stage_id, struct prog *stage)
49{
50 struct stage_cache *meta;
51 const struct cbmem_entry *e;
52 void *c;
53 size_t size;
54 void *load_addr;
55
56 prog_set_entry(stage, NULL, NULL);
57
58 meta = cbmem_find(CBMEM_ID_STAGEx_META + stage_id);
Marshall Dawson0876caa2018-01-30 15:54:52 -070059 if (meta == NULL) {
60 printk(BIOS_ERR, "Error: Can't find %x metadata in cbmem\n",
61 CBMEM_ID_STAGEx_META + stage_id);
Aaron Durbinbd74a4b2015-03-06 23:17:33 -060062 return;
Marshall Dawson0876caa2018-01-30 15:54:52 -070063 }
Aaron Durbinbd74a4b2015-03-06 23:17:33 -060064
65 e = cbmem_entry_find(CBMEM_ID_STAGEx_CACHE + stage_id);
66
Marshall Dawson0876caa2018-01-30 15:54:52 -070067 if (e == NULL) {
68 printk(BIOS_ERR, "Error: Can't find stage_cache %x in cbmem\n",
69 CBMEM_ID_STAGEx_CACHE + stage_id);
Aaron Durbinbd74a4b2015-03-06 23:17:33 -060070 return;
Marshall Dawson0876caa2018-01-30 15:54:52 -070071 }
Aaron Durbinbd74a4b2015-03-06 23:17:33 -060072
73 c = cbmem_entry_start(e);
74 size = cbmem_entry_size(e);
75 load_addr = (void *)(uintptr_t)meta->load_addr;
76
77 memcpy(load_addr, c, size);
78
79 prog_set_area(stage, load_addr, size);
Kyösti Mälkkid87e4b32017-09-05 22:43:05 +030080 prog_set_entry(stage, (void *)(uintptr_t)meta->entry_addr,
81 (void *)(uintptr_t)meta->arg);
Aaron Durbinbd74a4b2015-03-06 23:17:33 -060082}