blob: 9fac70113e7f96e711f3c65f430ae4f40d36ac48 [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
5#include <string.h>
Aaron Durbin9ef9d852015-03-16 17:30:09 -05006#include <stddef.h>
Aaron Durbin622eea72016-02-10 23:15:07 -06007/* Only declare main() when in ramstage. */
8#if ENV_RAMSTAGE
9#include <main_decl.h>
10#endif
Aaron Durbin7e35efa2013-04-24 15:14:01 -050011
Aaron Durbin7e35efa2013-04-24 15:14:01 -050012/*
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
76typedef 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,
Aaron Durbin0a6c20a2013-04-24 22:33:08 -050084 BS_OS_RESUME_CHECK,
Aaron Durbin7e35efa2013-04-24 15:14:01 -050085 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. */
93typedef enum {
94 BS_ON_ENTRY,
95 BS_ON_EXIT
96} boot_state_sequence_t;
97
98struct 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;
Julius Wernercd49cce2019-03-05 16:53:33 -0800103#if CONFIG(DEBUG_BOOT_STATE)
Aaron Durbin7e35efa2013-04-24 15:14:01 -0500104 const char *location;
105#endif
106};
107
Julius Wernercd49cce2019-03-05 16:53:33 -0800108#if CONFIG(DEBUG_BOOT_STATE)
Aaron Durbin7e35efa2013-04-24 15:14:01 -0500109#define BOOT_STATE_CALLBACK_LOC __FILE__ ":" STRINGIFY(__LINE__)
110#define BOOT_STATE_CALLBACK_INIT_DEBUG .location = BOOT_STATE_CALLBACK_LOC,
Elyes HAOUASb0f19882018-06-09 11:59:00 +0200111#define INIT_BOOT_STATE_CALLBACK_DEBUG(bscb_) \
Lee Leahybb4ae072017-03-07 12:01:02 -0800112 do { \
113 bscb_->location = BOOT_STATE_CALLBACK_LOC; \
114 } while (0)
Aaron Durbin7e35efa2013-04-24 15:14:01 -0500115#else
116#define BOOT_STATE_CALLBACK_INIT_DEBUG
117#define INIT_BOOT_STATE_CALLBACK_DEBUG(bscb_)
118#endif
119
120#define BOOT_STATE_CALLBACK_INIT(func_, arg_) \
121 { \
122 .arg = arg_, \
123 .callback = func_, \
124 .next = NULL, \
125 BOOT_STATE_CALLBACK_INIT_DEBUG \
126 }
127
128#define BOOT_STATE_CALLBACK(name_, func_, arg_) \
129 struct boot_state_callback name_ = BOOT_STATE_CALLBACK_INIT(func_, arg_)
130
131/* Initialize an allocated boot_state_callback. */
132#define INIT_BOOT_STATE_CALLBACK(bscb_, func_, arg_) \
Lee Leahybb4ae072017-03-07 12:01:02 -0800133 do { \
134 INIT_BOOT_STATE_CALLBACK_DEBUG(bscb_) \
135 bscb_->callback = func_; \
136 bscb_->arg = arg_ \
Lee Leahy86f60a92017-03-07 12:06:44 -0800137 } while (0)
Aaron Durbin7e35efa2013-04-24 15:14:01 -0500138
139/* The following 2 functions schedule a callback to be called on entry/exit
Martin Roth0cb07e32013-07-09 21:46:01 -0600140 * to a given state. Note that there are no ordering guarantees between the
Aaron Durbin7e35efa2013-04-24 15:14:01 -0500141 * individual callbacks on a given state. 0 is returned on success < 0 on
142 * error. */
143int boot_state_sched_on_entry(struct boot_state_callback *bscb,
Lee Leahy708fc272017-03-07 12:18:53 -0800144 boot_state_t state);
Aaron Durbin7e35efa2013-04-24 15:14:01 -0500145int boot_state_sched_on_exit(struct boot_state_callback *bscb,
Lee Leahy708fc272017-03-07 12:18:53 -0800146 boot_state_t state);
Aaron Durbin9ef9d852015-03-16 17:30:09 -0500147/* Schedule an array of entries of size num. */
148struct boot_state_init_entry;
149void boot_state_sched_entries(struct boot_state_init_entry *entries,
150 size_t num);
Aaron Durbin7e35efa2013-04-24 15:14:01 -0500151
Aaron Durbin0748d302013-05-06 10:50:19 -0500152/* Block/Unblock the (state, seq) pair from transitioning. Returns 0 on
153 * success < 0 when the phase of the (state,seq) has already ran. */
154int boot_state_block(boot_state_t state, boot_state_sequence_t seq);
155int boot_state_unblock(boot_state_t state, boot_state_sequence_t seq);
156/* Block/Unblock current state phase from transitioning. */
157void boot_state_current_block(void);
158void boot_state_current_unblock(void);
159
Aaron Durbina4feddf2013-04-24 16:12:52 -0500160/* In order to schedule boot state callbacks at compile-time specify the
161 * entries in an array using the BOOT_STATE_INIT_ENTRIES and
162 * BOOT_STATE_INIT_ENTRY macros below. */
163struct boot_state_init_entry {
164 boot_state_t state;
165 boot_state_sequence_t when;
166 struct boot_state_callback bscb;
167};
168
Aaron Durbin4d3de7e2015-09-02 17:34:04 -0500169#if ENV_RAMSTAGE
Stefan Reinauer6a001132017-07-13 02:20:27 +0200170#define BOOT_STATE_INIT_ATTR __attribute__((used, section(".bs_init")))
Aaron Durbin4d3de7e2015-09-02 17:34:04 -0500171#else
Stefan Reinauer6a001132017-07-13 02:20:27 +0200172#define BOOT_STATE_INIT_ATTR __attribute__((unused))
Aaron Durbin4d3de7e2015-09-02 17:34:04 -0500173#endif
Aaron Durbina4feddf2013-04-24 16:12:52 -0500174
Aaron Durbin9ef9d852015-03-16 17:30:09 -0500175#define BOOT_STATE_INIT_ENTRY(state_, when_, func_, arg_) \
176 static struct boot_state_init_entry func_ ##_## state_ ##_## when_ = \
177 { \
178 .state = state_, \
179 .when = when_, \
180 .bscb = BOOT_STATE_CALLBACK_INIT(func_, arg_), \
181 }; \
182 static struct boot_state_init_entry * \
183 bsie_ ## func_ ##_## state_ ##_## when_ BOOT_STATE_INIT_ATTR = \
Lee Leahy18cb7e62017-03-07 13:00:08 -0800184 &func_ ##_## state_ ##_## when_;
Aaron Durbina4feddf2013-04-24 16:12:52 -0500185
Aaron Durbin16bd2672016-12-07 11:58:20 -0600186/* Hook per arch when coreboot is exiting to payload or ACPI OS resume. It's
187 * the very last thing done before the transition. */
188void arch_bootstate_coreboot_exit(void);
189
Aaron Durbin7e35efa2013-04-24 15:14:01 -0500190#endif /* BOOTSTATE_H */