mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-12-28 10:45:22 +00:00
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:
committed by
chrome-internal-fetch
parent
b5557217aa
commit
bc16903667
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -205,6 +205,10 @@ void cpu_reset(void)
|
||||
;
|
||||
}
|
||||
|
||||
void system_reset(int flags)
|
||||
{
|
||||
cpu_reset();
|
||||
}
|
||||
/**
|
||||
* Default exception handler, which reports a panic.
|
||||
*
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user