123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125 |
- /* Copyright 2016 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
- #include <stdint.h>
- #include "bdb.h"
- #include "bdb_api.h"
- #include "vboot_register.h"
- static int did_current_slot_fail(struct vba_context *ctx)
- {
- uint32_t val = vbe_get_vboot_register(VBOOT_REGISTER_PERSIST);
- if (ctx->slot)
- return val & VBOOT_REGISTER_FAILED_RW_SECONDARY;
- else
- return val & VBOOT_REGISTER_FAILED_RW_PRIMARY;
- }
- static int did_other_slot_fail(struct vba_context *ctx)
- {
- uint32_t val = vbe_get_vboot_register(VBOOT_REGISTER_PERSIST);
- if (ctx->slot)
- return val & VBOOT_REGISTER_FAILED_RW_PRIMARY;
- else
- return val & VBOOT_REGISTER_FAILED_RW_SECONDARY;
- }
- static void set_try_other_slot(struct vba_context *ctx)
- {
- uint32_t val = vbe_get_vboot_register(VBOOT_REGISTER_PERSIST);
- if (ctx->slot)
- val &= ~VBOOT_REGISTER_TRY_SECONDARY_BDB;
- else
- val |= VBOOT_REGISTER_TRY_SECONDARY_BDB;
- vbe_set_vboot_register(VBOOT_REGISTER_PERSIST, val);
- }
- static void set_recovery_request(struct vba_context *ctx)
- {
- uint32_t val = vbe_get_vboot_register(VBOOT_REGISTER_PERSIST);
- val |= VBOOT_REGISTER_RECOVERY_REQUEST;
- vbe_set_vboot_register(VBOOT_REGISTER_PERSIST, val);
- }
- static void get_current_slot(struct vba_context *ctx)
- {
- /* Assume SP-RO selects slot this way */
- ctx->slot = (vbe_get_vboot_register(VBOOT_REGISTER_PERSIST)
- & VBOOT_REGISTER_TRY_SECONDARY_BDB) ? 1 : 0;
- }
- static void set_current_slot_failed(struct vba_context *ctx)
- {
- uint32_t val = vbe_get_vboot_register(VBOOT_REGISTER_PERSIST);
- if (ctx->slot)
- val |= VBOOT_REGISTER_FAILED_RW_SECONDARY;
- else
- val |= VBOOT_REGISTER_FAILED_RW_PRIMARY;
- vbe_set_vboot_register(VBOOT_REGISTER_PERSIST, val);
- }
- static void unset_current_slot_failed(struct vba_context *ctx)
- {
- uint32_t val = vbe_get_vboot_register(VBOOT_REGISTER_PERSIST);
- if (ctx->slot)
- val &= ~VBOOT_REGISTER_FAILED_RW_SECONDARY;
- else
- val &= ~VBOOT_REGISTER_FAILED_RW_PRIMARY;
- vbe_set_vboot_register(VBOOT_REGISTER_PERSIST, val);
- }
- int vba_bdb_init(struct vba_context *ctx)
- {
- /* Get current slot */
- get_current_slot(ctx);
- /* Check current slot failed or not at the last boot */
- if (!did_current_slot_fail(ctx)) {
- /* If not, we try this slot. Prepare for any accidents */
- set_current_slot_failed(ctx);
- return BDB_SUCCESS;
- }
- /* Check other slot failed or not at the previous boot */
- if (!did_other_slot_fail(ctx)) {
- /* If not, we try the other slot after reboot. */
- set_try_other_slot(ctx);
- return BDB_ERROR_TRY_OTHER_SLOT;
- } else {
- /* Otherwise, both slots are bad. Reboot to recovery */
- set_recovery_request(ctx);
- return BDB_ERROR_RECOVERY_REQUEST;
- }
- }
- int vba_bdb_finalize(struct vba_context *ctx)
- {
- /* Mark the current slot good */
- unset_current_slot_failed(ctx);
- /* Disable NVM bus */
- return BDB_SUCCESS;
- }
- void vba_bdb_fail(struct vba_context *ctx)
- {
- /* We can do some logging here if we want */
- /* Unconditionally reboot. FailedRW flag is already set.
- * At the next boot, bdb_init will decide what to do. */
- vbe_reset();
- }
|