blob: ec5eeb8693567e430bdcc9524887994887c8b512 [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
Aaron Durbinac12c66c2015-05-20 12:08:55 -0500124static struct prog global_payload =
125 PROG_INIT(ASSET_PAYLOAD, CONFIG_CBFS_PREFIX "/payload");
Aaron Durbin899d13d2015-05-15 23:39:23 -0500126
127void __attribute__((weak)) mirror_payload(struct prog *payload)
128{
129 return;
130}
131
132void payload_load(void)
133{
134 struct prog *payload = &global_payload;
135
136 timestamp_add_now(TS_LOAD_PAYLOAD);
137
138 if (prog_locate(payload))
139 goto out;
140
141 mirror_payload(payload);
142
143 /* Pass cbtables to payload if architecture desires it. */
144 prog_set_entry(payload, selfload(payload),
145 cbmem_find(CBMEM_ID_CBTABLE));
146
147out:
148 if (prog_entry(payload) == NULL)
149 die("Payload not loaded.\n");
150}
151
152void payload_run(void)
153{
154 struct prog *payload = &global_payload;
155
156 /* Reset to booting from this image as late as possible */
157 boot_successful();
158
159 printk(BIOS_DEBUG, "Jumping to boot code at %p(%p)\n",
160 prog_entry(payload), prog_entry_arg(payload));
161
162 post_code(POST_ENTER_ELF_BOOT);
163
164 timestamp_add_now(TS_SELFBOOT_JUMP);
165
166 /* Before we go off to run the payload, see if
167 * we stayed within our bounds.
168 */
169 checkstack(_estack, 0);
170
171 prog_run(payload);
172}