summaryrefslogtreecommitdiff
path: root/chip
diff options
context:
space:
mode:
authorBrian J. Nemec <bnemec@google.com>2022-02-04 13:01:40 -0800
committerCommit Bot <commit-bot@chromium.org>2022-02-11 06:22:45 +0000
commit5c9813df84e0d0794a92108262fc255854f6565c (patch)
tree182b197af47a30e73ea95779a652ae2d3a7272ee /chip
parent59e9e0544ec4e449b11267053e5525d6de372a39 (diff)
downloadchrome-ec-5c9813df84e0d0794a92108262fc255854f6565c.tar.gz
stm32: Add the DFU Runtime identifiers
Adds a DFU Runtime identifier and a DFU bootmanager to control the switch between the DFU and main application region. The DFU runtime identifier operates on the main application in the RW region. A DFU host recognizes the interface and can send commands to switch the firmware into DFU mode. BRANCH=servo BUG=b:217955677 TEST=Enabled the DFU configuration on Servo_v4 with CONFIG_DFU_RUNTIME TEST='sudo dfu-util -l' Verified the dfu-util recognizes the DFU runtime device. Signed-off-by: Brian Nemec <bnemec@chromium.org> Change-Id: I0e02b7cb35a7c594f169c56a96f965e5d87e3cfb Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3441173 Tested-by: Brian Nemec <bnemec@google.com> Reviewed-by: Sam Hurst <shurst@google.com> Commit-Queue: Brian Nemec <bnemec@google.com>
Diffstat (limited to 'chip')
-rw-r--r--chip/stm32/build.mk1
-rw-r--r--chip/stm32/usb_dfu_runtime.c91
-rw-r--r--chip/stm32/usb_dfu_runtime.h73
3 files changed, 165 insertions, 0 deletions
diff --git a/chip/stm32/build.mk b/chip/stm32/build.mk
index 9213ca3042..3990b8d4d7 100644
--- a/chip/stm32/build.mk
+++ b/chip/stm32/build.mk
@@ -81,6 +81,7 @@ chip-$(CHIP_FAMILY_STM32F3)+=flash-f.o
chip-$(CHIP_FAMILY_STM32F4)+=flash-f.o
endif
chip-$(CONFIG_ADC)+=adc-$(CHIP_FAMILY).o
+chip-$(CONFIG_DFU_RUNTIME)+=usb_dfu_runtime.o
chip-$(CONFIG_STM32_CHARGER_DETECT)+=charger_detect.o
chip-$(CONFIG_DEBUG_PRINTF)+=debug_printf.o
chip-$(CONFIG_OTP)+=otp-$(CHIP_FAMILY).o
diff --git a/chip/stm32/usb_dfu_runtime.c b/chip/stm32/usb_dfu_runtime.c
new file mode 100644
index 0000000000..b902f32af2
--- /dev/null
+++ b/chip/stm32/usb_dfu_runtime.c
@@ -0,0 +1,91 @@
+/* Copyright 2022 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.
+ */
+
+#include "registers.h"
+#include "usb_descriptor.h"
+#include "usb_dfu_runtime.h"
+#include "usb_hw.h"
+
+/* DFU Run-Time Descriptor Set. */
+const struct usb_interface_descriptor USB_IFACE_DESC(USB_IFACE_DFU) = {
+ .bLength = USB_DT_INTERFACE_SIZE,
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bInterfaceNumber = USB_IFACE_DFU,
+ .bAlternateSetting = 0,
+ .bNumEndpoints = 0,
+ .bInterfaceClass = USB_CLASS_APP_SPEC,
+ .bInterfaceSubClass = USB_DFU_RUNTIME_SUBCLASS,
+ .bInterfaceProtocol = USB_DFU_RUNTIME_PROTOCOL,
+ .iInterface = USB_STR_DFU_NAME,
+};
+
+/* DFU Functional Descriptor. */
+const struct usb_runtime_dfu_functional_desc USB_CUSTOM_DESC_VAR(USB_IFACE_DFU,
+ dfu, dfu_func_desc) = {
+ .bLength = USB_DFU_RUNTIME_DESC_SIZE,
+ .bDescriptorType = USB_DFU_RUNTIME_DESC_FUNCTIONAL,
+ .bmAttributes = USB_DFU_RUNTIME_DESC_ATTRS,
+ .wDetachTimeOut = USB_DFU_RUNTIME_DESC_DETACH_TIMEOUT,
+ .wTransferSize = USB_DFU_RUNTIME_DESC_TRANSFER_SIZE,
+ .bcdDFUVersion = USB_DFU_RUNTIME_DESC_DFU_VERSION,
+};
+
+static int dfu_runtime_request(usb_uint *ep0_buf_rx, usb_uint *ep0_buf_tx)
+{
+ struct usb_setup_packet packet;
+
+ usb_read_setup_packet(ep0_buf_rx, &packet);
+ btable_ep[0].tx_count = 0;
+ if ((packet.bmRequestType ==
+ (USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_INTERFACE)) &&
+ (packet.bRequest == USB_REQ_SET_INTERFACE)) {
+ /* ACK the change alternative mode request. */
+
+ STM32_TOGGLE_EP(0, EP_TX_RX_MASK, EP_TX_RX_VALID, 0);
+ return 0;
+ } else if ((packet.bmRequestType ==
+ (USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE)) &&
+ (packet.bRequest == USB_DFU_RUNTIME_REQ_DETACH)) {
+ /* Host is requesting a jump from application to DFU mode. */
+
+ STM32_TOGGLE_EP(0, EP_TX_RX_MASK, EP_TX_RX_VALID, 0);
+ return 0;
+ } else if (packet.bmRequestType ==
+ (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE)) {
+ if (packet.bRequest == USB_DFU_RUNTIME_REQ_GET_STATUS) {
+ /* Return the Get Status response. */
+
+ struct usb_runtime_dfu_get_status_resp response = {
+ .bStatus = USB_DFU_RUNTIME_STATUS_OK,
+ .bState = USB_DFU_RUNTIME_STATE_APP_IDLE,
+ };
+
+ memcpy_to_usbram((void *) usb_sram_addr(ep0_buf_tx),
+ &response, sizeof(response));
+ btable_ep[0].tx_count = sizeof(response);
+ STM32_TOGGLE_EP(0, EP_TX_RX_MASK, EP_TX_RX_VALID, 0);
+ return 0;
+ }
+ if (packet.bRequest == USB_DFU_RUNTIME_REQ_GET_STATE) {
+ /* Return the Get State response. */
+
+ struct usb_runtime_dfu_get_state_resp response = {
+ .bState = USB_DFU_RUNTIME_STATE_APP_IDLE,
+ };
+
+ memcpy_to_usbram((void *) usb_sram_addr(ep0_buf_tx),
+ &response, sizeof(response));
+ btable_ep[0].tx_count = sizeof(response);
+ STM32_TOGGLE_EP(0, EP_TX_RX_MASK, EP_TX_RX_VALID, 0);
+ return 0;
+ }
+ }
+ /* Return a stall response for any unhandled packets. */
+
+ STM32_TOGGLE_EP(0, EP_TX_RX_MASK, EP_RX_VALID | EP_TX_STALL, 0);
+ return 0;
+}
+
+USB_DECLARE_IFACE(USB_IFACE_DFU, dfu_runtime_request)
diff --git a/chip/stm32/usb_dfu_runtime.h b/chip/stm32/usb_dfu_runtime.h
new file mode 100644
index 0000000000..08781d77b0
--- /dev/null
+++ b/chip/stm32/usb_dfu_runtime.h
@@ -0,0 +1,73 @@
+/* Copyright 2022 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 __USB_DFU_H
+#define __USB_DFU_H
+
+#include "common.h"
+
+/* Universal Serial Bus Device Class Specification for Device Firmware Upgrade
+ * Version 1.1
+ * https://www.usb.org/sites/default/files/DFU_1.1.pdf
+ */
+
+#define USB_DFU_RUNTIME_SUBCLASS 0x01
+#define USB_DFU_RUNTIME_PROTOCOL 0x01
+
+#define USB_DFU_RUNTIME_DESC_ATTR_CAN_DOWNLOAD BIT(0)
+#define USB_DFU_RUNTIME_DESC_ATTR_CAN_UPLOAD BIT(1)
+#define USB_DFU_RUNTIME_DESC_ATTR_MANIFEST_TOLERANT BIT(2)
+#define USB_DFU_RUNTIME_DESC_ATTR_WILL_DETACH BIT(3)
+
+#define USB_DFU_RUNTIME_DESC_ATTRS \
+ (USB_DFU_RUNTIME_DESC_ATTR_CAN_DOWNLOAD | \
+ USB_DFU_RUNTIME_DESC_ATTR_CAN_UPLOAD | \
+ USB_DFU_RUNTIME_DESC_ATTR_WILL_DETACH)
+
+#define USB_DFU_RUNTIME_DESC_SIZE 9
+#define USB_DFU_RUNTIME_DESC_FUNCTIONAL 0x21
+#define USB_DFU_RUNTIME_DESC_DETACH_TIMEOUT 0xffff
+#define USB_DFU_RUNTIME_DESC_TRANSFER_SIZE 64
+#define USB_DFU_RUNTIME_DESC_DFU_VERSION 0x0022
+
+/* DFU states */
+#define USB_DFU_RUNTIME_STATE_APP_IDLE 0
+#define USB_DFU_RUNTIME_STATE_APP_DETACH 1
+
+/* DFU status */
+#define USB_DFU_RUNTIME_STATUS_OK 0
+
+/* DFU Request types */
+#define USB_DFU_RUNTIME_REQ_DETACH 0
+#define USB_DFU_RUNTIME_REQ_DNLOAD 1
+#define USB_DFU_RUNTIME_REQ_UPLOAD 2
+#define USB_DFU_RUNTIME_REQ_GET_STATUS 3
+#define USB_DFU_RUNTIME_REQ_CLR_STATUS 4
+#define USB_DFU_RUNTIME_REQ_GET_STATE 5
+#define USB_DFU_RUNTIME_REQ_ABORT 6
+
+
+/* DFU Functional Descriptor */
+struct usb_runtime_dfu_functional_desc {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bmAttributes;
+ uint16_t wDetachTimeOut;
+ uint16_t wTransferSize;
+ uint16_t bcdDFUVersion;
+} __packed;
+
+/* DFU response packets */
+struct usb_runtime_dfu_get_status_resp {
+ uint8_t bStatus;
+ uint8_t bwPollTimeout[3];
+ uint8_t bState;
+ uint8_t iString;
+} __packed;
+
+struct usb_runtime_dfu_get_state_resp {
+ uint8_t bState;
+} __packed;
+
+#endif /* __USB_DFU_H */