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
22 #include <arch/exception.h>
23 #include <bootstate.h>
24 #include <console/console.h>
25 #include <console/post_codes.h>
28 #include <device/device.h>
29 #include <device/pci.h>
33 #include <boot/tables.h>
34 #include <program_loading.h>
36 #if IS_ENABLED(CONFIG_HAVE_ACPI_RESUME)
37 #include <arch/acpi.h>
40 #include <timestamp.h>
43 static boot_state_t
bs_pre_device(void *arg
);
44 static boot_state_t
bs_dev_init_chips(void *arg
);
45 static boot_state_t
bs_dev_enumerate(void *arg
);
46 static boot_state_t
bs_dev_resources(void *arg
);
47 static boot_state_t
bs_dev_enable(void *arg
);
48 static boot_state_t
bs_dev_init(void *arg
);
49 static boot_state_t
bs_post_device(void *arg
);
50 static boot_state_t
bs_os_resume_check(void *arg
);
51 static boot_state_t
bs_os_resume(void *arg
);
52 static boot_state_t
bs_write_tables(void *arg
);
53 static boot_state_t
bs_payload_load(void *arg
);
54 static boot_state_t
bs_payload_boot(void *arg
);
57 * Typically a state will take 4 time samples:
58 * 1. Before state entry callbacks
59 * 2. After state entry callbacks / Before state function.
60 * 3. After state function / Before state exit callbacks.
61 * 4. After state exit callbacks.
63 #define MAX_TIME_SAMPLES 4
64 struct boot_state_times
{
66 struct mono_time samples
[MAX_TIME_SAMPLES
];
69 /* The prologue (BS_ON_ENTRY) and epilogue (BS_ON_EXIT) of a state can be
70 * blocked from transitioning to the next (state,seq) pair. When the blockers
71 * field is 0 a transition may occur. */
73 struct boot_state_callback
*callbacks
;
81 struct boot_phase phases
[2];
82 boot_state_t (*run_state
)(void *arg
);
85 #if IS_ENABLED(CONFIG_HAVE_MONOTONIC_TIMER)
86 struct boot_state_times times
;
90 #define BS_INIT(state_, run_func_) \
94 .post_code = POST_ ## state_, \
95 .phases = { { NULL, 0 }, { NULL, 0 } }, \
96 .run_state = run_func_, \
100 #define BS_INIT_ENTRY(state_, run_func_) \
101 [state_] = BS_INIT(state_, run_func_)
103 static struct boot_state boot_states
[] = {
104 BS_INIT_ENTRY(BS_PRE_DEVICE
, bs_pre_device
),
105 BS_INIT_ENTRY(BS_DEV_INIT_CHIPS
, bs_dev_init_chips
),
106 BS_INIT_ENTRY(BS_DEV_ENUMERATE
, bs_dev_enumerate
),
107 BS_INIT_ENTRY(BS_DEV_RESOURCES
, bs_dev_resources
),
108 BS_INIT_ENTRY(BS_DEV_ENABLE
, bs_dev_enable
),
109 BS_INIT_ENTRY(BS_DEV_INIT
, bs_dev_init
),
110 BS_INIT_ENTRY(BS_POST_DEVICE
, bs_post_device
),
111 BS_INIT_ENTRY(BS_OS_RESUME_CHECK
, bs_os_resume_check
),
112 BS_INIT_ENTRY(BS_OS_RESUME
, bs_os_resume
),
113 BS_INIT_ENTRY(BS_WRITE_TABLES
, bs_write_tables
),
114 BS_INIT_ENTRY(BS_PAYLOAD_LOAD
, bs_payload_load
),
115 BS_INIT_ENTRY(BS_PAYLOAD_BOOT
, bs_payload_boot
),
118 void __attribute__((weak
)) arch_bootstate_coreboot_exit(void) { }
120 static boot_state_t
bs_pre_device(void *arg
)
122 return BS_DEV_INIT_CHIPS
;
125 static boot_state_t
bs_dev_init_chips(void *arg
)
127 timestamp_add_now(TS_DEVICE_ENUMERATE
);
129 /* Initialize chips early, they might disable unused devices. */
130 dev_initialize_chips();
132 return BS_DEV_ENUMERATE
;
135 static boot_state_t
bs_dev_enumerate(void *arg
)
137 /* Find the devices we don't have hard coded knowledge about. */
140 return BS_DEV_RESOURCES
;
143 static boot_state_t
bs_dev_resources(void *arg
)
145 timestamp_add_now(TS_DEVICE_CONFIGURE
);
147 /* Now compute and assign the bus resources. */
150 return BS_DEV_ENABLE
;
153 static boot_state_t
bs_dev_enable(void *arg
)
155 timestamp_add_now(TS_DEVICE_ENABLE
);
157 /* Now actually enable devices on the bus */
163 static boot_state_t
bs_dev_init(void *arg
)
165 timestamp_add_now(TS_DEVICE_INITIALIZE
);
167 /* And of course initialize devices on the bus */
170 return BS_POST_DEVICE
;
173 static boot_state_t
bs_post_device(void *arg
)
176 timestamp_add_now(TS_DEVICE_DONE
);
178 return BS_OS_RESUME_CHECK
;
181 static boot_state_t
bs_os_resume_check(void *arg
)
183 #if IS_ENABLED(CONFIG_HAVE_ACPI_RESUME)
186 wake_vector
= acpi_find_wakeup_vector();
188 if (wake_vector
!= NULL
) {
189 boot_states
[BS_OS_RESUME
].arg
= wake_vector
;
193 acpi_prepare_resume_backup();
195 timestamp_add_now(TS_CBMEM_POST
);
197 return BS_WRITE_TABLES
;
200 static boot_state_t
bs_os_resume(void *wake_vector
)
202 #if IS_ENABLED(CONFIG_HAVE_ACPI_RESUME)
203 arch_bootstate_coreboot_exit();
204 acpi_resume(wake_vector
);
206 return BS_WRITE_TABLES
;
209 static boot_state_t
bs_write_tables(void *arg
)
211 timestamp_add_now(TS_WRITE_TABLES
);
213 /* Now that we have collected all of our information
214 * write our configuration tables.
218 timestamp_add_now(TS_FINALIZE_CHIPS
);
219 dev_finalize_chips();
221 return BS_PAYLOAD_LOAD
;
224 static boot_state_t
bs_payload_load(void *arg
)
228 return BS_PAYLOAD_BOOT
;
231 static boot_state_t
bs_payload_boot(void *arg
)
233 arch_bootstate_coreboot_exit();
236 printk(BIOS_EMERG
, "Boot failed\n");
237 /* Returning from this state will fail because the following signals
238 * return to a completed state. */
239 return BS_PAYLOAD_BOOT
;
242 #if IS_ENABLED(CONFIG_HAVE_MONOTONIC_TIMER)
243 static void bs_sample_time(struct boot_state
*state
)
245 struct mono_time
*mt
;
247 mt
= &state
->times
.samples
[state
->times
.num_samples
];
248 timer_monotonic_get(mt
);
249 state
->times
.num_samples
++;
252 static void bs_report_time(struct boot_state
*state
)
257 struct mono_time
*samples
= &state
->times
.samples
[0];
259 entry_time
= mono_time_diff_microseconds(&samples
[0], &samples
[1]);
260 run_time
= mono_time_diff_microseconds(&samples
[1], &samples
[2]);
261 exit_time
= mono_time_diff_microseconds(&samples
[2], &samples
[3]);
263 printk(BIOS_DEBUG
, "BS: %s times (us): entry %ld run %ld exit %ld\n",
264 state
->name
, entry_time
, run_time
, exit_time
);
267 static inline void bs_sample_time(struct boot_state
*state
) {}
268 static inline void bs_report_time(struct boot_state
*state
) {}
271 #if IS_ENABLED(CONFIG_TIMER_QUEUE)
272 static void bs_run_timers(int drain
)
274 /* Drain all timer callbacks until none are left, if directed.
275 * Otherwise run the timers only once. */
282 static void bs_run_timers(int drain
) {}
285 static void bs_call_callbacks(struct boot_state
*state
,
286 boot_state_sequence_t seq
)
288 struct boot_phase
*phase
= &state
->phases
[seq
];
291 if (phase
->callbacks
!= NULL
) {
292 struct boot_state_callback
*bscb
;
294 /* Remove the first callback. */
295 bscb
= phase
->callbacks
;
296 phase
->callbacks
= bscb
->next
;
299 #if IS_ENABLED(CONFIG_DEBUG_BOOT_STATE)
300 printk(BIOS_DEBUG
, "BS: callback (%p) @ %s.\n",
301 bscb
, bscb
->location
);
303 bscb
->callback(bscb
->arg
);
307 /* All callbacks are complete and there are no blockers for
308 * this state. Therefore, this part of the state is complete. */
309 if (!phase
->blockers
)
312 /* Something is blocking this state from transitioning. As
313 * there are no more callbacks a pending timer needs to be
314 * ran to unblock the state. */
319 /* Keep track of the current state. */
320 static struct state_tracker
{
321 boot_state_t state_id
;
322 boot_state_sequence_t seq
;
324 .state_id
= BS_PRE_DEVICE
,
328 static void bs_walk_state_machine(void)
332 struct boot_state
*state
;
333 boot_state_t next_id
;
335 state
= &boot_states
[current_phase
.state_id
];
337 if (state
->complete
) {
338 printk(BIOS_EMERG
, "BS: %s state already executed.\n",
343 if (IS_ENABLED(CONFIG_DEBUG_BOOT_STATE
))
344 printk(BIOS_DEBUG
, "BS: Entering %s state.\n",
349 bs_sample_time(state
);
351 bs_call_callbacks(state
, current_phase
.seq
);
352 /* Update the current sequence so that any calls to block the
353 * current state from the run_state() function will place a
354 * block on the correct phase. */
355 current_phase
.seq
= BS_ON_EXIT
;
357 bs_sample_time(state
);
359 post_code(state
->post_code
);
361 next_id
= state
->run_state(state
->arg
);
363 if (IS_ENABLED(CONFIG_DEBUG_BOOT_STATE
))
364 printk(BIOS_DEBUG
, "BS: Exiting %s state.\n",
367 bs_sample_time(state
);
369 bs_call_callbacks(state
, current_phase
.seq
);
371 if (IS_ENABLED(CONFIG_DEBUG_BOOT_STATE
))
373 "----------------------------------------\n");
375 /* Update the current phase with new state id and sequence. */
376 current_phase
.state_id
= next_id
;
377 current_phase
.seq
= BS_ON_ENTRY
;
379 bs_sample_time(state
);
381 bs_report_time(state
);
387 static int boot_state_sched_callback(struct boot_state
*state
,
388 struct boot_state_callback
*bscb
,
389 boot_state_sequence_t seq
)
391 if (state
->complete
) {
393 "Tried to schedule callback on completed state %s.\n",
399 bscb
->next
= state
->phases
[seq
].callbacks
;
400 state
->phases
[seq
].callbacks
= bscb
;
405 int boot_state_sched_on_entry(struct boot_state_callback
*bscb
,
406 boot_state_t state_id
)
408 struct boot_state
*state
= &boot_states
[state_id
];
410 return boot_state_sched_callback(state
, bscb
, BS_ON_ENTRY
);
413 int boot_state_sched_on_exit(struct boot_state_callback
*bscb
,
414 boot_state_t state_id
)
416 struct boot_state
*state
= &boot_states
[state_id
];
418 return boot_state_sched_callback(state
, bscb
, BS_ON_EXIT
);
421 static void boot_state_schedule_static_entries(void)
423 extern struct boot_state_init_entry
*_bs_init_begin
[];
424 struct boot_state_init_entry
**slot
;
426 for (slot
= &_bs_init_begin
[0]; *slot
!= NULL
; slot
++) {
427 struct boot_state_init_entry
*cur
= *slot
;
429 if (cur
->when
== BS_ON_ENTRY
)
430 boot_state_sched_on_entry(&cur
->bscb
, cur
->state
);
432 boot_state_sched_on_exit(&cur
->bscb
, cur
->state
);
439 * We can generally jump between C and Ada code back and forth
440 * without trouble. But since we don't have an Ada main() we
441 * have to do some Ada package initializations that GNAT would
442 * do there. This has to be done before calling any Ada code.
444 * The package initializations should not have any dependen-
445 * cies on C code. So we can call them here early, and don't
446 * have to worry at which point we can start to use Ada.
450 /* TODO: Understand why this is here and move to arch/platform code. */
451 /* For MMIO UART this needs to be called before any other printk. */
452 if (IS_ENABLED(CONFIG_ARCH_X86
))
455 /* console_init() MUST PRECEDE ALL printk()! Additionally, ensure
456 * it is the very first thing done in ramstage.*/
459 post_code(POST_CONSOLE_READY
);
462 * CBMEM needs to be recovered in the EARLY_CBMEM_INIT case because
463 * timestamps, APCI, etc rely on the cbmem infrastructure being
464 * around. Explicitly recover it.
466 if (IS_ENABLED(CONFIG_EARLY_CBMEM_INIT
))
469 /* Record current time, try to locate timestamps in CBMEM. */
470 timestamp_init(timestamp_get());
472 timestamp_add_now(TS_START_RAMSTAGE
);
473 post_code(POST_ENTRY_RAMSTAGE
);
475 /* Handoff sleep type from romstage. */
476 #if IS_ENABLED(CONFIG_HAVE_ACPI_RESUME)
481 threads_initialize();
483 /* Schedule the static boot state entries. */
484 boot_state_schedule_static_entries();
486 bs_walk_state_machine();
488 die("Boot state machine failure.\n");
492 int boot_state_block(boot_state_t state
, boot_state_sequence_t seq
)
494 struct boot_phase
*bp
;
496 /* Blocking a previously ran state is not appropriate. */
497 if (current_phase
.state_id
> state
||
498 (current_phase
.state_id
== state
&& current_phase
.seq
> seq
)) {
500 "BS: Completed state (%d, %d) block attempted.\n",
505 bp
= &boot_states
[state
].phases
[seq
];
511 int boot_state_unblock(boot_state_t state
, boot_state_sequence_t seq
)
513 struct boot_phase
*bp
;
515 /* Blocking a previously ran state is not appropriate. */
516 if (current_phase
.state_id
> state
||
517 (current_phase
.state_id
== state
&& current_phase
.seq
> seq
)) {
519 "BS: Completed state (%d, %d) unblock attempted.\n",
524 bp
= &boot_states
[state
].phases
[seq
];
526 if (bp
->blockers
== 0) {
528 "BS: Unblock attempted on non-blocked state (%d, %d).\n",
538 void boot_state_current_block(void)
540 boot_state_block(current_phase
.state_id
, current_phase
.seq
);
543 void boot_state_current_unblock(void)
545 boot_state_unblock(current_phase
.state_id
, current_phase
.seq
);