blob: a1743a81aba4bcf427276fefdf68e065a1930b8f [file] [log] [blame]
Angel Pons32859fc2020-04-02 23:48:27 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Aaron Durbin7e35efa2013-04-24 15:14:01 -05002#ifndef BOOTSTATE_H
3#define BOOTSTATE_H
4
Angel Pons83156682021-06-10 13:57:35 +02005#include <assert.h>
Aaron Durbin7e35efa2013-04-24 15:14:01 -05006#include <string.h>
Aaron Durbin9ef9d852015-03-16 17:30:09 -05007#include <stddef.h>
Aaron Durbin622eea72016-02-10 23:15:07 -06008/* Only declare main() when in ramstage. */
9#if ENV_RAMSTAGE
10#include <main_decl.h>
11#endif
Aaron Durbin7e35efa2013-04-24 15:14:01 -050012
Aaron Durbin7e35efa2013-04-24 15:14:01 -050013/*
14 * The boot state machine provides a mechanism for calls to be made through-
15 * out the main boot process. The boot process is separated into discrete
16 * states. Upon a state's entry and exit and callbacks can be made. For
17 * example:
18 *
19 * Enter State
20 * +
21 * |
22 * V
23 * +-----------------+
24 * | Entry callbacks |
25 * +-----------------+
26 * | State Actions |
27 * +-----------------+
28 * | Exit callbacks |
29 * +-------+---------+
30 * |
31 * V
32 * Next State
33 *
34 * Below is the current flow from top to bottom:
35 *
36 * start
37 * |
38 * BS_PRE_DEVICE
39 * |
40 * BS_DEV_INIT_CHIPS
41 * |
42 * BS_DEV_ENUMERATE
43 * |
44 * BS_DEV_RESOURCES
45 * |
46 * BS_DEV_ENABLE
47 * |
48 * BS_DEV_INIT
49 * |
50 * BS_POST_DEVICE
51 * |
52 * BS_OS_RESUME_CHECK -------- BS_OS_RESUME
53 * | |
54 * BS_WRITE_TABLES os handoff
55 * |
56 * BS_PAYLOAD_LOAD
57 * |
58 * BS_PAYLOAD_BOOT
59 * |
60 * payload run
61 *
62 * Brief description of states:
63 * BS_PRE_DEVICE - before any device tree actions take place
64 * BS_DEV_INIT_CHIPS - init all chips in device tree
65 * BS_DEV_ENUMERATE - device tree probing
66 * BS_DEV_RESOURCES - device tree resource allocation and assignment
67 * BS_DEV_ENABLE - device tree enabling/disabling of devices
68 * BS_DEV_INIT - device tree device initialization
69 * BS_POST_DEVICE - all device tree actions performed
70 * BS_OS_RESUME_CHECK - check for OS resume
71 * BS_OS_RESUME - resume to OS
72 * BS_WRITE_TABLES - write coreboot tables
73 * BS_PAYLOAD_LOAD - Load payload into memory
74 * BS_PAYLOAD_BOOT - Boot to payload
75 */
76
77typedef enum {
78 BS_PRE_DEVICE,
79 BS_DEV_INIT_CHIPS,
80 BS_DEV_ENUMERATE,
81 BS_DEV_RESOURCES,
82 BS_DEV_ENABLE,
83 BS_DEV_INIT,
84 BS_POST_DEVICE,
Aaron Durbin0a6c20a2013-04-24 22:33:08 -050085 BS_OS_RESUME_CHECK,
Aaron Durbin7e35efa2013-04-24 15:14:01 -050086 BS_OS_RESUME,
87 BS_WRITE_TABLES,
88 BS_PAYLOAD_LOAD,
89 BS_PAYLOAD_BOOT,
90} boot_state_t;
91
92/* The boot_state_sequence_t describes when a callback is to be made. It is
93 * called either before a state is entered or when a state is exited. */
94typedef enum {
95 BS_ON_ENTRY,
96 BS_ON_EXIT
97} boot_state_sequence_t;
98
99struct boot_state_callback {
100 void *arg;
101 void (*callback)(void *arg);
102 /* For use internal to the boot state machine. */
103 struct boot_state_callback *next;
Julius Wernercd49cce2019-03-05 16:53:33 -0800104#if CONFIG(DEBUG_BOOT_STATE)
Aaron Durbin7e35efa2013-04-24 15:14:01 -0500105 const char *location;
106#endif
107};
108
Angel Pons83156682021-06-10 13:57:35 +0200109static inline const char *bscb_location(const struct boot_state_callback *bscb)
110{
111#if CONFIG(DEBUG_BOOT_STATE)
112 return bscb->location;
113#else
114 return dead_code_t(const char *);
115#endif
116}
117
Julius Wernercd49cce2019-03-05 16:53:33 -0800118#if CONFIG(DEBUG_BOOT_STATE)
Aaron Durbin7e35efa2013-04-24 15:14:01 -0500119#define BOOT_STATE_CALLBACK_LOC __FILE__ ":" STRINGIFY(__LINE__)
120#define BOOT_STATE_CALLBACK_INIT_DEBUG .location = BOOT_STATE_CALLBACK_LOC,
Elyes HAOUASb0f19882018-06-09 11:59:00 +0200121#define INIT_BOOT_STATE_CALLBACK_DEBUG(bscb_) \
Lee Leahybb4ae072017-03-07 12:01:02 -0800122 do { \
123 bscb_->location = BOOT_STATE_CALLBACK_LOC; \
124 } while (0)
Aaron Durbin7e35efa2013-04-24 15:14:01 -0500125#else
126#define BOOT_STATE_CALLBACK_INIT_DEBUG
127#define INIT_BOOT_STATE_CALLBACK_DEBUG(bscb_)
128#endif
129
130#define BOOT_STATE_CALLBACK_INIT(func_, arg_) \
131 { \
132 .arg = arg_, \
133 .callback = func_, \
134 .next = NULL, \
135 BOOT_STATE_CALLBACK_INIT_DEBUG \
136 }
137
138#define BOOT_STATE_CALLBACK(name_, func_, arg_) \
139 struct boot_state_callback name_ = BOOT_STATE_CALLBACK_INIT(func_, arg_)
140
141/* Initialize an allocated boot_state_callback. */
142#define INIT_BOOT_STATE_CALLBACK(bscb_, func_, arg_) \
Lee Leahybb4ae072017-03-07 12:01:02 -0800143 do { \
144 INIT_BOOT_STATE_CALLBACK_DEBUG(bscb_) \
145 bscb_->callback = func_; \
146 bscb_->arg = arg_ \
Lee Leahy86f60a92017-03-07 12:06:44 -0800147 } while (0)
Aaron Durbin7e35efa2013-04-24 15:14:01 -0500148
149/* The following 2 functions schedule a callback to be called on entry/exit
Martin Roth0cb07e32013-07-09 21:46:01 -0600150 * to a given state. Note that there are no ordering guarantees between the
Aaron Durbin7e35efa2013-04-24 15:14:01 -0500151 * individual callbacks on a given state. 0 is returned on success < 0 on
152 * error. */
153int boot_state_sched_on_entry(struct boot_state_callback *bscb,
Lee Leahy708fc272017-03-07 12:18:53 -0800154 boot_state_t state);
Aaron Durbin7e35efa2013-04-24 15:14:01 -0500155int boot_state_sched_on_exit(struct boot_state_callback *bscb,
Lee Leahy708fc272017-03-07 12:18:53 -0800156 boot_state_t state);
Aaron Durbin9ef9d852015-03-16 17:30:09 -0500157/* Schedule an array of entries of size num. */
158struct boot_state_init_entry;
159void boot_state_sched_entries(struct boot_state_init_entry *entries,
160 size_t num);
Aaron Durbin7e35efa2013-04-24 15:14:01 -0500161
Aaron Durbin0748d302013-05-06 10:50:19 -0500162/* Block/Unblock the (state, seq) pair from transitioning. Returns 0 on
163 * success < 0 when the phase of the (state,seq) has already ran. */
164int boot_state_block(boot_state_t state, boot_state_sequence_t seq);
165int boot_state_unblock(boot_state_t state, boot_state_sequence_t seq);
Aaron Durbin0748d302013-05-06 10:50:19 -0500166
Aaron Durbina4feddf2013-04-24 16:12:52 -0500167/* In order to schedule boot state callbacks at compile-time specify the
168 * entries in an array using the BOOT_STATE_INIT_ENTRIES and
169 * BOOT_STATE_INIT_ENTRY macros below. */
170struct boot_state_init_entry {
171 boot_state_t state;
172 boot_state_sequence_t when;
173 struct boot_state_callback bscb;
174};
175
Aaron Durbin4d3de7e2015-09-02 17:34:04 -0500176#if ENV_RAMSTAGE
Stefan Reinauer6a001132017-07-13 02:20:27 +0200177#define BOOT_STATE_INIT_ATTR __attribute__((used, section(".bs_init")))
Aaron Durbin4d3de7e2015-09-02 17:34:04 -0500178#else
Stefan Reinauer6a001132017-07-13 02:20:27 +0200179#define BOOT_STATE_INIT_ATTR __attribute__((unused))
Aaron Durbin4d3de7e2015-09-02 17:34:04 -0500180#endif
Aaron Durbina4feddf2013-04-24 16:12:52 -0500181
Aaron Durbin9ef9d852015-03-16 17:30:09 -0500182#define BOOT_STATE_INIT_ENTRY(state_, when_, func_, arg_) \
183 static struct boot_state_init_entry func_ ##_## state_ ##_## when_ = \
184 { \
185 .state = state_, \
186 .when = when_, \
187 .bscb = BOOT_STATE_CALLBACK_INIT(func_, arg_), \
188 }; \
189 static struct boot_state_init_entry * \
190 bsie_ ## func_ ##_## state_ ##_## when_ BOOT_STATE_INIT_ATTR = \
Arthur Heymans9ce79352023-02-01 11:11:13 +0100191 &func_ ##_## state_ ##_## when_; \
192 _Static_assert(!(state_ == BS_PAYLOAD_BOOT && when_ == BS_ON_EXIT), \
193 "Invalid bootstate hook"); \
194 _Static_assert(!(state_ == BS_OS_RESUME && when_ == BS_ON_EXIT), \
195 "Invalid bootstate hook");
Aaron Durbina4feddf2013-04-24 16:12:52 -0500196
Aaron Durbin16bd2672016-12-07 11:58:20 -0600197/* Hook per arch when coreboot is exiting to payload or ACPI OS resume. It's
198 * the very last thing done before the transition. */
199void arch_bootstate_coreboot_exit(void);
200
Aaron Durbin7e35efa2013-04-24 15:14:01 -0500201#endif /* BOOTSTATE_H */