2 * This file is part of the coreboot project.
4 * Copyright (C) 2013 Google, Inc.
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.
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.
18 * C Bootstrap code for the coreboot
21 #include <arch/exception.h>
22 #include <bootstate.h>
23 #include <console/console.h>
24 #include <console/post_codes.h>
27 #include <device/device.h>
28 #include <device/pci.h>
32 #include <boot/tables.h>
33 #include <program_loading.h>
35 #if CONFIG_HAVE_ACPI_RESUME
36 #include <arch/acpi.h>
39 #include <timestamp.h>
42 static boot_state_t
bs_pre_device(void *arg
);
43 static boot_state_t
bs_dev_init_chips(void *arg
);
44 static boot_state_t
bs_dev_enumerate(void *arg
);
45 static boot_state_t
bs_dev_resources(void *arg
);
46 static boot_state_t
bs_dev_enable(void *arg
);
47 static boot_state_t
bs_dev_init(void *arg
);
48 static boot_state_t
bs_post_device(void *arg
);
49 static boot_state_t
bs_os_resume_check(void *arg
);
50 static boot_state_t
bs_os_resume(void *arg
);
51 static boot_state_t
bs_write_tables(void *arg
);
52 static boot_state_t
bs_payload_load(void *arg
);
53 static boot_state_t
bs_payload_boot(void *arg
);
56 * Typically a state will take 4 time samples:
57 * 1. Before state entry callbacks
58 * 2. After state entry callbacks / Before state function.
59 * 3. After state function / Before state exit callbacks.
60 * 4. After state exit callbacks.
62 #define MAX_TIME_SAMPLES 4
63 struct boot_state_times
{
65 struct mono_time samples
[MAX_TIME_SAMPLES
];
68 /* The prologue (BS_ON_ENTRY) and epilogue (BS_ON_EXIT) of a state can be
69 * blocked from transitioning to the next (state,seq) pair. When the blockers
70 * field is 0 a transition may occur. */
72 struct boot_state_callback
*callbacks
;
80 struct boot_phase phases
[2];
81 boot_state_t (*run_state
)(void *arg
);
84 #if CONFIG_HAVE_MONOTONIC_TIMER
85 struct boot_state_times times
;
89 #define BS_INIT(state_, run_func_) \
93 .post_code = POST_ ## state_, \
94 .phases = { { NULL, 0 }, { NULL, 0 } }, \
95 .run_state = run_func_, \
99 #define BS_INIT_ENTRY(state_, run_func_) \
100 [state_] = BS_INIT(state_, run_func_)
102 static struct boot_state boot_states
[] = {
103 BS_INIT_ENTRY(BS_PRE_DEVICE
, bs_pre_device
),
104 BS_INIT_ENTRY(BS_DEV_INIT_CHIPS
, bs_dev_init_chips
),
105 BS_INIT_ENTRY(BS_DEV_ENUMERATE
, bs_dev_enumerate
),
106 BS_INIT_ENTRY(BS_DEV_RESOURCES
, bs_dev_resources
),
107 BS_INIT_ENTRY(BS_DEV_ENABLE
, bs_dev_enable
),
108 BS_INIT_ENTRY(BS_DEV_INIT
, bs_dev_init
),
109 BS_INIT_ENTRY(BS_POST_DEVICE
, bs_post_device
),
110 BS_INIT_ENTRY(BS_OS_RESUME_CHECK
, bs_os_resume_check
),
111 BS_INIT_ENTRY(BS_OS_RESUME
, bs_os_resume
),
112 BS_INIT_ENTRY(BS_WRITE_TABLES
, bs_write_tables
),
113 BS_INIT_ENTRY(BS_PAYLOAD_LOAD
, bs_payload_load
),
114 BS_INIT_ENTRY(BS_PAYLOAD_BOOT
, bs_payload_boot
),
117 static boot_state_t
bs_pre_device(void *arg
)
119 return BS_DEV_INIT_CHIPS
;
122 static boot_state_t
bs_dev_init_chips(void *arg
)
124 timestamp_add_now(TS_DEVICE_ENUMERATE
);
126 /* Initialize chips early, they might disable unused devices. */
127 dev_initialize_chips();
129 return BS_DEV_ENUMERATE
;
132 static boot_state_t
bs_dev_enumerate(void *arg
)
134 /* Find the devices we don't have hard coded knowledge about. */
137 return BS_DEV_RESOURCES
;
140 static boot_state_t
bs_dev_resources(void *arg
)
142 timestamp_add_now(TS_DEVICE_CONFIGURE
);
144 /* Now compute and assign the bus resources. */
147 return BS_DEV_ENABLE
;
150 static boot_state_t
bs_dev_enable(void *arg
)
152 timestamp_add_now(TS_DEVICE_ENABLE
);
154 /* Now actually enable devices on the bus */
160 static boot_state_t
bs_dev_init(void *arg
)
162 timestamp_add_now(TS_DEVICE_INITIALIZE
);
164 /* And of course initialize devices on the bus */
167 return BS_POST_DEVICE
;
170 static boot_state_t
bs_post_device(void *arg
)
173 timestamp_add_now(TS_DEVICE_DONE
);
175 return BS_OS_RESUME_CHECK
;
178 static boot_state_t
bs_os_resume_check(void *arg
)
180 #if CONFIG_HAVE_ACPI_RESUME
183 wake_vector
= acpi_find_wakeup_vector();
185 if (wake_vector
!= NULL
) {
186 boot_states
[BS_OS_RESUME
].arg
= wake_vector
;
190 acpi_prepare_resume_backup();
192 timestamp_add_now(TS_CBMEM_POST
);
194 return BS_WRITE_TABLES
;
197 static boot_state_t
bs_os_resume(void *wake_vector
)
199 #if CONFIG_HAVE_ACPI_RESUME
200 acpi_resume(wake_vector
);
202 return BS_WRITE_TABLES
;
205 static boot_state_t
bs_write_tables(void *arg
)
207 timestamp_add_now(TS_WRITE_TABLES
);
209 /* Now that we have collected all of our information
210 * write our configuration tables.
214 dev_finalize_chips();
216 return BS_PAYLOAD_LOAD
;
219 static boot_state_t
bs_payload_load(void *arg
)
223 return BS_PAYLOAD_BOOT
;
226 static boot_state_t
bs_payload_boot(void *arg
)
230 printk(BIOS_EMERG
, "Boot failed\n");
231 /* Returning from this state will fail because the following signals
232 * return to a completed state. */
233 return BS_PAYLOAD_BOOT
;
236 #if CONFIG_HAVE_MONOTONIC_TIMER
237 static void bs_sample_time(struct boot_state
*state
)
239 struct mono_time
*mt
;
241 mt
= &state
->times
.samples
[state
->times
.num_samples
];
242 timer_monotonic_get(mt
);
243 state
->times
.num_samples
++;
246 static void bs_report_time(struct boot_state
*state
)
251 struct mono_time
*samples
= &state
->times
.samples
[0];
253 entry_time
= mono_time_diff_microseconds(&samples
[0], &samples
[1]);
254 run_time
= mono_time_diff_microseconds(&samples
[1], &samples
[2]);
255 exit_time
= mono_time_diff_microseconds(&samples
[2], &samples
[3]);
257 printk(BIOS_DEBUG
, "BS: %s times (us): entry %ld run %ld exit %ld\n",
258 state
->name
, entry_time
, run_time
, exit_time
);
261 static inline void bs_sample_time(struct boot_state
*state
) {}
262 static inline void bs_report_time(struct boot_state
*state
) {}
265 #if CONFIG_TIMER_QUEUE
266 static void bs_run_timers(int drain
)
268 /* Drain all timer callbacks until none are left, if directed.
269 * Otherwise run the timers only once. */
276 static void bs_run_timers(int drain
) {}
279 static void bs_call_callbacks(struct boot_state
*state
,
280 boot_state_sequence_t seq
)
282 struct boot_phase
*phase
= &state
->phases
[seq
];
285 if (phase
->callbacks
!= NULL
) {
286 struct boot_state_callback
*bscb
;
288 /* Remove the first callback. */
289 bscb
= phase
->callbacks
;
290 phase
->callbacks
= bscb
->next
;
293 #if IS_ENABLED(CONFIG_DEBUG_BOOT_STATE)
294 printk(BIOS_DEBUG
, "BS: callback (%p) @ %s.\n",
295 bscb
, bscb
->location
);
297 bscb
->callback(bscb
->arg
);
301 /* All callbacks are complete and there are no blockers for
302 * this state. Therefore, this part of the state is complete. */
303 if (!phase
->blockers
)
306 /* Something is blocking this state from transitioning. As
307 * there are no more callbacks a pending timer needs to be
308 * ran to unblock the state. */
313 /* Keep track of the current state. */
314 static struct state_tracker
{
315 boot_state_t state_id
;
316 boot_state_sequence_t seq
;
318 .state_id
= BS_PRE_DEVICE
,
322 static void bs_walk_state_machine(void)
326 struct boot_state
*state
;
327 boot_state_t next_id
;
329 state
= &boot_states
[current_phase
.state_id
];
331 if (state
->complete
) {
332 printk(BIOS_EMERG
, "BS: %s state already executed.\n",
337 if (IS_ENABLED(CONFIG_DEBUG_BOOT_STATE
))
338 printk(BIOS_DEBUG
, "BS: Entering %s state.\n",
343 bs_sample_time(state
);
345 bs_call_callbacks(state
, current_phase
.seq
);
346 /* Update the current sequence so that any calls to block the
347 * current state from the run_state() function will place a
348 * block on the correct phase. */
349 current_phase
.seq
= BS_ON_EXIT
;
351 bs_sample_time(state
);
353 post_code(state
->post_code
);
355 next_id
= state
->run_state(state
->arg
);
357 if (IS_ENABLED(CONFIG_DEBUG_BOOT_STATE
))
358 printk(BIOS_DEBUG
, "BS: Exiting %s state.\n",
361 bs_sample_time(state
);
363 bs_call_callbacks(state
, current_phase
.seq
);
365 if (IS_ENABLED(CONFIG_DEBUG_BOOT_STATE
))
367 "----------------------------------------\n");
369 /* Update the current phase with new state id and sequence. */
370 current_phase
.state_id
= next_id
;
371 current_phase
.seq
= BS_ON_ENTRY
;
373 bs_sample_time(state
);
375 bs_report_time(state
);
381 static int boot_state_sched_callback(struct boot_state
*state
,
382 struct boot_state_callback
*bscb
,
383 boot_state_sequence_t seq
)
385 if (state
->complete
) {
387 "Tried to schedule callback on completed state %s.\n",
393 bscb
->next
= state
->phases
[seq
].callbacks
;
394 state
->phases
[seq
].callbacks
= bscb
;
399 int boot_state_sched_on_entry(struct boot_state_callback
*bscb
,
400 boot_state_t state_id
)
402 struct boot_state
*state
= &boot_states
[state_id
];
404 return boot_state_sched_callback(state
, bscb
, BS_ON_ENTRY
);
407 int boot_state_sched_on_exit(struct boot_state_callback
*bscb
,
408 boot_state_t state_id
)
410 struct boot_state
*state
= &boot_states
[state_id
];
412 return boot_state_sched_callback(state
, bscb
, BS_ON_EXIT
);
415 static void boot_state_schedule_static_entries(void)
417 extern struct boot_state_init_entry
*_bs_init_begin
[];
418 struct boot_state_init_entry
**slot
;
420 for (slot
= &_bs_init_begin
[0]; *slot
!= NULL
; slot
++) {
421 struct boot_state_init_entry
*cur
= *slot
;
423 if (cur
->when
== BS_ON_ENTRY
)
424 boot_state_sched_on_entry(&cur
->bscb
, cur
->state
);
426 boot_state_sched_on_exit(&cur
->bscb
, cur
->state
);
432 /* TODO: Understand why this is here and move to arch/platform code. */
433 /* For MMIO UART this needs to be called before any other printk. */
434 if (IS_ENABLED(CONFIG_ARCH_X86
))
437 /* console_init() MUST PRECEDE ALL printk()! Additionally, ensure
438 * it is the very first thing done in ramstage.*/
441 post_code(POST_CONSOLE_READY
);
444 * CBMEM needs to be recovered in the EARLY_CBMEM_INIT case because
445 * timestamps, APCI, etc rely on the cbmem infrastructure being
446 * around. Explicitly recover it.
448 if (IS_ENABLED(CONFIG_EARLY_CBMEM_INIT
))
451 /* Record current time, try to locate timestamps in CBMEM. */
452 timestamp_init(timestamp_get());
454 timestamp_add_now(TS_START_RAMSTAGE
);
455 post_code(POST_ENTRY_RAMSTAGE
);
457 /* Handoff sleep type from romstage. */
458 #if CONFIG_HAVE_ACPI_RESUME
463 threads_initialize();
465 /* Schedule the static boot state entries. */
466 boot_state_schedule_static_entries();
468 bs_walk_state_machine();
470 die("Boot state machine failure.\n");
474 int boot_state_block(boot_state_t state
, boot_state_sequence_t seq
)
476 struct boot_phase
*bp
;
478 /* Blocking a previously ran state is not appropriate. */
479 if (current_phase
.state_id
> state
||
480 (current_phase
.state_id
== state
&& current_phase
.seq
> seq
) ) {
482 "BS: Completed state (%d, %d) block attempted.\n",
487 bp
= &boot_states
[state
].phases
[seq
];
493 int boot_state_unblock(boot_state_t state
, boot_state_sequence_t seq
)
495 struct boot_phase
*bp
;
497 /* Blocking a previously ran state is not appropriate. */
498 if (current_phase
.state_id
> state
||
499 (current_phase
.state_id
== state
&& current_phase
.seq
> seq
) ) {
501 "BS: Completed state (%d, %d) unblock attempted.\n",
506 bp
= &boot_states
[state
].phases
[seq
];
508 if (bp
->blockers
== 0) {
510 "BS: Unblock attempted on non-blocked state (%d, %d).\n",
520 void boot_state_current_block(void)
522 boot_state_block(current_phase
.state_id
, current_phase
.seq
);
525 void boot_state_current_unblock(void)
527 boot_state_unblock(current_phase
.state_id
, current_phase
.seq
);