diff options
-rw-r--r-- | board/host/board.c | 33 | ||||
-rw-r--r-- | board/host/board.h | 8 | ||||
-rw-r--r-- | common/cbi.c | 31 | ||||
-rw-r--r-- | include/cros_board_info.h | 9 | ||||
-rw-r--r-- | test/build.mk | 2 | ||||
-rw-r--r-- | test/cbi.c | 195 | ||||
-rw-r--r-- | test/cbi.tasklist | 9 |
7 files changed, 284 insertions, 3 deletions
diff --git a/board/host/board.c b/board/host/board.c index 307ccac991..25abd9a0ad 100644 --- a/board/host/board.c +++ b/board/host/board.c @@ -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); diff --git a/board/host/board.h b/board/host/board.h index 1e5d14476f..0eafedc2bc 100644 --- a/board/host/board.h +++ b/board/host/board.h @@ -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 */ diff --git a/common/cbi.c b/common/cbi.c index 5263407441..6918ad50dd 100644 --- a/common/cbi.c +++ b/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); diff --git a/include/cros_board_info.h b/include/cros_board_info.h index 25330779d5..57839ba4a5 100644 --- a/include/cros_board_info.h +++ b/include/cros_board_info.h @@ -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 */ diff --git a/test/build.mk b/test/build.mk index 9f2e1eec33..c8fea42660 100644 --- a/test/build.mk +++ b/test/build.mk @@ -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 diff --git a/test/cbi.c b/test/cbi.c new file mode 100644 index 0000000000..df57febb6f --- /dev/null +++ b/test/cbi.c @@ -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(); +} diff --git a/test/cbi.tasklist b/test/cbi.tasklist new file mode 100644 index 0000000000..52c0d390ef --- /dev/null +++ b/test/cbi.tasklist @@ -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 */ |