diff --git a/src/soc/intel/skylake/Makefile.inc b/src/soc/intel/skylake/Makefile.inc index d6c2212310..9c578c56c1 100644 --- a/src/soc/intel/skylake/Makefile.inc +++ b/src/soc/intel/skylake/Makefile.inc @@ -37,6 +37,7 @@ ramstage-y += cpu_info.c ramstage-y += elog.c ramstage-y += finalize.c ramstage-y += flash_controller.c +ramstage-$(CONFIG_VBOOT_VERIFY_FIRMWARE) += fsp_reset.c ramstage-y += gpio.c ramstage-y += igd.c ramstage-y += lpc.c diff --git a/src/soc/intel/skylake/fsp_reset.c b/src/soc/intel/skylake/fsp_reset.c new file mode 100644 index 0000000000..4751872a47 --- /dev/null +++ b/src/soc/intel/skylake/fsp_reset.c @@ -0,0 +1,62 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2015 Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#include +#include + +static int is_recovery; /* flag to identify recovery mode */ + +/* + * coreboot used to clear recovery status towards romstage end after FSP + * memory init. Later inside FSP silicon init due to HSIO CRC mismatch + * or other silicon related programming may request for an additional + * reset. Thus on the next boot the system resumed in normal mode rather than + * recovery because it lost its original state due to FSP silicon init reset. + * Hence it needs an addition reset to get into old state and continue + * booting into recovery mode. This function will set recovery reason + * during Silicon init, in case of recovery mode booting, + * so, system will not lose its original context. + */ +static void set_recovery_request(void *unused) +{ + is_recovery = recovery_mode_enabled(); + /* + * Set recovery flag during Recovery Mode Silicon Init + * & store recovery request into VBNV + */ + if (is_recovery) + set_recovery_mode_into_vbnv(vboot_recovery_reason()); + +} + +static void clear_recovery_request(void *unused) +{ + /* + * Done with Silicon Init, it's safe to clear + * reset request now with assumption that no reset occurs hereafter + * so we will not miss original data. + */ + if (is_recovery) + set_recovery_mode_into_vbnv(0); +} +/* + * On Recovery Path Set Recovery Request during early RAMSTAGE + * before initiated Silicon Init + */ +BOOT_STATE_INIT_ENTRY(BS_PRE_DEVICE, BS_ON_ENTRY, set_recovery_request, NULL); +/* + * On Recovery Path Clear Recovery Request during early RAMSTAGE + * end of Silicon Init + */ +BOOT_STATE_INIT_ENTRY(BS_DEV_INIT_CHIPS, BS_ON_EXIT, clear_recovery_request, NULL); diff --git a/src/vendorcode/google/chromeos/chromeos.h b/src/vendorcode/google/chromeos/chromeos.h index caf18946bf..9dbb68129d 100644 --- a/src/vendorcode/google/chromeos/chromeos.h +++ b/src/vendorcode/google/chromeos/chromeos.h @@ -29,6 +29,7 @@ void save_chromeos_gpios(void); /* functions implemented in vbnv.c: */ int get_recovery_mode_from_vbnv(void); +void set_recovery_mode_into_vbnv(int recovery_reason); int vboot_wants_oprom(void); void read_vbnv(uint8_t *vbnv_copy); diff --git a/src/vendorcode/google/chromeos/vbnv_cmos.c b/src/vendorcode/google/chromeos/vbnv_cmos.c index d7850b6796..27f7f0a211 100644 --- a/src/vendorcode/google/chromeos/vbnv_cmos.c +++ b/src/vendorcode/google/chromeos/vbnv_cmos.c @@ -104,6 +104,22 @@ static void vbnv_setup(void) car_set_var(vbnv_initialized, 1); } +void set_recovery_mode_into_vbnv(int recovery_reason) +{ + uint8_t vbnv_copy[CONFIG_VBNV_SIZE]; + uint8_t crc_val; + + read_vbnv(vbnv_copy); + + vbnv_copy[RECOVERY_OFFSET] = recovery_reason; + + crc_val = crc8(vbnv_copy, CRC_OFFSET); + + vbnv_copy[CRC_OFFSET] = crc_val; + + save_vbnv(vbnv_copy); +} + int get_recovery_mode_from_vbnv(void) { if (!is_vbnv_initialized()) diff --git a/src/vendorcode/google/chromeos/vboot_common.c b/src/vendorcode/google/chromeos/vboot_common.c index ac16382186..448aad6db0 100644 --- a/src/vendorcode/google/chromeos/vboot_common.c +++ b/src/vendorcode/google/chromeos/vboot_common.c @@ -77,6 +77,21 @@ int vboot_enable_recovery(void) return vboot_handoff_flag(VB_INIT_OUT_ENABLE_RECOVERY); } +int vboot_recovery_reason(void) +{ + struct vboot_handoff *vbho; + VbSharedDataHeader *sd; + + vbho = cbmem_find(CBMEM_ID_VBOOT_HANDOFF); + + if (vbho == NULL) + return 0; + + sd = (VbSharedDataHeader *)vbho->shared_data; + + return sd->recovery_reason; +} + void vboot_reboot(void) { if (IS_ENABLED(CONFIG_CONSOLE_CBMEM_DUMP_TO_UART)) diff --git a/src/vendorcode/google/chromeos/vboot_common.h b/src/vendorcode/google/chromeos/vboot_common.h index cc79fa5efd..fbffc29d54 100644 --- a/src/vendorcode/google/chromeos/vboot_common.h +++ b/src/vendorcode/google/chromeos/vboot_common.h @@ -42,6 +42,8 @@ int vboot_skip_display_init(void); int vboot_enable_recovery(void); int vboot_enable_developer(void); +int vboot_recovery_reason(void); + void vboot_reboot(void); /* Main logic for verified boot. verstage() is the stage entry point