blob: 2f4a2c118ab3d5e2d00444c46b7ef585b4ae57c4 [file] [log] [blame]
Aaron Durbin899d13d2015-05-15 23:39:23 -05001/*
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.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc.
18 */
19
20
21#include <stdlib.h>
22#include <arch/stages.h>
Aaron Durbin899d13d2015-05-15 23:39:23 -050023#include <cbfs.h>
24#include <cbmem.h>
25#include <console/console.h>
26#include <fallback.h>
27#include <halt.h>
28#include <lib.h>
29#include <program_loading.h>
30#include <romstage_handoff.h>
31#include <rmodule.h>
32#include <rules.h>
33#include <stage_cache.h>
34#include <symbols.h>
35#include <timestamp.h>
36
Aaron Durbin6a452ef2015-05-19 16:25:20 -050037/* Only can represent up to 1 byte less than size_t. */
38const struct mem_region_device addrspace_32bit = MEM_REGION_DEV_INIT(0, ~0UL);
39
Aaron Durbin899d13d2015-05-15 23:39:23 -050040void run_romstage(void)
41{
Aaron Durbinac12c66c2015-05-20 12:08:55 -050042 struct prog romstage =
43 PROG_INIT(ASSET_ROMSTAGE, CONFIG_CBFS_PREFIX "/romstage");
Aaron Durbin899d13d2015-05-15 23:39:23 -050044
45 if (prog_locate(&romstage))
46 goto fail;
47
48 timestamp_add_now(TS_START_COPYROM);
49
50 if (cbfs_prog_stage_load(&romstage))
51 goto fail;
52
53 timestamp_add_now(TS_END_COPYROM);
54
55 prog_run(&romstage);
56
57fail:
58 if (IS_ENABLED(CONFIG_BOOTBLOCK_CONSOLE))
59 die("Couldn't load romstage.\n");
60 halt();
61}
62
Aaron Durbin54546c92015-08-05 00:52:13 -050063void __attribute__((weak)) stage_cache_add(int stage_id,
64 const struct prog *stage) {}
Aaron Durbin899d13d2015-05-15 23:39:23 -050065void __attribute__((weak)) stage_cache_load_stage(int stage_id,
66 struct prog *stage) {}
67void __attribute__((weak)) ramstage_cache_invalid(void) {}
68
69static void run_ramstage_from_resume(struct romstage_handoff *handoff,
70 struct prog *ramstage)
71{
72 if (handoff != NULL && handoff->s3_resume) {
73 /* Load the cached ramstage to runtime location. */
74 stage_cache_load_stage(STAGE_RAMSTAGE, ramstage);
75
76 if (prog_entry(ramstage) != NULL) {
77 printk(BIOS_DEBUG, "Jumping to image.\n");
78 prog_run(ramstage);
79 }
80 ramstage_cache_invalid();
81 }
82}
83
84static int load_relocatable_ramstage(struct prog *ramstage)
85{
86 struct rmod_stage_load rmod_ram = {
87 .cbmem_id = CBMEM_ID_RAMSTAGE,
88 .prog = ramstage,
89 };
90
91 return rmodule_stage_load(&rmod_ram);
92}
93
94void run_ramstage(void)
95{
Aaron Durbinac12c66c2015-05-20 12:08:55 -050096 struct prog ramstage =
97 PROG_INIT(ASSET_RAMSTAGE, CONFIG_CBFS_PREFIX "/ramstage");
Aaron Durbin899d13d2015-05-15 23:39:23 -050098
99 /* Only x86 systems currently take the same firmware path on resume. */
100 if (IS_ENABLED(CONFIG_ARCH_X86) && IS_ENABLED(CONFIG_EARLY_CBMEM_INIT))
101 run_ramstage_from_resume(romstage_handoff_find_or_add(),
102 &ramstage);
103
104 if (prog_locate(&ramstage))
105 goto fail;
106
107 timestamp_add_now(TS_START_COPYRAM);
108
109 if (IS_ENABLED(CONFIG_RELOCATABLE_RAMSTAGE)) {
110 if (load_relocatable_ramstage(&ramstage))
111 goto fail;
112 } else if (cbfs_prog_stage_load(&ramstage))
113 goto fail;
114
115 stage_cache_add(STAGE_RAMSTAGE, &ramstage);
116
117 timestamp_add_now(TS_END_COPYRAM);
118
119 prog_run(&ramstage);
120
121fail:
122 die("Ramstage was not loaded!\n");
123}
124
Stefan Reinauereec2db42015-06-18 01:19:50 -0700125#ifdef __RAMSTAGE__ // gc-sections should take care of this
126
Aaron Durbinac12c66c2015-05-20 12:08:55 -0500127static struct prog global_payload =
128 PROG_INIT(ASSET_PAYLOAD, CONFIG_CBFS_PREFIX "/payload");
Aaron Durbin899d13d2015-05-15 23:39:23 -0500129
130void __attribute__((weak)) mirror_payload(struct prog *payload)
131{
132 return;
133}
134
135void payload_load(void)
136{
137 struct prog *payload = &global_payload;
138
139 timestamp_add_now(TS_LOAD_PAYLOAD);
140
141 if (prog_locate(payload))
142 goto out;
143
144 mirror_payload(payload);
145
146 /* Pass cbtables to payload if architecture desires it. */
147 prog_set_entry(payload, selfload(payload),
148 cbmem_find(CBMEM_ID_CBTABLE));
149
150out:
151 if (prog_entry(payload) == NULL)
152 die("Payload not loaded.\n");
153}
154
155void payload_run(void)
156{
157 struct prog *payload = &global_payload;
158
159 /* Reset to booting from this image as late as possible */
160 boot_successful();
161
162 printk(BIOS_DEBUG, "Jumping to boot code at %p(%p)\n",
163 prog_entry(payload), prog_entry_arg(payload));
164
165 post_code(POST_ENTER_ELF_BOOT);
166
167 timestamp_add_now(TS_SELFBOOT_JUMP);
168
169 /* Before we go off to run the payload, see if
170 * we stayed within our bounds.
171 */
172 checkstack(_estack, 0);
173
174 prog_run(payload);
175}
Stefan Reinauereec2db42015-06-18 01:19:50 -0700176
177#endif