/* Add some unknown blocks at the start of the wmfw */
get_random_bytes(random_data, sizeof(random_data));
cs_dsp_mock_wmfw_add_raw_block(local->wmfw_builder, 0xf5, 0,
random_data, sizeof(random_data));
cs_dsp_mock_wmfw_add_raw_block(local->wmfw_builder, 0xc0, 0, random_data, sizeof(random_data));
cs_dsp_mock_wmfw_add_raw_block(local->wmfw_builder, 0x33, 0, NULL, 0);
/* Add a single payload to be written to DSP memory */
cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,
WMFW_ADSP2_YM, 0,
payload_data, payload_size_bytes);
/* Sanity-check that the good wmfw loads ok */
KUNIT_EXPECT_EQ(test,
cs_dsp_power_up(priv->dsp, wmfw, "wmfw", NULL, NULL, "misc"),
0);
cs_dsp_power_down(priv->dsp);
/* Check that the payload was written to memory */
reg_addr = cs_dsp_mock_base_addr_for_mem(priv, WMFW_ADSP2_YM);
KUNIT_EXPECT_EQ(test,
regmap_raw_read(priv->dsp->regmap, reg_addr, readback, payload_size_bytes),
0);
KUNIT_EXPECT_MEMEQ(test, readback, payload_data, payload_size_bytes);
}
/* Load a wmfw that doesn't have a valid magic marker. */ staticvoid wmfw_err_wrong_magic(struct kunit *test)
{ struct cs_dsp_test *priv = test->priv; struct cs_dsp_test_local *local = priv->local; struct firmware *wmfw;
/* Sanity-check that the good wmfw loads ok */
KUNIT_EXPECT_EQ(test,
cs_dsp_power_up(priv->dsp, wmfw, "wmfw", NULL, NULL, "misc"),
0);
cs_dsp_power_down(priv->dsp);
/* Load a wmfw that is too short for a valid header. */ staticvoid wmfw_err_too_short_for_header(struct kunit *test)
{ struct cs_dsp_test *priv = test->priv; struct cs_dsp_test_local *local = priv->local; struct firmware *wmfw;
/* Sanity-check that the good wmfw loads ok */
KUNIT_EXPECT_EQ(test,
cs_dsp_power_up(priv->dsp, wmfw, "wmfw", NULL, NULL, "misc"),
0);
cs_dsp_power_down(priv->dsp);
/* Sanity-check that the good wmfw loads ok */
KUNIT_EXPECT_EQ(test,
cs_dsp_power_up(priv->dsp, wmfw, "wmfw", NULL, NULL, "misc"),
0);
cs_dsp_power_down(priv->dsp);
/* Sanity-check that the good wmfw loads ok */
KUNIT_EXPECT_EQ(test,
cs_dsp_power_up(priv->dsp, wmfw, "wmfw", NULL, NULL, "misc"),
0);
cs_dsp_power_down(priv->dsp);
/* Add the block. A block must have at least 4 bytes of payload */
cs_dsp_mock_wmfw_add_raw_block(local->wmfw_builder, param->block_type, 0,
&dummy_payload, sizeof(dummy_payload));
/* Sanity-check that the good wmfw loads ok */
KUNIT_EXPECT_EQ(test,
cs_dsp_power_up(priv->dsp, wmfw, "wmfw", NULL, NULL, "misc"),
0);
cs_dsp_power_down(priv->dsp);
/* Sanity-check that the good wmfw loads ok */
KUNIT_EXPECT_EQ(test,
cs_dsp_power_up(priv->dsp, wmfw, "wmfw", NULL, NULL, "misc"),
0);
cs_dsp_power_down(priv->dsp);
for (i = 0; i < sizeof(payload); i++) {
wmfw->size--;
KUNIT_EXPECT_EQ(test,
cs_dsp_power_up(priv->dsp, wmfw, "mock_wmfw", NULL, NULL, "misc"),
-EOVERFLOW);
}
}
/* Sanity-check that the good wmfw loads ok */
KUNIT_EXPECT_EQ(test,
cs_dsp_power_up(priv->dsp, wmfw, "wmfw", NULL, NULL, "misc"),
0);
cs_dsp_power_down(priv->dsp);
header = (struct wmfw_header *)wmfw->data;
region = (struct wmfw_region *)&wmfw->data[le32_to_cpu(header->len)];
/* Sanity check that we're looking at the correct part of the wmfw */
KUNIT_ASSERT_EQ(test, le32_to_cpu(region->offset) >> 24, param->block_type);
KUNIT_ASSERT_EQ(test, le32_to_cpu(region->len), sizeof(payload));
/* Sanity-check that the good wmfw loads ok */
KUNIT_EXPECT_EQ(test,
cs_dsp_power_up(priv->dsp, wmfw, "wmfw", NULL, NULL, "misc"),
0);
cs_dsp_power_down(priv->dsp);
/* Sanity check we're pointing at the alg header */
KUNIT_ASSERT_EQ(test, le32_to_cpu(alg_data->id), cs_dsp_wmfw_err_test_mock_algs[0].id);
/* Write a string to the alg name that overflows the array */
memset(alg_data->descr, 0, sizeof(alg_data->descr));
memset(alg_data->name, 'A', sizeof(alg_data->name));
memset(alg_data->descr, 'A', sizeof(alg_data->descr) - 1);
/* * Sanity-check that a strlen would overflow alg_data->name. * FORTIFY_STRING obstructs testing what strlen() would actually * return, so instead verify that a strnlen() returns * sizeof(alg_data->name[]), therefore it doesn't have a NUL.
*/
KUNIT_ASSERT_EQ(test, strnlen(alg_data->name, sizeof(alg_data->name)), sizeof(alg_data->name));
/* * The alg name isn't stored, but cs_dsp parses the name field. * It should load the file successfully and create the control. * If FORTIFY_STRING is enabled it will detect a buffer overflow * if cs_dsp string length walks past end of alg name array.
*/
KUNIT_EXPECT_EQ(test,
cs_dsp_power_up(priv->dsp, wmfw, "mock_wmfw", NULL, NULL, "misc"),
0);
ctl = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
KUNIT_ASSERT_NOT_NULL(test, ctl);
KUNIT_EXPECT_EQ(test, ctl->subname_len, 0);
}
/* Sanity-check that the good wmfw loads ok */
KUNIT_EXPECT_EQ(test,
cs_dsp_power_up(priv->dsp, wmfw, "wmfw", NULL, NULL, "misc"),
0);
cs_dsp_power_down(priv->dsp);
/* Set name string length longer than available space */
*(u8 *)&alg_data[1] = 4;
KUNIT_EXPECT_EQ(test,
cs_dsp_power_up(priv->dsp, wmfw, "mock_wmfw", NULL, NULL, "misc"),
-EOVERFLOW);
/* Sanity-check that the good wmfw loads ok */
KUNIT_EXPECT_EQ(test,
cs_dsp_power_up(priv->dsp, wmfw, "wmfw", NULL, NULL, "misc"),
0);
cs_dsp_power_down(priv->dsp);
/* Set name string length longer than available space */
*(__le16 *)&alg_data[2] = cpu_to_le16(4);
KUNIT_EXPECT_EQ(test,
cs_dsp_power_up(priv->dsp, wmfw, "mock_wmfw", NULL, NULL, "misc"),
-EOVERFLOW);
/* Sanity-check that the good wmfw loads ok */
KUNIT_EXPECT_EQ(test,
cs_dsp_power_up(priv->dsp, wmfw, "wmfw", NULL, NULL, "misc"),
0);
cs_dsp_power_down(priv->dsp);
/* Sanity-check that the good wmfw loads ok */
KUNIT_EXPECT_EQ(test,
cs_dsp_power_up(priv->dsp, wmfw, "wmfw", NULL, NULL, "misc"),
0);
cs_dsp_power_down(priv->dsp);
/* Sanity-check that the good wmfw loads ok */
KUNIT_EXPECT_EQ(test,
cs_dsp_power_up(priv->dsp, wmfw, "wmfw", NULL, NULL, "misc"),
0);
cs_dsp_power_down(priv->dsp);
/* Sanity check we're pointing at the alg header */
KUNIT_ASSERT_EQ(test, le32_to_cpu(alg_data->id), cs_dsp_wmfw_err_test_mock_algs[0].id);
KUNIT_ASSERT_EQ(test, le32_to_cpu(alg_data->ncoeff), 1);
coeff = (void *)alg_data->data;
/* Write a string to the coeff name that overflows the array */
memset(coeff->descr, 0, sizeof(coeff->descr));
memset(coeff->name, 'A', sizeof(coeff->name));
memset(coeff->descr, 'A', sizeof(coeff->descr) - 1);
/* * Sanity-check that a strlen would overflow coeff->name. * FORTIFY_STRING obstructs testing what strlen() would actually * return, so instead verify that a strnlen() returns * sizeof(coeff->name[]), therefore it doesn't have a NUL.
*/
KUNIT_ASSERT_EQ(test, strnlen(coeff->name, sizeof(coeff->name)), sizeof(coeff->name));
/* * V1 controls do not have names, but cs_dsp parses the name * field. It should load the file successfully and create the * control. * If FORTIFY_STRING is enabled it will detect a buffer overflow * if cs_dsp string length walks past end of coeff name array.
*/
KUNIT_EXPECT_EQ(test,
cs_dsp_power_up(priv->dsp, wmfw, "mock_wmfw", NULL, NULL, "misc"),
0);
ctl = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
KUNIT_ASSERT_NOT_NULL(test, ctl);
KUNIT_EXPECT_EQ(test, ctl->subname_len, 0);
}
/* Sanity-check that the good wmfw loads ok */
KUNIT_EXPECT_EQ(test,
cs_dsp_power_up(priv->dsp, wmfw, "wmfw", NULL, NULL, "misc"),
0);
cs_dsp_power_down(priv->dsp);
/* Sanity-check that the good wmfw loads ok */
KUNIT_EXPECT_EQ(test,
cs_dsp_power_up(priv->dsp, wmfw, "wmfw", NULL, NULL, "misc"),
0);
cs_dsp_power_down(priv->dsp);
/* Sanity check we're pointing at the alg header */
KUNIT_ASSERT_EQ(test, le32_to_cpu(alg_data[0]), cs_dsp_wmfw_err_test_mock_algs[0].id);
/* Sanity check we're pointing at the coeff block */
coeff = (__force __le32 *)&alg_data[4];
KUNIT_ASSERT_EQ(test, le32_to_cpu(coeff[0]), mock_coeff_template.mem_type << 16);
/* Fullname follows the shortname rounded up to a __le32 boundary */
shortlen = round_up(le32_to_cpu(coeff[2]) & 0xff, sizeof(__le32));
fullname = &coeff[2] + (shortlen / sizeof(*coeff));
/* Fullname increases in blocks of __le32 so increase past the current __le32 */
fullname[0] = cpu_to_le32(round_up(le32_to_cpu(fullname[0]) + 1, sizeof(__le32)));
KUNIT_EXPECT_EQ(test,
cs_dsp_power_up(priv->dsp, wmfw, "mock_wmfw", NULL, NULL, "misc"),
-EOVERFLOW);
/* Sanity-check that the good wmfw loads ok */
KUNIT_EXPECT_EQ(test,
cs_dsp_power_up(priv->dsp, wmfw, "wmfw", NULL, NULL, "misc"),
0);
cs_dsp_power_down(priv->dsp);
/* Sanity check we're pointing at the alg header */
KUNIT_ASSERT_EQ(test, le32_to_cpu(alg_data[0]), cs_dsp_wmfw_err_test_mock_algs[0].id);
/* Sanity check we're pointing at the coeff block */
coeff = (__force __le32 *)&alg_data[4];
KUNIT_ASSERT_EQ(test, le32_to_cpu(coeff[0]), mock_coeff_template.mem_type << 16);
/* Description follows the shortname and fullname rounded up to __le32 boundaries */
namelen = round_up(le32_to_cpu(coeff[2]) & 0xff, sizeof(__le32));
fullname = &coeff[2] + (namelen / sizeof(*coeff));
namelen = round_up(le32_to_cpu(fullname[0]) & 0xff, sizeof(__le32));
description = fullname + (namelen / sizeof(*fullname));
/* Description increases in blocks of __le32 so increase past the current __le32 */
description[0] = cpu_to_le32(round_up(le32_to_cpu(fullname[0]) + 1, sizeof(__le32)));
KUNIT_EXPECT_EQ(test,
cs_dsp_power_up(priv->dsp, wmfw, "mock_wmfw", NULL, NULL, "misc"),
-EOVERFLOW);
staticvoid cs_dsp_wmfw_err_test_exit(struct kunit *test)
{ /* * Testing error conditions can produce a lot of log output * from cs_dsp error messages, so rate limit the test cases.
*/
usleep_range(200, 500);
}
dsp->dev = get_device(test_dev); if (!dsp->dev) return -ENODEV;
ret = kunit_add_action_or_reset(test, _put_device_wrapper, dsp->dev); if (ret) return ret;
dev_set_drvdata(dsp->dev, priv);
/* Allocate regmap */
ret = cs_dsp_mock_regmap_init(priv); if (ret) return ret;
/* * There must always be a XM header with at least 1 algorithm, * so create a dummy one and pre-populate XM so the wmfw doesn't * have to contain an XM blob.
*/
local->xm_header = cs_dsp_create_mock_xm_header(priv,
cs_dsp_wmfw_err_test_mock_algs,
ARRAY_SIZE(cs_dsp_wmfw_err_test_mock_algs));
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, local->xm_header);
cs_dsp_mock_xm_header_write_to_regmap(local->xm_header);
switch (dsp->type) { case WMFW_ADSP2:
ret = cs_dsp_adsp2_init(dsp); break; case WMFW_HALO:
ret = cs_dsp_halo_init(dsp); break; default:
KUNIT_FAIL(test, "Untested DSP type %d\n", dsp->type); return -EINVAL;
}
if (ret) return ret;
/* Automatically call cs_dsp_remove() when test case ends */ return kunit_add_action_or_reset(priv->test, _cs_dsp_remove_wrapper, dsp);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.