summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaisuke Nojiri <dnojiri@chromium.org>2021-04-10 08:22:05 -0700
committerCommit Bot <commit-bot@chromium.org>2021-06-17 01:08:19 +0000
commit6bb2d508988e9725e41915d430e1feb21fe68534 (patch)
tree0aab84e31b96838b017bdb238c2cfde57ac72c61
parent2252a56cd80adb017614c35fe1a27716cc0046f8 (diff)
downloadchrome-ec-6bb2d508988e9725e41915d430e1feb21fe68534.tar.gz
PCHG: Fuzz PCHG and ctn730 driver
This patch adds a fuzz test for PCHG and ctn730 driver. With the given corpus, the test currently reaches all the normal mode states. BUG=b:190841496 BRANCH=trogdor TEST=make run-pchg_fuzz TEST=pchg_fuzz.exe -seed=1 -runs=1000000 -dict=fuzz/pchg_fuzz.corpus Change-Id: I6eedbbbdbf3396dfa2b98ca302e16d142ea251d5 Signed-off-by: Daisuke Nojiri <dnojiri@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2956076
-rw-r--r--board/host/board.c2
-rw-r--r--driver/nfc/ctn730.c115
-rw-r--r--driver/nfc/ctn730.h119
-rw-r--r--fuzz/build.mk3
-rw-r--r--fuzz/fuzz_config.h12
-rw-r--r--fuzz/pchg_fuzz.c115
-rw-r--r--fuzz/pchg_fuzz.corpus26
-rw-r--r--fuzz/pchg_fuzz.tasklist12
-rw-r--r--include/peripheral_charger.h3
9 files changed, 293 insertions, 114 deletions
diff --git a/board/host/board.c b/board/host/board.c
index 2253475dde..b59b570d52 100644
--- a/board/host/board.c
+++ b/board/host/board.c
@@ -69,6 +69,8 @@ const struct i2c_port_t i2c_ports[] = {
{"tcpc", I2C_PORT_HOST_TCPC, 100, 0, 0},
#elif defined I2C_PORT_EEPROM
{"eeprom", I2C_PORT_EEPROM, 100, 0, 0},
+#elif defined I2C_PORT_WLC
+ {"wlc", I2C_PORT_WLC, 100, 0, 0},
#endif
};
diff --git a/driver/nfc/ctn730.c b/driver/nfc/ctn730.c
index 1fe5a48b1b..657635dd94 100644
--- a/driver/nfc/ctn730.c
+++ b/driver/nfc/ctn730.c
@@ -3,6 +3,8 @@
* found in the LICENSE file.
*/
+#include "chipset.h"
+#include "ctn730.h"
#include "common.h"
#include "console.h"
#include "gpio.h"
@@ -31,119 +33,6 @@ static const int _detection_interval_ms = 500;
/* Buffer size for i2c read & write */
#define CTN730_MESSAGE_BUFFER_SIZE 0x20
-/*
- * Static (Chip) Parameters
- */
-#define CTN730_I2C_ADDR 0x28
-
-/* Size of flash address space in bytes */
-#define CTN730_FLASH_ADDR_SIZE 3
-
-/* All commands are guaranteed to finish within 1 second. */
-#define CTN730_COMMAND_TIME_OUT (1 * SECOND)
-
-/* Message Types */
-#define CTN730_MESSAGE_TYPE_COMMAND 0b00
-#define CTN730_MESSAGE_TYPE_RESPONSE 0b01
-#define CTN730_MESSAGE_TYPE_EVENT 0b10
-
-/* Instruction Codes */
-#define WLC_HOST_CTRL_RESET 0b000000
-#define WLC_HOST_CTRL_DL_OPEN_SESSION 0b000011
-#define WLC_HOST_CTRL_DL_COMMIT_SESSION 0b000100
-#define WLC_HOST_CTRL_DL_WRITE_FLASH 0b000101
-#define WLC_HOST_CTRL_DUMP_STATUS 0b001100
-#define WLC_HOST_CTRL_GENERIC_ERROR 0b001111
-#define WLC_HOST_CTRL_BIST 0b000110
-#define WLC_CHG_CTRL_ENABLE 0b010000
-#define WLC_CHG_CTRL_DISABLE 0b010001
-#define WLC_CHG_CTRL_DEVICE_STATE 0b010010
-#define WLC_CHG_CTRL_CHARGING_STATE 0b010100
-#define WLC_CHG_CTRL_CHARGING_INFO 0b010101
-
-/* WLC_HOST_CTRL_RESET constants */
-#define WLC_HOST_CTRL_RESET_CMD_SIZE 1
-#define WLC_HOST_CTRL_RESET_RSP_SIZE 1
-#define WLC_HOST_CTRL_RESET_EVT_NORMAL_MODE 0x00
-#define WLC_HOST_CTRL_RESET_EVT_NORMAL_MODE_SIZE 3
-#define WLC_HOST_CTRL_RESET_EVT_DOWNLOAD_MODE 0x01
-#define WLC_HOST_CTRL_RESET_EVT_DOWNLOAD_MODE_SIZE 2
-#define WLC_HOST_CTRL_RESET_REASON_INTENDED 0x00
-#define WLC_HOST_CTRL_RESET_REASON_CORRUPTED 0x01
-#define WLC_HOST_CTRL_RESET_REASON_UNRECOVERABLE 0x02
-#define WLC_HOST_CTRL_RESET_CMD_MODE_NORMAL 0x00
-#define WLC_HOST_CTRL_RESET_CMD_MODE_DOWNLOAD 0x01
-
-/* WLC_HOST_CTRL_DL_* constants */
-#define WLC_HOST_CTRL_DL_OPEN_SESSION_CMD_SIZE 2
-#define WLC_HOST_CTRL_DL_OPEN_SESSION_RSP_SIZE 1
-#define WLC_HOST_CTRL_DL_WRITE_FLASH_BLOCK_SIZE 128
-#define WLC_HOST_CTRL_DL_WRITE_FLASH_CMD_SIZE \
- (CTN730_FLASH_ADDR_SIZE + WLC_HOST_CTRL_DL_WRITE_FLASH_BLOCK_SIZE)
-#define WLC_HOST_CTRL_DL_WRITE_FLASH_RSP_SIZE 1
-#define WLC_HOST_CTRL_DL_COMMIT_SESSION_CMD_SIZE 4
-#define WLC_HOST_CTRL_DL_COMMIT_SESSION_RSP_SIZE 1
-
-/* WLC_CHG_CTRL_ENABLE constants */
-#define WLC_CHG_CTRL_ENABLE_CMD_SIZE 2
-#define WLC_CHG_CTRL_ENABLE_RSP_SIZE 1
-
-/* WLC_CHG_CTRL_DISABLE constants */
-#define WLC_CHG_CTRL_DISABLE_CMD_SIZE 0
-#define WLC_CHG_CTRL_DISABLE_RSP_SIZE 1
-#define WLC_CHG_CTRL_DISABLE_EVT_SIZE 1
-
-/* WLC_CHG_CTRL_DEVICE_STATE constants */
-#define WLC_CHG_CTRL_DEVICE_STATE_DEVICE_DETECTED 0x00
-#define WLC_CHG_CTRL_DEVICE_STATE_DEVICE_DEACTIVATED 0x01
-#define WLC_CHG_CTRL_DEVICE_STATE_DEVICE_DEVICE_LOST 0x02
-#define WLC_CHG_CTRL_DEVICE_STATE_DEVICE_DEVICE_BAD_VERSION 0x03
-#define WLC_CHG_CTRL_DEVICE_STATE_DEVICE_DOCKED 0x04
-#define WLC_CHG_CTRL_DEVICE_STATE_DEVICE_UNDOCKED 0x05
-#define WLC_CHG_CTRL_DEVICE_STATE_EVT_SIZE_DETECTED 8
-#define WLC_CHG_CTRL_DEVICE_STATE_EVT_SIZE 1
-
-/* WLC_CHG_CTRL_CHARGING_STATE constants */
-#define WLC_CHG_CTRL_CHARGING_STATE_CHARGE_STARTED 0x00
-#define WLC_CHG_CTRL_CHARGING_STATE_CHARGE_ENDED 0x01
-#define WLC_CHG_CTRL_CHARGING_STATE_CHARGE_STOPPED 0x02
-#define WLC_CHG_CTRL_CHARGING_STATE_EVT_SIZE 1
-
-/* WLC_HOST_CTRL_DUMP_STATUS constants */
-#define WLC_HOST_CTRL_DUMP_STATUS_CMD_SIZE 1
-
-/* WLC_CHG_CTRL_CHARGING_INFO constants */
-#define WLC_CHG_CTRL_CHARGING_INFO_CMD_SIZE 0
-#define WLC_CHG_CTRL_CHARGING_INFO_RSP_SIZE 2
-#define WLC_CHG_CTRL_CHARGING_INFO_EVT_SIZE 5
-
-/* Status Codes */
-enum wlc_host_status {
- WLC_HOST_STATUS_OK = 0x00,
- WLC_HOST_STATUS_PARAMETER_ERROR = 0x01,
- WLC_HOST_STATUS_STATE_ERROR = 0x02,
- WLC_HOST_STATUS_VALUE_ERROR = 0x03,
- WLC_HOST_STATUS_REJECTED = 0x04,
- WLC_HOST_STATUS_RESOURCE_ERROR = 0x10,
- WLC_HOST_STATUS_TXLDO_ERROR = 0x11,
- WLC_HOST_STATUS_ANTENNA_SELECTION_ERROR = 0x12,
- WLC_HOST_STATUS_BIST_FAILED = 0x20,
- WLC_HOST_STATUS_BIST_NO_WLC_CAP = 0x21,
- WLC_HOST_STATUS_BIST_TXLDO_CURRENT_OVERFLOW = 0x22,
- WLC_HOST_STATUS_BIST_TXLDO_CURRENT_UNDERFLOW = 0x23,
- WLC_HOST_STATUS_FW_VERSION_ERROR = 0x30,
- WLC_HOST_STATUS_FW_VERIFICATION_ERROR = 0x31,
- WLC_HOST_STATUS_NTAG_BLOCK_PARAMETER_ERROR = 0x32,
- WLC_HOST_STATUS_NTAG_READ_ERROR = 0x33,
-};
-
-struct ctn730_msg {
- uint8_t instruction : 6;
- uint8_t message_type : 2;
- uint8_t length;
- uint8_t payload[];
-} __packed;
-
/* This driver isn't compatible with big endian. */
BUILD_ASSERT(__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__);
diff --git a/driver/nfc/ctn730.h b/driver/nfc/ctn730.h
new file mode 100644
index 0000000000..7a243c0561
--- /dev/null
+++ b/driver/nfc/ctn730.h
@@ -0,0 +1,119 @@
+/* Copyright 2021 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.
+ */
+
+#ifndef __CROS_EC_CTN730_H
+#define __CROS_EC_CTN730_H
+
+#define CTN730_I2C_ADDR 0x28
+
+/* Size of flash address space in bytes */
+#define CTN730_FLASH_ADDR_SIZE 3
+
+/* All commands are guaranteed to finish within 1 second. */
+#define CTN730_COMMAND_TIME_OUT (1 * SECOND)
+
+/* Message Types */
+#define CTN730_MESSAGE_TYPE_COMMAND 0b00
+#define CTN730_MESSAGE_TYPE_RESPONSE 0b01
+#define CTN730_MESSAGE_TYPE_EVENT 0b10
+
+/* Instruction Codes */
+#define WLC_HOST_CTRL_RESET 0b000000
+#define WLC_HOST_CTRL_DL_OPEN_SESSION 0b000011
+#define WLC_HOST_CTRL_DL_COMMIT_SESSION 0b000100
+#define WLC_HOST_CTRL_DL_WRITE_FLASH 0b000101
+#define WLC_HOST_CTRL_DUMP_STATUS 0b001100
+#define WLC_HOST_CTRL_GENERIC_ERROR 0b001111
+#define WLC_HOST_CTRL_BIST 0b000110
+#define WLC_CHG_CTRL_ENABLE 0b010000
+#define WLC_CHG_CTRL_DISABLE 0b010001
+#define WLC_CHG_CTRL_DEVICE_STATE 0b010010
+#define WLC_CHG_CTRL_CHARGING_STATE 0b010100
+#define WLC_CHG_CTRL_CHARGING_INFO 0b010101
+
+/* WLC_HOST_CTRL_RESET constants */
+#define WLC_HOST_CTRL_RESET_CMD_SIZE 1
+#define WLC_HOST_CTRL_RESET_RSP_SIZE 1
+#define WLC_HOST_CTRL_RESET_EVT_NORMAL_MODE 0x00
+#define WLC_HOST_CTRL_RESET_EVT_NORMAL_MODE_SIZE 3
+#define WLC_HOST_CTRL_RESET_EVT_DOWNLOAD_MODE 0x01
+#define WLC_HOST_CTRL_RESET_EVT_DOWNLOAD_MODE_SIZE 2
+#define WLC_HOST_CTRL_RESET_REASON_INTENDED 0x00
+#define WLC_HOST_CTRL_RESET_REASON_CORRUPTED 0x01
+#define WLC_HOST_CTRL_RESET_REASON_UNRECOVERABLE 0x02
+#define WLC_HOST_CTRL_RESET_CMD_MODE_NORMAL 0x00
+#define WLC_HOST_CTRL_RESET_CMD_MODE_DOWNLOAD 0x01
+
+/* WLC_HOST_CTRL_DL_* constants */
+#define WLC_HOST_CTRL_DL_OPEN_SESSION_CMD_SIZE 2
+#define WLC_HOST_CTRL_DL_OPEN_SESSION_RSP_SIZE 1
+#define WLC_HOST_CTRL_DL_WRITE_FLASH_BLOCK_SIZE 128
+#define WLC_HOST_CTRL_DL_WRITE_FLASH_CMD_SIZE \
+ (CTN730_FLASH_ADDR_SIZE + WLC_HOST_CTRL_DL_WRITE_FLASH_BLOCK_SIZE)
+#define WLC_HOST_CTRL_DL_WRITE_FLASH_RSP_SIZE 1
+#define WLC_HOST_CTRL_DL_COMMIT_SESSION_CMD_SIZE 4
+#define WLC_HOST_CTRL_DL_COMMIT_SESSION_RSP_SIZE 1
+
+/* WLC_CHG_CTRL_ENABLE constants */
+#define WLC_CHG_CTRL_ENABLE_CMD_SIZE 2
+#define WLC_CHG_CTRL_ENABLE_RSP_SIZE 1
+
+/* WLC_CHG_CTRL_DISABLE constants */
+#define WLC_CHG_CTRL_DISABLE_CMD_SIZE 0
+#define WLC_CHG_CTRL_DISABLE_RSP_SIZE 1
+#define WLC_CHG_CTRL_DISABLE_EVT_SIZE 1
+
+/* WLC_CHG_CTRL_DEVICE_STATE constants */
+#define WLC_CHG_CTRL_DEVICE_STATE_DEVICE_DETECTED 0x00
+#define WLC_CHG_CTRL_DEVICE_STATE_DEVICE_DEACTIVATED 0x01
+#define WLC_CHG_CTRL_DEVICE_STATE_DEVICE_DEVICE_LOST 0x02
+#define WLC_CHG_CTRL_DEVICE_STATE_DEVICE_DEVICE_BAD_VERSION 0x03
+#define WLC_CHG_CTRL_DEVICE_STATE_DEVICE_DOCKED 0x04
+#define WLC_CHG_CTRL_DEVICE_STATE_DEVICE_UNDOCKED 0x05
+#define WLC_CHG_CTRL_DEVICE_STATE_EVT_SIZE_DETECTED 8
+#define WLC_CHG_CTRL_DEVICE_STATE_EVT_SIZE 1
+
+/* WLC_CHG_CTRL_CHARGING_STATE constants */
+#define WLC_CHG_CTRL_CHARGING_STATE_CHARGE_STARTED 0x00
+#define WLC_CHG_CTRL_CHARGING_STATE_CHARGE_ENDED 0x01
+#define WLC_CHG_CTRL_CHARGING_STATE_CHARGE_STOPPED 0x02
+#define WLC_CHG_CTRL_CHARGING_STATE_EVT_SIZE 1
+
+/* WLC_HOST_CTRL_DUMP_STATUS constants */
+#define WLC_HOST_CTRL_DUMP_STATUS_CMD_SIZE 1
+
+/* WLC_CHG_CTRL_CHARGING_INFO constants */
+#define WLC_CHG_CTRL_CHARGING_INFO_CMD_SIZE 0
+#define WLC_CHG_CTRL_CHARGING_INFO_RSP_SIZE 2
+#define WLC_CHG_CTRL_CHARGING_INFO_EVT_SIZE 5
+
+/* Status Codes */
+enum wlc_host_status {
+ WLC_HOST_STATUS_OK = 0x00,
+ WLC_HOST_STATUS_PARAMETER_ERROR = 0x01,
+ WLC_HOST_STATUS_STATE_ERROR = 0x02,
+ WLC_HOST_STATUS_VALUE_ERROR = 0x03,
+ WLC_HOST_STATUS_REJECTED = 0x04,
+ WLC_HOST_STATUS_RESOURCE_ERROR = 0x10,
+ WLC_HOST_STATUS_TXLDO_ERROR = 0x11,
+ WLC_HOST_STATUS_ANTENNA_SELECTION_ERROR = 0x12,
+ WLC_HOST_STATUS_BIST_FAILED = 0x20,
+ WLC_HOST_STATUS_BIST_NO_WLC_CAP = 0x21,
+ WLC_HOST_STATUS_BIST_TXLDO_CURRENT_OVERFLOW = 0x22,
+ WLC_HOST_STATUS_BIST_TXLDO_CURRENT_UNDERFLOW = 0x23,
+ WLC_HOST_STATUS_FW_VERSION_ERROR = 0x30,
+ WLC_HOST_STATUS_FW_VERIFICATION_ERROR = 0x31,
+ WLC_HOST_STATUS_NTAG_BLOCK_PARAMETER_ERROR = 0x32,
+ WLC_HOST_STATUS_NTAG_READ_ERROR = 0x33,
+};
+
+struct ctn730_msg {
+ uint8_t instruction : 6;
+ uint8_t message_type : 2;
+ uint8_t length;
+ uint8_t payload[];
+} __packed;
+
+#endif /* __CROS_EC_CTN730_H */
diff --git a/fuzz/build.mk b/fuzz/build.mk
index 44ddb56974..3b5f117d20 100644
--- a/fuzz/build.mk
+++ b/fuzz/build.mk
@@ -10,7 +10,7 @@ fuzz-test-list-host =
# Fuzzers should only be built for architectures that support sanitizers.
ifeq ($(ARCH),amd64)
fuzz-test-list-host += host_command_fuzz usb_pd_fuzz usb_tcpm_v2_rev20_fuzz \
- usb_tcpm_v2_rev30_fuzz
+ usb_tcpm_v2_rev30_fuzz pchg_fuzz
endif
# For fuzzing targets libec.a is built from the ro objects and hides functions
@@ -31,3 +31,4 @@ usb_tcpm_v2_rev30_fuzz-y = usb_pd_fuzz.o usb_tcpm_v2_rev30_fuzz.o \
../test/fake_battery.o
usb_tcpm_v2_rev20_fuzz-y = usb_pd_fuzz.o usb_tcpm_v2_rev20_fuzz.o \
../test/fake_battery.o
+pchg_fuzz-y = pchg_fuzz.o \ No newline at end of file
diff --git a/fuzz/fuzz_config.h b/fuzz/fuzz_config.h
index 0569a21b38..fb974ea727 100644
--- a/fuzz/fuzz_config.h
+++ b/fuzz/fuzz_config.h
@@ -84,5 +84,17 @@
#define CONFIG_USB_PD_3A_PORTS 0 /* Host does not define a 3.0 A PDO */
#endif /* TEST_USB_TCPM_V2_REV20_FUZZ */
+#ifdef TEST_PCHG_FUZZ
+#define CONFIG_CTN730
+#define CONFIG_DEVICE_EVENT
+#define CONFIG_MKBP_EVENT
+#define CONFIG_MKBP_USE_GPIO
+#define CONFIG_PERIPHERAL_CHARGER
+#define I2C_PORT_WLC 0
+#define GPIO_WLC_IRQ_CONN 1
+#define GPIO_WLC_NRST_CONN 2
+#define GPIO_PCHG_P0 GPIO_WLC_IRQ_CONN
+#endif /* TEST_PCHG_FUZZ */
+
#endif /* TEST_FUZZ */
#endif /* __FUZZ_FUZZ_CONFIG_H */
diff --git a/fuzz/pchg_fuzz.c b/fuzz/pchg_fuzz.c
new file mode 100644
index 0000000000..14bdb94566
--- /dev/null
+++ b/fuzz/pchg_fuzz.c
@@ -0,0 +1,115 @@
+/* Copyright 2021 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 peripheral device charger module.
+ */
+
+#define HIDE_EC_STDLIB
+#include "common.h"
+#include "compile_time_macros.h"
+#include "driver/nfc/ctn730.h"
+#include "peripheral_charger.h"
+#include "task.h"
+#include "test_util.h"
+#include "timer.h"
+#include "util.h"
+
+#include <pthread.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define TASK_EVENT_FUZZ TASK_EVENT_CUSTOM_BIT(0)
+
+extern struct pchg_drv ctn730_drv;
+struct pchg pchgs[] = {
+ [0] = {
+ .cfg = &(const struct pchg_config) {
+ .drv = &ctn730_drv,
+ .i2c_port = I2C_PORT_WLC,
+ .irq_pin = GPIO_WLC_IRQ_CONN,
+ .full_percent = 96,
+ .block_size = 128,
+ },
+ .events = QUEUE_NULL(PCHG_EVENT_QUEUE_SIZE, enum pchg_event),
+ },
+};
+const int pchg_count = ARRAY_SIZE(pchgs);
+
+static pthread_cond_t done_cond;
+static pthread_mutex_t lock;
+
+#define MAX_MESSAGES 8
+static uint8_t input[
+ MAX_MESSAGES * 256 * member_size(struct ctn730_msg, length)];
+static uint8_t *head, *tail;
+static bool data_available;
+
+int pchg_i2c_xfer(int port, uint16_t addr_flags,
+ const uint8_t *out, int out_size,
+ uint8_t *in, int in_size, int flags)
+{
+ if (port != I2C_PORT_WLC || addr_flags != CTN730_I2C_ADDR)
+ return EC_ERROR_INVAL;
+
+ if (in == NULL || in_size == 0)
+ return EC_SUCCESS;
+
+ if (head + in_size >= tail) {
+ data_available = false;
+ return EC_ERROR_OVERFLOW;
+ }
+
+ memcpy(in, head, in_size);
+ head += in_size;
+
+ return EC_SUCCESS;
+}
+DECLARE_TEST_I2C_XFER(pchg_i2c_xfer);
+
+/*
+ * Task for generating IRQs. The task priority is lower than the PCHG task so
+ * that it can yield the CPU to the PCHG task.
+ */
+void irq_task(int argc, char **argv)
+{
+ ccprints("%s task started", __func__);
+ wait_for_task_started();
+
+ while (1) {
+ int i = 0;
+
+ task_wait_event_mask(TASK_EVENT_FUZZ, -1);
+ test_chipset_on();
+
+ while (data_available && i++ < MAX_MESSAGES)
+ pchg_irq(pchgs[0].cfg->irq_pin);
+
+ test_chipset_off();
+
+ pthread_cond_signal(&done_cond);
+ }
+
+}
+
+void run_test(int argc, char **argv)
+{
+ ccprints("Fuzzing task started");
+ task_wait_event(-1);
+}
+
+int test_fuzz_one_input(const uint8_t *data, unsigned int size)
+{
+ if (size < sizeof(struct ctn730_msg))
+ return 0;
+
+ head = input;
+ tail = input + size;
+ memcpy(input, data, size);
+ data_available = true;
+
+ task_set_event(TASK_ID_IRQ, TASK_EVENT_FUZZ);
+ pthread_cond_wait(&done_cond, &lock);
+
+ return 0;
+}
diff --git a/fuzz/pchg_fuzz.corpus b/fuzz/pchg_fuzz.corpus
new file mode 100644
index 0000000000..0b069baf4f
--- /dev/null
+++ b/fuzz/pchg_fuzz.corpus
@@ -0,0 +1,26 @@
+"\xae\x01"
+"\x18\x01\x00\x00"
+"\xff~"
+"\x01u"
+"\x80\x00\x00\x00"
+"Q\x00"
+"5\x00"
+"\xb7\x01\x00\x00"
+"\x01\x00\x00\x00\x01\x00\x00\x00"
+"\x00\x00\x00\x00\x00\x00\x00\x00"
+"\xff\xff\xff\x00n_\x0b\xc0"
+"\x92\x00"
+"\xff\xdc"
+"\xa6\x01"
+"\x85f\xfc$\x00\x00\x00\x00"
+"\xff\xff\xff\xff\xff\xff\xff\xff"
+"\xff\xff\xff\xff\x00\x00\x00\x00"
+"\xfff"
+"\x01\xcb"
+"\x8f\x00\x00\x00"
+"\xff\xff\xff\x0d"
+"=\x00\x00\x00"
+"\xbc\x00"
+"\x02\x91"
+"\xff\xff\xff\x00\x00\x00\x00\x00"
+"\x00y"
diff --git a/fuzz/pchg_fuzz.tasklist b/fuzz/pchg_fuzz.tasklist
new file mode 100644
index 0000000000..5b30e09245
--- /dev/null
+++ b/fuzz/pchg_fuzz.tasklist
@@ -0,0 +1,12 @@
+/* Copyright 2021 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 \
+ TASK_TEST(IRQ, irq_task, NULL, TASK_STACK_SIZE) \
+ TASK_TEST(PCHG, pchg_task, NULL, LARGER_TASK_STACK_SIZE) \
+ TASK_TEST(CHIPSET, chipset_task, NULL, LARGER_TASK_STACK_SIZE)
diff --git a/include/peripheral_charger.h b/include/peripheral_charger.h
index 702d3c9835..b1f82bb1f3 100644
--- a/include/peripheral_charger.h
+++ b/include/peripheral_charger.h
@@ -7,6 +7,7 @@
#define __CROS_EC_PERIPHERAL_CHARGER_H
#include "common.h"
+#include "ec_commands.h"
#include "gpio.h"
#include "queue.h"
#include "stdbool.h"
@@ -146,6 +147,8 @@ enum pchg_error {
enum pchg_mode {
PCHG_MODE_NORMAL = 0,
PCHG_MODE_DOWNLOAD,
+ /* Add no more entries below here. */
+ PCHG_MODE_COUNT,
};
/**