mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-12-27 18:25:05 +00:00
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:
committed by
chrome-internal-fetch
parent
01c331fd33
commit
c817472c07
@@ -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]);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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())
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user