Update Zinger flashing process

Convert the Zinger flash update commands to the new RSA signature
mechanism.

Signed-off-by: Vincent Palatin <vpalatin@chromium.org>

BRANCH=samus
BUG=chrome-os-partner:28336
TEST=from the workstation:
./util/flash_pd.py -m 1 build/zinger/ec.RW.bin
from Samus command-line :
ectool --name=cros_pd flashpd 0 1 ec.RW.bin

Change-Id: Ie8cd7f644ec94e461c5775a4dbbcd408782c72e1
Reviewed-on: https://chromium-review.googlesource.com/221560
Reviewed-by: Alec Berg <alecaberg@chromium.org>
Tested-by: Vincent Palatin <vpalatin@chromium.org>
Commit-Queue: Vincent Palatin <vpalatin@chromium.org>
This commit is contained in:
Vincent Palatin
2014-10-03 15:17:25 -07:00
committed by chrome-internal-fetch
parent 01c331fd33
commit c817472c07
6 changed files with 49 additions and 102 deletions

View File

@@ -418,10 +418,16 @@ int pd_custom_vdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload)
(const char *)(payload+1));
flash_offset += 4*(cnt - 1);
break;
case VDO_CMD_FLASH_HASH:
case VDO_CMD_ERASE_SIG:
/* this is not touching the code area */
flash_write_rw(CONFIG_FW_RW_SIZE - 32, 4*cnt,
(const char *)(payload+1));
{
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);
}
break;
case VDO_CMD_PING_ENABLE:
pd_ping_enable(0, payload[1]);

View File

@@ -1586,15 +1586,9 @@ static int remote_flashing(int argc, char **argv)
} else if (!strcasecmp(argv[3], "reboot")) {
cmd = VDO_CMD_REBOOT;
ccprintf("REBOOT ...");
} else if (!strcasecmp(argv[3], "hash")) {
int i;
argc -= 4;
for (i = 0; i < argc; i++)
if (hex8tou32(argv[i+4], data + i))
return EC_ERROR_INVAL;
cmd = VDO_CMD_FLASH_HASH;
cnt = argc;
ccprintf("HASH ...");
} else if (!strcasecmp(argv[3], "signature")) {
cmd = VDO_CMD_ERASE_SIG;
ccprintf("ERASE SIG ...");
} else if (!strcasecmp(argv[3], "info")) {
cmd = VDO_CMD_READ_INFO;
ccprintf("INFO...");
@@ -1936,16 +1930,9 @@ static int hc_remote_flash(struct host_cmd_handler_args *args)
task_wait_event(100*MSEC);
break;
case USB_PD_FW_FLASH_HASH:
/* Can only write 20 bytes */
if (p->size != 20)
return EC_RES_INVALID_PARAM;
ccprintf("PD Update - Write RW flash hash ");
for (i = 0; i < 5; i++)
ccprintf("%08x ", *(data + i));
ccprintf("\n");
pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_FLASH_HASH, data, 5);
case USB_PD_FW_ERASE_SIG:
ccprintf("PD Update - Erase RW RSA signature\n");
pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_ERASE_SIG, NULL, 0);
/* Wait until VDM is done */
while (pd[port].vdm_state > 0)

View File

