blob: 8b5e4be62f49b58c495748350a95d4f0bc691412 [file] [log] [blame]
Aaron Durbin7e35efa2013-04-24 15:14:01 -05001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 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#ifndef BOOTSTATE_H
20#define BOOTSTATE_H
21
Patrick Georgi5c715ac2014-08-14 19:23:41 +020022#if !defined(__SMM__) && !defined(__PRE_RAM__)
23
Aaron Durbin7e35efa2013-04-24 15:14:01 -050024#include <string.h>
Aaron Durbin9ef9d852015-03-16 17:30:09 -050025#include <stdlib.h>
26#include <stddef.h>
27#include <stdint.h>
Aaron Durbin7e35efa2013-04-24 15:14:01 -050028
29/* Control debugging of the boot state machine. */
30#define BOOT_STATE_DEBUG 0
31
32/*
33 * The boot state machine provides a mechanism for calls to be made through-
34 * out the main boot process. The boot process is separated into discrete
35 * states. Upon a state's entry and exit and callbacks can be made. For
36 * example:
37 *
38 * Enter State
39 * +
40 * |
41 * V
42 * +-----------------+
43 * | Entry callbacks |
44 * +-----------------+
45 * | State Actions |
46 * +-----------------+
47 * | Exit callbacks |
48 * +-------+---------+
49 * |
50 * V
51 * Next State
52 *
53 * Below is the current flow from top to bottom:
54 *
55 * start
56 * |
57 * BS_PRE_DEVICE
58 * |
59 * BS_DEV_INIT_CHIPS
60 * |
61 * BS_DEV_ENUMERATE
62 * |
63 * BS_DEV_RESOURCES
64 * |
65 * BS_DEV_ENABLE
66 * |
67 * BS_DEV_INIT
68 * |
69 * BS_POST_DEVICE
70 * |
71 * BS_OS_RESUME_CHECK -------- BS_OS_RESUME
72 * | |
73 * BS_WRITE_TABLES os handoff
74 * |
75 * BS_PAYLOAD_LOAD
76 * |
77 * BS_PAYLOAD_BOOT
78 * |
79 * payload run
80 *
81 * Brief description of states:
82 * BS_PRE_DEVICE - before any device tree actions take place
83 * BS_DEV_INIT_CHIPS - init all chips in device tree
84 * BS_DEV_ENUMERATE - device tree probing
85 * BS_DEV_RESOURCES - device tree resource allocation and assignment
86 * BS_DEV_ENABLE - device tree enabling/disabling of devices
87 * BS_DEV_INIT - device tree device initialization
88 * BS_POST_DEVICE - all device tree actions performed
89 * BS_OS_RESUME_CHECK - check for OS resume
90 * BS_OS_RESUME - resume to OS
91 * BS_WRITE_TABLES - write coreboot tables
92 * BS_PAYLOAD_LOAD - Load payload into memory
93 * BS_PAYLOAD_BOOT - Boot to payload
94 */
95
96typedef enum {
97 BS_PRE_DEVICE,
98 BS_DEV_INIT_CHIPS,
99 BS_DEV_ENUMERATE,
100 BS_DEV_RESOURCES,
101 BS_DEV_ENABLE,
102 BS_DEV_INIT,
103 BS_POST_DEVICE,
Aaron Durbin0a6c20a2013-04-24 22:33:08 -0500104 BS_OS_RESUME_CHECK,
Aaron Durbin7e35efa2013-04-24 15:14:01 -0500105 BS_OS_RESUME,
106 BS_WRITE_TABLES,
107 BS_PAYLOAD_LOAD,
108 BS_PAYLOAD_BOOT,
109} boot_state_t;
110
111/* The boot_state_sequence_t describes when a callback is to be made. It is
112 * called either before a state is entered or when a state is exited. */
113typedef enum {
114 BS_ON_ENTRY,
115 BS_ON_EXIT
116} boot_state_sequence_t;
117
118struct boot_state_callback {
119 void *arg;
120 void (*callback)(void *arg);
121 /* For use internal to the boot state machine. */
122 struct boot_state_callback *next;
123#if BOOT_STATE_DEBUG
124 const char *location;
125#endif
126};
127
128#if BOOT_STATE_DEBUG
129#define BOOT_STATE_CALLBACK_LOC __FILE__ ":" STRINGIFY(__LINE__)
130#define BOOT_STATE_CALLBACK_INIT_DEBUG .location = BOOT_STATE_CALLBACK_LOC,
131#define INIT_BOOT_STATE_CALLBACK_DEBUG(bscb_) \
132 bscb_->location = BOOT_STATE_CALLBACK_LOC;
133#else
134#define BOOT_STATE_CALLBACK_INIT_DEBUG
135#define INIT_BOOT_STATE_CALLBACK_DEBUG(bscb_)
136#endif
137
138#define BOOT_STATE_CALLBACK_INIT(func_, arg_) \
139 { \
140 .arg = arg_, \
141 .callback = func_, \
142 .next = NULL, \
143 BOOT_STATE_CALLBACK_INIT_DEBUG \
144 }
145
146#define BOOT_STATE_CALLBACK(name_, func_, arg_) \
147 struct boot_state_callback name_ = BOOT_STATE_CALLBACK_INIT(func_, arg_)
148
149/* Initialize an allocated boot_state_callback. */
150#define INIT_BOOT_STATE_CALLBACK(bscb_, func_, arg_) \
151 INIT_BOOT_STATE_CALLBACK_DEBUG(bscb_) \
152 bscb_->callback = func_; \
153 bscb_->arg = arg_
154
155/* The following 2 functions schedule a callback to be called on entry/exit
Martin Roth0cb07e32013-07-09 21:46:01 -0600156 * to a given state. Note that there are no ordering guarantees between the
Aaron Durbin7e35efa2013-04-24 15:14:01 -0500157 * individual callbacks on a given state. 0 is returned on success < 0 on
158 * error. */
159int boot_state_sched_on_entry(struct boot_state_callback *bscb,
160 boot_state_t state);
161int boot_state_sched_on_exit(struct boot_state_callback *bscb,
162 boot_state_t state);
Aaron Durbin9ef9d852015-03-16 17:30:09 -0500163/* Schedule an array of entries of size num. */
164struct boot_state_init_entry;
165void boot_state_sched_entries(struct boot_state_init_entry *entries,
166 size_t num);
Aaron Durbin7e35efa2013-04-24 15:14:01 -0500167
Aaron Durbin0748d302013-05-06 10:50:19 -0500168/* Block/Unblock the (state, seq) pair from transitioning. Returns 0 on
169 * success < 0 when the phase of the (state,seq) has already ran. */
170int boot_state_block(boot_state_t state, boot_state_sequence_t seq);
171int boot_state_unblock(boot_state_t state, boot_state_sequence_t seq);
172/* Block/Unblock current state phase from transitioning. */
173void boot_state_current_block(void);
174void boot_state_current_unblock(void);
175
Aaron Durbin7e35efa2013-04-24 15:14:01 -0500176/* Entry into the boot state machine. */
Stefan Reinauer6adef082013-05-09 16:30:06 -0700177void main(void);
Aaron Durbin7e35efa2013-04-24 15:14:01 -0500178
Aaron Durbina4feddf2013-04-24 16:12:52 -0500179/* In order to schedule boot state callbacks at compile-time specify the
180 * entries in an array using the BOOT_STATE_INIT_ENTRIES and
181 * BOOT_STATE_INIT_ENTRY macros below. */
182struct boot_state_init_entry {
183 boot_state_t state;
184 boot_state_sequence_t when;
185 struct boot_state_callback bscb;
186};
187
188#define BOOT_STATE_INIT_ATTR __attribute__ ((used,section (".bs_init")))
189
Aaron Durbin9ef9d852015-03-16 17:30:09 -0500190#define BOOT_STATE_INIT_ENTRY(state_, when_, func_, arg_) \
191 static struct boot_state_init_entry func_ ##_## state_ ##_## when_ = \
192 { \
193 .state = state_, \
194 .when = when_, \
195 .bscb = BOOT_STATE_CALLBACK_INIT(func_, arg_), \
196 }; \
197 static struct boot_state_init_entry * \
198 bsie_ ## func_ ##_## state_ ##_## when_ BOOT_STATE_INIT_ATTR = \
199 & func_ ##_## state_ ##_## when_;
Aaron Durbina4feddf2013-04-24 16:12:52 -0500200
Patrick Georgi5c715ac2014-08-14 19:23:41 +0200201#endif
Aaron Durbin7e35efa2013-04-24 15:14:01 -0500202#endif /* BOOTSTATE_H */