diff options
author | Karthikeyan Ramasubramanian <kramasub@chromium.org> | 2019-06-12 11:30:49 -0600 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2019-08-23 00:12:31 +0000 |
commit | 402649748ac71d4fcc67d3b6e387acc1e71b0922 (patch) | |
tree | 171f65127d5a82badef5626ef481d5239504c4b9 | |
parent | ee8d481a027b78796ce30a48224e043fdf5f7491 (diff) | |
download | chrome-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.c | 5 | ||||
-rw-r--r-- | driver/tcpm/anx74xx.c | 6 | ||||
-rw-r--r-- | driver/tcpm/it83xx.c | 2 | ||||
-rw-r--r-- | driver/tcpm/ps8xxx.c | 6 | ||||
-rw-r--r-- | driver/tcpm/tcpci.c | 6 | ||||
-rw-r--r-- | driver/tcpm/tcpci.h | 2 | ||||
-rw-r--r-- | driver/tcpm/tcpm.h | 4 | ||||
-rw-r--r-- | fuzz/usb_pd_fuzz.c | 223 | ||||
-rw-r--r-- | include/ec_commands.h | 7 | ||||
-rw-r--r-- | include/usb_pd_tcpm.h | 4 | ||||
-rw-r--r-- | util/ectool.c | 14 |
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)) |