blob: 226d8d77b536e250ebb9c5d0b21214957d702d93 [file] [log] [blame]
Furquan Shaikh2af76f42014-04-28 16:39:40 -07001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright 2013 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <arch/cache.h>
Furquan Shaikh441df532014-09-11 16:06:01 -070021#include <arch/lib_helpers.h>
Furquan Shaikhabde3b52014-08-26 15:39:51 -070022#include <arch/secmon.h>
Furquan Shaikh2af76f42014-04-28 16:39:40 -070023#include <arch/stages.h>
Aaron Durbin5add4352014-09-17 11:43:20 -050024#include <arch/spintable.h>
Furquan Shaikh441df532014-09-11 16:06:01 -070025#include <arch/transition.h>
Julius Werner745a75f2015-05-11 16:45:56 -070026#include <arm_tf.h>
27#include <cbmem.h>
Furquan Shaikh2af76f42014-04-28 16:39:40 -070028#include <console/console.h>
Aaron Durbin04654a22015-03-17 11:43:44 -050029#include <program_loading.h>
Aaron Durbinb3847e62015-03-20 15:55:08 -050030#include <rules.h>
Furquan Shaikh441df532014-09-11 16:06:01 -070031#include <string.h>
Furquan Shaikh2af76f42014-04-28 16:39:40 -070032
Aaron Durbinb3847e62015-03-20 15:55:08 -050033static void run_payload(struct prog *prog)
Furquan Shaikh2af76f42014-04-28 16:39:40 -070034{
Aaron Durbin3948e532015-03-20 13:00:20 -050035 void (*doit)(void *);
36 void *arg;
Furquan Shaikhabde3b52014-08-26 15:39:51 -070037
Aaron Durbinb3847e62015-03-20 15:55:08 -050038 doit = prog_entry(prog);
39 arg = prog_entry_arg(prog);
Julius Wernerda3a1462015-05-13 11:19:33 -070040 u64 payload_spsr = SPSR_EXCEPTION_MASK | get_eret_el(EL2, SPSR_USE_L);
Aaron Durbin3948e532015-03-20 13:00:20 -050041
Julius Werner745a75f2015-05-11 16:45:56 -070042 if (IS_ENABLED(CONFIG_ARM64_USE_ARM_TRUSTED_FIRMWARE))
43 arm_tf_run_bl31((u64)doit, (u64)arg, payload_spsr);
44 else if (IS_ENABLED(CONFIG_ARM64_USE_SECURE_MONITOR))
Julius Werner786b1222015-05-07 16:59:31 -070045 secmon_run(doit, arg);
46 else {
Julius Wernerf52602a2015-05-07 16:59:31 -070047 uint8_t current_el = get_current_el();
48
Julius Werner786b1222015-05-07 16:59:31 -070049 /* Start the other CPUs spinning. */
Julius Wernerb436ce12015-05-07 16:59:31 -070050 if (IS_ENABLED(CONFIG_ARM64_USE_SPINTABLE))
51 spintable_start();
Furquan Shaikhabde3b52014-08-26 15:39:51 -070052
Julius Werner883ec982015-05-07 16:59:31 -070053 cache_sync_instructions();
54
Julius Wernerf52602a2015-05-07 16:59:31 -070055 printk(BIOS_SPEW, "entry = %p\n", doit);
56
Julius Werner786b1222015-05-07 16:59:31 -070057 /* If current EL is not EL3, jump to payload at same EL. */
Julius Wernerbbca3a92015-05-07 16:59:31 -070058 if (current_el != EL3)
Julius Werner786b1222015-05-07 16:59:31 -070059 doit(arg);
Julius Wernerbbca3a92015-05-07 16:59:31 -070060 else {
61 /* If current EL is EL3, we transition to payload in EL2. */
62 struct exc_state exc_state;
63 memset(&exc_state, 0, sizeof(exc_state));
Julius Werner745a75f2015-05-11 16:45:56 -070064 exc_state.elx.spsr = payload_spsr;
Julius Wernerbbca3a92015-05-07 16:59:31 -070065
66 transition_with_entry(doit, arg, &exc_state);
Julius Werner786b1222015-05-07 16:59:31 -070067 }
Furquan Shaikh441df532014-09-11 16:06:01 -070068 }
Furquan Shaikh2af76f42014-04-28 16:39:40 -070069}
Aaron Durbinb3847e62015-03-20 15:55:08 -050070
71void arch_prog_run(struct prog *prog)
72{
73 void (*doit)(void *);
74 void *arg;
75
Paul Menzel9484f552015-04-05 18:30:05 +020076 if (ENV_RAMSTAGE && prog->type == PROG_PAYLOAD) {
Aaron Durbinb3847e62015-03-20 15:55:08 -050077 run_payload(prog);
78 return;
Paul Menzel9484f552015-04-05 18:30:05 +020079 }
Aaron Durbinb3847e62015-03-20 15:55:08 -050080
81 doit = prog_entry(prog);
82 arg = prog_entry_arg(prog);
83
84 doit(prog_entry_arg(prog));
85}