@@ -2650,7 +2650,7 @@ enum usb_pd_fw_update_cmds {
USB_PD_FW_REBOOT,
USB_PD_FW_FLASH_ERASE,
USB_PD_FW_FLASH_WRITE,
USB_PD_FW_FLASH_HASH,
USB_PD_FW_ERASE_SIG,
};
struct ec_params_usb_pd_fw_update {

View File

@@ -126,7 +126,7 @@ enum pd_errors {
#define VDO_CMD_REBOOT VDO_CMD_VENDOR(5)
#define VDO_CMD_FLASH_ERASE VDO_CMD_VENDOR(6)
#define VDO_CMD_FLASH_WRITE VDO_CMD_VENDOR(7)
#define VDO_CMD_FLASH_HASH VDO_CMD_VENDOR(8)
#define VDO_CMD_ERASE_SIG VDO_CMD_VENDOR(8)
#define VDO_CMD_PING_ENABLE VDO_CMD_VENDOR(10)
#define VDO_CMD_CURRENT VDO_CMD_VENDOR(11)

View File

@@ -856,16 +856,15 @@ int cmd_pd_device_info(int argc, char *argv[])
/* PD image size is 16k minus 32 bits for the RW hash */
#define PD_RW_IMAGE_SIZE (16 * 1024 - 32)
static struct sha1_ctx ctx;
#define PD_RW_IMAGE_SIZE (16 * 1024)
int cmd_flash_pd(int argc, char *argv[])
{
struct ec_params_usb_pd_fw_update *p =
(struct ec_params_usb_pd_fw_update *)ec_outbuf;
int i;
int rv, fsize, step = 96, padding_size;
int rv, fsize, step = 96;
char *e;
char *buf, *fw_padding;
char *buf;
uint32_t *data = &(p->size) + 1;
if (argc < 4) {
@@ -892,21 +891,13 @@ int cmd_flash_pd(int argc, char *argv[])
return -1;
/* Verify size of file */
if (fsize > PD_RW_IMAGE_SIZE)
if (fsize != PD_RW_IMAGE_SIZE)
goto pd_flash_error;
/* Add padding to image */
padding_size = PD_RW_IMAGE_SIZE - fsize;
fw_padding = (char *)malloc(padding_size);
memset(fw_padding, 0xff, padding_size);
fprintf(stderr, "File size %d, Padding size %d\n", fsize, padding_size);
/* Write expected flash hash to all 0s */
/* Erase the current RW RSA signature */
fprintf(stderr, "Erasing expected RW hash\n");
p->cmd = USB_PD_FW_FLASH_HASH;
p->size = 20;
for (i = 0; i < 5; i++)
*(data + i) = 0;
p->cmd = USB_PD_FW_ERASE_SIG;
p->size = 0;
rv = ec_command(EC_CMD_USB_PD_FW_UPDATE, 0,
p, p->size + sizeof(*p), NULL, 0);
@@ -947,30 +938,6 @@ int cmd_flash_pd(int argc, char *argv[])
goto pd_flash_error;
}
/*
* TODO(crosbug.com/p/31552): Would be better to have sha1 in the RW
* binary and we won't have to calculate it here and send it down.
*/
/* Calculate sha1 of new RW flash */
sha1_init(&ctx);
sha1_update(&ctx, buf, fsize);
sha1_update(&ctx, fw_padding, padding_size);
sha1_final(&ctx);
/* Write expected flash hash */
fprintf(stderr, "Setting expected RW hash\n");
p->cmd = USB_PD_FW_FLASH_HASH;
p->size = 20;
memcpy(data, ctx.buf.b, p->size);
for (i = 0; i < 5; i++)
fprintf(stderr, "%08x ", *(data + i));
fprintf(stderr, "\n");
rv = ec_command(EC_CMD_USB_PD_FW_UPDATE, 0,
p, p->size + sizeof(*p), NULL, 0);
if (rv < 0)
goto pd_flash_error;
free(buf);
fprintf(stderr, "Complete\n");
return 0;

View File

@@ -5,12 +5,11 @@
"""Flash PD PSU RW firmware over the USBPD comm channel using console.
Example:
util/flash_pd.py ./build/zinger/ec.RW.flat
util/flash_pd.py ./build/zinger/ec.RW.bin
"""
import array
import errno
import hashlib
import logging
import optparse
import os
@@ -24,13 +23,12 @@ import serial
from servo import client
from servo import multiservo
VERSION = '0.0.1'
# RW area is half of the 32-kB flash minus the hash storage area
MAX_FW_SIZE = 16 * 1024 - 32
# Hash of RW when erased (set to all F's)
ERASED_RW_HASH = 'd582e94d 0d12a61c 1199927e 5610c036 2e2870a9'
VERSION = '0.0.2'
# RW area is half of the 32-kB
MAX_FW_SIZE = 16 * 1024
# 20 first bytes of SHA-256 of RW when erased (set to all F's)
ERASED_RW_HASH = 'd86670be 559860c7 2b2149e8 d2ae1104 9550e093'
class FlashPDError(Exception):
"""Exception class for flash_pd utility."""
@@ -200,14 +198,10 @@ def flash_pd(options):
with open(options.firmware) as fd:
fw = fd.read()
fw_size = len(fw)
# Compute SHA-1 hash for the full (padded) RW firmware
padded_fw = fw + '\xff' * (MAX_FW_SIZE - fw_size)
sha = hashlib.sha1(padded_fw).digest()
sha_str = ' '.join(['%08x' % (w) for w in array.array('I', sha)])
# The RW firmware should be already padded and signed
if fw_size != MAX_FW_SIZE:
raise FlashPDError('Bad RW firmware size %d/%d' % (fw_size, MAX_FW_SIZE))
# pad the firmware to a multiple of 6 U32
if fw_size % 24:
fw += '\xff'*(24 - fw_size % 24)
words = array.array('I', fw)
logging.info('Current PD FW version is %s', ec.get_version())
@@ -216,31 +210,23 @@ def flash_pd(options):
logging.info('Flashing %d bytes', fw_size)
# reset flashed hash to reboot in RO
ec.flash_command('hash' + ' 00000000' * 5)
# reset flashed signature to reboot in RO
ec.flash_command('signature')
# reboot in RO
ec.reboot()
# erase all RW partition
ec.flash_command('erase')
# TODO(tbroch) deprecate rw_hash if/when command is completely deprecated in
# favor of 'info'
# verify that erase was successful by reading hash empty RW
(done, _) = ec.flash_command('rw_hash', expect=ERASED_RW_HASH, retries=0,
ignore_fail=True)
if done:
done = ec.expect('DONE')
else:
# try info command and guarantee we're in RO
(done, line) = ec.flash_command('info', expect=r'INFO')
m = re.match(r'INFO.*(18d1\S{4})', line)
if done and m:
done = ec.expect('DONE 0')
in_rw = int(m.group(1), 16) & 0x1
if in_rw:
raise FlashPDError('Not in RO after erase')
# Google UFP devices share their hash to DFP after info command so check it
(done, _) = ec.pd_command('hash', expect=ERASED_RW_HASH)
# try info command and guarantee we're in RO
(done, line) = ec.flash_command('info', expect=r'INFO')
m = re.match(r'INFO.*(18d1\S{4})', line)
if done and m:
done = ec.expect('DONE 0')
in_rw = int(m.group(1), 16) & 0x1
if in_rw:
raise FlashPDError('Not in RO after erase')
# Google UFP devices share their hash to DFP after info command so check it
(done, _) = ec.pd_command('hash', expect=ERASED_RW_HASH)
if not done:
raise FlashPDError('Erase failed')
@@ -259,14 +245,15 @@ def flash_pd(options):
ec.flash_command(cmd)
if not i % 0x10:
logging.info('Chunk %d of %d done.', i, len(words) / 6)
# write the remaining words
chunk = words[len(words) / 6 * 6:]
cmd = ' '.join(['%08x' % (w) for w in chunk])
ec.flash_command(cmd)
# write new firmware hash
ec.flash_command('hash ' + sha_str)
# reboot in RW
ec.reboot()
logging.info('Flashing DONE.')
logging.info('SHA-1: %s', sha_str)
logging.info('New PD FW version is %s', ec.get_version())