Aaron Durbin | bdf913a | 2014-02-24 14:56:34 -0600 | [diff] [blame] | 1 | /* |
| 2 | * This file is part of the coreboot project. |
| 3 | * |
Aaron Durbin | 04654a2 | 2015-03-17 11:43:44 -0500 | [diff] [blame] | 4 | * Copyright 2015 Google Inc. |
Ionela Voinescu | 00903e5 | 2015-01-09 13:14:20 +0000 | [diff] [blame] | 5 | * Copyright (C) 2014 Imagination Technologies |
Aaron Durbin | bdf913a | 2014-02-24 14:56:34 -0600 | [diff] [blame] | 6 | * |
| 7 | * This program is free software; you can redistribute it and/or modify |
| 8 | * it under the terms of the GNU General Public License as published by |
| 9 | * the Free Software Foundation; version 2 of the License. |
| 10 | * |
| 11 | * This program is distributed in the hope that it will be useful, |
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 14 | * GNU General Public License for more details. |
Aaron Durbin | bdf913a | 2014-02-24 14:56:34 -0600 | [diff] [blame] | 15 | */ |
Aaron Durbin | 04654a2 | 2015-03-17 11:43:44 -0500 | [diff] [blame] | 16 | #ifndef PROGRAM_LOADING_H |
| 17 | #define PROGRAM_LOADING_H |
Aaron Durbin | bdf913a | 2014-02-24 14:56:34 -0600 | [diff] [blame] | 18 | |
Aaron Durbin | 7e7a4df | 2015-12-08 14:34:35 -0600 | [diff] [blame] | 19 | #include <commonlib/region.h> |
Aaron Durbin | bdf913a | 2014-02-24 14:56:34 -0600 | [diff] [blame] | 20 | #include <stdint.h> |
| 21 | #include <stddef.h> |
| 22 | |
Aaron Durbin | 6e76fff | 2015-03-20 09:42:05 -0500 | [diff] [blame] | 23 | enum { |
| 24 | /* Last segment of program. Can be used to take different actions for |
| 25 | * cache maintenance of a program load. */ |
| 26 | SEG_FINAL = 1 << 0, |
| 27 | }; |
Ionela Voinescu | 00903e5 | 2015-01-09 13:14:20 +0000 | [diff] [blame] | 28 | |
Aaron Durbin | 7e7a4df | 2015-12-08 14:34:35 -0600 | [diff] [blame] | 29 | enum prog_type { |
| 30 | PROG_UNKNOWN, |
| 31 | PROG_VERSTAGE, |
| 32 | PROG_ROMSTAGE, |
| 33 | PROG_RAMSTAGE, |
| 34 | PROG_REFCODE, |
| 35 | PROG_PAYLOAD, |
| 36 | PROG_BL31, |
| 37 | PROG_BL32, |
| 38 | }; |
| 39 | |
Aaron Durbin | 096f457 | 2016-03-31 13:49:00 -0500 | [diff] [blame] | 40 | /* |
| 41 | * prog_segment_loaded() is called for each segment of a program loaded. The |
| 42 | * SEG_FINAL flag will be set on the last segment loaded. The following two |
| 43 | * functions, platform_segment_loaded() and arch_segment_loaded(), are called |
| 44 | * in that order within prog_segment_loaded(). In short, rely on |
| 45 | * prog_segment_loaded() to perform the proper dispatch sequence. |
| 46 | */ |
| 47 | void prog_segment_loaded(uintptr_t start, size_t size, int flags); |
| 48 | void platform_segment_loaded(uintptr_t start, size_t size, int flags); |
Aaron Durbin | 6e76fff | 2015-03-20 09:42:05 -0500 | [diff] [blame] | 49 | void arch_segment_loaded(uintptr_t start, size_t size, int flags); |
Ionela Voinescu | 00903e5 | 2015-01-09 13:14:20 +0000 | [diff] [blame] | 50 | |
Vladimir Serbinenko | f0d39c4 | 2016-02-19 16:44:22 +0100 | [diff] [blame] | 51 | /* Return true if arch supports bounce buffer. */ |
| 52 | int arch_supports_bounce_buffer(void); |
| 53 | |
Aaron Durbin | 3948e53 | 2015-03-20 13:00:20 -0500 | [diff] [blame] | 54 | /* Representation of a program. */ |
| 55 | struct prog { |
Aaron Durbin | 7e7a4df | 2015-12-08 14:34:35 -0600 | [diff] [blame] | 56 | /* The region_device is the source of program content to load. After |
| 57 | * loading program it represents the memory region of the stages and |
| 58 | * payload. For architectures that use a bounce buffer |
Aaron Durbin | ac12c66c | 2015-05-20 12:08:55 -0500 | [diff] [blame] | 59 | * then it would represent the bounce buffer. */ |
Aaron Durbin | 7e7a4df | 2015-12-08 14:34:35 -0600 | [diff] [blame] | 60 | enum prog_type type; |
| 61 | const char *name; |
| 62 | struct region_device rdev; |
Aaron Durbin | 3948e53 | 2015-03-20 13:00:20 -0500 | [diff] [blame] | 63 | /* Entry to program with optional argument. It's up to the architecture |
| 64 | * to decide if argument is passed. */ |
| 65 | void (*entry)(void *); |
| 66 | void *arg; |
| 67 | }; |
| 68 | |
Aaron Durbin | ac12c66c | 2015-05-20 12:08:55 -0500 | [diff] [blame] | 69 | #define PROG_INIT(type_, name_) \ |
| 70 | { \ |
Aaron Durbin | 7e7a4df | 2015-12-08 14:34:35 -0600 | [diff] [blame] | 71 | .type = (type_), \ |
| 72 | .name = (name_), \ |
Aaron Durbin | ac12c66c | 2015-05-20 12:08:55 -0500 | [diff] [blame] | 73 | } |
| 74 | |
| 75 | static inline const char *prog_name(const struct prog *prog) |
| 76 | { |
Aaron Durbin | 7e7a4df | 2015-12-08 14:34:35 -0600 | [diff] [blame] | 77 | return prog->name; |
Aaron Durbin | ac12c66c | 2015-05-20 12:08:55 -0500 | [diff] [blame] | 78 | } |
| 79 | |
Aaron Durbin | 7e7a4df | 2015-12-08 14:34:35 -0600 | [diff] [blame] | 80 | static inline enum prog_type prog_type(const struct prog *prog) |
Aaron Durbin | ac12c66c | 2015-05-20 12:08:55 -0500 | [diff] [blame] | 81 | { |
Aaron Durbin | 7e7a4df | 2015-12-08 14:34:35 -0600 | [diff] [blame] | 82 | return prog->type; |
Aaron Durbin | ac12c66c | 2015-05-20 12:08:55 -0500 | [diff] [blame] | 83 | } |
| 84 | |
| 85 | static inline struct region_device *prog_rdev(struct prog *prog) |
| 86 | { |
Aaron Durbin | 7e7a4df | 2015-12-08 14:34:35 -0600 | [diff] [blame] | 87 | return &prog->rdev; |
Aaron Durbin | ac12c66c | 2015-05-20 12:08:55 -0500 | [diff] [blame] | 88 | } |
| 89 | |
Aaron Durbin | 6a452ef | 2015-05-19 16:25:20 -0500 | [diff] [blame] | 90 | /* Only valid for loaded programs. */ |
Aaron Durbin | 3948e53 | 2015-03-20 13:00:20 -0500 | [diff] [blame] | 91 | static inline size_t prog_size(const struct prog *prog) |
| 92 | { |
Aaron Durbin | 7e7a4df | 2015-12-08 14:34:35 -0600 | [diff] [blame] | 93 | return region_device_sz(&prog->rdev); |
Aaron Durbin | 3948e53 | 2015-03-20 13:00:20 -0500 | [diff] [blame] | 94 | } |
| 95 | |
Aaron Durbin | 6a452ef | 2015-05-19 16:25:20 -0500 | [diff] [blame] | 96 | /* Only valid for loaded programs. */ |
Aaron Durbin | 3948e53 | 2015-03-20 13:00:20 -0500 | [diff] [blame] | 97 | static inline void *prog_start(const struct prog *prog) |
| 98 | { |
Aaron Durbin | 7e7a4df | 2015-12-08 14:34:35 -0600 | [diff] [blame] | 99 | return rdev_mmap_full(&prog->rdev); |
Aaron Durbin | 3948e53 | 2015-03-20 13:00:20 -0500 | [diff] [blame] | 100 | } |
| 101 | |
| 102 | static inline void *prog_entry(const struct prog *prog) |
| 103 | { |
| 104 | return prog->entry; |
| 105 | } |
| 106 | |
| 107 | static inline void *prog_entry_arg(const struct prog *prog) |
| 108 | { |
| 109 | return prog->arg; |
| 110 | } |
| 111 | |
Aaron Durbin | 6a452ef | 2015-05-19 16:25:20 -0500 | [diff] [blame] | 112 | /* region_device representing the 32-bit flat address space. */ |
| 113 | extern const struct mem_region_device addrspace_32bit; |
| 114 | |
| 115 | static inline void prog_memory_init(struct prog *prog, uintptr_t ptr, |
| 116 | size_t size) |
| 117 | { |
Aaron Durbin | 7e7a4df | 2015-12-08 14:34:35 -0600 | [diff] [blame] | 118 | rdev_chain(&prog->rdev, &addrspace_32bit.rdev, ptr, size); |
Aaron Durbin | 6a452ef | 2015-05-19 16:25:20 -0500 | [diff] [blame] | 119 | } |
| 120 | |
Aaron Durbin | 3948e53 | 2015-03-20 13:00:20 -0500 | [diff] [blame] | 121 | static inline void prog_set_area(struct prog *prog, void *start, size_t size) |
| 122 | { |
Aaron Durbin | 6a452ef | 2015-05-19 16:25:20 -0500 | [diff] [blame] | 123 | prog_memory_init(prog, (uintptr_t)start, size); |
Aaron Durbin | 3948e53 | 2015-03-20 13:00:20 -0500 | [diff] [blame] | 124 | } |
| 125 | |
| 126 | static inline void prog_set_entry(struct prog *prog, void *e, void *arg) |
| 127 | { |
| 128 | prog->entry = e; |
| 129 | prog->arg = arg; |
| 130 | } |
| 131 | |
Aaron Durbin | 899d13d | 2015-05-15 23:39:23 -0500 | [diff] [blame] | 132 | /* Locate the identified program to run. Return 0 on success. < 0 on error. */ |
Aaron Durbin | 6d720f3 | 2015-12-08 17:00:23 -0600 | [diff] [blame] | 133 | int prog_locate(struct prog *prog); |
Aaron Durbin | ac12c66c | 2015-05-20 12:08:55 -0500 | [diff] [blame] | 134 | |
Aaron Durbin | b3847e6 | 2015-03-20 15:55:08 -0500 | [diff] [blame] | 135 | /* Run the program described by prog. */ |
| 136 | void prog_run(struct prog *prog); |
| 137 | /* Per architecture implementation running a program. */ |
| 138 | void arch_prog_run(struct prog *prog); |
| 139 | /* Platform (SoC/chipset) specific overrides for running a program. This is |
| 140 | * called prior to calling the arch_prog_run. Thus, if there is anything |
| 141 | * special that needs to be done by the platform similar to the architecture |
| 142 | * code it needs to that as well. */ |
| 143 | void platform_prog_run(struct prog *prog); |
| 144 | |
Aaron Durbin | ce9efe0 | 2015-03-20 16:37:12 -0500 | [diff] [blame] | 145 | struct prog_loader_ops { |
| 146 | const char *name; |
Aaron Durbin | 5e8286b | 2015-04-28 15:59:12 -0500 | [diff] [blame] | 147 | /* Determine if the loader is the active one. If so returns 1 else 0 |
| 148 | * or < 0 on error. */ |
| 149 | int (*is_loader_active)(struct prog *prog); |
Aaron Durbin | 899d13d | 2015-05-15 23:39:23 -0500 | [diff] [blame] | 150 | /* Returns < 0 on error or 0 on success. This function locates |
| 151 | * the rdev representing the file data associated with the passed in |
| 152 | * prog. */ |
| 153 | int (*locate)(struct prog *prog); |
Aaron Durbin | ce9efe0 | 2015-03-20 16:37:12 -0500 | [diff] [blame] | 154 | }; |
| 155 | |
Aaron Durbin | d1b0e87 | 2015-03-17 13:17:06 -0500 | [diff] [blame] | 156 | /************************ |
| 157 | * ROMSTAGE LOADING * |
| 158 | ************************/ |
| 159 | |
| 160 | /* Run romstage from bootblock. */ |
| 161 | void run_romstage(void); |
Aaron Durbin | 04654a2 | 2015-03-17 11:43:44 -0500 | [diff] [blame] | 162 | |
| 163 | /************************ |
| 164 | * RAMSTAGE LOADING * |
| 165 | ************************/ |
| 166 | |
Aaron Durbin | ce9efe0 | 2015-03-20 16:37:12 -0500 | [diff] [blame] | 167 | /* Run ramstage from romstage. */ |
| 168 | void run_ramstage(void); |
| 169 | |
Kyösti Mälkki | e5c00a5 | 2016-06-27 14:50:27 +0300 | [diff] [blame] | 170 | /* Determine where stack for ramstage loader is located. */ |
| 171 | enum { ROMSTAGE_STACK_CBMEM, ROMSTAGE_STACK_LOW_MEM }; |
| 172 | uintptr_t romstage_ram_stack_base(size_t size, int src); |
| 173 | uintptr_t romstage_ram_stack_top(void); |
| 174 | uintptr_t romstage_ram_stack_bottom(void); |
| 175 | |
Kyösti Mälkki | 9d6f365 | 2016-06-28 07:38:46 +0300 | [diff] [blame] | 176 | /* Backup OS memory to CBMEM_ID_RESUME on ACPI S3 resume path, |
| 177 | * if ramstage overwrites low memory. */ |
| 178 | void backup_ramstage_section(uintptr_t base, size_t size); |
| 179 | |
Aaron Durbin | 04654a2 | 2015-03-17 11:43:44 -0500 | [diff] [blame] | 180 | /*********************** |
| 181 | * PAYLOAD LOADING * |
| 182 | ***********************/ |
| 183 | |
Aaron Durbin | ebf2ed4 | 2015-03-20 10:20:15 -0500 | [diff] [blame] | 184 | /* Load payload into memory in preparation to run. */ |
| 185 | void payload_load(void); |
Aaron Durbin | bdf913a | 2014-02-24 14:56:34 -0600 | [diff] [blame] | 186 | |
| 187 | /* Run the loaded payload. */ |
Aaron Durbin | ebf2ed4 | 2015-03-20 10:20:15 -0500 | [diff] [blame] | 188 | void payload_run(void); |
Aaron Durbin | bdf913a | 2014-02-24 14:56:34 -0600 | [diff] [blame] | 189 | |
Aaron Durbin | c34713d | 2014-02-25 20:36:56 -0600 | [diff] [blame] | 190 | /* Mirror the payload to be loaded. */ |
Aaron Durbin | ce9efe0 | 2015-03-20 16:37:12 -0500 | [diff] [blame] | 191 | void mirror_payload(struct prog *payload); |
Aaron Durbin | bdf913a | 2014-02-24 14:56:34 -0600 | [diff] [blame] | 192 | |
Simon Glass | 7ae73fc | 2016-08-27 12:18:38 -0600 | [diff] [blame] | 193 | /* |
| 194 | * Set check_regions to true to check that the payload targets usable memory. |
| 195 | * With this flag set, if it does not, the load will fail and this function |
| 196 | * will return NULL. |
| 197 | * |
| 198 | * Defined in src/lib/selfboot.c |
| 199 | */ |
| 200 | void *selfload(struct prog *payload, bool check_regions); |
Aaron Durbin | 04654a2 | 2015-03-17 11:43:44 -0500 | [diff] [blame] | 201 | |
| 202 | #endif /* PROGRAM_LOADING_H */ |