summaryrefslogtreecommitdiff
path: root/extra/usb_updater
diff options
context:
space:
mode:
Diffstat (limited to 'extra/usb_updater')
-rw-r--r--extra/usb_updater/.gitignore6
-rw-r--r--extra/usb_updater/Makefile55
-rw-r--r--extra/usb_updater/c2d2.json15
-rw-r--r--extra/usb_updater/desc_parser.c377
-rw-r--r--extra/usb_updater/desc_parser.h58
l---------extra/usb_updater/ecusb1
-rwxr-xr-xextra/usb_updater/fw_update.py426
-rw-r--r--extra/usb_updater/sample_descriptor87
-rw-r--r--extra/usb_updater/servo_micro.json15
-rwxr-xr-xextra/usb_updater/servo_updater.py456
-rw-r--r--extra/usb_updater/servo_v4.json15
-rw-r--r--extra/usb_updater/servo_v4p1.json15
-rw-r--r--extra/usb_updater/sweetberry.json14
-rw-r--r--extra/usb_updater/usb_updater2.c1244
14 files changed, 0 insertions, 2784 deletions
diff --git a/extra/usb_updater/.gitignore b/extra/usb_updater/.gitignore
deleted file mode 100644
index 37c3bd3808..0000000000
--- a/extra/usb_updater/.gitignore
+++ /dev/null
@@ -1,6 +0,0 @@
-generated_version.h
-gsctool
-usb_updater2
-*.d
-*.o
-dp \ No newline at end of file
diff --git a/extra/usb_updater/Makefile b/extra/usb_updater/Makefile
deleted file mode 100644
index 1dfbc55645..0000000000
--- a/extra/usb_updater/Makefile
+++ /dev/null
@@ -1,55 +0,0 @@
-# Copyright 2015 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.
-
-CC ?= gcc
-PKG_CONFIG ?= pkg-config
-PROGRAMS := usb_updater2
-LIBS :=
-LFLAGS :=
-CFLAGS := -std=gnu99 \
- -g \
- -Wall \
- -Werror \
- -Wpointer-arith \
- -Wcast-align \
- -Wcast-qual \
- -Wundef \
- -Wsign-compare \
- -Wredundant-decls \
- -Wmissing-declarations
-
-ifeq (DEBUG,)
-CFLAGS += -O3
-else
-CFLAGS += -O0
-endif
-
-#
-# Add libusb-1.0 required flags
-#
-LIBS += $(shell $(PKG_CONFIG) --libs libusb-1.0)
-CFLAGS += $(shell $(PKG_CONFIG) --cflags libusb-1.0)
-CFLAGS += -I../../include -I../../util -I../../fuzz -I../../test
-
-VPATH = ../../util
-
-LIBS_common = -lfmap
-
-all: $(PROGRAMS)
-
-%.o: %.c
- $(CC) $(CFLAGS) -c -MMD -MF $(basename $@).d -o $@ $<
-
-# common EC code USB updater
-usb_updater2: usb_updater2.c Makefile
- $(CC) $(CFLAGS) $< $(LFLAGS) $(LIBS) $(LIBS_common) -o $@
-
-.PHONY: clean
-
-clean:
- rm -rf $(PROGRAMS) *~ *.o *.d dp
-
-parser_debug: desc_parser.c
- gcc -g -O0 -DTEST_PARSER desc_parser.c -o dp
-
diff --git a/extra/usb_updater/c2d2.json b/extra/usb_updater/c2d2.json
deleted file mode 100644
index 79fc6f0992..0000000000
--- a/extra/usb_updater/c2d2.json
+++ /dev/null
@@ -1,15 +0,0 @@
-{
- "Comment": "This file describes the updateable sections of the flash.",
- "board": "c2d2",
- "vid": "0x18d1",
- "pid": "0x5041",
- "console": "3",
- "Comment on flash": "This is the base address of writeable flash",
- "flash": "0x8000000",
- "Comment on region format": "name: [baseoffset, length]",
- "regions": {
- "RW": ["0x10000", "0x10000"],
- "PSTATE": ["0xf000", "0x1000"],
- "RO": ["0x0000", "0xf000"]
- }
-}
diff --git a/extra/usb_updater/desc_parser.c b/extra/usb_updater/desc_parser.c
deleted file mode 100644
index 5bd996bdda..0000000000
--- a/extra/usb_updater/desc_parser.c
+++ /dev/null
@@ -1,377 +0,0 @@
-/*
- * Copyright 2018 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 <ctype.h>
-#include <errno.h>
-#include <malloc.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-
-#include "desc_parser.h"
-
-static FILE *hash_file_;
-static int line_count_;
-static int section_count_;
-
-/*
- * This is used to verify consistency of the description database, namely that
- * all hash sections include the same number of hash variants.
- */
-static size_t variant_count;
-
-/* Size of the retrieved string or negative OS error value. */
-static ssize_t get_next_line(char *next_line, size_t line_size)
-{
- size_t index = 0;
-
- while (fgets(next_line + index, line_size - index, hash_file_)) {
- line_count_++;
-
- if (next_line[index] == '#')
- continue; /* Skip the comment */
-
- if (next_line[index] == '\n') {
- /*
- * This is an empty line, return all collected data,
- * pontintially an array of size zero if this is a
- * repeated empty line.
- */
- next_line[index] = '\0';
- return index;
- }
-
- /* Make sure next string overwrites this string's newline. */
- index += strlen(next_line + index) - 1;
-
- if (index >= (line_size - 1)) {
- fprintf(stderr, "%s: Input overflow in line %d\n",
- __func__, line_count_);
- return -EOVERFLOW;
- }
- }
-
- if (index) {
- /*
- * This must be the last line in the file with no empty line
- * after it. Drop the closing newline, if it is there.
- */
- if (next_line[index] == '\n')
- next_line[index--] = '\0';
-
- return index;
- }
- return errno ? -errno : -ENODATA;
-}
-
-static int get_next_token(char *input, size_t expected_size, char **output)
-{
- char *next_colon;
-
- next_colon = strchr(input, ':');
- if (next_colon)
- *next_colon = '\0';
- if (!next_colon || (expected_size &&
- strlen(input) != expected_size)) {
- fprintf(stderr, "Invalid entry in section %d\n",
- section_count_);
- return -EINVAL;
- }
-
- *output = next_colon + 1;
- return 0;
-}
-
-static int get_hex_value(char *input, char **output)
-{
- char *e;
- long int value;
-
- if (strchr(input, ':'))
- get_next_token(input, 0, output);
- else
- *output = NULL;
-
- value = strtol(input, &e, 16);
- if ((e && *e) || (strlen(input) > 8)) {
- fprintf(stderr, "Invalid hex value %s in section %d\n",
- input, section_count_);
- return -EINVAL;
- }
-
- return value;
-}
-
-static int parse_range(char *next_line,
- size_t line_len,
- struct addr_range *parsed_range)
-{
- char *line_cursor;
- char *next_token;
- int is_a_hash_range;
- struct result_node *node;
- int value;
-
- section_count_++;
- line_cursor = next_line;
-
- /* Range type. */
- if (get_next_token(line_cursor, 1, &next_token))
- return -EINVAL;
-
- switch (*line_cursor) {
- case 'a':
- parsed_range->range_type = AP_RANGE;
- break;
- case 'e':
- parsed_range->range_type = EC_RANGE;
- break;
- case 'g':
- parsed_range->range_type = EC_GANG_RANGE;
- break;
- default:
- fprintf(stderr, "Invalid range type %c in section %d\n",
- *line_cursor, section_count_);
- return -EINVAL;
- }
- line_cursor = next_token;
-
- /* Hash or dump? */
- if (get_next_token(line_cursor, 1, &next_token))
- return -EINVAL;
-
- switch (*line_cursor) {
- case 'd':
- is_a_hash_range = 0;
- break;
- case 'h':
- is_a_hash_range = 1;
- break;
- default:
- fprintf(stderr, "Invalid entry kind %c in section %d\n",
- *line_cursor, section_count_);
- return -EINVAL;
- }
- line_cursor = next_token;
-
- /* Range base address. */
- value = get_hex_value(line_cursor, &next_token);
- if (value < 0)
- return -EINVAL;
- parsed_range->base_addr = value;
-
- /* Range size. */
- line_cursor = next_token;
- value = get_hex_value(line_cursor, &next_token);
- if (value < 0)
- return -EINVAL;
- parsed_range->range_size = value;
-
- if (!next_token && is_a_hash_range) {
- fprintf(stderr, "Missing hash in section %d\n", section_count_);
- return -EINVAL;
- }
-
- if (next_token && !is_a_hash_range) {
- fprintf(stderr, "Unexpected data in section %d\n",
- section_count_);
- return -EINVAL;
- }
-
- parsed_range->variant_count = 0;
- if (!is_a_hash_range)
- return 0; /* No more input for dump ranges. */
-
- node = parsed_range->variants;
- do { /* While line is not over. */
- char c;
- int i = 0;
-
- line_cursor = next_token;
- next_token = strchr(line_cursor, ':');
- if (next_token)
- *next_token++ = '\0';
- if (strlen(line_cursor) != (2 * sizeof(*node))) {
- fprintf(stderr,
- "Invalid hash %zd size %zd in section %d\n",
- parsed_range->variant_count + 1,
- strlen(line_cursor), section_count_);
- return -EINVAL;
- }
-
- while ((c = *line_cursor++) != 0) {
- uint8_t nibble;
-
- if (!isxdigit(c)) {
- fprintf(stderr,
- "Invalid hash %zd value in section %d\n",
- parsed_range->variant_count + 1,
- section_count_);
- return -EINVAL;
- }
-
- if (c <= '9')
- nibble = c - '0';
- else if (c >= 'a')
- nibble = c - 'a' + 10;
- else
- nibble = c - 'A' + 10;
-
- if (i & 1)
- node->expected_result[i / 2] |= nibble;
- else
- node->expected_result[i / 2] = nibble << 4;
-
- i++;
- }
-
- node++;
- parsed_range->variant_count++;
-
- } while (next_token);
-
- return 0;
-}
-
-int parser_get_next_range(struct addr_range **range)
-{
- char next_line[1000]; /* Should be enough for the largest descriptor. */
- ssize_t entry_size;
- struct addr_range *new_range;
- int rv;
-
- /*
- * We come here after hash descriptor database file was opened and the
- * current board's section has been found. Just in case check if the
- * file has been opened.
- */
- if (!hash_file_ || !range)
- return -EIO;
-
- *range = NULL;
- do {
- entry_size = get_next_line(next_line, sizeof(next_line));
- if (entry_size < 0)
- return entry_size;
- } while (!entry_size); /* Skip empty lines. */
-
- if (entry_size == 4) /* Next board's entry must have been reached. */
- return -ENODATA;
-
- /* This sure will be enough to fit parsed structure contents. */
- new_range = malloc(sizeof(*new_range) + entry_size);
- if (!new_range) {
- fprintf(stderr, "Failed to allocate %zd bytes\n",
- sizeof(*new_range) + entry_size);
- return -ENOMEM;
- }
-
- /* This must be a new descriptor section, lets parse it. */
- rv = parse_range(next_line, entry_size, new_range);
-
- if (rv) {
- free(new_range);
- return rv;
- }
-
- if (new_range->variant_count) {
- /*
- * A new range was found, if this is the first hash range we
- * encountered, save its dimensions for future reference.
- *
- * If this is not the first one - verify that it has the same
- * number of hash variants as all previous hash blocks.
- */
- if (!variant_count) {
- variant_count = new_range->variant_count;
- } else if (variant_count != new_range->variant_count) {
- fprintf(stderr,
- "Unexpected number of variants in section %d\n",
- section_count_);
- free(new_range);
- return -EINVAL;
- }
- }
-
- *range = new_range;
- return 0;
-
-}
-
-int parser_find_board(const char *hash_file_name, const char *board_id)
-{
- char next_line[1000]; /* Should be enough for the largest descriptor. */
- ssize_t id_len = strlen(board_id);
-
- if (!hash_file_) {
- hash_file_ = fopen(hash_file_name, "r");
- if (!hash_file_) {
- fprintf(stderr, "Error:%s can not open file '%s'\n",
- strerror(errno), hash_file_name);
- return errno;
- }
- }
-
- while (1) {
- ssize_t entry_size;
-
- entry_size = get_next_line(next_line, sizeof(next_line));
- if (entry_size < 0) {
- return entry_size;
- }
-
- if ((entry_size == id_len) &&
- !memcmp(next_line, board_id, id_len)) {
- variant_count = 0;
- return 0;
- }
- }
-
- return -ENODATA;
-}
-
-void parser_done(void)
-{
- if (!hash_file_)
- return;
-
- fclose(hash_file_);
- hash_file_ = NULL;
-}
-
-#ifdef TEST_PARSER
-int main(int argc, char **argv)
-{
- const char *board_name = "QZUX";
- char next_line[1000]; /* Should be enough for the largest descriptor. */
- int rv;
- int count;
-
- if (argc < 2) {
- fprintf(stderr, "Name of the file to parse is required.\n");
- return -1;
- }
-
- if (parser_find_board(argv[1], board_name)) {
- fprintf(stderr, "Board %s NOT found\n", board_name);
- return -1;
- }
-
- count = 0;
- do {
- struct addr_range *range;
-
- rv = parser_get_next_range(&range);
- count++;
- printf("Section %d, rv %d\n", count, rv);
- free(range); /* Freeing NULL is OK. */
-
- } while (rv != -ENODATA);
-
- return 0;
-}
-#endif
diff --git a/extra/usb_updater/desc_parser.h b/extra/usb_updater/desc_parser.h
deleted file mode 100644
index faa80d1a63..0000000000
--- a/extra/usb_updater/desc_parser.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright 2018 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 __EXTRA_USB_UPDATER_DESC_PARSER_H
-#define __EXTRA_USB_UPDATER_DESC_PARSER_H
-
-#include <stddef.h>
-#include <stdint.h>
-
-struct result_node {
- uint8_t expected_result[32];
-};
-
-enum range_type_t {
- NOT_A_RANGE,
- AP_RANGE,
- EC_RANGE,
- EC_GANG_RANGE,
-};
-
-struct addr_range {
- enum range_type_t range_type;
- uint32_t base_addr;
- uint32_t range_size;
- size_t variant_count; /* Set to zero for dump ranges. */
- struct result_node variants[0];
-};
-
-/* Board description retrieval API includes the following functions. */
-
-/*
- * In the given hash database file find board by its ID. Return zero on
- * success, or OS error of error. In particular ENODATA is returned if the
- * section for the required board ID is not found in the file.
- */
-int parser_find_board(const char *hash_file_name, const char board_id[4]);
-
-/*
- * Find next range for the previousely defined board, parse it into the
- * addr_range structure and return pointer to the parsed structure to the
- * caller, set pointer to NULL if no more entries are available or in case of
- * error.
- *
- * Caller of this function is responsible for returning memory allocated for
- * the entry.
- *
- * Return value set to zero on success, or to OS error if one occurs. EIO is
- * used if an attmept to get next range is made before hash database file was
- * opened and board entry in it was found.
- */
-int parser_get_next_range(struct addr_range **range);
-
-/* Close the hash database file. */
-void parser_done(void);
-
-#endif // __EXTRA_USB_UPDATER_DESC_PARSER_H
diff --git a/extra/usb_updater/ecusb b/extra/usb_updater/ecusb
deleted file mode 120000
index c06ee0f51b..0000000000
--- a/extra/usb_updater/ecusb
+++ /dev/null
@@ -1 +0,0 @@
-../tigertool/ecusb/ \ No newline at end of file
diff --git a/extra/usb_updater/fw_update.py b/extra/usb_updater/fw_update.py
deleted file mode 100755
index 0d7a570fc3..0000000000
--- a/extra/usb_updater/fw_update.py
+++ /dev/null
@@ -1,426 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2016 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.
-#
-# Ignore indention messages, since legacy scripts use 2 spaces instead of 4.
-# pylint: disable=bad-indentation,docstring-section-indent
-# pylint: disable=docstring-trailing-quotes
-
-# Upload firmware over USB
-# Note: This is a py2/3 compatible file.
-
-from __future__ import print_function
-
-import argparse
-import array
-import json
-import os
-import struct
-import sys
-import time
-from pprint import pprint
-import usb
-
-
-debug = False
-def debuglog(msg):
- if debug:
- print(msg)
-
-def log(msg):
- print(msg)
- sys.stdout.flush()
-
-
-"""Sends firmware update to CROS EC usb endpoint."""
-
-class Supdate(object):
- """Class to access firmware update endpoints.
-
- Usage:
- d = Supdate()
-
- Instance Variables:
- _dev: pyUSB device object
- _read_ep: pyUSB read endpoint for this interface
- _write_ep: pyUSB write endpoint for this interface
- """
- USB_SUBCLASS_GOOGLE_UPDATE = 0x53
- USB_CLASS_VENDOR = 0xFF
-
- def __init__(self):
- pass
-
-
- def connect_usb(self, serialname=None):
- """Initial discovery and connection to USB endpoint.
-
- This searches for a USB device matching the VID:PID specified
- in the config file, optionally matching a specified serialname.
-
- Args:
- serialname: Find the device with this serial, in case multiple
- devices are attached.
-
- Returns:
- True on success.
- Raises:
- Exception on error.
- """
- # Find the stm32.
- vendor = self._brdcfg['vid']
- product = self._brdcfg['pid']
-
- dev_g = usb.core.find(idVendor=vendor, idProduct=product, find_all=True)
- dev_list = list(dev_g)
- if dev_list is None:
- raise Exception("Update", "USB device not found")
-
- # Check if we have multiple stm32s and we've specified the serial.
- dev = None
- if serialname:
- for d in dev_list:
- if usb.util.get_string(d, d.iSerialNumber) == serialname:
- dev = d
- break
- if dev is None:
- raise SusbError("USB device(%s) not found" % serialname)
- else:
- try:
- dev = dev_list[0]
- except:
- dev = dev_list.next()
-
- debuglog("Found stm32: %04x:%04x" % (vendor, product))
- self._dev = dev
-
- # Get an endpoint instance.
- try:
- dev.set_configuration()
- except:
- pass
- cfg = dev.get_active_configuration()
-
- intf = usb.util.find_descriptor(cfg, custom_match=lambda i: \
- i.bInterfaceClass==self.USB_CLASS_VENDOR and \
- i.bInterfaceSubClass==self.USB_SUBCLASS_GOOGLE_UPDATE)
-
- self._intf = intf
- debuglog("Interface: %s" % intf)
- debuglog("InterfaceNumber: %s" % intf.bInterfaceNumber)
-
- read_ep = usb.util.find_descriptor(
- intf,
- # match the first IN endpoint
- custom_match = \
- lambda e: \
- usb.util.endpoint_direction(e.bEndpointAddress) == \
- usb.util.ENDPOINT_IN
- )
-
- self._read_ep = read_ep
- debuglog("Reader endpoint: 0x%x" % read_ep.bEndpointAddress)
-
- write_ep = usb.util.find_descriptor(
- intf,
- # match the first OUT endpoint
- custom_match = \
- lambda e: \
- usb.util.endpoint_direction(e.bEndpointAddress) == \
- usb.util.ENDPOINT_OUT
- )
-
- self._write_ep = write_ep
- debuglog("Writer endpoint: 0x%x" % write_ep.bEndpointAddress)
-
- return True
-
-
- def wr_command(self, write_list, read_count=1, wtimeout=100, rtimeout=2000):
- """Write command to logger logic..
-
- This function writes byte command values list to stm, then reads
- byte status.
-
- Args:
- write_list: list of command byte values [0~255].
- read_count: number of status byte values to read.
- wtimeout: mS to wait for write success
- rtimeout: mS to wait for read success
-
- Returns:
- status byte, if one byte is read,
- byte list, if multiple bytes are read,
- None, if no bytes are read.
-
- Interface:
- write: [command, data ... ]
- read: [status ]
- """
- debuglog("wr_command(write_list=[%s] (%d), read_count=%s)" % (
- list(bytearray(write_list)), len(write_list), read_count))
-
- # Clean up args from python style to correct types.
- write_length = 0
- if write_list:
- write_length = len(write_list)
- if not read_count:
- read_count = 0
-
- # Send command to stm32.
- if write_list:
- cmd = write_list
- ret = self._write_ep.write(cmd, wtimeout)
- debuglog("RET: %s " % ret)
-
- # Read back response if necessary.
- if read_count:
- bytesread = self._read_ep.read(512, rtimeout)
- debuglog("BYTES: [%s]" % bytesread)
-
- if len(bytesread) != read_count:
- debuglog("Unexpected bytes read: %d, expected: %d" % (len(bytesread), read_count))
- pass
-
- debuglog("STATUS: 0x%02x" % int(bytesread[0]))
- if read_count == 1:
- return bytesread[0]
- else:
- return bytesread
-
- return None
-
- def stop(self):
- """Finalize system flash and exit."""
- cmd = struct.pack(">I", 0xB007AB1E)
- read = self.wr_command(cmd, read_count=4)
-
- if len(read) == 4:
- log("Finished flashing")
- return
-
- raise Exception("Update", "Stop failed [%s]" % read)
-
-
- def write_file(self):
- """Write the update region packet by packet to USB
-
- This sends write packets of size 128B out, in 32B chunks.
- Overall, this will write all data in the inactive code region.
-
- Raises:
- Exception if write failed or address out of bounds.
- """
- region = self._region
- flash_base = self._brdcfg["flash"]
- offset = self._base - flash_base
- if offset != self._brdcfg['regions'][region][0]:
- raise Exception("Update", "Region %s offset 0x%x != available offset 0x%x" % (
- region, self._brdcfg['regions'][region][0], offset))
-
- length = self._brdcfg['regions'][region][1]
- log("Sending")
-
- # Go to the correct region in the ec.bin file.
- self._binfile.seek(offset)
-
- # Send 32 bytes at a time. Must be less than the endpoint's max packet size.
- maxpacket = 32
-
- # While data is left, create update packets.
- while length > 0:
- # Update packets are 128B. We can use any number
- # but the micro must malloc this memory.
- pagesize = min(length, 128)
-
- # Packet is:
- # packet size: page bytes transferred plus 3 x 32b values header.
- # cmd: n/a
- # base: flash address to write this packet.
- # data: 128B of data to write into flash_base
- cmd = struct.pack(">III", pagesize + 12, 0, offset + flash_base)
- read = self.wr_command(cmd, read_count=0)
-
- # Push 'todo' bytes out the pipe.
- todo = pagesize
- while todo > 0:
- packetsize = min(maxpacket, todo)
- data = self._binfile.read(packetsize)
- if len(data) != packetsize:
- raise Exception("Update", "No more data from file")
- for i in range(0, 10):
- try:
- self.wr_command(data, read_count=0)
- break
- except:
- log("Timeout fail")
- todo -= packetsize
- # Done with this packet, move to the next one.
- length -= pagesize
- offset += pagesize
-
- # Validate that the micro thinks it successfully wrote the data.
- read = self.wr_command(''.encode(), read_count=4)
- result = struct.unpack("<I", read)
- result = result[0]
- if result != 0:
- raise Exception("Update", "Upload failed with rc: 0x%x" % result)
-
-
- def start(self):
- """Start a transaction and erase currently inactive region.
-
- This function sends a start command, and receives the base of the
- preferred inactive region. This could be RW, RW_B,
- or RO (if there's no RW_B)
-
- Note that the region is erased here, so you'd better program the RO if
- you just erased it. TODO(nsanders): Modify the protocol to allow active
- region select or query before erase.
- """
-
- # Size is 3 uint32 fields
- # packet: [packetsize, cmd, base]
- size = 4 + 4 + 4
- # Return value is [status, base_addr]
- expected = 4 + 4
-
- cmd = struct.pack("<III", size, 0, 0)
- read = self.wr_command(cmd, read_count=expected)
-
- if len(read) == 4:
- raise Exception("Update", "Protocol version 0 not supported")
- elif len(read) == expected:
- base, version = struct.unpack(">II", read)
- log("Update protocol v. %d" % version)
- log("Available flash region base: %x" % base)
- else:
- raise Exception("Update", "Start command returned %d bytes" % len(read))
-
- if base < 256:
- raise Exception("Update", "Start returned error code 0x%x" % base)
-
- self._base = base
- flash_base = self._brdcfg["flash"]
- self._offset = self._base - flash_base
-
- # Find our active region.
- for region in self._brdcfg['regions']:
- if (self._offset >= self._brdcfg['regions'][region][0]) and \
- (self._offset < (self._brdcfg['regions'][region][0] + \
- self._brdcfg['regions'][region][1])):
- log("Active region: %s" % region)
- self._region = region
-
-
- def load_board(self, brdfile):
- """Load firmware layout file.
-
- example as follows:
- {
- "board": "servo micro",
- "vid": 6353,
- "pid": 20506,
- "flash": 134217728,
- "regions": {
- "RW": [65536, 65536],
- "PSTATE": [61440, 4096],
- "RO": [0, 61440]
- }
- }
-
- Args:
- brdfile: path to board description file.
- """
- with open(brdfile) as data_file:
- data = json.load(data_file)
-
- # TODO(nsanders): validate this data before moving on.
- self._brdcfg = data;
- if debug:
- pprint(data)
-
- log("Board is %s" % self._brdcfg['board'])
- # Cast hex strings to int.
- self._brdcfg['flash'] = int(self._brdcfg['flash'], 0)
- self._brdcfg['vid'] = int(self._brdcfg['vid'], 0)
- self._brdcfg['pid'] = int(self._brdcfg['pid'], 0)
-
- log("Flash Base is %x" % self._brdcfg['flash'])
- self._flashsize = 0
- for region in self._brdcfg['regions']:
- base = int(self._brdcfg['regions'][region][0], 0)
- length = int(self._brdcfg['regions'][region][1], 0)
- log("region %s\tbase:0x%08x size:0x%08x" % (
- region, base, length))
- self._flashsize += length
-
- # Convert these to int because json doesn't support hex.
- self._brdcfg['regions'][region][0] = base
- self._brdcfg['regions'][region][1] = length
-
- log("Flash Size: 0x%x" % self._flashsize)
-
- def load_file(self, binfile):
- """Open and verify size of the target ec.bin file.
-
- Args:
- binfile: path to ec.bin
-
- Raises:
- Exception on file not found or filesize not matching.
- """
- self._filesize = os.path.getsize(binfile)
- self._binfile = open(binfile, 'rb')
-
- if self._filesize != self._flashsize:
- raise Exception("Update", "Flash size 0x%x != file size 0x%x" % (self._flashsize, self._filesize))
-
-
-
-# Generate command line arguments
-parser = argparse.ArgumentParser(description="Update firmware over usb")
-parser.add_argument('-b', '--board', type=str, help="Board configuration json file", default="board.json")
-parser.add_argument('-f', '--file', type=str, help="Complete ec.bin file", default="ec.bin")
-parser.add_argument('-s', '--serial', type=str, help="Serial number", default="")
-parser.add_argument('-l', '--list', action="store_true", help="List regions")
-parser.add_argument('-v', '--verbose', action="store_true", help="Chatty output")
-
-def main():
- global debug
- args = parser.parse_args()
-
-
- brdfile = args.board
- serial = args.serial
- binfile = args.file
- if args.verbose:
- debug = True
-
- with open(brdfile) as data_file:
- names = json.load(data_file)
-
- p = Supdate()
- p.load_board(brdfile)
- p.connect_usb(serialname=serial)
- p.load_file(binfile)
-
- # List solely prints the config.
- if (args.list):
- return
-
- # Start transfer and erase.
- p.start()
- # Upload the bin file
- log("Uploading %s" % binfile)
- p.write_file()
-
- # Finalize
- log("Done. Finalizing.")
- p.stop()
-
-if __name__ == "__main__":
- main()
-
-
diff --git a/extra/usb_updater/sample_descriptor b/extra/usb_updater/sample_descriptor
deleted file mode 100644
index 1566e9e2e1..0000000000
--- a/extra/usb_updater/sample_descriptor
+++ /dev/null
@@ -1,87 +0,0 @@
-# Copyright 2018 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.
-#
-# Hash descriptor database file consists of sections for various Chrome OS
-# boards. Each board description section starts with a line of 4 characters
-# which is the board ID (the same as the board's RLZ code).
-#
-# Each board description section includes variable number of range
-# descriptor entries, each entry consisting of semicolon separated fields:
-#
-# {a|e|g}:{h|d}:base_addr:size[:value[:value[:value...]]]]
-#
-# Where
-#
-# - the first sindgle character field defines the way the range is accessed:
-# a - AP flash
-# e - EC flash
-# g - EC flash requiring gang programming mode
-# - the second single character field defines the range type
-# h - Cr50 returns the hash of the range
-# d - Cr50 returns actual contents of the range (hex dump)
-# - the third and and forth fields are base address and size of the range
-# - ranges of type 'h' include one or more values for the hash of the range.
-#
-# Descriptor entries can be split along multiple lines. Each entry is
-# terminated by an empty line. Board description section is completed when
-# another board ID or end of file is encountered.
-#
-# All values are expressed in hex. Repeating empty lines and lines starting
-# with '#' are ignored.
-#
-
-QZUX
-
-# 1: Valid hash section.
-a:h:0:10000:
-756c41b90ac9aa23a6c98ce13549dccd72e0a83f8537eb834d9cfc3d12bf3503:
-336c41b90ac9aa23a6c98ce13549dccd72e0a83f8537eb834d9cfc3d12bf3503:
-446c41b90ac9aa23a6c98ce13549dccd72e0a83f8537eb834d9cfc3d12bf3503
-
-# 2: Valid dump section.
-a:d:10:10
-
-# 3: Valid hash section.
-e:h:0:100:
-55d262badc1116520a7ae1d3fda380c0382b4b87f0db10de6495053ba3aadb87:
-444442badc1116520a7ae1d3fda380c0382b4b87f0db10de6495053ba3aadb87:
-443322badc1116520a7ae1d3fda380c0382b4b87f0db10de6495053ba3aadb87
-
-# 4: Invalid dump section (includes hash)
-a:d:20:10:55d262badc1116520a7ae1d3fda380c0382b4b87f0db10de6495053ba3aadb87
-
-# 5: Invalid hash section (does not include hash)
-e:h:0:100:
-
-# 6: Another invalid hash section (does not include hash)
-e:h:0:100:
-
-# extra empty lines
-
-
-# 7: Invalid hash section (hash too short)
-e:h:0:100:
-55d262badc1116520a7ae1d3fda380c0382b4b87f0db10de6495053ba3aadb8
-
-# 8: Invalid hash section (hash too long)
-a:h:0:10000:
-756c41b90ac9aa23a6c98ce13549dccd72e0a83f8537eb834d9cfc3d12bf35034:
-336c41b90ac9aa23a6c98ce13549dccd72e0a83f8537eb834d9cfc3d12bf3503
-
-# 9: Invalid hash section (hash includes non-hex value)
-a:h:0:10000:
-756c41b90ac9aa23a6c98ce13549dccd7xe0a83f8537eb834d9cfc3d12bf3503:
-336c41b90ac9aa23a6c98ce13549dccd72e0a83f8537eb834d9cfc3d12bf3505
-
-# 10: Invalid hash section (hash does not include 3 variants)
-a:h:0:10000:
-756c41b90ac9aa23a6c98ce13549dccd75e0a83f8537eb834d9cfc3d12bf3503:
-336c41b90ac9aa23a6c98ce13549dccd72e0a83f8537eb834d9cfc3d12bf3505
-
-# 11: Invalid dump section (size includes non hex character)
-a:d:10:10x
-
-ABCD
-
-a:d:10:10
diff --git a/extra/usb_updater/servo_micro.json b/extra/usb_updater/servo_micro.json
deleted file mode 100644
index 71b1fd25dc..0000000000
--- a/extra/usb_updater/servo_micro.json
+++ /dev/null
@@ -1,15 +0,0 @@
-{
- "Comment": "This file describes the updateable sections of the flash.",
- "board": "servo_micro",
- "vid": "0x18d1",
- "pid": "0x501a",
- "console": "3",
- "Comment on flash": "This is the base address of writeable flash",
- "flash": "0x8000000",
- "Comment on region format": "name: [baseoffset, length]",
- "regions": {
- "RW": ["0x10000", "0x10000"],
- "PSTATE": ["0xf000", "0x1000"],
- "RO": ["0x0000", "0xf000"]
- }
-}
diff --git a/extra/usb_updater/servo_updater.py b/extra/usb_updater/servo_updater.py
deleted file mode 100755
index 4dff264182..0000000000
--- a/extra/usb_updater/servo_updater.py
+++ /dev/null
@@ -1,456 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2016 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.
-#
-# Ignore indention messages, since legacy scripts use 2 spaces instead of 4.
-# pylint: disable=bad-indentation,docstring-section-indent
-# pylint: disable=docstring-trailing-quotes
-
-# Note: This is a py2/3 compatible file.
-
-from __future__ import print_function
-
-import argparse
-import errno
-import os
-import re
-import subprocess
-import time
-import tempfile
-
-import json
-
-import fw_update
-import ecusb.tiny_servo_common as c
-from ecusb import tiny_servod
-
-class ServoUpdaterException(Exception):
- """Raised on exceptions generated by servo_updater."""
-
-BOARD_C2D2 = 'c2d2'
-BOARD_SERVO_MICRO = 'servo_micro'
-BOARD_SERVO_V4 = 'servo_v4'
-BOARD_SERVO_V4P1 = 'servo_v4p1'
-BOARD_SWEETBERRY = 'sweetberry'
-
-DEFAULT_BOARD = BOARD_SERVO_V4
-
-# These lists are to facilitate exposing choices in the command-line tool
-# below.
-BOARDS = [BOARD_C2D2, BOARD_SERVO_MICRO, BOARD_SERVO_V4, BOARD_SERVO_V4P1,
- BOARD_SWEETBERRY]
-
-# Servo firmware bundles four channels of firmware. We need to make sure the
-# user does not request a non-existing channel, so keep the lists around to
-# guard on command-line usage.
-
-DEFAULT_CHANNEL = STABLE_CHANNEL = 'stable'
-
-PREV_CHANNEL = 'prev'
-
-# The ordering here matters. From left to right it's the channel that the user
-# is most likely to be running. This is used to inform and warn the user if
-# there are issues. e.g. if the all channels are the same, we want to let the
-# user know they are running the 'stable' version before letting them know they
-# are running 'dev' or even 'alpah' which (while true) might cause confusion.
-
-CHANNELS = [DEFAULT_CHANNEL, PREV_CHANNEL, 'dev', 'alpha']
-
-DEFAULT_BASE_PATH = '/usr/'
-TEST_IMAGE_BASE_PATH = '/usr/local/'
-
-COMMON_PATH = 'share/servo_updater'
-
-FIRMWARE_DIR = "firmware/"
-CONFIGS_DIR = "configs/"
-
-RETRIES_COUNT = 10
-RETRIES_DELAY = 1
-
-def do_with_retries(func, *args):
- """
- Call function passed as argument and check if no error happened.
- If exception was raised by function,
- it will be retried up to RETRIES_COUNT times.
-
- Args:
- func: function that will be called
- args: arguments passed to 'func'
-
- Returns:
- If call to function was successful, its result will be returned.
- If retries count was exceeded, exception will be raised.
- """
-
- retry = 0
- while retry < RETRIES_COUNT:
- try:
- return func(*args)
- except Exception as e:
- print("Retrying function %s: %s" % (func.__name__, e))
- retry = retry + 1
- time.sleep(RETRIES_DELAY)
- continue
-
- raise Exception("'{}' failed after {} retries".format(func.__name__, RETRIES_COUNT))
-
-def flash(brdfile, serialno, binfile):
- """
- Call fw_update to upload to updater USB endpoint.
-
- Args:
- brdfile: path to board configuration file
- serialno: device serial number
- binfile: firmware file
- """
-
- p = fw_update.Supdate()
- p.load_board(brdfile)
- p.connect_usb(serialname=serialno)
- p.load_file(binfile)
-
- # Start transfer and erase.
- p.start()
- # Upload the bin file
- print("Uploading %s" % binfile)
- p.write_file()
-
- # Finalize
- print("Done. Finalizing.")
- p.stop()
-
-def flash2(vidpid, serialno, binfile):
- """
- Call fw update via usb_updater2 commandline.
-
- Args:
- vidpid: vendor id and product id of device
- serialno: device serial number (optional)
- binfile: firmware file
- """
-
- tool = 'usb_updater2'
- cmd = "%s -d %s" % (tool, vidpid)
- if serialno:
- cmd += " -S %s" % serialno
- cmd += " -n"
- cmd += " %s" % binfile
-
- print(cmd)
- help_cmd = '%s --help' % tool
- with open('/dev/null') as devnull:
- valid_check = subprocess.call(help_cmd.split(), stdout=devnull,
- stderr=devnull)
- if valid_check:
- raise ServoUpdaterException('%s exit with res = %d. Make sure the tool '
- 'is available on the device.' % (help_cmd,
- valid_check))
- res = subprocess.call(cmd.split())
-
- if res in (0, 1, 2):
- return res
- else:
- raise ServoUpdaterException("%s exit with res = %d" % (cmd, res))
-
-def select(tinys, region):
- """
- Ensure the servo is in the expected ro/rw region.
- This function jumps to the required region and verify if jump was
- successful by executing 'sysinfo' command and reading current region.
- If response was not received or region is invalid, exception is raised.
-
- Args:
- tinys: TinyServod object
- region: region to jump to, only "rw" and "ro" is allowed
- """
-
- if region not in ["rw", "ro"]:
- raise Exception("Region must be ro or rw")
-
- if region is "ro":
- cmd = "reboot"
- else:
- cmd = "sysjump %s" % region
-
- tinys.pty._issue_cmd(cmd)
-
- tinys.close()
- time.sleep(2)
- tinys.reinitialize()
-
- res = tinys.pty._issue_cmd_get_results("sysinfo", ["Copy:[\s]+(RO|RW)"])
- current_region = res[0][1].lower()
- if current_region != region:
- raise Exception("Invalid region: %s/%s" % (current_region, region))
-
-def do_version(tinys):
- """Check version via ec console 'pty'.
-
- Args:
- tinys: TinyServod object
-
- Returns:
- detected version number
-
- Commands are:
- # > version
- # ...
- # Build: tigertail_v1.1.6749-74d1a312e
- """
- cmd = '\r\nversion\r\n'
- regex = 'Build:\s+(\S+)[\r\n]+'
-
- results = tinys.pty._issue_cmd_get_results(cmd, [regex])[0]
-
- return results[1].strip(' \t\r\n\0')
-
-def do_updater_version(tinys):
- """Check whether this uses python updater or c++ updater
-
- Args:
- tinys: TinyServod object
-
- Returns:
- updater version number. 2 or 6.
- """
- vers = do_version(tinys)
-
- # Servo versions below 58 are from servo-9040.B. Versions starting with _v2
- # are newer than anything _v1, no need to check the exact number. Updater
- # version is not directly queryable.
- if re.search('_v[2-9]\.\d', vers):
- return 6
- m = re.search('_v1\.1\.(\d\d\d\d)', vers)
- if m:
- version_number = int(m.group(1))
- if version_number < 5800:
- return 2
- else:
- return 6
- raise ServoUpdaterException(
- "Can't determine updater target from vers: [%s]" % vers)
-
-def _extract_version(boardname, binfile):
- """Find the version string from |binfile|.
-
- Args:
- boardname: the name of the board, eg. "servo_micro"
- binfile: path to the binary to search
-
- Returns:
- the version string.
- """
- if boardname is None:
- # cannot extract the version if the name is None
- return None
- rawstrings = subprocess.check_output(
- ['cbfstool', binfile, 'read', '-r', 'RO_FRID', '-f', '/dev/stdout'],
- **c.get_subprocess_args())
- m = re.match(r'%s_v\S+' % boardname, rawstrings)
- if m:
- newvers = m.group(0).strip(' \t\r\n\0')
- else:
- raise ServoUpdaterException("Can't find version from file: %s." % binfile)
-
- return newvers
-
-def get_firmware_channel(bname, version):
- """Find out which channel |version| for |bname| came from.
-
- Args:
- bname: board name
- version: current version string
-
- Returns:
- one of the channel names if |version| came from one of those, or None
- """
- for channel in CHANNELS:
- # Pass |bname| as cname to find the board specific file, and pass None as
- # fname to ensure the default directory is searched
- _, _, vers = get_files_and_version(bname, None, channel=channel)
- if version == vers:
- return channel
- # None of the channels matched. This firmware is currently unknown.
- return None
-
-def get_files_and_version(cname, fname=None, channel=DEFAULT_CHANNEL):
- """Select config and firmware binary files.
-
- This checks default file names and paths.
- In: /usr/share/servo_updater/[firmware|configs]
- check for board.json, board.bin
-
- Args:
- cname: board name, or config name. eg. "servo_v4" or "servo_v4.json"
- fname: firmware binary name. Can be None to try default.
- channel: the channel requested for servo firmware. See |CHANNELS| above.
-
- Returns:
- cname, fname, version: validated filenames selected from the path.
- """
- for p in (DEFAULT_BASE_PATH, TEST_IMAGE_BASE_PATH):
- updater_path = os.path.join(p, COMMON_PATH)
- if os.path.exists(updater_path):
- break
- else:
- raise ServoUpdaterException('servo_updater/ dir not found in known spots.')
-
- firmware_path = os.path.join(updater_path, FIRMWARE_DIR)
- configs_path = os.path.join(updater_path, CONFIGS_DIR)
-
- for p in (firmware_path, configs_path):
- if not os.path.exists(p):
- raise ServoUpdaterException('Could not find required path %r' % p)
-
- if not os.path.isfile(cname):
- # If not an existing file, try checking on the default path.
- newname = os.path.join(configs_path, cname)
- if os.path.isfile(newname):
- cname = newname
- else:
- # Try appending ".json" to convert board name to config file.
- cname = newname + ".json"
- if not os.path.isfile(cname):
- raise ServoUpdaterException("Can't find config file: %s." % cname)
-
- # Always retrieve the boardname
- with open(cname) as data_file:
- data = json.load(data_file)
- boardname = data['board']
-
- if not fname:
- # If no |fname| supplied, look for the default locations with the board
- # and channel requested.
- binary_file = '%s.%s.bin' % (boardname, channel)
- newname = os.path.join(firmware_path, binary_file)
- if os.path.isfile(newname):
- fname = newname
- else:
- raise ServoUpdaterException("Can't find firmware binary: %s." %
- binary_file)
- elif not os.path.isfile(fname):
- # If a name is specified but not found, try the default path.
- newname = os.path.join(firmware_path, fname)
- if os.path.isfile(newname):
- fname = newname
- else:
- raise ServoUpdaterException("Can't find file: %s." % fname)
-
- # Lastly, retrieve the version as well for decision making, debug, and
- # informational purposes.
- binvers = _extract_version(boardname, fname)
-
- return cname, fname, binvers
-
-def main():
- parser = argparse.ArgumentParser(description="Image a servo device")
- parser.add_argument('-p', '--print', dest='print_only', action='store_true',
- default=False,
- help='only print available firmware for board/channel')
- parser.add_argument('-s', '--serialno', type=str,
- help="serial number to program", default=None)
- parser.add_argument('-b', '--board', type=str,
- help="Board configuration json file",
- default=DEFAULT_BOARD, choices=BOARDS)
- parser.add_argument('-c', '--channel', type=str,
- help="Firmware channel to use",
- default=DEFAULT_CHANNEL, choices=CHANNELS)
- parser.add_argument('-f', '--file', type=str,
- help="Complete ec.bin file", default=None)
- parser.add_argument('--force', action="store_true",
- help="Update even if version match", default=False)
- parser.add_argument('-v', '--verbose', action="store_true",
- help="Chatty output")
- parser.add_argument('-r', '--reboot', action="store_true",
- help="Always reboot, even after probe.")
-
- args = parser.parse_args()
-
- brdfile, binfile, newvers = get_files_and_version(args.board, args.file,
- args.channel)
-
- # If the user only cares about the information then just print it here,
- # and exit.
- if args.print_only:
- output = ('board: %s\n'
- 'channel: %s\n'
- 'firmware: %s') % (args.board, args.channel, newvers)
- print(output)
- return
-
- serialno = args.serialno
-
- with open(brdfile) as data_file:
- data = json.load(data_file)
- vid, pid = int(data['vid'], 0), int(data['pid'], 0)
- vidpid = "%04x:%04x" % (vid, pid)
- iface = int(data['console'], 0)
- boardname = data['board']
-
- # Make sure device is up.
- print("===== Waiting for USB device =====")
- c.wait_for_usb(vidpid, serialname=serialno)
- # We need a tiny_servod to query some information. Set it up first.
- tinys = tiny_servod.TinyServod(vid, pid, iface, serialno, args.verbose)
-
- if not args.force:
- vers = do_version(tinys)
- print("Current %s version is %s" % (boardname, vers))
- print("Available %s version is %s" % (boardname, newvers))
-
- if newvers == vers:
- print("No version update needed")
- if args.reboot:
- select(tinys, 'ro')
- return
- else:
- print("Updating to recommended version.")
-
- # Make sure the servo MCU is in RO
- print("===== Jumping to RO =====")
- do_with_retries(select, tinys, 'ro')
-
- print("===== Flashing RW =====")
- vers = do_with_retries(do_updater_version, tinys)
- # To make sure that the tiny_servod here does not interfere with other
- # processes, close it out.
- tinys.close()
-
- if vers == 2:
- flash(brdfile, serialno, binfile)
- elif vers == 6:
- flash2(vidpid, serialno, binfile)
- else:
- raise ServoUpdaterException("Can't detect updater version")
-
- # Make sure device is up.
- c.wait_for_usb(vidpid, serialname=serialno)
- # After we have made sure that it's back/available, reconnect the tiny servod.
- tinys.reinitialize()
-
- # Make sure the servo MCU is in RW
- print("===== Jumping to RW =====")
- do_with_retries(select, tinys, 'rw')
-
- print("===== Flashing RO =====")
- vers = do_with_retries(do_updater_version, tinys)
-
- if vers == 2:
- flash(brdfile, serialno, binfile)
- elif vers == 6:
- flash2(vidpid, serialno, binfile)
- else:
- raise ServoUpdaterException("Can't detect updater version")
-
- # Make sure the servo MCU is in RO
- print("===== Rebooting =====")
- do_with_retries(select, tinys, 'ro')
- # Perform additional reboot to free USB/UART resources, taken by tiny servod.
- # See https://issuetracker.google.com/196021317 for background.
- tinys.pty._issue_cmd("reboot")
-
- print("===== Finished =====")
-
-if __name__ == "__main__":
- main()
diff --git a/extra/usb_updater/servo_v4.json b/extra/usb_updater/servo_v4.json
deleted file mode 100644
index e041f56b68..0000000000
--- a/extra/usb_updater/servo_v4.json
+++ /dev/null
@@ -1,15 +0,0 @@
-{
- "Comment": "This file describes the updateable sections of the flash.",
- "board": "servo_v4",
- "vid": "0x18d1",
- "pid": "0x501b",
- "console": "0",
- "Comment on flash": "This is the base address of writeable flash",
- "flash": "0x8000000",
- "Comment on region format": "name: [baseoffset, length]",
- "regions": {
- "RW": ["0x10000", "0x10000"],
- "PSTATE": ["0xf000", "0x1000"],
- "RO": ["0x0000", "0xf000"]
- }
-}
diff --git a/extra/usb_updater/servo_v4p1.json b/extra/usb_updater/servo_v4p1.json
deleted file mode 100644
index 46efbf24ad..0000000000
--- a/extra/usb_updater/servo_v4p1.json
+++ /dev/null
@@ -1,15 +0,0 @@
-{
- "Comment": "This file describes the updateable sections of the flash.",
- "board": "servo_v4p1",
- "vid": "0x18d1",
- "pid": "0x520d",
- "console": "0",
- "Comment on flash": "This is the base address of writeable flash",
- "flash": "0x8000000",
- "Comment on region format": "name: [baseoffset, length]",
- "regions": {
- "RW": ["0x10000", "0x10000"],
- "PSTATE": ["0xf000", "0x1000"],
- "RO": ["0x0000", "0xf000"]
- }
-}
diff --git a/extra/usb_updater/sweetberry.json b/extra/usb_updater/sweetberry.json
deleted file mode 100644
index 6b70d19fad..0000000000
--- a/extra/usb_updater/sweetberry.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "Comment": "This file describes the updateable sections of the flash.",
- "board": "sweetberry",
- "vid": "0x18d1",
- "pid": "0x5020",
- "console": "0",
- "Comment on flash": "This is the base address of writeable flash",
- "flash": "0x8000000",
- "Comment on region format": "name: [baseoffset, length]",
- "regions": {
- "RW": ["0x40000", "0x40000"],
- "RO": ["0x0000", "0x40000"]
- }
-}
diff --git a/extra/usb_updater/usb_updater2.c b/extra/usb_updater/usb_updater2.c
deleted file mode 100644
index 12ee1615fc..0000000000
--- a/extra/usb_updater/usb_updater2.c
+++ /dev/null
@@ -1,1244 +0,0 @@
-/*
- * Copyright 2017 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 <asm/byteorder.h>
-#include <endian.h>
-#include <fcntl.h>
-#include <getopt.h>
-#include <libusb.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <time.h>
-#include <unistd.h>
-
-#include <fmap.h>
-
-#ifndef __packed
-#define __packed __attribute__((packed))
-#endif
-
-#include "compile_time_macros.h"
-#include "misc_util.h"
-#include "usb_descriptor.h"
-#include "update_fw.h"
-#include "vb21_struct.h"
-
-#ifdef DEBUG
-#define debug printf
-#else
-#define debug(fmt, args...)
-#endif
-
-/*
- * This file contains the source code of a Linux application used to update
- * EC device firmware (common code only, gsctool takes care of cr50).
- */
-
-#define VID USB_VID_GOOGLE
-#define PID 0x5022
-#define SUBCLASS USB_SUBCLASS_GOOGLE_UPDATE
-#define PROTOCOL USB_PROTOCOL_GOOGLE_UPDATE
-
-enum exit_values {
- noop = 0, /* All up to date, no update needed. */
- all_updated = 1, /* Update completed, reboot required. */
- rw_updated = 2, /* RO was not updated, reboot required. */
- update_error = 3 /* Something went wrong. */
-};
-
-struct usb_endpoint {
- struct libusb_device_handle *devh;
- uint8_t ep_num;
- int chunk_len;
-};
-
-struct transfer_descriptor {
- /*
- * offsets of section available for update (not currently active).
- */
- uint32_t offset;
-
- struct usb_endpoint uep;
-};
-
-/* Information about the target */
-static struct first_response_pdu targ;
-
-static uint16_t protocol_version;
-static uint16_t header_type;
-static char *progname;
-static char *short_opts = "bd:efg:hjlnp:rsS:tuw";
-static const struct option long_opts[] = {
- /* name hasarg *flag val */
- {"binvers", 1, NULL, 'b'},
- {"device", 1, NULL, 'd'},
- {"entropy", 0, NULL, 'e'},
- {"fwver", 0, NULL, 'f'},
- {"tp_debug", 1, NULL, 'g'},
- {"help", 0, NULL, 'h'},
- {"jump_to_rw", 0, NULL, 'j'},
- {"follow_log", 0, NULL, 'l'},
- {"no_reset", 0, NULL, 'n'},
- {"tp_update", 1, NULL, 'p'},
- {"reboot", 0, NULL, 'r'},
- {"stay_in_ro", 0, NULL, 's'},
- {"serial", 1, NULL, 'S'},
- {"tp_info", 0, NULL, 't'},
- {"unlock_rollback", 0, NULL, 'u'},
- {"unlock_rw", 0, NULL, 'w'},
- {},
-};
-
-/* Release USB device and return error to the OS. */
-static void shut_down(struct usb_endpoint *uep)
-{
- libusb_close(uep->devh);
- libusb_exit(NULL);
- exit(update_error);
-}
-
-static void usage(int errs)
-{
- printf("\nUsage: %s [options] <binary image>\n"
- "\n"
- "This updates EC firmware over USB (common code EC, no cr50).\n"
- "The required argument is the full RO+RW image.\n"
- "\n"
- "Options:\n"
- "\n"
- " -b,--binvers Report versions of image's "
- "RW and RO, do not update\n"
- " -d,--device VID:PID USB device (default %04x:%04x)\n"
- " -e,--entropy Add entropy to device secret\n"
- " -f,--fwver Report running firmware versions.\n"
- " -g,--tp_debug <hex data> Touchpad debug command\n"
- " -h,--help Show this message\n"
- " -j,--jump_to_rw Tell EC to jump to RW\n"
- " -l,--follow_log Get console log\n"
- " -p,--tp_update file Update touchpad FW\n"
- " -r,--reboot Tell EC to reboot\n"
- " -s,--stay_in_ro Tell EC to stay in RO\n"
- " -S,--serial Device serial number\n"
- " -t,--tp_info Get touchpad information\n"
- " -u,--unlock_rollback Tell EC to unlock the rollback region\n"
- " -w,--unlock_rw Tell EC to unlock the RW region\n"
- "\n", progname, VID, PID);
-
- exit(errs ? update_error : noop);
-}
-
-static void str2hex(const char *str, uint8_t *data, int *len)
-{
- int i;
- int slen = strlen(str);
-
- if (slen/2 > *len) {
- fprintf(stderr, "Hex string too long.\n");
- exit(update_error);
- }
-
- if (slen % 2 != 0) {
- fprintf(stderr, "Hex string length not a multiple of 2.\n");
- exit(update_error);
- }
-
- for (i = 0, *len = 0; i < slen; i += 2, (*len)++) {
- char *end;
- char tmp[3];
-
- tmp[0] = str[i];
- tmp[1] = str[i+1];
- tmp[2] = 0;
-
- data[*len] = strtol(tmp, &end, 16);
-
- if (*end != 0) {
- fprintf(stderr, "Invalid hex string.\n");
- exit(update_error);
- }
- }
-}
-
-static void hexdump(const uint8_t *data, int len)
-{
- int i;
-
- for (i = 0; i < len; i++) {
- printf("%02x", data[i]);
- if ((i % 16) == 15)
- printf("\n");
- }
-
- if ((len % 16) != 0)
- printf("\n");
-}
-
-static void dump_touchpad_info(const uint8_t *data, int len)
-{
- const struct touchpad_info *info = (const struct touchpad_info *)data;
-
- if (len != sizeof(struct touchpad_info)) {
- fprintf(stderr, "Hex string length is not %zu",
- sizeof(struct touchpad_info));
- hexdump(data, len);
- return;
- }
-
- printf("\n");
- printf("status: 0x%02x\n", info->status);
- printf("vendor: 0x%04x\n", info->vendor);
- printf("fw_address: 0x%08x\n", info->fw_address);
- printf("fw_size: 0x%08x\n", info->fw_size);
-
- printf("allowed_fw_hash:\n");
- hexdump(info->allowed_fw_hash, sizeof(info->allowed_fw_hash));
-
- switch (info->vendor) {
- case 0x04f3: /* ELAN */
- case 0x0483: /* ST */
- printf("id: 0x%04x\n", info->elan.id);
- printf("fw_version: 0x%04x\n", info->elan.fw_version);
- printf("fw_fw_checksum: 0x%04x\n", info->elan.fw_checksum);
- break;
- default:
- fprintf(stderr, "Unknown vendor, vendor specific data:\n");
- hexdump((const uint8_t *)&info->elan, sizeof(info->elan));
- break;
- }
-}
-
-/* Read file into buffer */
-static uint8_t *get_file_or_die(const char *filename, size_t *len_ptr)
-{
- FILE *fp;
- struct stat st;
- uint8_t *data;
- size_t len;
-
- fp = fopen(filename, "rb");
- if (!fp) {
- perror(filename);
- exit(update_error);
- }
- if (fstat(fileno(fp), &st)) {
- perror("stat");
- exit(update_error);
- }
-
- len = st.st_size;
-
- data = malloc(len);
- if (!data) {
- perror("malloc");
- exit(update_error);
- }
-
- if (fread(data, st.st_size, 1, fp) != 1) {
- perror("fread");
- exit(update_error);
- }
-
- fclose(fp);
-
- *len_ptr = len;
- return data;
-}
-
-#define USB_ERROR(m, r) \
- fprintf(stderr, "%s:%d, %s returned %d (%s)\n", __FILE__, __LINE__, \
- m, r, libusb_strerror(r))
-
-/*
- * Actual USB transfer function, the 'allow_less' flag indicates that the
- * valid response could be shortef than allotted memory, the 'rxed_count'
- * pointer, if provided along with 'allow_less' lets the caller know how mavy
- * bytes were received.
- */
-static void do_xfer(struct usb_endpoint *uep, void *outbuf, int outlen,
- void *inbuf, int inlen, int allow_less,
- size_t *rxed_count)
-{
-
- int r, actual;
-
- /* Send data out */
- if (outbuf && outlen) {
- actual = 0;
- r = libusb_bulk_transfer(uep->devh, uep->ep_num,
- outbuf, outlen,
- &actual, 2000);
- if (r < 0) {
- USB_ERROR("libusb_bulk_transfer", r);
- exit(update_error);
- }
- if (actual != outlen) {
- fprintf(stderr, "%s:%d, only sent %d/%d bytes\n",
- __FILE__, __LINE__, actual, outlen);
- shut_down(uep);
- }
- }
-
- /* Read reply back */
- if (inbuf && inlen) {
-
- actual = 0;
- r = libusb_bulk_transfer(uep->devh, uep->ep_num | 0x80,
- inbuf, inlen,
- &actual, 5000);
- if (r < 0) {
- USB_ERROR("libusb_bulk_transfer", r);
- exit(update_error);
- }
- if ((actual != inlen) && !allow_less) {
- fprintf(stderr, "%s:%d, only received %d/%d bytes\n",
- __FILE__, __LINE__, actual, inlen);
- hexdump(inbuf, actual);
- shut_down(uep);
- }
-
- if (rxed_count)
- *rxed_count = actual;
- }
-}
-
-static void xfer(struct usb_endpoint *uep, void *outbuf,
- size_t outlen, void *inbuf, size_t inlen, int allow_less)
-{
- do_xfer(uep, outbuf, outlen, inbuf, inlen, allow_less, NULL);
-}
-
-/* Return 0 on error, since it's never gonna be EP 0 */
-static int find_endpoint(const struct libusb_interface_descriptor *iface,
- struct usb_endpoint *uep)
-{
- const struct libusb_endpoint_descriptor *ep;
-
- if (iface->bInterfaceClass == 255 &&
- iface->bInterfaceSubClass == SUBCLASS &&
- iface->bInterfaceProtocol == PROTOCOL &&
- iface->bNumEndpoints) {
- ep = &iface->endpoint[0];
- uep->ep_num = ep->bEndpointAddress & 0x7f;
- uep->chunk_len = ep->wMaxPacketSize;
- return 1;
- }
-
- return 0;
-}
-
-/* Return -1 on error */
-static int find_interface(struct usb_endpoint *uep)
-{
- int iface_num = -1;
- int r, i, j;
- struct libusb_device *dev;
- struct libusb_config_descriptor *conf = 0;
- const struct libusb_interface *iface0;
- const struct libusb_interface_descriptor *iface;
-
- dev = libusb_get_device(uep->devh);
- r = libusb_get_active_config_descriptor(dev, &conf);
- if (r < 0) {
- USB_ERROR("libusb_get_active_config_descriptor", r);
- goto out;
- }
-
- for (i = 0; i < conf->bNumInterfaces; i++) {
- iface0 = &conf->interface[i];
- for (j = 0; j < iface0->num_altsetting; j++) {
- iface = &iface0->altsetting[j];
- if (find_endpoint(iface, uep)) {
- iface_num = i;
- goto out;
- }
- }
- }
-
-out:
- libusb_free_config_descriptor(conf);
- return iface_num;
-}
-
-/* Returns true if parsed. */
-static int parse_vidpid(const char *input, uint16_t *vid_ptr, uint16_t *pid_ptr)
-{
- char *copy, *s, *e = 0;
-
- copy = strdup(input);
-
- s = strchr(copy, ':');
- if (!s)
- return 0;
- *s++ = '\0';
-
- *vid_ptr = (uint16_t) strtoull(copy, &e, 16);
- if (!*optarg || (e && *e))
- return 0;
-
- *pid_ptr = (uint16_t) strtoull(s, &e, 16);
- if (!*optarg || (e && *e))
- return 0;
-
- return 1;
-}
-
-static libusb_device_handle *check_device(libusb_device *dev,
- uint16_t vid, uint16_t pid, char *serialno)
-{
- struct libusb_device_descriptor desc;
- libusb_device_handle *handle = NULL;
- char sn[256];
- int ret;
- int match = 1;
- int snvalid = 0;
-
- ret = libusb_get_device_descriptor(dev, &desc);
- if (ret < 0)
- return NULL;
-
- ret = libusb_open(dev, &handle);
-
- if (ret != LIBUSB_SUCCESS)
- return NULL;
-
- if (desc.iSerialNumber) {
- ret = libusb_get_string_descriptor_ascii(handle,
- desc.iSerialNumber, (unsigned char *)sn, sizeof(sn));
- if (ret > 0)
- snvalid = 1;
- }
-
- if (vid != 0 && vid != desc.idVendor)
- match = 0;
- if (pid != 0 && pid != desc.idProduct)
- match = 0;
- if (serialno != NULL && (!snvalid || strstr(sn, serialno) == NULL))
- match = 0;
-
- if (match)
- return handle;
-
- libusb_close(handle);
- return NULL;
-}
-
-static void usb_findit(uint16_t vid, uint16_t pid,
- char *serialno, struct usb_endpoint *uep)
-{
- int iface_num, r, i;
- libusb_device **devs;
- libusb_device_handle *devh = NULL;
- ssize_t count;
-
- memset(uep, 0, sizeof(*uep));
-
- r = libusb_init(NULL);
- if (r < 0) {
- USB_ERROR("libusb_init", r);
- exit(update_error);
- }
-
- count = libusb_get_device_list(NULL, &devs);
- if (count < 0)
- return;
-
- for (i = 0; devs[i]; i++) {
- devh = check_device(devs[i], vid, pid, serialno);
- if (devh) {
- printf("Found device.\n");
- break;
- }
- }
-
- libusb_free_device_list(devs, 1);
-
- if (!devh) {
- fprintf(stderr, "Can't find device\n");
- exit(update_error);
- }
-
- uep->devh = devh;
-
- iface_num = find_interface(uep);
- if (iface_num < 0) {
- fprintf(stderr, "USB FW update not supported by that device\n");
- shut_down(uep);
- }
- if (!uep->chunk_len) {
- fprintf(stderr, "wMaxPacketSize isn't valid\n");
- shut_down(uep);
- }
-
- printf("found interface %d endpoint %d, chunk_len %d\n",
- iface_num, uep->ep_num, uep->chunk_len);
-
- libusb_set_auto_detach_kernel_driver(uep->devh, 1);
- r = libusb_claim_interface(uep->devh, iface_num);
- if (r < 0) {
- USB_ERROR("libusb_claim_interface", r);
- shut_down(uep);
- }
-
- printf("READY\n-------\n");
-}
-
-static int transfer_block(struct usb_endpoint *uep,
- struct update_frame_header *ufh,
- uint8_t *transfer_data_ptr, size_t payload_size)
-{
- size_t transfer_size;
- uint32_t reply;
- int actual;
- int r;
-
- /* First send the header. */
- xfer(uep, ufh, sizeof(*ufh), NULL, 0, 0);
-
- /* Now send the block, chunk by chunk. */
- for (transfer_size = 0; transfer_size < payload_size;) {
- int chunk_size;
-
- chunk_size = MIN(uep->chunk_len, payload_size - transfer_size);
- xfer(uep, transfer_data_ptr, chunk_size, NULL, 0, 0);
- transfer_data_ptr += chunk_size;
- transfer_size += chunk_size;
- }
-
- /* Now get the reply. */
- r = libusb_bulk_transfer(uep->devh, uep->ep_num | 0x80,
- (void *) &reply, sizeof(reply),
- &actual, 5000);
- if (r) {
- if (r == -7) {
- fprintf(stderr, "Timeout!\n");
- return r;
- }
- USB_ERROR("libusb_bulk_transfer", r);
- shut_down(uep);
- }
-
- reply = *((uint8_t *)&reply);
- if (reply) {
- fprintf(stderr, "Error: status %#x\n", reply);
- exit(update_error);
- }
-
- return 0;
-}
-
-/**
- * Transfer an image section (typically RW or RO).
- *
- * td - transfer descriptor to use to communicate with the target
- * data_ptr - pointer at the section base in the image
- * section_addr - address of the section in the target memory space
- * data_len - section size
- * smart_update - non-zero to enable the smart trailing of 0xff.
- */
-static void transfer_section(struct transfer_descriptor *td,
- uint8_t *data_ptr,
- uint32_t section_addr,
- size_t data_len,
- uint8_t smart_update)
-{
- /*
- * Actually, we can skip trailing chunks of 0xff, as the entire
- * section space must be erased before the update is attempted.
- *
- * FIXME: We can be smarter than this and skip blocks within the image.
- */
- if (smart_update)
- while (data_len && (data_ptr[data_len - 1] == 0xff))
- data_len--;
-
- printf("sending 0x%zx bytes to %#x\n", data_len, section_addr);
- while (data_len) {
- size_t payload_size;
- uint32_t block_base;
- int max_retries;
-
- /* prepare the header to prepend to the block. */
- payload_size = MIN(data_len, targ.common.maximum_pdu_size);
-
- block_base = htobe32(section_addr);
-
- struct update_frame_header ufh;
-
- ufh.block_size = htobe32(payload_size +
- sizeof(struct update_frame_header));
- ufh.cmd.block_base = block_base;
- ufh.cmd.block_digest = 0;
- for (max_retries = 10; max_retries; max_retries--)
- if (!transfer_block(&td->uep, &ufh,
- data_ptr, payload_size))
- break;
-
- if (!max_retries) {
- fprintf(stderr,
- "Failed to transfer block, %zd to go\n",
- data_len);
- exit(update_error);
- }
- data_len -= payload_size;
- data_ptr += payload_size;
- section_addr += payload_size;
- }
-}
-
-/*
- * Each RO or RW section of the new image can be in one of the following
- * states.
- */
-enum upgrade_status {
- not_needed = 0, /* Version below or equal that on the target. */
- not_possible, /*
- * RO is newer, but can't be transferred due to
- * target RW shortcomings.
- */
- needed /*
- * This section needs to be transferred to the
- * target.
- */
-};
-
-/* This array describes all sections of the new image. */
-static struct {
- const char *name;
- uint32_t offset;
- uint32_t size;
- enum upgrade_status ustatus;
- char version[32];
- int32_t rollback;
- uint32_t key_version;
-} sections[] = {
- {"RO"},
- {"RW"}
-};
-
-static const struct fmap_area *fmap_find_area_or_die(const struct fmap *fmap,
- const char *name)
-{
- const struct fmap_area *fmaparea;
-
- fmaparea = fmap_find_area(fmap, name);
- if (!fmaparea) {
- fprintf(stderr, "Cannot find FMAP area %s\n", name);
- exit(update_error);
- }
-
- return fmaparea;
-}
-
-/*
- * Scan the new image and retrieve versions of all sections.
- */
-static void fetch_header_versions(const uint8_t *image, size_t len)
-{
- const struct fmap *fmap;
- const struct fmap_area *fmaparea;
- long int offset;
- size_t i;
-
- offset = fmap_find(image, len);
- if (offset < 0) {
- fprintf(stderr, "Cannot find FMAP in image\n");
- exit(update_error);
- }
- fmap = (const struct fmap *)(image+offset);
-
- /* FIXME: validate fmap struct more than this? */
- if (fmap->size != len) {
- fprintf(stderr, "Mismatch between FMAP size and image size\n");
- exit(update_error);
- }
-
- for (i = 0; i < ARRAY_SIZE(sections); i++) {
- const char *fmap_name;
- const char *fmap_fwid_name;
- const char *fmap_rollback_name = NULL;
- const char *fmap_key_name = NULL;
-
- if (!strcmp(sections[i].name, "RO")) {
- fmap_name = "EC_RO";
- fmap_fwid_name = "RO_FRID";
- } else if (!strcmp(sections[i].name, "RW")) {
- fmap_name = "EC_RW";
- fmap_fwid_name = "RW_FWID";
- fmap_rollback_name = "RW_RBVER";
- /*
- * Key version comes from key RO (RW signature does not
- * contain the key version.
- */
- fmap_key_name = "KEY_RO";
- } else {
- fprintf(stderr, "Invalid section name\n");
- exit(update_error);
- }
-
- fmaparea = fmap_find_area_or_die(fmap, fmap_name);
-
- /* FIXME: endianness? */
- sections[i].offset = fmaparea->offset;
- sections[i].size = fmaparea->size;
-
- fmaparea = fmap_find_area_or_die(fmap, fmap_fwid_name);
-
- if (fmaparea->size != sizeof(sections[i].version)) {
- fprintf(stderr, "Invalid fwid size\n");
- exit(update_error);
- }
- memcpy(sections[i].version, image+fmaparea->offset,
- fmaparea->size);
-
- sections[i].rollback = -1;
- if (fmap_rollback_name) {
- fmaparea = fmap_find_area(fmap, fmap_rollback_name);
- if (fmaparea)
- memcpy(&sections[i].rollback,
- image+fmaparea->offset,
- sizeof(sections[i].rollback));
- }
-
- sections[i].key_version = -1;
- if (fmap_key_name) {
- fmaparea = fmap_find_area(fmap, fmap_key_name);
- if (fmaparea) {
- const struct vb21_packed_key *key =
- (const void *)(image+fmaparea->offset);
- sections[i].key_version = key->key_version;
- }
- }
- }
-}
-
-static int show_headers_versions(const void *image)
-{
- size_t i;
-
- for (i = 0; i < ARRAY_SIZE(sections); i++) {
- printf("%s off=%08x/%08x v=%.32s rb=%d kv=%d\n",
- sections[i].name, sections[i].offset, sections[i].size,
- sections[i].version, sections[i].rollback,
- sections[i].key_version);
- }
- return 0;
-}
-
-/*
- * Pick sections to transfer based on information retrieved from the target,
- * the new image, and the protocol version the target is running.
- */
-static void pick_sections(struct transfer_descriptor *td)
-{
- size_t i;
-
- for (i = 0; i < ARRAY_SIZE(sections); i++) {
- uint32_t offset = sections[i].offset;
-
- /* Skip currently active section. */
- if (offset != td->offset)
- continue;
-
- sections[i].ustatus = needed;
- }
-}
-
-static void setup_connection(struct transfer_descriptor *td)
-{
- size_t rxed_size;
- size_t i;
- uint32_t error_code;
-
- /*
- * Need to be backwards compatible, communicate with targets running
- * different protocol versions.
- */
- union {
- struct first_response_pdu rpdu;
- uint32_t legacy_resp;
- } start_resp;
-
- /* Send start request. */
- printf("start\n");
-
- struct update_frame_header ufh;
- uint8_t inbuf[td->uep.chunk_len];
- int actual = 0;
-
- /* Flush all data from endpoint to recover in case of error. */
- while (!libusb_bulk_transfer(td->uep.devh,
- td->uep.ep_num | 0x80,
- (void *)&inbuf, td->uep.chunk_len,
- &actual, 10)) {
- printf("flush\n");
- }
-
- memset(&ufh, 0, sizeof(ufh));
- ufh.block_size = htobe32(sizeof(ufh));
- do_xfer(&td->uep, &ufh, sizeof(ufh), &start_resp,
- sizeof(start_resp), 1, &rxed_size);
-
- /* We got something. Check for errors in response */
- if (rxed_size < 8) {
- fprintf(stderr, "Unexpected response size %zd: ", rxed_size);
- for (i = 0; i < rxed_size; i++)
- fprintf(stderr, " %02x", ((uint8_t *)&start_resp)[i]);
- fprintf(stderr, "\n");
- exit(update_error);
- }
-
- protocol_version = be16toh(start_resp.rpdu.protocol_version);
- if (protocol_version < 5 || protocol_version > 6) {
- fprintf(stderr, "Unsupported protocol version %d\n",
- protocol_version);
- exit(update_error);
- }
-
- header_type = be16toh(start_resp.rpdu.header_type);
-
- printf("target running protocol version %d (type %d)\n",
- protocol_version, header_type);
- if (header_type != UPDATE_HEADER_TYPE_COMMON) {
- fprintf(stderr, "Unsupported header type %d\n",
- header_type);
- exit(update_error);
- }
-
- error_code = be32toh(start_resp.rpdu.return_value);
-
- if (error_code) {
- fprintf(stderr, "Target reporting error %d\n", error_code);
- shut_down(&td->uep);
- exit(update_error);
- }
-
- td->offset = be32toh(start_resp.rpdu.common.offset);
- memcpy(targ.common.version, start_resp.rpdu.common.version,
- sizeof(start_resp.rpdu.common.version));
- targ.common.maximum_pdu_size =
- be32toh(start_resp.rpdu.common.maximum_pdu_size);
- targ.common.flash_protection =
- be32toh(start_resp.rpdu.common.flash_protection);
- targ.common.min_rollback = be32toh(start_resp.rpdu.common.min_rollback);
- targ.common.key_version = be32toh(start_resp.rpdu.common.key_version);
-
- printf("maximum PDU size: %d\n", targ.common.maximum_pdu_size);
- printf("Flash protection status: %04x\n", targ.common.flash_protection);
- printf("version: %32s\n", targ.common.version);
- printf("key_version: %d\n", targ.common.key_version);
- printf("min_rollback: %d\n", targ.common.min_rollback);
- printf("offset: writable at %#x\n", td->offset);
-
- pick_sections(td);
-}
-
-/*
- * Channel TPM extension/vendor command over USB. The payload of the USB frame
- * in this case consists of the 2 byte subcommand code concatenated with the
- * command body. The caller needs to indicate if a response is expected, and
- * if it is - of what maximum size.
- */
-static int ext_cmd_over_usb(struct usb_endpoint *uep, uint16_t subcommand,
- void *cmd_body, size_t body_size,
- void *resp, size_t *resp_size,
- int allow_less)
-{
- struct update_frame_header *ufh;
- uint16_t *frame_ptr;
- size_t usb_msg_size;
-
- usb_msg_size = sizeof(struct update_frame_header) +
- sizeof(subcommand) + body_size;
-
- ufh = malloc(usb_msg_size);
- if (!ufh) {
- printf("%s: failed to allocate %zd bytes\n",
- __func__, usb_msg_size);
- return -1;
- }
-
- ufh->block_size = htobe32(usb_msg_size);
- ufh->cmd.block_digest = 0;
- ufh->cmd.block_base = htobe32(UPDATE_EXTRA_CMD);
- frame_ptr = (uint16_t *)(ufh + 1);
- *frame_ptr = htobe16(subcommand);
-
- if (body_size)
- memcpy(frame_ptr + 1, cmd_body, body_size);
-
- xfer(uep, ufh, usb_msg_size, resp, resp_size ? *resp_size : 0,
- allow_less);
-
- free(ufh);
- return 0;
-}
-
-/*
- * Indicate to the target that update image transfer has been completed. Upon
- * receiveing of this message the target state machine transitions into the
- * 'rx_idle' state. The host may send an extension command to reset the target
- * after this.
- */
-static void send_done(struct usb_endpoint *uep)
-{
- uint32_t out;
-
- /* Send stop request, ignoring reply. */
- out = htobe32(UPDATE_DONE);
- xfer(uep, &out, sizeof(out), &out, 1, 0);
-}
-
-static void send_subcommand(struct transfer_descriptor *td, uint16_t subcommand,
- void *cmd_body, size_t body_size,
- uint8_t *response, size_t response_size)
-{
- send_done(&td->uep);
-
- ext_cmd_over_usb(&td->uep, subcommand,
- cmd_body, body_size,
- response, &response_size, 0);
- printf("sent command %x, resp %x\n", subcommand, response[0]);
-}
-
-/* Returns number of successfully transmitted image sections. */
-static int transfer_image(struct transfer_descriptor *td,
- uint8_t *data, size_t data_len)
-{
- size_t i;
- int num_txed_sections = 0;
-
- for (i = 0; i < ARRAY_SIZE(sections); i++)
- if (sections[i].ustatus == needed) {
- transfer_section(td,
- data + sections[i].offset,
- sections[i].offset,
- sections[i].size, 1);
- num_txed_sections++;
- }
-
- /*
- * Move USB receiver sate machine to idle state so that vendor
- * commands can be processed later, if any.
- */
- send_done(&td->uep);
-
- if (!num_txed_sections)
- printf("nothing to do\n");
- else
- printf("-------\nupdate complete\n");
- return num_txed_sections;
-}
-
-static void generate_reset_request(struct transfer_descriptor *td)
-{
- size_t response_size;
- uint8_t response;
- uint16_t subcommand;
- uint8_t command_body[2]; /* Max command body size. */
- size_t command_body_size;
-
- if (protocol_version < 6) {
- /*
- * Send a second stop request, which should reboot
- * without replying.
- */
- send_done(&td->uep);
- /* Nothing we can do over /dev/tpm0 running versions below 6. */
- return;
- }
-
- /*
- * If the user explicitly wants it, request post reset instead of
- * immediate reset. In this case next time the target reboots, the h1
- * will reboot as well, and will consider running the uploaded code.
- *
- * In case target RW version is 19 or above, to reset the target the
- * host is supposed to send the command to enable the uploaded image
- * disabled by default.
- *
- * Otherwise the immediate reset command would suffice.
- */
- /* Most common case. */
- command_body_size = 0;
- response_size = 1;
- subcommand = UPDATE_EXTRA_CMD_IMMEDIATE_RESET;
- ext_cmd_over_usb(&td->uep, subcommand,
- command_body, command_body_size,
- &response, &response_size, 0);
-
- printf("reboot not triggered\n");
-}
-
-static void get_random(uint8_t *data, int len)
-{
- FILE *fp;
- int i = 0;
-
- fp = fopen("/dev/random", "rb");
- if (!fp) {
- perror("Can't open /dev/random");
- exit(update_error);
- }
-
- while (i < len) {
- int ret = fread(data+i, len-i, 1, fp);
-
- if (ret < 0) {
- perror("fread");
- exit(update_error);
- }
-
- i += ret;
- }
-
- fclose(fp);
-}
-
-static void read_console(struct transfer_descriptor *td)
-{
- uint8_t payload[] = { 0x1 };
- uint8_t response[64];
- size_t response_size = 64;
- struct timespec sleep_duration = { /* 100 ms */
- .tv_sec = 0,
- .tv_nsec = 100l * 1000l * 1000l,
- };
-
- send_done(&td->uep);
-
- printf("\n");
- while (1) {
- response_size = 1;
- ext_cmd_over_usb(&td->uep,
- UPDATE_EXTRA_CMD_CONSOLE_READ_INIT,
- NULL, 0,
- response, &response_size, 0);
-
- while (1) {
- response_size = 64;
- ext_cmd_over_usb(&td->uep,
- UPDATE_EXTRA_CMD_CONSOLE_READ_NEXT,
- payload, sizeof(payload),
- response, &response_size, 1);
- if (response[0] == 0)
- break;
- /* make sure it's null-terminated. */
- response[response_size - 1] = 0;
- printf("%s", (const char *)response);
- }
- nanosleep(&sleep_duration, NULL);
- }
-}
-
-int main(int argc, char *argv[])
-{
- struct transfer_descriptor td;
- int errorcnt;
- uint8_t *data = 0;
- size_t data_len = 0;
- uint16_t vid = VID, pid = PID;
- char *serialno = NULL;
- int i;
- size_t j;
- int transferred_sections = 0;
- int binary_vers = 0;
- int show_fw_ver = 0;
- int no_reset_request = 0;
- int touchpad_update = 0;
- int extra_command = -1;
- uint8_t extra_command_data[50];
- int extra_command_data_len = 0;
- uint8_t extra_command_answer[64];
- int extra_command_answer_len = 1;
-
- progname = strrchr(argv[0], '/');
- if (progname)
- progname++;
- else
- progname = argv[0];
-
- /* Usb transfer - default mode. */
- memset(&td, 0, sizeof(td));
-
- errorcnt = 0;
- opterr = 0; /* quiet, you */
- while ((i = getopt_long(argc, argv, short_opts, long_opts, 0)) != -1) {
- switch (i) {
- case 'b':
- binary_vers = 1;
- break;
- case 'd':
- if (!parse_vidpid(optarg, &vid, &pid)) {
- printf("Invalid argument: \"%s\"\n", optarg);
- errorcnt++;
- }
- break;
- case 'e':
- get_random(extra_command_data, 32);
- extra_command_data_len = 32;
- extra_command = UPDATE_EXTRA_CMD_INJECT_ENTROPY;
- break;
- case 'f':
- show_fw_ver = 1;
- break;
- case 'g':
- extra_command = UPDATE_EXTRA_CMD_TOUCHPAD_DEBUG;
- /* Maximum length. */
- extra_command_data_len = 50;
- str2hex(optarg,
- extra_command_data, &extra_command_data_len);
- hexdump(extra_command_data, extra_command_data_len);
- extra_command_answer_len = 64;
- break;
- case 'h':
- usage(errorcnt);
- break;
- case 'j':
- extra_command = UPDATE_EXTRA_CMD_JUMP_TO_RW;
- break;
- case 'l':
- extra_command = UPDATE_EXTRA_CMD_CONSOLE_READ_INIT;
- break;
- case 'n':
- no_reset_request = 1;
- break;
- case 'p':
- touchpad_update = 1;
-
- data = get_file_or_die(optarg, &data_len);
- printf("read %zd(%#zx) bytes from %s\n",
- data_len, data_len, argv[optind - 1]);
-
- break;
- case 'r':
- extra_command = UPDATE_EXTRA_CMD_IMMEDIATE_RESET;
- break;
- case 's':
- extra_command = UPDATE_EXTRA_CMD_STAY_IN_RO;
- break;
- case 'S':
- serialno = optarg;
- break;
- case 't':
- extra_command = UPDATE_EXTRA_CMD_TOUCHPAD_INFO;
- extra_command_answer_len =
- sizeof(struct touchpad_info);
- break;
- case 'u':
- extra_command = UPDATE_EXTRA_CMD_UNLOCK_ROLLBACK;
- break;
- case 'w':
- extra_command = UPDATE_EXTRA_CMD_UNLOCK_RW;
- break;
- case 0: /* auto-handled option */
- break;
- case '?':
- if (optopt)
- printf("Unrecognized option: -%c\n", optopt);
- else
- printf("Unrecognized option: %s\n",
- argv[optind - 1]);
- errorcnt++;
- break;
- case ':':
- printf("Missing argument to %s\n", argv[optind - 1]);
- errorcnt++;
- break;
- default:
- printf("Internal error at %s:%d\n", __FILE__, __LINE__);
- exit(update_error);
- }
- }
-
- if (errorcnt)
- usage(errorcnt);
-
- if (!show_fw_ver && extra_command == -1 && !touchpad_update) {
- if (optind >= argc) {
- fprintf(stderr,
- "\nERROR: Missing required <binary image>\n\n");
- usage(1);
- }
-
- data = get_file_or_die(argv[optind], &data_len);
- printf("read %zd(%#zx) bytes from %s\n",
- data_len, data_len, argv[optind]);
-
- fetch_header_versions(data, data_len);
-
- if (binary_vers)
- exit(show_headers_versions(data));
- } else {
- if (optind < argc)
- printf("Ignoring binary image %s\n", argv[optind]);
- }
-
- usb_findit(vid, pid, serialno, &td.uep);
-
- setup_connection(&td);
-
- if (show_fw_ver) {
- printf("Current versions:\n");
- printf("Writable %32s\n", targ.common.version);
- }
-
- if (data) {
- if (touchpad_update) {
- transfer_section(&td,
- data,
- 0x80000000,
- data_len, 0);
- free(data);
-
- send_done(&td.uep);
- } else {
- transferred_sections = transfer_image(&td,
- data, data_len);
- free(data);
-
- if (transferred_sections && !no_reset_request)
- generate_reset_request(&td);
- }
- } else if (extra_command == UPDATE_EXTRA_CMD_CONSOLE_READ_INIT) {
- read_console(&td);
- } else if (extra_command > -1) {
- send_subcommand(&td, extra_command,
- extra_command_data, extra_command_data_len,
- extra_command_answer, extra_command_answer_len);
-
- switch (extra_command) {
- case UPDATE_EXTRA_CMD_TOUCHPAD_INFO:
- dump_touchpad_info(extra_command_answer,
- extra_command_answer_len);
- break;
- case UPDATE_EXTRA_CMD_TOUCHPAD_DEBUG:
- hexdump(extra_command_answer, extra_command_answer_len);
- break;
- }
- }
-
- libusb_close(td.uep.devh);
- libusb_exit(NULL);
-
- if (!transferred_sections)
- return noop;
- /*
- * We should indicate if RO update was not done because of the
- * insufficient RW version.
- */
- for (j = 0; j < ARRAY_SIZE(sections); j++)
- if (sections[j].ustatus == not_possible) {
- /* This will allow scripting repeat attempts. */
- printf("Failed to update RO, run the command again\n");
- return rw_updated;
- }
-
- printf("image updated\n");
- return all_updated;
-}