CBI: Add unit test
This patch adds unit tests for Cros Board Info APIs. BUG=b:163038871 BRANCH=none TEST=buildall Signed-off-by: Daisuke Nojiri <dnojiri@chromium.org> Change-Id: I7b2fdb2c4f13da12f8c0dc2ab526332cbd46d849 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2339393
This commit is contained in:
parent
1c62421d79
commit
b29d0808e2
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "battery.h"
|
||||
#include "button.h"
|
||||
#include "cros_board_info.h"
|
||||
#include "extpower.h"
|
||||
#include "gpio.h"
|
||||
#include "host_command.h"
|
||||
|
@ -17,6 +18,7 @@
|
|||
#include "power_button.h"
|
||||
#include "spi.h"
|
||||
#include "temp_sensor.h"
|
||||
#include "test_util.h"
|
||||
#include "timer.h"
|
||||
#include "util.h"
|
||||
|
||||
|
@ -65,6 +67,8 @@ const struct i2c_port_t i2c_ports[] = {
|
|||
{"lightbar", I2C_PORT_LIGHTBAR, 100, 0, 0},
|
||||
#elif defined I2C_PORT_HOST_TCPC
|
||||
{"tcpc", I2C_PORT_HOST_TCPC, 100, 0, 0},
|
||||
#elif defined I2C_PORT_EEPROM
|
||||
{"eeprom", I2C_PORT_EEPROM, 100, 0, 0},
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -97,3 +101,32 @@ int board_get_entropy(void *buffer, int len)
|
|||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
static uint8_t eeprom[CBI_EEPROM_SIZE];
|
||||
|
||||
int eeprom_i2c_xfer(int port, uint16_t addr_flags,
|
||||
const uint8_t *out, int out_size,
|
||||
uint8_t *in, int in_size, int flags)
|
||||
{
|
||||
static int offset;
|
||||
|
||||
if (port != I2C_PORT_EEPROM || addr_flags != I2C_ADDR_EEPROM_FLAGS)
|
||||
return EC_ERROR_INVAL;
|
||||
|
||||
if (out_size == 1 && (flags & I2C_XFER_START)) {
|
||||
offset = *out;
|
||||
} else {
|
||||
if (offset + out_size > sizeof(eeprom))
|
||||
return EC_ERROR_OVERFLOW;
|
||||
memcpy(&eeprom[offset], out, out_size);
|
||||
}
|
||||
|
||||
if (in) {
|
||||
if (offset + in_size > sizeof(eeprom))
|
||||
return EC_ERROR_OVERFLOW;
|
||||
memcpy(in, &eeprom[offset], in_size);
|
||||
}
|
||||
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
DECLARE_TEST_I2C_XFER(eeprom_i2c_xfer);
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
/* Default-yes, override to no by including fake_battery module. */
|
||||
#define CONFIG_BATTERY_PRESENT_CUSTOM
|
||||
#undef CONFIG_CMD_PD
|
||||
#define CONFIG_CROS_BOARD_INFO
|
||||
#define CONFIG_EXTPOWER_GPIO
|
||||
#undef CONFIG_FMAP
|
||||
#define CONFIG_POWER_BUTTON
|
||||
|
@ -86,4 +87,11 @@ enum {
|
|||
#define CONFIG_RNG
|
||||
void fps_event(enum gpio_signal signal);
|
||||
|
||||
#define CONFIG_CRC8
|
||||
|
||||
#define CONFIG_I2C
|
||||
#define CONFIG_I2C_MASTER
|
||||
#define I2C_PORT_EEPROM 0
|
||||
#define I2C_ADDR_EEPROM_FLAGS 0x50
|
||||
|
||||
#endif /* __CROS_EC_BOARD_H */
|
||||
|
|
31
common/cbi.c
31
common/cbi.c
|
@ -57,12 +57,12 @@ uint8_t *cbi_set_string(uint8_t *p, enum cbi_data_tag tag, const char *str)
|
|||
return cbi_set_data(p, tag, str, strlen(str) + 1);
|
||||
}
|
||||
|
||||
struct cbi_data *cbi_find_tag(const void *cbi, enum cbi_data_tag tag)
|
||||
struct cbi_data *cbi_find_tag(const void *buf, enum cbi_data_tag tag)
|
||||
{
|
||||
struct cbi_data *d;
|
||||
const struct cbi_header *h = cbi;
|
||||
const struct cbi_header *h = buf;
|
||||
const uint8_t *p;
|
||||
for (p = h->data; p + sizeof(*d) < (uint8_t *)cbi + h->total_size;) {
|
||||
for (p = h->data; p + sizeof(*d) < (uint8_t *)buf + h->total_size;) {
|
||||
d = (struct cbi_data *)p;
|
||||
if (d->tag == tag)
|
||||
return d;
|
||||
|
@ -92,6 +92,26 @@ static int cached_read_result = EC_ERROR_CBI_CACHE_INVALID;
|
|||
static uint8_t cbi[CBI_EEPROM_SIZE];
|
||||
static struct cbi_header * const head = (struct cbi_header *)cbi;
|
||||
|
||||
int cbi_create(void)
|
||||
{
|
||||
struct cbi_header * const h = (struct cbi_header *)cbi;
|
||||
|
||||
memset(cbi, 0, sizeof(cbi));
|
||||
memcpy(h->magic, cbi_magic, sizeof(cbi_magic));
|
||||
h->total_size = sizeof(*h);
|
||||
h->major_version = CBI_VERSION_MAJOR;
|
||||
h->minor_version = CBI_VERSION_MINOR;
|
||||
h->crc = cbi_crc8(h);
|
||||
cached_read_result = EC_SUCCESS;
|
||||
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
void cbi_invalidate_cache(void)
|
||||
{
|
||||
cached_read_result = EC_ERROR_CBI_CACHE_INVALID;
|
||||
}
|
||||
|
||||
static int read_eeprom(uint8_t offset, uint8_t *in, int in_size)
|
||||
{
|
||||
return i2c_read_block(I2C_PORT_EEPROM, I2C_ADDR_EEPROM_FLAGS,
|
||||
|
@ -266,6 +286,11 @@ static int write_board_info(void)
|
|||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
int cbi_write(void)
|
||||
{
|
||||
return write_board_info();
|
||||
}
|
||||
|
||||
int cbi_get_board_version(uint32_t *ver)
|
||||
{
|
||||
uint8_t size = sizeof(*ver);
|
||||
|
|
|
@ -144,4 +144,13 @@ struct cbi_data *cbi_find_tag(const void *cbi, enum cbi_data_tag tag);
|
|||
*/
|
||||
int cbi_board_override(enum cbi_data_tag tag, uint8_t *buf, uint8_t *size);
|
||||
|
||||
#ifdef TEST_BUILD
|
||||
/**
|
||||
* Test only declarations. Firmware shouldn't need them.
|
||||
*/
|
||||
int cbi_create(void);
|
||||
int cbi_write(void);
|
||||
void cbi_invalidate_cache(void);
|
||||
#endif
|
||||
|
||||
#endif /* __CROS_EC_CROS_BOARD_INFO_H */
|
||||
|
|
|
@ -18,6 +18,7 @@ test-list-host += battery_get_params_smart
|
|||
test-list-host += bklight_lid
|
||||
test-list-host += bklight_passthru
|
||||
test-list-host += button
|
||||
test-list-host += cbi
|
||||
test-list-host += cec
|
||||
test-list-host += charge_manager
|
||||
test-list-host += charge_manager_drp_charging
|
||||
|
@ -121,6 +122,7 @@ battery_get_params_smart-y=battery_get_params_smart.o
|
|||
bklight_lid-y=bklight_lid.o
|
||||
bklight_passthru-y=bklight_passthru.o
|
||||
button-y=button.o
|
||||
cbi-y=cbi.o
|
||||
cec-y=cec.o
|
||||
charge_manager-y=charge_manager.o
|
||||
charge_manager_drp_charging-y=charge_manager.o
|
||||
|
|
|
@ -0,0 +1,195 @@
|
|||
/* Copyright 2020 The Chromium OS Authors. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*
|
||||
* Test CBI
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
#include "console.h"
|
||||
#include "cros_board_info.h"
|
||||
#include "gpio.h"
|
||||
#include "i2c.h"
|
||||
#include "test_util.h"
|
||||
#include "util.h"
|
||||
|
||||
void before_test(void)
|
||||
{
|
||||
cbi_create();
|
||||
cbi_write();
|
||||
}
|
||||
|
||||
static int test_uint8(void)
|
||||
{
|
||||
uint8_t d8;
|
||||
uint32_t d32;
|
||||
uint8_t size;
|
||||
const int tag = 0xff;
|
||||
|
||||
/* Set & get uint8_t */
|
||||
d8 = 0xa5;
|
||||
TEST_ASSERT(cbi_set_board_info(tag, &d8, sizeof(d8)) == EC_SUCCESS);
|
||||
size = 1;
|
||||
TEST_ASSERT(cbi_get_board_info(tag, &d8, &size) == EC_SUCCESS);
|
||||
TEST_EQ(d8, 0xa5, "0x%x");
|
||||
TEST_EQ(size, 1, "%x");
|
||||
|
||||
/* Size-up */
|
||||
d32 = 0x1234abcd;
|
||||
TEST_ASSERT(cbi_set_board_info(tag, (void *)&d32, sizeof(d32))
|
||||
== EC_SUCCESS);
|
||||
size = 4;
|
||||
TEST_ASSERT(cbi_get_board_info(tag, (void *)&d32, &size) == EC_SUCCESS);
|
||||
TEST_EQ(d32, 0x1234abcd, "0x%x");
|
||||
TEST_EQ(size, 4, "%u");
|
||||
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
static int test_uint32(void)
|
||||
{
|
||||
uint8_t d8;
|
||||
uint32_t d32;
|
||||
uint8_t size;
|
||||
const int tag = 0xff;
|
||||
|
||||
/* Set & get uint32_t */
|
||||
d32 = 0x1234abcd;
|
||||
TEST_ASSERT(cbi_set_board_info(tag, (void *)&d32, sizeof(d32))
|
||||
== EC_SUCCESS);
|
||||
size = 4;
|
||||
TEST_ASSERT(cbi_get_board_info(tag, (void *)&d32, &size) == EC_SUCCESS);
|
||||
TEST_EQ(d32, 0x1234abcd, "0x%x");
|
||||
TEST_EQ(size, 4, "%u");
|
||||
|
||||
/* Size-down */
|
||||
d8 = 0xa5;
|
||||
TEST_ASSERT(cbi_set_board_info(tag, &d8, sizeof(d8)) == EC_SUCCESS);
|
||||
size = 1;
|
||||
TEST_ASSERT(cbi_get_board_info(tag, &d8, &size) == EC_SUCCESS);
|
||||
TEST_EQ(d8, 0xa5, "0x%x");
|
||||
TEST_EQ(size, 1, "%u");
|
||||
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
static int test_string(void)
|
||||
{
|
||||
const uint8_t string[] = "abcdefghijklmn";
|
||||
uint8_t buf[32];
|
||||
uint8_t size;
|
||||
const int tag = 0xff;
|
||||
|
||||
/* Set & get string */
|
||||
TEST_ASSERT(cbi_set_board_info(tag, string, sizeof(string))
|
||||
== EC_SUCCESS);
|
||||
size = sizeof(buf);
|
||||
TEST_ASSERT(cbi_get_board_info(tag, buf, &size) == EC_SUCCESS);
|
||||
TEST_ASSERT(strncmp(buf, string, sizeof(string)) == 0);
|
||||
/* Size contains null byte */
|
||||
TEST_EQ((size_t)size - 1, strlen(buf), "%zu");
|
||||
|
||||
/* Read buffer too small */
|
||||
size = 4;
|
||||
TEST_ASSERT(cbi_get_board_info(tag, buf, &size) == EC_ERROR_INVAL);
|
||||
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
static int test_not_found(void)
|
||||
{
|
||||
uint8_t d8;
|
||||
const int tag = 0xff;
|
||||
uint8_t size;
|
||||
|
||||
size = 1;
|
||||
TEST_ASSERT(cbi_get_board_info(tag, &d8, &size) == EC_ERROR_UNKNOWN);
|
||||
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
static int test_too_large(void)
|
||||
{
|
||||
uint8_t buf[CBI_EEPROM_SIZE-1];
|
||||
const int tag = 0xff;
|
||||
|
||||
/* Data too large */
|
||||
memset(buf, 0xa5, sizeof(buf));
|
||||
TEST_ASSERT(cbi_set_board_info(tag, buf, sizeof(buf))
|
||||
== EC_ERROR_OVERFLOW);
|
||||
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
static int test_all_tags(void)
|
||||
{
|
||||
uint8_t d8;
|
||||
uint32_t d32;
|
||||
|
||||
/* Populate all data and read out */
|
||||
d8 = 0x12;
|
||||
TEST_ASSERT(cbi_set_board_info(CBI_TAG_BOARD_VERSION, &d8, sizeof(d8))
|
||||
== EC_SUCCESS);
|
||||
TEST_ASSERT(cbi_set_board_info(CBI_TAG_OEM_ID, &d8, sizeof(d8))
|
||||
== EC_SUCCESS);
|
||||
TEST_ASSERT(cbi_set_board_info(CBI_TAG_SKU_ID, &d8, sizeof(d8))
|
||||
== EC_SUCCESS);
|
||||
TEST_ASSERT(cbi_set_board_info(CBI_TAG_MODEL_ID, &d8, sizeof(d8))
|
||||
== EC_SUCCESS);
|
||||
TEST_ASSERT(cbi_set_board_info(CBI_TAG_FW_CONFIG, &d8, sizeof(d8))
|
||||
== EC_SUCCESS);
|
||||
TEST_ASSERT(cbi_set_board_info(CBI_TAG_PCB_SUPPLIER, &d8, sizeof(d8))
|
||||
== EC_SUCCESS);
|
||||
TEST_ASSERT(cbi_get_board_version(&d32) == EC_SUCCESS);
|
||||
TEST_EQ(d32, d8, "0x%x");
|
||||
TEST_ASSERT(cbi_get_oem_id(&d32) == EC_SUCCESS);
|
||||
TEST_EQ(d32, d8, "0x%x");
|
||||
TEST_ASSERT(cbi_get_sku_id(&d32) == EC_SUCCESS);
|
||||
TEST_EQ(d32, d8, "0x%x");
|
||||
TEST_ASSERT(cbi_get_model_id(&d32) == EC_SUCCESS);
|
||||
TEST_EQ(d32, d8, "0x%x");
|
||||
TEST_ASSERT(cbi_get_fw_config(&d32) == EC_SUCCESS);
|
||||
TEST_EQ(d32, d8, "0x%x");
|
||||
TEST_ASSERT(cbi_get_pcb_supplier(&d32) == EC_SUCCESS);
|
||||
TEST_EQ(d32, d8, "0x%x");
|
||||
|
||||
/* Write protect */
|
||||
gpio_set_level(GPIO_WP, 1);
|
||||
TEST_ASSERT(cbi_write() == EC_ERROR_ACCESS_DENIED);
|
||||
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
static int test_bad_crc(void)
|
||||
{
|
||||
uint8_t d8;
|
||||
const int tag = 0xff;
|
||||
uint8_t size;
|
||||
int crc;
|
||||
|
||||
/* Bad CRC */
|
||||
d8 = 0xa5;
|
||||
TEST_ASSERT(cbi_set_board_info(tag, &d8, sizeof(d8)) == EC_SUCCESS);
|
||||
i2c_read8(I2C_PORT_EEPROM, I2C_ADDR_EEPROM_FLAGS,
|
||||
offsetof(struct cbi_header, crc), &crc);
|
||||
i2c_write8(I2C_PORT_EEPROM, I2C_ADDR_EEPROM_FLAGS,
|
||||
offsetof(struct cbi_header, crc), ++crc);
|
||||
cbi_invalidate_cache();
|
||||
size = sizeof(d8);
|
||||
TEST_ASSERT(cbi_get_board_info(tag, &d8, &size) == EC_ERROR_UNKNOWN);
|
||||
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
void run_test(int argc, char **argv)
|
||||
{
|
||||
RUN_TEST(test_uint8);
|
||||
RUN_TEST(test_uint32);
|
||||
RUN_TEST(test_string);
|
||||
RUN_TEST(test_not_found);
|
||||
RUN_TEST(test_too_large);
|
||||
RUN_TEST(test_all_tags);
|
||||
RUN_TEST(test_bad_crc);
|
||||
|
||||
test_print_result();
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
/* Copyright 2020 The Chromium OS Authors. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
/**
|
||||
* See CONFIG_TASK_LIST in config.h for details.
|
||||
*/
|
||||
#define CONFIG_TEST_TASK_LIST /* No test task */
|
Loading…
Reference in New Issue