summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKarthikeyan Ramasubramanian <kramasub@chromium.org>2019-06-12 11:30:49 -0600
committerCommit Bot <commit-bot@chromium.org>2019-08-23 00:12:31 +0000
commit402649748ac71d4fcc67d3b6e387acc1e71b0922 (patch)
tree171f65127d5a82badef5626ef481d5239504c4b9
parentee8d481a027b78796ce30a48224e043fdf5f7491 (diff)
downloadchrome-ec-402649748ac71d4fcc67d3b6e387acc1e71b0922.tar.gz
ec_commands: Rename 'renew' to 'live' in EC_CMD_USB_PD_CHIP_INFO
Semantics of renew field in EC_CMD_USB_PD_CHIP_INFO is changing as follows: 0 -> Return hard-coded info for Vendor ID/Product ID and cached info for the Firmware Version 1 -> Return the live chip info for Vendor ID/Product ID/Firmware Version Also rename the 'renew' field to 'live' to match the new semantics. BUG=b:128820536,b:119046668 BRANCH=None TEST=make -j buildall; Boot to ChromeOS. Change-Id: Ie3dd022336b0be5c9728bb0ebabef32b7a6b5d57 Signed-off-by: Karthikeyan Ramasubramanian <kramasub@google.com> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1617893 Tested-by: Karthikeyan Ramasubramanian <kramasub@chromium.org> Reviewed-by: Daisuke Nojiri <dnojiri@chromium.org> Reviewed-by: Diana Z <dzigterman@chromium.org> Commit-Queue: Karthikeyan Ramasubramanian <kramasub@chromium.org> Auto-Submit: Karthikeyan Ramasubramanian <kramasub@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1767526 Reviewed-by: Edward Hill <ecgh@chromium.org> Commit-Queue: Edward Hill <ecgh@chromium.org> Tested-by: Edward Hill <ecgh@chromium.org>
-rw-r--r--common/usb_pd_protocol.c5
-rw-r--r--driver/tcpm/anx74xx.c6
-rw-r--r--driver/tcpm/it83xx.c2
-rw-r--r--driver/tcpm/ps8xxx.c6
-rw-r--r--driver/tcpm/tcpci.c6
-rw-r--r--driver/tcpm/tcpci.h2
-rw-r--r--driver/tcpm/tcpm.h4
-rw-r--r--fuzz/usb_pd_fuzz.c223
-rw-r--r--include/ec_commands.h7
-rw-r--r--include/usb_pd_tcpm.h4
-rw-r--r--util/ectool.c14
11 files changed, 256 insertions, 23 deletions
diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c
index e70c1e6692..b2ece4ac08 100644
--- a/common/usb_pd_protocol.c
+++ b/common/usb_pd_protocol.c
@@ -2697,7 +2697,8 @@ void pd_task(void *u)
if (!res) {
struct ec_response_pd_chip_info_v1 *info;
- if (tcpm_get_chip_info(port, 0, &info) == EC_SUCCESS) {
+ if (tcpm_get_chip_info(port, 0, &info) ==
+ EC_SUCCESS) {
CPRINTS("TCPC p%d VID:0x%x PID:0x%x DID:0x%x FWV:0x%lx",
port, info->vendor_id, info->product_id,
info->device_id, info->fw_version_number);
@@ -5202,7 +5203,7 @@ static int hc_remote_pd_chip_info(struct host_cmd_handler_args *args)
if (p->port >= CONFIG_USB_PD_PORT_COUNT)
return EC_RES_INVALID_PARAM;
- if (tcpm_get_chip_info(p->port, p->renew, &info))
+ if (tcpm_get_chip_info(p->port, p->live, &info))
return EC_RES_ERROR;
/*
diff --git a/driver/tcpm/anx74xx.c b/driver/tcpm/anx74xx.c
index 8bbab47cd0..68045f94bc 100644
--- a/driver/tcpm/anx74xx.c
+++ b/driver/tcpm/anx74xx.c
@@ -1052,17 +1052,17 @@ static int anx74xx_tcpm_init(int port)
return EC_SUCCESS;
}
-static int anx74xx_get_chip_info(int port, int renew,
+static int anx74xx_get_chip_info(int port, int live,
struct ec_response_pd_chip_info_v1 **chip_info)
{
- int rv = tcpci_get_chip_info(port, renew, chip_info);
+ int rv = tcpci_get_chip_info(port, live, chip_info);
int val;
if (rv)
return rv;
if ((*chip_info)->fw_version_number == 0 ||
- (*chip_info)->fw_version_number == -1 || renew) {
+ (*chip_info)->fw_version_number == -1 || live) {
rv = tcpc_read(port, ANX74XX_REG_FW_VERSION, &val);
if (rv)
diff --git a/driver/tcpm/it83xx.c b/driver/tcpm/it83xx.c
index 3f6ae5e0e3..02716f7f90 100644
--- a/driver/tcpm/it83xx.c
+++ b/driver/tcpm/it83xx.c
@@ -552,7 +552,7 @@ static int it83xx_tcpm_transmit(int port,
return EC_SUCCESS;
}
-static int it83xx_tcpm_get_chip_info(int port, int renew,
+static int it83xx_tcpm_get_chip_info(int port, int live,
struct ec_response_pd_chip_info_v1 **chip_info)
{
static struct ec_response_pd_chip_info_v1 i;
diff --git a/driver/tcpm/ps8xxx.c b/driver/tcpm/ps8xxx.c
index 93026f9773..35b76b6abd 100644
--- a/driver/tcpm/ps8xxx.c
+++ b/driver/tcpm/ps8xxx.c
@@ -131,17 +131,17 @@ static int ps8xxx_tcpm_release(int port)
return tcpci_tcpm_release(port);
}
-static int ps8xxx_get_chip_info(int port, int renew,
+static int ps8xxx_get_chip_info(int port, int live,
struct ec_response_pd_chip_info_v1 **chip_info)
{
int val;
- int rv = tcpci_get_chip_info(port, renew, chip_info);
+ int rv = tcpci_get_chip_info(port, live, chip_info);
if (rv)
return rv;
if ((*chip_info)->fw_version_number == 0 ||
- (*chip_info)->fw_version_number == -1 || renew) {
+ (*chip_info)->fw_version_number == -1 || live) {
rv = tcpc_read(port, FW_VER_REG, &val);
if (rv)
diff --git a/driver/tcpm/tcpci.c b/driver/tcpm/tcpci.c
index 882993e599..9a78460fb0 100644
--- a/driver/tcpm/tcpci.c
+++ b/driver/tcpm/tcpci.c
@@ -612,7 +612,7 @@ void tcpci_tcpc_alert(int port)
* Once it's called, the chip info will be stored in cache, which can be
* accessed by tcpm_get_chip_info without worrying about chip states.
*/
-int tcpci_get_chip_info(int port, int renew,
+int tcpci_get_chip_info(int port, int live,
struct ec_response_pd_chip_info_v1 **chip_info)
{
static struct ec_response_pd_chip_info_v1
@@ -631,8 +631,8 @@ int tcpci_get_chip_info(int port, int renew,
if (chip_info)
*chip_info = i;
- /* If already populated and renewal is not asked, return cache value */
- if (i->vendor_id && !renew)
+ /* If already cached && live data is not asked, return cached value */
+ if (i->vendor_id && !live)
return EC_SUCCESS;
error = tcpc_read16(port, TCPC_REG_VENDOR_ID, &val);
diff --git a/driver/tcpm/tcpci.h b/driver/tcpm/tcpci.h
index d0b29b796b..3ef53fc2f1 100644
--- a/driver/tcpm/tcpci.h
+++ b/driver/tcpm/tcpci.h
@@ -155,7 +155,7 @@ int tcpci_tcpm_mux_init(int i2c_addr);
int tcpci_tcpm_mux_set(int i2c_addr, mux_state_t mux_state);
int tcpci_tcpm_mux_get(int i2c_addr, mux_state_t *mux_state);
int tcpci_tcpm_mux_enter_low_power(int port);
-int tcpci_get_chip_info(int port, int renew,
+int tcpci_get_chip_info(int port, int live,
struct ec_response_pd_chip_info_v1 **chip_info);
#ifdef CONFIG_USBC_PPC
int tcpci_tcpm_set_snk_ctrl(int port, int enable);
diff --git a/driver/tcpm/tcpm.h b/driver/tcpm/tcpm.h
index fb67eb315b..9d03f52500 100644
--- a/driver/tcpm/tcpm.h
+++ b/driver/tcpm/tcpm.h
@@ -238,11 +238,11 @@ static inline int tcpc_i2c_write__7bf(const int port, const uint16_t addr__7bf,
}
#endif
-static inline int tcpm_get_chip_info(int port, int renew,
+static inline int tcpm_get_chip_info(int port, int live,
struct ec_response_pd_chip_info_v1 **info)
{
if (tcpc_config[port].drv->get_chip_info)
- return tcpc_config[port].drv->get_chip_info(port, renew, info);
+ return tcpc_config[port].drv->get_chip_info(port, live, info);
return EC_ERROR_UNIMPLEMENTED;
}
diff --git a/fuzz/usb_pd_fuzz.c b/fuzz/usb_pd_fuzz.c
new file mode 100644
index 0000000000..fd2df968c1
--- /dev/null
+++ b/fuzz/usb_pd_fuzz.c
@@ -0,0 +1,223 @@
+/* Copyright 2018 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 USB PD module.
+ */
+#define HIDE_EC_STDLIB
+#include "common.h"
+#include "task.h"
+#include "tcpm.h"
+#include "test_util.h"
+#include "timer.h"
+#include "usb_pd.h"
+#include "usb_pd_tcpm.h"
+#include "util.h"
+
+#include <pthread.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define TASK_EVENT_FUZZ TASK_EVENT_CUSTOM_BIT(0)
+
+#define PORT0 0
+
+static int mock_tcpm_init(int port) { return EC_SUCCESS; }
+static int mock_tcpm_release(int port) { return EC_SUCCESS; }
+
+static int mock_tcpm_select_rp_value(int port, int rp)
+{
+ return EC_SUCCESS;
+}
+
+static int mock_tcpm_set_cc(int port, int pull) { return EC_SUCCESS; }
+static int mock_tcpm_set_polarity(int port, int polarity) { return EC_SUCCESS; }
+static int mock_tcpm_set_vconn(int port, int enable) { return EC_SUCCESS; }
+static int mock_tcpm_set_msg_header(int port,
+ int power_role, int data_role) { return EC_SUCCESS; }
+static int mock_tcpm_set_rx_enable(int port, int enable) { return EC_SUCCESS; }
+static int mock_tcpm_transmit(int port, enum tcpm_transmit_type type,
+ uint16_t header, const uint32_t *data) { return EC_SUCCESS; }
+static void mock_tcpc_alert(int port) {}
+static int mock_tcpci_get_chip_info(int port, int live,
+ struct ec_response_pd_chip_info_v1 **info)
+{
+ return EC_ERROR_UNIMPLEMENTED;
+}
+
+#define MAX_TCPC_PAYLOAD 28
+
+struct message {
+ uint8_t cnt;
+ uint16_t header;
+ uint8_t payload[MAX_TCPC_PAYLOAD];
+} __packed;
+
+struct tcpc_state {
+ enum tcpc_cc_voltage_status cc1, cc2;
+ struct message message;
+};
+
+static struct tcpc_state mock_tcpc_state[CONFIG_USB_PD_PORT_COUNT];
+
+static int mock_tcpm_get_cc(int port, int *cc1, int *cc2)
+{
+ *cc1 = mock_tcpc_state[port].cc1;
+ *cc2 = mock_tcpc_state[port].cc2;
+
+ return EC_SUCCESS;
+}
+
+static int pending;
+
+int tcpm_has_pending_message(const int port)
+{
+ return pending;
+}
+
+int tcpm_dequeue_message(const int port, uint32_t *const payload,
+ int *const header)
+{
+ struct message *m = &mock_tcpc_state[port].message;
+
+ ccprints("%s", __func__);
+
+ /* Force a segfault, if no message is actually pending. */
+ if (pending == 0)
+ m = NULL;
+
+ *header = m->header;
+
+ /*
+ * This mirrors what tcpci.c:tcpm_dequeue_message does: always copy the
+ * whole payload to destination.
+ */
+ memcpy(payload, m->payload, sizeof(m->payload));
+
+ pending--;
+ return EC_SUCCESS;
+}
+
+/* Note this method can be called from an interrupt context. */
+int tcpm_enqueue_message(const int port)
+{
+ pending = 1;
+
+ /* Wake PD task up so it can process incoming RX messages */
+ task_set_event(PD_PORT_TO_TASK_ID(port), TASK_EVENT_WAKE, 0);
+
+ return EC_SUCCESS;
+}
+
+void tcpm_clear_pending_messages(int port) {}
+
+static const struct tcpm_drv mock_tcpm_drv = {
+ .init = &mock_tcpm_init,
+ .release = &mock_tcpm_release,
+ .get_cc = &mock_tcpm_get_cc,
+#ifdef CONFIG_USB_PD_VBUS_DETECT_TCPC
+ .get_vbus_level = &mock_tcpm_get_vbus_level,
+#endif
+ .select_rp_value = &mock_tcpm_select_rp_value,
+ .set_cc = &mock_tcpm_set_cc,
+ .set_polarity = &mock_tcpm_set_polarity,
+ .set_vconn = &mock_tcpm_set_vconn,
+ .set_msg_header = &mock_tcpm_set_msg_header,
+ .set_rx_enable = &mock_tcpm_set_rx_enable,
+ /* The core calls tcpm_dequeue_message. */
+ .get_message_raw = NULL,
+ .transmit = &mock_tcpm_transmit,
+ .tcpc_alert = &mock_tcpc_alert,
+ .get_chip_info = &mock_tcpci_get_chip_info,
+};
+
+/* TCPC mux configuration */
+const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_COUNT] = {
+ {
+ .drv = &mock_tcpm_drv,
+ },
+ {
+ .drv = &mock_tcpm_drv,
+ }
+};
+
+static pthread_cond_t done_cond;
+static pthread_mutex_t lock;
+
+enum tcpc_cc_voltage_status next_cc1, next_cc2;
+const int MAX_MESSAGES = 8;
+static struct message messages[MAX_MESSAGES];
+
+void run_test(void)
+{
+ uint8_t port = PORT0;
+ int i;
+
+ ccprints("Fuzzing task started");
+ wait_for_task_started();
+
+ while (1) {
+ task_wait_event_mask(TASK_EVENT_FUZZ, -1);
+
+ memset(&mock_tcpc_state[port],
+ 0, sizeof(mock_tcpc_state[port]));
+
+ task_set_event(PD_PORT_TO_TASK_ID(port),
+ PD_EVENT_TCPC_RESET, 0);
+ task_wait_event(250 * MSEC);
+
+ mock_tcpc_state[port].cc1 = next_cc1;
+ mock_tcpc_state[port].cc2 = next_cc2;
+
+ task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_CC, 0);
+ task_wait_event(50 * MSEC);
+
+ /* Fake RX messages, one by one. */
+ for (i = 0; i < MAX_MESSAGES && messages[i].cnt; i++) {
+ memcpy(&mock_tcpc_state[port].message, &messages[i],
+ sizeof(messages[i]));
+
+ tcpm_enqueue_message(port);
+ task_wait_event(50 * MSEC);
+ }
+
+ pthread_cond_signal(&done_cond);
+ }
+}
+
+int test_fuzz_one_input(const uint8_t *data, unsigned int size)
+{
+ int i;
+
+ if (size < 1)
+ return 0;
+
+ next_cc1 = data[0] & 0x0f;
+ next_cc2 = (data[0] & 0xf0) >> 4;
+ data++; size--;
+
+ memset(messages, 0, sizeof(messages));
+
+ for (i = 0; i < MAX_MESSAGES && size > 0; i++) {
+ int cnt = data[0];
+
+ if (cnt < 3 || cnt > MAX_TCPC_PAYLOAD+3 || cnt > size) {
+ /* Invalid count, or out of bounds. */
+ return 0;
+ }
+
+ memcpy(&messages[i], data, cnt);
+
+ data += cnt; size -= cnt;
+ }
+
+ if (size != 0) {
+ /* Useless extra data in buffer, skip. */
+ return 0;
+ }
+
+ task_set_event(TASK_ID_TEST_RUNNER, TASK_EVENT_FUZZ, 0);
+ pthread_cond_wait(&done_cond, &lock);
+
+ return 0;
+}
diff --git a/include/ec_commands.h b/include/ec_commands.h
index 2958b8e037..ea06cc1a83 100644
--- a/include/ec_commands.h
+++ b/include/ec_commands.h
@@ -4960,7 +4960,12 @@ struct ec_response_usb_pd_mux_info {
struct ec_params_pd_chip_info {
uint8_t port; /* USB-C port number */
- uint8_t renew; /* Force renewal */
+ /*
+ * Fetch the live chip info or hard-coded + cached chip info
+ * 0: hardcoded value for VID/PID, cached value for FW version
+ * 1: live chip value for VID/PID/FW Version
+ */
+ uint8_t live;
} __ec_align1;
struct ec_response_pd_chip_info {
diff --git a/include/usb_pd_tcpm.h b/include/usb_pd_tcpm.h
index 96f0147390..f2ec7df664 100644
--- a/include/usb_pd_tcpm.h
+++ b/include/usb_pd_tcpm.h
@@ -265,12 +265,12 @@ struct tcpm_drv {
* Get firmware version.
*
* @param port Type-C port number
- * @param renew Force renewal
+ * @param live Fetch live chip info or hard-coded + cached info
* @param info Pointer to pointer to PD chip info
*
* @return EC_SUCCESS or error
*/
- int (*get_chip_info)(int port, int renew,
+ int (*get_chip_info)(int port, int live,
struct ec_response_pd_chip_info_v1 **info);
#ifdef CONFIG_USBC_PPC
diff --git a/util/ectool.c b/util/ectool.c
index 3f56aeb6b7..f79a9e1c8b 100644
--- a/util/ectool.c
+++ b/util/ectool.c
@@ -8056,7 +8056,12 @@ int cmd_pd_chip_info(int argc, char *argv[])
int cmdver = 1;
if (argc < 2 || 3 < argc) {
- fprintf(stderr, "Usage: %s <port> [renew(on/off)]\n", argv[0]);
+ fprintf(stderr, "Usage: %s <port> [<live>]\n"
+ "live parameter can take values 0 or 1\n"
+ "0 -> Return hard-coded value for VID/PID and\n"
+ " cached value for Firmware Version\n"
+ "1 -> Return live chip value for VID/PID/FW Version\n",
+ argv[0]);
return -1;
}
@@ -8066,14 +8071,13 @@ int cmd_pd_chip_info(int argc, char *argv[])
return -1;
}
- p.renew = 0;
+ p.live = 0;
if (argc == 3) {
- int val;
- if (!parse_bool(argv[2], &val)) {
+ p.live = strtol(argv[2], &e, 0);
+ if (e && *e) {
fprintf(stderr, "invalid arg \"%s\"\n", argv[2]);
return -1;
}
- p.renew = val;
}
if (!ec_cmd_version_supported(EC_CMD_PD_CHIP_INFO, cmdver))