blob: 9af0063d8496af62910cdd438169437cfc664945 [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
#ifndef OPENTITAN_SW_DEVICE_SILICON_CREATOR_LIB_ERROR_H_
#define OPENTITAN_SW_DEVICE_SILICON_CREATOR_LIB_ERROR_H_
#include "sw/device/lib/base/bitfield.h"
#include "sw/device/lib/base/hardened.h"
#define USING_INTERNAL_STATUS
#include "sw/device/lib/base/internal/status.h"
#undef USING_INTERNAL_STATUS
#ifdef __cplusplus
extern "C" {
#endif
/**
* List of modules which can produce errors.
*
* Choose a two-letter identifier for each module and encode the module
* identifier the concatenated ASCII representation of those letters.
*/
#define MODULE_CODE(ch0_, ch1_) ((ch0_) << 8 | (ch1_))
enum module_ {
// clang-format off
kModuleUnknown = 0,
kModuleAlertHandler = MODULE_CODE('A', 'H'),
kModuleSigverify = MODULE_CODE('S', 'V'),
kModuleKeymgr = MODULE_CODE('K', 'M'),
kModuleManifest = MODULE_CODE('M', 'A'),
kModuleRom = MODULE_CODE('M', 'R'),
kModuleInterrupt = MODULE_CODE('I', 'R'),
kModuleEpmp = MODULE_CODE('E', 'P'),
kModuleKmac = MODULE_CODE('K', 'C'),
kModuleOtbn = MODULE_CODE('B', 'N'),
kModuleFlashCtrl = MODULE_CODE('F', 'C'),
kModuleBootPolicy = MODULE_CODE('B', 'P'),
kModuleBootstrap = MODULE_CODE('B', 'S'),
kModuleLog = MODULE_CODE('L', 'G'),
kModuleBootData = MODULE_CODE('B', 'D'),
kModuleSpiDevice = MODULE_CODE('S', 'P'),
kModuleAst = MODULE_CODE('A', 'S'),
KModuleRnd = MODULE_CODE('R', 'N'),
// clang-format on
};
/**
* Field definitions for the different fields of the error word.
*/
#define ROM_ERROR_FIELD_ERROR ((bitfield_field32_t){.mask = 0xFF, .index = 24})
#define ROM_ERROR_FIELD_MODULE \
((bitfield_field32_t){.mask = 0xFFFF, .index = 8})
#define ROM_ERROR_FIELD_STATUS ((bitfield_field32_t){.mask = 0xFF, .index = 0})
/**
* Helper macro for building up error codes.
* @param status_ An appropriate general status code from absl_staus.h.
* @param module_ The module identifier which produces this error.
* @param error_ The unique error id in that module. Error ids must not
* repeat within a module.
*/
#define ERROR_(error_, module_, status_) \
((error_ << 24) | (module_ << 8) | (status_))
// clang-format off
// Use an X-macro to facilitate writing unit tests.
// Note: This list is extend-only and you may not renumber errors after they
// have been created. This is required for error-space stability
// after the ROM is frozen.
#define DEFINE_ERRORS(X) \
X(kErrorOk, 0x739), \
X(kErrorUnknown, 0xffffffff), \
\
X(kErrorSigverifyBadEncodedMessage, ERROR_(1, kModuleSigverify, kInvalidArgument)), \
X(kErrorSigverifyBadKey, ERROR_(2, kModuleSigverify, kInvalidArgument)), \
X(kErrorSigverifyBadSignature, ERROR_(3, kModuleSigverify, kInvalidArgument)), \
\
X(kErrorKeymgrInternal, ERROR_(1, kModuleKeymgr, kInternal)), \
\
X(kErrorManifestBadEntryPoint, ERROR_(1, kModuleManifest, kInternal)), \
X(kErrorManifestBadCodeRegion, ERROR_(2, kModuleManifest, kInternal)), \
\
X(kErrorAlertBadIndex, ERROR_(1, kModuleAlertHandler, kInvalidArgument)), \
X(kErrorAlertBadClass, ERROR_(2, kModuleAlertHandler, kInvalidArgument)), \
X(kErrorAlertBadEnable, ERROR_(3, kModuleAlertHandler, kInvalidArgument)), \
X(kErrorAlertBadEscalation, ERROR_(4, kModuleAlertHandler, kInvalidArgument)), \
X(kErrorAlertBadCrc32, ERROR_(5, kModuleAlertHandler, kInvalidArgument)), \
\
X(kErrorRomBootFailed, ERROR_(1, kModuleRom, kFailedPrecondition)), \
\
/* The high-byte of kErrorInterrupt is modified with the interrupt cause */ \
X(kErrorInterrupt, ERROR_(0, kModuleInterrupt, kUnknown)), \
\
X(kErrorEpmpBadCheck, ERROR_(1, kModuleEpmp, kInternal)), \
\
X(kErrorKmacInvalidStatus, ERROR_(1, kModuleKmac, kInternal)), \
\
X(kErrorOtbnInvalidArgument, ERROR_(1, kModuleOtbn, kInvalidArgument)), \
X(kErrorOtbnBadOffsetLen, ERROR_(2, kModuleOtbn, kInvalidArgument)), \
X(kErrorOtbnExecutionFailed, ERROR_(3, kModuleOtbn, kInternal)), \
X(kErrorOtbnSecWipeImemFailed, ERROR_(4, kModuleOtbn, kInternal)), \
X(kErrorOtbnSecWipeDmemFailed, ERROR_(5, kModuleOtbn, kInternal)), \
X(kErrorOtbnBadInsnCount, ERROR_(6, kModuleOtbn, kInternal)), \
X(kErrorOtbnUnavailable, ERROR_(7, kModuleOtbn, kInternal)), \
\
X(kErrorFlashCtrlDataRead, ERROR_(1, kModuleFlashCtrl, kInternal)), \
X(kErrorFlashCtrlInfoRead, ERROR_(2, kModuleFlashCtrl, kInternal)), \
X(kErrorFlashCtrlDataWrite, ERROR_(3, kModuleFlashCtrl, kInternal)), \
X(kErrorFlashCtrlInfoWrite, ERROR_(4, kModuleFlashCtrl, kInternal)), \
X(kErrorFlashCtrlDataErase, ERROR_(5, kModuleFlashCtrl, kInternal)), \
X(kErrorFlashCtrlInfoErase, ERROR_(6, kModuleFlashCtrl, kInternal)), \
X(kErrorFlashCtrlDataEraseVerify, ERROR_(7, kModuleFlashCtrl, kInternal)), \
\
X(kErrorBootPolicyBadIdentifier, ERROR_(1, kModuleBootPolicy, kInternal)), \
X(kErrorBootPolicyBadLength, ERROR_(2, kModuleBootPolicy, kInternal)), \
X(kErrorBootPolicyRollback, ERROR_(3, kModuleBootPolicy, kInternal)), \
\
X(kErrorBootstrapEraseAddress, ERROR_(1, kModuleBootstrap, kInvalidArgument)), \
X(kErrorBootstrapProgramAddress, ERROR_(2, kModuleBootstrap, kInvalidArgument)), \
X(kErrorBootstrapInvalidState, ERROR_(3, kModuleBootstrap, kInvalidArgument)), \
X(kErrorBootstrapNotRequested, ERROR_(4, kModuleBootstrap, kInternal)), \
\
X(kErrorLogBadFormatSpecifier, ERROR_(1, kModuleLog, kInternal)), \
\
X(kErrorBootDataNotFound, ERROR_(1, kModuleBootData, kInternal)), \
X(kErrorBootDataWriteCheck, ERROR_(2, kModuleBootData, kInternal)), \
X(kErrorBootDataInvalid, ERROR_(3, kModuleBootData, kInternal)), \
\
X(kErrorSpiDevicePayloadOverflow, ERROR_(1, kModuleSpiDevice, kInternal)), \
\
X(kErrorAstInitNotDone, ERROR_(1, kModuleAst, kInternal)), \
\
X(kErrorRndBadCrc32, ERROR_(1, KModuleRnd, kInvalidArgument))
// clang-format on
#define ERROR_ENUM_INIT(name_, value_) name_ = value_
/**
* Unified set of errors for ROM and ROM_EXT.
*/
typedef enum rom_error {
DEFINE_ERRORS(ERROR_ENUM_INIT),
} rom_error_t;
/**
* Evaluate an expression and return if the result is an error.
*
* @param expr_ An expression which results in a `rom_error_t`.
*/
#define RETURN_IF_ERROR(expr_) \
do { \
rom_error_t local_error_ = expr_; \
if (local_error_ != kErrorOk) { \
return local_error_; \
} \
} while (false)
/**
* Hardened version of `RETURN_IF_ERROR()`.
*
* See `launder32()` and `HARDENED_CHECK_EQ()` in
* `sw/device/lib/base/hardened.h` for more details.
*
* @param expr_ An expression which results in a `rom_error_t`.
*/
#define HARDENED_RETURN_IF_ERROR(expr_) \
do { \
rom_error_t error_ = expr_; \
if (launder32(error_) != kErrorOk) { \
return error_; \
} \
HARDENED_CHECK_EQ(error_, kErrorOk); \
} while (false)
#ifdef __cplusplus
}
#endif
#endif // OPENTITAN_SW_DEVICE_SILICON_CREATOR_LIB_ERROR_H_