diff options
author | Brian J. Nemec <bnemec@google.com> | 2022-02-04 13:01:40 -0800 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2022-02-11 06:22:45 +0000 |
commit | 5c9813df84e0d0794a92108262fc255854f6565c (patch) | |
tree | 182b197af47a30e73ea95779a652ae2d3a7272ee /chip | |
parent | 59e9e0544ec4e449b11267053e5525d6de372a39 (diff) | |
download | chrome-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.mk | 1 | ||||
-rw-r--r-- | chip/stm32/usb_dfu_runtime.c | 91 | ||||
-rw-r--r-- | chip/stm32/usb_dfu_runtime.h | 73 |
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 */ |