pd: Re-factor common flash vdms.

CL to migrate the flashing VDMs from zinger's custom vdm to
common/usb_pd_flash.c such that other updateable type-C devices can
share.

Additionally adds gaskets to call standard runtime flashing facilities
for USB-PD devices using it.

Signed-off-by: Todd Broch <tbroch@chromium.org>

BRANCH=samus
BUG=chrome-os-partner:31192,chrome-os-partner:31193
TEST=manual,

Try following:
    1. From samus_pd console w/ zinger in port 1

    pd 1 flash version
    pd 1 flash reboot
    pd 1 flash info

    2. From samus linux prompt  w/ zinger in port 1

    ectool --name cros_pd flashpd 1 1 <zinger RW payload>

    Reading 16384 bytes from
    /usr/local/zinger_v1.1.2528-d809e42.ec.RW.bin...
    Erasing expected RW hash
    Rebooting
    Erasing RW flash
    Writing RW flash
    Rebooting PD into new RW
    Complete

    3. Repeat 1&2 above on hoho & dingdong.

Change-Id: I018055fa9de128f937c57debdc21dea026137bcf
Reviewed-on: https://chromium-review.googlesource.com/231835
Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
Reviewed-by: Alec Berg <alecaberg@chromium.org>
Tested-by: Todd Broch <tbroch@chromium.org>
Commit-Queue: Todd Broch <tbroch@chromium.org>
This commit is contained in:
Todd Broch
2014-11-24 10:20:41 -08:00
committed by chrome-internal-fetch
parent b5557217aa
commit bc16903667
11 changed files with 163 additions and 165 deletions

View File

