[PATCH 11/11] ASoC: cs-amp-lib-test: Add test cases for cs_amp_set_efi_calibration_data()

Richard Fitzgerald
2025-10-16T10:42:59Z

Add a set of test cases for cs_amp_set_efi_calibration_data().

Broadly there are two type of behavior being tested:

How the EFI is updated:
- Create a new EFI
- Overwrite part of existing content
- Overwrite part of zero-filled preallocated content
- Grow the file to append new content

And how the location within the content is chosen:
- Overwrite a specific array entry
- Overwrite an entry with the same calTarget (silicon ID)
- Overwrite a free entry
- Append after existing data

Plus some cases for error conditions.

Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com>
---
include/sound/cs-amp-lib.h | 5 +
sound/soc/codecs/cs-amp-lib-test.c | 1399 +++++++++++++++++++++++++++-
sound/soc/codecs/cs-amp-lib.c | 1 +
3 files changed, 1397 insertions(+), 8 deletions(-)

diff --git a/include/sound/cs-amp-lib.h b/include/sound/cs-amp-lib.h
index 4c8b84ee087e..8eee4ce9eefe 100644
--- a/include/sound/cs-amp-lib.h
+++ b/include/sound/cs-amp-lib.h
@@ -70,6 +70,11 @@ struct cs_amp_test_hooks {
u32 *returned_attr,
unsigned long *size,
void *buf);
+ efi_status_t (*set_efi_variable)(efi_char16_t *name,
+ efi_guid_t *guid,
+ u32 attr,
+ unsigned long size,
+ void *buf);

