<commit_before>// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

#include "sw/device/silicon_creator/lib/drivers/ast.h"

#include "sw/device/lib/base/abs_mmio.h"
#include "sw/device/lib/base/multibits.h"
#include "sw/device/silicon_creator/lib/drivers/otp.h"

#include "hw/top_earlgrey/sw/autogen/top_earlgrey.h"
#include "otp_ctrl_regs.h"     // Generated.
#include "sensor_ctrl_regs.h"  // Generated.

enum {
  kSensorCtrlBase = TOP_EARLGREY_SENSOR_CTRL_BASE_ADDR,
};

rom_error_t ast_check(lifecycle_state_t lc_state) {
  // OTP can be configured to skip AST initialization. In this situation we do
  // not check that AST_INIT_DONE is set.
  uint32_t en = otp_read32(OTP_CTRL_PARAM_CREATOR_SW_CFG_AST_INIT_EN_OFFSET);
  if (launder32(en) == kMultiBitBool4False) {
    HARDENED_CHECK_EQ(en, kMultiBitBool4False);
    return kErrorOk;
  }

  // In some lifecycle states we want to continue the boot process even if the
  // AST is not initialized. Note that in these states OTP may not have been
  // configured.
  switch (launder32(lc_state)) {
    case kLcStateTest:
      HARDENED_CHECK_EQ(lc_state, kLcStateTest);
      return kErrorOk;
    case kLcStateRma:
      HARDENED_CHECK_EQ(lc_state, kLcStateRma);
      return kErrorOk;
    case kLcStateDev:
      HARDENED_CHECK_EQ(lc_state, kLcStateDev);
      break;
    case kLcStateProd:
      HARDENED_CHECK_EQ(lc_state, kLcStateProd);
      break;
    case kLcStateProdEnd:
      HARDENED_CHECK_EQ(lc_state, kLcStateProdEnd);
      break;
    default:
      HARDENED_UNREACHABLE();
  }

  // AST initialization may take up to 100us. It is most likely already complete
  // at this point but for resilience poll for up to 100us.
  // TODO: tune this timeout or use mcycle.
  for (int i = 0; i < 10000; ++i) {
    if (ast_init_done() == kHardenedBoolTrue) {
      HARDENED_CHECK_EQ(ast_init_done(), kHardenedBoolTrue);
      return kErrorOk;
    }
  }

  return kErrorAstInitNotDone;
}

hardened_bool_t ast_init_done(void) {
  uint32_t status =
      abs_mmio_read32(kSensorCtrlBase + SENSOR_CTRL_STATUS_REG_OFFSET);
  if (!bitfield_bit32_read(status, SENSOR_CTRL_STATUS_AST_INIT_DONE_BIT)) {
    return kHardenedBoolFalse;
  }
  return kHardenedBoolTrue;
}
<commit_msg>[sw/silicon_creator] Read OTP after life cycle state check in ast_check()<commit_after>// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

#include "sw/device/silicon_creator/lib/drivers/ast.h"

#include "sw/device/lib/base/abs_mmio.h"
#include "sw/device/lib/base/multibits.h"
#include "sw/device/silicon_creator/lib/drivers/otp.h"

#include "hw/top_earlgrey/sw/autogen/top_earlgrey.h"
#include "otp_ctrl_regs.h"     // Generated.
#include "sensor_ctrl_regs.h"  // Generated.

enum {
  kSensorCtrlBase = TOP_EARLGREY_SENSOR_CTRL_BASE_ADDR,
};

rom_error_t ast_check(lifecycle_state_t lc_state) {
  // In some lifecycle states we want to continue the boot process even if the
  // AST is not initialized. Note that in these states OTP may not have been
  // configured.
  switch (launder32(lc_state)) {
    case kLcStateTest:
      HARDENED_CHECK_EQ(lc_state, kLcStateTest);
      return kErrorOk;
    case kLcStateRma:
      HARDENED_CHECK_EQ(lc_state, kLcStateRma);
      return kErrorOk;
    case kLcStateDev:
      HARDENED_CHECK_EQ(lc_state, kLcStateDev);
      break;
    case kLcStateProd:
      HARDENED_CHECK_EQ(lc_state, kLcStateProd);
      break;
    case kLcStateProdEnd:
      HARDENED_CHECK_EQ(lc_state, kLcStateProdEnd);
      break;
    default:
      HARDENED_UNREACHABLE();
  }

  // OTP can be configured to skip AST initialization. In this situation we do
  // not check that AST_INIT_DONE is set.
  uint32_t en = otp_read32(OTP_CTRL_PARAM_CREATOR_SW_CFG_AST_INIT_EN_OFFSET);
  if (launder32(en) == kMultiBitBool4False) {
    HARDENED_CHECK_EQ(en, kMultiBitBool4False);
    return kErrorOk;
  }

  // AST initialization may take up to 100us. It is most likely already complete
  // at this point but for resilience poll for up to 100us.
  // TODO: tune this timeout or use mcycle.
  for (int i = 0; i < 10000; ++i) {
    if (ast_init_done() == kHardenedBoolTrue) {
      HARDENED_CHECK_EQ(ast_init_done(), kHardenedBoolTrue);
      return kErrorOk;
    }
  }

  return kErrorAstInitNotDone;
}

hardened_bool_t ast_init_done(void) {
  uint32_t status =
      abs_mmio_read32(kSensorCtrlBase + SENSOR_CTRL_STATUS_REG_OFFSET);
  if (!bitfield_bit32_read(status, SENSOR_CTRL_STATUS_AST_INIT_DONE_BIT)) {
    return kHardenedBoolFalse;
  }
  return kHardenedBoolTrue;
}

{'fraction_non_alphanumeric': 0.09023354564755838, 'fraction_numerical': 0.013588110403397028, 'mean_word_length': 3.8617131062951495, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1074153', 'n_tokens_mistral': 1818, 'n_tokens_neox': 1744, 'n_words': 385}