summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarco Chen <marcochen@google.com>2020-08-10 12:19:10 +0800
committerCommit Bot <commit-bot@chromium.org>2021-09-08 05:56:23 +0000
commite29c2299d9b09815d973cc5f289ecb4a0cd4a770 (patch)
treefe28a87b7bead1ef8503dcd562812eadf56bc45f
parent925482a25807aafd3b5e9c3d143c07d19c12b633 (diff)
downloadchrome-ec-e29c2299d9b09815d973cc5f289ecb4a0cd4a770.tar.gz
cbi: add Second Source Factory Cache (SSFC) CBI field
SSFC field will be leveraged to record what second source is used in the DUT by probing components in the factory or RMA. Firmware code should refer to this field to judge what driver should be configured for a specific component. For example, the board code can arrange what sensor driver should be set into motion_sensors array if there are multiple sources of base or lid sensor. As the definition of FW_CONFIG, it describe which "features" the firmware code should enable or disable. For example, whether lid / base sensors should be enabled or not but not care about what second source is in this DUT. BRANCH=none BUG=b:197005105 TEST= make BOARD=rammus TEST= Run command "ectool cbi set 8 0x10 4" TEST= Run command "ectool cbi get 8" Change-Id: Icb4aa00ae47ab025198e7fd5edd6aab96a4bf53e Signed-off-by: Marco Chen <marcochen@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2344268 Reviewed-by: Daisuke Nojiri <dnojiri@chromium.org> Reviewed-by: Jett Rink <jettrink@chromium.org> Commit-Queue: Jett Rink <jettrink@chromium.org> (cherry picked from commit 0212d4a3ce01452ddaba46f076f90e9a5e90e589) Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3128387 Reviewed-by: Michael5 Chen <michael5_chen1@pegatron.corp-partner.google.com> Tested-by: Michael5 Chen <michael5_chen1@pegatron.corp-partner.google.com> Commit-Queue: Zhuohao Lee <zhuohao@chromium.org>
-rw-r--r--common/cbi.c34
-rw-r--r--include/cros_board_info.h7
-rw-r--r--include/ec_commands.h5
-rw-r--r--test/cbi.c199
-rw-r--r--util/cbi-util.c53
-rw-r--r--util/ectool.c36
6 files changed, 317 insertions, 17 deletions
diff --git a/common/cbi.c b/common/cbi.c
index f37d6950b1..a6dd13443d 100644
--- a/common/cbi.c
+++ b/common/cbi.c
@@ -253,6 +253,37 @@ int cbi_get_oem_id(uint32_t *id)
return cbi_get_board_info(CBI_TAG_OEM_ID, (uint8_t *)id, &size);
}
+int cbi_get_model_id(uint32_t *id)
+{
+ uint8_t size = sizeof(*id);
+
+ return cbi_get_board_info(CBI_TAG_MODEL_ID, (uint8_t *)id, &size);
+}
+
+int cbi_get_fw_config(uint32_t *fw_config)
+{
+ uint8_t size = sizeof(*fw_config);
+
+ return cbi_get_board_info(CBI_TAG_FW_CONFIG, (uint8_t *)fw_config,
+ &size);
+}
+
+int cbi_get_ssfc(uint32_t *ssfc)
+{
+ uint8_t size = sizeof(*ssfc);
+
+ return cbi_get_board_info(CBI_TAG_SSFC, (uint8_t *)ssfc,
+ &size);
+}
+
+int cbi_get_pcb_supplier(uint32_t *pcb_supplier)
+{
+ uint8_t size = sizeof(*pcb_supplier);
+
+ return cbi_get_board_info(CBI_TAG_PCB_SUPPLIER, (uint8_t *)pcb_supplier,
+ &size);
+}
+
static int hc_cbi_get(struct host_cmd_handler_args *args)
{
const struct __ec_align4 ec_params_get_cbi *p = args->params;
@@ -368,6 +399,9 @@ static void dump_cbi(void)
print_tag("BOARD_VERSION", cbi_get_board_version(&val), &val);
print_tag("OEM_ID", cbi_get_oem_id(&val), &val);
print_tag("SKU_ID", cbi_get_sku_id(&val), &val);
+ print_tag("FW_CONFIG", cbi_get_fw_config(&val), &val);
+ print_tag("PCB_SUPPLIER", cbi_get_pcb_supplier(&val), &val);
+ print_tag("SSFC", cbi_get_ssfc(&val), &val);
}
static int cc_cbi(int argc, char **argv)
diff --git a/include/cros_board_info.h b/include/cros_board_info.h
index 23063d2766..ca5dc34d0a 100644
--- a/include/cros_board_info.h
+++ b/include/cros_board_info.h
@@ -44,12 +44,17 @@ struct cbi_data {
/**
* Board info accessors
*
- * @param version/sku_id/oem_id [OUT] Data read from EEPROM
+ * @param version/sku_id/oem_id/id/fw_config/pcb_supplier/ssfc [OUT] Data read
+ * from EEPROM
* @return EC_SUCCESS on success or EC_ERROR_* otherwise.
*/
int cbi_get_board_version(uint32_t *version);
int cbi_get_sku_id(uint32_t *sku_id);
int cbi_get_oem_id(uint32_t *oem_id);
+int cbi_get_model_id(uint32_t *id);
+int cbi_get_fw_config(uint32_t *fw_config);
+int cbi_get_pcb_supplier(uint32_t *pcb_supplier);
+int cbi_get_ssfc(uint32_t *ssfc);
/**
* Primitive accessors
diff --git a/include/ec_commands.h b/include/ec_commands.h
index ca0660e5f5..6d99bb54a1 100644
--- a/include/ec_commands.h
+++ b/include/ec_commands.h
@@ -4947,6 +4947,11 @@ enum cbi_data_tag {
CBI_TAG_SKU_ID = 2, /* uint8_t */
CBI_TAG_DRAM_PART_NUM = 3, /* variable length ascii, nul terminated. */
CBI_TAG_OEM_NAME = 4, /* variable length ascii, nul terminated. */
+ CBI_TAG_MODEL_ID = 5, /* uint32_t or smaller */
+ CBI_TAG_FW_CONFIG = 6, /* uint32_t bit field */
+ CBI_TAG_PCB_SUPPLIER = 7, /* uint32_t or smaller */
+ /* Second Source Factory Cache */
+ CBI_TAG_SSFC = 8, /* uint32_t bit field */
CBI_TAG_COUNT,
};
diff --git a/test/cbi.c b/test/cbi.c
new file mode 100644
index 0000000000..936dc204b8
--- /dev/null
+++ b/test/cbi.c
@@ -0,0 +1,199 @@
+/* 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_set_board_info(CBI_TAG_SSFC, &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");
+ TEST_ASSERT(cbi_get_ssfc(&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/util/cbi-util.c b/util/cbi-util.c
index aa8e5dd325..108b82da7f 100644
--- a/util/cbi-util.c
+++ b/util/cbi-util.c
@@ -37,6 +37,10 @@ enum {
OPT_SKU_ID,
OPT_DRAM_PART_NUM,
OPT_OEM_NAME,
+ OPT_MODEL_ID,
+ OPT_FW_CONFIG,
+ OPT_PCB_SUPPLIER,
+ OPT_SSFC,
OPT_SIZE,
OPT_ERASE_BYTE,
OPT_SHOW_ALL,
@@ -50,6 +54,10 @@ static const struct option opts_create[] = {
{"sku_id", 1, 0, OPT_SKU_ID},
{"dram_part_num", 1, 0, OPT_DRAM_PART_NUM},
{"oem_name", 1, 0, OPT_OEM_NAME},
+ {"model_id", 1, 0, OPT_MODEL_ID},
+ {"fw_config", 1, 0, OPT_FW_CONFIG},
+ {"pcb_supplier", 1, 0, OPT_PCB_SUPPLIER},
+ {"ssfc", 1, 0, OPT_SSFC},
{"size", 1, 0, OPT_SIZE},
{"erase_byte", 1, 0, OPT_ERASE_BYTE},
{NULL, 0, 0, 0}
@@ -67,7 +75,11 @@ static const char *field_name[] = {
"OEM_ID",
"SKU_ID",
"DRAM_PART_NUM",
- "OEM_NAME"
+ "OEM_NAME",
+ "MODEL_ID",
+ "FW_CONFIG",
+ "PCB_SUPPLIER",
+ "SSFC",
};
BUILD_ASSERT(ARRAY_SIZE(field_name) == CBI_TAG_COUNT);
@@ -89,6 +101,15 @@ const char help_create[] =
" --oem_name <value> OEM NAME\n"
" --erase_byte <uint8> Byte used for empty space. Default:0xff\n"
" --format_version <uint16> Data format version\n"
+ " --model_id <value> Model ID\n"
+ " --fw_config <value> Firmware configuration bit-field\n"
+ " --pcb_supplier <value> PCB supplier\n"
+ " --ssfc <value> Second Source Factory Cache bit-field\n"
+ "\n"
+ "<value> must be a positive integer <= 0XFFFFFFFF and field size can\n"
+ " be optionally specified by <value:size> notation: e.g. 0xabcd:4.\n"
+ "<size> must be a positive integer <= 0XFFFF.\n"
+ "<string> is a string\n"
"\n";
const char help_show[] =
@@ -240,6 +261,10 @@ static int cmd_create(int argc, char **argv)
struct integer_field ver;
struct integer_field oem;
struct integer_field sku;
+ struct integer_field model;
+ struct integer_field fw_config;
+ struct integer_field pcb_supplier;
+ struct integer_field ssfc;
const char *dram_part_num;
const char *oem_name;
} bi;
@@ -305,6 +330,22 @@ static int cmd_create(int argc, char **argv)
case OPT_OEM_NAME:
bi.oem_name = optarg;
break;
+ case OPT_MODEL_ID:
+ if (parse_integer_field(optarg, &bi.model))
+ return -1;
+ break;
+ case OPT_FW_CONFIG:
+ if (parse_integer_field(optarg, &bi.fw_config))
+ return -1;
+ break;
+ case OPT_PCB_SUPPLIER:
+ if (parse_integer_field(optarg, &bi.pcb_supplier))
+ return -1;
+ break;
+ case OPT_SSFC:
+ if (parse_integer_field(optarg, &bi.ssfc))
+ return -1;
+ break;
}
}
@@ -338,6 +379,12 @@ static int cmd_create(int argc, char **argv)
p = cbi_set_data(p, CBI_TAG_OEM_NAME, bi.oem_name,
strlen(bi.oem_name) + 1);
}
+ p = cbi_set_data(p, CBI_TAG_MODEL_ID, &bi.model.val, bi.model.size);
+ p = cbi_set_data(p, CBI_TAG_FW_CONFIG, &bi.fw_config.val,
+ bi.fw_config.size);
+ p = cbi_set_data(p, CBI_TAG_PCB_SUPPLIER, &bi.pcb_supplier.val,
+ bi.pcb_supplier.size);
+ p = cbi_set_data(p, CBI_TAG_SSFC, &bi.ssfc.val, bi.ssfc.size);
h->total_size = p - cbi;
h->crc = cbi_crc8(h);
@@ -458,6 +505,10 @@ static int cmd_show(int argc, char **argv)
print_integer(buf, CBI_TAG_BOARD_VERSION);
print_integer(buf, CBI_TAG_OEM_ID);
print_integer(buf, CBI_TAG_SKU_ID);
+ print_integer(buf, CBI_TAG_MODEL_ID);
+ print_integer(buf, CBI_TAG_FW_CONFIG);
+ print_integer(buf, CBI_TAG_PCB_SUPPLIER);
+ print_integer(buf, CBI_TAG_SSFC);
print_string(buf, CBI_TAG_DRAM_PART_NUM);
print_string(buf, CBI_TAG_OEM_NAME);
diff --git a/util/ectool.c b/util/ectool.c
index 63833eb6da..5b004d62dd 100644
--- a/util/ectool.c
+++ b/util/ectool.c
@@ -6808,21 +6808,27 @@ int cmd_board_version(int argc, char *argv[])
static void cmd_cbi_help(char *cmd)
{
fprintf(stderr,
- " Usage: %s get <type> [get_flag]\n"
- " Usage: %s set <type> <value> <size> [set_flag]\n"
- " <type> is one of:\n"
- " 0: BOARD_VERSION\n"
- " 1: OEM_ID\n"
- " 2: SKU_ID\n"
- " 3: DRAM_PART_NUM\n"
- " 4: OEM_NAME\n"
- " <size> is the size of the data in byte\n"
- " <value> is integer to be set, string for DRAM_PART_NUM/OEM_NAME\n"
- " [get_flag] is combination of:\n"
- " 01b: Invalidate cache and reload data from EEPROM\n"
- " [set_flag] is combination of:\n"
- " 01b: Skip write to EEPROM. Use for back-to-back writes\n"
- " 10b: Set all fields to defaults first\n", cmd, cmd);
+ " Usage: %s get <tag> [get_flag]\n"
+ " Usage: %s set <tag> <value/string> <size> [set_flag]\n"
+ " Usage: %s remove <tag> [set_flag]\n"
+ " <tag> is one of:\n"
+ " 0: BOARD_VERSION\n"
+ " 1: OEM_ID\n"
+ " 2: SKU_ID\n"
+ " 3: DRAM_PART_NUM (string)\n"
+ " 4: OEM_NAME (string)\n"
+ " 5: MODEL_ID\n"
+ " 6: FW_CONFIG\n"
+ " 7: PCB_VENDOR\n"
+ " 8: SSFC\n"
+ " <size> is the size of the data in byte. It should be zero for\n"
+ " string types.\n"
+ " <value/string> is an integer or a string to be set\n"
+ " [get_flag] is combination of:\n"
+ " 01b: Invalidate cache and reload data from EEPROM\n"
+ " [set_flag] is combination of:\n"
+ " 01b: Skip write to EEPROM. Use for back-to-back writes\n"
+ " 10b: Set all fields to defaults first\n", cmd, cmd, cmd);
}
/*