int (*write_cal_coeff)(struct cs_dsp *dsp,
const struct cirrus_amp_cal_controls *controls,
diff --git a/sound/soc/codecs/cs-amp-lib-test.c b/sound/soc/codecs/cs-amp-lib-test.c
index d3419f48297e..7fa6aabc746a 100644
--- a/sound/soc/codecs/cs-amp-lib-test.c
+++ b/sound/soc/codecs/cs-amp-lib-test.c
@@ -20,6 +20,10 @@
#include <linux/random.h>
#include <sound/cs-amp-lib.h>

+#define CIRRUS_LOGIC_CALIBRATION_EFI_NAME L"CirrusSmartAmpCalibrationData"
+#define CIRRUS_LOGIC_CALIBRATION_EFI_GUID \
+ EFI_GUID(0x02f9af02, 0x7734, 0x4233, 0xb4, 0x3d, 0x93, 0xfe, 0x5a, 0xa3, 0x5d, 0xb3)
+
#define LENOVO_SPEAKER_ID_EFI_NAME L"SdwSpeaker"
#define LENOVO_SPEAKER_ID_EFI_GUID \
EFI_GUID(0x48df970e, 0xe27f, 0x460a, 0xb5, 0x86, 0x77, 0x19, 0x80, 0x1d, 0x92, 0x82)
@@ -28,6 +32,10 @@
#define HP_SPEAKER_ID_EFI_GUID \
EFI_GUID(0xc49593a4, 0xd099, 0x419b, 0xa2, 0xc3, 0x67, 0xe9, 0x80, 0xe6, 0x1d, 0x1e)

+#define HP_CALIBRATION_EFI_NAME L"SmartAmpCalibrationData"
+#define HP_CALIBRATION_EFI_GUID \
+ EFI_GUID(0x53559579, 0x8753, 0x4f5c, 0x91, 0x30, 0xe8, 0x2a, 0xcf, 0xb8, 0xd8, 0x93)
+
KUNIT_DEFINE_ACTION_WRAPPER(faux_device_destroy_wrapper, faux_device_destroy,
struct faux_device *)

@@ -36,6 +44,7 @@ struct cs_amp_lib_test_priv {

struct cirrus_amp_efi_data *cal_blob;
struct list_head ctl_write_list;
+ u32 efi_attr;
};

struct cs_amp_lib_test_ctl_write_entry {
@@ -49,6 +58,20 @@ struct cs_amp_lib_test_param {
int amp_index;
};

+static struct cirrus_amp_efi_data *cs_amp_lib_test_cal_blob_dup(struct kunit *test)
+{
+ struct cs_amp_lib_test_priv *priv = test->priv;
+ struct cirrus_amp_efi_data *temp;
+
+ KUNIT_ASSERT_EQ(test, struct_size(priv->cal_blob, data, priv->cal_blob->count),
+ priv->cal_blob->size);
+ temp = kunit_kmalloc(test, priv->cal_blob->size, GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, temp);
+ memcpy(temp, priv->cal_blob, priv->cal_blob->size);
+
+ return temp;
+}
+
static void cs_amp_lib_test_init_dummy_cal_blob(struct kunit *test, int num_amps)
{
struct cs_amp_lib_test_priv *priv = test->priv;
@@ -69,9 +92,15 @@ static void cs_amp_lib_test_init_dummy_cal_blob(struct kunit *test, int num_amps
for (i = 0; i < num_amps; i++)
priv->cal_blob->data[i].calTime[0] |= 1;

- /* Ensure that all UIDs are non-zero and unique. */
- for (i = 0; i < num_amps; i++)
+ /*
+ * Ensure that all UIDs are non-zero and unique.
+ * Make both words non-zero and not equal values, so that
+ * tests can verify that both words were checked or changed.
+ */
+ for (i = 0; i < num_amps; i++) {
*(u8 *)&priv->cal_blob->data[i].calTarget[0] = i + 1;
+ *(u8 *)&priv->cal_blob->data[i].calTarget[1] = i;
+ }
}

static u64 cs_amp_lib_test_get_target_uid(struct kunit *test)
@@ -199,9 +228,8 @@ static efi_status_t cs_amp_lib_test_get_efi_variable(efi_char16_t *name,
unsigned long *size,
void *buf)
{
- static const efi_char16_t expected_name[] = L"CirrusSmartAmpCalibrationData";
- static const efi_guid_t expected_guid =
- EFI_GUID(0x02f9af02, 0x7734, 0x4233, 0xb4, 0x3d, 0x93, 0xfe, 0x5a, 0xa3, 0x5d, 0xb3);
+ static const efi_char16_t expected_name[] = CIRRUS_LOGIC_CALIBRATION_EFI_NAME;
+ static const efi_guid_t expected_guid = CIRRUS_LOGIC_CALIBRATION_EFI_GUID;
struct kunit *test = kunit_get_current_test();
struct cs_amp_lib_test_priv *priv = test->priv;

@@ -223,9 +251,56 @@ static efi_status_t cs_amp_lib_test_get_efi_variable(efi_char16_t *name,
memcpy(buf, priv->cal_blob, priv->cal_blob->size);

if (returned_attr) {
- *returned_attr = EFI_VARIABLE_NON_VOLATILE |
- EFI_VARIABLE_BOOTSERVICE_ACCESS |
- EFI_VARIABLE_RUNTIME_ACCESS;
+ if (priv->efi_attr)
+ *returned_attr = priv->efi_attr;
+ else
+ *returned_attr = EFI_VARIABLE_NON_VOLATILE |
+ EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_RUNTIME_ACCESS;
+ }
+
+ return EFI_SUCCESS;
+}
+
+#define CS_AMP_LIB_ZERO_FILLED_BLOB_SIZE \
+ struct_size_t(struct cirrus_amp_efi_data, data, 8)
+
+/* Redirected get_efi_variable to simulate reading a prealloced zero-filled blob */
+static efi_status_t cs_amp_lib_test_get_efi_variable_all_zeros(efi_char16_t *name,
+ efi_guid_t *guid,
+ u32 *returned_attr,
+ unsigned long *size,
+ void *buf)
+{
+ static const efi_char16_t expected_name[] = CIRRUS_LOGIC_CALIBRATION_EFI_NAME;
+ static const efi_guid_t expected_guid = CIRRUS_LOGIC_CALIBRATION_EFI_GUID;
+ struct kunit *test = kunit_get_current_test();
+ struct cs_amp_lib_test_priv *priv = test->priv;
+
+ KUNIT_EXPECT_NOT_ERR_OR_NULL(test, name);
+ KUNIT_EXPECT_NOT_ERR_OR_NULL(test, guid);
+
+ if (memcmp(name, expected_name, sizeof(expected_name)) ||
+ efi_guidcmp(*guid, expected_guid))
+ return -EFI_NOT_FOUND;
+
+ if (!buf) {
+ *size = CS_AMP_LIB_ZERO_FILLED_BLOB_SIZE;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ KUNIT_ASSERT_EQ(test, *size, struct_size(priv->cal_blob, data, 8));
+ priv->cal_blob = kunit_kzalloc(test, CS_AMP_LIB_ZERO_FILLED_BLOB_SIZE, GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, priv->cal_blob);
+ memset(buf, 0, CS_AMP_LIB_ZERO_FILLED_BLOB_SIZE);
+
+ if (returned_attr) {
+ if (priv->efi_attr)
+ *returned_attr = priv->efi_attr;
+ else
+ *returned_attr = EFI_VARIABLE_NON_VOLATILE |
+ EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_RUNTIME_ACCESS;
}

return EFI_SUCCESS;
@@ -790,6 +865,1292 @@ static void cs_amp_lib_test_write_ambient_test(struct kunit *test)
KUNIT_EXPECT_EQ(test, entry->value, 18);
}

+static efi_status_t cs_amp_lib_test_set_efi_variable(efi_char16_t *name,
+ efi_guid_t *guid,
+ u32 attr,
+ unsigned long size,
+ void *buf)
+{
+ static const efi_char16_t expected_name[] = CIRRUS_LOGIC_CALIBRATION_EFI_NAME;
+ static const efi_guid_t expected_guid = CIRRUS_LOGIC_CALIBRATION_EFI_GUID;
+ struct kunit *test = kunit_get_current_test();
+ struct cs_amp_lib_test_priv *priv = test->priv;
+
+ KUNIT_ASSERT_NOT_NULL(test, name);
+ KUNIT_ASSERT_NOT_NULL(test, guid);
+
+ if (memcmp(name, expected_name, sizeof(expected_name)) ||
+ efi_guidcmp(*guid, expected_guid))
+ return -EFI_NOT_FOUND;
+
+ KUNIT_ASSERT_NOT_NULL(test, buf);
+ KUNIT_ASSERT_NE(test, 0, size);
+
+ kunit_kfree(test, priv->cal_blob);
+ priv->cal_blob = kunit_kmalloc(test, size, GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, priv->cal_blob);
+ memcpy(priv->cal_blob, buf, size);
+ priv->efi_attr = attr;
+
+ return EFI_SUCCESS;
+}
+
+static efi_status_t cs_amp_lib_test_set_efi_variable_denied(efi_char16_t *name,
+ efi_guid_t *guid,
+ u32 attr,
+ unsigned long size,
+ void *buf)
+{
+ return EFI_WRITE_PROTECTED;
+}
+
+#define CS_AMP_CAL_DEFAULT_EFI_ATTR \
+ (EFI_VARIABLE_NON_VOLATILE | \
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | \
+ EFI_VARIABLE_RUNTIME_ACCESS)
+
+static void cs_amp_lib_test_create_new_cal_efi(struct kunit *test)
+{
+ struct cs_amp_lib_test_priv *priv = test->priv;
+ struct device *dev = &priv->amp_dev->dev;
+ struct cirrus_amp_cal_data data;
+ int i;
+
+ kunit_activate_static_stub(test,
+ cs_amp_test_hooks->get_efi_variable,
+ cs_amp_lib_test_get_efi_variable_none);
+ kunit_activate_static_stub(test,
+ cs_amp_test_hooks->set_efi_variable,
+ cs_amp_lib_test_set_efi_variable);
+
+ /* For unspecified number of amps */
+ get_random_bytes(&data, sizeof(data));
+ KUNIT_EXPECT_EQ(test, 0, cs_amp_set_efi_calibration_data(dev, -1, -1, &data));
+ KUNIT_EXPECT_EQ(test, CS_AMP_CAL_DEFAULT_EFI_ATTR, priv->efi_attr);
+ KUNIT_EXPECT_GE(test, priv->cal_blob->count, 1);
+ KUNIT_EXPECT_LE(test, priv->cal_blob->count, 8);
+ KUNIT_EXPECT_EQ(test, struct_size(priv->cal_blob, data, priv->cal_blob->count),
+ priv->cal_blob->size);
+ KUNIT_EXPECT_MEMEQ(test, &data, &priv->cal_blob->data[0], sizeof(data));
+ for (i = 1; i < priv->cal_blob->count; i++)
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[i], sizeof(data)));
+
+ /* For 2 amps */
+ priv->cal_blob = NULL;
+ get_random_bytes(&data, sizeof(data));
+ KUNIT_EXPECT_EQ(test, 0, cs_amp_set_efi_calibration_data(dev, -1, 2, &data));
+ KUNIT_EXPECT_EQ(test, CS_AMP_CAL_DEFAULT_EFI_ATTR, priv->efi_attr);
+ KUNIT_EXPECT_EQ(test, 2, priv->cal_blob->count);
+ KUNIT_EXPECT_EQ(test, struct_size(priv->cal_blob, data, 2), priv->cal_blob->size);
+ KUNIT_EXPECT_MEMEQ(test, &data, &priv->cal_blob->data[0], sizeof(data));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[1], sizeof(data)));
+
+ /* For 4 amps */
+ priv->cal_blob = NULL;
+ get_random_bytes(&data, sizeof(data));
+ KUNIT_EXPECT_EQ(test, 0, cs_amp_set_efi_calibration_data(dev, -1, 4, &data));
+ KUNIT_EXPECT_EQ(test, 4, priv->cal_blob->count);
+ KUNIT_EXPECT_EQ(test, struct_size(priv->cal_blob, data, 4), priv->cal_blob->size);
+ KUNIT_EXPECT_MEMEQ(test, &data, &priv->cal_blob->data[0], sizeof(data));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[1], sizeof(data)));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[2], sizeof(data)));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[3], sizeof(data)));
+
+ /* For 6 amps */
+ priv->cal_blob = NULL;
+ get_random_bytes(&data, sizeof(data));
+ KUNIT_EXPECT_EQ(test, 0, cs_amp_set_efi_calibration_data(dev, -1, 6, &data));
+ KUNIT_EXPECT_EQ(test, 6, priv->cal_blob->count);
+ KUNIT_EXPECT_EQ(test, struct_size(priv->cal_blob, data, 6), priv->cal_blob->size);
+ KUNIT_EXPECT_MEMEQ(test, &data, &priv->cal_blob->data[0], sizeof(data));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[1], sizeof(data)));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[2], sizeof(data)));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[3], sizeof(data)));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[4], sizeof(data)));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[5], sizeof(data)));
+}
+
+static void cs_amp_lib_test_create_new_cal_efi_indexed(struct kunit *test)
+{
+ struct cs_amp_lib_test_priv *priv = test->priv;
+ struct device *dev = &priv->amp_dev->dev;
+ struct cirrus_amp_cal_data data;
+
+ kunit_activate_static_stub(test,
+ cs_amp_test_hooks->get_efi_variable,
+ cs_amp_lib_test_get_efi_variable_none);
+ kunit_activate_static_stub(test,
+ cs_amp_test_hooks->set_efi_variable,
+ cs_amp_lib_test_set_efi_variable);
+
+ /* In slot 0 */
+ priv->cal_blob = NULL;
+ get_random_bytes(&data, sizeof(data));
+ KUNIT_EXPECT_EQ(test, 0, cs_amp_set_efi_calibration_data(dev, 0, 6, &data));
+ KUNIT_EXPECT_EQ(test, 6, priv->cal_blob->count);
+ KUNIT_EXPECT_EQ(test, struct_size(priv->cal_blob, data, 6), priv->cal_blob->size);
+ KUNIT_EXPECT_MEMEQ(test, &data, &priv->cal_blob->data[0], sizeof(data));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[1], sizeof(data)));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[2], sizeof(data)));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[3], sizeof(data)));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[4], sizeof(data)));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[5], sizeof(data)));
+
+ /* In slot 1 */
+ priv->cal_blob = NULL;
+ get_random_bytes(&data, sizeof(data));
+ KUNIT_EXPECT_EQ(test, 0, cs_amp_set_efi_calibration_data(dev, 1, 6, &data));
+ KUNIT_EXPECT_EQ(test, 6, priv->cal_blob->count);
+ KUNIT_EXPECT_EQ(test, struct_size(priv->cal_blob, data, 6), priv->cal_blob->size);
+ KUNIT_EXPECT_MEMEQ(test, &data, &priv->cal_blob->data[1], sizeof(data));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[0], sizeof(data)));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[2], sizeof(data)));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[3], sizeof(data)));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[4], sizeof(data)));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[5], sizeof(data)));
+
+ /* In slot 5 */
+ priv->cal_blob = NULL;
+ get_random_bytes(&data, sizeof(data));
+ KUNIT_EXPECT_EQ(test, 0, cs_amp_set_efi_calibration_data(dev, 5, 6, &data));
+ KUNIT_EXPECT_EQ(test, 6, priv->cal_blob->count);
+ KUNIT_EXPECT_EQ(test, struct_size(priv->cal_blob, data, 6), priv->cal_blob->size);
+ KUNIT_EXPECT_MEMEQ(test, &data, &priv->cal_blob->data[5], sizeof(data));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[0], sizeof(data)));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[1], sizeof(data)));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[2], sizeof(data)));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[3], sizeof(data)));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[4], sizeof(data)));
+}
+
+static void cs_amp_lib_test_create_new_cal_efi_indexed_no_max(struct kunit *test)
+{
+ struct cs_amp_lib_test_priv *priv = test->priv;
+ struct device *dev = &priv->amp_dev->dev;
+ struct cirrus_amp_cal_data data;
+ int i;
+
+ kunit_activate_static_stub(test,
+ cs_amp_test_hooks->get_efi_variable,
+ cs_amp_lib_test_get_efi_variable_none);
+ kunit_activate_static_stub(test,
+ cs_amp_test_hooks->set_efi_variable,
+ cs_amp_lib_test_set_efi_variable);
+
+ /* In slot 0 with unspecified number of amps */
+ priv->cal_blob = NULL;
+ get_random_bytes(&data, sizeof(data));
+ KUNIT_EXPECT_EQ(test, 0, cs_amp_set_efi_calibration_data(dev, 0, -1, &data));
+ KUNIT_EXPECT_GE(test, priv->cal_blob->count, 1);
+ KUNIT_EXPECT_LE(test, priv->cal_blob->count, 8);
+ KUNIT_EXPECT_EQ(test, struct_size(priv->cal_blob, data, priv->cal_blob->count),
+ priv->cal_blob->size);
+ KUNIT_EXPECT_MEMEQ(test, &data, &priv->cal_blob->data[0], sizeof(data));
+ for (i = 1; i < priv->cal_blob->count; i++)
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[i], sizeof(data)));
+
+ /* In slot 1 with unspecified number of amps */
+ priv->cal_blob = NULL;
+ get_random_bytes(&data, sizeof(data));
+ KUNIT_EXPECT_EQ(test, 0, cs_amp_set_efi_calibration_data(dev, 1, -1, &data));
+ KUNIT_EXPECT_GE(test, priv->cal_blob->count, 2);
+ KUNIT_EXPECT_LE(test, priv->cal_blob->count, 8);
+ KUNIT_EXPECT_EQ(test, struct_size(priv->cal_blob, data, priv->cal_blob->count),
+ priv->cal_blob->size);
+ KUNIT_EXPECT_MEMEQ(test, &data, &priv->cal_blob->data[1], sizeof(data));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[0], sizeof(data)));
+ for (i = 2; i < priv->cal_blob->count; i++)
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[i], sizeof(data)));
+
+ /* In slot 5 with unspecified number of amps */
+ priv->cal_blob = NULL;
+ get_random_bytes(&data, sizeof(data));
+ KUNIT_EXPECT_EQ(test, 0, cs_amp_set_efi_calibration_data(dev, 5, -1, &data));
+ KUNIT_EXPECT_GE(test, priv->cal_blob->count, 6);
+ KUNIT_EXPECT_LE(test, priv->cal_blob->count, 8);
+ KUNIT_EXPECT_EQ(test, struct_size(priv->cal_blob, data, priv->cal_blob->count),
+ priv->cal_blob->size);
+ for (i = 0; (i < 5) && (i < priv->cal_blob->count); i++)
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[i], sizeof(data)));
+
+ KUNIT_EXPECT_MEMEQ(test, &data, &priv->cal_blob->data[5], sizeof(data));
+ for (i = 6; i < priv->cal_blob->count; i++)
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[i], sizeof(data)));
+}
+
+static void cs_amp_lib_test_grow_append_cal_efi(struct kunit *test)
+{
+ struct cs_amp_lib_test_priv *priv = test->priv;
+ struct device *dev = &priv->amp_dev->dev;
+ const struct cirrus_amp_efi_data *original_blob;
+ struct cirrus_amp_cal_data data;
+
+ kunit_activate_static_stub(test,
+ cs_amp_test_hooks->get_efi_variable,
+ cs_amp_lib_test_get_efi_variable);
+ kunit_activate_static_stub(test,
+ cs_amp_test_hooks->set_efi_variable,
+ cs_amp_lib_test_set_efi_variable);
+
+ /* Initially 1 used entry grown to 2 entries */
+ cs_amp_lib_test_init_dummy_cal_blob(test, 1);
+ KUNIT_ASSERT_EQ(test, 1, priv->cal_blob->count);
+ original_blob = cs_amp_lib_test_cal_blob_dup(test);
+ get_random_bytes(&data, sizeof(data));
+ data.calTarget[0] = 0xaaaaaaaa; /* won't match */
+ KUNIT_EXPECT_EQ(test, 0, cs_amp_set_efi_calibration_data(dev, -1, 2, &data));
+ KUNIT_EXPECT_EQ(test, CS_AMP_CAL_DEFAULT_EFI_ATTR, priv->efi_attr);
+ KUNIT_EXPECT_EQ(test, 2, priv->cal_blob->count);
+ KUNIT_EXPECT_EQ(test, struct_size(priv->cal_blob, data, 2), priv->cal_blob->size);
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[0], &priv->cal_blob->data[0], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &data, &priv->cal_blob->data[1], sizeof(data));
+
+ /* Initially 1 entry grown to 4 entries */
+ priv->cal_blob = NULL;
+ cs_amp_lib_test_init_dummy_cal_blob(test, 1);
+ KUNIT_ASSERT_EQ(test, 1, priv->cal_blob->count);
+ original_blob = cs_amp_lib_test_cal_blob_dup(test);
+ get_random_bytes(&data, sizeof(data));
+ data.calTarget[0] = 0xaaaaaaaa; /* won't match */
+ KUNIT_EXPECT_EQ(test, 0, cs_amp_set_efi_calibration_data(dev, -1, 4, &data));
+ KUNIT_EXPECT_EQ(test, 4, priv->cal_blob->count);
+ KUNIT_EXPECT_EQ(test, struct_size(priv->cal_blob, data, 4), priv->cal_blob->size);
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[0], &priv->cal_blob->data[0], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &data, &priv->cal_blob->data[1], sizeof(data));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[2], sizeof(data)));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[3], sizeof(data)));
+
+ /* Initially 2 entries grown to 4 entries */
+ priv->cal_blob = NULL;
+ cs_amp_lib_test_init_dummy_cal_blob(test, 2);
+ KUNIT_ASSERT_EQ(test, 2, priv->cal_blob->count);
+ original_blob = cs_amp_lib_test_cal_blob_dup(test);
+ get_random_bytes(&data, sizeof(data));
+ data.calTarget[0] = 0xaaaaaaaa; /* won't match */
+ KUNIT_EXPECT_EQ(test, 0, cs_amp_set_efi_calibration_data(dev, -1, 4, &data));
+ KUNIT_EXPECT_EQ(test, 4, priv->cal_blob->count);
+ KUNIT_EXPECT_EQ(test, struct_size(priv->cal_blob, data, 4), priv->cal_blob->size);
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[0], &priv->cal_blob->data[0], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[1], &priv->cal_blob->data[1], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &data, &priv->cal_blob->data[2], sizeof(data));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[3], sizeof(data)));
+
+ /* Initially 1 entry grown to 6 entries */
+ priv->cal_blob = NULL;
+ cs_amp_lib_test_init_dummy_cal_blob(test, 1);
+ KUNIT_ASSERT_EQ(test, 1, priv->cal_blob->count);
+ original_blob = cs_amp_lib_test_cal_blob_dup(test);
+ get_random_bytes(&data, sizeof(data));
+ data.calTarget[0] = 0xaaaaaaaa; /* won't match */
+ KUNIT_EXPECT_EQ(test, 0, cs_amp_set_efi_calibration_data(dev, -1, 6, &data));
+ KUNIT_EXPECT_EQ(test, 6, priv->cal_blob->count);
+ KUNIT_EXPECT_EQ(test, struct_size(priv->cal_blob, data, 6), priv->cal_blob->size);
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[0], &priv->cal_blob->data[0], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &data, &priv->cal_blob->data[1], sizeof(data));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[2], sizeof(data)));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[3], sizeof(data)));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[4], sizeof(data)));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[5], sizeof(data)));
+
+ /* Initially 4 entries grown to 6 entries */
+ priv->cal_blob = NULL;
+ cs_amp_lib_test_init_dummy_cal_blob(test, 4);
+ KUNIT_ASSERT_EQ(test, 4, priv->cal_blob->count);
+ original_blob = cs_amp_lib_test_cal_blob_dup(test);
+ get_random_bytes(&data, sizeof(data));
+ data.calTarget[0] = 0xaaaaaaaa; /* won't match */
+ KUNIT_EXPECT_EQ(test, 0, cs_amp_set_efi_calibration_data(dev, -1, 6, &data));
+ KUNIT_EXPECT_EQ(test, 6, priv->cal_blob->count);
+ KUNIT_EXPECT_EQ(test, struct_size(priv->cal_blob, data, 6), priv->cal_blob->size);
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[0], &priv->cal_blob->data[0], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[1], &priv->cal_blob->data[1], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[2], &priv->cal_blob->data[2], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[3], &priv->cal_blob->data[3], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &data, &priv->cal_blob->data[4], sizeof(data));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[5], sizeof(data)));
+}
+
+static void cs_amp_lib_test_grow_append_cal_efi_indexed(struct kunit *test)
+{
+ struct cs_amp_lib_test_priv *priv = test->priv;
+ struct device *dev = &priv->amp_dev->dev;
+ const struct cirrus_amp_efi_data *original_blob;
+ struct cirrus_amp_cal_data data;
+
+ kunit_activate_static_stub(test,
+ cs_amp_test_hooks->get_efi_variable,
+ cs_amp_lib_test_get_efi_variable);
+ kunit_activate_static_stub(test,
+ cs_amp_test_hooks->set_efi_variable,
+ cs_amp_lib_test_set_efi_variable);
+
+ /* Initially 1 entry grown to 2 entries using slot 1 */
+ priv->cal_blob = NULL;
+ cs_amp_lib_test_init_dummy_cal_blob(test, 1);
+ KUNIT_ASSERT_EQ(test, 1, priv->cal_blob->count);
+ original_blob = cs_amp_lib_test_cal_blob_dup(test);
+ get_random_bytes(&data, sizeof(data));
+ data.calTarget[0] = 0xaaaaaaaa; /* won't match */
+ KUNIT_EXPECT_EQ(test, 0, cs_amp_set_efi_calibration_data(dev, 1, 2, &data));
+ KUNIT_EXPECT_EQ(test, 2, priv->cal_blob->count);
+ KUNIT_EXPECT_EQ(test, struct_size(priv->cal_blob, data, 2), priv->cal_blob->size);
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[0], &priv->cal_blob->data[0], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &data, &priv->cal_blob->data[1], sizeof(data));
+
+ /* Initially 1 entry grown to 6 entries using slot 1 */
+ priv->cal_blob = NULL;
+ cs_amp_lib_test_init_dummy_cal_blob(test, 1);
+ KUNIT_ASSERT_EQ(test, 1, priv->cal_blob->count);
+ original_blob = cs_amp_lib_test_cal_blob_dup(test);
+ get_random_bytes(&data, sizeof(data));
+ data.calTarget[0] = 0xaaaaaaaa; /* won't match */
+ KUNIT_EXPECT_EQ(test, 0, cs_amp_set_efi_calibration_data(dev, 1, 6, &data));
+ KUNIT_EXPECT_EQ(test, 6, priv->cal_blob->count);
+ KUNIT_EXPECT_EQ(test, struct_size(priv->cal_blob, data, 6), priv->cal_blob->size);
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[0], &priv->cal_blob->data[0], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &data, &priv->cal_blob->data[1], sizeof(data));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[2], sizeof(data)));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[3], sizeof(data)));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[4], sizeof(data)));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[5], sizeof(data)));
+
+ /* Initially 2 entries grown to 6 entries using slot 2 */
+ priv->cal_blob = NULL;
+ cs_amp_lib_test_init_dummy_cal_blob(test, 2);
+ KUNIT_ASSERT_EQ(test, 2, priv->cal_blob->count);
+ original_blob = cs_amp_lib_test_cal_blob_dup(test);
+ get_random_bytes(&data, sizeof(data));
+ data.calTarget[0] = 0xaaaaaaaa; /* won't match */
+ KUNIT_EXPECT_EQ(test, 0, cs_amp_set_efi_calibration_data(dev, 2, 6, &data));
+ KUNIT_EXPECT_EQ(test, 6, priv->cal_blob->count);
+ KUNIT_EXPECT_EQ(test, struct_size(priv->cal_blob, data, 6), priv->cal_blob->size);
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[0], &priv->cal_blob->data[0], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[1], &priv->cal_blob->data[1], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &data, &priv->cal_blob->data[2], sizeof(data));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[3], sizeof(data)));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[4], sizeof(data)));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[5], sizeof(data)));
+
+ /* Initially 2 entries grown to 6 entries using slot 4 */
+ kunit_kfree(test, original_blob);
+ kunit_kfree(test, priv->cal_blob);
+ priv->cal_blob = NULL;
+ cs_amp_lib_test_init_dummy_cal_blob(test, 2);
+ KUNIT_ASSERT_EQ(test, 2, priv->cal_blob->count);
+ original_blob = cs_amp_lib_test_cal_blob_dup(test);
+ get_random_bytes(&data, sizeof(data));
+ data.calTarget[0] = 0xaaaaaaaa; /* won't match */
+ KUNIT_EXPECT_EQ(test, 0, cs_amp_set_efi_calibration_data(dev, 4, 6, &data));
+ KUNIT_EXPECT_EQ(test, 6, priv->cal_blob->count);
+ KUNIT_EXPECT_EQ(test, struct_size(priv->cal_blob, data, 6), priv->cal_blob->size);
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[0], &priv->cal_blob->data[0], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[1], &priv->cal_blob->data[1], sizeof(data));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[2], sizeof(data)));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[3], sizeof(data)));
+ KUNIT_EXPECT_MEMEQ(test, &data, &priv->cal_blob->data[4], sizeof(data));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[5], sizeof(data)));
+}
+
+static void cs_amp_lib_test_cal_efi_all_zeros_add_first(struct kunit *test)
+{
+ struct cs_amp_lib_test_priv *priv = test->priv;
+ struct device *dev = &priv->amp_dev->dev;
+ struct cirrus_amp_cal_data data;
+ int i;
+
+ /* Simulate a BIOS reserving EFI space that is entirely zero-filled. */
+ kunit_activate_static_stub(test,
+ cs_amp_test_hooks->get_efi_variable,
+ cs_amp_lib_test_get_efi_variable_all_zeros);
+ kunit_activate_static_stub(test,
+ cs_amp_test_hooks->set_efi_variable,
+ cs_amp_lib_test_set_efi_variable);
+
+ /*
+ * Add an entry. The header should be filled in to match the
+ * original EFI variable size.
+ */
+ get_random_bytes(&data, sizeof(data));
+ KUNIT_EXPECT_EQ(test, 0, cs_amp_set_efi_calibration_data(dev, -1, -1, &data));
+ KUNIT_EXPECT_EQ(test, struct_size(priv->cal_blob, data, 8), priv->cal_blob->size);
+ KUNIT_EXPECT_EQ(test, 8, priv->cal_blob->count);
+ KUNIT_EXPECT_MEMEQ(test, &data, &priv->cal_blob->data[0], sizeof(data));
+ for (i = 1; i < priv->cal_blob->count; i++) {
+ KUNIT_EXPECT_EQ(test, 0, priv->cal_blob->data[i].calTime[0]);
+ KUNIT_EXPECT_EQ(test, 0, priv->cal_blob->data[i].calTime[1]);
+ }
+}
+
+static void cs_amp_lib_test_cal_efi_all_zeros_add_first_no_shrink(struct kunit *test)
+{
+ struct cs_amp_lib_test_priv *priv = test->priv;
+ struct device *dev = &priv->amp_dev->dev;
+ struct cirrus_amp_cal_data data;
+ int i;
+
+ /* Simulate a BIOS reserving EFI space that is entirely zero-filled. */
+ kunit_activate_static_stub(test,
+ cs_amp_test_hooks->get_efi_variable,
+ cs_amp_lib_test_get_efi_variable_all_zeros);
+ kunit_activate_static_stub(test,
+ cs_amp_test_hooks->set_efi_variable,
+ cs_amp_lib_test_set_efi_variable);
+
+ /*
+ * Add an entry. The header should be filled in to match the
+ * original EFI variable size. A number of amps less than the
+ * available preallocated space does not shrink the EFI variable.
+ */
+ get_random_bytes(&data, sizeof(data));
+ KUNIT_EXPECT_EQ(test, 0, cs_amp_set_efi_calibration_data(dev, -1, 4, &data));
+ KUNIT_EXPECT_EQ(test, struct_size(priv->cal_blob, data, 8), priv->cal_blob->size);
+ KUNIT_EXPECT_EQ(test, 8, priv->cal_blob->count);
+ KUNIT_EXPECT_MEMEQ(test, &data, &priv->cal_blob->data[0], sizeof(data));
+ for (i = 1; i < priv->cal_blob->count; i++) {
+ KUNIT_EXPECT_EQ(test, 0, priv->cal_blob->data[i].calTime[0]);
+ KUNIT_EXPECT_EQ(test, 0, priv->cal_blob->data[i].calTime[1]);
+ }
+}
+
+static void cs_amp_lib_test_cal_efi_all_zeros_add_first_indexed(struct kunit *test)
+{
+ struct cs_amp_lib_test_priv *priv = test->priv;
+ struct device *dev = &priv->amp_dev->dev;
+ struct cirrus_amp_cal_data data;
+ int i;
+
+ /* Simulate a BIOS reserving EFI space that is entirely zero-filled. */
+ kunit_activate_static_stub(test,
+ cs_amp_test_hooks->get_efi_variable,
+ cs_amp_lib_test_get_efi_variable_all_zeros);
+ kunit_activate_static_stub(test,
+ cs_amp_test_hooks->set_efi_variable,
+ cs_amp_lib_test_set_efi_variable);
+
+ /*
+ * Write entry to slot 2. The header should be filled in to match
+ * the original EFI variable size.
+ */
+ get_random_bytes(&data, sizeof(data));
+ KUNIT_EXPECT_EQ(test, 0, cs_amp_set_efi_calibration_data(dev, 2, -1, &data));
+ KUNIT_EXPECT_EQ(test, struct_size(priv->cal_blob, data, 8), priv->cal_blob->size);
+ KUNIT_EXPECT_EQ(test, 8, priv->cal_blob->count);
+ KUNIT_EXPECT_EQ(test, 0, priv->cal_blob->data[0].calTime[0]);
+ KUNIT_EXPECT_EQ(test, 0, priv->cal_blob->data[0].calTime[1]);
+ KUNIT_EXPECT_EQ(test, 0, priv->cal_blob->data[1].calTime[0]);
+ KUNIT_EXPECT_EQ(test, 0, priv->cal_blob->data[1].calTime[1]);
+ KUNIT_EXPECT_MEMEQ(test, &data, &priv->cal_blob->data[2], sizeof(data));
+ for (i = 3; i < priv->cal_blob->count; i++) {
+ KUNIT_EXPECT_EQ(test, 0, priv->cal_blob->data[i].calTime[0]);
+ KUNIT_EXPECT_EQ(test, 0, priv->cal_blob->data[i].calTime[1]);
+ }
+}
+
+static void cs_amp_lib_test_cal_efi_all_zeros_add_first_indexed_no_shrink(struct kunit *test)
+{
+ struct cs_amp_lib_test_priv *priv = test->priv;
+ struct device *dev = &priv->amp_dev->dev;
+ struct cirrus_amp_cal_data data;
+ int i;
+
+ /* Simulate a BIOS reserving EFI space that is entirely zero-filled. */
+ kunit_activate_static_stub(test,
+ cs_amp_test_hooks->get_efi_variable,
+ cs_amp_lib_test_get_efi_variable_all_zeros);
+ kunit_activate_static_stub(test,
+ cs_amp_test_hooks->set_efi_variable,
+ cs_amp_lib_test_set_efi_variable);
+
+ /*
+ * Write entry to slot 2. The header should be filled in to match
+ * the original EFI variable size. A number of amps less than the
+ * available preallocated space does not shrink the EFI variable.
+ */
+ get_random_bytes(&data, sizeof(data));
+ KUNIT_EXPECT_EQ(test, 0, cs_amp_set_efi_calibration_data(dev, 2, 4, &data));
+ KUNIT_EXPECT_EQ(test, struct_size(priv->cal_blob, data, 8), priv->cal_blob->size);
+ KUNIT_EXPECT_EQ(test, 8, priv->cal_blob->count);
+ KUNIT_EXPECT_EQ(test, 0, priv->cal_blob->data[0].calTime[0]);
+ KUNIT_EXPECT_EQ(test, 0, priv->cal_blob->data[0].calTime[1]);
+ KUNIT_EXPECT_EQ(test, 0, priv->cal_blob->data[1].calTime[0]);
+ KUNIT_EXPECT_EQ(test, 0, priv->cal_blob->data[1].calTime[1]);
+ KUNIT_EXPECT_MEMEQ(test, &data, &priv->cal_blob->data[2], sizeof(data));
+ for (i = 3; i < priv->cal_blob->count; i++) {
+ KUNIT_EXPECT_EQ(test, 0, priv->cal_blob->data[i].calTime[0]);
+ KUNIT_EXPECT_EQ(test, 0, priv->cal_blob->data[i].calTime[1]);
+ }
+}
+
+static void cs_amp_lib_test_grow_append_cal_efi_indexed_no_max(struct kunit *test)
+{
+ struct cs_amp_lib_test_priv *priv = test->priv;
+ struct device *dev = &priv->amp_dev->dev;
+ const struct cirrus_amp_efi_data *original_blob;
+ struct cirrus_amp_cal_data data;
+ int i;
+
+ kunit_activate_static_stub(test,
+ cs_amp_test_hooks->get_efi_variable,
+ cs_amp_lib_test_get_efi_variable);
+ kunit_activate_static_stub(test,
+ cs_amp_test_hooks->set_efi_variable,
+ cs_amp_lib_test_set_efi_variable);
+
+ /* Initially 1 entry adding slot 1 */
+ cs_amp_lib_test_init_dummy_cal_blob(test, 1);
+ KUNIT_ASSERT_EQ(test, 1, priv->cal_blob->count);
+ original_blob = cs_amp_lib_test_cal_blob_dup(test);
+ get_random_bytes(&data, sizeof(data));
+ data.calTarget[0] = 0xaaaaaaaa; /* won't match */
+ KUNIT_EXPECT_EQ(test, 0, cs_amp_set_efi_calibration_data(dev, 1, -1, &data));
+ KUNIT_EXPECT_GE(test, priv->cal_blob->count, 2);
+ KUNIT_EXPECT_EQ(test, struct_size(priv->cal_blob, data, priv->cal_blob->count),
+ priv->cal_blob->size);
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[0], &priv->cal_blob->data[0], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &data, &priv->cal_blob->data[1], sizeof(data));
+ for (i = 2; i < priv->cal_blob->count; i++)
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[i], sizeof(data)));
+
+ /* Initially 1 entry adding slot 3 */
+ cs_amp_lib_test_init_dummy_cal_blob(test, 1);
+ KUNIT_ASSERT_EQ(test, 1, priv->cal_blob->count);
+ original_blob = cs_amp_lib_test_cal_blob_dup(test);
+ get_random_bytes(&data, sizeof(data));
+ data.calTarget[0] = 0xaaaaaaaa; /* won't match */
+ KUNIT_EXPECT_EQ(test, 0, cs_amp_set_efi_calibration_data(dev, 3, -1, &data));
+ KUNIT_EXPECT_GE(test, priv->cal_blob->count, 4);
+ KUNIT_EXPECT_EQ(test, struct_size(priv->cal_blob, data, priv->cal_blob->count),
+ priv->cal_blob->size);
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[0], &priv->cal_blob->data[0], sizeof(data));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[1], sizeof(data)));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[2], sizeof(data)));
+ KUNIT_EXPECT_MEMEQ(test, &data, &priv->cal_blob->data[3], sizeof(data));
+ for (i = 4; i < priv->cal_blob->count; i++)
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[i], sizeof(data)));
+
+ /* Initially 2 entries adding slot 3 */
+ priv->cal_blob = NULL;
+ cs_amp_lib_test_init_dummy_cal_blob(test, 2);
+ KUNIT_ASSERT_EQ(test, 2, priv->cal_blob->count);
+ original_blob = cs_amp_lib_test_cal_blob_dup(test);
+ get_random_bytes(&data, sizeof(data));
+ data.calTarget[0] = 0xaaaaaaaa; /* won't match */
+ KUNIT_EXPECT_EQ(test, 0, cs_amp_set_efi_calibration_data(dev, 3, -1, &data));
+ KUNIT_EXPECT_GE(test, priv->cal_blob->count, 1);
+ KUNIT_EXPECT_EQ(test, struct_size(priv->cal_blob, data, priv->cal_blob->count),
+ priv->cal_blob->size);
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[0], &priv->cal_blob->data[0], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[1], &priv->cal_blob->data[1], sizeof(data));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[2], sizeof(data)));
+ KUNIT_EXPECT_MEMEQ(test, &data, &priv->cal_blob->data[3], sizeof(data));
+ for (i = 4; i < priv->cal_blob->count; i++)
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[i], sizeof(data)));
+
+ /* Initially 4 entries adding slot 4 */
+ priv->cal_blob = NULL;
+ cs_amp_lib_test_init_dummy_cal_blob(test, 4);
+ KUNIT_ASSERT_EQ(test, 4, priv->cal_blob->count);
+ original_blob = cs_amp_lib_test_cal_blob_dup(test);
+ get_random_bytes(&data, sizeof(data));
+ data.calTarget[0] = 0xaaaaaaaa; /* won't match */
+ KUNIT_EXPECT_EQ(test, 0, cs_amp_set_efi_calibration_data(dev, 4, -1, &data));
+ KUNIT_EXPECT_GE(test, priv->cal_blob->count, 1);
+ KUNIT_EXPECT_EQ(test, struct_size(priv->cal_blob, data, priv->cal_blob->count),
+ priv->cal_blob->size);
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[0], &priv->cal_blob->data[0], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[1], &priv->cal_blob->data[1], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[2], &priv->cal_blob->data[2], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[3], &priv->cal_blob->data[3], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &data, &priv->cal_blob->data[4], sizeof(data));
+ for (i = 5; i < priv->cal_blob->count; i++)
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[i], sizeof(data)));
+
+ /* Initially 4 entries adding slot 6 */
+ priv->cal_blob = NULL;
+ cs_amp_lib_test_init_dummy_cal_blob(test, 4);
+ KUNIT_ASSERT_EQ(test, 4, priv->cal_blob->count);
+ original_blob = cs_amp_lib_test_cal_blob_dup(test);
+ get_random_bytes(&data, sizeof(data));
+ data.calTarget[0] = 0xaaaaaaaa; /* won't match */
+ KUNIT_EXPECT_EQ(test, 0, cs_amp_set_efi_calibration_data(dev, 6, -1, &data));
+ KUNIT_EXPECT_GE(test, priv->cal_blob->count, 1);
+ KUNIT_EXPECT_EQ(test, struct_size(priv->cal_blob, data, priv->cal_blob->count),
+ priv->cal_blob->size);
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[0], &priv->cal_blob->data[0], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[1], &priv->cal_blob->data[1], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[2], &priv->cal_blob->data[2], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[3], &priv->cal_blob->data[3], sizeof(data));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[4], sizeof(data)));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[5], sizeof(data)));
+ KUNIT_EXPECT_MEMEQ(test, &data, &priv->cal_blob->data[6], sizeof(data));
+ for (i = 7; i < priv->cal_blob->count; i++)
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[i], sizeof(data)));
+}
+
+static void cs_amp_lib_test_grow_cal_efi_replace_indexed(struct kunit *test)
+{
+ struct cs_amp_lib_test_priv *priv = test->priv;
+ struct device *dev = &priv->amp_dev->dev;
+ const struct cirrus_amp_efi_data *original_blob;
+ struct cirrus_amp_cal_data data;
+
+ kunit_activate_static_stub(test,
+ cs_amp_test_hooks->get_efi_variable,
+ cs_amp_lib_test_get_efi_variable);
+ kunit_activate_static_stub(test,
+ cs_amp_test_hooks->set_efi_variable,
+ cs_amp_lib_test_set_efi_variable);
+
+ /* Initially 1 entry grown to 2 entries overwriting slot 0 */
+ cs_amp_lib_test_init_dummy_cal_blob(test, 1);
+ KUNIT_ASSERT_EQ(test, 1, priv->cal_blob->count);
+ original_blob = cs_amp_lib_test_cal_blob_dup(test);
+ get_random_bytes(&data, sizeof(data));
+ data.calTarget[0] = 0xaaaaaaaa; /* won't match */
+ KUNIT_EXPECT_EQ(test, 0, cs_amp_set_efi_calibration_data(dev, 0, 2, &data));
+ KUNIT_EXPECT_EQ(test, 2, priv->cal_blob->count);
+ KUNIT_EXPECT_EQ(test, struct_size(priv->cal_blob, data, 2), priv->cal_blob->size);
+ KUNIT_EXPECT_MEMEQ(test, &data, &priv->cal_blob->data[0], sizeof(data));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[1], sizeof(data)));
+
+ /* Initially 2 entries grown to 4 entries overwriting slot 1 */
+ priv->cal_blob = NULL;
+ cs_amp_lib_test_init_dummy_cal_blob(test, 2);
+ KUNIT_ASSERT_EQ(test, 2, priv->cal_blob->count);
+ original_blob = cs_amp_lib_test_cal_blob_dup(test);
+ get_random_bytes(&data, sizeof(data));
+ data.calTarget[0] = 0xaaaaaaaa; /* won't match */
+ KUNIT_EXPECT_EQ(test, 0, cs_amp_set_efi_calibration_data(dev, 1, 4, &data));
+ KUNIT_EXPECT_EQ(test, 4, priv->cal_blob->count);
+ KUNIT_EXPECT_EQ(test, struct_size(priv->cal_blob, data, 4), priv->cal_blob->size);
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[0], &priv->cal_blob->data[0], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &data, &priv->cal_blob->data[1], sizeof(data));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[2], sizeof(data)));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[3], sizeof(data)));
+
+ /* Initially 4 entries grown to 6 entries overwriting slot 1 */
+ priv->cal_blob = NULL;
+ cs_amp_lib_test_init_dummy_cal_blob(test, 4);
+ KUNIT_ASSERT_EQ(test, 4, priv->cal_blob->count);
+ original_blob = cs_amp_lib_test_cal_blob_dup(test);
+ get_random_bytes(&data, sizeof(data));
+ data.calTarget[0] = 0xaaaaaaaa; /* won't match */
+ KUNIT_EXPECT_EQ(test, 0, cs_amp_set_efi_calibration_data(dev, 1, 6, &data));
+ KUNIT_EXPECT_EQ(test, 6, priv->cal_blob->count);
+ KUNIT_EXPECT_EQ(test, struct_size(priv->cal_blob, data, 6), priv->cal_blob->size);
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[0], &priv->cal_blob->data[0], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &data, &priv->cal_blob->data[1], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[2], &priv->cal_blob->data[2], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[3], &priv->cal_blob->data[3], sizeof(data));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[4], sizeof(data)));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[5], sizeof(data)));
+
+ /* Initially 4 entries grown to 6 entries overwriting slot 3 */
+ priv->cal_blob = NULL;
+ cs_amp_lib_test_init_dummy_cal_blob(test, 4);
+ KUNIT_ASSERT_EQ(test, 4, priv->cal_blob->count);
+ original_blob = cs_amp_lib_test_cal_blob_dup(test);
+ get_random_bytes(&data, sizeof(data));
+ data.calTarget[0] = 0xaaaaaaaa; /* won't match */
+ KUNIT_EXPECT_EQ(test, 0, cs_amp_set_efi_calibration_data(dev, 3, 6, &data));
+ KUNIT_EXPECT_EQ(test, 6, priv->cal_blob->count);
+ KUNIT_EXPECT_EQ(test, struct_size(priv->cal_blob, data, 6), priv->cal_blob->size);
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[0], &priv->cal_blob->data[0], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[1], &priv->cal_blob->data[1], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[2], &priv->cal_blob->data[2], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &data, &priv->cal_blob->data[3], sizeof(data));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[4], sizeof(data)));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[5], sizeof(data)));
+
+ /* Initially 6 entries grown to 8 entries overwriting slot 4 */
+ priv->cal_blob = NULL;
+ cs_amp_lib_test_init_dummy_cal_blob(test, 6);
+ KUNIT_ASSERT_EQ(test, 6, priv->cal_blob->count);
+ original_blob = cs_amp_lib_test_cal_blob_dup(test);
+ get_random_bytes(&data, sizeof(data));
+ data.calTarget[0] = 0xaaaaaaaa; /* won't match */
+ KUNIT_EXPECT_EQ(test, 0, cs_amp_set_efi_calibration_data(dev, 4, 8, &data));
+ KUNIT_EXPECT_EQ(test, 8, priv->cal_blob->count);
+ KUNIT_EXPECT_EQ(test, struct_size(priv->cal_blob, data, 8), priv->cal_blob->size);
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[0], &priv->cal_blob->data[0], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[1], &priv->cal_blob->data[1], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[2], &priv->cal_blob->data[2], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[3], &priv->cal_blob->data[3], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &data, &priv->cal_blob->data[4], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[5], &priv->cal_blob->data[5], sizeof(data));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[6], sizeof(data)));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[7], sizeof(data)));
+}
+
+static void cs_amp_lib_test_grow_cal_efi_replace_by_uid(struct kunit *test)
+{
+ struct cs_amp_lib_test_priv *priv = test->priv;
+ struct device *dev = &priv->amp_dev->dev;
+ const struct cirrus_amp_efi_data *original_blob;
+ struct cirrus_amp_cal_data data;
+
+ kunit_activate_static_stub(test,
+ cs_amp_test_hooks->get_efi_variable,
+ cs_amp_lib_test_get_efi_variable);
+ kunit_activate_static_stub(test,
+ cs_amp_test_hooks->set_efi_variable,
+ cs_amp_lib_test_set_efi_variable);
+
+ /* Initially 1 entry grown to 2 entries overwriting slot 0 */
+ cs_amp_lib_test_init_dummy_cal_blob(test, 1);
+ KUNIT_ASSERT_EQ(test, 1, priv->cal_blob->count);
+ original_blob = cs_amp_lib_test_cal_blob_dup(test);
+ get_random_bytes(&data, sizeof(data));
+ memcpy(data.calTarget, priv->cal_blob->data[0].calTarget, sizeof(data.calTarget));
+ KUNIT_EXPECT_EQ(test, 0, cs_amp_set_efi_calibration_data(dev, -1, 2, &data));
+ KUNIT_EXPECT_EQ(test, 2, priv->cal_blob->count);
+ KUNIT_EXPECT_EQ(test, struct_size(priv->cal_blob, data, 2), priv->cal_blob->size);
+ KUNIT_EXPECT_MEMEQ(test, &data, &priv->cal_blob->data[0], sizeof(data));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[1], sizeof(data)));
+
+ /* Initially 2 entries grown to 4 entries overwriting slot 1 */
+ priv->cal_blob = NULL;
+ cs_amp_lib_test_init_dummy_cal_blob(test, 2);
+ KUNIT_ASSERT_EQ(test, 2, priv->cal_blob->count);
+ original_blob = cs_amp_lib_test_cal_blob_dup(test);
+ get_random_bytes(&data, sizeof(data));
+ memcpy(data.calTarget, priv->cal_blob->data[1].calTarget, sizeof(data.calTarget));
+ KUNIT_EXPECT_EQ(test, 0, cs_amp_set_efi_calibration_data(dev, -1, 4, &data));
+ KUNIT_EXPECT_EQ(test, 4, priv->cal_blob->count);
+ KUNIT_EXPECT_EQ(test, struct_size(priv->cal_blob, data, 4), priv->cal_blob->size);
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[0], &priv->cal_blob->data[0], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &data, &priv->cal_blob->data[1], sizeof(data));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[2], sizeof(data)));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[3], sizeof(data)));
+
+ /* Initially 4 entries grown to 6 entries overwriting slot 1 */
+ priv->cal_blob = NULL;
+ cs_amp_lib_test_init_dummy_cal_blob(test, 4);
+ KUNIT_ASSERT_EQ(test, 4, priv->cal_blob->count);
+ original_blob = cs_amp_lib_test_cal_blob_dup(test);
+ get_random_bytes(&data, sizeof(data));
+ memcpy(data.calTarget, priv->cal_blob->data[1].calTarget, sizeof(data.calTarget));
+ KUNIT_EXPECT_EQ(test, 0, cs_amp_set_efi_calibration_data(dev, -1, 6, &data));
+ KUNIT_EXPECT_EQ(test, 6, priv->cal_blob->count);
+ KUNIT_EXPECT_EQ(test, struct_size(priv->cal_blob, data, 6), priv->cal_blob->size);
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[0], &priv->cal_blob->data[0], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &data, &priv->cal_blob->data[1], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[2], &priv->cal_blob->data[2], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[3], &priv->cal_blob->data[3], sizeof(data));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[4], sizeof(data)));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[5], sizeof(data)));
+
+ /* Initially 4 entries grown to 6 entries overwriting slot 3 */
+ priv->cal_blob = NULL;
+ cs_amp_lib_test_init_dummy_cal_blob(test, 4);
+ KUNIT_ASSERT_EQ(test, 4, priv->cal_blob->count);
+ original_blob = cs_amp_lib_test_cal_blob_dup(test);
+ get_random_bytes(&data, sizeof(data));
+ memcpy(data.calTarget, priv->cal_blob->data[3].calTarget, sizeof(data.calTarget));
+ KUNIT_EXPECT_EQ(test, 0, cs_amp_set_efi_calibration_data(dev, -1, 6, &data));
+ KUNIT_EXPECT_EQ(test, 6, priv->cal_blob->count);
+ KUNIT_EXPECT_EQ(test, struct_size(priv->cal_blob, data, 6), priv->cal_blob->size);
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[0], &priv->cal_blob->data[0], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[1], &priv->cal_blob->data[1], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[2], &priv->cal_blob->data[2], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &data, &priv->cal_blob->data[3], sizeof(data));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[4], sizeof(data)));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[5], sizeof(data)));
+
+ /* Initially 6 entries grown to 8 entries overwriting slot 4 */
+ priv->cal_blob = NULL;
+ cs_amp_lib_test_init_dummy_cal_blob(test, 6);
+ KUNIT_ASSERT_EQ(test, 6, priv->cal_blob->count);
+ original_blob = cs_amp_lib_test_cal_blob_dup(test);
+ get_random_bytes(&data, sizeof(data));
+ memcpy(data.calTarget, priv->cal_blob->data[4].calTarget, sizeof(data.calTarget));
+ KUNIT_EXPECT_EQ(test, 0, cs_amp_set_efi_calibration_data(dev, -1, 8, &data));
+ KUNIT_EXPECT_EQ(test, 8, priv->cal_blob->count);
+ KUNIT_EXPECT_EQ(test, struct_size(priv->cal_blob, data, 8), priv->cal_blob->size);
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[0], &priv->cal_blob->data[0], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[1], &priv->cal_blob->data[1], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[2], &priv->cal_blob->data[2], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[3], &priv->cal_blob->data[3], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &data, &priv->cal_blob->data[4], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[5], &priv->cal_blob->data[5], sizeof(data));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[6], sizeof(data)));
+ KUNIT_EXPECT_TRUE(test, mem_is_zero(&priv->cal_blob->data[7], sizeof(data)));
+}
+
+static void cs_amp_lib_test_cal_efi_replace_by_uid(struct kunit *test)
+{
+ struct cs_amp_lib_test_priv *priv = test->priv;
+ struct device *dev = &priv->amp_dev->dev;
+ const struct cirrus_amp_efi_data *original_blob;
+ struct cirrus_amp_cal_data data;
+
+ kunit_activate_static_stub(test,
+ cs_amp_test_hooks->get_efi_variable,
+ cs_amp_lib_test_get_efi_variable);
+ kunit_activate_static_stub(test,
+ cs_amp_test_hooks->set_efi_variable,
+ cs_amp_lib_test_set_efi_variable);
+
+ cs_amp_lib_test_init_dummy_cal_blob(test, 6);
+ KUNIT_ASSERT_EQ(test, 6, priv->cal_blob->count);
+
+ /* Replace entry matching slot 0 */
+ original_blob = cs_amp_lib_test_cal_blob_dup(test);
+ get_random_bytes(&data, sizeof(data));
+ memcpy(data.calTarget, priv->cal_blob->data[0].calTarget, sizeof(data.calTarget));
+ KUNIT_EXPECT_EQ(test, 0, cs_amp_set_efi_calibration_data(dev, -1, -1, &data));
+ KUNIT_EXPECT_EQ(test, 6, priv->cal_blob->count);
+ KUNIT_EXPECT_EQ(test, struct_size(priv->cal_blob, data, 6), priv->cal_blob->size);
+ KUNIT_EXPECT_MEMEQ(test, &data, &priv->cal_blob->data[0], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[1], &priv->cal_blob->data[1], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[2], &priv->cal_blob->data[2], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[3], &priv->cal_blob->data[3], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[4], &priv->cal_blob->data[4], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[5], &priv->cal_blob->data[5], sizeof(data));
+
+ /* Replace entry matching slot 4 */
+ original_blob = cs_amp_lib_test_cal_blob_dup(test);
+ get_random_bytes(&data, sizeof(data));
+ memcpy(data.calTarget, priv->cal_blob->data[4].calTarget, sizeof(data.calTarget));
+ KUNIT_EXPECT_EQ(test, 0, cs_amp_set_efi_calibration_data(dev, -1, -1, &data));
+ KUNIT_EXPECT_EQ(test, 6, priv->cal_blob->count);
+ KUNIT_EXPECT_EQ(test, struct_size(priv->cal_blob, data, 6), priv->cal_blob->size);
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[0], &priv->cal_blob->data[0], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[1], &priv->cal_blob->data[1], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[2], &priv->cal_blob->data[2], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[3], &priv->cal_blob->data[3], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &data, &priv->cal_blob->data[4], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[5], &priv->cal_blob->data[5], sizeof(data));
+
+ /* Replace entry matching slot 3 */
+ original_blob = cs_amp_lib_test_cal_blob_dup(test);
+ get_random_bytes(&data, sizeof(data));
+ memcpy(data.calTarget, priv->cal_blob->data[3].calTarget, sizeof(data.calTarget));
+ KUNIT_EXPECT_EQ(test, 0, cs_amp_set_efi_calibration_data(dev, -1, -1, &data));
+ KUNIT_EXPECT_EQ(test, 6, priv->cal_blob->count);
+ KUNIT_EXPECT_EQ(test, struct_size(priv->cal_blob, data, 6), priv->cal_blob->size);
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[0], &priv->cal_blob->data[0], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[1], &priv->cal_blob->data[1], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[2], &priv->cal_blob->data[2], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &data, &priv->cal_blob->data[3], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[4], &priv->cal_blob->data[4], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[5], &priv->cal_blob->data[5], sizeof(data));
+
+ /* Replace entry matching slot 5 */
+ original_blob = cs_amp_lib_test_cal_blob_dup(test);
+ get_random_bytes(&data, sizeof(data));
+ memcpy(data.calTarget, priv->cal_blob->data[5].calTarget, sizeof(data.calTarget));
+ KUNIT_EXPECT_EQ(test, 0, cs_amp_set_efi_calibration_data(dev, -1, -1, &data));
+ KUNIT_EXPECT_EQ(test, 6, priv->cal_blob->count);
+ KUNIT_EXPECT_EQ(test, struct_size(priv->cal_blob, data, 6), priv->cal_blob->size);
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[0], &priv->cal_blob->data[0], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[1], &priv->cal_blob->data[1], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[2], &priv->cal_blob->data[2], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[3], &priv->cal_blob->data[3], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[4], &priv->cal_blob->data[4], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &data, &priv->cal_blob->data[5], sizeof(data));
+}
+
+static void cs_amp_lib_test_cal_efi_replace_by_index(struct kunit *test)
+{
+ struct cs_amp_lib_test_priv *priv = test->priv;
+ struct device *dev = &priv->amp_dev->dev;
+ const struct cirrus_amp_efi_data *original_blob;
+ struct cirrus_amp_cal_data data;
+
+ kunit_activate_static_stub(test,
+ cs_amp_test_hooks->get_efi_variable,
+ cs_amp_lib_test_get_efi_variable);
+ kunit_activate_static_stub(test,
+ cs_amp_test_hooks->set_efi_variable,
+ cs_amp_lib_test_set_efi_variable);
+
+ cs_amp_lib_test_init_dummy_cal_blob(test, 6);
+ KUNIT_ASSERT_EQ(test, 6, priv->cal_blob->count);
+
+ /*
+ * Replace entry matching slot 0.
+ * data.calTarget is deliberately set different to current calTarget
+ * of the slot to check that the index forces that slot to be used.
+ */
+ original_blob = cs_amp_lib_test_cal_blob_dup(test);
+ get_random_bytes(&data, sizeof(data));
+ data.calTarget[0] = ~priv->cal_blob->data[0].calTarget[0];
+ KUNIT_EXPECT_EQ(test, 0, cs_amp_set_efi_calibration_data(dev, 0, -1, &data));
+ KUNIT_EXPECT_EQ(test, 6, priv->cal_blob->count);
+ KUNIT_EXPECT_EQ(test, struct_size(priv->cal_blob, data, 6), priv->cal_blob->size);
+ KUNIT_EXPECT_MEMEQ(test, &data, &priv->cal_blob->data[0], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[1], &priv->cal_blob->data[1], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[2], &priv->cal_blob->data[2], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[3], &priv->cal_blob->data[3], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[4], &priv->cal_blob->data[4], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[5], &priv->cal_blob->data[5], sizeof(data));
+
+ /* Replace entry matching slot 4 */
+ original_blob = cs_amp_lib_test_cal_blob_dup(test);
+ get_random_bytes(&data, sizeof(data));
+ data.calTarget[0] = ~priv->cal_blob->data[4].calTarget[0];
+ KUNIT_EXPECT_EQ(test, 0, cs_amp_set_efi_calibration_data(dev, 4, -1, &data));
+ KUNIT_EXPECT_EQ(test, 6, priv->cal_blob->count);
+ KUNIT_EXPECT_EQ(test, struct_size(priv->cal_blob, data, 6), priv->cal_blob->size);
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[0], &priv->cal_blob->data[0], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[1], &priv->cal_blob->data[1], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[2], &priv->cal_blob->data[2], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[3], &priv->cal_blob->data[3], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &data, &priv->cal_blob->data[4], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[5], &priv->cal_blob->data[5], sizeof(data));
+
+ /* Replace entry matching slot 3 */
+ original_blob = cs_amp_lib_test_cal_blob_dup(test);
+ get_random_bytes(&data, sizeof(data));
+ data.calTarget[0] = ~priv->cal_blob->data[3].calTarget[0];
+ KUNIT_EXPECT_EQ(test, 0, cs_amp_set_efi_calibration_data(dev, 3, -1, &data));
+ KUNIT_EXPECT_EQ(test, 6, priv->cal_blob->count);
+ KUNIT_EXPECT_EQ(test, struct_size(priv->cal_blob, data, 6), priv->cal_blob->size);
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[0], &priv->cal_blob->data[0], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[1], &priv->cal_blob->data[1], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[2], &priv->cal_blob->data[2], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &data, &priv->cal_blob->data[3], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[4], &priv->cal_blob->data[4], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[5], &priv->cal_blob->data[5], sizeof(data));
+
+ /* Replace entry matching slot 5 */
+ original_blob = cs_amp_lib_test_cal_blob_dup(test);
+ get_random_bytes(&data, sizeof(data));
+ data.calTarget[0] = ~priv->cal_blob->data[5].calTarget[0];
+ KUNIT_EXPECT_EQ(test, 0, cs_amp_set_efi_calibration_data(dev, 5, -1, &data));
+ KUNIT_EXPECT_EQ(test, 6, priv->cal_blob->count);
+ KUNIT_EXPECT_EQ(test, struct_size(priv->cal_blob, data, 6), priv->cal_blob->size);
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[0], &priv->cal_blob->data[0], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[1], &priv->cal_blob->data[1], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[2], &priv->cal_blob->data[2], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[3], &priv->cal_blob->data[3], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[4], &priv->cal_blob->data[4], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &data, &priv->cal_blob->data[5], sizeof(data));
+}
+
+static void cs_amp_lib_test_cal_efi_deduplicate(struct kunit *test)
+{
+ struct cs_amp_lib_test_priv *priv = test->priv;
+ struct device *dev = &priv->amp_dev->dev;
+ const struct cirrus_amp_efi_data *original_blob;
+ struct cirrus_amp_cal_data data;
+ int i;
+
+ kunit_activate_static_stub(test,
+ cs_amp_test_hooks->get_efi_variable,
+ cs_amp_lib_test_get_efi_variable);
+ kunit_activate_static_stub(test,
+ cs_amp_test_hooks->set_efi_variable,
+ cs_amp_lib_test_set_efi_variable);
+
+ /*
+ * Replace entry matching slot 0.
+ * An active entry in slot 1 for the same UID should be marked empty.
+ * Other entries are unaltered.
+ */
+ cs_amp_lib_test_init_dummy_cal_blob(test, 4);
+ KUNIT_ASSERT_EQ(test, 4, priv->cal_blob->count);
+ original_blob = cs_amp_lib_test_cal_blob_dup(test);
+ get_random_bytes(&data, sizeof(data));
+ memcpy(data.calTarget, priv->cal_blob->data[1].calTarget, sizeof(data.calTarget));
+ KUNIT_EXPECT_EQ(test, 0, cs_amp_set_efi_calibration_data(dev, 0, -1, &data));
+ KUNIT_EXPECT_MEMEQ(test, &data, &priv->cal_blob->data[0], sizeof(data));
+ KUNIT_EXPECT_EQ(test, 0, priv->cal_blob->data[1].calTime[0]);
+ KUNIT_EXPECT_EQ(test, 0, priv->cal_blob->data[1].calTime[1]);
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[2], &priv->cal_blob->data[2], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[3], &priv->cal_blob->data[3], sizeof(data));
+
+ /*
+ * Replace entry matching slot 1.
+ * An active entry in slot 0 for the same UID should be marked empty.
+ * Other entries are unaltered.
+ */
+ priv->cal_blob = NULL;
+ cs_amp_lib_test_init_dummy_cal_blob(test, 4);
+ KUNIT_ASSERT_EQ(test, 4, priv->cal_blob->count);
+ original_blob = cs_amp_lib_test_cal_blob_dup(test);
+ get_random_bytes(&data, sizeof(data));
+ memcpy(data.calTarget, priv->cal_blob->data[0].calTarget, sizeof(data.calTarget));
+ KUNIT_EXPECT_EQ(test, 0, cs_amp_set_efi_calibration_data(dev, 1, -1, &data));
+ KUNIT_EXPECT_EQ(test, 0, priv->cal_blob->data[0].calTime[0]);
+ KUNIT_EXPECT_EQ(test, 0, priv->cal_blob->data[0].calTime[1]);
+ KUNIT_EXPECT_MEMEQ(test, &data, &priv->cal_blob->data[1], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[2], &priv->cal_blob->data[2], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[3], &priv->cal_blob->data[3], sizeof(data));
+
+ /*
+ * Replace entry matching slot 1.
+ * An active entry in slot 3 for the same UID should be marked empty.
+ * Other entries are unaltered.
+ */
+ priv->cal_blob = NULL;
+ cs_amp_lib_test_init_dummy_cal_blob(test, 4);
+ KUNIT_ASSERT_EQ(test, 4, priv->cal_blob->count);
+ original_blob = cs_amp_lib_test_cal_blob_dup(test);
+ get_random_bytes(&data, sizeof(data));
+ memcpy(data.calTarget, priv->cal_blob->data[3].calTarget, sizeof(data.calTarget));
+ KUNIT_EXPECT_EQ(test, 0, cs_amp_set_efi_calibration_data(dev, 1, -1, &data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[0], &priv->cal_blob->data[0], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &data, &priv->cal_blob->data[1], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[2], &priv->cal_blob->data[2], sizeof(data));
+ KUNIT_EXPECT_EQ(test, 0, priv->cal_blob->data[3].calTime[0]);
+ KUNIT_EXPECT_EQ(test, 0, priv->cal_blob->data[3].calTime[1]);
+
+ /*
+ * Worst case, all entries have the same UID
+ */
+ priv->cal_blob = NULL;
+ cs_amp_lib_test_init_dummy_cal_blob(test, 4);
+ KUNIT_ASSERT_EQ(test, 4, priv->cal_blob->count);
+ original_blob = cs_amp_lib_test_cal_blob_dup(test);
+ get_random_bytes(&data, sizeof(data));
+ for (i = 0; i < priv->cal_blob->count; i++) {
+ priv->cal_blob->data[i].calTarget[0] = 0xe5e5e5e5;
+ priv->cal_blob->data[i].calTarget[1] = 0xa7a7a7a7;
+ }
+ memcpy(data.calTarget, priv->cal_blob->data[2].calTarget, sizeof(data.calTarget));
+ KUNIT_EXPECT_EQ(test, 0, cs_amp_set_efi_calibration_data(dev, 2, -1, &data));
+ KUNIT_EXPECT_EQ(test, 0, priv->cal_blob->data[0].calTime[0]);
+ KUNIT_EXPECT_EQ(test, 0, priv->cal_blob->data[0].calTime[1]);
+ KUNIT_EXPECT_EQ(test, 0, priv->cal_blob->data[1].calTime[0]);
+ KUNIT_EXPECT_EQ(test, 0, priv->cal_blob->data[1].calTime[1]);
+ KUNIT_EXPECT_MEMEQ(test, &data, &priv->cal_blob->data[2], sizeof(data));
+ KUNIT_EXPECT_EQ(test, 0, priv->cal_blob->data[3].calTime[0]);
+ KUNIT_EXPECT_EQ(test, 0, priv->cal_blob->data[3].calTime[1]);
+}
+
+static void cs_amp_lib_test_cal_efi_find_free(struct kunit *test)
+{
+ struct cs_amp_lib_test_priv *priv = test->priv;
+ struct device *dev = &priv->amp_dev->dev;
+ const struct cirrus_amp_efi_data *original_blob;
+ struct cirrus_amp_cal_data data;
+
+ kunit_activate_static_stub(test,
+ cs_amp_test_hooks->get_efi_variable,
+ cs_amp_lib_test_get_efi_variable);
+ kunit_activate_static_stub(test,
+ cs_amp_test_hooks->set_efi_variable,
+ cs_amp_lib_test_set_efi_variable);
+
+ cs_amp_lib_test_init_dummy_cal_blob(test, 6);
+ KUNIT_ASSERT_EQ(test, 6, priv->cal_blob->count);
+
+ /*
+ * Slot 0 is empty.
+ * data.calTarget is set to a value that won't match any existing entry.
+ */
+ memset(&priv->cal_blob->data[0].calTime, 0, sizeof(priv->cal_blob->data[0].calTime));
+ original_blob = cs_amp_lib_test_cal_blob_dup(test);
+ get_random_bytes(&data, sizeof(data));
+ data.calTarget[0] = 0xaaaaaaaa;
+ KUNIT_EXPECT_EQ(test, 0, cs_amp_set_efi_calibration_data(dev, -1, -1, &data));
+ KUNIT_EXPECT_EQ(test, 6, priv->cal_blob->count);
+ KUNIT_EXPECT_EQ(test, struct_size(priv->cal_blob, data, 6), priv->cal_blob->size);
+ KUNIT_EXPECT_MEMEQ(test, &data, &priv->cal_blob->data[0], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[1], &priv->cal_blob->data[1], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[2], &priv->cal_blob->data[2], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[3], &priv->cal_blob->data[3], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[4], &priv->cal_blob->data[4], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[5], &priv->cal_blob->data[5], sizeof(data));
+
+ /* Slot 4 is empty */
+ memset(&priv->cal_blob->data[4].calTime, 0, sizeof(priv->cal_blob->data[4].calTime));
+ original_blob = cs_amp_lib_test_cal_blob_dup(test);
+ get_random_bytes(&data, sizeof(data));
+ data.calTarget[0] = 0xaaaaaaaa;
+ KUNIT_EXPECT_EQ(test, 0, cs_amp_set_efi_calibration_data(dev, -1, -1, &data));
+ KUNIT_EXPECT_EQ(test, 6, priv->cal_blob->count);
+ KUNIT_EXPECT_EQ(test, struct_size(priv->cal_blob, data, 6), priv->cal_blob->size);
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[0], &priv->cal_blob->data[0], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[1], &priv->cal_blob->data[1], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[2], &priv->cal_blob->data[2], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[3], &priv->cal_blob->data[3], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &data, &priv->cal_blob->data[4], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[5], &priv->cal_blob->data[5], sizeof(data));
+
+ /* Slot 3 is empty */
+ memset(&priv->cal_blob->data[3].calTime, 0, sizeof(priv->cal_blob->data[3].calTime));
+ original_blob = cs_amp_lib_test_cal_blob_dup(test);
+ get_random_bytes(&data, sizeof(data));
+ data.calTarget[0] = 0xaaaaaaaa;
+ KUNIT_EXPECT_EQ(test, 0, cs_amp_set_efi_calibration_data(dev, -1, -1, &data));
+ KUNIT_EXPECT_EQ(test, 6, priv->cal_blob->count);
+ KUNIT_EXPECT_EQ(test, struct_size(priv->cal_blob, data, 6), priv->cal_blob->size);
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[0], &priv->cal_blob->data[0], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[1], &priv->cal_blob->data[1], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[2], &priv->cal_blob->data[2], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &data, &priv->cal_blob->data[3], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[4], &priv->cal_blob->data[4], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[5], &priv->cal_blob->data[5], sizeof(data));
+
+ /* Replace entry matching slot 5 */
+ memset(&priv->cal_blob->data[5].calTime, 0, sizeof(priv->cal_blob->data[5].calTime));
+ original_blob = cs_amp_lib_test_cal_blob_dup(test);
+ get_random_bytes(&data, sizeof(data));
+ data.calTarget[0] = 0xaaaaaaaa;
+ KUNIT_EXPECT_EQ(test, 0, cs_amp_set_efi_calibration_data(dev, -1, -1, &data));
+ KUNIT_EXPECT_EQ(test, 6, priv->cal_blob->count);
+ KUNIT_EXPECT_EQ(test, struct_size(priv->cal_blob, data, 6), priv->cal_blob->size);
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[0], &priv->cal_blob->data[0], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[1], &priv->cal_blob->data[1], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[2], &priv->cal_blob->data[2], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[3], &priv->cal_blob->data[3], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[4], &priv->cal_blob->data[4], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &data, &priv->cal_blob->data[5], sizeof(data));
+}
+
+static void cs_amp_lib_test_cal_efi_bad_cal_target(struct kunit *test)
+{
+ struct cs_amp_lib_test_priv *priv = test->priv;
+ struct device *dev = &priv->amp_dev->dev;
+ struct cirrus_amp_cal_data data;
+
+ kunit_activate_static_stub(test,
+ cs_amp_test_hooks->get_efi_variable,
+ cs_amp_lib_test_get_efi_variable);
+ kunit_activate_static_stub(test,
+ cs_amp_test_hooks->set_efi_variable,
+ cs_amp_lib_test_set_efi_variable);
+
+ cs_amp_lib_test_init_dummy_cal_blob(test, 4);
+
+ /* Zero calTarget is illegal */
+ get_random_bytes(&data, sizeof(data));
+ memset(data.calTarget, 0, sizeof(data.calTarget));
+ KUNIT_EXPECT_LT(test, cs_amp_set_efi_calibration_data(dev, -1, -1, &data), 0);
+ KUNIT_EXPECT_LT(test, cs_amp_set_efi_calibration_data(dev, 0, -1, &data), 0);
+ KUNIT_EXPECT_LT(test, cs_amp_set_efi_calibration_data(dev, 0, 2, &data), 0);
+}
+
+static void cs_amp_lib_test_cal_efi_write_denied(struct kunit *test)
+{
+ struct cs_amp_lib_test_priv *priv = test->priv;
+ struct device *dev = &priv->amp_dev->dev;
+ const struct cirrus_amp_efi_data *original_blob;
+ struct cirrus_amp_cal_data data;
+
+ kunit_activate_static_stub(test,
+ cs_amp_test_hooks->get_efi_variable,
+ cs_amp_lib_test_get_efi_variable);
+ kunit_activate_static_stub(test,
+ cs_amp_test_hooks->set_efi_variable,
+ cs_amp_lib_test_set_efi_variable_denied);
+
+ cs_amp_lib_test_init_dummy_cal_blob(test, 4);
+ KUNIT_ASSERT_EQ(test, 4, priv->cal_blob->count);
+ original_blob = cs_amp_lib_test_cal_blob_dup(test);
+ get_random_bytes(&data, sizeof(data));
+
+ /* Unspecified slot */
+ KUNIT_EXPECT_LT(test, cs_amp_set_efi_calibration_data(dev, -1, -1, &data), 0);
+ KUNIT_EXPECT_MEMEQ(test, original_blob, priv->cal_blob, original_blob->size);
+
+ /* Unspecified slot with size */
+ KUNIT_EXPECT_LT(test, cs_amp_set_efi_calibration_data(dev, -1, 6, &data), 0);
+ KUNIT_EXPECT_MEMEQ(test, original_blob, priv->cal_blob, original_blob->size);
+
+ /* Specified slot */
+ KUNIT_EXPECT_LT(test, cs_amp_set_efi_calibration_data(dev, 1, -1, &data), 0);
+ KUNIT_EXPECT_MEMEQ(test, original_blob, priv->cal_blob, original_blob->size);
+
+ /* Specified slot with size */
+ KUNIT_EXPECT_LT(test, cs_amp_set_efi_calibration_data(dev, 1, 6, &data), 0);
+ KUNIT_EXPECT_MEMEQ(test, original_blob, priv->cal_blob, original_blob->size);
+}
+
+static void cs_amp_lib_test_cal_efi_attr_preserved(struct kunit *test)
+{
+ struct cs_amp_lib_test_priv *priv = test->priv;
+ struct device *dev = &priv->amp_dev->dev;
+ struct cirrus_amp_cal_data data;
+
+ kunit_activate_static_stub(test,
+ cs_amp_test_hooks->get_efi_variable,
+ cs_amp_lib_test_get_efi_variable);
+ kunit_activate_static_stub(test,
+ cs_amp_test_hooks->set_efi_variable,
+ cs_amp_lib_test_set_efi_variable);
+
+ cs_amp_lib_test_init_dummy_cal_blob(test, 6);
+ KUNIT_ASSERT_EQ(test, 6, priv->cal_blob->count);
+ memset(&priv->cal_blob->data[0], 0, sizeof(priv->cal_blob->data[0]));
+ get_random_bytes(&data, sizeof(data));
+
+ /* Set a non-standard attr to return from get_efi_variable() */
+ priv->efi_attr = EFI_VARIABLE_HARDWARE_ERROR_RECORD;
+
+ KUNIT_EXPECT_EQ(test, 0, cs_amp_set_efi_calibration_data(dev, -1, -1, &data));
+ KUNIT_EXPECT_MEMEQ(test, &data, &priv->cal_blob->data[0], sizeof(data));
+ KUNIT_EXPECT_EQ(test, priv->efi_attr, EFI_VARIABLE_HARDWARE_ERROR_RECORD);
+}
+
+static efi_status_t cs_amp_lib_test_set_hp_efi_cal_variable(efi_char16_t *name,
+ efi_guid_t *guid,
+ u32 attr,
+ unsigned long size,
+ void *buf)
+{
+ static const efi_char16_t expected_name[] = HP_CALIBRATION_EFI_NAME;
+ static const efi_guid_t expected_guid = HP_CALIBRATION_EFI_GUID;
+ struct kunit *test = kunit_get_current_test();
+ struct cs_amp_lib_test_priv *priv = test->priv;
+
+ KUNIT_ASSERT_NOT_NULL(test, name);
+ KUNIT_ASSERT_NOT_NULL(test, guid);
+
+ if (memcmp(name, expected_name, sizeof(expected_name)) ||
+ efi_guidcmp(*guid, expected_guid))
+ return -EFI_ACCESS_DENIED;
+
+ KUNIT_ASSERT_NOT_NULL(test, buf);
+ KUNIT_ASSERT_NE(test, 0, size);
+
+ kunit_kfree(test, priv->cal_blob);
+ priv->cal_blob = kunit_kmalloc(test, size, GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, priv->cal_blob);
+ memcpy(priv->cal_blob, buf, size);
+ priv->efi_attr = attr;
+
+ return EFI_SUCCESS;
+}
+
+/*
+ * If the HP EFI exists it should be the one that is updated.
+ */
+static void cs_amp_lib_test_cal_efi_update_hp(struct kunit *test)
+{
+ struct cs_amp_lib_test_priv *priv = test->priv;
+ struct device *dev = &priv->amp_dev->dev;
+ const struct cirrus_amp_efi_data *original_blob;
+ struct cirrus_amp_cal_data data;
+
+ kunit_activate_static_stub(test,
+ cs_amp_test_hooks->get_efi_variable,
+ cs_amp_lib_test_get_hp_cal_efi_variable);
+ kunit_activate_static_stub(test,
+ cs_amp_test_hooks->set_efi_variable,
+ cs_amp_lib_test_set_hp_efi_cal_variable);
+
+ cs_amp_lib_test_init_dummy_cal_blob(test, 6);
+ KUNIT_ASSERT_EQ(test, 6, priv->cal_blob->count);
+
+ /* Replace entry matching slot 4 */
+ original_blob = cs_amp_lib_test_cal_blob_dup(test);
+ get_random_bytes(&data, sizeof(data));
+ data.calTarget[0] = ~priv->cal_blob->data[4].calTarget[0];
+ KUNIT_EXPECT_EQ(test, 0, cs_amp_set_efi_calibration_data(dev, 4, -1, &data));
+ KUNIT_EXPECT_EQ(test, 6, priv->cal_blob->count);
+ KUNIT_EXPECT_EQ(test, struct_size(priv->cal_blob, data, 6), priv->cal_blob->size);
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[0], &priv->cal_blob->data[0], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[1], &priv->cal_blob->data[1], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[2], &priv->cal_blob->data[2], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[3], &priv->cal_blob->data[3], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &data, &priv->cal_blob->data[4], sizeof(data));
+ KUNIT_EXPECT_MEMEQ(test, &original_blob->data[5], &priv->cal_blob->data[5], sizeof(data));
+}
+
static void cs_amp_lib_test_spkid_lenovo_not_present(struct kunit *test)
{
struct cs_amp_lib_test_priv *priv = test->priv;
@@ -1073,6 +2434,28 @@ static struct kunit_case cs_amp_lib_test_cases[] = {
KUNIT_CASE(cs_amp_lib_test_read_cal_data_test),
KUNIT_CASE(cs_amp_lib_test_write_ambient_test),

+ /* Test cases for writing cal data to UEFI */
+ KUNIT_CASE(cs_amp_lib_test_create_new_cal_efi),
+ KUNIT_CASE(cs_amp_lib_test_create_new_cal_efi_indexed),
+ KUNIT_CASE(cs_amp_lib_test_create_new_cal_efi_indexed_no_max),
+ KUNIT_CASE(cs_amp_lib_test_cal_efi_all_zeros_add_first),
+ KUNIT_CASE(cs_amp_lib_test_cal_efi_all_zeros_add_first_no_shrink),
+ KUNIT_CASE(cs_amp_lib_test_cal_efi_all_zeros_add_first_indexed),
+ KUNIT_CASE(cs_amp_lib_test_cal_efi_all_zeros_add_first_indexed_no_shrink),
+ KUNIT_CASE(cs_amp_lib_test_grow_append_cal_efi),
+ KUNIT_CASE(cs_amp_lib_test_grow_append_cal_efi_indexed),
+ KUNIT_CASE(cs_amp_lib_test_grow_append_cal_efi_indexed_no_max),
+ KUNIT_CASE(cs_amp_lib_test_grow_cal_efi_replace_indexed),
+ KUNIT_CASE(cs_amp_lib_test_grow_cal_efi_replace_by_uid),
+ KUNIT_CASE(cs_amp_lib_test_cal_efi_replace_by_uid),
+ KUNIT_CASE(cs_amp_lib_test_cal_efi_replace_by_index),
+ KUNIT_CASE(cs_amp_lib_test_cal_efi_deduplicate),
+ KUNIT_CASE(cs_amp_lib_test_cal_efi_find_free),
+ KUNIT_CASE(cs_amp_lib_test_cal_efi_bad_cal_target),
+ KUNIT_CASE(cs_amp_lib_test_cal_efi_write_denied),
+ KUNIT_CASE(cs_amp_lib_test_cal_efi_attr_preserved),
+ KUNIT_CASE(cs_amp_lib_test_cal_efi_update_hp),
+
/* Test cases for speaker ID */
KUNIT_CASE(cs_amp_lib_test_spkid_lenovo_not_present),
KUNIT_CASE(cs_amp_lib_test_spkid_lenovo_d0),
diff --git a/sound/soc/codecs/cs-amp-lib.c b/sound/soc/codecs/cs-amp-lib.c
index 3f352ecad3e0..1c53328d7165 100644
--- a/sound/soc/codecs/cs-amp-lib.c
+++ b/sound/soc/codecs/cs-amp-lib.c
@@ -701,6 +701,7 @@ EXPORT_SYMBOL_NS_GPL(cs_amp_get_vendor_spkid, "SND_SOC_CS_AMP_LIB");

static const struct cs_amp_test_hooks cs_amp_test_hook_ptrs = {
.get_efi_variable = cs_amp_get_efi_variable,
+ .set_efi_variable = cs_amp_set_efi_variable,
.write_cal_coeff = cs_amp_write_cal_coeff,
.read_cal_coeff = cs_amp_read_cal_coeff,
};
--
2.47.3