xref: /aosp_15_r20/external/coreboot/src/include/bootstate.h (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 #ifndef BOOTSTATE_H
3 #define BOOTSTATE_H
4 
5 #include <assert.h>
6 #include <stddef.h>
7 /* Only declare main() when in ramstage. */
8 #if ENV_RAMSTAGE
9 #include <main_decl.h>
10 #endif
11 
12 /*
13  * The boot state machine provides a mechanism for calls to be made through-
14  * out the main boot process. The boot process is separated into discrete
15  * states. Upon a state's entry and exit and callbacks can be made. For
16  * example:
17  *
18  *      Enter State
19  *           +
20  *           |
21  *           V
22  *   +-----------------+
23  *   | Entry callbacks |
24  *   +-----------------+
25  *   | State Actions   |
26  *   +-----------------+
27  *   | Exit callbacks  |
28  *   +-------+---------+
29  *           |
30  *           V
31  *       Next State
32  *
33  * Below is the current flow from top to bottom:
34  *
35  *        start
36  *          |
37  *    BS_PRE_DEVICE
38  *          |
39  *    BS_DEV_INIT_CHIPS
40  *          |
41  *    BS_DEV_ENUMERATE
42  *          |
43  *    BS_DEV_RESOURCES
44  *          |
45  *    BS_DEV_ENABLE
46  *          |
47  *    BS_DEV_INIT
48  *          |
49  *    BS_POST_DEVICE
50  *          |
51  *    BS_OS_RESUME_CHECK -------- BS_OS_RESUME
52  *          |                          |
53  *    BS_WRITE_TABLES              OS handoff
54  *          |
55  *    BS_PAYLOAD_LOAD
56  *          |
57  *    BS_PAYLOAD_BOOT
58  *          |
59  *      payload run
60  *
61  * Brief description of states:
62  *   BS_PRE_DEVICE - before any device tree actions take place
63  *   BS_DEV_INIT_CHIPS - init all chips in device tree
64  *   BS_DEV_ENUMERATE - device tree probing
65  *   BS_DEV_RESOURCES - device tree resource allocation and assignment
66  *   BS_DEV_ENABLE - device tree enabling/disabling of devices
67  *   BS_DEV_INIT - device tree device initialization
68  *   BS_POST_DEVICE - all device tree actions performed
69  *   BS_OS_RESUME_CHECK - check for OS resume
70  *   BS_OS_RESUME - resume to OS
71  *   BS_WRITE_TABLES - write coreboot tables
72  *   BS_PAYLOAD_LOAD - Load payload into memory
73  *   BS_PAYLOAD_BOOT - Boot to payload
74  */
75 
76 typedef enum {
77 	BS_PRE_DEVICE,
78 	BS_DEV_INIT_CHIPS,
79 	BS_DEV_ENUMERATE,
80 	BS_DEV_RESOURCES,
81 	BS_DEV_ENABLE,
82 	BS_DEV_INIT,
83 	BS_POST_DEVICE,
84 	BS_OS_RESUME_CHECK,
85 	BS_OS_RESUME,
86 	BS_WRITE_TABLES,
87 	BS_PAYLOAD_LOAD,
88 	BS_PAYLOAD_BOOT,
89 } boot_state_t;
90 
91 /* The boot_state_sequence_t describes when a callback is to be made. It is
92  * called either before a state is entered or when a state is exited. */
93 typedef enum {
94 	BS_ON_ENTRY,
95 	BS_ON_EXIT
96 } boot_state_sequence_t;
97 
98 struct boot_state_callback {
99 	void *arg;
100 	void (*callback)(void *arg);
101 	/* For use internal to the boot state machine. */
102 	struct boot_state_callback *next;
103 #if CONFIG(DEBUG_BOOT_STATE)
104 	const char *location;
105 #endif
106 };
107 
bscb_location(const struct boot_state_callback * bscb)108 static inline const char *bscb_location(const struct boot_state_callback *bscb)
109 {
110 #if CONFIG(DEBUG_BOOT_STATE)
111 	return bscb->location;
112 #else
113 	return dead_code_t(const char *);
114 #endif
115 }
116 
117 #if CONFIG(DEBUG_BOOT_STATE)
118 #define BOOT_STATE_CALLBACK_LOC __FILE__ ":" STRINGIFY(__LINE__)
119 #define BOOT_STATE_CALLBACK_INIT_DEBUG .location = BOOT_STATE_CALLBACK_LOC,
120 #define INIT_BOOT_STATE_CALLBACK_DEBUG(bscb_)			\
121 	do {							\
122 		bscb_->location = BOOT_STATE_CALLBACK_LOC;	\
123 	} while (0)
124 #else
125 #define BOOT_STATE_CALLBACK_INIT_DEBUG
126 #define INIT_BOOT_STATE_CALLBACK_DEBUG(bscb_)
127 #endif
128 
129 #define BOOT_STATE_CALLBACK_INIT(func_, arg_)		\
130 	{						\
131 		.arg = arg_,				\
132 		.callback = func_,			\
133 		.next = NULL,				\
134 		BOOT_STATE_CALLBACK_INIT_DEBUG		\
135 	}
136 
137 #define BOOT_STATE_CALLBACK(name_, func_, arg_)	\
138 	struct boot_state_callback name_ = BOOT_STATE_CALLBACK_INIT(func_, arg_)
139 
140 /* Initialize an allocated boot_state_callback. */
141 #define INIT_BOOT_STATE_CALLBACK(bscb_, func_, arg_)	\
142 	do {						\
143 		INIT_BOOT_STATE_CALLBACK_DEBUG(bscb_)	\
144 		bscb_->callback = func_;		\
145 		bscb_->arg = arg_			\
146 	} while (0)
147 
148 /* The following 2 functions schedule a callback to be called on entry/exit
149  * to a given state. Note that there are no ordering guarantees between the
150  * individual callbacks on a given state. 0 is returned on success < 0 on
151  * error. */
152 int boot_state_sched_on_entry(struct boot_state_callback *bscb,
153 				boot_state_t state);
154 int boot_state_sched_on_exit(struct boot_state_callback *bscb,
155 				boot_state_t state);
156 /* Schedule an array of entries of size num. */
157 struct boot_state_init_entry;
158 void boot_state_sched_entries(struct boot_state_init_entry *entries,
159 				size_t num);
160 
161 /* Block/Unblock the (state, seq) pair from transitioning. Returns 0 on
162  * success < 0  when the phase of the (state,seq) has already ran. */
163 int boot_state_block(boot_state_t state, boot_state_sequence_t seq);
164 int boot_state_unblock(boot_state_t state, boot_state_sequence_t seq);
165 
166 /* In order to schedule boot state callbacks at compile-time specify the
167  * entries in an array using the BOOT_STATE_INIT_ENTRIES and
168  * BOOT_STATE_INIT_ENTRY macros below. */
169 struct boot_state_init_entry {
170 	boot_state_t state;
171 	boot_state_sequence_t when;
172 	struct boot_state_callback bscb;
173 };
174 
175 #if ENV_RAMSTAGE
176 #define BOOT_STATE_INIT_ATTR  __attribute__((used, section(".bs_init")))
177 #else
178 #define BOOT_STATE_INIT_ATTR  __attribute__((unused))
179 #endif
180 
181 #define BOOT_STATE_INIT_ENTRY(state_, when_, func_, arg_)		\
182 	static struct boot_state_init_entry func_ ##_## state_ ##_## when_ = \
183 	{								\
184 		.state = state_,					\
185 		.when = when_,						\
186 		.bscb = BOOT_STATE_CALLBACK_INIT(func_, arg_),		\
187 	};								\
188 	static struct boot_state_init_entry *				\
189 		bsie_ ## func_ ##_## state_ ##_## when_ BOOT_STATE_INIT_ATTR = \
190 		&func_ ##_## state_ ##_## when_;			\
191 	_Static_assert(!(state_ == BS_PAYLOAD_BOOT && when_ == BS_ON_EXIT), \
192 		       "Invalid bootstate hook");			\
193 	_Static_assert(!(state_ == BS_OS_RESUME && when_ == BS_ON_EXIT), \
194 		       "Invalid bootstate hook");
195 
196 /* Hook per arch when coreboot is exiting to payload or ACPI OS resume. It's
197  * the very last thing done before the transition. */
198 void arch_bootstate_coreboot_exit(void);
199 
200 #endif /* BOOTSTATE_H */
201