summaryrefslogtreecommitdiff
path: root/zephyr
diff options
context:
space:
mode:
authorJeremy Bettis <jbettis@google.com>2022-08-31 16:36:39 -0600
committerChromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com>2022-09-12 18:33:37 +0000
commit54a17155080c63f4654ec8729de593fcda721f87 (patch)
treeb66348b7e4b8e5b1a0585407f91d978ed49aa732 /zephyr
parent866baf5818e7bda257f8f21ffe02b1a5cead3331 (diff)
downloadchrome-ec-54a17155080c63f4654ec8729de593fcda721f87.tar.gz
zephyr: Add new vboot efs2 tests for cr50 errors
Emulate the cr50 to test all code in verify_and_jump. Add LCOV_EXCL comments to prevent code coverage on stub functions that are not intended to be used. Depends on https://github.com/zephyrproject-rtos/zephyr/pull/49768 BRANCH=None BUG=None TEST=./twister Cq-Depend: chromium:3886718 Change-Id: Ia52e8d96ead69843749230e76ec1a90c02a02d36 Signed-off-by: Jeremy Bettis <jbettis@google.com> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3867801 Reviewed-by: Aaron Massey <aaronmassey@google.com> Code-Coverage: Zoss <zoss-cl-coverage@prod.google.com> Commit-Queue: Jeremy Bettis <jbettis@chromium.org> Tested-by: Jeremy Bettis <jbettis@chromium.org>
Diffstat (limited to 'zephyr')
-rw-r--r--zephyr/shim/src/console.c26
-rw-r--r--zephyr/test/vboot_efs2/boards/native_posix.overlay9
-rw-r--r--zephyr/test/vboot_efs2/prj.conf1
-rw-r--r--zephyr/test/vboot_efs2/src/main.c157
4 files changed, 177 insertions, 16 deletions
diff --git a/zephyr/shim/src/console.c b/zephyr/shim/src/console.c
index 5ae44e5a1b..b329133dc0 100644
--- a/zephyr/shim/src/console.c
+++ b/zephyr/shim/src/console.c
@@ -56,6 +56,8 @@ static struct k_poll_signal shell_init_signal;
* (which requires locking the shell).
*/
static bool shell_stopped;
+
+#if defined(CONFIG_UART_INTERRUPT_DRIVEN)
RING_BUF_DECLARE(rx_buffer, CONFIG_UART_RX_BUF_SIZE);
static void uart_rx_handle(const struct device *dev)
@@ -90,10 +92,12 @@ static void uart_callback(const struct device *dev, void *user_data)
if (uart_irq_rx_ready(dev))
uart_rx_handle(dev);
}
+#endif
static void shell_uninit_callback(const struct shell *shell, int res)
{
if (!res) {
+#if defined(CONFIG_UART_INTERRUPT_DRIVEN)
/* Set the new callback */
uart_irq_callback_user_data_set(uart_shell_dev, uart_callback,
NULL);
@@ -106,6 +110,7 @@ static void shell_uninit_callback(const struct shell *shell, int res)
/* Enable RX interrupts */
uart_irq_rx_enable(uart_shell_dev);
+#endif
}
/* Notify the uninit signal that we finished */
@@ -126,9 +131,11 @@ int uart_shell_stop(void)
/* Clear all pending input */
uart_clear_input();
+#if defined(CONFIG_UART_INTERRUPT_DRIVEN)
/* Disable RX and TX interrupts */
uart_irq_rx_disable(uart_shell_dev);
uart_irq_tx_disable(uart_shell_dev);
+#endif
/* Initialize the uninit signal */
k_poll_signal_init(&shell_uninit_signal);
@@ -169,8 +176,10 @@ static void shell_init_from_work(struct k_work *work)
k_thread_priority_set(shell_zephyr->ctx->tid,
EC_TASK_PRIORITY(EC_SHELL_PRIO));
+#if defined(CONFIG_UART_INTERRUPT_DRIVEN)
uart_irq_rx_enable(uart_shell_dev);
uart_irq_tx_enable(uart_shell_dev);
+#endif
/* Notify the init signal that initialization is complete */
k_poll_signal_raise(&shell_init_signal, 0);
@@ -183,9 +192,11 @@ void uart_shell_start(void)
K_POLL_TYPE_SIGNAL, K_POLL_MODE_NOTIFY_ONLY,
&shell_init_signal);
+#if defined(CONFIG_UART_INTERRUPT_DRIVEN)
/* Disable RX and TX interrupts */
uart_irq_rx_disable(uart_shell_dev);
uart_irq_tx_disable(uart_shell_dev);
+#endif
/* Initialize k_work to call shell init (this makes it thread safe) */
k_work_init(&shell_init_work, shell_init_from_work);
@@ -316,24 +327,39 @@ void uart_flush_output(void)
void uart_tx_flush(void)
{
+#if defined(CONFIG_UART_INTERRUPT_DRIVEN)
while (!uart_irq_tx_complete(uart_shell_dev))
;
+#endif
}
int uart_getc(void)
{
+#if defined(CONFIG_UART_INTERRUPT_DRIVEN)
uint8_t c;
if (ring_buf_get(&rx_buffer, &c, 1)) {
return c;
}
return -1;
+#else
+ uint8_t c;
+ int rv;
+
+ rv = uart_poll_in(uart_shell_dev, &c);
+ if (rv) {
+ return rv;
+ }
+ return c;
+#endif
}
void uart_clear_input(void)
{
+#if defined(CONFIG_UART_INTERRUPT_DRIVEN)
/* Reset the input ring buffer */
ring_buf_reset(&rx_buffer);
+#endif
}
static void handle_sprintf_rv(int rv, size_t *len)
diff --git a/zephyr/test/vboot_efs2/boards/native_posix.overlay b/zephyr/test/vboot_efs2/boards/native_posix.overlay
index d0ab830358..c03a4757fe 100644
--- a/zephyr/test/vboot_efs2/boards/native_posix.overlay
+++ b/zephyr/test/vboot_efs2/boards/native_posix.overlay
@@ -10,6 +10,7 @@
chosen {
cros-ec,flash = &flash1;
cros-ec,flash-controller = &cros_flash;
+ zephyr,shell-uart = &test_uart;
};
aliases {
gpio-wp = &gpio_wp_l;
@@ -74,7 +75,6 @@
compatible = "cros,tcpci-generic-emul";
status = "okay";
reg = <0x82>;
- label = "TCPCI_EMUL";
alert_gpio = <&usb_c0_tcpc_int_odl>;
};
};
@@ -98,6 +98,12 @@
compatible = "lgc,ac17a8m", "battery-smart";
};
};
+ test_uart: uart@55556666 {
+ compatible = "vnd,serial";
+ reg = <0x55556666 0x1000>;
+ status = "okay";
+ buffer-size = <200>;
+ };
};
&gpio0 {
@@ -121,7 +127,6 @@
compatible = "cros,isl923x-emul";
status = "okay";
reg = <0x9>;
- label = "ISL923X_EMUL";
battery = <&battery>;
};
};
diff --git a/zephyr/test/vboot_efs2/prj.conf b/zephyr/test/vboot_efs2/prj.conf
index 1b73555f90..988ebc4a8c 100644
--- a/zephyr/test/vboot_efs2/prj.conf
+++ b/zephyr/test/vboot_efs2/prj.conf
@@ -36,6 +36,7 @@ CONFIG_PLATFORM_EC_VBOOT_HASH=y
CONFIG_RING_BUFFER=y
CONFIG_SERIAL=y
CONFIG_SHELL_BACKEND_DUMMY=y
+CONFIG_SHELL_BACKEND_DUMMY_BUF_SIZE=1000
CONFIG_SHELL_BACKEND_SERIAL=n
CONFIG_SHIMMED_TASKS=y
CONFIG_ZTEST=y
diff --git a/zephyr/test/vboot_efs2/src/main.c b/zephyr/test/vboot_efs2/src/main.c
index b0ef86c92a..162a7088b2 100644
--- a/zephyr/test/vboot_efs2/src/main.c
+++ b/zephyr/test/vboot_efs2/src/main.c
@@ -3,21 +3,25 @@
* found in the LICENSE file.
*/
-#include "zephyr/kernel.h"
-#include <zephyr/ztest_assert.h>
-#include <zephyr/ztest_test_new.h>
-#include <zephyr/shell/shell_dummy.h>
-
+#include "driver/bc12/pi3usb9201_public.h"
+#include "driver/tcpm/tcpci.h"
#include "ec_app_main.h"
+#include "emul/emul_flash.h"
#include "hooks.h"
+#include "ppc/sn5s330_public.h"
#include "task.h"
-#include "emul/emul_flash.h"
-#include "vboot.h"
-#include "driver/bc12/pi3usb9201_public.h"
#include "usb_mux.h"
-#include "driver/tcpm/tcpci.h"
-#include "ppc/sn5s330_public.h"
#include "usbc_ppc.h"
+#include "vboot.h"
+
+#include <stdint.h>
+
+#include <zephyr/drivers/gpio/gpio_emul.h>
+#include <zephyr/drivers/uart/serial_test.h>
+#include <zephyr/kernel.h>
+#include <zephyr/shell/shell_dummy.h>
+#include <zephyr/ztest_assert.h>
+#include <zephyr/ztest_test_new.h>
static int show_power_shortage_called;
void show_power_shortage(void)
@@ -126,15 +130,139 @@ ZTEST(vboot_efs2, test_vboot_main_jump_timeout)
zassert_equal(show_power_shortage_called, 0, NULL);
}
-/* TODO(jbettis): Add cases for verify_and_jump() CR50_COMM_ERR_BAD_PAYLOAD &
- * CR50_COMM_SUCCESS
- */
+#define PACKET_MODE_GPIO DT_PATH(named_gpios, ec_gsc_packet_mode)
+
+static const struct device *uart_shell_dev =
+ DEVICE_DT_GET(DT_CHOSEN(zephyr_shell_uart));
+static const struct device *gpio_dev =
+ DEVICE_DT_GET(DT_GPIO_CTLR(PACKET_MODE_GPIO, gpios));
+
+static void reply_cr50_payload(const struct device *dev, void *user_data)
+{
+ if (gpio_emul_output_get(gpio_dev,
+ DT_GPIO_PIN(PACKET_MODE_GPIO, gpios))) {
+ struct cr50_comm_request req;
+ uint32_t bytes_read;
+
+ bytes_read = serial_vnd_peek_out_data(
+ uart_shell_dev, (void *)&req, sizeof(req));
+ /* If ! valid cr50_comm_request header, read 1 byte. */
+ while (bytes_read == sizeof(req) &&
+ req.magic != CR50_PACKET_MAGIC) {
+ /* Consume one byte and then peek again. */
+ serial_vnd_read_out_data(uart_shell_dev, NULL, 1);
+ bytes_read = serial_vnd_peek_out_data(
+ uart_shell_dev, (void *)&req, sizeof(req));
+ }
+ if (bytes_read == sizeof(req)) {
+ /* If we have a full packet, consume it, and reply
+ * with whatever is in user_data which holds a cr50
+ * reply.
+ */
+ if (req.size <=
+ serial_vnd_out_data_size_get(uart_shell_dev)) {
+ serial_vnd_read_out_data(uart_shell_dev, NULL,
+ req.size);
+ serial_vnd_queue_in_data(
+ uart_shell_dev, user_data,
+ sizeof(struct cr50_comm_response));
+ }
+ }
+ } else {
+ /* Packet mode is off, so just consume some bytes from the out
+ * buffer. The buffer is only 200 in the dts, so 1000 will
+ * consume it all.
+ */
+ serial_vnd_read_out_data(uart_shell_dev, NULL, 1000);
+ }
+}
+
+ZTEST(vboot_efs2, test_vboot_main_jump_bad_payload)
+{
+ const struct shell *shell_zephyr = get_ec_shell();
+ const char *outbuffer;
+ size_t buffer_size;
+ struct cr50_comm_response resp = {
+ .error = CR50_COMM_ERR_BAD_PAYLOAD,
+ };
+
+ serial_vnd_set_callback(uart_shell_dev, reply_cr50_payload, &resp);
+
+ shell_backend_dummy_clear_output(shell_zephyr);
+ vboot_main();
+
+ outbuffer = shell_backend_dummy_get_output(shell_zephyr, &buffer_size);
+
+ zassert_true(strstr(outbuffer, "VB Ping Cr50") != NULL,
+ "Expected msg not in %s", outbuffer);
+ zassert_true(strstr(outbuffer, "VB Hash mismatch") != NULL,
+ "Expected msg not in %s", outbuffer);
+ zassert_true(vboot_allow_usb_pd(), NULL);
+ zassert_equal(show_power_shortage_called, 0, NULL);
+ zassert_equal(show_critical_error_called, 0, NULL);
+}
+
+/* This hits the default case in verify_and_jump. */
+ZTEST(vboot_efs2, test_vboot_main_jump_bad_crc)
+{
+ const struct shell *shell_zephyr = get_ec_shell();
+ const char *outbuffer;
+ size_t buffer_size;
+ struct cr50_comm_response resp = {
+ .error = CR50_COMM_ERR_CRC,
+ };
+
+ serial_vnd_set_callback(uart_shell_dev, reply_cr50_payload, &resp);
+
+ shell_backend_dummy_clear_output(shell_zephyr);
+ vboot_main();
+
+ outbuffer = shell_backend_dummy_get_output(shell_zephyr, &buffer_size);
+
+ zassert_true(strstr(outbuffer, "VB Ping Cr50") != NULL,
+ "Expected msg not in %s", outbuffer);
+ zassert_true(strstr(outbuffer, "VB Failed to verify RW (0xec03)") !=
+ NULL,
+ "Expected msg not in %s", outbuffer);
+ zassert_false(vboot_allow_usb_pd(), NULL);
+ zassert_equal(show_power_shortage_called, 0, NULL);
+ zassert_equal(show_critical_error_called, 1, NULL);
+}
+
+ZTEST(vboot_efs2, test_vboot_main_jump_success)
+{
+ const struct shell *shell_zephyr = get_ec_shell();
+ const char *outbuffer;
+ size_t buffer_size;
+ struct cr50_comm_response resp = {
+ .error = CR50_COMM_SUCCESS,
+ };
+
+ serial_vnd_set_callback(uart_shell_dev, reply_cr50_payload, &resp);
+
+ shell_backend_dummy_clear_output(shell_zephyr);
+ vboot_main();
+
+ outbuffer = shell_backend_dummy_get_output(shell_zephyr, &buffer_size);
+
+ zassert_true(strstr(outbuffer, "VB Ping Cr50") != NULL,
+ "Expected msg not in %s", outbuffer);
+ zassert_true(strstr(outbuffer, "VB Failed to jump") != NULL,
+ "Expected msg not in %s", outbuffer);
+ zassert_false(vboot_allow_usb_pd(), NULL);
+ zassert_equal(show_power_shortage_called, 0, NULL);
+ zassert_equal(show_critical_error_called, 1, NULL);
+ zassert_equal(system_get_reset_flags(), 0, NULL);
+}
void *vboot_efs2_setup(void)
{
/* Wait for the shell to start. */
k_sleep(K_MSEC(1));
zassert_equal(get_ec_shell()->ctx->state, SHELL_STATE_ACTIVE, NULL);
+
+ system_common_pre_init();
+
return NULL;
}
@@ -146,8 +274,9 @@ void vboot_efs2_cleanup(void *fixture)
show_power_shortage_called = 0;
show_critical_error_called = 0;
system_exit_manual_recovery();
- system_clear_reset_flags(EC_RESET_FLAG_STAY_IN_RO);
+ system_clear_reset_flags(EC_RESET_FLAG_STAY_IN_RO | EC_RESET_FLAG_EFS);
vboot_disable_pd();
+ serial_vnd_set_callback(uart_shell_dev, NULL, NULL);
}
ZTEST_SUITE(vboot_efs2, NULL, vboot_efs2_setup, NULL, vboot_efs2_cleanup, NULL);