1 /* SPDX-License-Identifier: GPL-2.0-or-later */
3 #include <arch/null_breakpoint.h>
5 #include <console/console.h>
6 #include <cpu/x86/mtrr.h>
8 #include <mode_switch.h>
12 struct fsp_notify_phase_data
{
13 enum fsp_notify_phase notify_phase
;
15 uint8_t post_code_before
;
16 uint8_t post_code_after
;
17 enum timestamp_id timestamp_before
;
18 enum timestamp_id timestamp_after
;
21 static const struct fsp_notify_phase_data notify_data
[] = {
23 .notify_phase
= AFTER_PCI_ENUM
,
24 .skip
= !CONFIG(USE_FSP_NOTIFY_PHASE_POST_PCI_ENUM
),
25 .post_code_before
= POST_FSP_NOTIFY_BEFORE_ENUMERATE
,
26 .post_code_after
= POST_FSP_NOTIFY_AFTER_ENUMERATE
,
27 .timestamp_before
= TS_FSP_ENUMERATE_START
,
28 .timestamp_after
= TS_FSP_ENUMERATE_END
,
31 .notify_phase
= READY_TO_BOOT
,
32 .skip
= !CONFIG(USE_FSP_NOTIFY_PHASE_READY_TO_BOOT
),
33 .post_code_before
= POST_FSP_NOTIFY_BEFORE_FINALIZE
,
34 .post_code_after
= POST_FSP_NOTIFY_AFTER_FINALIZE
,
35 .timestamp_before
= TS_FSP_FINALIZE_START
,
36 .timestamp_after
= TS_FSP_FINALIZE_END
,
39 .notify_phase
= END_OF_FIRMWARE
,
40 .skip
= !CONFIG(USE_FSP_NOTIFY_PHASE_END_OF_FIRMWARE
),
41 .post_code_before
= POST_FSP_NOTIFY_BEFORE_END_OF_FIRMWARE
,
42 .post_code_after
= POST_FSP_NOTIFY_AFTER_END_OF_FIRMWARE
,
43 .timestamp_before
= TS_FSP_END_OF_FIRMWARE_START
,
44 .timestamp_after
= TS_FSP_END_OF_FIRMWARE_END
,
48 static const struct fsp_notify_phase_data
*get_notify_phase_data(enum fsp_notify_phase phase
)
50 for (size_t i
= 0; i
< ARRAY_SIZE(notify_data
); i
++) {
51 if (notify_data
[i
].notify_phase
== phase
)
52 return ¬ify_data
[i
];
54 die("Unknown FSP notify phase %u\n", phase
);
57 static void fsp_notify(enum fsp_notify_phase phase
)
59 const struct fsp_notify_phase_data
*data
= get_notify_phase_data(phase
);
60 struct fsp_notify_params notify_params
= { .phase
= phase
};
61 fsp_notify_fn fspnotify
;
65 printk(BIOS_INFO
, "coreboot skipped calling FSP notify phase: %08x.\n", phase
);
69 if (!fsps_hdr
.notify_phase_entry_offset
)
70 die("Notify_phase_entry_offset is zero!\n");
72 fspnotify
= (void *)(uintptr_t)(fsps_hdr
.image_base
+
73 fsps_hdr
.notify_phase_entry_offset
);
74 fsp_before_debug_notify(fspnotify
, ¬ify_params
);
76 timestamp_add_now(data
->timestamp_before
);
77 post_code(data
->post_code_before
);
79 /* FSP disables the interrupt handler so remove debug exceptions temporarily */
80 null_breakpoint_disable();
81 if (ENV_X86_64
&& CONFIG(PLATFORM_USES_FSP2_X86_32
))
82 ret
= protected_mode_call_1arg(fspnotify
, (uintptr_t)¬ify_params
);
84 ret
= fspnotify(¬ify_params
);
85 null_breakpoint_init();
87 timestamp_add_now(data
->timestamp_after
);
88 post_code(data
->post_code_after
);
90 fsp_debug_after_notify(ret
);
92 /* Handle any errors returned by FspNotify */
93 fsp_handle_reset(ret
);
94 if (ret
!= FSP_SUCCESS
)
95 die("FspNotify returned with error 0x%08x!\n", ret
);
97 /* Allow the platform to run something after FspNotify */
98 platform_fsp_notify_status(phase
);
101 static void fsp_notify_dummy(void *arg
)
103 enum fsp_notify_phase phase
= (uint32_t)(uintptr_t)arg
;
108 if (phase
== READY_TO_BOOT
)
109 fsp_notify(END_OF_FIRMWARE
);
112 BOOT_STATE_INIT_ENTRY(BS_DEV_ENABLE
, BS_ON_ENTRY
, fsp_notify_dummy
, (void *)AFTER_PCI_ENUM
);
113 BOOT_STATE_INIT_ENTRY(BS_PAYLOAD_LOAD
, BS_ON_EXIT
, fsp_notify_dummy
, (void *)READY_TO_BOOT
);
114 BOOT_STATE_INIT_ENTRY(BS_OS_RESUME
, BS_ON_ENTRY
, fsp_notify_dummy
, (void *)READY_TO_BOOT
);
116 __weak
void platform_fsp_notify_status(enum fsp_notify_phase phase
)