/* * This file is part of the coreboot project. * * Copyright 2016 Google Inc. * * 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 #include #include #include "misc.h" #include "../vboot_common.h" static int vb2_get_recovery_reason_shared_data(void) { /* Shared data does not exist for Ramstage and Post-CAR stage. */ if (ENV_RAMSTAGE || ENV_POSTCAR) return 0; struct vb2_shared_data *sd = vb2_get_shared_data(); assert(sd); return sd->recovery_reason; } /* * Returns 0 for the stages where we know that cbmem does not come online. * Even if this function returns 1 for romstage, depending upon the point in * bootup, cbmem might not actually be online. */ static int cbmem_possibly_online(void) { if (ENV_BOOTBLOCK) return 0; if (ENV_VERSTAGE && IS_ENABLED(CONFIG_VBOOT_STARTS_IN_BOOTBLOCK)) return 0; return 1; } /* * Returns 1 if vboot is being used and currently in a stage which might have * already executed vboot verification. */ static int vboot_possibly_executed(void) { if (!IS_ENABLED(CONFIG_VBOOT_VERIFY_FIRMWARE)) return 0; if (IS_ENABLED(CONFIG_VBOOT_STARTS_IN_BOOTBLOCK)) { if (ENV_BOOTBLOCK && IS_ENABLED(CONFIG_SEPARATE_VERSTAGE)) return 0; return 1; } if (IS_ENABLED(CONFIG_VBOOT_STARTS_IN_ROMSTAGE)) { if (ENV_BOOTBLOCK) return 0; return 1; } return 0; } /* * vb2_check_recovery_request looks up different components to identify if there * is a recovery request and returns appropriate reason code: * 1. Checks if recovery mode is initiated by EC. If yes, returns * VB2_RECOVERY_RO_MANUAL. * 2. Checks if recovery request is present in VBNV and returns the code read * from it. * 3. Checks recovery request in handoff for stages post-cbmem. * 4. For non-CBMEM stages, check if vboot verification is done and look-up * selected region to identify if vboot_refence library has requested recovery * path. If yes, return the reason code from shared data. * 5. If nothing applies, return 0 indicating no recovery request. */ int vboot_check_recovery_request(void) { int reason = 0; /* EC-initiated recovery. */ if (get_recovery_mode_switch()) return VB2_RECOVERY_RO_MANUAL; /* Recovery request in VBNV. */ if ((reason = get_recovery_mode_from_vbnv()) != 0) return reason; /* * Check recovery flag in vboot_handoff for stages post CBMEM coming * online. Since for some stages there is no way to know if cbmem has * already come online, try looking up handoff anyways. If it fails, * flow will fallback to looking up shared data. */ if (cbmem_possibly_online() && ((reason = vboot_handoff_get_recovery_reason()) != 0)) return reason; /* * For stages where CBMEM might not be online, identify if vboot * verification is already complete and no slot was selected * i.e. recovery path was requested. */ if (vboot_possibly_executed() && vb2_logic_executed() && !vb2_is_slot_selected()) return vb2_get_recovery_reason_shared_data(); return 0; }