blob: ddfc3c8b4e28cb3d0858e37650932219794b7907 [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
#include "sw/device/lib/dif/dif_entropy_src.h"
#include "gtest/gtest.h"
#include "sw/device/lib/base/mmio.h"
#include "sw/device/lib/base/multibits.h"
#include "sw/device/lib/base/testing/mock_mmio.h"
#include "sw/device/lib/dif/dif_base.h"
#include "sw/device/lib/dif/dif_test_base.h"
#include "entropy_src_regs.h" // Generated
namespace dif_entropy_src_unittest {
namespace {
class EntropySrcTest : public testing::Test, public mock_mmio::MmioTest {
protected:
const dif_entropy_src_t entropy_src_ = {.base_addr = dev().region()};
};
class ConfigTest : public EntropySrcTest {
protected:
dif_entropy_src_config_t config_ = {
.fips_enable = false,
.route_to_firmware = false,
.single_bit_mode = kDifEntropySrcSingleBitModeDisabled,
};
};
TEST_F(ConfigTest, NullHandle) {
EXPECT_DIF_BADARG(
dif_entropy_src_configure(nullptr, config_, kDifToggleEnabled));
}
TEST_F(ConfigTest, BadEnabled) {
EXPECT_DIF_BADARG(dif_entropy_src_configure(&entropy_src_, config_,
static_cast<dif_toggle_t>(2)));
}
TEST_F(ConfigTest, BadSingleBitMode) {
config_.single_bit_mode = static_cast<dif_entropy_src_single_bit_mode_t>(5);
EXPECT_DIF_BADARG(
dif_entropy_src_configure(&entropy_src_, config_, kDifToggleEnabled));
}
struct ConfigParams {
bool fips_enable;
bool route_to_firmware;
dif_entropy_src_single_bit_mode_t single_bit_mode;
bool health_test_threshold_scope;
uint16_t health_test_window_size;
dif_toggle_t enabled;
};
class ConfigTestAllParams : public ConfigTest,
public testing::WithParamInterface<ConfigParams> {};
TEST_P(ConfigTestAllParams, ValidConfigurationMode) {
const ConfigParams &test_param = GetParam();
config_.fips_enable = test_param.fips_enable;
config_.route_to_firmware = test_param.route_to_firmware;
config_.single_bit_mode = test_param.single_bit_mode;
config_.health_test_threshold_scope = test_param.health_test_threshold_scope;
config_.health_test_window_size = test_param.health_test_window_size;
multi_bit_bool_t route_to_firmware_mubi =
test_param.route_to_firmware ? kMultiBitBool4True : kMultiBitBool4False;
EXPECT_WRITE32(
ENTROPY_SRC_ENTROPY_CONTROL_REG_OFFSET,
{
{ENTROPY_SRC_ENTROPY_CONTROL_ES_ROUTE_OFFSET, route_to_firmware_mubi},
{ENTROPY_SRC_ENTROPY_CONTROL_ES_TYPE_OFFSET, kMultiBitBool4False},
});
multi_bit_bool_t fips_enable_mubi =
test_param.fips_enable ? kMultiBitBool4True : kMultiBitBool4False;
multi_bit_bool_t threshold_scope_mubi = test_param.health_test_threshold_scope
? kMultiBitBool4True
: kMultiBitBool4False;
multi_bit_bool_t rng_bit_enable_mubi =
test_param.single_bit_mode == kDifEntropySrcSingleBitModeDisabled
? kMultiBitBool4False
: kMultiBitBool4True;
uint8_t rng_bit_sel =
test_param.single_bit_mode == kDifEntropySrcSingleBitModeDisabled
? 0
: test_param.single_bit_mode;
EXPECT_WRITE32(
ENTROPY_SRC_CONF_REG_OFFSET,
{
{ENTROPY_SRC_CONF_FIPS_ENABLE_OFFSET, fips_enable_mubi},
{ENTROPY_SRC_CONF_ENTROPY_DATA_REG_ENABLE_OFFSET,
route_to_firmware_mubi},
{ENTROPY_SRC_CONF_THRESHOLD_SCOPE_OFFSET, threshold_scope_mubi},
{ENTROPY_SRC_CONF_RNG_BIT_ENABLE_OFFSET, rng_bit_enable_mubi},
{ENTROPY_SRC_CONF_RNG_BIT_SEL_OFFSET, rng_bit_sel},
});
EXPECT_WRITE32(ENTROPY_SRC_HEALTH_TEST_WINDOWS_REG_OFFSET,
test_param.health_test_window_size);
EXPECT_WRITE32(ENTROPY_SRC_MODULE_ENABLE_REG_OFFSET,
{
{ENTROPY_SRC_MODULE_ENABLE_MODULE_ENABLE_OFFSET,
dif_toggle_to_multi_bit_bool4(test_param.enabled)},
});
EXPECT_DIF_OK(
dif_entropy_src_configure(&entropy_src_, config_, test_param.enabled));
}
INSTANTIATE_TEST_SUITE_P(
ConfigTestAllParams, ConfigTestAllParams,
testing::Values(
// Test FIPS enabled.
ConfigParams{true, false, kDifEntropySrcSingleBitModeDisabled, false,
0xFFFF, kDifToggleEnabled},
// Test route to firmware.
ConfigParams{false, true, kDifEntropySrcSingleBitModeDisabled, false,
kDifToggleEnabled},
// Test single_bit_mode
ConfigParams{false, false, kDifEntropySrcSingleBitMode0, false, 512,
kDifToggleEnabled},
ConfigParams{false, false, kDifEntropySrcSingleBitMode1, false, 256,
kDifToggleEnabled},
ConfigParams{false, false, kDifEntropySrcSingleBitMode2, false, 128,
kDifToggleEnabled},
ConfigParams{false, false, kDifEntropySrcSingleBitMode3, false, 64,
kDifToggleEnabled},
// Test all disabled.
ConfigParams{false, false, kDifEntropySrcSingleBitMode0, false, 0,
kDifToggleDisabled},
// Test all enabled.
ConfigParams{true, true, kDifEntropySrcSingleBitMode0, true, 32,
kDifToggleEnabled}));
class FwOverrideConfigTest : public EntropySrcTest {
protected:
dif_entropy_src_fw_override_config_t config_ = {
.entropy_insert_enable = true,
.buffer_threshold = ENTROPY_SRC_OBSERVE_FIFO_THRESH_REG_RESVAL,
};
};
TEST_F(FwOverrideConfigTest, NullHandle) {
EXPECT_DIF_BADARG(dif_entropy_src_fw_override_configure(nullptr, config_,
kDifToggleEnabled));
}
TEST_F(FwOverrideConfigTest, BadBufferThreshold) {
config_.buffer_threshold =
ENTROPY_SRC_OBSERVE_FIFO_THRESH_OBSERVE_FIFO_THRESH_MASK + 1;
EXPECT_DIF_BADARG(dif_entropy_src_fw_override_configure(
&entropy_src_, config_, kDifToggleEnabled));
config_.buffer_threshold = 0;
EXPECT_DIF_BADARG(dif_entropy_src_fw_override_configure(
&entropy_src_, config_, kDifToggleEnabled));
}
TEST_F(FwOverrideConfigTest, BadEnabled) {
EXPECT_DIF_BADARG(dif_entropy_src_fw_override_configure(
&entropy_src_, config_, static_cast<dif_toggle_t>(2)));
}
TEST_F(FwOverrideConfigTest, Success) {
EXPECT_WRITE32(ENTROPY_SRC_OBSERVE_FIFO_THRESH_REG_OFFSET,
config_.buffer_threshold);
EXPECT_WRITE32(ENTROPY_SRC_FW_OV_CONTROL_REG_OFFSET, 0x66);
EXPECT_DIF_OK(dif_entropy_src_fw_override_configure(&entropy_src_, config_,
kDifToggleEnabled));
EXPECT_WRITE32(ENTROPY_SRC_OBSERVE_FIFO_THRESH_REG_OFFSET,
config_.buffer_threshold);
EXPECT_WRITE32(ENTROPY_SRC_FW_OV_CONTROL_REG_OFFSET, 0x69);
EXPECT_DIF_OK(dif_entropy_src_fw_override_configure(&entropy_src_, config_,
kDifToggleDisabled));
}
class ReadTest : public EntropySrcTest {};
TEST_F(ReadTest, EntropyBadArg) {
uint32_t word;
EXPECT_DIF_BADARG(dif_entropy_src_read(nullptr, &word));
}
TEST_F(ReadTest, WordBadArg) {
EXPECT_DIF_BADARG(dif_entropy_src_read(&entropy_src_, nullptr));
}
TEST_F(ReadTest, ReadDataUnAvailable) {
EXPECT_READ32(ENTROPY_SRC_INTR_STATE_REG_OFFSET, 0);
uint32_t got_word;
EXPECT_EQ(dif_entropy_src_read(&entropy_src_, &got_word), kDifUnavailable);
}
TEST_F(ReadTest, ReadOk) {
const uint32_t expected_word = 0x65585497;
EXPECT_READ32(ENTROPY_SRC_INTR_STATE_REG_OFFSET,
1 << ENTROPY_SRC_INTR_STATE_ES_ENTROPY_VALID_BIT);
EXPECT_READ32(ENTROPY_SRC_ENTROPY_DATA_REG_OFFSET, expected_word);
EXPECT_READ32(ENTROPY_SRC_INTR_STATE_REG_OFFSET,
1 << ENTROPY_SRC_INTR_STATE_ES_ENTROPY_VALID_BIT);
EXPECT_WRITE32(ENTROPY_SRC_INTR_STATE_REG_OFFSET,
{{ENTROPY_SRC_INTR_STATE_ES_ENTROPY_VALID_BIT, true}});
uint32_t got_word;
EXPECT_DIF_OK(dif_entropy_src_read(&entropy_src_, &got_word));
EXPECT_EQ(got_word, expected_word);
}
} // namespace
} // namespace dif_entropy_src_unittest