@@ -287,23 +287,18 @@ static int pd_custom_vdm(int port, int cnt, uint32_t *payload,
uint32_t **rpayload)
{
int cmd = PD_VDO_CMD(payload[0]);
int rsize = 1;
int rsize;
if (PD_VDO_VID(payload[0]) != USB_VID_GOOGLE || !gfu_mode)
return 0;
CPRINTF("VDM/%d [%d] %08x\n", cnt, cmd, payload[0]);
*rpayload = payload;
switch (cmd) {
case VDO_CMD_VERSION:
memcpy(payload + 1, &version_data.version, 24);
rsize = 7;
break;
case VDO_CMD_READ_INFO:
/* copy info into response */
pd_get_info(payload + 1);
rsize = 7;
break;
default:
rsize = 0;
}
rsize = pd_custom_flash_vdm(port, cnt, payload);
if (!rsize)
return 0;
CPRINTS("DONE");
/* respond (positively) to the request */

View File

@@ -286,23 +286,18 @@ static int pd_custom_vdm(int port, int cnt, uint32_t *payload,
uint32_t **rpayload)
{
int cmd = PD_VDO_CMD(payload[0]);
int rsize = 1;
int rsize;
if (PD_VDO_VID(payload[0]) != USB_VID_GOOGLE || !gfu_mode)
return 0;
CPRINTF("VDM/%d [%d] %08x\n", cnt, cmd, payload[0]);
*rpayload = payload;
switch (cmd) {
case VDO_CMD_VERSION:
memcpy(payload + 1, &version_data.version, 24);
rsize = 7;
break;
case VDO_CMD_READ_INFO:
/* copy info into response */
pd_get_info(payload + 1);
rsize = 7;
break;
default:
rsize = 0;
}
rsize = pd_custom_flash_vdm(port, cnt, payload);
if (!rsize)
return 0;
CPRINTS("DONE");
/* respond (positively) to the request */

View File

@@ -9,6 +9,7 @@
#include "registers.h"
#include "rsa.h"
#include "sha256.h"
#include "system.h"
#include "task.h"
#include "usb_pd.h"
#include "util.h"
@@ -23,10 +24,6 @@ static const void *rw_sig = (void *)CONFIG_FLASH_BASE + CONFIG_FW_RW_OFF
/* Large 768-Byte buffer for RSA computation : could be re-use afterwards... */
static uint32_t rsa_workbuf[3 * RSANUMWORDS];
static uint8_t *rw_hash;
static uint8_t rw_flash_changed;
static uint32_t info_data[6];
extern void pd_rx_handler(void);
/* RW firmware reset vector */
@@ -60,12 +57,16 @@ int is_ro_mode(void)
static int check_rw_valid(void)
{
int good;
void *rw_hash;
/* Check if we have a RW firmware flashed */
if (*rw_rst == 0xffffffff)
return 0;
good = rsa_verify(&pkey, (void *)rw_sig, (void *)rw_hash, rsa_workbuf);
/* calculate hash of RW */
rw_hash = flash_hash_rw();
good = rsa_verify(&pkey, (void *)rw_sig, rw_hash, rsa_workbuf);
if (!good) {
debug_printf("RSA verify FAILED\n");
return 0;
@@ -74,30 +75,6 @@ static int check_rw_valid(void)
return 1;
}
uint32_t *board_get_info(void)
{
if (rw_flash_changed) {
/* re-calculate RW hash */
rw_hash = flash_hash_rw();
rw_flash_changed = 0;
}
/* copy first 20 bytes of RW hash */
memcpy(info_data, rw_hash, 5 * sizeof(uint32_t));
/* copy other info into data msg */
info_data[5] = VDO_INFO(CONFIG_USB_PD_HW_DEV_ID_BOARD_MAJOR,
CONFIG_USB_PD_HW_DEV_ID_BOARD_MINOR,
ver_get_numcommits(), !is_ro_mode());
return info_data;
}
void board_rw_contents_change(void)
{
rw_flash_changed = 1;
}
extern void pd_task(void);
int main(void)
@@ -106,9 +83,6 @@ int main(void)
debug_printf("Power supply started ... %s\n",
is_ro_mode() ? "RO" : "RW");
/* calculate hash of RW */
rw_hash = flash_hash_rw();
/* Verify RW firmware and use it if valid */
if (is_ro_mode() && check_rw_valid())
jump_to_rw();
@@ -118,6 +92,6 @@ int main(void)
debug_printf("background loop exited !\n");
/* we should never reach that point */
cpu_reset();
system_reset(0);
return 0;
}

View File

@@ -109,13 +109,6 @@ int32_t get_rtc_diff(uint32_t rtc0, uint32_t rtc0ss,
uint32_t rtc1, uint32_t rtc1ss);
void __enter_hibernate(uint32_t seconds, uint32_t microseconds);
/* Reboot the CPU */
void cpu_reset(void);
/* Board version information functions */
uint32_t *board_get_info(void);
void board_rw_contents_change(void);
#endif /* !__ASSEMBLER__ */
#endif /* __BOARD_H */

View File

@@ -298,16 +298,12 @@ int adc_disable_watchdog(void)
#define STRT (1<<6)
#define CR_LOCK (1<<7)
int flash_write_rw(int offset, int size, const char *data)
int flash_physical_write(int offset, int size, const char *data)
{
uint16_t *address = (uint16_t *)
(CONFIG_FLASH_BASE + CONFIG_FW_RW_OFF + offset);
uint16_t *address = (uint16_t *)(CONFIG_FLASH_BASE + offset);
int res = EC_SUCCESS;
int i;
/* notify board of a RW flash contents change */
board_rw_contents_change();
if ((uint32_t)address > CONFIG_FLASH_BASE + CONFIG_FLASH_SIZE)
return EC_ERROR_INVAL;
@@ -353,14 +349,9 @@ exit_wr:
return res;
}
int flash_erase_rw(void)
int flash_physical_erase(int offset, int size)
{
int res = EC_SUCCESS;
int offset = CONFIG_FW_RW_OFF;
int size = CONFIG_FW_RW_SIZE;
/* notify board of a RW flash contents change */
board_rw_contents_change();
/* unlock CR if needed */
if (STM32_FLASH_CR & CR_LOCK) {

View File

@@ -205,6 +205,10 @@ void cpu_reset(void)
;
}
void system_reset(int flags)
{
cpu_reset();
}
/**
* Default exception handler, which reports a panic.
*

View File

@@ -14,7 +14,6 @@
#include "timer.h"
#include "util.h"
#include "usb_pd.h"
#include "version.h"
/* ------------------------- Power supply control ------------------------ */
@@ -491,69 +490,33 @@ const struct svdm_response svdm_rsp = {
static int pd_custom_vdm(int port, int cnt, uint32_t *payload,
uint32_t **rpayload)
{
static int flash_offset;
int cmd = PD_VDO_CMD(payload[0]);
int rsize = 1;
int rsize;
if (PD_VDO_VID(payload[0]) != USB_VID_GOOGLE || !gfu_mode)
return 0;
debug_printf("%T] VDM/%d [%d] %08x\n", cnt, cmd, payload[0]);
*rpayload = payload;
switch (cmd) {
case VDO_CMD_VERSION:
memcpy(payload + 1, &version_data.version, 24);
rsize = 7;
break;
case VDO_CMD_REBOOT:
/* ensure the power supply is in a safe state */
pd_power_supply_reset(0);
cpu_reset();
break;
case VDO_CMD_READ_INFO:
/* copy info into response */
memcpy(payload + 1, board_get_info(), 24);
rsize = 7;
break;
case VDO_CMD_FLASH_ERASE:
/* do not kill the code under our feet */
if (!is_ro_mode())
rsize = pd_custom_flash_vdm(port, cnt, payload);
if (!rsize) {
switch (cmd) {
case VDO_CMD_PING_ENABLE:
pd_ping_enable(0, payload[1]);
rsize = 1;
break;
flash_offset = 0;
flash_erase_rw();
break;
case VDO_CMD_FLASH_WRITE:
/* do not kill the code under our feet */
if (!is_ro_mode())
case VDO_CMD_CURRENT:
/* return last measured current */
payload[1] = ADC_TO_CURR_MA(vbus_amp);
rsize = 2;
break;
flash_write_rw(flash_offset, 4*(cnt - 1),
(const char *)(payload+1));
flash_offset += 4*(cnt - 1);
break;
case VDO_CMD_ERASE_SIG:
/* this is not touching the code area */
{
uint32_t zero = 0;
int offset;
/* zeroes the area containing the RSA signature */
for (offset = CONFIG_FW_RW_SIZE - 256;
offset < CONFIG_FW_RW_SIZE; offset += 4)
flash_write_rw(offset, 4, (const char *)&zero);
default:
/* Unknown : do not answer */
return 0;
}
break;
case VDO_CMD_PING_ENABLE:
pd_ping_enable(0, payload[1]);
break;
case VDO_CMD_CURRENT:
/* return last measured current */
payload[1] = ADC_TO_CURR_MA(vbus_amp);
rsize = 2;
break;
default:
/* Unknown : do not answer */
return 0;
}
debug_printf("%T] DONE\n");
/* respond (positively) to the request */
payload[0] |= VDO_SRC_RESPONDER;

View File

@@ -26,7 +26,8 @@ endif
# Select between 16-bit and 32-bit timer for clock source
TIMER_TYPE=$(if $(CONFIG_STM_HWTIMER32),32,)
chip-y=dma.o system.o
chip-y=dma.o
chip-$(CONFIG_COMMON_RUNTIME)+=system.o
chip-y+=jtag-$(CHIP_FAMILY).o clock-$(CHIP_FAMILY).o
chip-$(CONFIG_SPI)+=spi.o
chip-$(CONFIG_SPI_MASTER_PORT)+=spi_master.o
@@ -40,9 +41,11 @@ chip-$(HAS_TASK_CONSOLE)+=uart.o
chip-$(HAS_TASK_KEYSCAN)+=keyboard_raw.o
chip-$(HAS_TASK_POWERLED)+=power_led.o
chip-$(CONFIG_FLASH)+=flash-$(CHIP_FAMILY).o
ifdef CONFIG_FLASH
chip-$(CHIP_FAMILY_STM32F)+=flash-f.o
chip-$(CHIP_FAMILY_STM32F0)+=flash-f.o
chip-$(CHIP_FAMILY_STM32F3)+=flash-f.o
endif
chip-$(CONFIG_ADC)+=adc-$(CHIP_FAMILY).o
chip-$(CONFIG_PWM)+=pwm.o
chip-$(CONFIG_USB)+=usb.o usb-$(CHIP_FAMILY).o usb_endpoints.o

View File

@@ -6,10 +6,14 @@
#include "atomic.h"
#include "common.h"
#include "console.h"
#include "flash.h"
#include "gpio.h"
#include "hooks.h"
#include "host_command.h"
#include "registers.h"
#include "rsa.h"
#include "sha256.h"
#include "system.h"
#include "task.h"
#include "timer.h"
#include "util.h"
@@ -26,6 +30,8 @@
#define CPRINTF(format, args...)
#endif
static int rw_flash_changed = 1;
#ifdef CONFIG_USB_PD_ALT_MODE
#ifdef CONFIG_USB_PD_ALT_MODE_DFP
@@ -475,3 +481,97 @@ DECLARE_HOST_COMMAND(EC_CMD_USB_PD_DISCOVERY,
hc_remote_pd_discovery,
EC_VER_MASK(0));
#endif
#define FW_RW_END (CONFIG_FW_RW_OFF + CONFIG_FW_RW_SIZE)
uint8_t *flash_hash_rw(void)
{
static struct sha256_ctx ctx;
/* re-calculate RW hash when changed as its time consuming */
if (rw_flash_changed) {
rw_flash_changed = 0;
SHA256_init(&ctx);
SHA256_update(&ctx, (void *)CONFIG_FLASH_BASE +
CONFIG_FW_RW_OFF,
CONFIG_FW_RW_SIZE - RSANUMBYTES);
return SHA256_final(&ctx);
} else {
return ctx.buf;
}
}
void pd_get_info(uint32_t *info_data)
{
void *rw_hash = flash_hash_rw();
/* copy first 20 bytes of RW hash */
memcpy(info_data, rw_hash, 5 * sizeof(uint32_t));
/* copy other info into data msg */
#if defined(CONFIG_USB_PD_HW_DEV_ID_BOARD_MAJOR) && \
defined(CONFIG_USB_PD_HW_DEV_ID_BOARD_MINOR)
info_data[5] = VDO_INFO(CONFIG_USB_PD_HW_DEV_ID_BOARD_MAJOR,
CONFIG_USB_PD_HW_DEV_ID_BOARD_MINOR,
ver_get_numcommits(),
(system_get_image_copy() != SYSTEM_IMAGE_RO));
#else
info_data[5] = 0;
#endif
}
int pd_custom_flash_vdm(int port, int cnt, uint32_t *payload)
{
static int flash_offset;
int rsize = 1; /* default is just VDM header returned */
switch (PD_VDO_CMD(payload[0])) {
case VDO_CMD_VERSION:
memcpy(payload + 1, &version_data.version, 24);
rsize = 7;
break;
case VDO_CMD_REBOOT:
/* ensure the power supply is in a safe state */
pd_power_supply_reset(0);
system_reset(0);
break;
case VDO_CMD_READ_INFO:
/* copy info into response */
pd_get_info(payload + 1);
rsize = 7;
break;
case VDO_CMD_FLASH_ERASE:
/* do not kill the code under our feet */
if (system_get_image_copy() != SYSTEM_IMAGE_RO)
break;
flash_offset = CONFIG_FW_RW_OFF;
flash_physical_erase(CONFIG_FW_RW_OFF, CONFIG_FW_RW_SIZE);
rw_flash_changed = 1;
break;
case VDO_CMD_FLASH_WRITE:
/* do not kill the code under our feet */
if ((system_get_image_copy() != SYSTEM_IMAGE_RO) ||
(flash_offset < CONFIG_FW_RW_OFF))
break;
flash_physical_write(flash_offset, 4*(cnt - 1),
(const char *)(payload+1));
flash_offset += 4*(cnt - 1);
rw_flash_changed = 1;
break;
case VDO_CMD_ERASE_SIG:
/* this is not touching the code area */
{
uint32_t zero = 0;
int offset;
/* zeroes the area containing the RSA signature */
for (offset = FW_RW_END - RSANUMBYTES;
offset < FW_RW_END; offset += 4)
flash_physical_write(offset, 4,
(const char *)&zero);
}
break;
default:
/* Unknown : do not answer */
return 0;
}
return rsize;
}

View File

@@ -15,8 +15,6 @@
#include "hooks.h"
#include "host_command.h"
#include "registers.h"
#include "rsa.h"
#include "sha256.h"
#include "system.h"
#include "task.h"
#include "timer.h"
@@ -1329,35 +1327,6 @@ void pd_dev_store_rw_hash(int port, uint16_t dev_id, uint32_t *rw_hash)
pd_dev_dump_info(dev_id, (uint8_t *)rw_hash);
}
uint8_t *flash_hash_rw(void)
{
static struct sha256_ctx ctx;
SHA256_init(&ctx);
SHA256_update(&ctx, (void *)CONFIG_FLASH_BASE + CONFIG_FW_RW_OFF,
CONFIG_FW_RW_SIZE - RSANUMBYTES);
return SHA256_final(&ctx);
}
void pd_get_info(uint32_t *info_data)
{
void *hash;
/* calculate RW hash */
hash = flash_hash_rw();
/* copy first 20 bytes of RW hash */
memcpy(info_data, hash, 5 * sizeof(uint32_t));
/* copy other info into data msg */
#if defined(CONFIG_USB_PD_HW_DEV_ID_BOARD_MAJOR) && \
defined(CONFIG_USB_PD_HW_DEV_ID_BOARD_MINOR)
info_data[5] = VDO_INFO(CONFIG_USB_PD_HW_DEV_ID_BOARD_MAJOR,
CONFIG_USB_PD_HW_DEV_ID_BOARD_MINOR,
ver_get_numcommits(),
(system_get_image_copy() != SYSTEM_IMAGE_RO));
#else
info_data[5] = 0;
#endif
}
#ifdef CONFIG_USB_PD_DUAL_ROLE
void pd_set_dual_role(enum pd_dual_role_states state)
{

View File

@@ -820,6 +820,16 @@ int pd_vdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload);
*/
int pd_svdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload);
/**
* Handle Custom VDMs for flashing.
*
* @param port USB-C port number
* @param cnt number of data objects in the payload.
* @param payload payload data.
* @return if >0, number of VDOs to send back.
*/
int pd_custom_flash_vdm(int port, int cnt, uint32_t *payload);
/**
* Exit alternate mode
*
@@ -1165,4 +1175,5 @@ void pd_soft_reset(void);
* @param port USB-C port number
*/
void pd_set_new_power_request(int port);
#endif /* __USB_PD_H */