1 /* SPDX-License-Identifier: GPL-2.0-or-later */
3 #include <arch/null_breakpoint.h>
4 #include <arch/stack_canary_breakpoint.h>
6 #include <console/console.h>
7 #include <cpu/x86/mtrr.h>
9 #include <mode_switch.h>
10 #include <timestamp.h>
13 struct fsp_notify_phase_data
{
14 enum fsp_notify_phase notify_phase
;
16 uint8_t post_code_before
;
17 uint8_t post_code_after
;
18 enum timestamp_id timestamp_before
;
19 enum timestamp_id timestamp_after
;
22 static const struct fsp_notify_phase_data notify_data
[] = {
24 .notify_phase
= AFTER_PCI_ENUM
,
25 .skip
= !CONFIG(USE_FSP_NOTIFY_PHASE_POST_PCI_ENUM
),
26 .post_code_before
= POSTCODE_FSP_NOTIFY_BEFORE_ENUMERATE
,
27 .post_code_after
= POSTCODE_FSP_NOTIFY_AFTER_ENUMERATE
,
28 .timestamp_before
= TS_FSP_ENUMERATE_START
,
29 .timestamp_after
= TS_FSP_ENUMERATE_END
,
32 .notify_phase
= READY_TO_BOOT
,
33 .skip
= !CONFIG(USE_FSP_NOTIFY_PHASE_READY_TO_BOOT
),
34 .post_code_before
= POSTCODE_FSP_NOTIFY_BEFORE_FINALIZE
,
35 .post_code_after
= POSTCODE_FSP_NOTIFY_AFTER_FINALIZE
,
36 .timestamp_before
= TS_FSP_FINALIZE_START
,
37 .timestamp_after
= TS_FSP_FINALIZE_END
,
40 .notify_phase
= END_OF_FIRMWARE
,
41 .skip
= !CONFIG(USE_FSP_NOTIFY_PHASE_END_OF_FIRMWARE
),
42 .post_code_before
= POSTCODE_FSP_NOTIFY_BEFORE_END_OF_FIRMWARE
,
43 .post_code_after
= POSTCODE_FSP_NOTIFY_AFTER_END_OF_FIRMWARE
,
44 .timestamp_before
= TS_FSP_END_OF_FIRMWARE_START
,
45 .timestamp_after
= TS_FSP_END_OF_FIRMWARE_END
,
49 static const struct fsp_notify_phase_data
*get_notify_phase_data(enum fsp_notify_phase phase
)
51 for (size_t i
= 0; i
< ARRAY_SIZE(notify_data
); i
++) {
52 if (notify_data
[i
].notify_phase
== phase
)
53 return ¬ify_data
[i
];
55 die("Unknown FSP notify phase %u\n", phase
);
58 static void fsp_notify(enum fsp_notify_phase phase
)
60 const struct fsp_notify_phase_data
*data
= get_notify_phase_data(phase
);
61 struct fsp_notify_params notify_params
= { .phase
= phase
};
62 fsp_notify_fn fspnotify
;
66 printk(BIOS_INFO
, "coreboot skipped calling FSP notify phase: %08x.\n", phase
);
70 if (!fsps_hdr
.notify_phase_entry_offset
)
71 die("Notify_phase_entry_offset is zero!\n");
73 fspnotify
= (void *)(uintptr_t)(fsps_hdr
.image_base
+
74 fsps_hdr
.notify_phase_entry_offset
);
75 fsp_before_debug_notify(fspnotify
, ¬ify_params
);
77 timestamp_add_now(data
->timestamp_before
);
78 post_code(data
->post_code_before
);
80 /* FSP disables the interrupt handler so remove debug exceptions temporarily */
81 null_breakpoint_remove();
82 stack_canary_breakpoint_remove();
83 if (ENV_X86_64
&& CONFIG(PLATFORM_USES_FSP2_X86_32
))
84 ret
= protected_mode_call_1arg(fspnotify
, (uintptr_t)¬ify_params
);
86 ret
= fspnotify(¬ify_params
);
87 null_breakpoint_init();
88 stack_canary_breakpoint_init();
90 timestamp_add_now(data
->timestamp_after
);
91 post_code(data
->post_code_after
);
93 fsp_debug_after_notify(ret
);
95 /* Handle any errors returned by FspNotify */
96 fsp_handle_reset(ret
);
97 if (ret
!= FSP_SUCCESS
)
98 die("FspNotify returned with error 0x%08x!\n", ret
);
100 /* Allow the platform to run something after FspNotify */
101 platform_fsp_notify_status(phase
);
104 static void fsp_notify_dummy(void *arg
)
106 enum fsp_notify_phase phase
= (uint32_t)(uintptr_t)arg
;
111 if (phase
== READY_TO_BOOT
)
112 fsp_notify(END_OF_FIRMWARE
);
115 BOOT_STATE_INIT_ENTRY(BS_DEV_ENABLE
, BS_ON_ENTRY
, fsp_notify_dummy
, (void *)AFTER_PCI_ENUM
);
116 BOOT_STATE_INIT_ENTRY(BS_PAYLOAD_LOAD
, BS_ON_EXIT
, fsp_notify_dummy
, (void *)READY_TO_BOOT
);
117 BOOT_STATE_INIT_ENTRY(BS_OS_RESUME
, BS_ON_ENTRY
, fsp_notify_dummy
, (void *)READY_TO_BOOT
);
119 __weak
void platform_fsp_notify_status(enum fsp_notify_phase phase
)