blob: 7c00abad711ceb8db834529c9733c51d68dffcfe [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
63void __attribute__((weak)) stage_cache_add(int stage_id, struct prog *stage) {}
64void __attribute__((weak)) stage_cache_load_stage(int stage_id,
65 struct prog *stage) {}
66void __attribute__((weak)) ramstage_cache_invalid(void) {}
67
68static void run_ramstage_from_resume(struct romstage_handoff *handoff,
69 struct prog *ramstage)
70{
71 if (handoff != NULL && handoff->s3_resume) {
72 /* Load the cached ramstage to runtime location. */
73 stage_cache_load_stage(STAGE_RAMSTAGE, ramstage);
74
75 if (prog_entry(ramstage) != NULL) {
76 printk(BIOS_DEBUG, "Jumping to image.\n");
77 prog_run(ramstage);
78 }
79 ramstage_cache_invalid();
80 }
81}
82
83static int load_relocatable_ramstage(struct prog *ramstage)
84{
85 struct rmod_stage_load rmod_ram = {
86 .cbmem_id = CBMEM_ID_RAMSTAGE,
87 .prog = ramstage,
88 };
89
90 return rmodule_stage_load(&rmod_ram);
91}
92
93void run_ramstage(void)
94{
Aaron Durbinac12c66c2015-05-20 12:08:55 -050095 struct prog ramstage =
96 PROG_INIT(ASSET_RAMSTAGE, CONFIG_CBFS_PREFIX "/ramstage");
Aaron Durbin899d13d2015-05-15 23:39:23 -050097
98 /* Only x86 systems currently take the same firmware path on resume. */
99 if (IS_ENABLED(CONFIG_ARCH_X86) && IS_ENABLED(CONFIG_EARLY_CBMEM_INIT))
100 run_ramstage_from_resume(romstage_handoff_find_or_add(),
101 &ramstage);
102
103 if (prog_locate(&ramstage))
104 goto fail;
105
106 timestamp_add_now(TS_START_COPYRAM);
107
108 if (IS_ENABLED(CONFIG_RELOCATABLE_RAMSTAGE)) {
109 if (load_relocatable_ramstage(&ramstage))
110 goto fail;
111 } else if (cbfs_prog_stage_load(&ramstage))
112 goto fail;
113
114 stage_cache_add(STAGE_RAMSTAGE, &ramstage);
115
116 timestamp_add_now(TS_END_COPYRAM);
117
118 prog_run(&ramstage);
119
120fail:
121 die("Ramstage was not loaded!\n");
122}
123
Stefan Reinauereec2db42015-06-18 01:19:50 -0700124#ifdef __RAMSTAGE__ // gc-sections should take care of this
125
Aaron Durbinac12c66c2015-05-20 12:08:55 -0500126static struct prog global_payload =
127 PROG_INIT(ASSET_PAYLOAD, CONFIG_CBFS_PREFIX "/payload");
Aaron Durbin899d13d2015-05-15 23:39:23 -0500128
129void __attribute__((weak)) mirror_payload(struct prog *payload)
130{
131 return;
132}
133
134void payload_load(void)
135{
136 struct prog *payload = &global_payload;
137
138 timestamp_add_now(TS_LOAD_PAYLOAD);
139
140 if (prog_locate(payload))
141 goto out;
142
143 mirror_payload(payload);
144
145 /* Pass cbtables to payload if architecture desires it. */
146 prog_set_entry(payload, selfload(payload),
147 cbmem_find(CBMEM_ID_CBTABLE));
148
149out:
150 if (prog_entry(payload) == NULL)
151 die("Payload not loaded.\n");
152}
153
154void payload_run(void)
155{
156 struct prog *payload = &global_payload;
157
158 /* Reset to booting from this image as late as possible */
159 boot_successful();
160
161 printk(BIOS_DEBUG, "Jumping to boot code at %p(%p)\n",
162 prog_entry(payload), prog_entry_arg(payload));
163
164 post_code(POST_ENTER_ELF_BOOT);
165
166 timestamp_add_now(TS_SELFBOOT_JUMP);
167
168 /* Before we go off to run the payload, see if
169 * we stayed within our bounds.
170 */
171 checkstack(_estack, 0);
172
173 prog_run(payload);
174}
Stefan Reinauereec2db42015-06-18 01:19:50 -0700175
176#endif