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