From cee40844bcbd751ca854cae30cb6756c446880cd Mon Sep 17 00:00:00 2001 From: Vadim Bendebury Date: Fri, 3 Jan 2020 14:29:41 -0800 Subject: utils/extras: do not build unnecessary tools The vast majority of tools built from the ./util directory and many built from ./extra/usb_updater directory are not used by Cr50, let's not build them. Also eliminating some irrelevant pre-upload checks. BRANCH=cr50, cr50-mp BUG=b:145912698 TEST=verified that all the following commands succeed: make buildall -j make BOARD=cr50 CR50_DEV=1 -j make BOARD=cr50 CR50_SQA=1 -j make -C extra/usb_updater Change-Id: I0040ceab95ad280bda86ef599b3e902addcbdcde Signed-off-by: Vadim Bendebury Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1986943 Reviewed-by: Namyoon Woo --- Makefile | 2 - PRESUBMIT.cfg | 4 - extra/usb_updater/Makefile | 6 +- extra/usb_updater/ecusb | 1 - extra/usb_updater/fw_update.py | 421 -- extra/usb_updater/sample_descriptor | 87 - extra/usb_updater/servo_micro.json | 15 - extra/usb_updater/servo_updater.py | 305 -- extra/usb_updater/servo_v4.json | 15 - extra/usb_updater/usb_updater2.c | 1244 ----- util/battery_temp | 56 - util/build.mk | 110 - util/cbi-util.c | 492 -- util/chargen | 69 - util/comm-dev.c | 293 -- util/comm-host.c | 157 - util/comm-host.h | 103 - util/comm-i2c.c | 255 - util/comm-lpc.c | 316 -- util/comm-servo-spi.c | 357 -- util/cros_ec_dev.h | 98 - util/ec3po/__init__.py | 25 - util/ec3po/console.py | 1125 ----- util/ec3po/console_unittest.py | 1626 ------ util/ec3po/interpreter.py | 462 -- util/ec3po/interpreter_unittest.py | 366 -- util/ec3po/run_tests.sh | 9 - util/ec3po/threadproc_shim.py | 66 - util/ec_flash.c | 231 - util/ec_flash.h | 62 - util/ec_panicinfo.c | 126 - util/ec_panicinfo.h | 19 - util/ec_parse_panicinfo.c | 22 - util/ec_sb_firmware_update.c | 843 ---- util/ec_sb_firmware_update.h | 126 - util/ec_uartd.c | 159 - util/ecst.c | 2519 ---------- util/ecst.h | 278 -- util/ectool.c | 9397 ----------------------------------- util/ectool.h | 42 - util/ectool_keyscan.c | 678 --- util/export_taskinfo.c | 43 - util/flash_ec | 1439 ------ util/flash_fp_mcu | 298 -- util/flash_pd.py | 348 -- util/g_regs | 77 - util/gdbinit | 172 - util/gen_emmc_transfer_data.c | 158 - util/gen_ipi_table.c | 58 - util/gen_touchpad_hash.c | 174 - util/genvif.c | 698 --- util/host_command_check.sh | 135 - util/inject-keys.py | 127 - util/iteflash.c | 2142 -------- util/iteflash.md | 119 - util/lbcc.c | 690 --- util/lbplay.c | 165 - util/linux_ec_commands_h_check.sh | 25 - util/lock/android.c | 51 - util/lock/android.h | 54 - util/lock/build.mk | 10 - util/lock/file_lock.c | 262 - util/lock/gec_lock.c | 45 - util/lock/gec_lock.h | 51 - util/lock/ipc_lock.h | 69 - util/lock/locks.h | 38 - util/make_linux_ec_commands_h.sh | 76 - util/misc_util.c | 175 - util/openocd/lm4_chip.cfg | 11 - util/openocd/lm4x_cmds.tcl | 51 - util/openocd/npcx.cfg | 61 - util/openocd/npcx_chip.cfg | 11 - util/openocd/npcx_cmds.tcl | 184 - util/openocd/nrf51_chip.cfg | 14 - util/openocd/nrf51_cmds.tcl | 22 - util/openocd/servo.cfg | 14 - util/powerd_lock.c | 63 - util/powerd_lock.h | 41 - util/run_ects.py | 92 - util/stm32mon.c | 1698 ------- util/tagbranch.sh | 84 - util/temp_metrics.conf | 396 -- util/test-inject-keys.sh | 111 - util/uart_stress_tester.py | 540 -- util/unpack_ftb.py | 116 - util/uut/cmd.c | 482 -- util/uut/cmd.h | 69 - util/uut/com_port.h | 149 - util/uut/l_com_port.c | 446 -- util/uut/lib_crc.c | 109 - util/uut/lib_crc.h | 68 - util/uut/main.c | 749 --- util/uut/main.h | 74 - util/uut/opr.c | 550 -- util/uut/opr.h | 59 - 95 files changed, 1 insertion(+), 36549 deletions(-) delete mode 120000 extra/usb_updater/ecusb delete mode 100755 extra/usb_updater/fw_update.py delete mode 100644 extra/usb_updater/sample_descriptor delete mode 100644 extra/usb_updater/servo_micro.json delete mode 100755 extra/usb_updater/servo_updater.py delete mode 100644 extra/usb_updater/servo_v4.json delete mode 100644 extra/usb_updater/usb_updater2.c delete mode 100755 util/battery_temp delete mode 100644 util/build.mk delete mode 100644 util/cbi-util.c delete mode 100644 util/chargen delete mode 100644 util/comm-dev.c delete mode 100644 util/comm-host.c delete mode 100644 util/comm-host.h delete mode 100644 util/comm-i2c.c delete mode 100644 util/comm-lpc.c delete mode 100644 util/comm-servo-spi.c delete mode 100644 util/cros_ec_dev.h delete mode 100644 util/ec3po/__init__.py delete mode 100755 util/ec3po/console.py delete mode 100755 util/ec3po/console_unittest.py delete mode 100644 util/ec3po/interpreter.py delete mode 100755 util/ec3po/interpreter_unittest.py delete mode 100755 util/ec3po/run_tests.sh delete mode 100644 util/ec3po/threadproc_shim.py delete mode 100644 util/ec_flash.c delete mode 100644 util/ec_flash.h delete mode 100644 util/ec_panicinfo.c delete mode 100644 util/ec_panicinfo.h delete mode 100644 util/ec_parse_panicinfo.c delete mode 100644 util/ec_sb_firmware_update.c delete mode 100644 util/ec_sb_firmware_update.h delete mode 100644 util/ec_uartd.c delete mode 100644 util/ecst.c delete mode 100644 util/ecst.h delete mode 100644 util/ectool.c delete mode 100644 util/ectool.h delete mode 100644 util/ectool_keyscan.c delete mode 100644 util/export_taskinfo.c delete mode 100755 util/flash_ec delete mode 100644 util/flash_fp_mcu delete mode 100755 util/flash_pd.py delete mode 100755 util/g_regs delete mode 100644 util/gdbinit delete mode 100644 util/gen_emmc_transfer_data.c delete mode 100644 util/gen_ipi_table.c delete mode 100644 util/gen_touchpad_hash.c delete mode 100644 util/genvif.c delete mode 100755 util/host_command_check.sh delete mode 100755 util/inject-keys.py delete mode 100644 util/iteflash.c delete mode 100644 util/iteflash.md delete mode 100644 util/lbcc.c delete mode 100644 util/lbplay.c delete mode 100755 util/linux_ec_commands_h_check.sh delete mode 100644 util/lock/android.c delete mode 100644 util/lock/android.h delete mode 100644 util/lock/build.mk delete mode 100644 util/lock/file_lock.c delete mode 100644 util/lock/gec_lock.c delete mode 100644 util/lock/gec_lock.h delete mode 100644 util/lock/ipc_lock.h delete mode 100644 util/lock/locks.h delete mode 100755 util/make_linux_ec_commands_h.sh delete mode 100644 util/misc_util.c delete mode 100644 util/openocd/lm4_chip.cfg delete mode 100644 util/openocd/lm4x_cmds.tcl delete mode 100644 util/openocd/npcx.cfg delete mode 100644 util/openocd/npcx_chip.cfg delete mode 100644 util/openocd/npcx_cmds.tcl delete mode 100644 util/openocd/nrf51_chip.cfg delete mode 100644 util/openocd/nrf51_cmds.tcl delete mode 100644 util/openocd/servo.cfg delete mode 100644 util/powerd_lock.c delete mode 100644 util/powerd_lock.h delete mode 100644 util/run_ects.py delete mode 100644 util/stm32mon.c delete mode 100755 util/tagbranch.sh delete mode 100644 util/temp_metrics.conf delete mode 100755 util/test-inject-keys.sh delete mode 100755 util/uart_stress_tester.py delete mode 100755 util/unpack_ftb.py delete mode 100644 util/uut/cmd.c delete mode 100644 util/uut/cmd.h delete mode 100644 util/uut/com_port.h delete mode 100644 util/uut/l_com_port.c delete mode 100644 util/uut/lib_crc.c delete mode 100644 util/uut/lib_crc.h delete mode 100644 util/uut/main.c delete mode 100644 util/uut/main.h delete mode 100644 util/uut/opr.c delete mode 100644 util/uut/opr.h diff --git a/Makefile b/Makefile index 41e87a173b..4bcf468c5c 100644 --- a/Makefile +++ b/Makefile @@ -273,8 +273,6 @@ ifneq ($(PBDIR),) include $(PBDIR)/build.mk endif include test/build.mk -include util/build.mk -include util/lock/build.mk includes+=$(includes-y) diff --git a/PRESUBMIT.cfg b/PRESUBMIT.cfg index eb8325b4dd..219253c9e9 100644 --- a/PRESUBMIT.cfg +++ b/PRESUBMIT.cfg @@ -1,7 +1,6 @@ [Hook Overrides] branch_check: true checkpatch_check: true -kerneldoc_check: true signoff_check: true # We are using Linux style indentation with tabs @@ -10,10 +9,7 @@ tab_check: false [Hook Overrides Options] checkpatch_check: --no-tree --ignore=MSLEEP,VOLATILE,SPDX_LICENSE_TAG -kerneldoc_check: --include_regex=\bec_commands\.h$ [Hook Scripts] presubmit_check = util/presubmit_check.sh config_option_check = util/config_option_check.py -host_command_check = util/host_command_check.sh -ec_commands_h = util/linux_ec_commands_h_check.sh diff --git a/extra/usb_updater/Makefile b/extra/usb_updater/Makefile index 2f8f70a6d3..04adfff4dd 100644 --- a/extra/usb_updater/Makefile +++ b/extra/usb_updater/Makefile @@ -4,7 +4,7 @@ CC ?= gcc PKG_CONFIG ?= pkg-config -PROGRAMS := gsctool usb_updater2 +PROGRAMS := gsctool LIBS := LFLAGS := CFLAGS := -std=gnu99 \ @@ -56,10 +56,6 @@ gsctool: $(GSCTOOL_OBJS) Makefile gsctool.o: generated_version.h -# common EC code USB updater -usb_updater2: usb_updater2.c Makefile - $(CC) $(CFLAGS) $< $(LFLAGS) $(LIBS) $(LIBS_common) -o $@ - .PHONY: clean generated_version.h: $(GSCTOOL_SOURCES) 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 3755ba9d20..0000000000 --- a/extra/usb_updater/fw_update.py +++ /dev/null @@ -1,421 +0,0 @@ -#!/usr/bin/env python2 -# 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. - -# Upload firmware over USB - -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("", read_count=4) - result = 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) - - 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 c819230f21..0000000000 --- a/extra/usb_updater/servo_updater.py +++ /dev/null @@ -1,305 +0,0 @@ -#!/usr/bin/env python2 -# 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. - -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 - - -class ServoUpdaterException(Exception): - """Raised on exceptions generated by servo_updater.""" - - -DEFAULT_BASE_PATH = '/usr/' -TEST_IMAGE_BASE_PATH = '/usr/local/' - -COMMON_PATH = 'share/servo_updater' - -FIRMWARE_DIR = "firmware/" -CONFIGS_DIR = "configs/" - -if os.path.exists(os.path.join(DEFAULT_BASE_PATH, COMMON_PATH)): - BASE_PATH = DEFAULT_BASE_PATH -elif os.path.exists(os.path.join(TEST_IMAGE_BASE_PATH, COMMON_PATH)): - BASE_PATH = TEST_IMAGE_BASE_PATH -else: - raise ServoUpdaterException('servo_updater/ dir not found in known spots.') - -FIRMWARE_PATH = os.path.join(BASE_PATH, COMMON_PATH, FIRMWARE_DIR) -CONFIGS_PATH = os.path.join(BASE_PATH, COMMON_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) - -def flash(brdfile, serialno, binfile): - """Call fw_update to upload to updater USB endpoint.""" - 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.""" - 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: - sanity_check = subprocess.call(help_cmd.split(), stdout=devnull, - stderr=devnull) - if sanity_check: - raise ServoUpdaterException('%s exit with res = %d. Make sure the tool ' - 'is available on the device.' % (help_cmd, - sanity_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 connect(vidpid, iface, serialno, debuglog=False): - """Connect to console. - - Args: - vidpid: vidpid of desired device. - iface: interface to connect. - serialno: serial number, to differentiate multiple devices. - debuglog: do chatty log. - - Returns: - a connected pty object. - """ - # Make sure device is up. - c.wait_for_usb(vidpid, serialname=serialno) - - # make a console. - pty = c.setup_tinyservod(vidpid, iface, - serialname=serialno, debuglog=debuglog) - - return pty - -def select(vidpid, iface, serialno, region, debuglog=False): - """Ensure the servo is in the expected ro/rw partition.""" - - if region not in ["rw", "ro"]: - raise Exception("Region must be ro or rw") - - pty = connect(vidpid, iface, serialno) - - if region is "ro": - cmd = "reboot" - else: - cmd = "sysjump %s" % region - pty._issue_cmd(cmd) - time.sleep(1) - pty.close() - -def do_version(vidpid, iface, serialno): - """Check version via ec console 'pty'. - - Args: - see connect() - - Returns: - detected version number - - Commands are: - # > version - # ... - # Build: tigertail_v1.1.6749-74d1a312e - """ - pty = connect(vidpid, iface, serialno) - - cmd = '\r\nversion\r\n' - regex = 'Build:\s+(\S+)[\r\n]+' - - results = pty._issue_cmd_get_results(cmd, [regex])[0] - pty.close() - - return results[1].strip(' \t\r\n\0') - -def do_updater_version(vidpid, iface, serialno): - """Check whether this uses python updater or c++ updater - - Args: - see connect() - - Returns: - updater version number. 2 or 6. - """ - vers = do_version(vidpid, iface, serialno) - - # 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 findfiles(cname, fname): - """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: config name, or board name. eg. "servo_v4". - fname: firmware binary name. Can be None to try default. - Returns: - cname, fname: validated filenames selected from the path. - """ - if not os.path.isfile(cname): - # If not an existing file, try checking on the default path. - newname = CONFIGS_PATH + cname - if os.path.isfile(newname): - cname = newname - elif os.path.isfile(newname + ".json"): - # Try appending ".json" to convert board name to config file. - cname = newname + ".json" - else: - raise ServoUpdaterException("Can't find file: %s." % cname) - - if not fname: - # If None, try defaults. - dev = None - for default_f in ['servo_v4', 'servo_micro', 'sweetberry']: - if default_f in cname: - dev = default_f - if os.path.isfile(FIRMWARE_PATH + dev + ".bin"): - fname = FIRMWARE_PATH + dev + ".bin" - elif not os.path.isfile(fname): - # If a name is specified but not found, try the default path. - if os.path.isfile(FIRMWARE_PATH + fname): - fname = FIRMWARE_PATH + fname - else: - raise ServoUpdaterException("Can't find file: %s." % fname) - - return cname, fname - -def find_available_version(boardname, binfile): - """Find the version string from the binary file. - - Args: - boardname: the name of the board, eg. "servo_micro" - binfile: the binary to search - - Returns: - the version string. - """ - rawstrings = subprocess.check_output( - ['cbfstool', binfile, 'read', '-r', 'RO_FRID', '-f', '/dev/stdout']) - 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 main(): - parser = argparse.ArgumentParser(description="Image a servo micro device") - 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="servo_v4") - 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 = findfiles(args.board, args.file) - - serialno = args.serialno - debuglog = (args.verbose is True) - - with open(brdfile) as data_file: - data = json.load(data_file) - - vidpid = "%04x:%04x" % (int(data['vid'], 0), int(data['pid'], 0)) - iface = int(data['console'], 0) - boardname = data['board'] - - if not args.force: - vers = do_version(vidpid, iface, serialno) - print("Current %s version is %s" % (boardname, vers)) - - newvers = find_available_version(boardname, binfile) - print("Available %s version is %s" % (boardname, newvers)) - - if newvers == vers: - print("No version update needed") - if args.reboot is True: - select(vidpid, iface, serialno, "ro", debuglog=debuglog) - return - else: - print("Updating to recommended version.") - - - select(vidpid, iface, serialno, "ro", debuglog=debuglog) - - vers = do_updater_version(vidpid, iface, serialno) - if vers == 2: - flash(brdfile, serialno, binfile) - elif vers == 6: - flash2(vidpid, serialno, binfile) - else: - raise ServoUpdaterException("Can't detect updater version") - - select(vidpid, iface, serialno, "rw", debuglog=debuglog) - - vers = do_updater_version(vidpid, iface, serialno) - if vers == 2: - flash(brdfile, serialno, binfile) - elif vers == 6: - flash2(vidpid, serialno, binfile) - else: - raise ServoUpdaterException("Can't detect updater version") - - select(vidpid, iface, serialno, "ro", debuglog=debuglog) - -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/usb_updater2.c b/extra/usb_updater/usb_updater2.c deleted file mode 100644 index 10bfeee7bb..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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#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] \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 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) strtoul(copy, &e, 16); - if (!*optarg || (e && *e)) - return 0; - - *pid_ptr = (uint16_t) strtoul(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(§ions[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]); - - 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 \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; -} diff --git a/util/battery_temp b/util/battery_temp deleted file mode 100755 index c69e3d4778..0000000000 --- a/util/battery_temp +++ /dev/null @@ -1,56 +0,0 @@ -#!/bin/bash -# 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. -# -# Description: Read and output temperature of device's primary battery in -# degrees Celsius. -# -# TODO(tbroch) revisit for detachables with multiple batteries. - -# Read battery temperature from sysfs power_supply and return in degC. -batt_temp_sysfs() { - local temp="" - - for psdir in /sys/class/power_supply/* ; do - if [[ -e "${psdir}/temp" ]] ; then - pstype=$(cat $psdir/type) - if [[ "${pstype}" -eq "Battery" ]] ; then - temp=$(bc <<< "scale=2; $(cat ${psdir}/temp)/10") - break - fi - fi - done - echo ${temp} -} - -# Read battery temperature from EC and return in degC. -batt_temp_ec() { - local temp="" - - local sensor_str=$(ectool tempsinfo all 2>/dev/null | grep Battery) - if [[ $? -eq 0 ]] && [[ ! -z "${sensor_str}" ]] ; then - local idx=$(echo ${sensor_str} | cut -d: -f1) - # ectool temps looks like 'Reading temperature...298 K' - temp_str=$(ectool temps ${idx}) - temp="${temp_str//[!0-9]/}" - if [[ -z "${temp}" ]] ; then - temp="error" - else - temp=$(bc <<< "scale=2; ${temp} - 273.15") - fi - fi - echo $temp -} - -# Main -TEMP_DEGC=$(batt_temp_sysfs) -if [[ -z "${TEMP_DEGC}" ]] ; then - TEMP_DEGC=$(batt_temp_ec) -fi - -if [[ -z "${TEMP_DEGC}" ]] ; then - echo "unknown" -else - echo ${TEMP_DEGC} -fi diff --git a/util/build.mk b/util/build.mk deleted file mode 100644 index 9b9f44c814..0000000000 --- a/util/build.mk +++ /dev/null @@ -1,110 +0,0 @@ -# -*- makefile -*- -# Copyright 2014 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. -# -# Host tools build -# - -host-util-bin=ectool lbplay stm32mon ec_sb_firmware_update lbcc \ - ec_parse_panicinfo cbi-util iteflash -build-util-bin=ec_uartd -build-util-art+=util/export_taskinfo.so -ifeq ($(CHIP),npcx) -build-util-bin+=ecst -endif -host-util-bin+=uartupdatetool -uartupdatetool-objs=uut/main.o uut/cmd.o uut/opr.o uut/l_com_port.o \ - uut/lib_crc.o -$(out)/util/uartupdatetool: HOST_CFLAGS+=-Iutil/ -# Build on a limited subset of boards to save build time -ifeq ($(BOARD),nocturne_fp) -build-util-bin+=ectool_servo -endif - -# If the util/ directory in the private repo is symlinked into util/private, -# we want to build host-side tools from it, too. -ifneq ("$(wildcard util/private/build.mk)","") -include util/private/build.mk -endif - -comm-objs=$(util-lock-objs:%=lock/%) comm-host.o comm-dev.o -comm-objs+=comm-lpc.o comm-i2c.o misc_util.o - -iteflash-objs = iteflash.o usb_if.o -ectool-objs=ectool.o ectool_keyscan.o ec_flash.o ec_panicinfo.o $(comm-objs) -ectool_servo-objs=$(ectool-objs) comm-servo-spi.o -ec_sb_firmware_update-objs=ec_sb_firmware_update.o $(comm-objs) misc_util.o -ec_sb_firmware_update-objs+=powerd_lock.o -lbplay-objs=lbplay.o $(comm-objs) - -util/ectool.c: $(out)/ec_version.h - -ec_parse_panicinfo-objs=ec_parse_panicinfo.o ec_panicinfo.o - -# USB type-C Vendor Information File generation -ifeq ($(CONFIG_USB_POWER_DELIVERY),y) -build-util-bin+=genvif -build-util-art+=$(BOARD)_vif.txt - -# usb_pd_policy.c can be in baseboard, or board, or both. -genvif-pd-srcs=$(sort $(wildcard $(BASEDIR)/usb_pd_policy.c \ - board/$(BOARD)/usb_pd_policy.c)) -genvif-pd-objs=$(genvif-pd-srcs:%.c=$(out)/util/%.o) -deps-$(CONFIG_USB_POWER_DELIVERY) += $(genvif-pd-objs:%.o=%.o.d) - -$(out)/util/genvif: $(genvif-pd-objs) board/$(BOARD)/board.h \ - include/usb_pd.h include/usb_pd_tcpm.h -$(out)/util/genvif: BUILD_LDFLAGS+=$(genvif-pd-objs) -flto - -STANDALONE_FLAGS=-ffreestanding -fno-builtin -nostdinc \ - -Ibuiltin/ -D"__keep= " -DVIF_BUILD=$(EMPTY) - -$(out)/util/%/usb_pd_policy.o: %/usb_pd_policy.c - -@ mkdir -p $(@D) - $(call quiet,c_to_vif,BUILDCC) -endif # CONFIG_USB_POWER_DELIVERY - -ifneq ($(CONFIG_BOOTBLOCK),) -build-util-bin += gen_emmc_transfer_data - -# Bootblock is only packed in RO image. -$(out)/util/gen_emmc_transfer_data: BUILD_LDFLAGS += -DSECTION_IS_RO=$(EMPTY) -endif # CONFIG_BOOTBLOCK - -ifneq ($(CONFIG_IPI),) -build-util-bin += gen_ipi_table - -$(out)/util/gen_ipi_table: board/$(BOARD)/board.h -$(out)/ipi_table_gen.inc: $(out)/util/gen_ipi_table - $(call quiet,ipi_table,IPITBL ) -endif - -ifneq ($(CONFIG_TOUCHPAD_HASH_FW),) -build-util-bin += gen_touchpad_hash - -# Assume RW section (touchpad FW must be identical for both RO+RW) -$(out)/util/gen_touchpad_hash: BUILD_LDFLAGS += -DSECTION_IS_RW=$(EMPTY) - -OPENSSL_CFLAGS := $(shell $(PKG_CONFIG) --libs openssl) -OPENSSL_LDFLAGS := $(shell $(PKG_CONFIG) --libs openssl) - -$(out)/util/gen_touchpad_hash: BUILD_CFLAGS += $(OPENSSL_CFLAGS) -$(out)/util/gen_touchpad_hash: BUILD_LDFLAGS += $(OPENSSL_LDFLAGS) - -deps-y += $(out)/util/gen_touchpad_hash.d -endif # CONFIG_TOUCHPAD_VIRTUAL_OFF - -cbi-util-objs=../common/crc8.o ../common/cbi.o - -$(out)/util/export_taskinfo.so: $(out)/util/export_taskinfo_ro.o \ - $(out)/util/export_taskinfo_rw.o - $(call quiet,link_taskinfo,BUILDLD) - -$(out)/util/export_taskinfo_ro.o: util/export_taskinfo.c - $(call quiet,c_to_taskinfo,BUILDCC,RO) - -$(out)/util/export_taskinfo_rw.o: util/export_taskinfo.c - $(call quiet,c_to_taskinfo,BUILDCC,RW) - -deps-y += $(out)/util/export_taskinfo_ro.o.d $(out)/util/export_taskinfo_rw.o.d diff --git a/util/cbi-util.c b/util/cbi-util.c deleted file mode 100644 index ad050f36c5..0000000000 --- a/util/cbi-util.c +++ /dev/null @@ -1,492 +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. - * - * Cros Board Info utility - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "cros_board_info.h" -#include "crc8.h" - -#define ARGS_MASK_BOARD_VERSION BIT(0) -#define ARGS_MASK_FILENAME BIT(1) -#define ARGS_MASK_SIZE BIT(2) -#define ARGS_MASK_SKU_ID BIT(3) - -/* TODO: Set it by macro */ -const char cmd_name[] = "cbi-util"; - -/* Command line options */ -enum { - OPT_FILENAME, - OPT_BOARD_VERSION, - OPT_OEM_ID, - OPT_SKU_ID, - OPT_DRAM_PART_NUM, - OPT_OEM_NAME, - OPT_MODEL_ID, - OPT_SIZE, - OPT_ERASE_BYTE, - OPT_SHOW_ALL, - OPT_HELP, -}; - -static const struct option opts_create[] = { - {"file", 1, 0, OPT_FILENAME}, - {"board_version", 1, 0, OPT_BOARD_VERSION}, - {"oem_id", 1, 0, OPT_OEM_ID}, - {"sku_id", 1, 0, OPT_SKU_ID}, - {"dram_part_num", 1, 0, OPT_DRAM_PART_NUM}, - {"oem_name", 1, 0, OPT_OEM_NAME}, - {"model_id", 1, 0, OPT_MODEL_ID}, - {"size", 1, 0, OPT_SIZE}, - {"erase_byte", 1, 0, OPT_ERASE_BYTE}, - {NULL, 0, 0, 0} -}; - -static const struct option opts_show[] = { - {"file", 1, 0, OPT_FILENAME}, - {"all", 0, 0, OPT_SHOW_ALL}, - {NULL, 0, 0, 0} -}; - -static const char *field_name[] = { - /* Same order as enum cbi_data_tag */ - "BOARD_VERSION", - "OEM_ID", - "SKU_ID", - "DRAM_PART_NUM", - "OEM_NAME", - "MODEL_ID", -}; -BUILD_ASSERT(ARRAY_SIZE(field_name) == CBI_TAG_COUNT); - -const char help_create[] = - "\n" - "'%s create [ARGS]' creates an EEPROM image file.\n" - "Required ARGS are:\n" - " --file Path to output file\n" - " --board_version Board version\n" - " --sku_id SKU ID\n" - " --size Size of output file in bytes\n" - " must be a positive integer <= 0XFFFFFFFF and field size can\n" - "be optionally specified by notation: e.g. 0xabcd:4.\n" - " must be a positive integer <= 0XFFFF.\n" - "Optional ARGS are:\n" - " --dram_part_num DRAM PART NUM\n" - " --oem_id OEM ID\n" - " --oem_name OEM NAME\n" - " --erase_byte Byte used for empty space. Default:0xff\n" - " --format_version Data format version\n" - " --model_id Model ID\n" - " is a string\n" - "\n"; - -const char help_show[] = - "\n" - "'%s show [ARGS]' shows data in an EEPROM image file.\n" - "Required ARGS are:\n" - " --file Path to input file\n" - "Optional ARGS are:\n" - " --all Dump all information\n" - "It also validates the contents against the checksum and\n" - "returns non-zero if validation fails.\n" - "\n"; - -struct integer_field { - uint32_t val; - int size; -}; - -static void print_help_create(void) -{ - printf(help_create, cmd_name); -} - -static void print_help_show(void) -{ - printf(help_show, cmd_name); -} - -static void print_help(void) -{ - printf("\nUsage: %s [ARGS]\n" - "\n" - "Utility for CBI:Cros Board Info images.\n", cmd_name); - print_help_create(); - print_help_show(); -} - -static int write_file(const char *filename, const char *buf, int size) -{ - FILE *f; - int i; - - /* Write to file */ - f = fopen(filename, "wb"); - if (!f) { - perror("Error opening output file"); - return -1; - } - i = fwrite(buf, 1, size, f); - fclose(f); - if (i != size) { - perror("Error writing to file"); - return -1; - } - - return 0; -} - -static uint8_t *read_file(const char *filename, uint32_t *size_ptr) -{ - FILE *f; - uint8_t *buf; - long size; - - *size_ptr = 0; - - f = fopen(filename, "rb"); - if (!f) { - fprintf(stderr, "Unable to open file %s\n", filename); - return NULL; - } - - fseek(f, 0, SEEK_END); - size = ftell(f); - rewind(f); - - if (size < 0 || size > UINT32_MAX) { - fclose(f); - return NULL; - } - - buf = malloc(size); - if (!buf) { - fclose(f); - return NULL; - } - - if (1 != fread(buf, size, 1, f)) { - fprintf(stderr, "Unable to read from %s\n", filename); - fclose(f); - free(buf); - return NULL; - } - - fclose(f); - - *size_ptr = size; - return buf; -} - -static int estimate_field_size(uint32_t value) -{ - if (value <= UINT8_MAX) - return 1; - if (value <= UINT16_MAX) - return 2; - return 4; -} - -static int parse_integer_field(const char *arg, struct integer_field *f) -{ - uint64_t val; - char *e; - char *ch; - - val = strtoul(arg, &e, 0); - if (val > UINT32_MAX || !*arg || (e && *e && *e != ':')) { - fprintf(stderr, "Invalid integer value\n"); - return -1; - } - f->val = val; - - ch = strchr(arg, ':'); - if (ch) { - ch++; - val = strtoul(ch, &e , 0); - if (val < 1 || 4 < val || !*ch || (e && *e)) { - fprintf(stderr, "Invalid size suffix\n"); - return -1; - } - f->size = val; - } else { - f->size = estimate_field_size(f->val); - } - - if (f->val > (1ull << f->size * 8)) { - fprintf(stderr, "Value (0x%x) exceeds field size (%d)\n", - f->val, f->size); - return -1; - } - - return 0; -} - -static int cmd_create(int argc, char **argv) -{ - uint8_t *cbi; - struct board_info { - struct integer_field ver; - struct integer_field oem; - struct integer_field sku; - struct integer_field model; - const char *dram_part_num; - const char *oem_name; - } bi; - struct cbi_header *h; - int rv; - uint8_t *p; - const char *filename; - uint32_t set_mask = 0; - uint16_t size; - uint8_t erase = 0xff; - int i; - - memset(&bi, 0, sizeof(bi)); - - while ((i = getopt_long(argc, argv, "", opts_create, NULL)) != -1) { - uint64_t val; - char *e; - switch (i) { - case '?': /* Unhandled option */ - print_help_create(); - return -1; - case OPT_HELP: - print_help_create(); - return 0; - case OPT_BOARD_VERSION: - if (parse_integer_field(optarg, &bi.ver)) - return -1; - set_mask |= ARGS_MASK_BOARD_VERSION; - break; - case OPT_ERASE_BYTE: - erase = strtoul(optarg, &e, 0); - if (!*optarg || (e && *e)) { - fprintf(stderr, "Invalid --erase_byte\n"); - return -1; - } - break; - case OPT_FILENAME: - filename = optarg; - set_mask |= ARGS_MASK_FILENAME; - break; - case OPT_OEM_ID: - if (parse_integer_field(optarg, &bi.oem)) - return -1; - break; - case OPT_SIZE: - val = strtoul(optarg, &e, 0); - if (val > UINT16_MAX || !*optarg || (e && *e)) { - fprintf(stderr, "Invalid --size\n"); - return -1; - } - size = val; - set_mask |= ARGS_MASK_SIZE; - break; - case OPT_SKU_ID: - if (parse_integer_field(optarg, &bi.sku)) - return -1; - set_mask |= ARGS_MASK_SKU_ID; - break; - case OPT_DRAM_PART_NUM: - bi.dram_part_num = optarg; - break; - case OPT_OEM_NAME: - bi.oem_name = optarg; - break; - case OPT_MODEL_ID: - if (parse_integer_field(optarg, &bi.model)) - return -1; - break; - } - } - - if (set_mask != (ARGS_MASK_BOARD_VERSION | ARGS_MASK_FILENAME | - ARGS_MASK_SIZE | ARGS_MASK_SKU_ID)) { - fprintf(stderr, "Missing required arguments\n"); - print_help_create(); - return -1; - } - - cbi = malloc(size); - if (!cbi) { - fprintf(stderr, "Failed to allocate memory\n"); - return -1; - } - memset(cbi, erase, size); - - h = (struct cbi_header *)cbi; - memcpy(h->magic, cbi_magic, sizeof(cbi_magic)); - h->major_version = CBI_VERSION_MAJOR; - h->minor_version = CBI_VERSION_MINOR; - p = h->data; - p = cbi_set_data(p, CBI_TAG_BOARD_VERSION, &bi.ver.val, bi.ver.size); - p = cbi_set_data(p, CBI_TAG_OEM_ID, &bi.oem.val, bi.oem.size); - p = cbi_set_data(p, CBI_TAG_SKU_ID, &bi.sku.val, bi.sku.size); - p = cbi_set_data(p, CBI_TAG_MODEL_ID, &bi.model.val, bi.model.size); - p = cbi_set_string(p, CBI_TAG_DRAM_PART_NUM, bi.dram_part_num); - p = cbi_set_string(p, CBI_TAG_OEM_NAME, bi.oem_name); - - h->total_size = p - cbi; - h->crc = cbi_crc8(h); - - /* Output image */ - rv = write_file(filename, cbi, size); - free(cbi); - if (rv) { - fprintf(stderr, "Unable to write CBI image to %s\n", filename); - return rv; - } - - fprintf(stderr, "CBI image is created successfully\n"); - - return 0; -} - -static void print_string(const uint8_t *buf, enum cbi_data_tag tag) -{ - struct cbi_data *d = cbi_find_tag(buf, tag); - const char *name; - - if (!d) - return; - - name = d->tag < CBI_TAG_COUNT ? field_name[d->tag] : "???"; - - printf(" %s: %.*s (%u, %u)\n", name, d->size, (const char *)d->value, - d->tag, d->size); -} - -static void print_integer(const uint8_t *buf, enum cbi_data_tag tag) -{ - uint32_t v; - struct cbi_data *d = cbi_find_tag(buf, tag); - const char *name; - - if (!d) - return; - - name = d->tag < CBI_TAG_COUNT ? field_name[d->tag] : "???"; - - switch (d->size) { - case 1: - v = *(uint8_t *)d->value; - break; - case 2: - v = *(uint16_t *)d->value; - break; - case 4: - v = *(uint32_t *)d->value; - break; - default: - printf(" %s: Integer of size %d not supported\n", - name, d->size); - return; - } - printf(" %s: %u (0x%x, %u, %u)\n", name, v, v, d->tag, d->size); -} - -static int cmd_show(int argc, char **argv) -{ - uint8_t *buf; - uint32_t size; - struct cbi_header *h; - uint32_t set_mask = 0; - const char *filename; - int show_all = 0; - int i; - - while ((i = getopt_long(argc, argv, "", opts_show, NULL)) != -1) { - switch (i) { - case '?': /* Unhandled option */ - print_help_show(); - return -1; - case OPT_HELP: - print_help_show(); - return 0; - case OPT_FILENAME: - filename = optarg; - set_mask |= ARGS_MASK_FILENAME; - break; - case OPT_SHOW_ALL: - show_all = 1; - break; - } - } - - if (set_mask != ARGS_MASK_FILENAME) { - fprintf(stderr, "Missing required arguments\n"); - print_help_show(); - return -1; - } - - buf = read_file(filename, &size); - if (!buf) { - fprintf(stderr, "Unable to read CBI image\n"); - return -1; - } - - h = (struct cbi_header *)buf; - printf("CBI image: %s\n", filename); - - if (memcmp(h->magic, cbi_magic, sizeof(cbi_magic))) { - fprintf(stderr, "Invalid Magic\n"); - free(buf); - return -1; - } - - if (cbi_crc8(h) != h->crc) { - fprintf(stderr, "Invalid CRC\n"); - free(buf); - return -1; - } - - printf(" TOTAL_SIZE: %u\n", h->total_size); - if (show_all) - printf(" CBI_VERSION: %u\n", h->version); - printf(" Data Field: name: value (hex, tag, size)\n"); - print_integer(buf, CBI_TAG_BOARD_VERSION); - print_integer(buf, CBI_TAG_OEM_ID); - print_integer(buf, CBI_TAG_SKU_ID); - print_integer(buf, CBI_TAG_MODEL_ID); - print_string(buf, CBI_TAG_DRAM_PART_NUM); - print_string(buf, CBI_TAG_OEM_NAME); - - free(buf); - - printf("Data validated successfully\n"); - return 0; -} - -int main(int argc, char **argv) -{ - if (argc < 2) { - fprintf(stderr, "Unknown option or missing value\n"); - print_help(); - return -1; - } - - if (!strncmp(argv[1], "create", sizeof("create"))) - return cmd_create(--argc, ++argv); - else if (!strncmp(argv[1], "show", sizeof("show"))) - return cmd_show(--argc, ++argv); - - fprintf(stderr, "Unknown option or missing value\n"); - print_help(); - - return -1; -} diff --git a/util/chargen b/util/chargen deleted file mode 100644 index 42c40f13e4..0000000000 --- a/util/chargen +++ /dev/null @@ -1,69 +0,0 @@ -#!/usr/bin/env python2 -# Copyright 2019 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. - -import sys - -def chargen(modulo, max_chars): - """Generate a stream of characters on the console. - - The stream is an ever incrementing pattern of characters from the - following set: 0..9A..Za..z. - - Args: - modulo: an int, restart the pattern every modulo characters, if - modulo is non zero - max_chars: an int, stop printing after this number of characters if non - zero, if zero - print indefinitely - """ - - base = '0' - c = base - counter = 0 - while True: - sys.stdout.write(c) - counter = counter + 1 - - if (max_chars != 0) and (counter == max_chars): - sys.stdout.write('\n') - return - - if modulo and ((counter % modulo) == 0): - c = base - continue - - if c == 'z': - c = base - elif c == 'Z': - c = 'a' - elif c == '9': - c = 'A' - else: - c = '%c' % (ord(c) + 1) - - -def main(args): - '''Process command line arguments and invoke chargen if args are valid''' - - modulo = 0 - max_chars = 0 - - try: - if len(args) > 0: - modulo = int(args[0]) - if len(args) > 1: - max_chars = int(args[1]) - except ValueError: - sys.stderr.write('usage %s:' - "['seq_length' ['max_chars']]\n") - sys.exit(1) - - try: - chargen(modulo, max_chars) - except KeyboardInterrupt: - print - -if __name__ == '__main__': - main(sys.argv[1:]) - sys.exit(0) diff --git a/util/comm-dev.c b/util/comm-dev.c deleted file mode 100644 index 679f15225f..0000000000 --- a/util/comm-dev.c +++ /dev/null @@ -1,293 +0,0 @@ -/* Copyright 2013 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "cros_ec_dev.h" -#include "comm-host.h" -#include "ec_commands.h" -#include "misc_util.h" - -static int fd = -1; - -#ifndef ARRAY_SIZE -#define ARRAY_SIZE(t) (sizeof(t) / sizeof(t[0])) -#endif - -static const char * const meanings[] = { - "SUCCESS", - "INVALID_COMMAND", - "ERROR", - "INVALID_PARAM", - "ACCESS_DENIED", - "INVALID_RESPONSE", - "INVALID_VERSION", - "INVALID_CHECKSUM", - "IN_PROGRESS", - "UNAVAILABLE", - "TIMEOUT", - "OVERFLOW", - "INVALID_HEADER", - "REQUEST_TRUNCATED", - "RESPONSE_TOO_BIG", - "BUS_ERROR", - "BUSY", - "INVALID_HEADER_VERSION", - "INVALID_HEADER_CRC", - "INVALID_DATA_CRC", - "DUP_UNAVAILABLE", -}; - -static const char *strresult(int i) -{ - if (i < 0 || i >= ARRAY_SIZE(meanings)) - return ""; - return meanings[i]; -} - -/* Old ioctl format, used by Chrome OS 3.18 and older */ - -static int ec_command_dev(int command, int version, - const void *outdata, int outsize, - void *indata, int insize) -{ - struct cros_ec_command s_cmd; - int r; - - s_cmd.command = command; - s_cmd.version = version; - s_cmd.result = 0xff; - s_cmd.outsize = outsize; - s_cmd.outdata = (uint8_t *)outdata; - s_cmd.insize = insize; - s_cmd.indata = indata; - - r = ioctl(fd, CROS_EC_DEV_IOCXCMD, &s_cmd); - if (r < 0) { - fprintf(stderr, "ioctl %d, errno %d (%s), EC result %d (%s)\n", - r, errno, strerror(errno), s_cmd.result, - strresult(s_cmd.result)); - if (errno == EAGAIN && s_cmd.result == EC_RES_IN_PROGRESS) { - s_cmd.command = EC_CMD_RESEND_RESPONSE; - r = ioctl(fd, CROS_EC_DEV_IOCXCMD, &s_cmd); - fprintf(stderr, - "ioctl %d, errno %d (%s), EC result %d (%s)\n", - r, errno, strerror(errno), s_cmd.result, - strresult(s_cmd.result)); - } - } else if (s_cmd.result != EC_RES_SUCCESS) { - fprintf(stderr, "EC result %d (%s)\n", s_cmd.result, - strresult(s_cmd.result)); - return -EECRESULT - s_cmd.result; - } - - return r; -} - -static int ec_readmem_dev(int offset, int bytes, void *dest) -{ - struct cros_ec_readmem s_mem; - struct ec_params_read_memmap r_mem; - int r; - static int fake_it; - - if (!fake_it) { - s_mem.offset = offset; - s_mem.bytes = bytes; - s_mem.buffer = dest; - r = ioctl(fd, CROS_EC_DEV_IOCRDMEM, &s_mem); - if (r < 0 && errno == ENOTTY) - fake_it = 1; - else - return r; - } - - r_mem.offset = offset; - r_mem.size = bytes; - return ec_command_dev(EC_CMD_READ_MEMMAP, 0, - &r_mem, sizeof(r_mem), - dest, bytes); -} - -/* New ioctl format, used by Chrome OS 4.4 and later as well as upstream 4.0+ */ - -static int ec_command_dev_v2(int command, int version, - const void *outdata, int outsize, - void *indata, int insize) -{ - struct cros_ec_command_v2 *s_cmd; - int r; - - assert(outsize == 0 || outdata != NULL); - assert(insize == 0 || indata != NULL); - - s_cmd = malloc(sizeof(struct cros_ec_command_v2) + - MAX(outsize, insize)); - if (s_cmd == NULL) - return -EC_RES_ERROR; - - s_cmd->command = command; - s_cmd->version = version; - s_cmd->result = 0xff; - s_cmd->outsize = outsize; - s_cmd->insize = insize; - memcpy(s_cmd->data, outdata, outsize); - - r = ioctl(fd, CROS_EC_DEV_IOCXCMD_V2, s_cmd); - if (r < 0) { - fprintf(stderr, "ioctl %d, errno %d (%s), EC result %d (%s)\n", - r, errno, strerror(errno), s_cmd->result, - strresult(s_cmd->result)); - if (errno == EAGAIN && s_cmd->result == EC_RES_IN_PROGRESS) { - s_cmd->command = EC_CMD_RESEND_RESPONSE; - r = ioctl(fd, CROS_EC_DEV_IOCXCMD_V2, &s_cmd); - fprintf(stderr, - "ioctl %d, errno %d (%s), EC result %d (%s)\n", - r, errno, strerror(errno), s_cmd->result, - strresult(s_cmd->result)); - } - } else { - memcpy(indata, s_cmd->data, MIN(r, insize)); - if (s_cmd->result != EC_RES_SUCCESS) { - fprintf(stderr, "EC result %d (%s)\n", s_cmd->result, - strresult(s_cmd->result)); - r = -EECRESULT - s_cmd->result; - } - } - free(s_cmd); - - return r; -} - -static int ec_readmem_dev_v2(int offset, int bytes, void *dest) -{ - struct cros_ec_readmem_v2 s_mem; - struct ec_params_read_memmap r_mem; - int r; - static int fake_it; - - if (!fake_it) { - s_mem.offset = offset; - s_mem.bytes = bytes; - r = ioctl(fd, CROS_EC_DEV_IOCRDMEM_V2, &s_mem); - if (r < 0 && errno == ENOTTY) { - fake_it = 1; - } else { - memcpy(dest, s_mem.buffer, bytes); - return r; - } - } - - r_mem.offset = offset; - r_mem.size = bytes; - return ec_command_dev_v2(EC_CMD_READ_MEMMAP, 0, - &r_mem, sizeof(r_mem), - dest, bytes); -} - -/* - * Attempt to communicate with kernel using old ioctl format. - * If it returns ENOTTY, assume that this kernel uses the new format. - */ -static int ec_dev_is_v2(void) -{ - struct ec_params_hello h_req = { - .in_data = 0xa0b0c0d0 - }; - struct ec_response_hello h_resp; - struct cros_ec_command s_cmd = { }; - int r; - - s_cmd.command = EC_CMD_HELLO; - s_cmd.result = 0xff; - s_cmd.outsize = sizeof(h_req); - s_cmd.outdata = (uint8_t *)&h_req; - s_cmd.insize = sizeof(h_resp); - s_cmd.indata = (uint8_t *)&h_resp; - - r = ioctl(fd, CROS_EC_DEV_IOCXCMD, &s_cmd); - if (r < 0 && errno == ENOTTY) - return 1; - - return 0; -} - -static int ec_pollevent_dev(unsigned long mask, void *buffer, size_t buf_size, - int timeout) -{ - int rv; - struct pollfd pf = { .fd = fd, .events = POLLIN }; - - ioctl(fd, CROS_EC_DEV_IOCEVENTMASK_V2, mask); - - rv = poll(&pf, 1, timeout); - if (rv != 1) - return rv; - - if (pf.revents != POLLIN) - return -pf.revents; - - return read(fd, buffer, buf_size); -} - -int comm_init_dev(const char *device_name) -{ - int (*ec_cmd_readmem)(int offset, int bytes, void *dest); - char version[80]; - char device[80] = "/dev/"; - int r; - char *s; - - strncat(device, (device_name ? device_name : CROS_EC_DEV_NAME), 40); - fd = open(device, O_RDWR); - if (fd < 0) - return 1; - - r = read(fd, version, sizeof(version)-1); - if (r <= 0) { - close(fd); - return 2; - } - version[r] = '\0'; - s = strchr(version, '\n'); - if (s) - *s = '\0'; - if (strcmp(version, CROS_EC_DEV_VERSION)) { - close(fd); - return 3; - } - - if (ec_dev_is_v2()) { - ec_command_proto = ec_command_dev_v2; - ec_cmd_readmem = ec_readmem_dev_v2; - } else { - ec_command_proto = ec_command_dev; - ec_cmd_readmem = ec_readmem_dev; - } - - if (ec_cmd_readmem(EC_MEMMAP_ID, 2, version) == 2 && - version[0] == 'E' && version[1] == 'C') - ec_readmem = ec_cmd_readmem; - ec_pollevent = ec_pollevent_dev; - - /* - * Set temporary size, will be updated later. - */ - ec_max_outsize = EC_PROTO2_MAX_PARAM_SIZE - 8; - ec_max_insize = EC_PROTO2_MAX_PARAM_SIZE; - - return 0; -} diff --git a/util/comm-host.c b/util/comm-host.c deleted file mode 100644 index dd42df1aa8..0000000000 --- a/util/comm-host.c +++ /dev/null @@ -1,157 +0,0 @@ -/* Copyright 2013 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 -#include -#include -#include -#include -#include - -#include "comm-host.h" -#include "cros_ec_dev.h" -#include "ec_commands.h" -#include "misc_util.h" - - -int (*ec_command_proto)(int command, int version, - const void *outdata, int outsize, - void *indata, int insize); - -int (*ec_readmem)(int offset, int bytes, void *dest); - -int (*ec_pollevent)(unsigned long mask, void *buffer, size_t buf_size, - int timeout); - -int ec_max_outsize, ec_max_insize; -void *ec_outbuf; -void *ec_inbuf; -static int command_offset; - -int comm_init_dev(const char *device_name) __attribute__((weak)); -int comm_init_lpc(void) __attribute__((weak)); -int comm_init_i2c(int i2c_bus) __attribute__((weak)); -int comm_init_servo_spi(const char *device_name) __attribute__((weak)); - -static int fake_readmem(int offset, int bytes, void *dest) -{ - struct ec_params_read_memmap p; - int c; - char *buf; - - p.offset = offset; - - if (bytes) { - p.size = bytes; - c = ec_command(EC_CMD_READ_MEMMAP, 0, &p, sizeof(p), - dest, p.size); - if (c < 0) - return c; - return p.size; - } - - p.size = EC_MEMMAP_TEXT_MAX; - - c = ec_command(EC_CMD_READ_MEMMAP, 0, &p, sizeof(p), dest, p.size); - if (c < 0) - return c; - - buf = dest; - for (c = 0; c < EC_MEMMAP_TEXT_MAX; c++) { - if (buf[c] == 0) - return c; - } - - buf[EC_MEMMAP_TEXT_MAX - 1] = 0; - return EC_MEMMAP_TEXT_MAX - 1; -} - -void set_command_offset(int offset) -{ - command_offset = offset; -} - -int ec_command(int command, int version, - const void *outdata, int outsize, - void *indata, int insize) -{ - /* Offset command code to support sub-devices */ - return ec_command_proto(command_offset + command, version, - outdata, outsize, - indata, insize); -} - -int comm_init_alt(int interfaces, const char *device_name, int i2c_bus) -{ - bool dev_is_cros_ec; - - /* Default memmap access */ - ec_readmem = fake_readmem; - - if ((interfaces & COMM_SERVO) && comm_init_servo_spi && - !comm_init_servo_spi(device_name)) - return 0; - - /* Do not fallback to other communication methods if target is not a - * cros_ec device */ - dev_is_cros_ec = !strcmp(CROS_EC_DEV_NAME, device_name); - - /* Fallback to direct LPC on x86 */ - if (dev_is_cros_ec && (interfaces & COMM_LPC) && - comm_init_lpc && !comm_init_lpc()) - return 0; - - /* Fallback to direct I2C */ - if ((dev_is_cros_ec || i2c_bus != -1) && (interfaces & COMM_I2C) && - comm_init_i2c && !comm_init_i2c(i2c_bus)) - return 0; - - /* Give up */ - fprintf(stderr, "Unable to establish host communication\n"); - return 1; -} - -int comm_init_buffer(void) -{ - int allow_large_buffer; - struct ec_response_get_protocol_info info; - - allow_large_buffer = kernel_version_ge(3, 14, 0); - if (allow_large_buffer < 0) { - fprintf(stderr, "Unable to check linux version\n"); - return 1; - } - - /* Allocate shared I/O buffers */ - ec_outbuf = malloc(ec_max_outsize); - ec_inbuf = malloc(ec_max_insize); - if (!ec_outbuf || !ec_inbuf) { - fprintf(stderr, "Unable to allocate buffers\n"); - return 1; - } - - /* read max request / response size from ec for protocol v3+ */ - if (ec_command(EC_CMD_GET_PROTOCOL_INFO, 0, NULL, 0, &info, - sizeof(info)) == sizeof(info)) { - int outsize = info.max_request_packet_size - - sizeof(struct ec_host_request); - int insize = info.max_response_packet_size - - sizeof(struct ec_host_response); - if ((allow_large_buffer) || (outsize < ec_max_outsize)) - ec_max_outsize = outsize; - if ((allow_large_buffer) || (insize < ec_max_insize)) - ec_max_insize = insize; - - ec_outbuf = realloc(ec_outbuf, ec_max_outsize); - ec_inbuf = realloc(ec_inbuf, ec_max_insize); - - if (!ec_outbuf || !ec_inbuf) { - fprintf(stderr, "Unable to reallocate buffers\n"); - return 1; - } - } - - return 0; -} diff --git a/util/comm-host.h b/util/comm-host.h deleted file mode 100644 index 309c97eeb5..0000000000 --- a/util/comm-host.h +++ /dev/null @@ -1,103 +0,0 @@ -/* Copyright 2013 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. - * - * For hysterical raisins, there are several mechanisms for communicating with - * the EC. This abstracts them. - */ - -#ifndef __UTIL_COMM_HOST_H -#define __UTIL_COMM_HOST_H - -#include "common.h" -#include "ec_commands.h" - -/* ec_command return value for non-success result from EC */ -#define EECRESULT 1000 - -/* Maximum output and input sizes for EC command, in bytes */ -extern int ec_max_outsize, ec_max_insize; - -/* - * Maximum-size output and input buffers, for use by callers. This saves each - * caller needing to allocate/free its own buffers. - */ -extern void *ec_outbuf; -extern void *ec_inbuf; - -/* Interfaces to allow for comm_init() */ -enum comm_interface { - COMM_DEV = BIT(0), - COMM_LPC = BIT(1), - COMM_I2C = BIT(2), - COMM_SERVO = BIT(3), - COMM_ALL = -1 -}; - -/** - * Initialize alternative interfaces - * - * @param interfaces Interfaces to try; use COMM_ALL to try all of them. - * @param device_name For DEV option, the device file to use. - * @param i2c_bus For I2C option, the bus number to use (or -1 to autodetect). - * @return 0 in case of success, or error code. - */ -int comm_init_alt(int interfaces, const char *device_name, int i2c_bus); - -/** - * Initialize dev interface - * - * @return 0 in case of success, or error code. - */ -int comm_init_dev(const char *device_name); - -/** - * Initialize input & output buffers - * - * @return 0 in case of success, or error code. - */ -int comm_init_buffer(void); - -/** - * Send a command to the EC. Returns the length of output data returned (0 if - * none), or negative on error. - */ -int ec_command(int command, int version, - const void *outdata, int outsize, /* to the EC */ - void *indata, int insize); /* from the EC */ - -/** - * Set the offset to be applied to the command number when ec_command() calls - * ec_command_proto(). - */ -void set_command_offset(int offset); - -/** - * Send a command to the EC. Returns the length of output data returned (0 if - * none), or negative on error. This is the low-level interface implemented - * by the protocol-specific driver. DO NOT call this version directly from - * anywhere but ec_command(), or the --device option will not work. - */ -extern int (*ec_command_proto)(int command, int version, - const void *outdata, int outsize, /* to EC */ - void *indata, int insize); /* from EC */ - -/** - * Return the content of the EC information area mapped as "memory". - * The offsets are defined by the EC_MEMMAP_ constants. Returns the number - * of bytes read, or negative on error. Specifying bytes=0 will read a - * string (always including the trailing '\0'). - */ -extern int (*ec_readmem)(int offset, int bytes, void *dest); - -/** - * Wait for a MKBP event matching 'mask' for at most 'timeout' milliseconds. - * Then read the incoming event content in 'buffer' (or at most - * 'buf_size' bytes of it). - * Return the size of the event read on success, 0 in case of timeout, - * or a negative value in case of error. - */ -extern int (*ec_pollevent)(unsigned long mask, void *buffer, size_t buf_size, - int timeout); - -#endif /* __UTIL_COMM_HOST_H */ diff --git a/util/comm-i2c.c b/util/comm-i2c.c deleted file mode 100644 index d88454ee3b..0000000000 --- a/util/comm-i2c.c +++ /dev/null @@ -1,255 +0,0 @@ -/* Copyright 2012 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. - */ - -#define _GNU_SOURCE /* for asprintf */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "comm-host.h" -#include "i2c.h" - -#define EC_I2C_ADDR 0x1e - -#define I2C_ADAPTER_NODE "/sys/class/i2c-adapter/i2c-%d/%d-%04x/name" -#define I2C_ADAPTER_NAME "cros-ec-i2c" -#define I2C_MAX_ADAPTER 32 -#define I2C_NODE "/dev/i2c-%d" - -#ifdef DEBUG -#define debug(format, arg...) printf(format, ##arg) -#else -#define debug(...) -#endif - -static int i2c_fd = -1; - -static int sum_bytes(const void *data, int length) -{ - const uint8_t *bytes = (const uint8_t *)data; - int sum = 0; - int i; - - for (i = 0; i < length; i++) - sum += bytes[i]; - return sum; -} - -static void dump_buffer(const uint8_t *data, int length) -{ - int i; - - for (i = 0; i < length; i++) - fprintf(stderr, "%02X ", data[i]); - fprintf(stderr, "\n"); -} - -/* - * Sends a command to the EC (protocol v3). Returns the command status code - * (>= 0), or a negative EC_RES_* value on error. - */ -static int ec_command_i2c_3(int command, int version, - const void *outdata, int outsize, - void *indata, int insize) -{ - int ret = -EC_RES_ERROR; - int error; - int req_len, resp_len; - uint8_t *req_buf = NULL; - uint8_t *resp_buf = NULL; - struct ec_host_request *req; - struct ec_host_response *resp; - uint8_t command_return_code; - struct i2c_msg i2c_msg; - struct i2c_rdwr_ioctl_data data; - - if (outsize > ec_max_outsize) { - fprintf(stderr, "Request is too large (%d > %d).\n", outsize, - ec_max_outsize); - return -EC_RES_ERROR; - } - if (insize > ec_max_insize) { - fprintf(stderr, "Response would be too large (%d > %d).\n", - insize, ec_max_insize); - return -EC_RES_ERROR; - } - req_len = I2C_REQUEST_HEADER_SIZE + sizeof(struct ec_host_request) - + outsize; - req_buf = calloc(1, req_len); - if (!req_buf) - goto done; - - req_buf[0] = EC_COMMAND_PROTOCOL_3; - req = (struct ec_host_request *)&req_buf[1]; - req->struct_version = EC_HOST_REQUEST_VERSION; - req->checksum = 0; - req->command = command; - req->command_version = version; - req->reserved = 0; - req->data_len = outsize; - - memcpy(&req_buf[I2C_REQUEST_HEADER_SIZE - + sizeof(struct ec_host_request)], - outdata, outsize); - - req->checksum = - (uint8_t)(-sum_bytes(&req_buf[I2C_REQUEST_HEADER_SIZE], - req_len - I2C_REQUEST_HEADER_SIZE)); - - i2c_msg.addr = EC_I2C_ADDR; - i2c_msg.flags = 0; - i2c_msg.len = req_len; - i2c_msg.buf = (char *)req_buf; - - resp_len = I2C_RESPONSE_HEADER_SIZE + sizeof(struct ec_host_response) - + insize; - resp_buf = calloc(1, resp_len); - if (!resp_buf) - goto done; - memset(resp_buf, 0, resp_len); - - if (IS_ENABLED(DEBUG)) { - fprintf(stderr, "Sending: 0x"); - dump_buffer(req_buf, req_len); - } - - /* - * Combining these two ioctls makes the write-read interval too short - * for some chips (such as the MAX32660) to handle. - */ - data.msgs = &i2c_msg; - data.nmsgs = 1; - error = ioctl(i2c_fd, I2C_RDWR, &data); - if (error < 0) { - fprintf(stderr, "I2C write failed: %d (err: %d, %s)\n", - error, errno, strerror(errno)); - goto done; - } - - i2c_msg.addr = EC_I2C_ADDR; - i2c_msg.flags = I2C_M_RD; - i2c_msg.len = resp_len; - i2c_msg.buf = (char *)resp_buf; - error = ioctl(i2c_fd, I2C_RDWR, &data); - if (error < 0) { - fprintf(stderr, "I2C read failed: %d (err: %d, %s)\n", - error, errno, strerror(errno)); - goto done; - } - - if (IS_ENABLED(DEBUG)) { - fprintf(stderr, "Received: 0x"); - dump_buffer(resp_buf, resp_len); - } - - command_return_code = resp_buf[0]; - if (command_return_code != EC_RES_SUCCESS) { - debug("command 0x%02x returned an error %d\n", command, - command_return_code); - ret = -EECRESULT - command_return_code; - goto done; - } - - if (resp_buf[1] > sizeof(struct ec_host_response) + insize) { - debug("EC returned too much data.\n"); - ret = -EC_RES_RESPONSE_TOO_BIG; - goto done; - } - - resp = (struct ec_host_response *)(&resp_buf[2]); - if (resp->struct_version != EC_HOST_RESPONSE_VERSION) { - debug("EC response version mismatch.\n"); - ret = -EC_RES_INVALID_RESPONSE; - goto done; - } - - if ((uint8_t)sum_bytes(&resp_buf[I2C_RESPONSE_HEADER_SIZE], resp_buf[1]) - != 0) { - debug("Bad checksum on EC response.\n"); - ret = -EC_RES_INVALID_CHECKSUM; - goto done; - } - - memcpy(indata, &resp_buf[I2C_RESPONSE_HEADER_SIZE - + sizeof(struct ec_host_response)], - insize); - - ret = resp->data_len; -done: - if (req_buf) - free(req_buf); - if (resp_buf) - free(resp_buf); - - return ret; -} - -int comm_init_i2c(int i2c_bus) -{ - char *file_path; - char buffer[64]; - int i; - - if (i2c_bus != -1) { - i = i2c_bus; - - if (i >= I2C_MAX_ADAPTER) { - fprintf(stderr, "Invalid I2C bus number %d. (The highest possible bus number is %d.)\n", - i, I2C_MAX_ADAPTER); - return -1; - } - } else { - /* find the device number based on the adapter name */ - for (i = 0; i < I2C_MAX_ADAPTER; i++) { - FILE *f; - - if (asprintf(&file_path, I2C_ADAPTER_NODE, - i, i, EC_I2C_ADDR) < 0) - return -1; - f = fopen(file_path, "r"); - if (f) { - if (fgets(buffer, sizeof(buffer), f) && - !strncmp(buffer, I2C_ADAPTER_NAME, 6)) { - free(file_path); - fclose(f); - break; - } - fclose(f); - } - free(file_path); - } - if (i == I2C_MAX_ADAPTER) { - fprintf(stderr, "Cannot find I2C adapter\n"); - return -1; - } - } - - if (asprintf(&file_path, I2C_NODE, i) < 0) - return -1; - debug("using I2C adapter %s\n", file_path); - i2c_fd = open(file_path, O_RDWR); - if (i2c_fd < 0) - fprintf(stderr, "Cannot open %s : %d\n", file_path, errno); - - free(file_path); - - ec_command_proto = ec_command_i2c_3; - ec_max_outsize = I2C_MAX_HOST_PACKET_SIZE - I2C_REQUEST_HEADER_SIZE - - sizeof(struct ec_host_request); - ec_max_insize = I2C_MAX_HOST_PACKET_SIZE - I2C_RESPONSE_HEADER_SIZE - - sizeof(struct ec_host_response); - - return 0; -} diff --git a/util/comm-lpc.c b/util/comm-lpc.c deleted file mode 100644 index a3a8f64ff7..0000000000 --- a/util/comm-lpc.c +++ /dev/null @@ -1,316 +0,0 @@ -/* Copyright 2013 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. - */ - -/* The I/O asm funcs exist only on x86. */ -#if defined(__i386__) || defined(__x86_64__) - -#include -#include -#include -#include -#include - -#include "comm-host.h" - -#define INITIAL_UDELAY 5 /* 5 us */ -#define MAXIMUM_UDELAY 10000 /* 10 ms */ - -/* - * Wait for the EC to be unbusy. Returns 0 if unbusy, non-zero if - * timeout. - */ -static int wait_for_ec(int status_addr, int timeout_usec) -{ - int i; - int delay = INITIAL_UDELAY; - - for (i = 0; i < timeout_usec; i += delay) { - /* - * Delay first, in case we just sent out a command but the EC - * hasn't raised the busy flag. However, I think this doesn't - * happen since the LPC commands are executed in order and the - * busy flag is set by hardware. Minor issue in any case, - * since the initial delay is very short. - */ - usleep(MIN(delay, timeout_usec - i)); - - if (!(inb(status_addr) & EC_LPC_STATUS_BUSY_MASK)) - return 0; - - /* Increase the delay interval after a few rapid checks */ - if (i > 20) - delay = MIN(delay * 2, MAXIMUM_UDELAY); - } - return -1; /* Timeout */ -} - -static int ec_command_lpc(int command, int version, - const void *outdata, int outsize, - void *indata, int insize) -{ - struct ec_lpc_host_args args; - const uint8_t *d; - uint8_t *dout; - int csum; - int i; - - /* Fill in args */ - args.flags = EC_HOST_ARGS_FLAG_FROM_HOST; - args.command_version = version; - args.data_size = outsize; - - /* Initialize checksum */ - csum = command + args.flags + args.command_version + args.data_size; - - /* Write data and update checksum */ - for (i = 0, d = (uint8_t *)outdata; i < outsize; i++, d++) { - outb(*d, EC_LPC_ADDR_HOST_PARAM + i); - csum += *d; - } - - /* Finalize checksum and write args */ - args.checksum = (uint8_t)csum; - for (i = 0, d = (const uint8_t *)&args; i < sizeof(args); i++, d++) - outb(*d, EC_LPC_ADDR_HOST_ARGS + i); - - outb(command, EC_LPC_ADDR_HOST_CMD); - - if (wait_for_ec(EC_LPC_ADDR_HOST_CMD, 1000000)) { - fprintf(stderr, "Timeout waiting for EC response\n"); - return -EC_RES_ERROR; - } - - /* Check result */ - i = inb(EC_LPC_ADDR_HOST_DATA); - if (i) { - fprintf(stderr, "EC returned error result code %d\n", i); - return -EECRESULT - i; - } - - /* Read back args */ - for (i = 0, dout = (uint8_t *)&args; i < sizeof(args); i++, dout++) - *dout = inb(EC_LPC_ADDR_HOST_ARGS + i); - - /* - * If EC didn't modify args flags, then somehow we sent a new-style - * command to an old EC, which means it would have read its params - * from the wrong place. - */ - if (!(args.flags & EC_HOST_ARGS_FLAG_TO_HOST)) { - fprintf(stderr, "EC protocol mismatch\n"); - return -EC_RES_INVALID_RESPONSE; - } - - if (args.data_size > insize) { - fprintf(stderr, "EC returned too much data\n"); - return -EC_RES_INVALID_RESPONSE; - } - - /* Start calculating response checksum */ - csum = command + args.flags + args.command_version + args.data_size; - - /* Read response and update checksum */ - for (i = 0, dout = (uint8_t *)indata; i < args.data_size; - i++, dout++) { - *dout = inb(EC_LPC_ADDR_HOST_PARAM + i); - csum += *dout; - } - - /* Verify checksum */ - if (args.checksum != (uint8_t)csum) { - fprintf(stderr, "EC response has invalid checksum\n"); - return -EC_RES_INVALID_CHECKSUM; - } - - /* Return actual amount of data received */ - return args.data_size; -} - -static int ec_command_lpc_3(int command, int version, - const void *outdata, int outsize, - void *indata, int insize) -{ - struct ec_host_request rq; - struct ec_host_response rs; - const uint8_t *d; - uint8_t *dout; - int csum = 0; - int i; - - /* Fail if output size is too big */ - if (outsize + sizeof(rq) > EC_LPC_HOST_PACKET_SIZE) - return -EC_RES_REQUEST_TRUNCATED; - - /* Fill in request packet */ - /* TODO(crosbug.com/p/23825): This should be common to all protocols */ - rq.struct_version = EC_HOST_REQUEST_VERSION; - rq.checksum = 0; - rq.command = command; - rq.command_version = version; - rq.reserved = 0; - rq.data_len = outsize; - - /* Copy data and start checksum */ - for (i = 0, d = (const uint8_t *)outdata; i < outsize; i++, d++) { - outb(*d, EC_LPC_ADDR_HOST_PACKET + sizeof(rq) + i); - csum += *d; - } - - /* Finish checksum */ - for (i = 0, d = (const uint8_t *)&rq; i < sizeof(rq); i++, d++) - csum += *d; - - /* Write checksum field so the entire packet sums to 0 */ - rq.checksum = (uint8_t)(-csum); - - /* Copy header */ - for (i = 0, d = (const uint8_t *)&rq; i < sizeof(rq); i++, d++) - outb(*d, EC_LPC_ADDR_HOST_PACKET + i); - - /* Start the command */ - outb(EC_COMMAND_PROTOCOL_3, EC_LPC_ADDR_HOST_CMD); - - if (wait_for_ec(EC_LPC_ADDR_HOST_CMD, 1000000)) { - fprintf(stderr, "Timeout waiting for EC response\n"); - return -EC_RES_ERROR; - } - - /* Check result */ - i = inb(EC_LPC_ADDR_HOST_DATA); - if (i) { - fprintf(stderr, "EC returned error result code %d\n", i); - return -EECRESULT - i; - } - - /* Read back response header and start checksum */ - csum = 0; - for (i = 0, dout = (uint8_t *)&rs; i < sizeof(rs); i++, dout++) { - *dout = inb(EC_LPC_ADDR_HOST_PACKET + i); - csum += *dout; - } - - if (rs.struct_version != EC_HOST_RESPONSE_VERSION) { - fprintf(stderr, "EC response version mismatch\n"); - return -EC_RES_INVALID_RESPONSE; - } - - if (rs.reserved) { - fprintf(stderr, "EC response reserved != 0\n"); - return -EC_RES_INVALID_RESPONSE; - } - - if (rs.data_len > insize) { - fprintf(stderr, "EC returned too much data\n"); - return -EC_RES_RESPONSE_TOO_BIG; - } - - /* Read back data and update checksum */ - for (i = 0, dout = (uint8_t *)indata; i < rs.data_len; i++, dout++) { - *dout = inb(EC_LPC_ADDR_HOST_PACKET + sizeof(rs) + i); - csum += *dout; - } - - /* Verify checksum */ - if ((uint8_t)csum) { - fprintf(stderr, "EC response has invalid checksum\n"); - return -EC_RES_INVALID_CHECKSUM; - } - - /* Return actual amount of data received */ - return rs.data_len; -} - -static int ec_readmem_lpc(int offset, int bytes, void *dest) -{ - int i = offset; - char *s = dest; - int cnt = 0; - - if (offset >= EC_MEMMAP_SIZE - bytes) - return -1; - - if (bytes) { /* fixed length */ - for (; cnt < bytes; i++, s++, cnt++) - *s = inb(EC_LPC_ADDR_MEMMAP + i); - } else { /* string */ - for (; i < EC_MEMMAP_SIZE; i++, s++) { - *s = inb(EC_LPC_ADDR_MEMMAP + i); - cnt++; - if (!*s) - break; - } - } - - return cnt; -} - -int comm_init_lpc(void) -{ - int i; - int byte = 0xff; - - /* Request I/O privilege */ - if (iopl(3) < 0) { - perror("Error getting I/O privilege"); - return -3; - } - - /* - * Test if the I/O port has been configured for Chromium EC LPC - * interface. Chromium EC guarantees that at least one status bit will - * be 0, so if the command and data bytes are both 0xff, very likely - * that Chromium EC is not present. See crosbug.com/p/10963. - */ - byte &= inb(EC_LPC_ADDR_HOST_CMD); - byte &= inb(EC_LPC_ADDR_HOST_DATA); - if (byte == 0xff) { - fprintf(stderr, "Port 0x%x,0x%x are both 0xFF.\n", - EC_LPC_ADDR_HOST_CMD, EC_LPC_ADDR_HOST_DATA); - fprintf(stderr, - "Very likely this board doesn't have a Chromium EC.\n"); - return -4; - } - - /* - * Test if LPC command args are supported. - * - * The cheapest way to do this is by looking for the memory-mapped - * flag. This is faster than sending a new-style 'hello' command and - * seeing whether the EC sets the EC_HOST_ARGS_FLAG_FROM_HOST flag - * in args when it responds. - */ - if (inb(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID) != 'E' || - inb(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID + 1) != 'C') { - fprintf(stderr, "Missing Chromium EC memory map.\n"); - return -5; - } - - /* Check which command version we'll use */ - i = inb(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_HOST_CMD_FLAGS); - - if (i & EC_HOST_CMD_FLAG_VERSION_3) { - /* Protocol version 3 */ - ec_command_proto = ec_command_lpc_3; - ec_max_outsize = EC_LPC_HOST_PACKET_SIZE - - sizeof(struct ec_host_request); - ec_max_insize = EC_LPC_HOST_PACKET_SIZE - - sizeof(struct ec_host_response); - - } else if (i & EC_HOST_CMD_FLAG_LPC_ARGS_SUPPORTED) { - /* Protocol version 2 */ - ec_command_proto = ec_command_lpc; - ec_max_outsize = ec_max_insize = EC_PROTO2_MAX_PARAM_SIZE; - - } else { - fprintf(stderr, "EC doesn't support protocols we need.\n"); - return -5; - } - - /* Either one supports reading mapped memory directly. */ - ec_readmem = ec_readmem_lpc; - return 0; -} - -#endif diff --git a/util/comm-servo-spi.c b/util/comm-servo-spi.c deleted file mode 100644 index 4010d2ec64..0000000000 --- a/util/comm-servo-spi.c +++ /dev/null @@ -1,357 +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. - */ -/* - * Transport using the Servo V2 SPI1 interface through the FT4232 MPSSE - * hardware engine (driven by libftdi) in order to send host commands V3 - * directly to a MCU slave SPI controller. - * - * It allows to drive a MCU with the cros_ec host SPI interface directly from - * a developer workstation or another test system. - * - * The USB serial number of the servo board can be passed in the 'name' - * parameter, e.g. : - * sudo ectool_servo --name=905537-00474 version - */ - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "comm-host.h" -#include "cros_ec_dev.h" - -/* Servo V2 SPI1 interface identifiers */ -#define SERVO_V2_USB_VID 0x18d1 -#define SERVO_V2_USB_PID 0x5003 -#define SERVO_V2_USB_SPI1_INTERFACE INTERFACE_B - -/* SPI clock frequency in Hz */ -#define SPI_CLOCK_FREQ 1000000 - -#define FTDI_LATENCY_1MS 2 - -/* Timeout when waiting for the EC answer to our request */ -#define RESP_TIMEOUT 2 /* second */ - -#ifdef DEBUG -#define debug(format, arg...) printf(format, ##arg) -#else -#define debug(...) -#endif - -/* Communication context */ -static struct ftdi_context ftdi; - -/* Size of a MPSSE command packet */ -#define MPSSE_CMD_SIZE 3 - -enum mpsse_commands { - ENABLE_ADAPTIVE_CLOCK = 0x96, - DISABLE_ADAPTIVE_CLOCK = 0x97, - TCK_X5 = 0x8A, - TCK_D5 = 0x8B, - TRISTATE_IO = 0x9E, -}; - -enum mpsse_pins { - SCLK = 1, - MOSI = 2, - MISO = 4, - CS_L = 8, -}; -/* SCLK/MOSI/CS_L are outputs, MISO is an input */ -#define PINS_DIR (SCLK | MOSI | CS_L) - -/* SPI mode 0: - * propagates data on the falling edge - * and reads data on the rising edge of the clock. - */ -#define SPI_CMD_TX (MPSSE_DO_WRITE | MPSSE_WRITE_NEG) -#define SPI_CMD_RX (MPSSE_DO_READ) -#define SPI_CMD_TXRX (MPSSE_DO_WRITE | MPSSE_DO_READ | MPSSE_WRITE_NEG) - -static int raw_read(uint8_t *buf, int size) -{ - int rlen; - - while (size) { - rlen = ftdi_read_data(&ftdi, buf, size); - if (rlen < 0) - break; - buf += rlen; - size -= rlen; - } - return !!size; -} - -static int mpsse_set_pins(uint8_t levels) -{ - uint8_t buf[MPSSE_CMD_SIZE] = {0}; - - buf[0] = SET_BITS_LOW; - buf[1] = levels; - buf[2] = PINS_DIR; - - return ftdi_write_data(&ftdi, buf, sizeof(buf)) != sizeof(buf); -} - -static int send_request(int cmd, int version, - const uint8_t *outdata, size_t outsize) -{ - uint8_t *txbuf; - struct ec_host_request *request; - size_t i; - int ret = -EC_RES_ERROR; - uint8_t csum = 0; - size_t block_size = sizeof(struct ec_host_request) + outsize; - size_t total_len = MPSSE_CMD_SIZE + block_size; - - txbuf = calloc(1, total_len); - if (!txbuf) - return -ENOMEM; - - /* MPSSE block size is the full command minus 1 byte */ - txbuf[0] = SPI_CMD_TXRX; - txbuf[1] = ((block_size - 1) & 0xFF); - txbuf[2] = (((block_size - 1) >> 8) & 0xFF); - - /* Command header first */ - request = (struct ec_host_request *)(txbuf + MPSSE_CMD_SIZE); - request->struct_version = EC_HOST_REQUEST_VERSION; - request->checksum = 0; - request->command = cmd; - request->command_version = version; - request->reserved = 0; - request->data_len = outsize; - - /* copy the data to transmit after the command header */ - memcpy(txbuf + MPSSE_CMD_SIZE + sizeof(struct ec_host_request), - outdata, outsize); - - /* Compute the checksum */ - for (i = MPSSE_CMD_SIZE; i < total_len; i++) - csum += txbuf[i]; - request->checksum = -csum; - - if (ftdi_write_data(&ftdi, txbuf, total_len) != total_len) - goto free_request; - - if (raw_read(txbuf, block_size) != 0) - goto free_request; - - /* Make sure the EC was listening */ - ret = 0; - for (i = 0; i < block_size; i++) { - switch (txbuf[i]) { - case EC_SPI_PAST_END: - case EC_SPI_RX_BAD_DATA: - case EC_SPI_NOT_READY: - ret = txbuf[i]; - /* Fall-through */ - default: - break; - } - if (ret) - break; - } - -free_request: - free(txbuf); - return ret; -} - -static int spi_read(void *buf, size_t size) -{ - uint8_t cmd[MPSSE_CMD_SIZE]; - - cmd[0] = SPI_CMD_RX; - cmd[1] = ((size - 1) & 0xFF); - cmd[2] = (((size - 1) >> 8) & 0xFF); - - if (ftdi_write_data(&ftdi, cmd, sizeof(cmd)) != sizeof(cmd)) - return -EC_RES_ERROR; - - return raw_read(buf, size) != 0; -} - -static int get_response(uint8_t *bodydest, size_t bodylen) -{ - uint8_t sum = 0; - size_t i; - struct ec_host_response hdr; - uint8_t status; - time_t deadline = time(NULL) + RESP_TIMEOUT; - - /* - * Read a byte at a time until we see the start of the frame. - * This is slow, but often still faster than the EC. - */ - while (time(NULL) < deadline) { - if (spi_read(&status, sizeof(status))) - goto read_error; - if (status == EC_SPI_FRAME_START) - break; - } - if (status != EC_SPI_FRAME_START) { - fprintf(stderr, "timeout wait for response\n"); - return -EC_RES_ERROR; - } - - /* Now read the response header */ - if (spi_read(&hdr, sizeof(hdr))) - goto read_error; - - /* Check the header */ - if (hdr.struct_version != EC_HOST_RESPONSE_VERSION) { - fprintf(stderr, "response version %d (should be %d)\n", - hdr.struct_version, - EC_HOST_RESPONSE_VERSION); - return -EC_RES_ERROR; - } - if (hdr.data_len > bodylen) { - fprintf(stderr, "response data_len %d is > %zd\n", - hdr.data_len, bodylen); - return -EC_RES_ERROR; - } - - /* Read the data if needed */ - if (hdr.data_len && spi_read(bodydest, hdr.data_len)) - goto read_error; - - /* Verify the checksum */ - for (i = 0; i < sizeof(struct ec_host_response); i++) - sum += ((uint8_t *)&hdr)[i]; - for (i = 0; i < hdr.data_len; i++) - sum += bodydest[i]; - if (sum) { - fprintf(stderr, "Checksum invalid\n"); - return -EC_RES_ERROR; - } - - return hdr.result ? -EECRESULT - hdr.result : 0; - -read_error: - fprintf(stderr, "Read failed: %s\n", ftdi_get_error_string(&ftdi)); - return -EC_RES_ERROR; -} - -static int ec_command_servo_spi(int cmd, int version, - const void *outdata, int outsize, - void *indata, int insize) -{ - int ret = -EC_RES_ERROR; - - /* Set the chip select low */ - if (mpsse_set_pins(0) != 0) { - fprintf(stderr, "Start failed: %s\n", - ftdi_get_error_string(&ftdi)); - return -EC_RES_ERROR; - } - - if (send_request(cmd, version, outdata, outsize) == 0) - ret = get_response(indata, insize); - - if (mpsse_set_pins(CS_L) != 0) { - fprintf(stderr, "Stop failed: %s\n", - ftdi_get_error_string(&ftdi)); - return -EC_RES_ERROR; - } - /* SPI protocol gap ... */ - usleep(10); - - return ret; -} - -static int mpsse_set_clock(uint32_t freq) -{ - uint32_t system_clock = 0; - uint16_t divisor = 0; - uint8_t buf[MPSSE_CMD_SIZE] = {0}; - - if (freq > 6000000) { - buf[0] = TCK_X5; - system_clock = 60000000; - } else { - buf[0] = TCK_D5; - system_clock = 12000000; - } - - if (ftdi_write_data(&ftdi, buf, 1) != 1) - return -EC_RES_ERROR; - - divisor = (((system_clock / freq) / 2) - 1); - - buf[0] = TCK_DIVISOR; - buf[1] = (divisor & 0xFF); - buf[2] = ((divisor >> 8) & 0xFF); - - return ftdi_write_data(&ftdi, buf, MPSSE_CMD_SIZE) != MPSSE_CMD_SIZE; -} - -static void servo_spi_close(void) -{ - ftdi_set_bitmode(&ftdi, 0, BITMODE_RESET); - ftdi_usb_close(&ftdi); - ftdi_deinit(&ftdi); -} - -int comm_init_servo_spi(const char *device_name) -{ - int status; - uint8_t buf[MPSSE_CMD_SIZE] = {0}; - /* if the user mentioned a device name, use it as serial string */ - const char *serial = strcmp(CROS_EC_DEV_NAME, device_name) ? - device_name : NULL; - - if (ftdi_init(&ftdi)) - return -EC_RES_ERROR; - ftdi_set_interface(&ftdi, SERVO_V2_USB_SPI1_INTERFACE); - - status = ftdi_usb_open_desc(&ftdi, SERVO_V2_USB_VID, SERVO_V2_USB_PID, - NULL, serial); - if (status) { - debug("Can't find a Servo v2 USB device\n"); - return -EC_RES_ERROR; - } - - status |= ftdi_usb_reset(&ftdi); - status |= ftdi_set_latency_timer(&ftdi, FTDI_LATENCY_1MS); - status |= ftdi_set_bitmode(&ftdi, 0, BITMODE_RESET); - if (status) - goto err_close; - - ftdi_set_bitmode(&ftdi, 0, BITMODE_MPSSE); - if (mpsse_set_clock(SPI_CLOCK_FREQ)) - goto err_close; - - /* Disable FTDI internal loopback */ - buf[0] = LOOPBACK_END; - if (ftdi_write_data(&ftdi, buf, 1) != 1) - goto err_close; - /* Ensure adaptive clock is disabled */ - buf[0] = DISABLE_ADAPTIVE_CLOCK; - if (ftdi_write_data(&ftdi, buf, 1) != 1) - goto err_close; - /* Set the idle pin states */ - if (mpsse_set_pins(CS_L) != 0) - goto err_close; - - ec_command_proto = ec_command_servo_spi; - /* Set temporary size, will be updated later. */ - ec_max_outsize = EC_PROTO2_MAX_PARAM_SIZE - 8; - ec_max_insize = EC_PROTO2_MAX_PARAM_SIZE; - - return 0; - -err_close: - servo_spi_close(); - return -EC_RES_ERROR; -} diff --git a/util/cros_ec_dev.h b/util/cros_ec_dev.h deleted file mode 100644 index 41930f97dd..0000000000 --- a/util/cros_ec_dev.h +++ /dev/null @@ -1,98 +0,0 @@ -/* Copyright 2013 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 __UTIL_CROS_EC_DEV_H -#define __UTIL_CROS_EC_DEV_H - -#include -#include -#include "ec_commands.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define CROS_EC_DEV_NAME "cros_ec" -#define CROS_EC_DEV_VERSION "1.0.0" - -/* - * @version: Command version number (often 0) - * @command: Command to send (EC_CMD_...) - * @outdata: Outgoing data to EC - * @outsize: Outgoing length in bytes - * @indata: Where to put the incoming data from EC - * @insize: On call, how much we can accept. On return, how much we got. - * @result: EC's response to the command (separate from communication failure) - * ioctl returns zero on success, negative on error - */ -struct cros_ec_command { - uint32_t version; - uint32_t command; - uint8_t *outdata; - uint32_t outsize; - uint8_t *indata; - uint32_t insize; - uint32_t result; -}; - -/* - * @offset: within EC_LPC_ADDR_MEMMAP region - * @bytes: number of bytes to read. zero means "read a string" (including '\0') - * (at most only EC_MEMMAP_SIZE bytes can be read) - * @buffer: where to store the result - * ioctl returns the number of bytes read, negative on error - */ -struct cros_ec_readmem { - uint32_t offset; - uint32_t bytes; - char *buffer; -}; - -#define CROS_EC_DEV_IOC ':' -#define CROS_EC_DEV_IOCXCMD _IOWR(':', 0, struct cros_ec_command) -#define CROS_EC_DEV_IOCRDMEM _IOWR(':', 1, struct cros_ec_readmem) - -/* - * @version: Command version number (often 0) - * @command: Command to send (EC_CMD_...) - * @outsize: Outgoing length in bytes - * @insize: Max number of bytes to accept from EC - * @result: EC's response to the command (separate from communication failure) - * @data: Where to put the incoming data from EC and outgoing data to EC - */ -struct cros_ec_command_v2 { - uint32_t version; - uint32_t command; - uint32_t outsize; - uint32_t insize; - uint32_t result; - uint8_t data[0]; -}; - -/* - * @offset: within EC_LPC_ADDR_MEMMAP region - * @bytes: number of bytes to read. zero means "read a string" (including '\0') - * (at most only EC_MEMMAP_SIZE bytes can be read) - * @buffer: where to store the result - * ioctl returns the number of bytes read, negative on error - */ -struct cros_ec_readmem_v2 { - uint32_t offset; - uint32_t bytes; - uint8_t buffer[EC_MEMMAP_SIZE]; -}; - -#define CROS_EC_DEV_IOC_V2 0xEC -#define CROS_EC_DEV_IOCXCMD_V2 _IOWR(CROS_EC_DEV_IOC_V2, 0, \ - struct cros_ec_command_v2) -#define CROS_EC_DEV_IOCRDMEM_V2 _IOWR(CROS_EC_DEV_IOC_V2, 1, \ - struct cros_ec_readmem_v2) -#define CROS_EC_DEV_IOCEVENTMASK_V2 _IO(CROS_EC_DEV_IOC_V2, 2) - -#ifdef __cplusplus -} -#endif - -#endif /* __UTIL_CROS_EC_DEV_H */ diff --git a/util/ec3po/__init__.py b/util/ec3po/__init__.py deleted file mode 100644 index 9bebfa5842..0000000000 --- a/util/ec3po/__init__.py +++ /dev/null @@ -1,25 +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. - -"""The EC console interpreter. - -EC-3PO is a console interpreter which migrates the rich debug console from the -EC itself to the host. This allows for a rich debug console without impacting -EC image sizes while also allowing the development of new console features. - -The package consists of two modules: console and interpreter. The console -module provides the interactive console interface between the user and the -interpreter. It handles the presentation of the EC console including editing -methods as well as session-persistent command history. - -The interpreter module provides the interpretation layer between the EC UART and -the user. The user does not necessarily have to be the interactive console, but -could be something like autotest. The interpreter is also responsible for the -automatic command retrying if the EC drops a character in a command. This is a -stopgap until all commands are communicated via host commands. -""" - -import console -import interpreter -import threadproc_shim diff --git a/util/ec3po/console.py b/util/ec3po/console.py deleted file mode 100755 index 3643ea498a..0000000000 --- a/util/ec3po/console.py +++ /dev/null @@ -1,1125 +0,0 @@ -#!/usr/bin/env python2 -# 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. - -"""EC-3PO Interactive Console Interface - -console provides the console interface between the user and the interpreter. It -handles the presentation of the EC console including editing methods as well as -session-persistent command history. -""" - -from __future__ import print_function - -import argparse -import binascii -import copy -import ctypes -from datetime import datetime -# pylint: disable=cros-logging-import -import logging -import os -import pty -import re -import select -import stat -import sys -import traceback - -import interpreter -import threadproc_shim - - -PROMPT = '> ' -CONSOLE_INPUT_LINE_SIZE = 80 # Taken from the CONFIG_* with the same name. -CONSOLE_MAX_READ = 100 # Max bytes to read at a time from the user. -LOOK_BUFFER_SIZE = 256 # Size of search window when looking for the enhanced EC - # image string. - -# In console_init(), the EC will print a string saying that the EC console is -# enabled. Enhanced images will print a slightly different string. These -# regular expressions are used to determine at reboot whether the EC image is -# enhanced or not. -ENHANCED_IMAGE_RE = re.compile(r'Enhanced Console is enabled ' - r'\(v([0-9]+\.[0-9]+\.[0-9]+)\)') -NON_ENHANCED_IMAGE_RE = re.compile(r'Console is enabled; ') - -# The timeouts are really only useful for enhanced EC images, but otherwise just -# serve as a delay for non-enhanced EC images. Therefore, we can keep this -# value small enough so that there's not too much of a delay, but long enough -# that enhanced EC images can respond in time. Once we've detected an enhanced -# EC image, we can increase the timeout for stability just in case it takes a -# bit longer to receive an ACK for some reason. -NON_ENHANCED_EC_INTERROGATION_TIMEOUT = 0.3 # Maximum number of seconds to wait - # for a response to an - # interrogation of a non-enhanced - # EC image. -ENHANCED_EC_INTERROGATION_TIMEOUT = 1.0 # Maximum number of seconds to wait for - # a response to an interrogation of an - # enhanced EC image. -INTERROGATION_MODES = ['never', 'always', 'auto'] # List of modes which control - # when interrogations are - # performed with the EC. -# Format for printing host timestamp -HOST_STRFTIME="%Y-%m-%d %H:%M:%S " - - -class EscState(object): - """Class which contains an enumeration for states of ESC sequences.""" - ESC_START = 1 - ESC_BRACKET = 2 - ESC_BRACKET_1 = 3 - ESC_BRACKET_3 = 4 - ESC_BRACKET_8 = 5 - - -class ControlKey(object): - """Class which contains codes for various control keys.""" - BACKSPACE = 0x08 - CTRL_A = 0x01 - CTRL_B = 0x02 - CTRL_D = 0x04 - CTRL_E = 0x05 - CTRL_F = 0x06 - CTRL_K = 0x0b - CTRL_N = 0xe - CTRL_P = 0x10 - CARRIAGE_RETURN = 0x0d - ESC = 0x1b - - -class Console(object): - """Class which provides the console interface between the EC and the user. - - This class essentially represents the console interface between the user and - the EC. It handles all of the console editing behaviour - - Attributes: - logger: A logger for this module. - master_pty: File descriptor to the master side of the PTY. Used for driving - output to the user and receiving user input. - user_pty: A string representing the PTY name of the served console. - cmd_pipe: A socket.socket or multiprocessing.Connection object which - represents the console side of the command pipe. This must be a - bidirectional pipe. Console commands and responses utilize this pipe. - dbg_pipe: A socket.socket or multiprocessing.Connection object which - represents the console's read-only side of the debug pipe. This must be a - unidirectional pipe attached to the intepreter. EC debug messages use - this pipe. - oobm_queue: A Queue.Queue or multiprocessing.Queue which is used for out of - band management for the interactive console. - input_buffer: A string representing the current input command. - input_buffer_pos: An integer representing the current position in the buffer - to insert a char. - partial_cmd: A string representing the command entered on a line before - pressing the up arrow keys. - esc_state: An integer represeting the current state within an escape - sequence. - line_limit: An integer representing the maximum number of characters on a - line. - history: A list of strings containing the past entered console commands. - history_pos: An integer representing the current history buffer position. - This index is used to show previous commands. - prompt: A string representing the console prompt displayed to the user. - enhanced_ec: A boolean indicating if the EC image that we are currently - communicating with is enhanced or not. Enhanced EC images will support - packed commands and host commands over the UART. This defaults to False - until we perform some handshaking. - interrogation_timeout: A float representing the current maximum seconds to - wait for a response to an interrogation. - receiving_oobm_cmd: A boolean indicating whether or not the console is in - the middle of receiving an out of band command. - pending_oobm_cmd: A string containing the pending OOBM command. - interrogation_mode: A string containing the current mode of whether - interrogations are performed with the EC or not and how often. - raw_debug: Flag to indicate whether per interrupt data should be logged to - debug - output_line_log_buffer: buffer for lines coming from the EC to log to debug - """ - - def __init__(self, master_pty, user_pty, interface_pty, cmd_pipe, dbg_pipe, - name=None): - """Initalises a Console object with the provided arguments. - - Args: - master_pty: File descriptor to the master side of the PTY. Used for driving - output to the user and receiving user input. - user_pty: A string representing the PTY name of the served console. - interface_pty: A string representing the PTY name of the served command - interface. - cmd_pipe: A socket.socket or multiprocessing.Connection object which - represents the console side of the command pipe. This must be a - bidirectional pipe. Console commands and responses utilize this pipe. - dbg_pipe: A socket.socket or multiprocessing.Connection object which - represents the console's read-only side of the debug pipe. This must be a - unidirectional pipe attached to the intepreter. EC debug messages use - this pipe. - name: the console source name - """ - # Create a unique logger based on the console name - console_prefix = ('%s - ' % name) if name else '' - logger = logging.getLogger('%sEC3PO.Console' % console_prefix) - self.logger = interpreter.LoggerAdapter(logger, {'pty': user_pty}) - self.master_pty = master_pty - self.user_pty = user_pty - self.interface_pty = interface_pty - self.cmd_pipe = cmd_pipe - self.dbg_pipe = dbg_pipe - self.oobm_queue = threadproc_shim.Queue() - self.input_buffer = '' - self.input_buffer_pos = 0 - self.partial_cmd = '' - self.esc_state = 0 - self.line_limit = CONSOLE_INPUT_LINE_SIZE - self.history = [] - self.history_pos = 0 - self.prompt = PROMPT - self.enhanced_ec = False - self.interrogation_timeout = NON_ENHANCED_EC_INTERROGATION_TIMEOUT - self.receiving_oobm_cmd = False - self.pending_oobm_cmd = '' - self.interrogation_mode = 'auto' - self.timestamp_enabled = True - self.look_buffer = '' - self.raw_debug = False - self.output_line_log_buffer = '' - - def __str__(self): - """Show internal state of Console object as a string.""" - string = [] - string.append('master_pty: %s' % self.master_pty) - string.append('user_pty: %s' % self.user_pty) - string.append('interface_pty: %s' % self.interface_pty) - string.append('cmd_pipe: %s' % self.cmd_pipe) - string.append('dbg_pipe: %s' % self.dbg_pipe) - string.append('oobm_queue: %s' % self.oobm_queue) - string.append('input_buffer: %s' % self.input_buffer) - string.append('input_buffer_pos: %d' % self.input_buffer_pos) - string.append('esc_state: %d' % self.esc_state) - string.append('line_limit: %d' % self.line_limit) - string.append('history: [\'' + '\', \''.join(self.history) + '\']') - string.append('history_pos: %d' % self.history_pos) - string.append('prompt: \'%s\'' % self.prompt) - string.append('partial_cmd: \'%s\''% self.partial_cmd) - string.append('interrogation_mode: \'%s\'' % self.interrogation_mode) - string.append('look_buffer: \'%s\'' % self.look_buffer) - return '\n'.join(string) - - def LogConsoleOutput(self, data): - """Log to debug user MCU output to master_pty when line is filled. - - Args: - data: string received from MCU - """ - output_data = '%s%s' % (self.output_line_log_buffer, data) - ends_in_nl = output_data[-1] == '\n' - data_lines = output_data.splitlines() - for line in data_lines[:-1]: - self.logger.debug(line) - if ends_in_nl: - self.logger.debug(data_lines[-1]) - self.output_line_log_buffer = '' - else: - self.output_line_log_buffer = data_lines[-1] - - def PrintHistory(self): - """Print the history of entered commands.""" - fd = self.master_pty - # Make it pretty by figuring out how wide to pad the numbers. - wide = (len(self.history) / 10) + 1 - for i in range(len(self.history)): - line = ' %*d %s\r\n' % (wide, i, self.history[i]) - os.write(fd, line) - - def ShowPreviousCommand(self): - """Shows the previous command from the history list.""" - # There's nothing to do if there's no history at all. - if not self.history: - self.logger.debug('No history to print.') - return - - # Don't do anything if there's no more history to show. - if self.history_pos == 0: - self.logger.debug('No more history to show.') - return - - self.logger.debug('current history position: %d.', self.history_pos) - - # Decrement the history buffer position. - self.history_pos -= 1 - self.logger.debug('new history position.: %d', self.history_pos) - - # Save the text entered on the console if any. - if self.history_pos == len(self.history)-1: - self.logger.debug('saving partial_cmd: \'%s\'', self.input_buffer) - self.partial_cmd = self.input_buffer - - # Backspace the line. - for _ in range(self.input_buffer_pos): - self.SendBackspace() - - # Print the last entry in the history buffer. - self.logger.debug('printing previous entry %d - %s', self.history_pos, - self.history[self.history_pos]) - fd = self.master_pty - prev_cmd = self.history[self.history_pos] - os.write(fd, prev_cmd) - # Update the input buffer. - self.input_buffer = prev_cmd - self.input_buffer_pos = len(prev_cmd) - - def ShowNextCommand(self): - """Shows the next command from the history list.""" - # Don't do anything if there's no history at all. - if not self.history: - self.logger.debug('History buffer is empty.') - return - - fd = self.master_pty - - self.logger.debug('current history position: %d', self.history_pos) - # Increment the history position. - self.history_pos += 1 - - # Restore the partial cmd. - if self.history_pos == len(self.history): - self.logger.debug('Restoring partial command of \'%s\'', self.partial_cmd) - # Backspace the line. - for _ in range(self.input_buffer_pos): - self.SendBackspace() - # Print the partially entered command if any. - os.write(fd, self.partial_cmd) - self.input_buffer = self.partial_cmd - self.input_buffer_pos = len(self.input_buffer) - # Now that we've printed it, clear the partial cmd storage. - self.partial_cmd = '' - # Reset history position. - self.history_pos = len(self.history) - return - - self.logger.debug('new history position: %d', self.history_pos) - if self.history_pos > len(self.history)-1: - self.logger.debug('No more history to show.') - self.history_pos -= 1 - self.logger.debug('Reset history position to %d', self.history_pos) - return - - # Backspace the line. - for _ in range(self.input_buffer_pos): - self.SendBackspace() - - # Print the newer entry from the history buffer. - self.logger.debug('printing next entry %d - %s', self.history_pos, - self.history[self.history_pos]) - next_cmd = self.history[self.history_pos] - os.write(fd, next_cmd) - # Update the input buffer. - self.input_buffer = next_cmd - self.input_buffer_pos = len(next_cmd) - self.logger.debug('new history position: %d.', self.history_pos) - - def SliceOutChar(self): - """Remove a char from the line and shift everything over 1 column.""" - fd = self.master_pty - # Remove the character at the input_buffer_pos by slicing it out. - self.input_buffer = self.input_buffer[0:self.input_buffer_pos] + \ - self.input_buffer[self.input_buffer_pos+1:] - # Write the rest of the line - moved_col = os.write(fd, self.input_buffer[self.input_buffer_pos:]) - # Write a space to clear out the last char - moved_col += os.write(fd, ' ') - # Update the input buffer position. - self.input_buffer_pos += moved_col - # Reset the cursor - self.MoveCursor('left', moved_col) - - def HandleEsc(self, byte): - """HandleEsc processes escape sequences. - - Args: - byte: An integer representing the current byte in the sequence. - """ - # We shouldn't be handling an escape sequence if we haven't seen one. - assert self.esc_state != 0 - - if self.esc_state is EscState.ESC_START: - self.logger.debug('ESC_START') - if byte == ord('['): - self.esc_state = EscState.ESC_BRACKET - return - - else: - self.logger.error('Unexpected sequence. %c', byte) - self.esc_state = 0 - - elif self.esc_state is EscState.ESC_BRACKET: - self.logger.debug('ESC_BRACKET') - # Left Arrow key was pressed. - if byte == ord('D'): - self.logger.debug('Left arrow key pressed.') - self.MoveCursor('left', 1) - self.esc_state = 0 # Reset the state. - return - - # Right Arrow key. - elif byte == ord('C'): - self.logger.debug('Right arrow key pressed.') - self.MoveCursor('right', 1) - self.esc_state = 0 # Reset the state. - return - - # Up Arrow key. - elif byte == ord('A'): - self.logger.debug('Up arrow key pressed.') - self.ShowPreviousCommand() - # Reset the state. - self.esc_state = 0 # Reset the state. - return - - # Down Arrow key. - elif byte == ord('B'): - self.logger.debug('Down arrow key pressed.') - self.ShowNextCommand() - # Reset the state. - self.esc_state = 0 # Reset the state. - return - - # For some reason, minicom sends a 1 instead of 7. /shrug - # TODO(aaboagye): Figure out why this happens. - elif byte == ord('1') or byte == ord('7'): - self.esc_state = EscState.ESC_BRACKET_1 - - elif byte == ord('3'): - self.esc_state = EscState.ESC_BRACKET_3 - - elif byte == ord('8'): - self.esc_state = EscState.ESC_BRACKET_8 - - else: - self.logger.error(r'Bad or unhandled escape sequence. got ^[%c\(%d)', - chr(byte), byte) - self.esc_state = 0 - return - - elif self.esc_state is EscState.ESC_BRACKET_1: - self.logger.debug('ESC_BRACKET_1') - # HOME key. - if byte == ord('~'): - self.logger.debug('Home key pressed.') - self.MoveCursor('left', self.input_buffer_pos) - self.esc_state = 0 # Reset the state. - self.logger.debug('ESC sequence complete.') - return - - elif self.esc_state is EscState.ESC_BRACKET_3: - self.logger.debug('ESC_BRACKET_3') - # DEL key. - if byte == ord('~'): - self.logger.debug('Delete key pressed.') - if self.input_buffer_pos != len(self.input_buffer): - self.SliceOutChar() - self.esc_state = 0 # Reset the state. - - elif self.esc_state is EscState.ESC_BRACKET_8: - self.logger.debug('ESC_BRACKET_8') - # END key. - if byte == ord('~'): - self.logger.debug('End key pressed.') - self.MoveCursor('right', - len(self.input_buffer) - self.input_buffer_pos) - self.esc_state = 0 # Reset the state. - self.logger.debug('ESC sequence complete.') - return - - else: - self.logger.error('Unexpected sequence. %c', byte) - self.esc_state = 0 - - else: - self.logger.error('Unexpected sequence. %c', byte) - self.esc_state = 0 - - def ProcessInput(self): - """Captures the input determines what actions to take.""" - # There's nothing to do if the input buffer is empty. - if len(self.input_buffer) == 0: - return - - # Don't store 2 consecutive identical commands in the history. - if (self.history and self.history[-1] != self.input_buffer - or not self.history): - self.history.append(self.input_buffer) - - # Split the command up by spaces. - line = self.input_buffer.split(' ') - self.logger.debug('cmd: %s', self.input_buffer) - cmd = line[0].lower() - - # The 'history' command is a special case that we handle locally. - if cmd == 'history': - self.PrintHistory() - return - - # Send the command to the interpreter. - self.logger.debug('Sending command to interpreter.') - self.cmd_pipe.send(self.input_buffer) - - def CheckForEnhancedECImage(self): - """Performs an interrogation of the EC image. - - Send a SYN and expect an ACK. If no ACK or the response is incorrect, then - assume that the current EC image that we are talking to is not enhanced. - - Returns: - is_enhanced: A boolean indicating whether the EC responded to the - interrogation correctly. - - Raises: - EOFError: Allowed to propagate through from self.dbg_pipe.recv(). - """ - # Send interrogation byte and wait for the response. - self.logger.debug('Performing interrogation.') - self.cmd_pipe.send(interpreter.EC_SYN) - - response = '' - if self.dbg_pipe.poll(self.interrogation_timeout): - response = self.dbg_pipe.recv() - self.logger.debug('response: \'%s\'', binascii.hexlify(response)) - else: - self.logger.debug('Timed out waiting for EC_ACK') - - # Verify the acknowledgment. - is_enhanced = response == interpreter.EC_ACK - - if is_enhanced: - # Increase the interrogation timeout for stability purposes. - self.interrogation_timeout = ENHANCED_EC_INTERROGATION_TIMEOUT - self.logger.debug('Increasing interrogation timeout to %rs.', - self.interrogation_timeout) - else: - # Reduce the timeout in order to reduce the perceivable delay. - self.interrogation_timeout = NON_ENHANCED_EC_INTERROGATION_TIMEOUT - self.logger.debug('Reducing interrogation timeout to %rs.', - self.interrogation_timeout) - - return is_enhanced - - def HandleChar(self, byte): - """HandleChar does a certain action when it receives a character. - - Args: - byte: An integer representing the character received from the user. - - Raises: - EOFError: Allowed to propagate through from self.CheckForEnhancedECImage() - i.e. from self.dbg_pipe.recv(). - """ - fd = self.master_pty - - # Enter the OOBM prompt mode if the user presses '%'. - if byte == ord('%'): - self.logger.debug('Begin OOBM command.') - self.receiving_oobm_cmd = True - # Print a "prompt". - os.write(self.master_pty, '\r\n% ') - return - - # Add chars to the pending OOBM command if we're currently receiving one. - if self.receiving_oobm_cmd and byte != ControlKey.CARRIAGE_RETURN: - self.pending_oobm_cmd += chr(byte) - self.logger.debug('%s', chr(byte)) - os.write(self.master_pty, chr(byte)) - return - - if byte == ControlKey.CARRIAGE_RETURN: - if self.receiving_oobm_cmd: - # Terminate the command and place it in the OOBM queue. - self.logger.debug('End OOBM command.') - if self.pending_oobm_cmd: - self.oobm_queue.put(self.pending_oobm_cmd) - self.logger.debug('Placed \'%s\' into OOBM command queue.', - self.pending_oobm_cmd) - - # Reset the state. - os.write(self.master_pty, '\r\n' + self.prompt) - self.input_buffer = '' - self.input_buffer_pos = 0 - self.receiving_oobm_cmd = False - self.pending_oobm_cmd = '' - return - - if self.interrogation_mode == 'never': - self.logger.debug('Skipping interrogation because interrogation mode' - ' is set to never.') - elif self.interrogation_mode == 'always': - # Only interrogate the EC if the interrogation mode is set to 'always'. - self.enhanced_ec = self.CheckForEnhancedECImage() - self.logger.debug('Enhanced EC image? %r', self.enhanced_ec) - - if not self.enhanced_ec: - # Send everything straight to the EC to handle. - self.cmd_pipe.send(chr(byte)) - # Reset the input buffer. - self.input_buffer = '' - self.input_buffer_pos = 0 - self.logger.log(1, 'Reset input buffer.') - return - - # Keep handling the ESC sequence if we're in the middle of it. - if self.esc_state != 0: - self.HandleEsc(byte) - return - - # When we're at the end of the line, we should only allow going backwards, - # backspace, carriage return, up, or down. The arrow keys are escape - # sequences, so we let the escape...escape. - if (self.input_buffer_pos >= self.line_limit and - byte not in [ControlKey.CTRL_B, ControlKey.ESC, ControlKey.BACKSPACE, - ControlKey.CTRL_A, ControlKey.CARRIAGE_RETURN, - ControlKey.CTRL_P, ControlKey.CTRL_N]): - return - - # If the input buffer is full we can't accept new chars. - buffer_full = len(self.input_buffer) >= self.line_limit - - - # Carriage_Return/Enter - if byte == ControlKey.CARRIAGE_RETURN: - self.logger.debug('Enter key pressed.') - # Put a carriage return/newline and the print the prompt. - os.write(fd, '\r\n') - - # TODO(aaboagye): When we control the printing of all output, print the - # prompt AFTER printing all the output. We can't do it yet because we - # don't know how much is coming from the EC. - - # Print the prompt. - os.write(fd, self.prompt) - # Process the input. - self.ProcessInput() - # Now, clear the buffer. - self.input_buffer = '' - self.input_buffer_pos = 0 - # Reset history buffer pos. - self.history_pos = len(self.history) - # Clear partial command. - self.partial_cmd = '' - - # Backspace - elif byte == ControlKey.BACKSPACE: - self.logger.debug('Backspace pressed.') - if self.input_buffer_pos > 0: - # Move left 1 column. - self.MoveCursor('left', 1) - # Remove the character at the input_buffer_pos by slicing it out. - self.SliceOutChar() - - self.logger.debug('input_buffer_pos: %d', self.input_buffer_pos) - - # Ctrl+A. Move cursor to beginning of the line - elif byte == ControlKey.CTRL_A: - self.logger.debug('Control+A pressed.') - self.MoveCursor('left', self.input_buffer_pos) - - # Ctrl+B. Move cursor left 1 column. - elif byte == ControlKey.CTRL_B: - self.logger.debug('Control+B pressed.') - self.MoveCursor('left', 1) - - # Ctrl+D. Delete a character. - elif byte == ControlKey.CTRL_D: - self.logger.debug('Control+D pressed.') - if self.input_buffer_pos != len(self.input_buffer): - # Remove the character by slicing it out. - self.SliceOutChar() - - # Ctrl+E. Move cursor to end of the line. - elif byte == ControlKey.CTRL_E: - self.logger.debug('Control+E pressed.') - self.MoveCursor('right', - len(self.input_buffer) - self.input_buffer_pos) - - # Ctrl+F. Move cursor right 1 column. - elif byte == ControlKey.CTRL_F: - self.logger.debug('Control+F pressed.') - self.MoveCursor('right', 1) - - # Ctrl+K. Kill line. - elif byte == ControlKey.CTRL_K: - self.logger.debug('Control+K pressed.') - self.KillLine() - - # Ctrl+N. Next line. - elif byte == ControlKey.CTRL_N: - self.logger.debug('Control+N pressed.') - self.ShowNextCommand() - - # Ctrl+P. Previous line. - elif byte == ControlKey.CTRL_P: - self.logger.debug('Control+P pressed.') - self.ShowPreviousCommand() - - # ESC sequence - elif byte == ControlKey.ESC: - # Starting an ESC sequence - self.esc_state = EscState.ESC_START - - # Only print printable chars. - elif IsPrintable(byte): - # Drop the character if we're full. - if buffer_full: - self.logger.debug('Dropped char: %c(%d)', byte, byte) - return - # Print the character. - os.write(fd, chr(byte)) - # Print the rest of the line (if any). - extra_bytes_written = os.write(fd, - self.input_buffer[self.input_buffer_pos:]) - - # Recreate the input buffer. - self.input_buffer = (self.input_buffer[0:self.input_buffer_pos] + - ('%c' % byte) + - self.input_buffer[self.input_buffer_pos:]) - # Update the input buffer position. - self.input_buffer_pos += 1 + extra_bytes_written - - # Reset the cursor if we wrote any extra bytes. - if extra_bytes_written: - self.MoveCursor('left', extra_bytes_written) - - self.logger.debug('input_buffer_pos: %d', self.input_buffer_pos) - - def MoveCursor(self, direction, count): - """MoveCursor moves the cursor left or right by count columns. - - Args: - direction: A string that should be either 'left' or 'right' representing - the direction to move the cursor on the console. - count: An integer representing how many columns the cursor should be - moved. - - Raises: - AssertionError: If the direction is not equal to 'left' or 'right'. - """ - # If there's nothing to move, we're done. - if not count: - return - fd = self.master_pty - seq = '\033[' + str(count) - if direction == 'left': - # Bind the movement. - if count > self.input_buffer_pos: - count = self.input_buffer_pos - seq += 'D' - self.logger.debug('move cursor left %d', count) - self.input_buffer_pos -= count - - elif direction == 'right': - # Bind the movement. - if (count + self.input_buffer_pos) > len(self.input_buffer): - count = 0 - seq += 'C' - self.logger.debug('move cursor right %d', count) - self.input_buffer_pos += count - - else: - raise AssertionError(('The only valid directions are \'left\' and ' - '\'right\'')) - - self.logger.debug('input_buffer_pos: %d', self.input_buffer_pos) - # Move the cursor. - if count != 0: - os.write(fd, seq) - - def KillLine(self): - """Kill the rest of the line based on the input buffer position.""" - # Killing the line is killing all the text to the right. - diff = len(self.input_buffer) - self.input_buffer_pos - self.logger.debug('diff: %d', diff) - # Diff shouldn't be negative, but if it is for some reason, let's try to - # correct the cursor. - if diff < 0: - self.logger.warning('Resetting input buffer position to %d...', - len(self.input_buffer)) - self.MoveCursor('left', -diff) - return - if diff: - self.MoveCursor('right', diff) - for _ in range(diff): - self.SendBackspace() - self.input_buffer_pos -= diff - self.input_buffer = self.input_buffer[0:self.input_buffer_pos] - - def SendBackspace(self): - """Backspace a character on the console.""" - os.write(self.master_pty, '\033[1D \033[1D') - - def ProcessOOBMQueue(self): - """Retrieve an item from the OOBM queue and process it.""" - item = self.oobm_queue.get() - self.logger.debug('OOBM cmd: %s', item) - cmd = item.split(' ') - - if cmd[0] == 'loglevel': - # An integer is required in order to set the log level. - if len(cmd) < 2: - self.logger.debug('Insufficient args') - self.PrintOOBMHelp() - return - try: - self.logger.debug('Log level change request.') - new_log_level = int(cmd[1]) - self.logger.logger.setLevel(new_log_level) - self.logger.info('Log level changed to %d.', new_log_level) - - # Forward the request to the interpreter as well. - self.cmd_pipe.send(item) - except ValueError: - # Ignoring the request if an integer was not provided. - self.PrintOOBMHelp() - - elif cmd[0] == 'timestamp': - mode = cmd[1].lower() - self.timestamp_enabled = mode == 'on' - self.logger.info('%sabling uart timestamps.', - 'En' if self.timestamp_enabled else 'Dis') - - elif cmd[0] == 'rawdebug': - mode = cmd[1].lower() - self.raw_debug = mode == 'on' - self.logger.info('%sabling per interrupt debug logs.', - 'En' if self.raw_debug else 'Dis') - - elif cmd[0] == 'interrogate' and len(cmd) >= 2: - enhanced = False - mode = cmd[1] - if len(cmd) >= 3 and cmd[2] == 'enhanced': - enhanced = True - - # Set the mode if correct. - if mode in INTERROGATION_MODES: - self.interrogation_mode = mode - self.logger.debug('Updated interrogation mode to %s.', mode) - - # Update the assumptions of the EC image. - self.enhanced_ec = enhanced - self.logger.debug('Enhanced EC image is now %r', self.enhanced_ec) - - # Send command to interpreter as well. - self.cmd_pipe.send('enhanced ' + str(self.enhanced_ec)) - else: - self.PrintOOBMHelp() - - else: - self.PrintOOBMHelp() - - def PrintOOBMHelp(self): - """Prints out the OOBM help.""" - # Print help syntax. - os.write(self.master_pty, '\r\n' + 'Known OOBM commands:\r\n') - os.write(self.master_pty, ' interrogate ' - '[enhanced]\r\n') - os.write(self.master_pty, ' loglevel \r\n') - - def CheckBufferForEnhancedImage(self, data): - """Adds data to a look buffer and checks to see for enhanced EC image. - - The EC's console task prints a string upon initialization which says that - "Console is enabled; type HELP for help.". The enhanced EC images print a - different string as a part of their init. This function searches through a - "look" buffer, scanning for the presence of either of those strings and - updating the enhanced_ec state accordingly. - - Args: - data: A string containing the data sent from the interpreter. - """ - self.look_buffer += data - - # Search the buffer for any of the EC image strings. - enhanced_match = re.search(ENHANCED_IMAGE_RE, self.look_buffer) - non_enhanced_match = re.search(NON_ENHANCED_IMAGE_RE, self.look_buffer) - - # Update the state if any matches were found. - if enhanced_match or non_enhanced_match: - if enhanced_match: - self.enhanced_ec = True - elif non_enhanced_match: - self.enhanced_ec = False - - # Inform the interpreter of the result. - self.cmd_pipe.send('enhanced ' + str(self.enhanced_ec)) - self.logger.debug('Enhanced EC image? %r', self.enhanced_ec) - - # Clear look buffer since a match was found. - self.look_buffer = '' - - # Move the sliding window. - self.look_buffer = self.look_buffer[-LOOK_BUFFER_SIZE:] - - -def IsPrintable(byte): - """Determines if a byte is printable. - - Args: - byte: An integer potentially representing a printable character. - - Returns: - A boolean indicating whether the byte is a printable character. - """ - return byte >= ord(' ') and byte <= ord('~') - -def StartLoop(console, command_active, shutdown_pipe=None): - """Starts the infinite loop of console processing. - - Args: - console: A Console object that has been properly initialzed. - command_active: ctypes data object or multiprocessing.Value indicating if - servod owns the console, or user owns the console. This prevents input - collisions. - shutdown_pipe: A file object for a pipe or equivalent that becomes readable - (not blocked) to indicate that the loop should exit. Can be None to never - exit the loop. - """ - try: - console.logger.debug('Console is being served on %s.', console.user_pty) - console.logger.debug('Console master is on %s.', console.master_pty) - console.logger.debug('Command interface is being served on %s.', - console.interface_pty) - console.logger.debug(console) - - # This checks for HUP to indicate if the user has connected to the pty. - ep = select.epoll() - ep.register(console.master_pty, select.EPOLLHUP) - - # This is used instead of "break" to avoid exiting the loop in the middle of - # an iteration. - continue_looping = True - - # Used for determining when to print host timestamps - tm_req = True - - while continue_looping: - # Check to see if pts is connected to anything - events = ep.poll(0) - master_connected = not events - - # Check to see if pipes or the console are ready for reading. - read_list = [console.interface_pty, - console.cmd_pipe, console.dbg_pipe] - if master_connected: - read_list.append(console.master_pty) - if shutdown_pipe is not None: - read_list.append(shutdown_pipe) - - # Check if any input is ready, or wait for .1 sec and re-poll if - # a user has connected to the pts. - select_output = select.select(read_list, [], [], .1) - if not select_output: - continue - ready_for_reading = select_output[0] - - for obj in ready_for_reading: - if obj is console.master_pty: - if not command_active.value: - # Convert to bytes so we can look for non-printable chars such as - # Ctrl+A, Ctrl+E, etc. - try: - line = bytearray(os.read(console.master_pty, CONSOLE_MAX_READ)) - console.logger.debug('Input from user: %s, locked:%s', - str(line).strip(), command_active.value) - for i in line: - try: - # Handle each character as it arrives. - console.HandleChar(i) - except EOFError: - console.logger.debug( - 'ec3po console received EOF from dbg_pipe in HandleChar()' - ' while reading console.master_pty') - continue_looping = False - break - except OSError: - console.logger.debug('Ptm read failed, probably user disconnect.') - - elif obj is console.interface_pty: - if command_active.value: - # Convert to bytes so we can look for non-printable chars such as - # Ctrl+A, Ctrl+E, etc. - line = bytearray(os.read(console.interface_pty, CONSOLE_MAX_READ)) - console.logger.debug('Input from interface: %s, locked:%s', - str(line).strip(), command_active.value) - for i in line: - try: - # Handle each character as it arrives. - console.HandleChar(i) - except EOFError: - console.logger.debug( - 'ec3po console received EOF from dbg_pipe in HandleChar()' - ' while reading console.interface_pty') - continue_looping = False - break - - elif obj is console.cmd_pipe: - try: - data = console.cmd_pipe.recv() - except EOFError: - console.logger.debug('ec3po console received EOF from cmd_pipe') - continue_looping = False - else: - # Write it to the user console. - if console.raw_debug: - console.logger.debug('|CMD|-%s->\'%s\'', - ('u' if master_connected else '') + - ('i' if command_active.value else ''), - data.strip()) - if master_connected: - os.write(console.master_pty, data) - if command_active.value: - os.write(console.interface_pty, data) - - elif obj is console.dbg_pipe: - try: - data = console.dbg_pipe.recv() - except EOFError: - console.logger.debug('ec3po console received EOF from dbg_pipe') - continue_looping = False - else: - if console.interrogation_mode == 'auto': - # Search look buffer for enhanced EC image string. - console.CheckBufferForEnhancedImage(data) - # Write it to the user console. - if len(data) > 1 and console.raw_debug: - console.logger.debug('|DBG|-%s->\'%s\'', - ('u' if master_connected else '') + - ('i' if command_active.value else ''), - data.strip()) - console.LogConsoleOutput(data) - if master_connected: - end = len(data) - 1 - if console.timestamp_enabled: - # A timestamp is required at the beginning of this line - if tm_req is True: - now = datetime.now() - tm = now.strftime(HOST_STRFTIME) - os.write(console.master_pty, tm) - tm_req = False - - # Insert timestamps into the middle where appropriate - # except if the last character is a newline - nls_found = data.count('\n', 0, end) - now = datetime.now() - tm = now.strftime('\n' + HOST_STRFTIME) - data_tm = data.replace('\n', tm, nls_found) - else: - data_tm = data - - # timestamp required on next input - if data[end] == '\n': - tm_req = True - os.write(console.master_pty, data_tm) - if command_active.value: - os.write(console.interface_pty, data) - - elif obj is shutdown_pipe: - console.logger.debug( - 'ec3po console received shutdown pipe unblocked notification') - continue_looping = False - - while not console.oobm_queue.empty(): - console.logger.debug('OOBM queue ready for reading.') - console.ProcessOOBMQueue() - - except KeyboardInterrupt: - pass - - # TODO(crbug.com/894870): Stop suppressing all exceptions. - except: - traceback.print_exc() - - finally: - ep.unregister(console.master_pty) - console.dbg_pipe.close() - console.cmd_pipe.close() - os.close(console.master_pty) - os.close(console.interface_pty) - if shutdown_pipe is not None: - shutdown_pipe.close() - console.logger.debug('Exit ec3po console loop for %s', console.user_pty) - - -def main(argv): - """Kicks off the EC-3PO interactive console interface and interpreter. - - We create some pipes to communicate with an interpreter, instantiate an - interpreter, create a PTY pair, and begin serving the console interface. - - Args: - argv: A list of strings containing the arguments this module was called - with. - """ - # Set up argument parser. - parser = argparse.ArgumentParser(description=('Start interactive EC console ' - 'and interpreter.')) - parser.add_argument('ec_uart_pty', - help=('The full PTY name that the EC UART' - ' is present on. eg: /dev/pts/12')) - parser.add_argument('--log-level', - default='info', - help='info, debug, warning, error, or critical') - - # Parse arguments. - opts = parser.parse_args(argv) - - # Set logging level. - opts.log_level = opts.log_level.lower() - if opts.log_level == 'info': - log_level = logging.INFO - elif opts.log_level == 'debug': - log_level = logging.DEBUG - elif opts.log_level == 'warning': - log_level = logging.WARNING - elif opts.log_level == 'error': - log_level = logging.ERROR - elif opts.log_level == 'critical': - log_level = logging.CRITICAL - else: - parser.error('Invalid log level. (info, debug, warning, error, critical)') - - # Start logging with a timestamp, module, and log level shown in each log - # entry. - logging.basicConfig(level=log_level, format=('%(asctime)s - %(module)s -' - ' %(levelname)s - %(message)s')) - - # Create some pipes to communicate between the interpreter and the console. - # The command pipe is bidirectional. - cmd_pipe_interactive, cmd_pipe_interp = threadproc_shim.Pipe() - # The debug pipe is unidirectional from interpreter to console only. - dbg_pipe_interactive, dbg_pipe_interp = threadproc_shim.Pipe(duplex=False) - - # Create an interpreter instance. - itpr = interpreter.Interpreter(opts.ec_uart_pty, cmd_pipe_interp, - dbg_pipe_interp, log_level) - - # Spawn an interpreter process. - itpr_process = threadproc_shim.ThreadOrProcess( - target=interpreter.StartLoop, args=(itpr,)) - # Make sure to kill the interpreter when we terminate. - itpr_process.daemon = True - # Start the interpreter. - itpr_process.start() - - # Open a new pseudo-terminal pair - (master_pty, user_pty) = pty.openpty() - # Set the permissions to 660. - os.chmod(os.ttyname(user_pty), (stat.S_IRGRP | stat.S_IWGRP | - stat.S_IRUSR | stat.S_IWUSR)) - # Create a console. - console = Console(master_pty, os.ttyname(user_pty), cmd_pipe_interactive, - dbg_pipe_interactive) - # Start serving the console. - v = threadproc_shim.Value(ctypes.c_bool, False) - StartLoop(console, v) - - -if __name__ == '__main__': - main(sys.argv[1:]) diff --git a/util/ec3po/console_unittest.py b/util/ec3po/console_unittest.py deleted file mode 100755 index 3c194d8419..0000000000 --- a/util/ec3po/console_unittest.py +++ /dev/null @@ -1,1626 +0,0 @@ -#!/usr/bin/env python2 -# 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. - -"""Unit tests for the EC-3PO Console interface.""" - -from __future__ import print_function - -import binascii -# pylint: disable=cros-logging-import -import logging -import mock -import tempfile -import unittest - -import console -import interpreter -import threadproc_shim - -ESC_STRING = chr(console.ControlKey.ESC) - -class Keys(object): - """A class that contains the escape sequences for special keys.""" - LEFT_ARROW = [console.ControlKey.ESC, ord('['), ord('D')] - RIGHT_ARROW = [console.ControlKey.ESC, ord('['), ord('C')] - UP_ARROW = [console.ControlKey.ESC, ord('['), ord('A')] - DOWN_ARROW = [console.ControlKey.ESC, ord('['), ord('B')] - HOME = [console.ControlKey.ESC, ord('['), ord('1'), ord('~')] - END = [console.ControlKey.ESC, ord('['), ord('8'), ord('~')] - DEL = [console.ControlKey.ESC, ord('['), ord('3'), ord('~')] - -class OutputStream(object): - """A class that has methods which return common console output.""" - - @staticmethod - def MoveCursorLeft(count): - """Produces what would be printed to the console if the cursor moved left. - - Args: - count: An integer representing how many columns to move left. - - Returns: - string: A string which contains what would be printed to the console if - the cursor moved left. - """ - string = ESC_STRING - string += '[' + str(count) + 'D' - return string - - @staticmethod - def MoveCursorRight(count): - """Produces what would be printed to the console if the cursor moved right. - - Args: - count: An integer representing how many columns to move right. - - Returns: - string: A string which contains what would be printed to the console if - the cursor moved right. - """ - string = ESC_STRING - string += '[' + str(count) + 'C' - return string - -BACKSPACE_STRING = '' -# Move cursor left 1 column. -BACKSPACE_STRING += OutputStream.MoveCursorLeft(1) -# Write a space. -BACKSPACE_STRING += ' ' -# Move cursor left 1 column. -BACKSPACE_STRING += OutputStream.MoveCursorLeft(1) - -def StringToByteList(string): - """Converts a string to list of bytes. - - Args: - string: A literal string to turn into a list of bytes. - - Returns: - A list of integers representing the byte value of each character in the - string. - """ - return [ord(c) for c in string] - -def BadConsoleOutput(expected, got): - """Format the console output into readable text. - - Args: - expected: A list of bytes representing the expected output console - stream. - got: A list of byte representing the actual output console stream. - - Returns: - string: A formatted string which shows the expected console output stream - and the actual console output stream. - """ - esc_state = 0 - string = 'Incorrect console output stream.\n' - string += 'exp: |' - count = 0 - for char in expected: - if esc_state != 0: - if esc_state == console.EscState.ESC_START: - if char == '[': - esc_state = console.EscState.ESC_BRACKET - elif esc_state == console.EscState.ESC_BRACKET: - if char == 'D': - string += '[cursor left ' + str(count) + ' cols]' - esc_state = 0 - elif char == 'C': - string += '[cursor right ' + str(count) + ' cols]' - esc_state = 0 - else: - count = int(char) - # Print if it's printable. - elif console.IsPrintable(ord(char)): - string += char - else: - # It might be a sequence of some type. - if ord(char) == console.ControlKey.ESC: - # Need to look at the following sequence. - esc_state = console.EscState.ESC_START - else: - string += '{' + binascii.hexlify(char) + '}' - - string += '|\n\ngot: |' - for char in got: - if esc_state != 0: - if esc_state == console.EscState.ESC_START: - if char == '[': - esc_state = console.EscState.ESC_BRACKET - elif esc_state == console.EscState.ESC_BRACKET: - if char == 'D': - string += '[cursor left ' + str(count) + ' cols]' - esc_state = 0 - elif char == 'C': - string += '[cursor right ' + str(count) + ' cols]' - esc_state = 0 - else: - count = int(char) - # Print if it's printable. - elif console.IsPrintable(ord(char)): - string += char - else: - # It might be a sequence of some type. - if ord(char) == console.ControlKey.ESC: - # Need to look at the following sequence. - esc_state = console.EscState.ESC_START - else: - string += '{' + binascii.hexlify(char) + '}' - string += '|\n\n' - - # TODO(aaboagye): It would be nice to replace all those move left 1, ' ', - # move left 1, with backspace. - - return string - -def CheckConsoleOutput(test_case, exp_console_out): - """Verify what was sent out the console matches what we expect. - - Args: - test_case: A unittest.TestCase object representing the current unit test. - exp_console_out: A string representing the console output stream. - """ - # Read what was sent out the console. - test_case.tempfile.seek(0) - console_out = test_case.tempfile.read() - - test_case.assertEqual(exp_console_out, - console_out, - (BadConsoleOutput(exp_console_out, console_out) - + str(test_case.console))) - -def CheckInputBuffer(test_case, exp_input_buffer): - """Verify that the input buffer contains what we expect. - - Args: - test_case: A unittest.TestCase object representing the current unit test. - exp_input_buffer: A string containing the contents of the current input - buffer. - """ - test_case.assertEqual(exp_input_buffer, test_case.console.input_buffer, - ('input buffer does not match expected.\n' - 'expected: |' + exp_input_buffer + '|\n' - 'got: |' + test_case.console.input_buffer + - '|\n' + str(test_case.console))) - -def CheckInputBufferPosition(test_case, exp_pos): - """Verify the input buffer position. - - Args: - test_case: A unittest.TestCase object representing the current unit test. - exp_pos: An integer representing the expected input buffer position. - """ - test_case.assertEqual(exp_pos, test_case.console.input_buffer_pos, - 'input buffer position is incorrect.\ngot: ' + - str(test_case.console.input_buffer_pos) + '\nexp: ' + - str(exp_pos) + '\n' + str(test_case.console)) - -def CheckHistoryBuffer(test_case, exp_history): - """Verify that the items in the history buffer are what we expect. - - Args: - test_case: A unittest.TestCase object representing the current unit test. - exp_history: A list of strings representing the expected contents of the - history buffer. - """ - # First, check to see if the length is what we expect. - test_case.assertEqual(len(exp_history), len(test_case.console.history), - ('The number of items in the history is unexpected.\n' - 'exp: ' + str(len(exp_history)) + '\n' - 'got: ' + str(len(test_case.console.history)) + '\n' - 'internal state:\n' + str(test_case.console))) - - # Next, check the actual contents of the history buffer. - for i in range(len(exp_history)): - test_case.assertEqual(exp_history[i], test_case.console.history[i], - ('history buffer contents are incorrect.\n' - 'exp: ' + exp_history[i] + '\n' - 'got: ' + test_case.console.history[i] + '\n' - 'internal state:\n' + str(test_case.console))) - - -class TestConsoleEditingMethods(unittest.TestCase): - """Test case to verify all console editing methods.""" - - def setUp(self): - """Setup the test harness.""" - # Setup logging with a timestamp, the module, and the log level. - logging.basicConfig(level=logging.DEBUG, - format=('%(asctime)s - %(module)s -' - ' %(levelname)s - %(message)s')) - - # Create a temp file and set both the master and slave PTYs to the file to - # create a loopback. - self.tempfile = tempfile.TemporaryFile() - - # Create some dummy pipes. These won't be used since we'll mock out sends - # to the interpreter. - dummy_pipe_end_0, dummy_pipe_end_1 = threadproc_shim.Pipe() - self.console = console.Console(self.tempfile.fileno(), self.tempfile, - tempfile.TemporaryFile(), - dummy_pipe_end_0, dummy_pipe_end_1, "EC") - - # Console editing methods are only valid for enhanced EC images, therefore - # we have to assume that the "EC" we're talking to is enhanced. By default, - # the console believes that the EC it's communicating with is NOT enhanced - # which is why we have to override it here. - self.console.enhanced_ec = True - self.console.CheckForEnhancedECImage = mock.MagicMock(return_value=True) - - def test_EnteringChars(self): - """Verify that characters are echoed onto the console.""" - test_str = 'abc' - input_stream = StringToByteList(test_str) - - # Send the characters in. - for byte in input_stream: - self.console.HandleChar(byte) - - # Check the input position. - exp_pos = len(test_str) - CheckInputBufferPosition(self, exp_pos) - - # Verify that the input buffer is correct. - expected_buffer = test_str - CheckInputBuffer(self, expected_buffer) - - # Check console output - exp_console_out = test_str - CheckConsoleOutput(self, exp_console_out) - - def test_EnteringDeletingMoreCharsThanEntered(self): - """Verify that we can press backspace more than we have entered chars.""" - test_str = 'spamspam' - input_stream = StringToByteList(test_str) - - # Send the characters in. - for byte in input_stream: - self.console.HandleChar(byte) - - # Now backspace 1 more than what we sent. - input_stream = [] - for _ in range(len(test_str) + 1): - input_stream.append(console.ControlKey.BACKSPACE) - - # Send that sequence out. - for byte in input_stream: - self.console.HandleChar(byte) - - # First, verify that input buffer position is 0. - CheckInputBufferPosition(self, 0) - - # Next, examine the output stream for the correct sequence. - exp_console_out = test_str - for _ in range(len(test_str)): - exp_console_out += BACKSPACE_STRING - - # Now, verify that we got what we expected. - CheckConsoleOutput(self, exp_console_out) - - def test_EnteringMoreThanCharLimit(self): - """Verify that we drop characters when the line is too long.""" - test_str = self.console.line_limit * 'o' # All allowed. - test_str += 5 * 'x' # All should be dropped. - input_stream = StringToByteList(test_str) - - # Send the characters in. - for byte in input_stream: - self.console.HandleChar(byte) - - # First, we expect that input buffer position should be equal to the line - # limit. - exp_pos = self.console.line_limit - CheckInputBufferPosition(self, exp_pos) - - # The input buffer should only hold until the line limit. - exp_buffer = test_str[0:self.console.line_limit] - CheckInputBuffer(self, exp_buffer) - - # Lastly, check that the extra characters are not printed. - exp_console_out = exp_buffer - CheckConsoleOutput(self, exp_console_out) - - def test_ValidKeysOnLongLine(self): - """Verify that we can still press valid keys if the line is too long.""" - # Fill the line. - test_str = self.console.line_limit * 'o' - exp_console_out = test_str - # Try to fill it even more; these should all be dropped. - test_str += 5 * 'x' - input_stream = StringToByteList(test_str) - - # We should be able to press the following keys: - # - Backspace - # - Arrow Keys/CTRL+B/CTRL+F/CTRL+P/CTRL+N - # - Delete - # - Home/CTRL+A - # - End/CTRL+E - # - Carriage Return - - # Backspace 1 character - input_stream.append(console.ControlKey.BACKSPACE) - exp_console_out += BACKSPACE_STRING - # Refill the line. - input_stream.extend(StringToByteList('o')) - exp_console_out += 'o' - - # Left arrow key. - input_stream.extend(Keys.LEFT_ARROW) - exp_console_out += OutputStream.MoveCursorLeft(1) - - # Right arrow key. - input_stream.extend(Keys.RIGHT_ARROW) - exp_console_out += OutputStream.MoveCursorRight(1) - - # CTRL+B - input_stream.append(console.ControlKey.CTRL_B) - exp_console_out += OutputStream.MoveCursorLeft(1) - - # CTRL+F - input_stream.append(console.ControlKey.CTRL_F) - exp_console_out += OutputStream.MoveCursorRight(1) - - # Let's press enter now so we can test up and down. - input_stream.append(console.ControlKey.CARRIAGE_RETURN) - exp_console_out += '\r\n' + self.console.prompt - - # Up arrow key. - input_stream.extend(Keys.UP_ARROW) - exp_console_out += test_str[:self.console.line_limit] - - # Down arrow key. - input_stream.extend(Keys.DOWN_ARROW) - # Since the line was blank, we have to backspace the entire line. - exp_console_out += self.console.line_limit * BACKSPACE_STRING - - # CTRL+P - input_stream.append(console.ControlKey.CTRL_P) - exp_console_out += test_str[:self.console.line_limit] - - # CTRL+N - input_stream.append(console.ControlKey.CTRL_N) - # Since the line was blank, we have to backspace the entire line. - exp_console_out += self.console.line_limit * BACKSPACE_STRING - - # Press the Up arrow key to reprint the long line. - input_stream.extend(Keys.UP_ARROW) - exp_console_out += test_str[:self.console.line_limit] - - # Press the Home key to jump to the beginning of the line. - input_stream.extend(Keys.HOME) - exp_console_out += OutputStream.MoveCursorLeft(self.console.line_limit) - - # Press the End key to jump to the end of the line. - input_stream.extend(Keys.END) - exp_console_out += OutputStream.MoveCursorRight(self.console.line_limit) - - # Press CTRL+A to jump to the beginning of the line. - input_stream.append(console.ControlKey.CTRL_A) - exp_console_out += OutputStream.MoveCursorLeft(self.console.line_limit) - - # Press CTRL+E to jump to the end of the line. - input_stream.extend(Keys.END) - exp_console_out += OutputStream.MoveCursorRight(self.console.line_limit) - - # Move left one column so we can delete a character. - input_stream.extend(Keys.LEFT_ARROW) - exp_console_out += OutputStream.MoveCursorLeft(1) - - # Press the delete key. - input_stream.extend(Keys.DEL) - # This should look like a space, and then move cursor left 1 column since - # we're at the end of line. - exp_console_out += ' ' + OutputStream.MoveCursorLeft(1) - - # Send the sequence out. - for byte in input_stream: - self.console.HandleChar(byte) - - # Verify everything happened correctly. - CheckConsoleOutput(self, exp_console_out) - - def test_BackspaceOnEmptyLine(self): - """Verify that we can backspace on an empty line with no bad effects.""" - # Send a single backspace. - test_str = [console.ControlKey.BACKSPACE] - - # Send the characters in. - for byte in test_str: - self.console.HandleChar(byte) - - # Check the input position. - exp_pos = 0 - CheckInputBufferPosition(self, exp_pos) - - # Check that buffer is empty. - exp_input_buffer = '' - CheckInputBuffer(self, exp_input_buffer) - - # Check that the console output is empty. - exp_console_out = '' - CheckConsoleOutput(self, exp_console_out) - - def test_BackspaceWithinLine(self): - """Verify that we shift the chars over when backspacing within a line.""" - # Misspell 'help' - test_str = 'heelp' - input_stream = StringToByteList(test_str) - # Use the arrow key to go back to fix it. - # Move cursor left 1 column. - input_stream.extend(2*Keys.LEFT_ARROW) - # Backspace once to remove the extra 'e'. - input_stream.append(console.ControlKey.BACKSPACE) - - # Send the sequence out. - for byte in input_stream: - self.console.HandleChar(byte) - - # Verify the input buffer - exp_input_buffer = 'help' - CheckInputBuffer(self, exp_input_buffer) - - # Verify the input buffer position. It should be at 2 (cursor over the 'l') - CheckInputBufferPosition(self, 2) - - # We expect the console output to be the test string, with two moves to the - # left, another move left, and then the rest of the line followed by a - # space. - exp_console_out = test_str - exp_console_out += 2 * OutputStream.MoveCursorLeft(1) - - # Move cursor left 1 column. - exp_console_out += OutputStream.MoveCursorLeft(1) - # Rest of the line and a space. (test_str in this case) - exp_console_out += 'lp ' - # Reset the cursor 2 + 1 to the left. - exp_console_out += OutputStream.MoveCursorLeft(3) - - # Verify console output. - CheckConsoleOutput(self, exp_console_out) - - def test_JumpToBeginningOfLineViaCtrlA(self): - """Verify that we can jump to the beginning of a line with Ctrl+A.""" - # Enter some chars and press CTRL+A - test_str = 'abc' - input_stream = StringToByteList(test_str) + [console.ControlKey.CTRL_A] - - # Send the characters in. - for byte in input_stream: - self.console.HandleChar(byte) - - # We expect to see our test string followed by a move cursor left. - exp_console_out = test_str - exp_console_out += OutputStream.MoveCursorLeft(len(test_str)) - - # Check to see what whas printed on the console. - CheckConsoleOutput(self, exp_console_out) - - # Check that the input buffer position is now 0. - CheckInputBufferPosition(self, 0) - - # Check input buffer still contains our test string. - CheckInputBuffer(self, test_str) - - def test_JumpToBeginningOfLineViaHomeKey(self): - """Jump to beginning of line via HOME key.""" - test_str = 'version' - input_stream = StringToByteList(test_str) - input_stream.extend(Keys.HOME) - - # Send out the stream. - for byte in input_stream: - self.console.HandleChar(byte) - - # First, verify that input buffer position is now 0. - CheckInputBufferPosition(self, 0) - - # Next, verify that the input buffer did not change. - CheckInputBuffer(self, test_str) - - # Lastly, check that the cursor moved correctly. - exp_console_out = test_str - exp_console_out += OutputStream.MoveCursorLeft(len(test_str)) - CheckConsoleOutput(self, exp_console_out) - - def test_JumpToEndOfLineViaEndKey(self): - """Jump to the end of the line using the END key.""" - test_str = 'version' - input_stream = StringToByteList(test_str) - input_stream += [console.ControlKey.CTRL_A] - # Now, jump to the end of the line. - input_stream.extend(Keys.END) - - # Send out the stream. - for byte in input_stream: - self.console.HandleChar(byte) - - # Verify that the input buffer position is correct. This should be at the - # end of the test string. - CheckInputBufferPosition(self, len(test_str)) - - # The expected output should be the test string, followed by a jump to the - # beginning of the line, and lastly a jump to the end of the line. - exp_console_out = test_str - exp_console_out += OutputStream.MoveCursorLeft(len(test_str)) - # Now the jump back to the end of the line. - exp_console_out += OutputStream.MoveCursorRight(len(test_str)) - - # Verify console output stream. - CheckConsoleOutput(self, exp_console_out) - - def test_JumpToEndOfLineViaCtrlE(self): - """Enter some chars and then try to jump to the end. (Should be a no-op)""" - test_str = 'sysinfo' - input_stream = StringToByteList(test_str) - input_stream.append(console.ControlKey.CTRL_E) - - # Send out the stream - for byte in input_stream: - self.console.HandleChar(byte) - - # Verify that the input buffer position isn't any further than we expect. - # At this point, the position should be at the end of the test string. - CheckInputBufferPosition(self, len(test_str)) - - # Now, let's try to jump to the beginning and then jump back to the end. - input_stream = [console.ControlKey.CTRL_A, console.ControlKey.CTRL_E] - - # Send the sequence out. - for byte in input_stream: - self.console.HandleChar(byte) - - # Perform the same verification. - CheckInputBufferPosition(self, len(test_str)) - - # Lastly try to jump again, beyond the end. - input_stream = [console.ControlKey.CTRL_E] - - # Send the sequence out. - for byte in input_stream: - self.console.HandleChar(byte) - - # Perform the same verification. - CheckInputBufferPosition(self, len(test_str)) - - # We expect to see the test string, a jump to the beginning of the line, and - # one jump to the end of the line. - exp_console_out = test_str - # Jump to beginning. - exp_console_out += OutputStream.MoveCursorLeft(len(test_str)) - # Jump back to end. - exp_console_out += OutputStream.MoveCursorRight(len(test_str)) - - # Verify the console output. - CheckConsoleOutput(self, exp_console_out) - - def test_MoveLeftWithArrowKey(self): - """Move cursor left one column with arrow key.""" - test_str = 'tastyspam' - input_stream = StringToByteList(test_str) - input_stream.extend(Keys.LEFT_ARROW) - - # Send the sequence out. - for byte in input_stream: - self.console.HandleChar(byte) - - # Verify that the input buffer position is 1 less than the length. - CheckInputBufferPosition(self, len(test_str) - 1) - - # Also, verify that the input buffer is not modified. - CheckInputBuffer(self, test_str) - - # We expect the test string, followed by a one column move left. - exp_console_out = test_str + OutputStream.MoveCursorLeft(1) - - # Verify console output. - CheckConsoleOutput(self, exp_console_out) - - def test_MoveLeftWithCtrlB(self): - """Move cursor back one column with Ctrl+B.""" - test_str = 'tastyspam' - input_stream = StringToByteList(test_str) - input_stream.append(console.ControlKey.CTRL_B) - - # Send the sequence out. - for byte in input_stream: - self.console.HandleChar(byte) - - # Verify that the input buffer position is 1 less than the length. - CheckInputBufferPosition(self, len(test_str) - 1) - - # Also, verify that the input buffer is not modified. - CheckInputBuffer(self, test_str) - - # We expect the test string, followed by a one column move left. - exp_console_out = test_str + OutputStream.MoveCursorLeft(1) - - # Verify console output. - CheckConsoleOutput(self, exp_console_out) - - def test_MoveRightWithArrowKey(self): - """Move cursor one column to the right with the arrow key.""" - test_str = 'version' - input_stream = StringToByteList(test_str) - # Jump to beginning of line. - input_stream.append(console.ControlKey.CTRL_A) - # Press right arrow key. - input_stream.extend(Keys.RIGHT_ARROW) - - # Send the sequence out. - for byte in input_stream: - self.console.HandleChar(byte) - - # Verify that the input buffer position is 1. - CheckInputBufferPosition(self, 1) - - # Also, verify that the input buffer is not modified. - CheckInputBuffer(self, test_str) - - # We expect the test string, followed by a jump to the beginning of the - # line, and finally a move right 1. - exp_console_out = test_str + OutputStream.MoveCursorLeft(len((test_str))) - - # A move right 1 column. - exp_console_out += OutputStream.MoveCursorRight(1) - - # Verify console output. - CheckConsoleOutput(self, exp_console_out) - - def test_MoveRightWithCtrlF(self): - """Move cursor forward one column with Ctrl+F.""" - test_str = 'panicinfo' - input_stream = StringToByteList(test_str) - input_stream.append(console.ControlKey.CTRL_A) - # Now, move right one column. - input_stream.append(console.ControlKey.CTRL_F) - - # Send the sequence out. - for byte in input_stream: - self.console.HandleChar(byte) - - # Verify that the input buffer position is 1. - CheckInputBufferPosition(self, 1) - - # Also, verify that the input buffer is not modified. - CheckInputBuffer(self, test_str) - - # We expect the test string, followed by a jump to the beginning of the - # line, and finally a move right 1. - exp_console_out = test_str + OutputStream.MoveCursorLeft(len((test_str))) - - # A move right 1 column. - exp_console_out += OutputStream.MoveCursorRight(1) - - # Verify console output. - CheckConsoleOutput(self, exp_console_out) - - def test_ImpossibleMoveLeftWithArrowKey(self): - """Verify that we can't move left at the beginning of the line.""" - # We shouldn't be able to move left if we're at the beginning of the line. - input_stream = Keys.LEFT_ARROW - - # Send the sequence out. - for byte in input_stream: - self.console.HandleChar(byte) - - # Nothing should have been output. - exp_console_output = '' - CheckConsoleOutput(self, exp_console_output) - - # The input buffer position should still be 0. - CheckInputBufferPosition(self, 0) - - # The input buffer itself should be empty. - CheckInputBuffer(self, '') - - def test_ImpossibleMoveRightWithArrowKey(self): - """Verify that we can't move right at the end of the line.""" - # We shouldn't be able to move right if we're at the end of the line. - input_stream = Keys.RIGHT_ARROW - - # Send the sequence out. - for byte in input_stream: - self.console.HandleChar(byte) - - # Nothing should have been output. - exp_console_output = '' - CheckConsoleOutput(self, exp_console_output) - - # The input buffer position should still be 0. - CheckInputBufferPosition(self, 0) - - # The input buffer itself should be empty. - CheckInputBuffer(self, '') - - def test_KillEntireLine(self): - """Verify that we can kill an entire line with Ctrl+K.""" - test_str = 'accelinfo on' - input_stream = StringToByteList(test_str) - # Jump to beginning of line and then kill it with Ctrl+K. - input_stream.extend([console.ControlKey.CTRL_A, console.ControlKey.CTRL_K]) - - # Send the sequence out. - for byte in input_stream: - self.console.HandleChar(byte) - - # First, we expect that the input buffer is empty. - CheckInputBuffer(self, '') - - # The buffer position should be 0. - CheckInputBufferPosition(self, 0) - - # What we expect to see on the console stream should be the following. The - # test string, a jump to the beginning of the line, then jump back to the - # end of the line and replace the line with spaces. - exp_console_out = test_str - # Jump to beginning of line. - exp_console_out += OutputStream.MoveCursorLeft(len(test_str)) - # Jump to end of line. - exp_console_out += OutputStream.MoveCursorRight(len(test_str)) - # Replace line with spaces, which looks like backspaces. - for _ in range(len(test_str)): - exp_console_out += BACKSPACE_STRING - - # Verify the console output. - CheckConsoleOutput(self, exp_console_out) - - def test_KillPartialLine(self): - """Verify that we can kill a portion of a line.""" - test_str = 'accelread 0 1' - input_stream = StringToByteList(test_str) - len_to_kill = 5 - for _ in range(len_to_kill): - # Move cursor left - input_stream.extend(Keys.LEFT_ARROW) - # Now kill - input_stream.append(console.ControlKey.CTRL_K) - - # Send the sequence out. - for byte in input_stream: - self.console.HandleChar(byte) - - # First, check that the input buffer was truncated. - exp_input_buffer = test_str[:-len_to_kill] - CheckInputBuffer(self, exp_input_buffer) - - # Verify the input buffer position. - CheckInputBufferPosition(self, len(test_str) - len_to_kill) - - # The console output stream that we expect is the test string followed by a - # move left of len_to_kill, then a jump to the end of the line and backspace - # of len_to_kill. - exp_console_out = test_str - for _ in range(len_to_kill): - # Move left 1 column. - exp_console_out += OutputStream.MoveCursorLeft(1) - # Then jump to the end of the line - exp_console_out += OutputStream.MoveCursorRight(len_to_kill) - # Backspace of len_to_kill - for _ in range(len_to_kill): - exp_console_out += BACKSPACE_STRING - - # Verify console output. - CheckConsoleOutput(self, exp_console_out) - - def test_InsertingCharacters(self): - """Verify that we can insert charcters within the line.""" - test_str = 'accel 0 1' # Here we forgot the 'read' part in 'accelread' - input_stream = StringToByteList(test_str) - # We need to move over to the 'l' and add read. - insertion_point = test_str.find('l') + 1 - for i in range(len(test_str) - insertion_point): - # Move cursor left. - input_stream.extend(Keys.LEFT_ARROW) - # Now, add in 'read' - added_str = 'read' - input_stream.extend(StringToByteList(added_str)) - - # Send the sequence out. - for byte in input_stream: - self.console.HandleChar(byte) - - # First, verify that the input buffer is correct. - exp_input_buffer = test_str[:insertion_point] + added_str - exp_input_buffer += test_str[insertion_point:] - CheckInputBuffer(self, exp_input_buffer) - - # Verify that the input buffer position is correct. - exp_input_buffer_pos = insertion_point + len(added_str) - CheckInputBufferPosition(self, exp_input_buffer_pos) - - # The console output stream that we expect is the test string, followed by - # move cursor left until the 'l' was found, the added test string while - # shifting characters around. - exp_console_out = test_str - for i in range(len(test_str) - insertion_point): - # Move cursor left. - exp_console_out += OutputStream.MoveCursorLeft(1) - - # Now for each character, write the rest of the line will be shifted to the - # right one column. - for i in range(len(added_str)): - # Printed character. - exp_console_out += added_str[i] - # The rest of the line - exp_console_out += test_str[insertion_point:] - # Reset the cursor back left - reset_dist = len(test_str[insertion_point:]) - exp_console_out += OutputStream.MoveCursorLeft(reset_dist) - - # Verify the console output. - CheckConsoleOutput(self, exp_console_out) - - def test_StoreCommandHistory(self): - """Verify that entered commands are stored in the history.""" - test_commands = [] - test_commands.append('help') - test_commands.append('version') - test_commands.append('accelread 0 1') - input_stream = [] - for c in test_commands: - input_stream.extend(StringToByteList(c)) - input_stream.append(console.ControlKey.CARRIAGE_RETURN) - - # Send the sequence out. - for byte in input_stream: - self.console.HandleChar(byte) - - # We expect to have the test commands in the history buffer. - exp_history_buf = test_commands - CheckHistoryBuffer(self, exp_history_buf) - - def test_CycleUpThruCommandHistory(self): - """Verify that the UP arrow key will print itmes in the history buffer.""" - # Enter some commands. - test_commands = ['version', 'accelrange 0', 'battery', 'gettime'] - input_stream = [] - for command in test_commands: - input_stream.extend(StringToByteList(command)) - input_stream.append(console.ControlKey.CARRIAGE_RETURN) - - # Now, hit the UP arrow key to print the previous entries. - for i in range(len(test_commands)): - input_stream.extend(Keys.UP_ARROW) - - # Send the sequence out. - for byte in input_stream: - self.console.HandleChar(byte) - - # The expected output should be test commands with prompts printed in - # between, followed by line kills with the previous test commands printed. - exp_console_out = '' - for i in range(len(test_commands)): - exp_console_out += test_commands[i] + '\r\n' + self.console.prompt - - # When we press up, the line should be cleared and print the previous buffer - # entry. - for i in range(len(test_commands)-1, 0, -1): - exp_console_out += test_commands[i] - # Backspace to the beginning. - for i in range(len(test_commands[i])): - exp_console_out += BACKSPACE_STRING - - # The last command should just be printed out with no backspacing. - exp_console_out += test_commands[0] - - # Now, verify. - CheckConsoleOutput(self, exp_console_out) - - def test_UpArrowOnEmptyHistory(self): - """Ensure nothing happens if the history is empty.""" - # Press the up arrow key twice. - input_stream = 2 * Keys.UP_ARROW - - # Send the sequence out. - for byte in input_stream: - self.console.HandleChar(byte) - - # We expect nothing to have happened. - exp_console_out = '' - exp_input_buffer = '' - exp_input_buffer_pos = 0 - exp_history_buf = [] - - # Verify. - CheckConsoleOutput(self, exp_console_out) - CheckInputBufferPosition(self, exp_input_buffer_pos) - CheckInputBuffer(self, exp_input_buffer) - CheckHistoryBuffer(self, exp_history_buf) - - def test_UpArrowDoesNotGoOutOfBounds(self): - """Verify that pressing the up arrow many times won't go out of bounds.""" - # Enter one command. - test_str = 'help version' - input_stream = StringToByteList(test_str) - input_stream.append(console.ControlKey.CARRIAGE_RETURN) - # Then press the up arrow key twice. - input_stream.extend(2 * Keys.UP_ARROW) - - # Send the sequence out. - for byte in input_stream: - self.console.HandleChar(byte) - - # Verify that the history buffer is correct. - exp_history_buf = [test_str] - CheckHistoryBuffer(self, exp_history_buf) - - # We expect that the console output should only contain our entered command, - # a new prompt, and then our command aggain. - exp_console_out = test_str + '\r\n' + self.console.prompt - # Pressing up should reprint the command we entered. - exp_console_out += test_str - - # Verify. - CheckConsoleOutput(self, exp_console_out) - - def test_CycleDownThruCommandHistory(self): - """Verify that we can select entries by hitting the down arrow.""" - # Enter at least 4 commands. - test_commands = ['version', 'accelrange 0', 'battery', 'gettime'] - input_stream = [] - for command in test_commands: - input_stream.extend(StringToByteList(command)) - input_stream.append(console.ControlKey.CARRIAGE_RETURN) - - # Now, hit the UP arrow key twice to print the previous two entries. - for i in range(2): - input_stream.extend(Keys.UP_ARROW) - - # Now, hit the DOWN arrow key twice to print the newer entries. - input_stream.extend(2*Keys.DOWN_ARROW) - - # Send the sequence out. - for byte in input_stream: - self.console.HandleChar(byte) - - # The expected output should be commands that we entered, followed by - # prompts, then followed by our last two commands in reverse. Then, we - # should see the last entry in the list, followed by the saved partial cmd - # of a blank line. - exp_console_out = '' - for i in range(len(test_commands)): - exp_console_out += test_commands[i] + '\r\n' + self.console.prompt - - # When we press up, the line should be cleared and print the previous buffer - # entry. - for i in range(len(test_commands)-1, 1, -1): - exp_console_out += test_commands[i] - # Backspace to the beginning. - for i in range(len(test_commands[i])): - exp_console_out += BACKSPACE_STRING - - # When we press down, it should have cleared the last command (which we - # covered with the previous for loop), and then prints the next command. - exp_console_out += test_commands[3] - for i in range(len(test_commands[3])): - exp_console_out += BACKSPACE_STRING - - # Verify console output. - CheckConsoleOutput(self, exp_console_out) - - # Verify input buffer. - exp_input_buffer = '' # Empty because our partial command was empty. - exp_input_buffer_pos = len(exp_input_buffer) - CheckInputBuffer(self, exp_input_buffer) - CheckInputBufferPosition(self, exp_input_buffer_pos) - - def test_SavingPartialCommandWhenNavigatingHistory(self): - """Verify that partial commands are saved when navigating history.""" - # Enter a command. - test_str = 'accelinfo' - input_stream = StringToByteList(test_str) - input_stream.append(console.ControlKey.CARRIAGE_RETURN) - - # Enter a partial command. - partial_cmd = 'ver' - input_stream.extend(StringToByteList(partial_cmd)) - - # Hit the UP arrow key. - input_stream.extend(Keys.UP_ARROW) - # Then, the DOWN arrow key. - input_stream.extend(Keys.DOWN_ARROW) - - # Send the sequence out. - for byte in input_stream: - self.console.HandleChar(byte) - - # The expected output should be the command we entered, a prompt, the - # partial command, clearing of the partial command, the command entered, - # clearing of the command entered, and then the partial command. - exp_console_out = test_str + '\r\n' + self.console.prompt - exp_console_out += partial_cmd - for _ in range(len(partial_cmd)): - exp_console_out += BACKSPACE_STRING - exp_console_out += test_str - for _ in range(len(test_str)): - exp_console_out += BACKSPACE_STRING - exp_console_out += partial_cmd - - # Verify console output. - CheckConsoleOutput(self, exp_console_out) - - # Verify input buffer. - exp_input_buffer = partial_cmd - exp_input_buffer_pos = len(exp_input_buffer) - CheckInputBuffer(self, exp_input_buffer) - CheckInputBufferPosition(self, exp_input_buffer_pos) - - def test_DownArrowOnEmptyHistory(self): - """Ensure nothing happens if the history is empty.""" - # Then press the up down arrow twice. - input_stream = 2 * Keys.DOWN_ARROW - - # Send the sequence out. - for byte in input_stream: - self.console.HandleChar(byte) - - # We expect nothing to have happened. - exp_console_out = '' - exp_input_buffer = '' - exp_input_buffer_pos = 0 - exp_history_buf = [] - - # Verify. - CheckConsoleOutput(self, exp_console_out) - CheckInputBufferPosition(self, exp_input_buffer_pos) - CheckInputBuffer(self, exp_input_buffer) - CheckHistoryBuffer(self, exp_history_buf) - - def test_DeleteCharsUsingDELKey(self): - """Verify that we can delete characters using the DEL key.""" - test_str = 'version' - input_stream = StringToByteList(test_str) - - # Hit the left arrow key 2 times. - input_stream.extend(2 * Keys.LEFT_ARROW) - - # Press the DEL key. - input_stream.extend(Keys.DEL) - - # Send the sequence out. - for byte in input_stream: - self.console.HandleChar(byte) - - # The expected output should be the command we entered, 2 individual cursor - # moves to the left, and then removing a char and shifting everything to the - # left one column. - exp_console_out = test_str - exp_console_out += 2 * OutputStream.MoveCursorLeft(1) - - # Remove the char by shifting everything to the left one, slicing out the - # remove char. - exp_console_out += test_str[-1:] + ' ' - - # Reset the cursor by moving back 2 columns because of the 'n' and space. - exp_console_out += OutputStream.MoveCursorLeft(2) - - # Verify console output. - CheckConsoleOutput(self, exp_console_out) - - # Verify input buffer. The input buffer should have the char sliced out and - # be positioned where the char was removed. - exp_input_buffer = test_str[:-2] + test_str[-1:] - exp_input_buffer_pos = len(exp_input_buffer) - 1 - CheckInputBuffer(self, exp_input_buffer) - CheckInputBufferPosition(self, exp_input_buffer_pos) - - def test_RepeatedCommandInHistory(self): - """Verify that we don't store 2 consecutive identical commands in history""" - # Enter a few commands. - test_commands = ['version', 'accelrange 0', 'battery', 'gettime'] - # Repeat the last command. - test_commands.append(test_commands[len(test_commands)-1]) - - input_stream = [] - for command in test_commands: - input_stream.extend(StringToByteList(command)) - input_stream.append(console.ControlKey.CARRIAGE_RETURN) - - # Send the sequence out. - for byte in input_stream: - self.console.HandleChar(byte) - - # Verify that the history buffer is correct. The last command, since - # it was repeated, should not have been added to the history. - exp_history_buf = test_commands[0:len(test_commands)-1] - CheckHistoryBuffer(self, exp_history_buf) - - -class TestConsoleCompatibility(unittest.TestCase): - """Verify that console can speak to enhanced and non-enhanced EC images.""" - def setUp(self): - """Setup the test harness.""" - # Setup logging with a timestamp, the module, and the log level. - logging.basicConfig(level=logging.DEBUG, - format=('%(asctime)s - %(module)s -' - ' %(levelname)s - %(message)s')) - # Create a temp file and set both the master and slave PTYs to the file to - # create a loopback. - self.tempfile = tempfile.TemporaryFile() - - # Mock out the pipes. - dummy_pipe_end_0, dummy_pipe_end_1 = mock.MagicMock(), mock.MagicMock() - self.console = console.Console(self.tempfile.fileno(), self.tempfile, - tempfile.TemporaryFile(), - dummy_pipe_end_0, dummy_pipe_end_1, "EC") - - @mock.patch('console.Console.CheckForEnhancedECImage') - def test_ActAsPassThruInNonEnhancedMode(self, mock_check): - """Verify we simply pass everything thru to non-enhanced ECs. - - Args: - mock_check: A MagicMock object replacing the CheckForEnhancedECImage() - method. - """ - # Set the interrogation mode to always so that we actually interrogate. - self.console.interrogation_mode = 'always' - - # Assume EC interrogations indicate that the image is non-enhanced. - mock_check.return_value = False - - # Press enter, followed by the command, and another enter. - input_stream = [] - input_stream.append(console.ControlKey.CARRIAGE_RETURN) - test_command = 'version' - input_stream.extend(StringToByteList(test_command)) - input_stream.append(console.ControlKey.CARRIAGE_RETURN) - - # Send the sequence out. - for byte in input_stream: - self.console.HandleChar(byte) - - # Expected calls to send down the pipe would be each character of the test - # command. - expected_calls = [] - expected_calls.append(mock.call(chr(console.ControlKey.CARRIAGE_RETURN))) - for char in test_command: - expected_calls.append(mock.call(char)) - expected_calls.append(mock.call(chr(console.ControlKey.CARRIAGE_RETURN))) - - # Verify that the calls happened. - self.console.cmd_pipe.send.assert_has_calls(expected_calls) - - # Since we're acting as a pass-thru, the input buffer should be empty and - # input_buffer_pos is 0. - CheckInputBuffer(self, '') - CheckInputBufferPosition(self, 0) - - @mock.patch('console.Console.CheckForEnhancedECImage') - def test_TransitionFromNonEnhancedToEnhanced(self, mock_check): - """Verify that we transition correctly to enhanced mode. - - Args: - mock_check: A MagicMock object replacing the CheckForEnhancedECImage() - method. - """ - # Set the interrogation mode to always so that we actually interrogate. - self.console.interrogation_mode = 'always' - - # First, assume that the EC interrogations indicate an enhanced EC image. - mock_check.return_value = True - # But our current knowledge of the EC image (which was actually the - # 'previous' EC) was a non-enhanced image. - self.console.enhanced_ec = False - - test_command = 'sysinfo' - input_stream = [] - input_stream.extend(StringToByteList(test_command)) - - expected_calls = [] - # All keystrokes to the console should be directed straight through to the - # EC until we press the enter key. - for char in test_command: - expected_calls.append(mock.call(char)) - - # Press the enter key. - input_stream.append(console.ControlKey.CARRIAGE_RETURN) - # The enter key should not be sent to the pipe since we should negotiate - # to an enhanced EC image. - - # Send the sequence out. - for byte in input_stream: - self.console.HandleChar(byte) - - # At this point, we should have negotiated to enhanced. - self.assertTrue(self.console.enhanced_ec, msg=('Did not negotiate to ' - 'enhanced EC image.')) - - # The command would have been dropped however, so verify this... - CheckInputBuffer(self, '') - CheckInputBufferPosition(self, 0) - # ...and repeat the command. - input_stream = StringToByteList(test_command) - input_stream.append(console.ControlKey.CARRIAGE_RETURN) - - # Send the sequence out. - for byte in input_stream: - self.console.HandleChar(byte) - - # Since we're enhanced now, we should have sent the entire command as one - # string with no trailing carriage return - expected_calls.append(mock.call(test_command)) - - # Verify all of the calls. - self.console.cmd_pipe.send.assert_has_calls(expected_calls) - - @mock.patch('console.Console.CheckForEnhancedECImage') - def test_TransitionFromEnhancedToNonEnhanced(self, mock_check): - """Verify that we transition correctly to non-enhanced mode. - - Args: - mock_check: A MagicMock object replacing the CheckForEnhancedECImage() - method. - """ - # Set the interrogation mode to always so that we actually interrogate. - self.console.interrogation_mode = 'always' - - # First, assume that the EC interrogations indicate an non-enhanced EC - # image. - mock_check.return_value = False - # But our current knowledge of the EC image (which was actually the - # 'previous' EC) was an enhanced image. - self.console.enhanced_ec = True - - test_command = 'sysinfo' - input_stream = [] - input_stream.extend(StringToByteList(test_command)) - input_stream.append(console.ControlKey.CARRIAGE_RETURN) - - # Send the sequence out. - for byte in input_stream: - self.console.HandleChar(byte) - - # But, we will negotiate to non-enhanced however, dropping this command. - # Verify this. - self.assertFalse(self.console.enhanced_ec, msg=('Did not negotiate to' - 'non-enhanced EC image.')) - CheckInputBuffer(self, '') - CheckInputBufferPosition(self, 0) - - # The carriage return should have passed through though. - expected_calls = [] - expected_calls.append(mock.call(chr(console.ControlKey.CARRIAGE_RETURN))) - - # Since the command was dropped, repeat the command. - input_stream = StringToByteList(test_command) - input_stream.append(console.ControlKey.CARRIAGE_RETURN) - - # Send the sequence out. - for byte in input_stream: - self.console.HandleChar(byte) - - # Since we're not enhanced now, we should have sent each character in the - # entire command separately and a carriage return. - for char in test_command: - expected_calls.append(mock.call(char)) - expected_calls.append(mock.call(chr(console.ControlKey.CARRIAGE_RETURN))) - - # Verify all of the calls. - self.console.cmd_pipe.send.assert_has_calls(expected_calls) - - def test_EnhancedCheckIfTimedOut(self): - """Verify that the check returns false if it times out.""" - # Make the debug pipe "time out". - self.console.dbg_pipe.poll.return_value = False - self.assertFalse(self.console.CheckForEnhancedECImage()) - - def test_EnhancedCheckIfACKReceived(self): - """Verify that the check returns true if the ACK is received.""" - # Make the debug pipe return EC_ACK. - self.console.dbg_pipe.poll.return_value = True - self.console.dbg_pipe.recv.return_value = interpreter.EC_ACK - self.assertTrue(self.console.CheckForEnhancedECImage()) - - def test_EnhancedCheckIfWrong(self): - """Verify that the check returns false if byte received is wrong.""" - # Make the debug pipe return the wrong byte. - self.console.dbg_pipe.poll.return_value = True - self.console.dbg_pipe.recv.return_value = '\xff' - self.assertFalse(self.console.CheckForEnhancedECImage()) - - def test_EnhancedCheckUsingBuffer(self): - """Verify that given reboot output, enhanced EC images are detected.""" - enhanced_output_stream = """ ---- UART initialized after reboot --- -[Reset cause: reset-pin soft] -[Image: RO, jerry_v1.1.4363-2af8572-dirty 2016-02-23 13:26:20 aaboagye@lithium.mtv.corp.google.com] -[0.001695 KB boot key 0] -[0.001790 Inits done] -[0.001923 not sysjump; forcing AP shutdown] -[0.002047 EC triggered warm reboot] -[0.002155 assert GPIO_PMIC_WARM_RESET_L for 4 ms] -[0.006326 auto_power_on set due to reset_flag 0x22] -[0.006477 Wait for battery stabilized during 1000000] -[0.007368 battery responded with status c0] -[0.009099 hash start 0x00010000 0x0000eb7c] -[0.009307 KB init state: -- -- -- -- -- -- -- -- -- -- -- -- --] -[0.009531 KB wait] -Enhanced Console is enabled (v1.0.0); type HELP for help. -> [0.009782 event set 0x00002000] -[0.009903 hostcmd init 0x2000] -[0.010031 power state 0 = G3, in 0x0000] -[0.010173 power state 4 = G3->S5, in 0x0000] -[0.010324 power state 1 = S5, in 0x0000] -[0.010466 power on 2] -[0.010566 power state 5 = S5->S3, in 0x0000] -[0.037713 event set 0x00000080] -[0.037836 event set 0x00400000] -[0.038675 Battery 89% / 1092h:15 to empty] -[0.224060 hash done 41dac382e3a6e3d2ea5b4d789c1bc46525cae7cc5ff6758f0de8d8369b506f57] -[0.375150 POWER_GOOD seen] -""" - for line in enhanced_output_stream.split('\n'): - self.console.CheckBufferForEnhancedImage(line) - - # Since the enhanced console string was present in the output, the console - # should have caught it. - self.assertTrue(self.console.enhanced_ec) - - # Also should check that the command was sent to the interpreter. - self.console.cmd_pipe.send.assert_called_once_with('enhanced True') - - # Now test the non-enhanced EC image. - self.console.cmd_pipe.reset_mock() - non_enhanced_output_stream = """ ---- UART initialized after reboot --- -[Reset cause: reset-pin soft] -[Image: RO, jerry_v1.1.4363-2af8572-dirty 2016-02-23 13:03:15 aaboagye@lithium.mtv.corp.google.com] -[0.001695 KB boot key 0] -[0.001790 Inits done] -[0.001923 not sysjump; forcing AP shutdown] -[0.002047 EC triggered warm reboot] -[0.002156 assert GPIO_PMIC_WARM_RESET_L for 4 ms] -[0.006326 auto_power_on set due to reset_flag 0x22] -[0.006477 Wait for battery stabilized during 1000000] -[0.007368 battery responded with status c0] -[0.008951 hash start 0x00010000 0x0000ed78] -[0.009159 KB init state: -- -- -- -- -- -- -- -- -- -- -- -- --] -[0.009383 KB wait] -Console is enabled; type HELP for help. -> [0.009602 event set 0x00002000] -[0.009722 hostcmd init 0x2000] -[0.009851 power state 0 = G3, in 0x0000] -[0.009993 power state 4 = G3->S5, in 0x0000] -[0.010144 power state 1 = S5, in 0x0000] -[0.010285 power on 2] -[0.010385 power state 5 = S5->S3, in 0x0000] -""" - for line in non_enhanced_output_stream.split('\n'): - self.console.CheckBufferForEnhancedImage(line) - - # Since the default console string is present in the output, it should be - # determined to be non enhanced now. - self.assertFalse(self.console.enhanced_ec) - - # Check that command was also sent to the interpreter. - self.console.cmd_pipe.send.assert_called_once_with('enhanced False') - - -class TestOOBMConsoleCommands(unittest.TestCase): - """Verify that OOBM console commands work correctly.""" - def setUp(self): - """Setup the test harness.""" - # Setup logging with a timestamp, the module, and the log level. - logging.basicConfig(level=logging.DEBUG, - format=('%(asctime)s - %(module)s -' - ' %(levelname)s - %(message)s')) - # Create a temp file and set both the master and slave PTYs to the file to - # create a loopback. - self.tempfile = tempfile.TemporaryFile() - - # Mock out the pipes. - dummy_pipe_end_0, dummy_pipe_end_1 = mock.MagicMock(), mock.MagicMock() - self.console = console.Console(self.tempfile.fileno(), self.tempfile, - tempfile.TemporaryFile(), - dummy_pipe_end_0, dummy_pipe_end_1, "EC") - self.console.oobm_queue = mock.MagicMock() - - @mock.patch('console.Console.CheckForEnhancedECImage') - def test_InterrogateCommand(self, mock_check): - """Verify that 'interrogate' command works as expected. - - Args: - mock_check: A MagicMock object replacing the CheckForEnhancedECIMage() - method. - """ - input_stream = [] - expected_calls = [] - mock_check.side_effect = [False] - - # 'interrogate never' should disable the interrogation from happening at - # all. - cmd = 'interrogate never' - # Enter the OOBM prompt. - input_stream.extend(StringToByteList('%')) - # Type the command - input_stream.extend(StringToByteList(cmd)) - # Press enter. - input_stream.append(console.ControlKey.CARRIAGE_RETURN) - - # Send the sequence out. - for byte in input_stream: - self.console.HandleChar(byte) - - input_stream = [] - - # The OOBM queue should have been called with the command being put. - expected_calls.append(mock.call.put(cmd)) - self.console.oobm_queue.assert_has_calls(expected_calls) - - # Process the OOBM queue. - self.console.oobm_queue.get.side_effect = [cmd] - self.console.ProcessOOBMQueue() - - # Type out a few commands. - input_stream.extend(StringToByteList('version')) - input_stream.append(console.ControlKey.CARRIAGE_RETURN) - input_stream.extend(StringToByteList('flashinfo')) - input_stream.append(console.ControlKey.CARRIAGE_RETURN) - input_stream.extend(StringToByteList('sysinfo')) - input_stream.append(console.ControlKey.CARRIAGE_RETURN) - - # Send the sequence out. - for byte in input_stream: - self.console.HandleChar(byte) - - # The Check function should NOT have been called at all. - mock_check.assert_not_called() - - # The EC image should be assumed to be not enhanced. - self.assertFalse(self.console.enhanced_ec, 'The image should be assumed to' - ' be NOT enhanced.') - - # Reset the mocks. - mock_check.reset_mock() - self.console.oobm_queue.reset_mock() - - # 'interrogate auto' should not interrogate at all. It should only be - # scanning the output stream for the 'console is enabled' strings. - cmd = 'interrogate auto' - # Enter the OOBM prompt. - input_stream.extend(StringToByteList('%')) - # Type the command - input_stream.extend(StringToByteList(cmd)) - # Press enter. - input_stream.append(console.ControlKey.CARRIAGE_RETURN) - - # Send the sequence out. - for byte in input_stream: - self.console.HandleChar(byte) - - input_stream = [] - expected_calls = [] - - # The OOBM queue should have been called with the command being put. - expected_calls.append(mock.call.put(cmd)) - self.console.oobm_queue.assert_has_calls(expected_calls) - - # Process the OOBM queue. - self.console.oobm_queue.get.side_effect = [cmd] - self.console.ProcessOOBMQueue() - - # Type out a few commands. - input_stream.extend(StringToByteList('version')) - input_stream.append(console.ControlKey.CARRIAGE_RETURN) - input_stream.extend(StringToByteList('flashinfo')) - input_stream.append(console.ControlKey.CARRIAGE_RETURN) - input_stream.extend(StringToByteList('sysinfo')) - input_stream.append(console.ControlKey.CARRIAGE_RETURN) - - # Send the sequence out. - for byte in input_stream: - self.console.HandleChar(byte) - - # The Check function should NOT have been called at all. - mock_check.assert_not_called() - - # The EC image should be assumed to be not enhanced. - self.assertFalse(self.console.enhanced_ec, 'The image should be assumed to' - ' be NOT enhanced.') - - # Reset the mocks. - mock_check.reset_mock() - self.console.oobm_queue.reset_mock() - - # 'interrogate always' should, like its name implies, interrogate always - # after each press of the enter key. This was the former way of doing - # interrogation. - cmd = 'interrogate always' - # Enter the OOBM prompt. - input_stream.extend(StringToByteList('%')) - # Type the command - input_stream.extend(StringToByteList(cmd)) - # Press enter. - input_stream.append(console.ControlKey.CARRIAGE_RETURN) - - # Send the sequence out. - for byte in input_stream: - self.console.HandleChar(byte) - - input_stream = [] - expected_calls = [] - - # The OOBM queue should have been called with the command being put. - expected_calls.append(mock.call.put(cmd)) - self.console.oobm_queue.assert_has_calls(expected_calls) - - # Process the OOBM queue. - self.console.oobm_queue.get.side_effect = [cmd] - self.console.ProcessOOBMQueue() - - # The Check method should be called 3 times here. - mock_check.side_effect = [False, False, False] - - # Type out a few commands. - input_stream.extend(StringToByteList('help list')) - input_stream.append(console.ControlKey.CARRIAGE_RETURN) - input_stream.extend(StringToByteList('taskinfo')) - input_stream.append(console.ControlKey.CARRIAGE_RETURN) - input_stream.extend(StringToByteList('hibdelay')) - input_stream.append(console.ControlKey.CARRIAGE_RETURN) - - # Send the sequence out. - for byte in input_stream: - self.console.HandleChar(byte) - - # The Check method should have been called 3 times here. - expected_calls = [mock.call(), mock.call(), mock.call()] - mock_check.assert_has_calls(expected_calls) - - # The EC image should be assumed to be not enhanced. - self.assertFalse(self.console.enhanced_ec, 'The image should be assumed to' - ' be NOT enhanced.') - - # Now, let's try to assume that the image is enhanced while still disabling - # interrogation. - mock_check.reset_mock() - self.console.oobm_queue.reset_mock() - input_stream = [] - cmd = 'interrogate never enhanced' - # Enter the OOBM prompt. - input_stream.extend(StringToByteList('%')) - # Type the command - input_stream.extend(StringToByteList(cmd)) - # Press enter. - input_stream.append(console.ControlKey.CARRIAGE_RETURN) - - # Send the sequence out. - for byte in input_stream: - self.console.HandleChar(byte) - - input_stream = [] - expected_calls = [] - - # The OOBM queue should have been called with the command being put. - expected_calls.append(mock.call.put(cmd)) - self.console.oobm_queue.assert_has_calls(expected_calls) - - # Process the OOBM queue. - self.console.oobm_queue.get.side_effect = [cmd] - self.console.ProcessOOBMQueue() - - # Type out a few commands. - input_stream.extend(StringToByteList('chgstate')) - input_stream.append(console.ControlKey.CARRIAGE_RETURN) - input_stream.extend(StringToByteList('hash')) - input_stream.append(console.ControlKey.CARRIAGE_RETURN) - input_stream.extend(StringToByteList('sysjump rw')) - input_stream.append(console.ControlKey.CARRIAGE_RETURN) - - # Send the sequence out. - for byte in input_stream: - self.console.HandleChar(byte) - - # The check method should have never been called. - mock_check.assert_not_called() - - # The EC image should be assumed to be enhanced. - self.assertTrue(self.console.enhanced_ec, 'The image should be' - ' assumed to be enhanced.') - - -if __name__ == '__main__': - unittest.main() diff --git a/util/ec3po/interpreter.py b/util/ec3po/interpreter.py deleted file mode 100644 index 23eb6a6071..0000000000 --- a/util/ec3po/interpreter.py +++ /dev/null @@ -1,462 +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. - -"""EC-3PO EC Interpreter - -interpreter provides the interpretation layer between the EC UART and the user. -It receives commands through its command pipe, formats the commands for the EC, -and sends the command to the EC. It also presents data from the EC to either be -displayed via the interactive console interface, or some other consumer. It -additionally supports automatic command retrying if the EC drops a character in -a command. -""" - -from __future__ import print_function - -import binascii -# pylint: disable=cros-logging-import -import copy -import logging -import os -import Queue -import select -import traceback - - -COMMAND_RETRIES = 3 # Number of attempts to retry a command. -EC_MAX_READ = 1024 # Max bytes to read at a time from the EC. -EC_SYN = '\xec' # Byte indicating EC interrogation. -EC_ACK = '\xc0' # Byte representing correct EC response to interrogation. - - -class LoggerAdapter(logging.LoggerAdapter): - """Class which provides a small adapter for the logger.""" - - def process(self, msg, kwargs): - """Prepends the served PTY to the beginning of the log message.""" - return '%s - %s' % (self.extra['pty'], msg), kwargs - - -class Interpreter(object): - """Class which provides the interpretation layer between the EC and user. - - This class essentially performs all of the intepretation for the EC and the - user. It handles all of the automatic command retrying as well as the - formation of commands for EC images which support that. - - Attributes: - logger: A logger for this module. - ec_uart_pty: An opened file object to the raw EC UART PTY. - ec_uart_pty_name: A string containing the name of the raw EC UART PTY. - cmd_pipe: A socket.socket or multiprocessing.Connection object which - represents the Interpreter side of the command pipe. This must be a - bidirectional pipe. Commands and responses will utilize this pipe. - dbg_pipe: A socket.socket or multiprocessing.Connection object which - represents the Interpreter side of the debug pipe. This must be a - unidirectional pipe with write capabilities. EC debug output will utilize - this pipe. - cmd_retries: An integer representing the number of attempts the console - should retry commands if it receives an error. - log_level: An integer representing the numeric value of the log level. - inputs: A list of objects that the intpreter selects for reading. - Initially, these are the EC UART and the command pipe. - outputs: A list of objects that the interpreter selects for writing. - ec_cmd_queue: A FIFO queue used for sending commands down to the EC UART. - last_cmd: A string that represents the last command sent to the EC. If an - error is encountered, the interpreter will attempt to retry this command - up to COMMAND_RETRIES. - enhanced_ec: A boolean indicating if the EC image that we are currently - communicating with is enhanced or not. Enhanced EC images will support - packed commands and host commands over the UART. This defaults to False - and is changed depending on the result of an interrogation. - interrogating: A boolean indicating if we are in the middle of interrogating - the EC. - connected: A boolean indicating if the interpreter is actually connected to - the UART and listening. - """ - def __init__(self, ec_uart_pty, cmd_pipe, dbg_pipe, log_level=logging.INFO, - name=None): - """Intializes an Interpreter object with the provided args. - - Args: - ec_uart_pty: A string representing the EC UART to connect to. - cmd_pipe: A socket.socket or multiprocessing.Connection object which - represents the Interpreter side of the command pipe. This must be a - bidirectional pipe. Commands and responses will utilize this pipe. - dbg_pipe: A socket.socket or multiprocessing.Connection object which - represents the Interpreter side of the debug pipe. This must be a - unidirectional pipe with write capabilities. EC debug output will - utilize this pipe. - cmd_retries: An integer representing the number of attempts the console - should retry commands if it receives an error. - log_level: An optional integer representing the numeric value of the log - level. By default, the log level will be logging.INFO (20). - name: the console source name - """ - # Create a unique logger based on the interpreter name - interpreter_prefix = ('%s - ' % name) if name else '' - logger = logging.getLogger('%sEC3PO.Interpreter' % interpreter_prefix) - self.logger = LoggerAdapter(logger, {'pty': ec_uart_pty}) - self.ec_uart_pty = open(ec_uart_pty, 'a+') - self.ec_uart_pty_name = ec_uart_pty - self.cmd_pipe = cmd_pipe - self.dbg_pipe = dbg_pipe - self.cmd_retries = COMMAND_RETRIES - self.log_level = log_level - self.inputs = [self.ec_uart_pty, self.cmd_pipe] - self.outputs = [] - self.ec_cmd_queue = Queue.Queue() - self.last_cmd = '' - self.enhanced_ec = False - self.interrogating = False - self.connected = True - - def __str__(self): - """Show internal state of the Interpreter object. - - Returns: - A string that shows the values of the attributes. - """ - string = [] - string.append('%r' % self) - string.append('ec_uart_pty: %s' % self.ec_uart_pty) - string.append('cmd_pipe: %r' % self.cmd_pipe) - string.append('dbg_pipe: %r' % self.dbg_pipe) - string.append('cmd_retries: %d' % self.cmd_retries) - string.append('log_level: %d' % self.log_level) - string.append('inputs: %r' % self.inputs) - string.append('outputs: %r' % self.outputs) - string.append('ec_cmd_queue: %r' % self.ec_cmd_queue) - string.append('last_cmd: \'%s\'' % self.last_cmd) - string.append('enhanced_ec: %r' % self.enhanced_ec) - string.append('interrogating: %r' % self.interrogating) - return '\n'.join(string) - - def EnqueueCmd(self, command): - """Enqueue a command to be sent to the EC UART. - - Args: - command: A string which contains the command to be sent. - """ - self.ec_cmd_queue.put(command) - self.logger.log(1, 'Commands now in queue: %d', self.ec_cmd_queue.qsize()) - - # Add the EC UART as an output to be serviced. - if self.connected and self.ec_uart_pty not in self.outputs: - self.outputs.append(self.ec_uart_pty) - - def PackCommand(self, raw_cmd): - r"""Packs a command for use with error checking. - - For error checking, we pack console commands in a particular format. The - format is as follows: - - &&[x][x][x][x]&{cmd}\n\n - ^ ^ ^^ ^^ ^ ^-- 2 newlines. - | | || || |-- the raw console command. - | | || ||-- 1 ampersand. - | | ||____|--- 2 hex digits representing the CRC8 of cmd. - | |____|-- 2 hex digits reprsenting the length of cmd. - |-- 2 ampersands - - Args: - raw_cmd: A pre-packed string which contains the raw command. - - Returns: - A string which contains the packed command. - """ - # Don't pack a single carriage return. - if raw_cmd != '\r': - # The command format is as follows. - # &&[x][x][x][x]&{cmd}\n\n - packed_cmd = [] - packed_cmd.append('&&') - # The first pair of hex digits are the length of the command. - packed_cmd.append('%02x' % len(raw_cmd)) - # Then the CRC8 of cmd. - packed_cmd.append('%02x' % Crc8(raw_cmd)) - packed_cmd.append('&') - # Now, the raw command followed by 2 newlines. - packed_cmd.append(raw_cmd) - packed_cmd.append('\n\n') - return ''.join(packed_cmd) - else: - return raw_cmd - - def ProcessCommand(self, command): - """Captures the input determines what actions to take. - - Args: - command: A string representing the command sent by the user. - """ - if command == "disconnect": - if self.connected: - self.logger.debug('UART disconnect request.') - # Drop all pending commands if any. - while not self.ec_cmd_queue.empty(): - c = self.ec_cmd_queue.get() - self.logger.debug('dropped: \'%s\'', c) - if self.enhanced_ec: - # Reset retry state. - self.cmd_retries = COMMAND_RETRIES - self.last_cmd = '' - # Get the UART that the interpreter is attached to. - fileobj = self.ec_uart_pty - self.logger.debug('fileobj: %r', fileobj) - # Remove the descriptor from the inputs and outputs. - self.inputs.remove(fileobj) - if fileobj in self.outputs: - self.outputs.remove(fileobj) - self.logger.debug('Removed fileobj. Remaining inputs: %r', self.inputs) - # Close the file. - fileobj.close() - # Mark the interpreter as disconnected now. - self.connected = False - self.logger.debug('Disconnected from %s.', self.ec_uart_pty_name) - return - - elif command == "reconnect": - if not self.connected: - self.logger.debug('UART reconnect request.') - # Reopen the PTY. - fileobj = open(self.ec_uart_pty_name, 'a+') - self.logger.debug('fileobj: %r', fileobj) - self.ec_uart_pty = fileobj - # Add the descriptor to the inputs. - self.inputs.append(fileobj) - self.logger.debug('fileobj added. curr inputs: %r', self.inputs) - # Mark the interpreter as connected now. - self.connected = True - self.logger.debug('Connected to %s.', self.ec_uart_pty_name) - return - - elif command.startswith('enhanced'): - self.enhanced_ec = command.split(' ')[1] == 'True' - return - - # Ignore any other commands while in the disconnected state. - self.logger.log(1, 'command: \'%s\'', command) - if not self.connected: - self.logger.debug('Ignoring command because currently disconnected.') - return - - # Remove leading and trailing spaces only if this is an enhanced EC image. - # For non-enhanced EC images, commands will be single characters at a time - # and can be spaces. - if self.enhanced_ec: - command = command.strip(' ') - - # There's nothing to do if the command is empty. - if len(command) == 0: - return - - # Handle log level change requests. - if command.startswith('loglevel'): - self.logger.debug('Log level change request.') - new_log_level = int(command.split(' ')[1]) - self.logger.logger.setLevel(new_log_level) - self.logger.info('Log level changed to %d.', new_log_level) - return - - # Check for interrogation command. - if command == EC_SYN: - # User is requesting interrogation. Send SYN as is. - self.logger.debug('User requesting interrogation.') - self.interrogating = True - # Assume the EC isn't enhanced until we get a response. - self.enhanced_ec = False - elif self.enhanced_ec: - # Enhanced EC images require the plaintext commands to be packed. - command = self.PackCommand(command) - # TODO(aaboagye): Make a dict of commands and keys and eventually, - # handle partial matching based on unique prefixes. - - self.EnqueueCmd(command) - - def HandleCmdRetries(self): - """Attempts to retry commands if possible.""" - if self.cmd_retries > 0: - # The EC encountered an error. We'll have to retry again. - self.logger.warning('Retrying command...') - self.cmd_retries -= 1 - self.logger.warning('Retries remaining: %d', self.cmd_retries) - # Retry the command and add the EC UART to the writers again. - self.EnqueueCmd(self.last_cmd) - self.outputs.append(self.ec_uart_pty) - else: - # We're out of retries, so just give up. - self.logger.error('Command failed. No retries left.') - # Clear the command in progress. - self.last_cmd = '' - # Reset the retry count. - self.cmd_retries = COMMAND_RETRIES - - def SendCmdToEC(self): - """Sends a command to the EC.""" - # If we're retrying a command, just try to send it again. - if self.cmd_retries < COMMAND_RETRIES: - cmd = self.last_cmd - else: - # If we're not retrying, we should not be writing to the EC if we have no - # items in our command queue. - assert not self.ec_cmd_queue.empty() - # Get the command to send. - cmd = self.ec_cmd_queue.get() - - # Send the command. - self.ec_uart_pty.write(cmd) - self.ec_uart_pty.flush() - self.logger.log(1, 'Sent command to EC.') - - if self.enhanced_ec and cmd != EC_SYN: - # Now, that we've sent the command, store the current command as the last - # command sent. If we encounter an error string, we will attempt to retry - # this command. - if cmd != self.last_cmd: - self.last_cmd = cmd - # Reset the retry count. - self.cmd_retries = COMMAND_RETRIES - - # If no command is pending to be sent, then we can remove the EC UART from - # writers. Might need better checking for command retry logic in here. - if self.ec_cmd_queue.empty(): - # Remove the EC UART from the writers while we wait for a response. - self.logger.debug('Removing EC UART from writers.') - self.outputs.remove(self.ec_uart_pty) - - def HandleECData(self): - """Handle any debug prints from the EC.""" - self.logger.log(1, 'EC has data') - # Read what the EC sent us. - data = os.read(self.ec_uart_pty.fileno(), EC_MAX_READ) - self.logger.log(1, 'got: \'%s\'', binascii.hexlify(data)) - if '&E' in data and self.enhanced_ec: - # We received an error, so we should retry it if possible. - self.logger.warning('Error string found in data.') - self.HandleCmdRetries() - return - - # If we were interrogating, check the response and update our knowledge - # of the current EC image. - if self.interrogating: - self.enhanced_ec = data == EC_ACK - if self.enhanced_ec: - self.logger.debug('The current EC image seems enhanced.') - else: - self.logger.debug('The current EC image does NOT seem enhanced.') - # Done interrogating. - self.interrogating = False - # For now, just forward everything the EC sends us. - self.logger.log(1, 'Forwarding to user...') - self.dbg_pipe.send(data) - - def HandleUserData(self): - """Handle any incoming commands from the user. - - Raises: - EOFError: Allowed to propagate through from self.cmd_pipe.recv(). - """ - self.logger.log(1, 'Command data available. Begin processing.') - data = self.cmd_pipe.recv() - # Process the command. - self.ProcessCommand(data) - - -def Crc8(data): - """Calculates the CRC8 of data. - - The generator polynomial used is: x^8 + x^2 + x + 1. - This is the same implementation that is used in the EC. - - Args: - data: A string of data that we wish to calculate the CRC8 on. - - Returns: - crc >> 8: An integer representing the CRC8 value. - """ - crc = 0 - for byte in data: - crc ^= (ord(byte) << 8) - for _ in range(8): - if crc & 0x8000: - crc ^= (0x1070 << 3) - crc <<= 1 - return crc >> 8 - - -def StartLoop(interp, shutdown_pipe=None): - """Starts an infinite loop of servicing the user and the EC. - - StartLoop checks to see if there are any commands to process, processing them - if any, and forwards EC output to the user. - - When sending a command to the EC, we send the command once and check the - response to see if the EC encountered an error when receiving the command. An - error condition is reported to the interpreter by a string with at least one - '&' and 'E'. The full string is actually '&&EE', however it's possible that - the leading ampersand or trailing 'E' could be dropped. If an error is - encountered, the interpreter will retry up to the amount configured. - - Args: - interp: An Interpreter object that has been properly initialised. - shutdown_pipe: A file object for a pipe or equivalent that becomes readable - (not blocked) to indicate that the loop should exit. Can be None to never - exit the loop. - """ - try: - # This is used instead of "break" to avoid exiting the loop in the middle of - # an iteration. - continue_looping = True - - while continue_looping: - # The inputs list is created anew in each loop iteration because the - # Interpreter class sometimes modifies the interp.inputs list. - if shutdown_pipe is None: - inputs = interp.inputs - else: - inputs = list(interp.inputs) - inputs.append(shutdown_pipe) - - readable, writeable, _ = select.select(inputs, interp.outputs, []) - - for obj in readable: - # Handle any debug prints from the EC. - if obj is interp.ec_uart_pty: - interp.HandleECData() - - # Handle any commands from the user. - elif obj is interp.cmd_pipe: - try: - interp.HandleUserData() - except EOFError: - interp.logger.debug( - 'ec3po interpreter received EOF from cmd_pipe in ' - 'HandleUserData()') - continue_looping = False - - elif obj is shutdown_pipe: - interp.logger.debug( - 'ec3po interpreter received shutdown pipe unblocked notification') - continue_looping = False - - for obj in writeable: - # Send a command to the EC. - if obj is interp.ec_uart_pty: - interp.SendCmdToEC() - - except KeyboardInterrupt: - pass - - # TODO(crbug.com/894870): Stop suppressing all exceptions. - except: - traceback.print_exc() - - finally: - interp.cmd_pipe.close() - interp.dbg_pipe.close() - interp.ec_uart_pty.close() - if shutdown_pipe is not None: - shutdown_pipe.close() - interp.logger.debug('Exit ec3po interpreter loop for %s', - interp.ec_uart_pty_name) diff --git a/util/ec3po/interpreter_unittest.py b/util/ec3po/interpreter_unittest.py deleted file mode 100755 index de2335158b..0000000000 --- a/util/ec3po/interpreter_unittest.py +++ /dev/null @@ -1,366 +0,0 @@ -#!/usr/bin/env python2 -# 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. - -"""Unit tests for the EC-3PO interpreter.""" - -from __future__ import print_function - -# pylint: disable=cros-logging-import -import logging -import mock -import tempfile -import unittest - -import interpreter -import threadproc_shim - -class TestEnhancedECBehaviour(unittest.TestCase): - """Test case to verify all enhanced EC interpretation tasks.""" - def setUp(self): - """Setup the test harness.""" - # Setup logging with a timestamp, the module, and the log level. - logging.basicConfig(level=logging.DEBUG, - format=('%(asctime)s - %(module)s -' - ' %(levelname)s - %(message)s')) - - # Create a tempfile that would represent the EC UART PTY. - self.tempfile = tempfile.NamedTemporaryFile() - - # Create the pipes that the interpreter will use. - self.cmd_pipe_user, self.cmd_pipe_itpr = threadproc_shim.Pipe() - self.dbg_pipe_user, self.dbg_pipe_itpr = threadproc_shim.Pipe(duplex=False) - - # Mock the open() function so we can inspect reads/writes to the EC. - self.ec_uart_pty = mock.mock_open() - with mock.patch('__builtin__.open', self.ec_uart_pty): - # Create an interpreter. - self.itpr = interpreter.Interpreter(self.tempfile.name, - self.cmd_pipe_itpr, - self.dbg_pipe_itpr, - log_level=logging.DEBUG, - name="EC") - - @mock.patch('interpreter.os') - def test_HandlingCommandsThatProduceNoOutput(self, mock_os): - """Verify that the Interpreter correctly handles non-output commands. - - Args: - mock_os: MagicMock object replacing the 'os' module for this test - case. - """ - # The interpreter init should open the EC UART PTY. - expected_ec_calls = [mock.call(self.tempfile.name, 'a+')] - # Have a command come in the command pipe. The first command will be an - # interrogation to determine if the EC is enhanced or not. - self.cmd_pipe_user.send(interpreter.EC_SYN) - self.itpr.HandleUserData() - # At this point, the command should be queued up waiting to be sent, so - # let's actually send it to the EC. - self.itpr.SendCmdToEC() - expected_ec_calls.extend([mock.call().write(interpreter.EC_SYN), - mock.call().flush()]) - # Now, assume that the EC sends only 1 response back of EC_ACK. - mock_os.read.side_effect = [interpreter.EC_ACK] - # When reading the EC, the interpreter will call file.fileno() to pass to - # os.read(). - expected_ec_calls.append(mock.call().fileno()) - # Simulate the response. - self.itpr.HandleECData() - - # Now that the interrogation was complete, it's time to send down the real - # command. - test_cmd = 'chan save' - # Send the test command down the pipe. - self.cmd_pipe_user.send(test_cmd) - self.itpr.HandleUserData() - self.itpr.SendCmdToEC() - # Since the EC image is enhanced, we should have sent a packed command. - expected_ec_calls.append(mock.call().write(self.itpr.PackCommand(test_cmd))) - expected_ec_calls.append(mock.call().flush()) - - # Now that the first command was sent, we should send another command which - # produces no output. The console would send another interrogation. - self.cmd_pipe_user.send(interpreter.EC_SYN) - self.itpr.HandleUserData() - self.itpr.SendCmdToEC() - expected_ec_calls.extend([mock.call().write(interpreter.EC_SYN), - mock.call().flush()]) - # Again, assume that the EC sends only 1 response back of EC_ACK. - mock_os.read.side_effect = [interpreter.EC_ACK] - # When reading the EC, the interpreter will call file.fileno() to pass to - # os.read(). - expected_ec_calls.append(mock.call().fileno()) - # Simulate the response. - self.itpr.HandleECData() - - # Now send the second test command. - test_cmd = 'chan 0' - self.cmd_pipe_user.send(test_cmd) - self.itpr.HandleUserData() - self.itpr.SendCmdToEC() - # Since the EC image is enhanced, we should have sent a packed command. - expected_ec_calls.append(mock.call().write(self.itpr.PackCommand(test_cmd))) - expected_ec_calls.append(mock.call().flush()) - - # Finally, verify that the appropriate writes were actually sent to the EC. - self.ec_uart_pty.assert_has_calls(expected_ec_calls) - - @mock.patch('interpreter.os') - def test_CommandRetryingOnError(self, mock_os): - """Verify that commands are retried if an error is encountered. - - Args: - mock_os: MagicMock object replacing the 'os' module for this test - case. - """ - # The interpreter init should open the EC UART PTY. - expected_ec_calls = [mock.call(self.tempfile.name, 'a+')] - # Have a command come in the command pipe. The first command will be an - # interrogation to determine if the EC is enhanced or not. - self.cmd_pipe_user.send(interpreter.EC_SYN) - self.itpr.HandleUserData() - # At this point, the command should be queued up waiting to be sent, so - # let's actually send it to the EC. - self.itpr.SendCmdToEC() - expected_ec_calls.extend([mock.call().write(interpreter.EC_SYN), - mock.call().flush()]) - # Now, assume that the EC sends only 1 response back of EC_ACK. - mock_os.read.side_effect = [interpreter.EC_ACK] - # When reading the EC, the interpreter will call file.fileno() to pass to - # os.read(). - expected_ec_calls.append(mock.call().fileno()) - # Simulate the response. - self.itpr.HandleECData() - - # Let's send a command that is received on the EC-side with an error. - test_cmd = 'accelinfo' - self.cmd_pipe_user.send(test_cmd) - self.itpr.HandleUserData() - self.itpr.SendCmdToEC() - packed_cmd = self.itpr.PackCommand(test_cmd) - expected_ec_calls.extend([mock.call().write(packed_cmd), - mock.call().flush()]) - # Have the EC return the error string twice. - mock_os.read.side_effect = ['&&EE', '&&EE'] - for i in range(2): - # When reading the EC, the interpreter will call file.fileno() to pass to - # os.read(). - expected_ec_calls.append(mock.call().fileno()) - # Simulate the response. - self.itpr.HandleECData() - - # Since an error was received, the EC should attempt to retry the command. - expected_ec_calls.extend([mock.call().write(packed_cmd), - mock.call().flush()]) - # Verify that the retry count was decremented. - self.assertEqual(interpreter.COMMAND_RETRIES-i-1, self.itpr.cmd_retries, - 'Unexpected cmd_remaining count.') - # Actually retry the command. - self.itpr.SendCmdToEC() - - # Now assume that the last one goes through with no trouble. - expected_ec_calls.extend([mock.call().write(packed_cmd), - mock.call().flush()]) - self.itpr.SendCmdToEC() - - # Verify all the calls. - self.ec_uart_pty.assert_has_calls(expected_ec_calls) - - def test_PackCommandsForEnhancedEC(self): - """Verify that the interpreter packs commands for enhanced EC images.""" - # Assume current EC image is enhanced. - self.itpr.enhanced_ec = True - # Receive a command from the user. - test_cmd = 'gettime' - self.cmd_pipe_user.send(test_cmd) - # Mock out PackCommand to see if it was called. - self.itpr.PackCommand = mock.MagicMock() - # Have the interpreter handle the command. - self.itpr.HandleUserData() - # Verify that PackCommand() was called. - self.itpr.PackCommand.assert_called_once_with(test_cmd) - - def test_DontPackCommandsForNonEnhancedEC(self): - """Verify the interpreter doesn't pack commands for non-enhanced images.""" - # Assume current EC image is not enhanced. - self.itpr.enhanced_ec = False - # Receive a command from the user. - test_cmd = 'gettime' - self.cmd_pipe_user.send(test_cmd) - # Mock out PackCommand to see if it was called. - self.itpr.PackCommand = mock.MagicMock() - # Have the interpreter handle the command. - self.itpr.HandleUserData() - # Verify that PackCommand() was called. - self.itpr.PackCommand.assert_not_called() - - @mock.patch('interpreter.os') - def test_KeepingTrackOfInterrogation(self, mock_os): - """Verify that the interpreter can track the state of the interrogation. - - Args: - mock_os: MagicMock object replacing the 'os' module. for this test - case. - """ - # Upon init, the interpreter should assume that the current EC image is not - # enhanced. - self.assertFalse(self.itpr.enhanced_ec, msg=('State of enhanced_ec upon' - ' init is not False.')) - - # Assume an interrogation request comes in from the user. - self.cmd_pipe_user.send(interpreter.EC_SYN) - self.itpr.HandleUserData() - - # Verify the state is now within an interrogation. - self.assertTrue(self.itpr.interrogating, 'interrogating should be True') - # The state of enhanced_ec should not be changed yet because we haven't - # received a valid response yet. - self.assertFalse(self.itpr.enhanced_ec, msg=('State of enhanced_ec is ' - 'not False.')) - - # Assume that the EC responds with an EC_ACK. - mock_os.read.side_effect = [interpreter.EC_ACK] - self.itpr.HandleECData() - - # Now, the interrogation should be complete and we should know that the - # current EC image is enhanced. - self.assertFalse(self.itpr.interrogating, msg=('interrogating should be ' - 'False')) - self.assertTrue(self.itpr.enhanced_ec, msg='enhanced_ec sholud be True') - - # Now let's perform another interrogation, but pretend that the EC ignores - # it. - self.cmd_pipe_user.send(interpreter.EC_SYN) - self.itpr.HandleUserData() - - # Verify interrogating state. - self.assertTrue(self.itpr.interrogating, 'interrogating sholud be True') - # We should assume that the image is not enhanced until we get the valid - # response. - self.assertFalse(self.itpr.enhanced_ec, 'enhanced_ec should be False now.') - - # Let's pretend that we get a random debug print. This should clear the - # interrogating flag. - mock_os.read.side_effect = '[1660.593076 HC 0x103]' - self.itpr.HandleECData() - - # Verify that interrogating flag is cleared and enhanced_ec is still False. - self.assertFalse(self.itpr.interrogating, 'interrogating should be False.') - self.assertFalse(self.itpr.enhanced_ec, - 'enhanced_ec should still be False.') - - -class TestUARTDisconnection(unittest.TestCase): - """Test case to verify interpreter disconnection/reconnection.""" - def setUp(self): - """Setup the test harness.""" - # Setup logging with a timestamp, the module, and the log level. - logging.basicConfig(level=logging.DEBUG, - format=('%(asctime)s - %(module)s -' - ' %(levelname)s - %(message)s')) - - # Create a tempfile that would represent the EC UART PTY. - self.tempfile = tempfile.NamedTemporaryFile() - - # Create the pipes that the interpreter will use. - self.cmd_pipe_user, self.cmd_pipe_itpr = threadproc_shim.Pipe() - self.dbg_pipe_user, self.dbg_pipe_itpr = threadproc_shim.Pipe(duplex=False) - - # Mock the open() function so we can inspect reads/writes to the EC. - self.ec_uart_pty = mock.mock_open() - with mock.patch('__builtin__.open', self.ec_uart_pty): - # Create an interpreter. - self.itpr = interpreter.Interpreter(self.tempfile.name, - self.cmd_pipe_itpr, - self.dbg_pipe_itpr, - log_level=logging.DEBUG, - name="EC") - - # First, check that interpreter is initialized to connected. - self.assertTrue(self.itpr.connected, ('The interpreter should be' - ' initialized in a connected state')) - - def test_DisconnectStopsECTraffic(self): - """Verify that when in disconnected state, no debug prints are sent.""" - # Let's send a disconnect command through the command pipe. - self.cmd_pipe_user.send('disconnect') - self.itpr.HandleUserData() - - # Verify interpreter is disconnected from EC. - self.assertFalse(self.itpr.connected, ('The interpreter should be' - 'disconnected.')) - # Verify that the EC UART is no longer a member of the inputs. The - # interpreter will never pull data from the EC if it's not a member of the - # inputs list. - self.assertFalse(self.itpr.ec_uart_pty in self.itpr.inputs) - - def test_CommandsDroppedWhenDisconnected(self): - """Verify that when in disconnected state, commands are dropped.""" - # Send a command, followed by 'disconnect'. - self.cmd_pipe_user.send('taskinfo') - self.itpr.HandleUserData() - self.cmd_pipe_user.send('disconnect') - self.itpr.HandleUserData() - - # Verify interpreter is disconnected from EC. - self.assertFalse(self.itpr.connected, ('The interpreter should be' - 'disconnected.')) - # Verify that the EC UART is no longer a member of the inputs nor outputs. - self.assertFalse(self.itpr.ec_uart_pty in self.itpr.inputs) - self.assertFalse(self.itpr.ec_uart_pty in self.itpr.outputs) - - # Have the user send a few more commands in the disconnected state. - command = 'help\n' - for char in command: - self.cmd_pipe_user.send(char) - self.itpr.HandleUserData() - - # The command queue should be empty. - self.assertEqual(0, self.itpr.ec_cmd_queue.qsize()) - - # Now send the reconnect command. - self.cmd_pipe_user.send('reconnect') - with mock.patch('__builtin__.open', mock.mock_open()): - self.itpr.HandleUserData() - - # Verify interpreter is connected. - self.assertTrue(self.itpr.connected) - # Verify that EC UART is a member of the inputs. - self.assertTrue(self.itpr.ec_uart_pty in self.itpr.inputs) - # Since no command was sent after reconnection, verify that the EC UART is - # not a member of the outputs. - self.assertFalse(self.itpr.ec_uart_pty in self.itpr.outputs) - - def test_ReconnectAllowsECTraffic(self): - """Verify that when connected, EC UART traffic is allowed.""" - # Let's send a disconnect command through the command pipe. - self.cmd_pipe_user.send('disconnect') - self.itpr.HandleUserData() - - # Verify interpreter is disconnected. - self.assertFalse(self.itpr.connected, ('The interpreter should be' - 'disconnected.')) - # Verify that the EC UART is no longer a member of the inputs nor outputs. - self.assertFalse(self.itpr.ec_uart_pty in self.itpr.inputs) - self.assertFalse(self.itpr.ec_uart_pty in self.itpr.outputs) - - # Issue reconnect command through the command pipe. - self.cmd_pipe_user.send('reconnect') - with mock.patch('__builtin__.open', mock.mock_open()): - self.itpr.HandleUserData() - - # Verify interpreter is connected. - self.assertTrue(self.itpr.connected, ('The interpreter should be' - 'connected.')) - # Verify that the EC UART is now a member of the inputs. - self.assertTrue(self.itpr.ec_uart_pty in self.itpr.inputs) - # Since we have issued no commands during the disconnected state, no - # commands are pending and therefore the PTY should not be added to the - # outputs. - self.assertFalse(self.itpr.ec_uart_pty in self.itpr.outputs) - - -if __name__ == '__main__': - unittest.main() diff --git a/util/ec3po/run_tests.sh b/util/ec3po/run_tests.sh deleted file mode 100755 index f0ef348273..0000000000 --- a/util/ec3po/run_tests.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash -# -# 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. - -# Discover all the unit tests in the ec3po directory and run them. -python2 -m unittest discover -b -s util/ec3po/ -p *_unittest.py \ - && touch util/ec3po/.tests-passed diff --git a/util/ec3po/threadproc_shim.py b/util/ec3po/threadproc_shim.py deleted file mode 100644 index d5f5d19245..0000000000 --- a/util/ec3po/threadproc_shim.py +++ /dev/null @@ -1,66 +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. - -"""This is a shim library for the ec3po transition from subprocesses to threads. - -This is necessary because ec3po is split between the platform/ec/ and -third_party/hdctools/ repositories, so the transition cannot happen atomically -in one change. See http://b/79684405 #39. - -This contains only the multiprocessing objects or threading-oriented equivalents -that are actually in use by ec3po. There is no need for further functionality, -because this shim will be deleted after the migration is complete. - -TODO(b/79684405): Stop using multiprocessing.Pipe. The -multiprocessing.Connection objects it returns serialize and deserialize objects -(via Python pickling), which is necessary for sending them between processes, -but is unnecessary overhead between threads. This will not be a simple change, -because the ec3po Console and Interpreter classes use the underlying pipe/socket -pairs with select/poll/epoll alongside other file descriptors. A drop-in -replacement would be non-trivial and add undesirable complexity. The correct -solution will be to split off the polling of the pipes/queues from this module -into separate threads, so that they can be transitioned to another form of -cross-thread synchronization, e.g. directly waiting on Queue.Queue.get() or a -lower-level thread synchronization primitive. - -TODO(b/79684405): After this library has been updated to contain -threading-oriented equivalents to its original multiprocessing implementations, -and some reasonable amount of time has elapsed for thread-based ec3po problems -to be discovered, migrate both the platform/ec/ and third_party/hdctools/ sides -of ec3po off of this shim and then delete this file. IMPORTANT: This should -wait until after completing the TODO above to stop using multiprocessing.Pipe! -""" - -# Imports to bring objects into this namespace for users of this module. -from Queue import Queue -from multiprocessing import Pipe -from threading import Thread as ThreadOrProcess - -# True if this module has ec3po using subprocesses, False if using threads. -USING_SUBPROCS = False - - -def _DoNothing(): - """Do-nothing function for use as a callback with DoIf().""" - - -def DoIf(subprocs=_DoNothing, threads=_DoNothing): - """Return a callback or not based on ec3po use of subprocesses or threads. - - Args: - subprocs: callback that does not require any args - This will be returned - (not called!) if and only if ec3po is using subprocesses. This is - OPTIONAL, the default value is a do-nothing callback that returns None. - threads: callback that does not require any args - This will be returned - (not called!) if and only if ec3po is using threads. This is OPTIONAL, - the default value is a do-nothing callback that returns None. - - Returns: - Either the subprocs or threads argument will be returned. - """ - return subprocs if USING_SUBPROCS else threads - - -def Value(ctype, *args): - return ctype(*args) diff --git a/util/ec_flash.c b/util/ec_flash.c deleted file mode 100644 index 3bae077200..0000000000 --- a/util/ec_flash.c +++ /dev/null @@ -1,231 +0,0 @@ -/* Copyright 2013 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 -#include -#include -#include -#include - -#include "comm-host.h" -#include "misc_util.h" -#include "timer.h" - -static const uint32_t ERASE_ASYNC_TIMEOUT = 10 * SECOND; -static const uint32_t ERASE_ASYNC_WAIT = 500 * MSEC; -static const int FLASH_ERASE_BUSY_RV = -EECRESULT - EC_RES_BUSY; - -int ec_flash_read(uint8_t *buf, int offset, int size) -{ - struct ec_params_flash_read p; - int rv; - int i; - - /* Read data in chunks */ - for (i = 0; i < size; i += ec_max_insize) { - p.offset = offset + i; - p.size = MIN(size - i, ec_max_insize); - rv = ec_command(EC_CMD_FLASH_READ, 0, - &p, sizeof(p), ec_inbuf, p.size); - if (rv < 0) { - fprintf(stderr, "Read error at offset %d\n", i); - return rv; - } - memcpy(buf + i, ec_inbuf, p.size); - } - - return 0; -} - -int ec_flash_verify(const uint8_t *buf, int offset, int size) -{ - uint8_t *rbuf = malloc(size); - int rv; - int i; - - if (!rbuf) { - fprintf(stderr, "Unable to allocate buffer.\n"); - return -1; - } - - rv = ec_flash_read(rbuf, offset, size); - if (rv < 0) { - free(rbuf); - return rv; - } - - for (i = 0; i < size; i++) { - if (buf[i] != rbuf[i]) { - fprintf(stderr, "Mismatch at offset 0x%x: " - "want 0x%02x, got 0x%02x\n", - i, buf[i], rbuf[i]); - free(rbuf); - return -1; - } - } - - free(rbuf); - return 0; -} - -/** - * @param info_response pointer to response that will be filled on success - * @return Zero or positive on success, negative on failure - */ -static int get_flash_info_v2(struct ec_response_flash_info_2 *info_response) -{ - struct ec_params_flash_info_2 info_params = { - /* - * By setting this to zero we indicate that we don't care - * about getting the bank description in the response. - */ - .num_banks_desc = 0 - }; - - return ec_command(EC_CMD_FLASH_INFO, 2, &info_params, - sizeof(info_params), info_response, - sizeof(*info_response)); -} - -/** - * @param info_response pointer to response that will be filled on success - * @return Zero or positive on success, negative on failure - */ -static int get_flash_info_v0(struct ec_response_flash_info *info_response) -{ - return ec_command(EC_CMD_FLASH_INFO, 0, NULL, 0, info_response, - sizeof(*info_response)); -} - -/** - * @return Write size on success, negative on failure - */ -static int get_flash_write_size(void) -{ - int rv = 0; - int write_size; - int flash_info_version = -1; - struct ec_response_flash_info info_response_v0 = { 0 }; - struct ec_response_flash_info_2 info_response_v2 = { 0 }; - - if (ec_cmd_version_supported(EC_CMD_FLASH_INFO, 2)) - flash_info_version = 2; - else if (ec_cmd_version_supported(EC_CMD_FLASH_INFO, 0)) - flash_info_version = 0; - - if (flash_info_version < 0) - return -1; - - if (flash_info_version == 2) { - rv = get_flash_info_v2(&info_response_v2); - write_size = info_response_v2.write_ideal_size; - } else { - rv = get_flash_info_v0(&info_response_v0); - write_size = info_response_v0.write_block_size; - } - - if (rv < 0) - return rv; - - return write_size; -} - -int ec_flash_write(const uint8_t *buf, int offset, int size) -{ - struct ec_params_flash_write *p = - (struct ec_params_flash_write *)ec_outbuf; - int write_size; - int pdata_max_size = (int)(ec_max_outsize - sizeof(*p)); - int step; - int rv; - int i; - - /* - * Determine whether we can use version 1 of the EC_CMD_FLASH_WRITE - * command with more data, or only version 0. - */ - if (!ec_cmd_version_supported(EC_CMD_FLASH_WRITE, EC_VER_FLASH_WRITE)) - pdata_max_size = EC_FLASH_WRITE_VER0_SIZE; - - write_size = get_flash_write_size(); - if (write_size < 0) - return write_size; - - /* - * shouldn't ever happen, but report an error rather than a division - * by zero in the next statement. - */ - if (write_size == 0) - return -1; - - step = (pdata_max_size / write_size) * write_size; - - if (!step) { - fprintf(stderr, "Write block size %d > max param size %d\n", - write_size, pdata_max_size); - return -1; - } - - /* Write data in chunks */ - printf("Write size %d...\n", step); - - for (i = 0; i < size; i += step) { - p->offset = offset + i; - p->size = MIN(size - i, step); - memcpy(p + 1, buf + i, p->size); - rv = ec_command(EC_CMD_FLASH_WRITE, 0, p, sizeof(*p) + p->size, - NULL, 0); - if (rv < 0) { - fprintf(stderr, "Write error at offset %d\n", i); - return rv; - } - } - - return 0; -} - -int ec_flash_erase(int offset, int size) -{ - struct ec_params_flash_erase p; - - p.offset = offset; - p.size = size; - - return ec_command(EC_CMD_FLASH_ERASE, 0, &p, sizeof(p), NULL, 0); -} - -int ec_flash_erase_async(int offset, int size) -{ - struct ec_params_flash_erase_v1 p = { 0 }; - uint32_t timeout = 0; - int rv = FLASH_ERASE_BUSY_RV; - - p.cmd = FLASH_ERASE_SECTOR_ASYNC; - p.params.offset = offset; - p.params.size = size; - - rv = ec_command(EC_CMD_FLASH_ERASE, 1, &p, sizeof(p), NULL, 0); - - if (rv < 0) - return rv; - - rv = FLASH_ERASE_BUSY_RV; - - while (rv < 0 && timeout < ERASE_ASYNC_TIMEOUT) { - /* - * The erase is not complete until FLASH_ERASE_GET_RESULT - * returns success. It's important that we retry even when the - * underlying ioctl returns an error (not just - * FLASH_ERASE_BUSY_RV). - * - * See https://crrev.com/c/511805 for details. - */ - usleep(ERASE_ASYNC_WAIT); - timeout += ERASE_ASYNC_WAIT; - p.cmd = FLASH_ERASE_GET_RESULT; - rv = ec_command(EC_CMD_FLASH_ERASE, 1, &p, sizeof(p), NULL, 0); - } - return rv; -} diff --git a/util/ec_flash.h b/util/ec_flash.h deleted file mode 100644 index f4aea3b7a3..0000000000 --- a/util/ec_flash.h +++ /dev/null @@ -1,62 +0,0 @@ -/* Copyright 2013 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 __UTIL_EC_FLASH_H -#define __UTIL_EC_FLASH_H - -/** - * Read EC flash memory - * - * @param buf Destination buffer - * @param offset Offset in EC flash to read - * @param size Number of bytes to read - * - * @return 0 if success, negative if error. - */ -int ec_flash_read(uint8_t *buf, int offset, int size); - -/** - * Verify EC flash memory - * - * @param buf Source buffer to verify against EC flash - * @param offset Offset in EC flash to check - * @param size Number of bytes to check - * - * @return 0 if success, negative if error. - */ -int ec_flash_verify(const uint8_t *buf, int offset, int size); - -/** - * Write EC flash memory - * - * @param buf Source buffer - * @param offset Offset in EC flash to write - * @param size Number of bytes to write - * - * @return 0 if success, negative if error. - */ -int ec_flash_write(const uint8_t *buf, int offset, int size); - -/** - * Erase EC flash memory - * - * @param offset Offset in EC flash to erase - * @param size Number of bytes to erase - * - * @return 0 if success, negative if error. - */ -int ec_flash_erase(int offset, int size); - -/** - * Erase EC flash memory asynchronously - * - * @param offset Offset in EC flash to erase - * @param size Number of bytes to erase - * - * @return 0 if success, negative if error. - */ -int ec_flash_erase_async(int offset, int size); - -#endif diff --git a/util/ec_panicinfo.c b/util/ec_panicinfo.c deleted file mode 100644 index f614770619..0000000000 --- a/util/ec_panicinfo.c +++ /dev/null @@ -1,126 +0,0 @@ -/* 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. - */ - -#include -#include -#include "compile_time_macros.h" -#include "ec_panicinfo.h" - -static void print_panic_reg(int regnum, const uint32_t *regs, int index) -{ - static const char * const regname[] = { - "r0 ", "r1 ", "r2 ", "r3 ", "r4 ", - "r5 ", "r6 ", "r7 ", "r8 ", "r9 ", - "r10", "r11", "r12", "sp ", "lr ", - "pc "}; - - printf("%s:", regname[regnum]); - if (regs) - printf("%08x", regs[index]); - else - printf(" "); - printf((regnum & 3) == 3 ? "\n" : " "); -} - -static int parse_panic_info_cm(const struct panic_data *pdata) -{ - const uint32_t *lregs = pdata->cm.regs; - const uint32_t *sregs = NULL; - enum { - ORIG_UNKNOWN = 0, - ORIG_PROCESS, - ORIG_HANDLER - } origin = ORIG_UNKNOWN; - int i; - const char *panic_origins[3] = {"", "PROCESS", "HANDLER"}; - - printf("Saved panic data:%s\n", - (pdata->flags & PANIC_DATA_FLAG_OLD_HOSTCMD ? "" : " (NEW)")); - - if (pdata->struct_version == 2) - origin = ((lregs[11] & 0xf) == 1 || (lregs[11] & 0xf) == 9) ? - ORIG_HANDLER : ORIG_PROCESS; - - /* - * In pdata struct, 'regs', which is allocated before 'frame', has - * one less elements in version 1. Therefore, if the data is from - * version 1, shift 'sregs' by one element to align with 'frame' in - * version 1. - */ - if (pdata->flags & PANIC_DATA_FLAG_FRAME_VALID) - sregs = pdata->cm.frame - (pdata->struct_version == 1 ? 1 : 0); - - printf("=== %s EXCEPTION: %02x ====== xPSR: %08x ===\n", - panic_origins[origin], - lregs[1] & 0xff, sregs ? sregs[7] : -1); - for (i = 0; i < 4; ++i) - print_panic_reg(i, sregs, i); - for (i = 4; i < 10; ++i) - print_panic_reg(i, lregs, i - 1); - print_panic_reg(10, lregs, 9); - print_panic_reg(11, lregs, 10); - print_panic_reg(12, sregs, 4); - print_panic_reg(13, lregs, origin == ORIG_HANDLER ? 2 : 0); - print_panic_reg(14, sregs, 5); - print_panic_reg(15, sregs, 6); - - return 0; -} - -static int parse_panic_info_nds32(const struct panic_data *pdata) -{ - const uint32_t *regs = pdata->nds_n8.regs; - uint32_t itype = pdata->nds_n8.itype; - uint32_t ipc = pdata->nds_n8.ipc; - uint32_t ipsw = pdata->nds_n8.ipsw; - - printf("Saved panic data:%s\n", - (pdata->flags & PANIC_DATA_FLAG_OLD_HOSTCMD ? "" : " (NEW)")); - - printf("=== EXCEP: ITYPE=%x ===\n", itype); - printf("R0 %08x R1 %08x R2 %08x R3 %08x\n", - regs[0], regs[1], regs[2], regs[3]); - printf("R4 %08x R5 %08x R6 %08x R7 %08x\n", - regs[4], regs[5], regs[6], regs[7]); - printf("R8 %08x R9 %08x R10 %08x R15 %08x\n", - regs[8], regs[9], regs[10], regs[11]); - printf("FP %08x GP %08x LP %08x SP %08x\n", - regs[12], regs[13], regs[14], regs[15]); - printf("IPC %08x IPSW %05x\n", ipc, ipsw); - printf("SWID of ITYPE: %x\n", ((itype >> 16) & 0x7fff)); - - return 0; -} - -int parse_panic_info(const struct panic_data *pdata) -{ - /* - * We only understand panic data with version <= 2. Warn the user - * of higher versions. - */ - if (pdata->struct_version > 2) - fprintf(stderr, - "Unknown panic data version (%d). " - "Following data may be incorrect!\n", - pdata->struct_version); - - /* Validate magic number */ - if (pdata->magic != PANIC_DATA_MAGIC) - fprintf(stderr, - "Incorrect panic magic (%d). " - "Following data may be incorrect!\n", - pdata->magic); - - switch (pdata->arch) { - case PANIC_ARCH_CORTEX_M: - return parse_panic_info_cm(pdata); - case PANIC_ARCH_NDS32_N8: - return parse_panic_info_nds32(pdata); - default: - fprintf(stderr, "Unknown architecture (%d).\n", pdata->arch); - break; - } - return -1; -} diff --git a/util/ec_panicinfo.h b/util/ec_panicinfo.h deleted file mode 100644 index f70c58e59f..0000000000 --- a/util/ec_panicinfo.h +++ /dev/null @@ -1,19 +0,0 @@ -/* 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. - */ - -#ifndef EC_PANICINFO_H -#define EC_PANICINFO_H - -#include "panic.h" - -/** - * Prints panic information to stdout. - * - * @param pdata Panic information to print - * @return 0 if success or non-zero error code if error. - */ -int parse_panic_info(const struct panic_data *pdata); - -#endif /* EC_PANICINFO_H */ diff --git a/util/ec_parse_panicinfo.c b/util/ec_parse_panicinfo.c deleted file mode 100644 index 5db8ed2e05..0000000000 --- a/util/ec_parse_panicinfo.c +++ /dev/null @@ -1,22 +0,0 @@ -/* 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. - * - * Standalone utility to parse EC panicinfo. - */ - -#include -#include -#include "ec_panicinfo.h" - -int main(int argc, char *argv[]) -{ - struct panic_data pdata; - - if (fread(&pdata, sizeof(pdata), 1, stdin) != 1) { - fprintf(stderr, "Error reading panicinfo from stdin.\n"); - return 1; - } - - return parse_panic_info(&pdata) ? 1 : 0; -} diff --git a/util/ec_sb_firmware_update.c b/util/ec_sb_firmware_update.c deleted file mode 100644 index 72d3baf175..0000000000 --- a/util/ec_sb_firmware_update.c +++ /dev/null @@ -1,843 +0,0 @@ -/* Copyright 2014 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 -#include -#include -#include -#include -#include - -#include "comm-host.h" -#include "compile_time_macros.h" -#include "ec_sb_firmware_update.h" -#include "ec_commands.h" -#include "lock/gec_lock.h" -#include "misc_util.h" -#include "powerd_lock.h" - -/* Subcommands: [check|update] */ -enum { - OP_UNKNOWN = 0, - OP_CHECK = 1, - OP_UPDATE = 2, -}; - -struct delay_value { - uint32_t steps; - uint32_t value; -}; - -/* Default retry counter on errors */ -#define SB_FW_UPDATE_DEFAULT_RETRY_CNT 3 -/* Default delay value */ -#define SB_FW_UPDATE_DEFAULT_DELAY 1000 - -#define DELAY_US_BEGIN 500000 -#define DELAY_US_END 1000000 -#define DELAY_US_BUSY 1000000 -#define DELAY_US_WRITE_END 50000 - -static struct delay_value sb_delays[] = { - {1, 100000}, - {2, 9000000}, - {4, 100000}, - {771, 30000}, - {2200, 10000}, - {0xFFFFFF, 50000}, -}; - -enum fw_update_state { - S0_READ_STATUS = 0, - S1_READ_INFO = 1, - S2_WRITE_PREPARE = 2, - S3_READ_STATUS = 3, - S4_WRITE_UPDATE = 4, - S5_READ_STATUS = 5, - S6_WRITE_BLOCK = 6, - S7_READ_STATUS = 7, - S8_WRITE_END = 8, - S9_READ_STATUS = 9, - S10_TERMINAL = 10 -}; - -#define MAX_FW_IMAGE_NAME_SIZE 80 - -/* Firmware Update Control Flags */ -enum { - F_AC_PRESENT = 0x1, /* AC Present */ - F_VERSION_CHECK = 0x2, /* do firmware version check */ - F_UPDATE = 0x4, /* do firmware update */ - F_NEED_UPDATE = 0x8, /* need firmware update */ - F_POWERD_DISABLED = 0x10, /* powerd is disabled */ - F_LFCC_ZERO = 0x20, /* last full charge is zero */ - F_BATT_DISCHARGE = 0x40 /* battery discharging */ -}; - -struct fw_update_ctrl { - uint32_t flags; /* fw update control flags */ - int size; /* size of battery firmware image */ - char *ptr; /* current read pointer of the firmware image */ - int offset; /* current block write offset */ - struct sb_fw_header *fw_img_hdr; /*pointer to firmware image header*/ - struct sb_fw_update_status status; - struct sb_fw_update_info info; - int err_retry_cnt; - int fec_err_retry_cnt; - int busy_retry_cnt; - int step_size; - int rv; - char image_name[MAX_FW_IMAGE_NAME_SIZE]; - char msg[256]; -}; - -/* - * Global Firmware Update Control Data Structure - */ -static struct fw_update_ctrl fw_update; - -static uint32_t get_delay_value(uint32_t offset, uint32_t step_size) -{ - int sz = ARRAY_SIZE(sb_delays); - int i; - for (i = 0; i < sz; i++) { - if (offset <= sb_delays[i].steps * step_size) - return sb_delays[i].value; - } - return sb_delays[sz-1].value; -} - -static void print_battery_firmware_image_hdr( - struct sb_fw_header *hdr) -{ - printf("Latest Battery Firmware:\n"); - printf("\t%c%c%c%c hdr_ver:%04x major_minor:%04x\n", - hdr->signature[0], - hdr->signature[1], - hdr->signature[2], - hdr->signature[3], - hdr->hdr_version, hdr->pkg_version_major_minor); - - printf("\tmaker:0x%04x hwid:0x%04x fw_ver:0x%04x tbl_ver:0x%04x\n", - hdr->vendor_id, hdr->battery_type, hdr->fw_version, - hdr->data_table_version); - - printf("\tbinary offset:0x%08x size:0x%08x chk_sum:0x%02x\n", - hdr->fw_binary_offset, hdr->fw_binary_size, hdr->checksum); -} - -static void print_info(struct sb_fw_update_info *info) -{ - printf("\nCurrent Battery Firmware:\n"); - printf("\tmaker:0x%04x hwid:0x%04x fw_ver:0x%04x tbl_ver:0x%04x\n", - info->maker_id, - info->hardware_id, - info->fw_version, - info->data_version); - return; -} - -static void print_status(struct sb_fw_update_status *sts) -{ - printf("f_maker_id:%d f_hw_id:%d f_fw_ver:%d f_permnent:%d\n", - sts->v_fail_maker_id, - sts->v_fail_hw_id, - sts->v_fail_fw_version, - sts->v_fail_permanent); - printf("permanent failure:%d abnormal:%d fw_update:%d\n", - sts->permanent_failure, - sts->abnormal_condition, - sts->fw_update_supported); - printf("fw_update_mode:%d fw_corrupted:%d cmd_reject:%d\n", - sts->fw_update_mode, - sts->fw_corrupted, - sts->cmd_reject); - printf("invliad data:%d fw_fatal_err:%d fec_err:%d busy:%d\n", - sts->invalid_data, - sts->fw_fatal_error, - sts->fec_error, - sts->busy); - printf("\n"); - return; -} - -/* @return 1 (True) if img signature is valid */ -static int check_battery_firmware_image_signature( - struct sb_fw_header *hdr) -{ - return (hdr->signature[0] == 'B') && - (hdr->signature[1] == 'T') && - (hdr->signature[2] == 'F') && - (hdr->signature[3] == 'W'); -} - -/* @return 1 (True) if img checksum is valid. */ -static int check_battery_firmware_image_checksum( - struct sb_fw_header *hdr) -{ - int i; - uint8_t sum = 0; - uint8_t *img = (uint8_t *)hdr; - - img += hdr->fw_binary_offset; - for (i = 0; i < hdr->fw_binary_size; i++) - sum += img[i]; - sum += hdr->checksum; - return sum == 0; -} - -/* @return 1 (True) if img versions are ok to update. */ -static int check_battery_firmware_image_version( - struct sb_fw_header *hdr, - struct sb_fw_update_info *p) -{ - /* - * If the battery firmware has a newer fw version - * or a newer data table version, then it is ok to update. - */ - return (hdr->fw_version > p->fw_version) - || (hdr->data_table_version > p->data_version); -} - - -static int check_battery_firmware_ids( - struct sb_fw_header *hdr, - struct sb_fw_update_info *p) -{ - return ((hdr->vendor_id == p->maker_id) && - (hdr->battery_type == p->hardware_id)); -} - -/* check_if_need_update_fw - * @return 1 (true) if need; 0 (false) if not. - */ -static int check_if_valid_fw( - struct sb_fw_header *hdr, - struct sb_fw_update_info *info) -{ - return check_battery_firmware_image_signature(hdr) - && check_battery_firmware_ids(hdr, info) - && check_battery_firmware_image_checksum(hdr); -} - -/* check_if_need_update_fw - * @return 1 (true) if need; 0 (false) if not. - */ -static int check_if_need_update_fw( - struct sb_fw_header *hdr, - struct sb_fw_update_info *info) -{ - return check_battery_firmware_image_version(hdr, info); -} - -static void log_msg(struct fw_update_ctrl *fw_update, - enum fw_update_state state, const char *msg) -{ - sprintf(fw_update->msg, - "Battery Firmware Updater State:%d %s", state, msg); -} - - -static char *read_fw_image(struct fw_update_ctrl *fw_update) -{ - int size; - char *buf; - fw_update->size = 0; - fw_update->ptr = NULL; - fw_update->fw_img_hdr = (struct sb_fw_header *)NULL; - - /* Read the input file */ - buf = read_file(fw_update->image_name, &size); - if (!buf) - return NULL; - - fw_update->size = size; - fw_update->ptr = buf; - fw_update->fw_img_hdr = (struct sb_fw_header *)buf; - print_battery_firmware_image_hdr(fw_update->fw_img_hdr); - - if (fw_update->fw_img_hdr->fw_binary_offset >= fw_update->size || - fw_update->size < 256) { - printf("Load Firmware Image[%s] Error offset:%d size:%d\n", - fw_update->image_name, - fw_update->fw_img_hdr->fw_binary_offset, - fw_update->size); - free(buf); - return NULL; - } - return buf; -} - -static int get_status(struct sb_fw_update_status *status) -{ - int rv = EC_RES_SUCCESS; - int cnt = 0; - - struct ec_params_sb_fw_update *param = - (struct ec_params_sb_fw_update *)ec_outbuf; - - struct ec_response_sb_fw_update *resp = - (struct ec_response_sb_fw_update *)ec_inbuf; - - param->hdr.subcmd = EC_SB_FW_UPDATE_STATUS; - do { - usleep(SB_FW_UPDATE_DEFAULT_DELAY); - rv = ec_command(EC_CMD_SB_FW_UPDATE, 0, - param, sizeof(struct ec_sb_fw_update_header), - resp, SB_FW_UPDATE_CMD_STATUS_SIZE); - } while ((rv < 0) && (cnt++ < SB_FW_UPDATE_DEFAULT_RETRY_CNT)); - - if (rv < 0) { - memset(status, 0, SB_FW_UPDATE_CMD_STATUS_SIZE); - return -EC_RES_ERROR; - } - - memcpy(status, resp->status.data, SB_FW_UPDATE_CMD_STATUS_SIZE); - return EC_RES_SUCCESS; -} - -static int get_info(struct sb_fw_update_info *info) -{ - int rv = EC_RES_SUCCESS; - int cnt = 0; - - struct ec_params_sb_fw_update *param = - (struct ec_params_sb_fw_update *)ec_outbuf; - - struct ec_response_sb_fw_update *resp = - (struct ec_response_sb_fw_update *)ec_inbuf; - - param->hdr.subcmd = EC_SB_FW_UPDATE_INFO; - do { - usleep(SB_FW_UPDATE_DEFAULT_DELAY); - rv = ec_command(EC_CMD_SB_FW_UPDATE, 0, - param, sizeof(struct ec_sb_fw_update_header), - resp, SB_FW_UPDATE_CMD_INFO_SIZE); - } while ((rv < 0) && (cnt++ < SB_FW_UPDATE_DEFAULT_RETRY_CNT)); - - if (rv < 0) { - memset(info, 0, SB_FW_UPDATE_CMD_INFO_SIZE); - return -EC_RES_ERROR; - } - - memcpy(info, resp->info.data, SB_FW_UPDATE_CMD_INFO_SIZE); - return EC_RES_SUCCESS; -} - -static int send_subcmd(int subcmd) -{ - int rv = EC_RES_SUCCESS; - - struct ec_params_sb_fw_update *param = - (struct ec_params_sb_fw_update *)ec_outbuf; - - param->hdr.subcmd = subcmd; - rv = ec_command(EC_CMD_SB_FW_UPDATE, 0, - param, sizeof(struct ec_sb_fw_update_header), NULL, 0); - if (rv < 0) { - printf("Firmware Update subcmd:%d Error\n", subcmd); - return -EC_RES_ERROR; - } - return EC_RES_SUCCESS; -} - -static int write_block(struct fw_update_ctrl *fw_update, - int offset, int bsize) -{ - int rv; - - struct ec_params_sb_fw_update *param = - (struct ec_params_sb_fw_update *)ec_outbuf; - - memcpy(param->write.data, fw_update->ptr+offset, bsize); - - param->hdr.subcmd = EC_SB_FW_UPDATE_WRITE; - rv = ec_command(EC_CMD_SB_FW_UPDATE, 0, - param, sizeof(struct ec_params_sb_fw_update), NULL, 0); - if (rv < 0) { - printf("Firmware Update Write Error ptr:%p offset@%x\n", - fw_update->ptr, offset); - return -EC_RES_ERROR; - } - return EC_RES_SUCCESS; -} - -static void dump_data(uint8_t *data, int offset, int size) -{ - int i = 0; - - printf("Offset:0x%X\n", offset); - for (i = 0; i < size; i++) { - if ((i%16) == 0) - printf("\n"); - printf("%02X ", data[i]); - } - printf("\n"); -} - -static enum fw_update_state s0_read_status(struct fw_update_ctrl *fw_update) -{ - if (fw_update->busy_retry_cnt == 0) { - fw_update->rv = -1; - log_msg(fw_update, S0_READ_STATUS, "Busy"); - return S10_TERMINAL; - } - - fw_update->busy_retry_cnt--; - - fw_update->rv = get_status(&fw_update->status); - if (fw_update->rv) { - fw_update->rv = -1; - log_msg(fw_update, S0_READ_STATUS, "Interface Error"); - return S10_TERMINAL; - } - - if (!((fw_update->status.abnormal_condition == 0) - && (fw_update->status.fw_update_supported == 1))) { - return S0_READ_STATUS; - } - - if (fw_update->status.busy) { - usleep(DELAY_US_BUSY); - return S0_READ_STATUS; - } else - return S1_READ_INFO; -} - -static enum fw_update_state s1_read_battery_info( - struct fw_update_ctrl *fw_update) -{ - int rv; - - if (fw_update->err_retry_cnt == 0) { - fw_update->rv = -1; - log_msg(fw_update, S1_READ_INFO, "Retry Error"); - return S10_TERMINAL; - } - - fw_update->err_retry_cnt--; - - rv = get_info(&fw_update->info); - if (rv) { - fw_update->rv = -1; - log_msg(fw_update, S1_READ_INFO, "Interface Error"); - return S10_TERMINAL; - } - print_info(&fw_update->info); - - sprintf(fw_update->image_name, - "/lib/firmware/battery/maker.%04x.hwid.%04x.bin", - fw_update->info.maker_id, - fw_update->info.hardware_id); - - if (NULL == read_fw_image(fw_update)) { - fw_update->rv = 0; - log_msg(fw_update, S1_READ_INFO, "Open Image File"); - return S10_TERMINAL; - } - - rv = get_status(&fw_update->status); - if (rv) { - fw_update->rv = -1; - log_msg(fw_update, S1_READ_INFO, "Interface Error"); - return S10_TERMINAL; - } - - rv = check_if_valid_fw(fw_update->fw_img_hdr, &fw_update->info); - if (rv == 0) { - fw_update->rv = -EC_RES_INVALID_PARAM; - log_msg(fw_update, S1_READ_INFO, "Invalid Firmware"); - return S10_TERMINAL; - } - - rv = check_if_need_update_fw(fw_update->fw_img_hdr, &fw_update->info); - if (rv == 0 && (fw_update->flags & F_VERSION_CHECK)) { - fw_update->rv = 0; - log_msg(fw_update, S1_READ_INFO, "Latest Firmware"); - return S10_TERMINAL; - } - - fw_update->flags |= F_NEED_UPDATE; - - if (!(fw_update->flags & F_UPDATE)) { - fw_update->rv = 0; - return S10_TERMINAL; - } - - if (!(fw_update->flags & F_AC_PRESENT)) { - fw_update->rv = 0; - log_msg(fw_update, S1_READ_INFO, - "Require AC Adapter Connected."); - return S10_TERMINAL; - } - - if ((fw_update->flags & F_BATT_DISCHARGE) && - (fw_update->flags & F_AC_PRESENT)) { - /* - * If battery discharge due to battery learning mode, - * we can't update battery FW, because device will shutdown - * during FW update. - */ - fw_update->rv = 0; - log_msg(fw_update, S1_READ_INFO, - "battery can't update in learning mode"); - return S10_TERMINAL; - } - - return S2_WRITE_PREPARE; -} - -static enum fw_update_state s2_write_prepare(struct fw_update_ctrl *fw_update) -{ - int rv; - - rv = disable_power_management(); - if (0 == rv) - fw_update->flags |= F_POWERD_DISABLED; - - rv = send_subcmd(EC_SB_FW_UPDATE_PREPARE); - if (rv) { - fw_update->rv = -1; - log_msg(fw_update, S2_WRITE_PREPARE, "Interface Error"); - return S10_TERMINAL; - } - return S3_READ_STATUS; -} - -static enum fw_update_state s3_read_status(struct fw_update_ctrl *fw_update) -{ - int rv; - - rv = get_status(&fw_update->status); - if (rv) { - fw_update->rv = -1; - log_msg(fw_update, S3_READ_STATUS, "Interface Error"); - return S10_TERMINAL; - } - return S4_WRITE_UPDATE; - -} - -static enum fw_update_state s4_write_update(struct fw_update_ctrl *fw_update) -{ - int rv; - - rv = send_subcmd(EC_SB_FW_UPDATE_BEGIN); - if (rv) { - fw_update->rv = -1; - log_msg(fw_update, S4_WRITE_UPDATE, "Interface Error"); - return S10_TERMINAL; - } - usleep(DELAY_US_BEGIN); - return S5_READ_STATUS; -} - -static enum fw_update_state s5_read_status(struct fw_update_ctrl *fw_update) -{ - int rv = get_status(&fw_update->status); - - if (rv) { - fw_update->rv = -1; - log_msg(fw_update, S5_READ_STATUS, "Interface Error"); - return S10_TERMINAL; - } - if (fw_update->status.fw_update_mode == 0) - return S2_WRITE_PREPARE; - - /* Init Write Block Loop Controls */ - fw_update->ptr += fw_update->fw_img_hdr->fw_binary_offset; - fw_update->size -= fw_update->fw_img_hdr->fw_binary_offset; - fw_update->offset = 0; - - return S6_WRITE_BLOCK; -} - -static enum fw_update_state s6_write_block(struct fw_update_ctrl *fw_update) -{ - int rv; - int bsize; - int offset = fw_update->offset; - - if (offset >= fw_update->size) - return S8_WRITE_END; - - bsize = fw_update->step_size; - - if ((offset & 0xFFFF) == 0x0) - printf("\n%X\n", offset); - - if (fw_update->fec_err_retry_cnt == 0) { - fw_update->rv = -1; - log_msg(fw_update, S6_WRITE_BLOCK, "FEC Retry Error"); - return S10_TERMINAL; - } - fw_update->fec_err_retry_cnt--; - - rv = write_block(fw_update, offset, bsize); - if (rv) { - fw_update->rv = -1; - log_msg(fw_update, S6_WRITE_BLOCK, "Interface Error"); - return S10_TERMINAL; - } - - /* - * Add more delays after the last few (3) block writes. - * 3 is chosen based on current test results. - */ - if ((offset + 3*fw_update->step_size) >= fw_update->size) - usleep(DELAY_US_WRITE_END); - - usleep(get_delay_value(offset, fw_update->step_size)); - - return S7_READ_STATUS; -} - -static enum fw_update_state s7_read_status(struct fw_update_ctrl *fw_update) -{ - int rv; - int offset = fw_update->offset; - int bsize; - int cnt = 0; - - bsize = fw_update->step_size; - do { - usleep(SB_FW_UPDATE_DEFAULT_DELAY); - rv = get_status(&fw_update->status); - if (rv) { - dump_data(fw_update->ptr+offset, offset, bsize); - print_status(&fw_update->status); - fw_update->rv = -1; - log_msg(fw_update, S7_READ_STATUS, "Interface Error"); - return S10_TERMINAL; - } - } while (fw_update->status.busy && - (cnt++ < SB_FW_UPDATE_DEFAULT_RETRY_CNT)); - - if (fw_update->status.fec_error) { - dump_data(fw_update->ptr+offset, offset, bsize); - print_status(&fw_update->status); - fw_update->rv = 0; - return S6_WRITE_BLOCK; - } - if (fw_update->status.permanent_failure || - fw_update->status.v_fail_permanent) { - dump_data(fw_update->ptr+offset, offset, bsize); - print_status(&fw_update->status); - fw_update->rv = -1; - log_msg(fw_update, S7_READ_STATUS, "Battery Permanent Error"); - return S8_WRITE_END; - } - if (fw_update->status.v_fail_maker_id || - fw_update->status.v_fail_hw_id || - fw_update->status.v_fail_fw_version || - fw_update->status.fw_corrupted || - fw_update->status.cmd_reject || - fw_update->status.invalid_data || - fw_update->status.fw_fatal_error) { - - dump_data(fw_update->ptr+offset, offset, bsize); - print_status(&fw_update->status); - fw_update->rv = 0; - return S1_READ_INFO; - } - - fw_update->fec_err_retry_cnt = SB_FW_UPDATE_FEC_ERROR_RETRY_CNT; - fw_update->offset += fw_update->step_size; - return S6_WRITE_BLOCK; -} - - -static enum fw_update_state s8_write_end(struct fw_update_ctrl *fw_update) -{ - int rv; - - rv = send_subcmd(EC_SB_FW_UPDATE_END); - if (rv && (0 == fw_update->rv)) { - fw_update->rv = -1; - log_msg(fw_update, S8_WRITE_END, "Interface Error"); - } - - if (fw_update->rv) - return S10_TERMINAL; - - usleep(DELAY_US_END); - fw_update->busy_retry_cnt = SB_FW_UPDATE_BUSY_ERROR_RETRY_CNT; - return S9_READ_STATUS; -} - -static enum fw_update_state s9_read_status(struct fw_update_ctrl *fw_update) -{ - int rv; - - if (fw_update->busy_retry_cnt == 0) { - fw_update->rv = -1; - log_msg(fw_update, S9_READ_STATUS, "Busy"); - return S10_TERMINAL; - } - - rv = get_status(&fw_update->status); - if (rv) { - fw_update->rv = -1; - log_msg(fw_update, S9_READ_STATUS, "Interface Error"); - return S10_TERMINAL; - } - if ((fw_update->status.fw_update_mode == 1) - || (fw_update->status.busy == 1)) { - usleep(SB_FW_UPDATE_DEFAULT_DELAY); - fw_update->busy_retry_cnt--; - return S9_READ_STATUS; - } - log_msg(fw_update, S9_READ_STATUS, "Complete"); - fw_update->flags &= ~F_NEED_UPDATE; - return S10_TERMINAL; -} - - -typedef enum fw_update_state (*fw_state_func)(struct fw_update_ctrl *fw_update); - -fw_state_func state_table[] = { - s0_read_status, - s1_read_battery_info, - s2_write_prepare, - s3_read_status, - s4_write_update, - s5_read_status, - s6_write_block, - s7_read_status, - s8_write_end, - s9_read_status -}; - - -/** - * Update Smart Battery Firmware - * - * @param fw_update struct fw_update_ctrl - * - * @return 0 if success, negative if error. - */ -static int ec_sb_firmware_update(struct fw_update_ctrl *fw_update) -{ - enum fw_update_state state; - - fw_update->err_retry_cnt = SB_FW_UPDATE_ERROR_RETRY_CNT; - fw_update->fec_err_retry_cnt = SB_FW_UPDATE_FEC_ERROR_RETRY_CNT; - fw_update->busy_retry_cnt = SB_FW_UPDATE_BUSY_ERROR_RETRY_CNT; - fw_update->step_size = SB_FW_UPDATE_CMD_WRITE_BLOCK_SIZE; - - state = S0_READ_STATUS; - while (state != S10_TERMINAL) - state = state_table[state](fw_update); - - if (fw_update->fw_img_hdr) - free(fw_update->fw_img_hdr); - - return fw_update->rv; -} - -#define GEC_LOCK_TIMEOUT_SECS 30 /* 30 secs */ -void usage(char *argv[]) -{ - printf("Usage: %s [check|update]\n" - " check: check if AC Adaptor is connected.\n" - " update: trigger battery firmware update.\n", - argv[0]); -} - -int main(int argc, char *argv[]) -{ - int rv = 0; - int op = OP_UNKNOWN; - uint8_t val = 0; - - if (argc != 2) { - usage(argv); - return -1; - } - - if (!strcmp(argv[1], "check")) - op = OP_CHECK; - else if (!strcmp(argv[1], "update")) - op = OP_UPDATE; - else { - op = OP_UNKNOWN; - usage(argv); - return -1; - } - - if (comm_init_dev(NULL)) { - printf("Couldn't initialize /dev.\n"); - return -1; - } - - if (comm_init_buffer()) { - fprintf(stderr, "Couldn't initialize buffers\n"); - return -1; - } - - fw_update.flags = 0; - rv = ec_readmem(EC_MEMMAP_BATT_FLAG, sizeof(val), &val); - if (rv <= 0) { - printf("EC Memmap read error:%d\n", rv); - goto out; - } - - rv = get_status(&fw_update.status); - if (rv) { - fw_update.rv = -1; - log_msg(&fw_update, S1_READ_INFO, "Interface Error"); - return S10_TERMINAL; - } - - if (fw_update.status.fw_update_mode) { - /* - * Previous battery firmware update was interrupted, - * and we may not detect the presence of AC correctly. - * Therefore, lie about our AC status. - */ - fw_update.flags |= F_AC_PRESENT; - printf("Assuming AC_PRESENT due to interrupted FW update\n"); - } else { - if (val & EC_BATT_FLAG_AC_PRESENT) { - fw_update.flags |= F_AC_PRESENT; - printf("AC_PRESENT\n"); - } - } - - if (val & EC_BATT_FLAG_DISCHARGING) { - fw_update.flags |= F_BATT_DISCHARGE; - printf("Battery is in discharge state\n"); - } - rv = ec_readmem(EC_MEMMAP_BATT_LFCC, sizeof(val), &val); - if (rv <= 0) { - printf("EC Memmap read error:%d\n", rv); - goto out; - } - if (val == 0) - fw_update.flags |= F_LFCC_ZERO; - - if (op == OP_UPDATE) - fw_update.flags |= F_UPDATE; - - fw_update.flags |= F_VERSION_CHECK; - - rv = ec_sb_firmware_update(&fw_update); - printf("Battery Firmware Update:0x%02x %s\n%s\n", - fw_update.flags, - ((rv) ? "FAIL " : " "), - fw_update.msg); - - /* Update battery firmware update interface to be protected */ - if (!(fw_update.flags & F_NEED_UPDATE)) - rv |= send_subcmd(EC_SB_FW_UPDATE_PROTECT); - - if (fw_update.flags & F_POWERD_DISABLED) - rv |= restore_power_management(); -out: - if (rv) - return -1; - else - return fw_update.flags & (F_LFCC_ZERO | F_NEED_UPDATE); -} diff --git a/util/ec_sb_firmware_update.h b/util/ec_sb_firmware_update.h deleted file mode 100644 index 5bddebaf4a..0000000000 --- a/util/ec_sb_firmware_update.h +++ /dev/null @@ -1,126 +0,0 @@ -/* Copyright 2014 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. - * - * Smart battery Firmware Update driver. - * Ref: Common Smart Battery System Interface Specification v8.0. - * - * cmd.0x35, Write Word - * 0x1000: Prepare to Update - * 0x2000: End of Update - * 0xF000: Update Firmware - * - * cmd.0x35, Read Word - * Firmware Update Status - * - * cmd.0x36 Write Block - * Send 32 byte firmware image - * - * cmd.0x37 Read Word - * Get Battery Information - * sequence:=b1,b0,b3,b2,b5,b5,b7,b6 - * - * Command Sequence for Battery FW Update - * - * 0. cmd.0x35.read - * 1. cmd.0x37.read - * 2. cmd.0x35.write.0x1000 - * 3. cmd.0x35.read.status (optional) - * 4. cmd.0x35.write.0xF000 - * 5. cmd.0x35.read.status - * if bit8-0, go to step 2 - * 6. cmd.0x36.write.32byte - * 7. cmd.0x35.read.status - * if FEC.b13=1, go to step 6 - * if fatal.b12=1, go to step 2 - * if b11,b10,b9,b2,b1,b0; go to step 1 - * if b5,b3; go to step 8 - * (repeat 6,7) - * 8. cmd.0x36.write.0x2000 - * 9. cmd.0x35.read.status - */ - -#ifndef __UTIL_EC_SB_FIRMWARE_UPDATE_H -#define __UTIL_EC_SB_FIRMWARE_UPDATE_H - -struct sb_fw_header { - uint8_t signature[4]; /* "BTFW" */ - uint16_t hdr_version; /* 0x0100 */ - uint16_t pkg_version_major_minor; - - uint16_t vendor_id; /* 8,9 */ - uint16_t battery_type; /* A B */ - - uint16_t fw_version; /* C D */ - uint16_t data_table_version; /* E F */ - uint32_t fw_binary_offset; /*0x10 0x11 0x12 0x13 */ - uint32_t fw_binary_size; /* 0x14 0x15 0x16 0x17 */ - uint8_t checksum; /* 0x18 */ -}; - -/** - * sb.fw.update.cmd.0x35, Read Word - * Firmware Update Status - */ -struct sb_fw_update_status { - uint16_t v_fail_maker_id:1; /* b0 */ - uint16_t v_fail_hw_id:1; /* b1 */ - uint16_t v_fail_fw_version:1; /* b2 */ - uint16_t v_fail_permanent:1; /* b3 */ - - uint16_t rsvd5:1; /* b4 */ - uint16_t permanent_failure:1; /* b5 */ - uint16_t abnormal_condition:1; /* b6 */ - uint16_t fw_update_supported:1; /* b7 */ - - uint16_t fw_update_mode:1; /* b8 */ - uint16_t fw_corrupted:1; /* b9 */ - uint16_t cmd_reject:1; /* b10 */ - uint16_t invalid_data:1; /* b11 */ - - uint16_t fw_fatal_error:1; /* b12 */ - uint16_t fec_error:1; /* b13 */ - uint16_t busy:1; /* b14 */ - uint16_t rsvd15:1; /* b15 */ -} __packed; - -/** - * sb.fw.update.cmd.0x37 Read Word - * Get Battery Information - * sequence:=b1,b0,b3,b2,b5,b5,b7,b6 - */ -struct sb_fw_update_info { - uint16_t maker_id; /* b0, b1 */ - uint16_t hardware_id; /* b2, b3 */ - uint16_t fw_version; /* b4, b5 */ - uint16_t data_version;/* b6, b7 */ -} __packed; - -/** - * smart.battery.maker.id - */ -enum sb_maker_id { - sb_maker_id_lgc = 0x0001, /* b0=0; b1=1 */ - sb_maker_id_panasonic = 0x0002, - sb_maker_id_sanyo = 0x0003, - sb_maker_id_sony = 0x0004, - sb_maker_id_simplo = 0x0005, - sb_maker_id_celxpert = 0x0006, -}; - -/* - * Ref: Common Smart Battery System Interface Specification v8.0 page 21-24. - * case 1. If permanent error:b5,b3, go to setp8. - * case 2. If error:b11,b10,b9 b2,b1,b0, go to step1. Retry < 3 times. - * case 3. If firmware update fatal error:b12, go to step2. Retry < 3 times. - * In order to simply the implementation, I merged case 2 and 3. - * If firmware update fatal error:b12, go to step1 as well. - * case 4. If error.FEC.b13=1, go to step6. Retry < 3 times. - * case 5. If battery interface is busy, retry < 10 times. - * Delay 1 second between retries. - */ -#define SB_FW_UPDATE_ERROR_RETRY_CNT 2 -#define SB_FW_UPDATE_FEC_ERROR_RETRY_CNT 2 -#define SB_FW_UPDATE_BUSY_ERROR_RETRY_CNT 4 - -#endif diff --git a/util/ec_uartd.c b/util/ec_uartd.c deleted file mode 100644 index 4fc0323619..0000000000 --- a/util/ec_uartd.c +++ /dev/null @@ -1,159 +0,0 @@ -/* Copyright 2011 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. - */ -/* ec_uartd.c - UART daemon for BD-ICDI-B board for EC debugging - * - * based on chromeos_public/src/third_party/hdctools/src/ftdiuart.c - * - * compile with: - * gcc -o ftdi_uartd ftdi_uartd.c -lftdi - */ - -/* Force header files to define grantpt(), posix_openpt(), cfmakeraw() */ -#define _DEFAULT_SOURCE /* Newer glibc */ -#define _BSD_SOURCE /* Older glibc */ -#define _XOPEN_SOURCE 600 -/* Force header file to declare ptsname_r(), etc. */ -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static const int ftdi_id[][2] = { {0x0403, 0xbcda}, - {0x0403, 0xbcd9} }; - -int main(int argc, char **argv) -{ - struct ftdi_context fcontext; - struct termios tty_cfg; - char ptname[PATH_MAX]; - char buf[1024]; - int fd; - int rv; - int i; - int device_opened; - - /* Init */ - if (ftdi_init(&fcontext) < 0) { - fprintf(stderr, "ftdi_init failed\n"); - return 1; - } - - /* Open interface B (UART) in the FTDI device and set 115kbaud */ - ftdi_set_interface(&fcontext, INTERFACE_B); - device_opened = 0; - for (i = 0; i < sizeof(ftdi_id) / sizeof(ftdi_id[0]); ++i) { - rv = ftdi_usb_open(&fcontext, ftdi_id[i][0], ftdi_id[i][1]); - if (rv >= 0) { - fprintf(stderr, "Using FTDI device %04x:%04x\n", - ftdi_id[i][0], ftdi_id[i][1]); - device_opened = 1; - break; - } - } - if (!device_opened) { - fprintf(stderr, "error opening ftdi device: %d (%s)\n", - rv, ftdi_get_error_string(&fcontext)); - return 2; - } - - rv = ftdi_set_baudrate(&fcontext, 115200); - if (rv < 0) { - fprintf(stderr, "error setting baudrate: %d (%s)\n", - rv, ftdi_get_error_string(&fcontext)); - return 2; - } - - /* Set DTR; this muxes RX on the ICDI board */ - ftdi_setdtr(&fcontext, 1); - - /* Open the pty */ - fd = posix_openpt(O_RDWR | O_NOCTTY); - if (fd == -1) { - perror("opening pty master"); - return 3; - } - if (grantpt(fd) == -1) { - perror("grantpt"); - return 3; - } - if (unlockpt(fd) == -1) { - perror("unlockpt"); - return 3; - } - if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1) { - perror("fcntl setfl -> nonblock"); - return 3; - } - if (ptsname_r(fd, ptname, PATH_MAX) != 0) { - perror("getting name of pty"); - return 3; - } - fprintf(stderr, "pty name = %s\n", ptname); - if (!isatty(fd)) { - perror("not a TTY device\n"); - return 3; - } - cfmakeraw(&tty_cfg); - tcsetattr(fd, TCSANOW, &tty_cfg); - if (chmod(ptname, 0666) == -1) { - perror("setting pty attributes"); - return 3; - } - - /* Read and write data forever */ - while (1) { - int bytes = read(fd, buf, sizeof(buf)); - if (bytes > 0) { - rv = ftdi_write_data(&fcontext, buf, bytes); - if (rv != bytes) { - perror("writing to uart"); - break; - } - } - - usleep(1000); - - bytes = ftdi_read_data(&fcontext, buf, sizeof(buf)); - if (bytes > 0) { - int bytes_remaining = bytes; - char *buf_ptr = buf; - -retry_write: - while (bytes_remaining && - ((bytes = write(fd, buf_ptr, - bytes_remaining)) > 0)) { - buf_ptr += bytes; - bytes_remaining -= bytes; - } - - if ((bytes == -1) && - ((errno == EAGAIN) || (errno == EWOULDBLOCK))) - goto retry_write; - - if (bytes == -1) - perror("writing ftdi data to pty"); - - } else if (bytes < 0) { - perror("failed ftdi_read_data"); - break; - } - } - - /* Cleanup */ - close(fd); - ftdi_usb_close(&fcontext); - ftdi_deinit(&fcontext); - return 0; -} diff --git a/util/ecst.c b/util/ecst.c deleted file mode 100644 index 22f9f6c0e8..0000000000 --- a/util/ecst.c +++ /dev/null @@ -1,2519 +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. - */ - -/* - * This utility is used to generate/modify the firmware header which holds - * data used by NPCX ROM code (booter). - */ - -#include "ecst.h" - -/* Global Variables */ -enum verbose_level g_verbose; -char input_file_name[NAME_SIZE]; -char output_file_name[NAME_SIZE]; -char arg_file_name[NAME_SIZE]; -char g_hdr_input_name[NAME_SIZE]; -char hdr_args[MAX_ARGS][ARG_SIZE]; -char tmp_hdr_args[MAX_ARGS][ARG_SIZE]; -FILE *input_file_pointer; -FILE *g_hfd_pointer; -FILE *arg_file_pointer; -FILE *api_file_pointer; -FILE *g_hdr_pointer; -void *gh_console; -unsigned short g_text_atrib; -unsigned short g_bg_atrib; -enum calc_type g_calc_type; -unsigned int ptr_fw_addr; -unsigned int fw_offset; -int is_ptr_merge; -unsigned int g_ram_start_address; -unsigned int g_ram_size; -int api_file_size_bytes; -int is_mrider15 = FALSE; - -/* Chips information, RAM start address and RAM size. */ -struct chip_info chip_info[] = {{NPCX5M5G_RAM_ADDR, NPCX5M5G_RAM_SIZE}, - {NPCX5M6G_RAM_ADDR, NPCX5M6G_RAM_SIZE}, - {NPCX7M5X_RAM_ADDR, NPCX7M5X_RAM_SIZE}, - {NPCX7M6X_RAM_ADDR, NPCX7M6X_RAM_SIZE}, - {NPCX7M7X_RAM_ADDR, NPCX7M7X_RAM_SIZE},}; - -/* Support chips name strings */ -const char *supported_chips = "npcx5m5g, npcx5m6g, npcx7m5g, npcx7m6g, " - "npcx7m6f, npcx7m6fb, npcx7m6fc, npcx7m7wb, or npcx7m7wc"; - -static unsigned int calc_api_csum_bin(void); -static unsigned int initialize_crc_32(void); -static unsigned int update_crc_32(unsigned int crc, char c); -static unsigned int finalize_crc_32(unsigned int crc); - -/* - * Expects a path in `path`, returning a transformation as follows in `result` - * - * The last element of `path` is prefixed with `prefix` if the resulting - * string fits in an array of `resultsz` characters (incl 0-termination). - * - * On success returns TRUE, - * on error (path too long) prints an error on the TERR channel - * and returns FALSE. - */ -static int splice_into_path(char *result, const char *path, int resultsz, - const char *prefix) { - char *last_delim, *result_last_delim; - - if (strlen(path) + strlen(prefix) + 1 > resultsz) { - my_printf(TERR, - "\n\nfilename '%s' with prefix '%s' too long\n\n", - path, prefix); - my_printf(TINF, - "\n\n%zu + %zu + 1 needs to fit in %d bytes\n\n", - strlen(path), strlen(prefix), resultsz); - return FALSE; - } - - last_delim = strrchr(path, '/'); - - if (last_delim == NULL) { - /* no delimiter: prefix and exit */ - sprintf(result, "%s%s", prefix, path); - return TRUE; - } - - /* delimiter: copy, then patch in the prefix */ - strcpy(result, path); - result_last_delim = result + (last_delim - path); - sprintf(result_last_delim + 1, "%s%s", prefix, last_delim + 1); - return TRUE; -} - -/* - *---------------------------------------------------------------------- - * Function: main() - * Parameters: argc, argv - * Return: 0 - * Description: Parse the arguments - * Chose manipulation routine according to arguments - * - * In case of bin, save optional parameters given by user - *---------------------------------------------------------------------- - */ -int main(int argc, char *argv[]) - -{ - - int mode_choose = FALSE; - /* Do we get a bin File? */ - int main_fw_hdr_flag = FALSE; - /* Do we get a API bin File? */ - int main_api_flag = FALSE; - /* Do we need to create a BootLoader Header file? */ - int main_hdr_flag = FALSE; - - /* Following variables: common to all modes */ - int main_status = TRUE; - unsigned int main_temp = 0L; - char main_str_temp[TMP_STR_SIZE]; - char *end_ptr; - - int arg_num; - int arg_ind; - int tmp_ind; - int tmp_arg_num; - int cur_arg_index; - FILE *tmp_file; - - /* Following variables are used when bin file is provided */ - struct tbinparams bin_params; - - bin_params.bin_params = 0; - - input_file_name[0] = '\0'; - memset(input_file_name, 0, NAME_SIZE); - output_file_name[0] = '\0'; - memset(output_file_name, 0, NAME_SIZE); - arg_file_name[0] = '\0'; - memset(arg_file_name, 0, NAME_SIZE); - g_hdr_input_name[0] = '\0'; - memset(g_hdr_input_name, 0, NAME_SIZE); - - /* Initialize Global variables */ - g_verbose = NO_VERBOSE; - - g_ram_start_address = chip_info[DEFAULT_CHIP].ram_addr; - g_ram_size = chip_info[DEFAULT_CHIP].ram_size; - - /* Set default values */ - g_calc_type = CALC_TYPE_NONE; - bin_params.spi_max_clk = SPI_MAX_CLOCK_DEFAULT; - bin_params.spi_clk_ratio = 0x00; - bin_params.spi_read_mode = SPI_READ_MODE_DEFAULT; - bin_params.fw_load_addr = - chip_info[DEFAULT_CHIP].ram_addr; - bin_params.fw_ep = - chip_info[DEFAULT_CHIP].ram_addr; - bin_params.fw_err_detec_s_addr = FW_CRC_START_ADDR; - bin_params.fw_err_detec_e_addr = FW_CRC_START_ADDR; - bin_params.flash_size = FLASH_SIZE_DEFAULT; - bin_params.fw_hdr_offset = 0; - - ptr_fw_addr = 0x00000000; - fw_offset = 0x00000000; - is_ptr_merge = FALSE; - - /* Get Standard Output Handler */ - - /* Wrong Number of Arguments ? No problem */ - if (argc < 3) - exit_with_usage(); - - /* Read all arguments to local array. */ - for (arg_num = 0; arg_num < argc; arg_num++) - strncpy(hdr_args[arg_num], argv[arg_num], ARG_SIZE); - - /* Loop all arguments. */ - /* Parse the Arguments - supports ecrp and bin */ - for (arg_ind = 1; arg_ind < arg_num; arg_ind++) { - /* -h display help screen */ - if (str_cmp_no_case(hdr_args[arg_ind], "-h") == 0) - exit_with_usage(); - - /* -v verbose */ - else if (str_cmp_no_case(hdr_args[arg_ind], "-v") == 0) - g_verbose = REGULAR_VERBOSE; - - /* Super verbose. */ - else if (str_cmp_no_case(hdr_args[arg_ind], "-vv") == 0) - g_verbose = SUPER_VERBOSE; - - else if (str_cmp_no_case(hdr_args[arg_ind], - "-mode") == 0) { - mode_choose = TRUE; - arg_ind++; - if ((hdr_args[arg_ind] == NULL) || - (sscanf(hdr_args[arg_ind], - "%s", main_str_temp) != 1)) { - my_printf(TERR, "\nCannot read operation mode"); - my_printf(TERR, ", bt, bh or api. !\n"); - main_status = FALSE; - } else { - /* bt, bh and api should not coexist */ - if (main_fw_hdr_flag || - main_api_flag || - main_hdr_flag) { - my_printf(TERR, "\nOperation modes bt"); - my_printf(TERR, ", bh, and api should"); - my_printf(TERR, " not coexist.\n"); - main_status = FALSE; - } - - if (str_cmp_no_case(main_str_temp, "bt") == 0) - main_fw_hdr_flag = TRUE; - else if (str_cmp_no_case(main_str_temp, - "bh") == 0) - main_hdr_flag = TRUE; - else if (str_cmp_no_case(main_str_temp, - "api") == 0) - main_api_flag = TRUE; - else { - my_printf(TERR, - "\nInvalid operation mode "); - my_printf(TERR, - "(%s)\n", main_str_temp); - main_status = FALSE; - } - } - } - - else if (str_cmp_no_case(hdr_args[arg_ind], "-chip") == 0) { - arg_ind++; - if ((hdr_args[arg_ind] == NULL) || - (sscanf(hdr_args[arg_ind], - "%s", - main_str_temp) != 1)) { - my_printf(TERR, "\nCannot read chip name %s.\n", - supported_chips); - main_status = FALSE; - } else { - if ((str_cmp_no_case(main_str_temp, - "npcx7m7wb") == 0) || - (str_cmp_no_case(main_str_temp, - "npcx7m7wc") == 0)) { - if ((bin_params.bin_params - & BIN_FW_LOAD_START_ADDR) == - 0x00000000) - bin_params.fw_load_addr = - chip_info[NPCX7M7].ram_addr; - - if ((bin_params.bin_params - & BIN_FW_ENTRY_POINT) == - 0x00000000) - bin_params.fw_ep = - chip_info[NPCX7M7].ram_addr; - - g_ram_start_address = - chip_info[NPCX7M7].ram_addr; - g_ram_size = - chip_info[NPCX7M7].ram_size; - } else if ((str_cmp_no_case(main_str_temp, - "npcx7m6f") == 0) || - (str_cmp_no_case(main_str_temp, - "npcx7m6fb") == 0) || - (str_cmp_no_case(main_str_temp, - "npcx7m6fc") == 0) || - (str_cmp_no_case(main_str_temp, - "npcx7m6g") == 0)) { - if ((bin_params.bin_params - & BIN_FW_LOAD_START_ADDR) == - 0x00000000) - bin_params.fw_load_addr = - chip_info[NPCX7M6].ram_addr; - - if ((bin_params.bin_params & - BIN_FW_ENTRY_POINT) == - 0x00000000) - bin_params.fw_ep = - chip_info[NPCX7M6].ram_addr; - - g_ram_start_address = - chip_info[NPCX7M6].ram_addr; - g_ram_size = - chip_info[NPCX7M6].ram_size; - } else if (str_cmp_no_case(main_str_temp, - "npcx7m5g") == 0) { - if ((bin_params.bin_params - & BIN_FW_LOAD_START_ADDR) == - 0x00000000) - bin_params.fw_load_addr = - chip_info[NPCX7M5].ram_addr; - - if ((bin_params.bin_params & - BIN_FW_ENTRY_POINT) == - 0x00000000) - bin_params.fw_ep = - chip_info[NPCX7M5].ram_addr; - - g_ram_start_address = - chip_info[NPCX7M5].ram_addr; - g_ram_size = - chip_info[NPCX7M5].ram_size; - } else if (str_cmp_no_case(main_str_temp, - "npcx5m5g") == 0) { - if ((bin_params.bin_params - & BIN_FW_LOAD_START_ADDR) == - 0x00000000) - bin_params.fw_load_addr = - chip_info[NPCX5M5G].ram_addr; - - if ((bin_params.bin_params & - BIN_FW_ENTRY_POINT) == 0x00000000) - bin_params.fw_ep = - chip_info[NPCX5M5G].ram_addr; - - g_ram_start_address = - chip_info[NPCX5M5G].ram_addr; - g_ram_size = - chip_info[NPCX5M5G].ram_size; - - is_mrider15 = TRUE; - - } else if (str_cmp_no_case(main_str_temp, - "npcx5m6g") == 0) { - if ((bin_params.bin_params & - BIN_FW_LOAD_START_ADDR) == - 0x00000000) - bin_params.fw_load_addr = - chip_info[NPCX5M6G].ram_addr; - - if ((bin_params.bin_params & - BIN_FW_ENTRY_POINT) == - 0x00000000) - bin_params.fw_ep = - chip_info[NPCX5M6G].ram_addr; - - g_ram_start_address = - chip_info[NPCX5M6G].ram_addr; - g_ram_size = - chip_info[NPCX5M6G].ram_size; - - is_mrider15 = TRUE; - - } else { - my_printf(TERR, - "\nInvalid chip name (%s) ", - main_str_temp); - my_printf(TERR, ", it should be %s.\n", - supported_chips); - main_status = FALSE; - } - - } - /* -argfile Read argument file. File name must be after it.*/ - } else if (str_cmp_no_case(hdr_args[arg_ind], - "-argfile") == 0) { - arg_ind++; - if (arg_ind < arg_num) { - strncpy(arg_file_name, - hdr_args[arg_ind], - sizeof(arg_file_name) - 1); - arg_file_pointer = fopen(arg_file_name, "rt"); - if (arg_file_pointer == NULL) { - my_printf(TERR, - "\n\nCannot open %s\n\n", - arg_file_name); - main_status = FALSE; - } else { - cur_arg_index = arg_ind; - - /* Copy the arguments to temp array. */ - for (tmp_ind = 0; - (tmp_ind + arg_ind + 1) < arg_num; - tmp_ind++) - strncpy(tmp_hdr_args[tmp_ind], - hdr_args - [tmp_ind+arg_ind+1], - ARG_SIZE); - - tmp_arg_num = tmp_ind; - - /* Read arguments from file to array */ - for (arg_ind++; - fscanf(arg_file_pointer, - "%s", - hdr_args[arg_ind]) == 1; - arg_ind++) - ; - - fclose(arg_file_pointer); - arg_file_pointer = NULL; - - /* Copy back the restored arguments. */ - for (tmp_ind = 0; - tmp_ind < tmp_arg_num; - tmp_ind++) { - strncpy(hdr_args[arg_ind++], - tmp_hdr_args[tmp_ind], - ARG_SIZE); - } - arg_num = arg_ind; - arg_ind = cur_arg_index; - } - - } else { - my_printf(TERR, - "\nMissing Argument File Name\n"); - main_status = FALSE; - } - /* -i get input file name. */ - } else if (str_cmp_no_case(hdr_args[arg_ind], "-i") == 0) { - arg_ind++; - if (arg_ind < arg_num) { - strncpy(input_file_name, - hdr_args[arg_ind], - sizeof(input_file_name) - 1); - } else { - my_printf(TERR, "\nMissing Input File Name\n"); - main_status = FALSE; - } - /* -o Get output file name. */ - } else if (str_cmp_no_case(hdr_args[arg_ind], "-o") == 0) { - arg_ind++; - if (arg_ind < arg_num) { - strncpy(output_file_name, - hdr_args[arg_ind], - sizeof(output_file_name) - 1); - } else { - my_printf(TERR, - "\nMissing Output File Name.\n"); - main_status = FALSE; - } - /* -usearmrst get FW entry point from FW image offset 4.*/ - } else if (str_cmp_no_case(hdr_args[arg_ind], - "-usearmrst") == 0) { - if ((bin_params.bin_params & - BIN_FW_ENTRY_POINT) != 0x00000000) { - my_printf(TERR, "\n-usearmrst not allowed, "); - my_printf(TERR, "FW entry point already set "); - my_printf(TERR, "using -fwep !\n"); - main_status = FALSE; - } else - bin_params.bin_params |= - BIN_FW_USER_ARM_RESET; - /* -nohcrs disable header CRC*/ - } else if (str_cmp_no_case(hdr_args[arg_ind], "-nohcrc") == 0) - bin_params.bin_params |= - BIN_FW_HDR_CRC_DISABLE; - /* -ph merg header in BIN file. */ - else if (str_cmp_no_case(hdr_args[arg_ind], "-ph") == 0) { - bin_params.bin_params |= - BIN_FW_HDR_OFFSET; - if ((strlen(hdr_args[arg_ind+1]) == 0) || - (sscanf(hdr_args[arg_ind+1], - "%x", - &main_temp) != 1)) - bin_params.fw_hdr_offset = 0; - else { - arg_ind++; - bin_params.fw_hdr_offset = main_temp; - } - /* -spimaxclk Get SPI flash max clock. */ - } else if (str_cmp_no_case(hdr_args[arg_ind], - "-spimaxclk") == 0) { - arg_ind++; - if ((hdr_args[arg_ind] == NULL) || - (sscanf(hdr_args[arg_ind], - "%d", &main_temp) != 1)) { - my_printf(TERR, "\nCannot read SPI Flash Max"); - my_printf(TERR, " Clock !\n"); - main_status = FALSE; - } else - bin_params.spi_max_clk = - (unsigned char) main_temp; - /* -spiclkratio Get SPI flash max clock ratio. */ - } else if (str_cmp_no_case(hdr_args[arg_ind], - "-spiclkratio") == 0) { - arg_ind++; - if ((hdr_args[arg_ind] == NULL) || - (sscanf(hdr_args[arg_ind], - "%d", &main_temp) != 1)) { - my_printf(TERR, - "\nCannot read SPI Clock Ratio\n"); - main_status = FALSE; - } else - bin_params.spi_clk_ratio = - (unsigned char)main_temp; - - /* spireadmode get SPI read mode. */ - } else if (str_cmp_no_case(hdr_args[arg_ind], - "-spireadmode") == 0) { - arg_ind++; - if ((hdr_args[arg_ind] == NULL) || - (sscanf(hdr_args[arg_ind], - "%20s", - main_str_temp) != 1)) { - my_printf(TERR, "\nCannot read SPI Flash"); - my_printf(TERR, " Read Mode !\n"); - main_status = FALSE; - } else { - if (str_cmp_no_case(main_str_temp, - SPI_NORMAL_MODE_VAL) == 0) - bin_params.spi_read_mode = - (unsigned char) SPI_NORMAL_MODE; - else if (str_cmp_no_case(main_str_temp, - SPI_SINGLE_MODE_VAL) == 0) - bin_params.spi_read_mode = - (unsigned char) - SPI_SINGLE_MODE; - else if (str_cmp_no_case(main_str_temp, - SPI_DUAL_MODE_VAL) == 0) - bin_params.spi_read_mode = - (unsigned char) - SPI_DUAL_MODE; - else if (str_cmp_no_case(main_str_temp, - SPI_QUAD_MODE_VAL) == 0) - bin_params.spi_read_mode = - (unsigned char) - SPI_QUAD_MODE; - else { - my_printf(TERR, - "\nInvalid SPI Flash Read "); - my_printf(TERR, - "Mode (%s), it should be ", - main_str_temp); - my_printf(TERR, - "normal, singleMode, "); - my_printf(TERR, - "dualMode or quadMode !\n"); - main_status = FALSE; - } - } - - } - /* -unlimburst enable unlimited burst */ - else if (str_cmp_no_case(hdr_args[arg_ind], "-unlimburst") == 0) - bin_params.bin_params |= BIN_UNLIM_BURST_ENABLE; - /* -nofcrc disable FW CRC. */ - else if (str_cmp_no_case(hdr_args[arg_ind], "-nofcrc") == 0) - bin_params.bin_params |= BIN_FW_CRC_DISABLE; - - /* -fwloadaddr, Get the FW load address. */ - else if (str_cmp_no_case(hdr_args[arg_ind], - "-fwloadaddr") == 0) { - arg_ind++; - if ((hdr_args[arg_ind] == NULL) || - (sscanf(hdr_args[arg_ind], - "%x", - &main_temp) != 1)) { - my_printf(TERR, "\nCannot read FW Load "); - my_printf(TERR, "\nstart address !\n"); - main_status = FALSE; - } else { - /* Check that the address is 16-bytes aligned */ - if ((main_temp & - ADDR_16_BYTES_ALIGNED_MASK) != 0) { - my_printf(TERR, - "\nFW load address start "); - my_printf(TERR, - "address (0x%08X) is not ", - main_temp); - my_printf(TERR, - "16-bytes aligned !\n"); - main_status = FALSE; - } else { - bin_params.fw_load_addr = - main_temp; - bin_params.bin_params |= - BIN_FW_LOAD_START_ADDR; - } - } - /* -fwep, Get the FW entry point. */ - } else if (str_cmp_no_case(hdr_args[arg_ind], "-fwep") == 0) { - if ((bin_params.bin_params & BIN_FW_USER_ARM_RESET) - != 0x00000000) { - my_printf(TERR, - "\n-fwep not allowed, FW entry point"); - my_printf(TERR, - " already set using -usearmrst!\n"); - main_status = FALSE; - } else { - arg_ind++; - if ((hdr_args[arg_ind] == NULL) || - (sscanf(hdr_args[arg_ind], - "%x", - &main_temp) != 1)) { - my_printf(TERR, - "\nCan't read FW E-Point\n"); - main_status = FALSE; - } else { - bin_params.fw_ep = - main_temp; - bin_params.bin_params |= - BIN_FW_ENTRY_POINT; - } - } - /* - * -crcstart, Get the address from where to calculate - * the FW CRC. - */ - } else if (str_cmp_no_case(hdr_args[arg_ind], - "-crcstart") == 0) { - arg_ind++; - if ((hdr_args[arg_ind] == NULL) || - (sscanf(hdr_args[arg_ind], - "%x", - &main_temp) != 1)) { - my_printf(TERR, - "\nCannot read FW CRC"); - my_printf(TERR, - " start address !\n"); - main_status = FALSE; - } else { - bin_params.fw_err_detec_e_addr = - bin_params.fw_err_detec_e_addr - - bin_params.fw_err_detec_s_addr - + main_temp; - bin_params.fw_err_detec_s_addr = - main_temp; - bin_params.bin_params |= BIN_FW_CKS_START; - } - /* -crcsize, Get the area size that need to be CRCed. */ - } else if (str_cmp_no_case(hdr_args[arg_ind], - "-crcsize") == 0) { - arg_ind++; - main_temp = 0x00; - if (hdr_args[arg_ind] == NULL) - end_ptr = NULL; - else - main_temp = strtol(hdr_args[arg_ind], - &end_ptr, 16); - - if (hdr_args[arg_ind] == end_ptr) { - my_printf(TERR, - "\nCannot read FW CRC area size !\n"); - main_status = FALSE; - } else { - bin_params.fw_err_detec_e_addr = - bin_params.fw_err_detec_s_addr - + main_temp - 1; - bin_params.bin_params |= BIN_FW_CKS_SIZE; - } - } - /* -fwlen, Get the FW length. */ - else if (str_cmp_no_case(hdr_args[arg_ind], "-fwlen") == 0) { - arg_ind++; - if ((hdr_args[arg_ind] == NULL) || - (sscanf(hdr_args[arg_ind], - "%x", - &main_temp) != 1)) { - my_printf(TERR, "\nCannot read FW length !\n"); - main_status = FALSE; - } else { - bin_params.fw_len = main_temp; - bin_params.bin_params |= BIN_FW_LENGTH; - } - } - /* flashsize, Get the flash size. */ - else if (str_cmp_no_case(hdr_args[arg_ind], - "-flashsize") == 0) { - arg_ind++; - if ((hdr_args[arg_ind] == NULL) || - (sscanf(hdr_args[arg_ind], - "%d", - &main_temp) != 1)) { - my_printf(TERR, "\nCannot read Flash size !\n"); - main_status = FALSE; - } else - bin_params.flash_size = main_temp; - /* -apisign, Get the method for error detect calculation. */ - } else if (str_cmp_no_case(hdr_args[arg_ind], - "-apisign") == 0) { - arg_ind++; - if ((hdr_args[arg_ind] == NULL) || - (sscanf(hdr_args[arg_ind], - "%s", - main_str_temp) != 1)) { - my_printf(TERR, "\nCannot read API sign, CRC,"); - my_printf(TERR, " CheckSum or None. !\n"); - main_status = FALSE; - } else { - if (!main_api_flag) { - my_printf(TERR, "\n-apisign is valid "); - my_printf(TERR, "-only with -api.\n"); - main_status = FALSE; - } - - if (str_cmp_no_case(main_str_temp, "crc") == 0) - g_calc_type = CALC_TYPE_CRC; - - else if (str_cmp_no_case(main_str_temp, - "checksum") == 0) - g_calc_type = CALC_TYPE_CHECKSUM; - - else { - my_printf(TERR, - "\nInvalid API sign (%s)\n", - main_str_temp); - main_status = FALSE; - } - - } - /* -pointer, Get the FW image address. */ - } else if (str_cmp_no_case(hdr_args[arg_ind], - "-pointer") == 0) { - arg_ind++; - if ((hdr_args[arg_ind] == NULL) || - (sscanf(hdr_args[arg_ind], - "%x", - &main_temp) != 1)) { - my_printf(TERR, - "\nCannot read FW Image address !\n"); - main_status = FALSE; - } else { - /* Check that the address is 16-bytes aligned */ - if ((main_temp & ADDR_16_BYTES_ALIGNED_MASK) - != 0) { - my_printf(TERR, - "\nFW Image address (0x%08X)" - " isn't 16-bytes aligned !\n", - main_temp); - main_status = FALSE; - } - - if (main_temp > MAX_FLASH_SIZE) { - my_printf(TERR, - "\nPointer address (0x%08X) ", - main_temp); - my_printf(TERR, - "is higher from flash size"); - my_printf(TERR, - " (0x%08X) !\n", - MAX_FLASH_SIZE); - main_status = FALSE; - } else { - ptr_fw_addr = main_temp; - is_ptr_merge = FALSE; - } - } - } - /* -bhoffset, BootLoader Header Offset (BH location in BT). */ - else if (str_cmp_no_case(hdr_args[arg_ind], "-bhoffset") == 0) { - arg_ind++; - main_temp = 0x00; - if (hdr_args[arg_ind] == NULL) - end_ptr = NULL; - else - main_temp = strtol(hdr_args[arg_ind], - &end_ptr, 16); - - if (hdr_args[arg_ind] == end_ptr) { - my_printf(TERR, "\nCannot read BootLoader"); - my_printf(TERR, " Header Offset !\n"); - main_status = FALSE; - } else { - /* Check that the address is 16-bytes aligned */ - if ((main_temp & ADDR_16_BYTES_ALIGNED_MASK) - != 0) { - my_printf(TERR, - "\nFW Image address (0x%08X) ", - main_temp); - my_printf(TERR, - "is not 16-bytes aligned!\n"); - } - - if (main_temp > MAX_FLASH_SIZE) { - my_printf(TERR, - "\nFW Image address (0x%08X)", - main_temp); - my_printf(TERR, - " is higher from flash size"); - my_printf(TERR, - " (0x%08X) !\n", - MAX_FLASH_SIZE); - main_status = FALSE; - } else { - fw_offset = main_temp; - is_ptr_merge = TRUE; - } - } - } else { - my_printf(TERR, - "\nUnknown flag: %s\n", - hdr_args[arg_ind]); - main_status = FALSE; - } - } - - /* - * If the input and output file have the same name then exit with error. - */ - if (strcmp(output_file_name, input_file_name) == 0) { - my_printf(TINF, - "Input file name (%s) should be differed from\n", - input_file_name); - my_printf(TINF, "Output file name (%s).\n", output_file_name); - main_status = FALSE; - } - - /* No problems reading argv? So go on... */ - if (main_status) { - - /* if output file already exist, then delete it. */ - tmp_file = fopen(output_file_name, "w"); - if (tmp_file != NULL) - fclose(tmp_file); - - /* If no mode choose than "bt" is the default mode.*/ - if (mode_choose == FALSE) - main_fw_hdr_flag = TRUE; - - /* Chose manipulation routine according to arguments */ - if (main_fw_hdr_flag) - main_status = main_bin(bin_params); - else if (main_api_flag) - main_status = main_api(); - else if (main_hdr_flag) - main_status = main_hdr(); - else - exit_with_usage(); - } - - /* Be sure there's no open file before you leave */ - if (input_file_pointer) - fclose(input_file_pointer); - if (g_hfd_pointer) - fclose(g_hfd_pointer); - if (api_file_pointer) - fclose(api_file_pointer); - - /* Delete temprary header file. */ - remove(g_hdr_input_name); - - /* Say Bye Bye */ - if (main_status) { - my_printf(TPAS, "\n\n******************************"); - my_printf(TPAS, "\n*** SUCCESS ***"); - my_printf(TPAS, "\n******************************\n"); - - exit(EXIT_SUCCESS); - } else { - my_printf(TERR, "\n\n******************************"); - my_printf(TERR, "\n*** FAILED ***"); - my_printf(TERR, "\n******************************\n"); - - exit(EXIT_FAILURE); - } - -} - -/* - *----------------------------------------------------------------------- - * Function: exit_with_usage() - * Parameters: none - * Return: none - * Description: No Words... - *----------------------------------------------------------------------- - */ -void exit_with_usage(void) -{ - my_printf(TUSG, - "\nECST, Embedded Controller Sign Tool, version %d.%d.%d", - T_VER, T_REV_MAJOR, T_REV_MINOR); - my_printf(TUSG, "\n"); - my_printf(TUSG, "\nUsage:"); - my_printf(TUSG, "\n "); - my_printf(TUSG, "\n ECST -mode -i [Flags]"); - my_printf(TUSG, "\n "); - my_printf(TUSG, "\nOperation Modes: "); - my_printf(TUSG, "\n bt - BootLoader Table"); - my_printf(TUSG, "\n bh - BootLoader Header"); - my_printf(TUSG, "\n api - Download from Flash API"); - my_printf(TUSG, "\n "); - my_printf(TUSG, "\nCommon flags:"); - my_printf(TUSG, "\n -mode - Operation mode: "); - my_printf(TUSG, "bt|bh|api (default is bt)"); - my_printf(TUSG, "\n -i - Input file name; "); - my_printf(TUSG, "must differ from the output file name"); - my_printf(TUSG, "\n -o - Output file name "); - my_printf(TUSG, "(default is out_.bin)"); - my_printf(TUSG, "\n -argfile - Arguments file name; "); - my_printf(TUSG, "includes multiple flags"); - my_printf(TUSG, "\n -chip - Supported EC Chip Name: "); - my_printf(TUSG, "%s. ", supported_chips); - my_printf(TUSG, "(default is npcx5m5g)"); - my_printf(TUSG, "\n -v - Verbose; prints "); - my_printf(TUSG, "information messages"); - my_printf(TUSG, "\n -vv - Super Verbose; prints "); - my_printf(TUSG, "intermediate calculations"); - my_printf(TUSG, "\n -h - Show this help screen"); - my_printf(TUSG, "\n "); - my_printf(TUSG, "\nBootLoader Table mode flags:"); - my_printf(TUSG, "\n -nohcrc - Disable CRC on header "); - my_printf(TUSG, "(default is ON)"); - my_printf(TUSG, "\n -nofcrc - Disable CRC on firmware "); - my_printf(TUSG, "(default is ON)"); - my_printf(TUSG, "\n -spimaxclk - SPI Flash Maximum Clock, in"); - my_printf(TUSG, " MHz: 20|25|33|40|50 (default is 20)"); - my_printf(TUSG, "\n -spiclkratio - Core Clock / SPI Flash "); - my_printf(TUSG, "Clocks Ratio: 1 | 2 (default is 1)"); - my_printf(TUSG, "\n "); - my_printf(TUSG, "Note: Not relevant for npcx5mng chips family"); - my_printf(TUSG, "\n -spireadmode - SPI Flash Read Mode: "); - my_printf(TUSG, "normal|fast|dual|quad (default is normal)"); - my_printf(TUSG, "\n -unlimburst - Enable FIU Unlimited "); - my_printf(TUSG, "\n "); - my_printf(TUSG, "Note: Not relevant for npcx5mng chips family"); - my_printf(TUSG, "Burst for SPI Flash Accesses (default is disable)."); - my_printf(TUSG, "\n -fwloadaddr - Firmware load start "); - my_printf(TUSG, "address (default is Start-of-RAM)"); - my_printf(TUSG, "\n Located in code RAM, "); - my_printf(TUSG, "16-bytes aligned, hex format"); - my_printf(TUSG, "\n -usearmrst - Use the ARM reset table "); - my_printf(TUSG, "entry as the Firmware Entry Point"); - my_printf(TUSG, "\n Can't be used with -fwep"); - my_printf(TUSG, "\n -fwep - Firmware entry "); - my_printf(TUSG, "point (default is Firmware Entry Point)"); - my_printf(TUSG, "\n Located in firmware area,"); - my_printf(TUSG, " hex format"); - my_printf(TUSG, "\n -crcstart - Firmware CRC start offset "); - my_printf(TUSG, "(default is 00000000)"); - my_printf(TUSG, "\n Offset from firmware image,"); - my_printf(TUSG, " 4B-aligned, for partial CRC, hex format"); - my_printf(TUSG, "\n -crcsize - Firmware CRC size "); - my_printf(TUSG, "(default is entire firmware size)"); - my_printf(TUSG, "\n 4B-aligned, for partial "); - my_printf(TUSG, "CRC, hex format"); - my_printf(TUSG, "\n -fwlen - Firmware length, "); - my_printf(TUSG, "16B-aligned, hex format (default is file size)."); - my_printf(TUSG, "\n -flashsize - Flash size, in MB: "); - my_printf(TUSG, "1|2|4|8|16 (default is 16)"); - my_printf(TUSG, "\n -ph - Paste the Firmware "); - my_printf(TUSG, "Header in the input file copy at the selected"); - my_printf(TUSG, "\n offset "); - my_printf(TUSG, "(default is 00000000), hex format."); - my_printf(TUSG, "\n The firmware itself is "); - my_printf(TUSG, "expected to start at offset + 64 bytes."); - my_printf(TUSG, "\n "); - my_printf(TUSG, "\nBootLoader Header mode flags:"); - my_printf(TUSG, "\n -pointer - BootLoader Table location"); - my_printf(TUSG, " in the flash, hex format"); - my_printf(TUSG, "\n -bhoffset - BootLoader Header Offset"); - my_printf(TUSG, " in file, hex format (BH location in BT)"); - my_printf(TUSG, "\n "); - my_printf(TUSG, "\nAPI mode flags:"); - my_printf(TUSG, "\n -apisign - Signature type: "); - my_printf(TUSG, "crc|checksum (default is OFF)"); - my_printf(TUSG, "\n\n"); - - exit(EXIT_FAILURE); -} - -/* - *-------------------------------------------------------------------------- - * Function: copy_file_to_file() - * Parameters: dst_file_name - Destination file name. - * src_file_name - Source file name. - * offset - number of bytes from the origin. - * origin - From where to seek, START, END, or CURRENT of - * file. - * Return: Number of copied bytes - * Description: Copy the source file to the end of the destination file. - *-------------------------------------------------------------------------- - */ -int copy_file_to_file(char *dst_file_name, - char *src_file_name, - int offset, - int origin) -{ - - int index = 0; - int result = 0; - unsigned char local_val; - int src_file_size; - FILE *dst_file; - FILE *src_file; - - /* Open the destination file for append. */ - dst_file = fopen(dst_file_name, "r+b"); - if (dst_file == NULL) { - /* destination file not exist, create it. */ - dst_file = fopen(dst_file_name, "ab"); - if (dst_file == NULL) - return 0; - } - - /* Open the source file for read. */ - src_file = fopen(src_file_name, "rb"); - if (src_file == NULL) { - fclose(dst_file); - return 0; - } - - /* Get the source file length in bytes. */ - src_file_size = get_file_length(src_file); - - /* Point to the end of the destination file, and to the start */ - /* of the source file. */ - if (fseek(dst_file, offset, origin) < 0) - goto out; - if (fseek(src_file, 0, SEEK_SET) < 0) - goto out; - - /* Loop over all destination file and write it to the source file.*/ - for (index = 0; index < src_file_size; index++) { - /* Read byte from source file. */ - result = (int)(fread(&local_val, 1, 1, src_file)); - - /* If byte reading pass than write it to the destination, */ - /* else exit from the reading loop. */ - if (result) { - /* Read pass, so write it to destination file.*/ - result = fwrite(&local_val, 1, 1, dst_file); - if (!result) - /* - * Write failed, - * return with the copied bytes number. - */ - break; - } else - /* Read failed, return with the copied bytes number. */ - break; - } - -out: - /* Close the files. */ - fclose(dst_file); - fclose(src_file); - - /* Copy ended, return with the number of bytes that were copied. */ - return index; -} - -/* - *-------------------------------------------------------------------------- - * Function: my_printf() - * Parameters: as in printf + error level - * Return: none - * Description: No Words... - *-------------------------------------------------------------------------- - */ -void my_printf(int error_level, char *fmt, ...) -{ - va_list argptr; - - if ((g_verbose == NO_VERBOSE) && (error_level == TINF)) - return; - - if ((g_verbose != SUPER_VERBOSE) && (error_level == TDBG)) - return; - - va_start(argptr, fmt); - vprintf(fmt, argptr); - va_end(argptr); -} - -/* - *-------------------------------------------------------------------------- - * Function: write_to_file - * Parameters: TBD - * Return: TRUE on successful write - * Description: Writes to ELF or BIN files - whatever is open - *-------------------------------------------------------------------------- - */ -int write_to_file(unsigned int write_value, - unsigned int offset, - unsigned char num_of_bytes, - char *print_string) -{ - - int result = 0; - int index; - unsigned int localValue4; - unsigned short localValue2; - unsigned char localValue1; - - if (fseek(g_hfd_pointer, offset, SEEK_SET) < 0) - return FALSE; - - switch (num_of_bytes) { - case(1): - localValue1 = (unsigned char)write_value; - result = (int)(fwrite(&localValue1, 1, - 1, g_hfd_pointer)); - break; - case(2): - localValue2 = (unsigned short)write_value; - result = (int)(fwrite(&localValue2, - 2, - 1, - g_hfd_pointer)); - break; - case(4): - localValue4 = write_value; - result = (int)(fwrite(&localValue4, - 4, - 1, - g_hfd_pointer)); - break; - default: - /* Pad the same value N times. */ - localValue1 = (unsigned char)write_value; - for (index = 0; index < num_of_bytes; index++) - result = (int)(fwrite(&localValue1, - 1, - 1, - g_hfd_pointer)); - break; - } - - my_printf(TINF, "\nIn write_to_file - %s", print_string); - - if (result) { - my_printf(TINF, - " - Offset %2d - value 0x%x", - offset, write_value); - } else { - my_printf(TERR, - "\n\nCouldn't write %x to file at %x\n\n", - write_value, offset); - return FALSE; - } - - return TRUE; - -} - -/* - *-------------------------------------------------------------------------- - * Function: read_from_file - * Parameters: TBD - * Return: TRUE on successful read - * Description : Reads from open BIN file - *-------------------------------------------------------------------------- - */ -int read_from_file(unsigned int offset, - unsigned char size_to_read, - unsigned int *read_value, - char *print_string) -{ - int result; - unsigned int localValue4; - unsigned short localValue2; - unsigned char localValue1; - - if (fseek(input_file_pointer, offset, SEEK_SET) < 0) - return FALSE; - - switch (size_to_read) { - case(1): - result = (int)(fread(&localValue1, - 1, - 1, - input_file_pointer)); - *read_value = localValue1; - break; - case(2): - result = (int)(fread(&localValue2, - 2, - 1, - input_file_pointer)); - *read_value = localValue2; - break; - case(4): - result = (int)(fread(&localValue4, - 4, - 1, - input_file_pointer)); - *read_value = localValue4; - break; - default: - my_printf(TERR, "\nIn read_from_file - %s", print_string); - my_printf(TERR, "\n\nInvalid call to read_from_file\n\n"); - return FALSE; - } - - my_printf(TINF, "\nIn read_from_file - %s", print_string); - - if (result) { - my_printf(TINF, - " - Offset %d - value %x", - offset, *read_value); - } else { - my_printf(TERR, - "\n\nCouldn't read from file at %x\n\n", - offset); - return FALSE; - } - - return TRUE; -} - -/* - *-------------------------------------------------------------------------- - * Function: init_calculation - * Parameters: unsigned int check_sum_crc (I\O) - * Return: - * Description: Initialize the variable according to the selected - * calculation - *-------------------------------------------------------------------------- - */ -void init_calculation(unsigned int *check_sum_crc) -{ - switch (g_calc_type) { - case CALC_TYPE_NONE: - case CALC_TYPE_CHECKSUM: - *check_sum_crc = 0; - break; - case CALC_TYPE_CRC: - *check_sum_crc = initialize_crc_32(); - break; - } -} - -/* - *-------------------------------------------------------------------------- - * Function: finalize_calculation - * Parameters: unsigned int check_sum_crc (I\O) - * Return: - * Description: Finalize the variable according to the selected calculation - *-------------------------------------------------------------------------- - */ -void finalize_calculation(unsigned int *check_sum_crc) -{ - switch (g_calc_type) { - case CALC_TYPE_NONE: - case CALC_TYPE_CHECKSUM: - /* Do nothing */ - break; - case CALC_TYPE_CRC: - *check_sum_crc = finalize_crc_32(*check_sum_crc); - break; - } -} - -/*-------------------------------------------------------------------------- - * Function: update_calculation - * Parameters: unsigned int check_sum_crc (I\O) - * unsigned int byte_to_add (I) - * Return: - * Description: Calculate a new checksum\crc with the new byte_to_add - * given the previous checksum\crc - *-------------------------------------------------------------------------- - */ -void update_calculation(unsigned int *check_sum_crc, - unsigned char byte_to_add) -{ - switch (g_calc_type) { - case CALC_TYPE_NONE: - /* Do nothing */ - break; - case CALC_TYPE_CHECKSUM: - *check_sum_crc += byte_to_add; - break; - case CALC_TYPE_CRC: - *check_sum_crc = update_crc_32(*check_sum_crc, byte_to_add); - break; - } -} - -/* - *-------------------------------------------------------------------------- - * Function: str_cmp_no_case - * Parameters: s1, s2: Strings to compare. - * Return: function returns an integer less than, equal to, or - * greater than zero if s1 (or the first n bytes thereof) is - * found, respectively, to be less than, to match, or be - * greater than s2. - * Description: Compare two string without case sensitive. - *-------------------------------------------------------------------------- - */ -int str_cmp_no_case(const char *s1, const char *s2) -{ - return strcasecmp(s1, s2); -} - -/* - *-------------------------------------------------------------------------- - * Function: get_file_length - * Parameters: stream - Pointer to a FILE object - * Return: File length in bytes or -1 on error - * Description: Gets the file length in bytes. - *-------------------------------------------------------------------------- - */ -int get_file_length(FILE *stream) -{ - int current_position; - int file_len; - - /* Store current position. */ - current_position = ftell(stream); - if (current_position < 0) - return -1; - - /* End position of the file is its length. */ - if (fseek(stream, 0, SEEK_END) < 0) - return -1; - file_len = ftell(stream); - - /* Restore the original position. */ - if (fseek(stream, current_position, SEEK_SET) < 0) - return -1; - - /* return file length. */ - return file_len; -} - -/* - *************************************************************************** - * "bt" mode Handler - *************************************************************************** - */ - -/* - *************************************************************************** - * Function: main_bin - * Parameters: TBD - * Return: True for success - * Description: - * TBD - *************************************************************************** - */ -int main_bin(struct tbinparams binary_params) -{ - unsigned int bin_file_size_bytes; - unsigned int bin_fw_offset = 0; - unsigned int tmp_param; - FILE *output_file_pointer; - - /* If input file was not declared, then print error message. */ - if (strlen(input_file_name) == 0) { - my_printf(TERR, "\n\nDefine input file, using -i flag\n\n"); - return FALSE; - } - - /* Open input file */ - input_file_pointer = fopen(input_file_name, "r+b"); - if (input_file_pointer == NULL) { - my_printf(TERR, "\n\nCannot open %s\n\n", input_file_name); - return FALSE; - } - - /* - * Check Binary file size, this file contain the image itself, - * without any header. - */ - bin_file_size_bytes = get_file_length(input_file_pointer); - if (bin_file_size_bytes == 0) { - my_printf(TINF, - "\nBIN Input file name %s is empty (size is %d)\n", - input_file_name, bin_file_size_bytes); - return FALSE; - } - - /* - * If the binary file contains also place for the header, then the FW - * size is the length of the file minus the header length - */ - if ((binary_params.bin_params & BIN_FW_HDR_OFFSET) != 0) - bin_fw_offset = binary_params.fw_hdr_offset + HEADER_SIZE; - - my_printf(TINF, "\nBIN file: %s, size: %d (0x%x) bytes\n", - input_file_name, - bin_file_size_bytes, - bin_file_size_bytes); - - /* Check validity of FW header offset. */ - if (((int)binary_params.fw_hdr_offset < 0) || - (binary_params.fw_hdr_offset > bin_file_size_bytes)) { - my_printf(TERR, - "\nFW header offset 0x%08x (%d) should be in the" - " range of 0 and file size (%d).\n", - binary_params.fw_hdr_offset, - binary_params.fw_hdr_offset, - bin_file_size_bytes); - return FALSE; - } - - /* Create the header file in the same directory as the input file. */ - if (!splice_into_path(g_hdr_input_name, input_file_name, - sizeof(g_hdr_input_name), "hdr_")) - return FALSE; - g_hfd_pointer = fopen(g_hdr_input_name, "w+b"); - if (g_hfd_pointer == NULL) { - my_printf(TERR, "\n\nCannot open %s\n\n", g_hdr_input_name); - return FALSE; - } - - if (strlen(output_file_name) == 0) { - if (!splice_into_path(output_file_name, input_file_name, - sizeof(output_file_name), "out_")) - return FALSE; - } - - my_printf(TINF, "Output file name: %s\n", output_file_name); - - /* - ********************************************************************* - * Set the ANCHOR & Extended-ANCHOR - ********************************************************************* - */ - /* Write the ancore. */ - if (!write_to_file(FW_HDR_ANCHOR, - HDR_ANCHOR_OFFSET, - 4, - "HDR - FW Header ANCHOR ")) - return FALSE; - - /* Write the extended anchor. */ - if (binary_params.bin_params & BIN_FW_HDR_CRC_DISABLE) { - - /* Write the ancore and the extended anchor. */ - if (!write_to_file(FW_HDR_EXT_ANCHOR_DISABLE, - HDR_EXTENDED_ANCHOR_OFFSET, 2, - "HDR - Header EXTENDED ANCHOR ")) - return FALSE; - } else { - /* Write the anchor and the extended anchor. */ - if (!write_to_file(FW_HDR_EXT_ANCHOR_ENABLE, - HDR_EXTENDED_ANCHOR_OFFSET, 2, - "HDR - Header EXTENDED ANCHOR ")) - return FALSE; - } - - /* Write the SPI flash MAX clock. */ - switch (binary_params.spi_max_clk) { - case SPI_MAX_CLOCK_20_MHZ_VAL: - tmp_param = SPI_MAX_CLOCK_20_MHZ; - break; - case SPI_MAX_CLOCK_25_MHZ_VAL: - tmp_param = SPI_MAX_CLOCK_25_MHZ; - break; - case SPI_MAX_CLOCK_33_MHZ_VAL: - tmp_param = SPI_MAX_CLOCK_33_MHZ; - break; - case SPI_MAX_CLOCK_40_MHZ_VAL: - tmp_param = SPI_MAX_CLOCK_40_MHZ; - break; - case SPI_MAX_CLOCK_50_MHZ_VAL: - tmp_param = SPI_MAX_CLOCK_50_MHZ; - break; - default: - my_printf(TERR, "\n\nInvalid SPI Flash MAX clock (%d MHz) ", - binary_params.spi_max_clk); - my_printf(TERR, "- it should be 20, 25, 33, 40 or 50 MHz"); - return FALSE; - } - - /* If SPI clock ratio set for MRIDER15, then it is error. */ - if ((binary_params.spi_clk_ratio != 0x00) && (is_mrider15 == TRUE)) { - - my_printf(TERR, "\nspiclkratio is not relevant for"); - my_printf(TERR, " npcx5mng chips family !\n"); - - return FALSE; - } - - /* - * In case SPIU clock ratio didn't set by the user, - * set it to its default value. - */ - if (binary_params.spi_clk_ratio == 0x00) - binary_params.spi_clk_ratio = SPI_CLOCK_RATIO_1_VAL; - - switch (binary_params.spi_clk_ratio) { - case SPI_CLOCK_RATIO_1_VAL: - tmp_param &= SPI_CLOCK_RATIO_1; - break; - case SPI_CLOCK_RATIO_2_VAL: - tmp_param |= SPI_CLOCK_RATIO_2; - break; - default: - my_printf(TERR, "\n\nInvalid SPI Core Clock Ratio (%d) ", - binary_params.spi_clk_ratio); - my_printf(TERR, "- it should be 1 or 2"); - return FALSE; - } - - if (!write_to_file(tmp_param, HDR_SPI_MAX_CLK_OFFSET, 1, - "HDR - SPI flash MAX Clock ")) - return FALSE; - - /* Write the SPI flash Read Mode. */ - tmp_param = binary_params.spi_read_mode; - /* If needed, set the unlimited burst bit. */ - if (binary_params.bin_params & BIN_UNLIM_BURST_ENABLE) { - if (is_mrider15 == TRUE) { - - my_printf(TERR, "\nunlimburst is not relevant for"); - my_printf(TERR, " npcx5mng chips family !\n"); - - return FALSE; - } - - tmp_param |= SPI_UNLIMITED_BURST_ENABLE; - } - if (!write_to_file(tmp_param, - HDR_SPI_READ_MODE_OFFSET, 1, - "HDR - SPI flash Read Mode ")) - return FALSE; - - /* Write the error detection configuration. */ - if (binary_params.bin_params & BIN_FW_CRC_DISABLE) { - if (!write_to_file(FW_CRC_DISABLE, - HDR_ERR_DETECTION_CONF_OFFSET, - 1, - "HDR - FW CRC Disabled ")) - return FALSE; - } else { - /* Write the ancore and the extended anchor. */ - if (!write_to_file(FW_CRC_ENABLE, - HDR_ERR_DETECTION_CONF_OFFSET, 1, - "HDR - FW CRC Enabled ")) - return FALSE; - } - - /* FW entry point should be between the FW load address and RAM size */ - if ((binary_params.fw_load_addr > - (g_ram_start_address + g_ram_size)) || - (binary_params.fw_load_addr < g_ram_start_address)) { - my_printf(TERR, - "\nFW load address (0x%08x) should be between ", - binary_params.fw_load_addr); - my_printf(TERR, - "start (0x%08x) and end (0x%08x) of RAM ).", - g_ram_start_address, - (g_ram_start_address + g_ram_size)); - - return FALSE; - } - - /* Write the FW load start address */ - if (!write_to_file(binary_params.fw_load_addr, - HDR_FW_LOAD_START_ADDR_OFFSET, 4, - "HDR - FW load start address ")) - return FALSE; - - /* - * Write the FW length. (MUST BE SET BEFORE fw_err_detec_e_addr) - */ - if ((binary_params.bin_params & BIN_FW_LENGTH) == 0x00000000) { - /* - * In case the FW length was not set, then the FW length is the - * size of the binary file minus the offset of the start of the - * FW. - */ - binary_params.fw_len = bin_file_size_bytes-bin_fw_offset; - } - - if ((int)binary_params.fw_len < 0) { - my_printf(TERR, - "\nFW length %d (0x%08x) should be greater than 0x0.", - binary_params.fw_len, - binary_params.fw_len); - return FALSE; - } - - if (((int)binary_params.fw_len > - (bin_file_size_bytes - bin_fw_offset)) || - ((int)binary_params.fw_len > g_ram_size)) { - my_printf(TERR, - "\nFW length %d (0x%08x) should be within the", - binary_params.fw_len, binary_params.fw_len); - my_printf(TERR, - " input-file (related to the FW offset)"); - my_printf(TERR, - "\n (0x%08x) and within the RAM (RAM size: 0x%08x).", - (bin_file_size_bytes - bin_fw_offset), g_ram_size); - return FALSE; - } - - if ((binary_params.bin_params & BIN_FW_USER_ARM_RESET) != 0x00000000) { - read_from_file((bin_fw_offset + ARM_FW_ENTRY_POINT_OFFSET), - 4, - &binary_params.fw_ep, - "read FW entry point for FW image "); - - if ((binary_params.fw_ep < - binary_params.fw_load_addr) || - (binary_params.fw_ep > - (binary_params.fw_load_addr + - binary_params.fw_len))) { - my_printf(TERR, - "\nFW entry point (0x%08x) should be between", - binary_params.fw_ep); - my_printf(TERR, - " the FW load address (0x%08x) ", - binary_params.fw_load_addr); - my_printf(TERR, - "and FW length (0x%08x).\n", - (binary_params.fw_load_addr + - binary_params.fw_len)); - return FALSE; - } - } - - /* FW entry point should be between the FW load address and RAM size */ - if ((binary_params.fw_ep < - binary_params.fw_load_addr) || - (binary_params.fw_ep > - (binary_params.fw_load_addr + - binary_params.fw_len))) { - if (((binary_params.bin_params & BIN_FW_ENTRY_POINT) == - 0x00000000) && - ((binary_params.bin_params & - BIN_FW_LOAD_START_ADDR) != 0x00000000)) { - binary_params.fw_ep = - binary_params.fw_load_addr; - } else { - my_printf(TERR, - "\nFW entry point (0x%08x) should be ", - binary_params.fw_ep); - my_printf(TERR, - "\between the FW load address (0x%08x)", - binary_params.fw_load_addr); - my_printf(TERR, - " and FW length (0x%08x).\n", - (binary_params.fw_load_addr + - binary_params.fw_len)); - return FALSE; - } - } - - /* Write the FW entry point */ - if (!write_to_file(binary_params.fw_ep, - HDR_FW_ENTRY_POINT_OFFSET, - 4, - "HDR - FW Entry point ")) - return FALSE; - - /* Calculate the CRC end address. */ - if ((binary_params.bin_params & BIN_FW_CKS_SIZE) == 0x00000000) { - /* - * In case the size was not set, then CRC end address is - * the size of the binary file. - */ - binary_params.fw_err_detec_e_addr = - binary_params.fw_len - 1; - } else { - /* CRC end address should be less than FW length. */ - if (binary_params.fw_err_detec_e_addr > - (binary_params.fw_len - 1)) { - my_printf(TERR, - "\nCRC end address (0x%08x) should be less ", - binary_params.fw_err_detec_e_addr); - my_printf(TERR, - "than the FW length %d (0x%08x)", - (binary_params.fw_len), - (binary_params.fw_len)); - return FALSE; - } - } - - /* Check CRC start and end addresses. */ - if (binary_params.fw_err_detec_s_addr > - binary_params.fw_err_detec_e_addr) { - my_printf(TERR, - "\nCRC start address (0x%08x) should be less or ", - binary_params.fw_err_detec_s_addr); - my_printf(TERR, - "equal to CRC end address (0x%08x)\nPlease check ", - binary_params.fw_err_detec_e_addr); - my_printf(TERR, - "CRC start address and CRC size arguments."); - return FALSE; - } - - /* CRC start addr should be between the FW load address and RAM size */ - if (binary_params.fw_err_detec_s_addr > - binary_params.fw_len) { - my_printf(TERR, "\nCRC start address (0x%08x) should ", - binary_params.fw_err_detec_s_addr); - my_printf(TERR, "be FW length (0x%08x).", - binary_params.fw_len); - return FALSE; - } - - /* Write the CRC start address */ - if (!write_to_file(binary_params.fw_err_detec_s_addr, - HDR_FW_ERR_DETECT_START_ADDR_OFFSET, - 4, - "HDR - FW CRC Start ")) - return FALSE; - - /* CRC end addr should be between the CRC start address and RAM size */ - if ((binary_params.fw_err_detec_e_addr < - binary_params.fw_err_detec_s_addr) || - (binary_params.fw_err_detec_e_addr > - binary_params.fw_len)) { - my_printf(TERR, - "\nCRC end address (0x%08x) should be between the ", - binary_params.fw_err_detec_e_addr); - my_printf(TERR, - "CRC start address (0x%08x) and FW length (0x%08x).", - binary_params.fw_err_detec_s_addr, - binary_params.fw_len); - return FALSE; - } - - /* Write the CRC end address */ - if (!write_to_file(binary_params.fw_err_detec_e_addr, - HDR_FW_ERR_DETECT_END_ADDR_OFFSET, - 4, - "HDR - FW CRC End ")) - return FALSE; - - /* Let the FW length to be aligned to 16 */ - tmp_param = binary_params.fw_len % 16; - if (tmp_param) - binary_params.fw_len += (16 - tmp_param); - - /* FW load address + FW length should be less than the RAM size. */ - if ((binary_params.fw_load_addr + - binary_params.fw_len) > - (g_ram_start_address + g_ram_size)) { - my_printf(TERR, - "\nFW load address + FW length should (0x%08x) be ", - (binary_params.fw_load_addr + binary_params.fw_len)); - my_printf(TERR, - "less than the RAM size (0x%08x).", - (g_ram_start_address + g_ram_size)); - return FALSE; - } - - /* Write the FW length */ - if (!write_to_file(binary_params.fw_len, - HDR_FW_LENGTH_OFFSET, - 4, - "HDR - FW Length ")) - return FALSE; - - /* Write the SPI flash MAX clock. */ - switch (binary_params.flash_size) { - case FLASH_SIZE_1_MBYTES_VAL: - tmp_param = FLASH_SIZE_1_MBYTES; - break; - case FLASH_SIZE_2_MBYTES_VAL: - tmp_param = FLASH_SIZE_2_MBYTES; - break; - case FLASH_SIZE_4_MBYTES_VAL: - tmp_param = FLASH_SIZE_4_MBYTES; - break; - case FLASH_SIZE_8_MBYTES_VAL: - tmp_param = FLASH_SIZE_8_MBYTES; - break; - case FLASH_SIZE_16_MBYTES_VAL: - tmp_param = FLASH_SIZE_16_MBYTES; - break; - default: - my_printf(TERR, "\n\nInvalid Flash size (%d MBytes) -", - binary_params.flash_size); - my_printf(TERR, " it should be 1, 2, 4, 8 or 16 MBytes\n"); - return FALSE; - } - if (!write_to_file(tmp_param, - HDR_FLASH_SIZE_OFFSET, - 1, - "HDR - Flash size ")) - - return FALSE; - - /* Write the reserved bytes. */ - if (!write_to_file(PAD_VALUE, HDR_RESERVED, 26, - "HDR - Reserved (26 bytes) ")) - return FALSE; - - - /* Refresh the FW header bin file in order to calculate CRC */ - if (g_hfd_pointer) { - fclose(g_hfd_pointer); - g_hfd_pointer = fopen(g_hdr_input_name, "r+b"); - if (g_hfd_pointer == NULL) { - my_printf(TERR, - "\n\nCannot open %s\n\n", - input_file_name); - return FALSE; - } - } - - /* Calculate the FW header CRC */ - if ((binary_params.bin_params & BIN_FW_HDR_CRC_DISABLE) == 0) { - /* Calculate ... */ - g_calc_type = CALC_TYPE_CRC; - if (!calc_header_crc_bin(&binary_params.hdr_crc)) - return FALSE; - - g_calc_type = CALC_TYPE_NONE; - } else - binary_params.hdr_crc = 0; - - /* Write FW header CRC to header file */ - if (!write_to_file(binary_params.hdr_crc, - HDR_FW_HEADER_SIG_OFFSET, - 4, - "HDR - Header CRC ")) - return FALSE; - - /* Calculate the FW CRC */ - if ((binary_params.bin_params & BIN_FW_CRC_DISABLE) == 0) { - /* Calculate ... */ - g_calc_type = CALC_TYPE_CRC; - if (!calc_firmware_csum_bin(&binary_params.fw_crc, - (bin_fw_offset + - binary_params.fw_err_detec_s_addr), - (binary_params.fw_err_detec_e_addr - - binary_params.fw_err_detec_s_addr+1))) - return FALSE; - - g_calc_type = CALC_TYPE_NONE; - } else - binary_params.fw_crc = 0; - - /* Write the FW CRC into file header file */ - if (!write_to_file(binary_params.fw_crc, - HDR_FW_IMAGE_SIG_OFFSET, - 4, - "HDR - FW CRC ")) - return FALSE; - - /* Close if needed... */ - if (input_file_pointer) { - fclose(input_file_pointer); - input_file_pointer = NULL; - } - - if (g_hfd_pointer) { - fclose(g_hfd_pointer); - g_hfd_pointer = NULL; - } - - /* Create empty output file. */ - output_file_pointer = fopen(output_file_name, "wb"); - if (output_file_pointer) - fclose(output_file_pointer); - - if ((binary_params.bin_params & BIN_FW_HDR_OFFSET) != 0) { - copy_file_to_file(output_file_name, - input_file_name, - 0, - SEEK_SET); - copy_file_to_file(output_file_name, - g_hdr_input_name, - binary_params.fw_hdr_offset, - SEEK_SET); - } else { - copy_file_to_file(output_file_name, - g_hdr_input_name, - 0, - SEEK_END); - copy_file_to_file(output_file_name, - input_file_name, - 0, - SEEK_END); - } - - my_printf(TINF, "\n\n"); - - return TRUE; -} - -/******************************************************************* - * Function: calc_header_crc_bin - * Parameters: unsigned short header checksum (O) - * unsigned int header offset from first byte in - * the binary (I) - * Return: TRUE if successful - * Description: Go thru bin file and calculate checksum - ******************************************************************* - */ -int calc_header_crc_bin(unsigned int *p_cksum) -{ - int i; - unsigned int calc_header_checksum_crc = 0; - unsigned char g_header_array[HEADER_SIZE]; - int line_print_size = 32; - - init_calculation(&calc_header_checksum_crc); - - /* Go thru the BIN File and calculate the Checksum */ - if (fseek(g_hfd_pointer, 0x00000000, SEEK_SET) < 0) - return FALSE; - - if (fread(g_header_array, - HEADER_SIZE, - 1, - g_hfd_pointer) != 1) - return FALSE; - - for (i = 0; i < (HEADER_SIZE - HEADER_CRC_FIELDS_SIZE); i++) { - - /* - * I had once the Verbose check inside the my_printf, but - * it made ECST run sloooowwwwwly.... - */ - if (g_verbose == SUPER_VERBOSE) { - if (i%line_print_size == 0) - my_printf(TDBG, "\n[%.4x]: ", i); - - my_printf(TDBG, "%.2x ", g_header_array[i]); - } - - update_calculation(&calc_header_checksum_crc, - g_header_array[i]); - - if (g_verbose == SUPER_VERBOSE) { - if ((i + 1) % line_print_size == 0) - my_printf(TDBG, - "FW Header ChecksumCRC = %.8x", - calc_header_checksum_crc); - - } - } - - finalize_calculation(&calc_header_checksum_crc); - *p_cksum = calc_header_checksum_crc; - - return TRUE; -} - -/* - ******************************************************************* - * Function: calc_firmware_csum_bin - * Parameters: unsigned int fwStart (I) - * unsigned int firmware size in words (I) - * unsigned int - firmware checksum (O) - * Return: - * Description: TBD - ******************************************************************* - */ -int calc_firmware_csum_bin(unsigned int *p_cksum, - unsigned int fw_offset, - unsigned int fw_length) -{ - - unsigned int i; - unsigned int calc_read_bytes; - unsigned int calc_num_of_bytes_to_read; - unsigned int calc_curr_position; - unsigned int calc_fw_checksum_crc = 0; - unsigned char g_fw_array[BUFF_SIZE]; - int line_print_size = 32; - - calc_num_of_bytes_to_read = fw_length; - calc_curr_position = fw_offset; - - if (g_verbose == REGULAR_VERBOSE) { - my_printf(TINF, - "\nFW Error Detect Start Dddress: 0x%08x", - calc_curr_position); - my_printf(TINF, - "\nFW Error Detect End Dddress: 0x%08x", - calc_curr_position + calc_num_of_bytes_to_read - 1); - my_printf(TINF, - "\nFW Error Detect Size: %d (0x%X)", - calc_num_of_bytes_to_read, - calc_num_of_bytes_to_read); - } - - init_calculation(&calc_fw_checksum_crc); - - while (calc_num_of_bytes_to_read > 0) { - if (calc_num_of_bytes_to_read > BUFF_SIZE) - calc_read_bytes = BUFF_SIZE; - else - calc_read_bytes = calc_num_of_bytes_to_read; - - if (fseek(input_file_pointer, - calc_curr_position, SEEK_SET) < 0) - return 0; - if (fread(g_fw_array, - calc_read_bytes, - 1, - input_file_pointer) != 1) - return 0; - - for (i = 0; i < calc_read_bytes; i++) { - /* - * I had once the Verbose check inside the my_printf, - * but it made ECST run sloooowwwwwly.... - */ - if (g_verbose == SUPER_VERBOSE) { - if (i%line_print_size == 0) - my_printf(TDBG, - "\n[%.4x]: ", - calc_curr_position + i); - - my_printf(TDBG, "%.2x ", g_fw_array[i]); - } - - update_calculation(&calc_fw_checksum_crc, - g_fw_array[i]); - - if (g_verbose == SUPER_VERBOSE) { - if ((i + 1) % line_print_size == 0) - my_printf(TDBG, - "FW Checksum= %.8x", - calc_fw_checksum_crc); - } - } - calc_num_of_bytes_to_read -= calc_read_bytes; - calc_curr_position += calc_read_bytes; - } /* end of while(calc_num_of_bytes_to_read > 0) */ - - finalize_calculation(&calc_fw_checksum_crc); - *p_cksum = calc_fw_checksum_crc; - - return TRUE; -} - -/* - *************************************************************************** - * "bh" mode Handler - *************************************************************************** - */ - -/* - ******************************************************************* - * Function: main_hdr - * Parameters: TBD - * Return: True for success - * Description: - ******************************************************************* - */ -int main_hdr(void) -{ - int result = 0; - char tmp_file_name[NAME_SIZE + 1]; - unsigned int tmp_long_val; - unsigned int bin_file_size_bytes; - - tmp_file_name[NAME_SIZE] = '\0'; - - if (is_ptr_merge) { - if (strlen(input_file_name) == 0) { - my_printf(TERR, "\n\nNo input BIN file selected for"); - my_printf(TERR, " BootLoader header file.\n\n"); - return FALSE; - } - - if (strlen(output_file_name) == 0) - strncpy(tmp_file_name, - input_file_name, - sizeof(tmp_file_name) - 1); - else { - copy_file_to_file(output_file_name, - input_file_name, - 0, - SEEK_END); - strncpy(tmp_file_name, - output_file_name, - sizeof(tmp_file_name) - 1); - } - - /* Open Header file */ - g_hdr_pointer = fopen(tmp_file_name, "r+b"); - if (g_hdr_pointer == NULL) { - my_printf(TERR, - "\n\nCannot open %s file.\n\n", - tmp_file_name); - return FALSE; - } - - bin_file_size_bytes = get_file_length(g_hdr_pointer); - - /* Offset should be less than file size. */ - if (fw_offset > bin_file_size_bytes) { - my_printf(TERR, - "\n\nFW offset 0x%08x should be less than ", - fw_offset); - my_printf(TERR, - "file size 0x%x (%d).\n\n", - bin_file_size_bytes, bin_file_size_bytes); - return FALSE; - } - - /* FW table should be less than file size. */ - if (ptr_fw_addr > bin_file_size_bytes) { - my_printf(TERR, "\n\nFW table 0x%08x should be less ", - ptr_fw_addr); - my_printf(TERR, "than file size 0x%x (%d).\n\n", - bin_file_size_bytes, bin_file_size_bytes); - return FALSE; - } - - if (fseek(g_hdr_pointer, fw_offset, SEEK_SET) < 0) - return FALSE; - - tmp_long_val = HDR_PTR_SIGNATURE; - result = (int)(fwrite(&tmp_long_val, - 4, - 1, - g_hdr_pointer)); - result |= (int)(fwrite(&ptr_fw_addr, - 4, - 1, - g_hdr_pointer)); - - if (result) { - my_printf(TINF, - "\nBootLoader Header file: %s\n", - tmp_file_name); - my_printf(TINF, - " Offset: 0x%08X, Signature: 0x%08X,", - fw_offset, HDR_PTR_SIGNATURE); - my_printf(TINF, - " Pointer: 0x%08X\n", - ptr_fw_addr); - } else { - my_printf(TERR, - "\n\nCouldn't write signature (%x) and " - "pointer to BootLoader header file (%s)\n\n", - tmp_long_val, tmp_file_name); - return FALSE; - } - - } else { - - if (strlen(output_file_name) == 0) { - my_printf(TERR, "\n\nNo output file selected "); - my_printf(TERR, "for BootLoader header file.\n\n"); - return FALSE; - } - - /* Open Output file */ - g_hdr_pointer = fopen(output_file_name, "w+b"); - if (g_hdr_pointer == NULL) { - my_printf(TERR, - "\n\nCannot open %s file.\n\n", - output_file_name); - return FALSE; - } - - if (fseek(g_hdr_pointer, 0L, SEEK_SET) < 0) - return FALSE; - - tmp_long_val = HDR_PTR_SIGNATURE; - result = (int)(fwrite(&tmp_long_val, - 4, - 1, - g_hdr_pointer)); - result |= (int)(fwrite(&ptr_fw_addr, - 4, - 1, - g_hdr_pointer)); - - if (result) { - my_printf(TINF, - "\nBootLoader Header file: %s\n", - output_file_name); - my_printf(TINF, - " Signature: 0x%08X, Pointer: 0x%08X\n", - HDR_PTR_SIGNATURE, - ptr_fw_addr); - } else { - my_printf(TERR, - "\n\nCouldn't write signature (%x) and ", - tmp_long_val); - my_printf(TERR, - "pointer to BootLoader header file (%s)\n\n", - output_file_name); - return FALSE; - } - - } - - /* Close if needed... */ - if (g_hdr_pointer) { - fclose(g_hdr_pointer); - g_hdr_pointer = NULL; - } - - return TRUE; -} - -/* - *************************************************************************** - * "api" mode Handler - *************************************************************************** - */ - -/* - ******************************************************************* - * Function: main_api - * Parameters: TBD - * Return: True for success - * Description: - * TBD - ******************************************************************* - */ -int main_api(void) -{ - char tmp_file_name[NAME_SIZE + 1]; - int result = 0; - unsigned int crc_checksum; - - tmp_file_name[NAME_SIZE] = '\0'; - api_file_size_bytes = 0; - - /* If API input file was not declared, then print error message. */ - if (strlen(input_file_name) == 0) { - my_printf(TERR, - "\n\nNeed to define API input file, using -i flag\n\n"); - return FALSE; - - } - - if (strlen(output_file_name) == 0) { - if (!splice_into_path(tmp_file_name, input_file_name, - sizeof(tmp_file_name), "api_")) - return FALSE; - } else - strncpy(tmp_file_name, output_file_name, - sizeof(tmp_file_name) - 1); - - /* Make sure that new empty file is created. */ - api_file_pointer = fopen(tmp_file_name, "w"); - if (api_file_pointer == NULL) { - my_printf(TERR, "\n\nCannot open %s\n\n", tmp_file_name); - return FALSE; - } - fclose(api_file_pointer); - - copy_file_to_file(tmp_file_name, input_file_name, 0, SEEK_END); - - /* Open API input file */ - api_file_pointer = fopen(tmp_file_name, "r+b"); - if (api_file_pointer == NULL) { - my_printf(TERR, "\n\nCannot open %s\n\n", tmp_file_name); - return FALSE; - } - - /* - * Check Binary file size, this file contain the image itself, - * without any header. - */ - api_file_size_bytes = get_file_length(api_file_pointer); - if (api_file_size_bytes < 0) - return FALSE; - my_printf(TINF, - "\nAPI file: %s, size: %d bytes (0x%x)\n", - tmp_file_name, - api_file_size_bytes, - api_file_size_bytes); - - crc_checksum = calc_api_csum_bin(); - - if (fseek(api_file_pointer, api_file_size_bytes, SEEK_SET) < 0) - return FALSE; - - result = (int)(fwrite(&crc_checksum, - 4, - 1, - api_file_pointer)); - - if (result) - my_printf(TINF, - "\nIn API BIN file - Offset 0x%08X - value 0x%08X", - api_file_size_bytes, - crc_checksum); - else { - my_printf(TERR, - "\n\nCouldn't write %x to API BIN file at %08x\n\n", - crc_checksum, api_file_size_bytes); - return FALSE; - } - - /* Close if needed... */ - if (api_file_pointer) { - fclose(api_file_pointer); - api_file_pointer = NULL; - } - - return TRUE; -} - - -/* - ******************************************************************* - * Function: calc_api_csum_bin - * Parameters: - * - * Return: Return the CRC \ checksum, or "0" in case of fail. - * Description: TBD - ******************************************************************* -*/ -unsigned int calc_api_csum_bin(void) -{ - - unsigned int i; - unsigned int calc_read_bytes; - int calc_num_of_bytes_to_read; - unsigned int calc_curr_position; - unsigned int calc_fw_checksum_crc = 0; - unsigned char g_fw_array[BUFF_SIZE]; - int line_print_size = 32; - - calc_num_of_bytes_to_read = api_file_size_bytes; - calc_curr_position = 0; - - if (g_verbose == SUPER_VERBOSE) { - my_printf(TDBG, - "\nAPI CRC \\ Checksum First Byte Address: 0x%08x", - calc_curr_position); - my_printf(TDBG, - "\nAPI CRC \\ Checksum Size: %d (0x%X)", - calc_num_of_bytes_to_read, - calc_num_of_bytes_to_read); - } - - init_calculation(&calc_fw_checksum_crc); - - while (calc_num_of_bytes_to_read > 0) { - if (calc_num_of_bytes_to_read > BUFF_SIZE) - calc_read_bytes = BUFF_SIZE; - else - calc_read_bytes = calc_num_of_bytes_to_read; - - if (fseek(api_file_pointer, - calc_curr_position, SEEK_SET) < 0) - return 0; - if (fread(g_fw_array, - calc_read_bytes, - 1, - api_file_pointer) != 1) - return 0; - - for (i = 0; i < calc_read_bytes; i++) { - /* - * I had once the Verbose check inside the my_printf, - * but it made ecst run sloooowwwwwly.... - */ - if (g_verbose == SUPER_VERBOSE) { - if (i%line_print_size == 0) - my_printf(TDBG, - "\n[%.4x]: ", - calc_curr_position + i); - - my_printf(TDBG, "%.2x ", g_fw_array[i]); - } - - update_calculation(&calc_fw_checksum_crc, - g_fw_array[i]); - - if (g_verbose == SUPER_VERBOSE) { - if ((i + 1) % line_print_size == 0) - my_printf(TDBG, - "FW Checksum= %.8x", - calc_fw_checksum_crc); - } - } - calc_num_of_bytes_to_read -= calc_read_bytes; - calc_curr_position += calc_read_bytes; - } /* end of while(calc_num_of_bytes_to_read > 0) */ - - finalize_calculation(&calc_fw_checksum_crc); - - return calc_fw_checksum_crc; - -} - -/* - ************************************************************************** - * CRC Handler - ************************************************************************** -*/ - -/* - ******************************************************************* - * - * #define P_xxxx - * - * The CRC's are computed using polynomials. The coefficients - * for the algorithms are defined by the following constants. - * - ******************************************************************* - */ - -#define P_32 0xEDB88320L - -/* - ******************************************************************* - * - * static int crc_tab...init - * static unsigned ... crc_tab...[] - * - * The algorithms use tables with pre-calculated values. This - * speeds up the calculation dramatically. The first time the - * CRC function is called, the table for that specific calcu- - * lation is set up. The ...init variables are used to deter- - * mine if the initialization has taken place. The calculated - * values are stored in the crc_tab... arrays. - * - * The variables are declared static. This makes them invisible - * for other modules of the program. - * - ******************************************************************* - */ -static int crc_tab32_init = FALSE; -static unsigned int crc_tab32[256]; - -/* - ******************************************************************** - * - * static void init_crc...tab(); - * - * Three local functions are used to initialize the tables - * with values for the algorithm. - * - ******************************************************************* - */ - -static void init_crc32_tab(void); - -/* - ******************************************************************* - * - * unsigned int initialize_crc_32( void ); - * - * The function update_crc_32 calculates a new CRC-32 value - * based on the previous value of the CRC and the next byte - * of the data to be checked. - * - ******************************************************************* - */ - -unsigned int initialize_crc_32(void) -{ - return 0xffffffffL; -} /* initialize_crc_32 */ - -/* - ******************************************************************* - * - * unsigned int update_crc_32( unsigned int crc, char c ); - * - * The function update_crc_32 calculates a new CRC-32 value - * based on the previous value of the CRC and the next byte - * of the data to be checked. - * - ******************************************************************* - */ - -unsigned int update_crc_32(unsigned int crc, char c) -{ - - unsigned int tmp, long_c; - - long_c = 0x000000ffL & (unsigned int)c; - - if (!crc_tab32_init) - init_crc32_tab(); - - tmp = crc ^ long_c; - crc = (crc >> 8) ^ crc_tab32[tmp & 0xff]; - - return crc; - -} /* update_crc_32 */ - -/* - ******************************************************************* - * - * static void init_crc32_tab( void ); - * - * The function init_crc32_tab() is used to fill the array - * for calculation of the CRC-32 with values. - * - ******************************************************************* - */ -static void init_crc32_tab(void) -{ - - int i, j; - unsigned int crc; - - for (i = 0; i < 256; i++) { - - crc = (unsigned int)i; - - for (j = 0; j < 8; j++) { - - if (crc & 0x00000001L) - crc = (crc >> 1) ^ P_32; - else - crc = crc >> 1; - } - - crc_tab32[i] = crc; - } - - crc_tab32_init = TRUE; - -} /* init_crc32_tab */ - -/* - ******************************************************************* - * - * unsigned int finalize_crc_32( unsigned int crc ); - * - * The function finalize_crc_32 finalizes a CRC-32 calculation - * by performing a bit convolution (bit 0 is bit 31, etc'). - * - ******************************************************************* - */ - -unsigned int finalize_crc_32(unsigned int crc) -{ - - int i; - unsigned int result = 0; - - for (i = 0; i < NUM_OF_BYTES; i++) - SET_VAR_BIT(result, NUM_OF_BYTES - (i+1), READ_VAR_BIT(crc, i)); - - return result; - -} /* finalize_crc_32 */ - diff --git a/util/ecst.h b/util/ecst.h deleted file mode 100644 index 423f65a102..0000000000 --- a/util/ecst.h +++ /dev/null @@ -1,278 +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. - */ - -#ifndef ECST_H -#define ECST_H - -/*--------------------------------------------------------------------------- - Includes - --------------------------------------------------------------------------*/ - -#include -#include -#include -#include - - -/*--------------------------------------------------------------------------- - Defines - --------------------------------------------------------------------------*/ - -/* For the beauty */ -#define TRUE 1 -#define FALSE 0 - -/* CHANGEME when the version is updated */ -#define T_VER 1 -#define T_REV_MAJOR 0 -#define T_REV_MINOR 3 - -/* Header starts by default at 0x20000 */ -#define FIRMWARE_OFFSET_FROM_HEADER 0x40 - -#define ARM_FW_ENTRY_POINT_OFFSET 0x04 - -/* Some useful offsets inside the header */ -#define HDR_ANCHOR_OFFSET 0 -#define HDR_EXTENDED_ANCHOR_OFFSET 4 -#define HDR_SPI_MAX_CLK_OFFSET 6 -#define HDR_SPI_READ_MODE_OFFSET 7 -#define HDR_ERR_DETECTION_CONF_OFFSET 8 -#define HDR_FW_LOAD_START_ADDR_OFFSET 9 -#define HDR_FW_ENTRY_POINT_OFFSET 13 -#define HDR_FW_ERR_DETECT_START_ADDR_OFFSET 17 -#define HDR_FW_ERR_DETECT_END_ADDR_OFFSET 21 -#define HDR_FW_LENGTH_OFFSET 25 -#define HDR_FLASH_SIZE_OFFSET 29 -#define HDR_RESERVED 30 -#define HDR_FW_HEADER_SIG_OFFSET 56 -#define HDR_FW_IMAGE_SIG_OFFSET 60 - - -#define FIRMW_CKSM_OFFSET 0x3C - -/* Header field known values */ -#define FW_HDR_ANCHOR 0x2A3B4D5E -#define FW_HDR_EXT_ANCHOR_ENABLE 0xAB1E -#define FW_HDR_EXT_ANCHOR_DISABLE 0x54E1 -#define FW_CRC_DISABLE 0x00 -#define FW_CRC_ENABLE 0x02 -#define HEADER_CRC_FIELDS_SIZE 8 - -#define HDR_PTR_SIGNATURE 0x55AA650E - -#define CKSMCRC_INV_BIT_OFFSET 0x1 - -/* Some common Sizes */ -#define STR_SIZE 200 -#define ARG_SIZE 100 -#define NAME_SIZE 160 -#define BUFF_SIZE 0x400 -#define HEADER_SIZE 64 -#define TMP_STR_SIZE 20 -#define PAD_VALUE 0x00 - - -#define MAX_ARGS 100 - -/* Text Colors */ -#define TDBG 0x02 /* Dark Green */ -#define TPAS 0x0A /* light green */ -#define TINF 0x0B /* light turquise */ -#define TERR 0x0C /* light red */ -#define TUSG 0x0E /* light yellow */ - -/* Indicates bin Command line parameters */ -#define BIN_FW_HDR_CRC_DISABLE 0x0001 -#define BIN_FW_CRC_DISABLE 0x0002 -#define BIN_FW_START 0x0004 -#define BIN_FW_SIZE 0x0008 -#define BIN_CK_FIRMWARE 0x0010 -#define BIN_FW_CKS_START 0x0020 -#define BIN_FW_CKS_SIZE 0x0040 -#define BIN_FW_CHANGE_SIG 0x0080 -#define BIN_FW_SPI_MAX_CLK 0x0100 -#define BIN_FW_LOAD_START_ADDR 0x0200 -#define BIN_FW_ENTRY_POINT 0x0400 -#define BIN_FW_LENGTH 0x0800 -#define BIN_FW_HDR_OFFSET 0x1000 -#define BIN_FW_USER_ARM_RESET 0x2000 -#define BIN_UNLIM_BURST_ENABLE 0x4000 - -#define ECRP_OFFSET 0x01 -#define ECRP_INPUT_FILE 0x02 -#define ECRP_OUTPUT_FILE 0x04 - -#define SPI_MAX_CLOCK_20_MHZ_VAL 20 -#define SPI_MAX_CLOCK_25_MHZ_VAL 25 -#define SPI_MAX_CLOCK_33_MHZ_VAL 33 -#define SPI_MAX_CLOCK_40_MHZ_VAL 40 -#define SPI_MAX_CLOCK_50_MHZ_VAL 50 - -#define SPI_MAX_CLOCK_20_MHZ 0x00 -#define SPI_MAX_CLOCK_25_MHZ 0x01 -#define SPI_MAX_CLOCK_33_MHZ 0x02 -#define SPI_MAX_CLOCK_40_MHZ 0x03 -#define SPI_MAX_CLOCK_50_MHZ 0x04 -#define SPI_MAX_CLOCK_MASK 0xF8 - -#define SPI_CLOCK_RATIO_1_VAL 1 -#define SPI_CLOCK_RATIO_2_VAL 2 - -#define SPI_CLOCK_RATIO_1 0x07 -#define SPI_CLOCK_RATIO_2 0x08 - -#define SPI_NORMAL_MODE_VAL "normal" -#define SPI_SINGLE_MODE_VAL "fast" -#define SPI_DUAL_MODE_VAL "dual" -#define SPI_QUAD_MODE_VAL "quad" - -#define SPI_NORMAL_MODE 0x00 -#define SPI_SINGLE_MODE 0x01 -#define SPI_DUAL_MODE 0x03 -#define SPI_QUAD_MODE 0x04 - -#define SPI_UNLIMITED_BURST_ENABLE 0x08 - -#define FLASH_SIZE_1_MBYTES_VAL 1 -#define FLASH_SIZE_2_MBYTES_VAL 2 -#define FLASH_SIZE_4_MBYTES_VAL 4 -#define FLASH_SIZE_8_MBYTES_VAL 8 -#define FLASH_SIZE_16_MBYTES_VAL 16 - -#define FLASH_SIZE_1_MBYTES 0x01 -#define FLASH_SIZE_2_MBYTES 0x03 -#define FLASH_SIZE_4_MBYTES 0x07 -#define FLASH_SIZE_8_MBYTES 0x0F -#define FLASH_SIZE_16_MBYTES 0x1F - -/* Header fields default values. */ -#define SPI_MAX_CLOCK_DEFAULT SPI_MAX_CLOCK_20_MHZ_VAL -#define SPI_READ_MODE_DEFAULT SPI_NORMAL_MODE -#define FLASH_SIZE_DEFAULT FLASH_SIZE_16_MBYTES_VAL -#define FW_CRC_START_ADDR 0x00000000 - -#define ADDR_16_BYTES_ALIGNED_MASK 0x0000000F -#define ADDR_4_BYTES_ALIGNED_MASK 0x00000003 - -#define MAX_FLASH_SIZE 0x03ffffff - -/* Chips: convert from name to index. */ -#define NPCX5M5G 0 -#define NPCX5M6G 1 -#define NPCX7M5 2 -#define NPCX7M6 3 -#define NPCX7M7 4 - -#define DEFAULT_CHIP NPCX5M5G - -#define NPCX5M5G_RAM_ADDR 0x100A8000 -#define NPCX5M5G_RAM_SIZE 0x20000 -#define NPCX5M6G_RAM_ADDR 0x10088000 -#define NPCX5M6G_RAM_SIZE 0x40000 -#define NPCX7M5X_RAM_ADDR 0x100A8000 -#define NPCX7M5X_RAM_SIZE 0x20000 -#define NPCX7M6X_RAM_ADDR 0x10090000 -#define NPCX7M6X_RAM_SIZE 0x40000 -#define NPCX7M7X_RAM_ADDR 0x10070000 -#define NPCX7M7X_RAM_SIZE 0x60000 - -/*--------------------------------------------------------------------------- - Typedefs - --------------------------------------------------------------------------*/ - -/* Parameters for Binary manipulation */ -struct tbinparams { - unsigned int anchor; - unsigned short ext_anchor; - unsigned char spi_max_clk; - unsigned char spi_clk_ratio; - unsigned char spi_read_mode; - unsigned char err_detec_cnf; - unsigned int fw_load_addr; - unsigned int fw_ep; - unsigned int fw_err_detec_s_addr; - unsigned int fw_err_detec_e_addr; - unsigned int fw_len; - unsigned int flash_size; - unsigned int hdr_crc; - unsigned int fw_crc; - unsigned int fw_hdr_offset; - unsigned int bin_params; -} bin_params_struct; - -enum verbose_level { - NO_VERBOSE = 0, - REGULAR_VERBOSE, - SUPER_VERBOSE -}; - -enum calc_type { - CALC_TYPE_NONE = 0, - CALC_TYPE_CHECKSUM , - CALC_TYPE_CRC -}; - -struct chip_info { - unsigned int ram_addr; - unsigned int ram_size; -} chip_info_struct; - -/*------------------------------------------------------------------------*/ -/* CRC Variable bit operation macros */ -/*------------------------------------------------------------------------*/ -#define NUM_OF_BYTES 32 -#define READ_VAR_BIT(var, nb) (((var) >> (nb)) & 0x1) -#define SET_VAR_BIT(var, nb, val) ((var) |= ((val)<<(nb))) - -/*--------------------------------------------------------------------------- - Functions Declaration - --------------------------------------------------------------------------*/ - -/* main manipulation */ -int main_bin(struct tbinparams binary_parameters); -int main_api(void); -int main_hdr(void); - -/* General Checksum\CRC calculation */ -void init_calculation(unsigned int *check_sum_crc); -void finalize_calculation(unsigned int *check_sum_crc); -void update_calculation_information(unsigned char crc_con_dat); - - -/* Checksum calculation etc. (BIN Specific) */ -int calc_header_crc_bin(unsigned int *pointer_header_checksum); -int calc_firmware_csum_bin(unsigned int *p_cksum, - unsigned int fw_offset, - unsigned int fw_length); - -/* Checksum calculation etc. (ERP Specific) */ -int calc_erp_csum_bin(unsigned short *region_pointer_header_checksum, - unsigned int region_pointer_ofs); - -/* No words - General */ -void exit_with_usage(void); -int copy_file_to_file(char *dst_file_name, - char *src_file_name, - int offset, - int origin); -int write_to_file(unsigned int write_value, - unsigned int offset, - unsigned char num_of_bytes, - char *print_string); -int read_from_file(unsigned int offset, - unsigned char size_to_read, - unsigned int *read_value, - char *print_string); - -/* Nice Particular Printf - General */ -__attribute__((__format__(__printf__, 2, 3))) -void my_printf(int error_level, char *fmt, ...); - -int str_cmp_no_case(const char *s1, const char *s2); -int get_file_length(FILE *stream); - -#endif /* ECST_H */ diff --git a/util/ectool.c b/util/ectool.c deleted file mode 100644 index 32ebe478e9..0000000000 --- a/util/ectool.c +++ /dev/null @@ -1,9397 +0,0 @@ -/* Copyright 2013 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "anx74xx.h" -#include "battery.h" -#include "comm-host.h" -#include "chipset.h" -#include "compile_time_macros.h" -#include "cros_ec_dev.h" -#include "ec_panicinfo.h" -#include "ec_flash.h" -#include "ec_version.h" -#include "ectool.h" -#include "i2c.h" -#include "lightbar.h" -#include "lock/gec_lock.h" -#include "misc_util.h" -#include "panic.h" -#include "ps8xxx.h" -#include "usb_pd.h" - -/* Maximum flash size (16 MB, conservative) */ -#define MAX_FLASH_SIZE 0x1000000 - -/* - * Calculate the expected response for a hello ec command. - */ -#define HELLO_RESP(in_data) ((in_data) + 0x01020304) - -/* Command line options */ -enum { - OPT_DEV = 1000, - OPT_INTERFACE, - OPT_NAME, - OPT_ASCII, - OPT_I2C_BUS, -}; - -static struct option long_opts[] = { - {"dev", 1, 0, OPT_DEV}, - {"interface", 1, 0, OPT_INTERFACE}, - {"name", 1, 0, OPT_NAME}, - {"ascii", 0, 0, OPT_ASCII}, - {"i2c_bus", 1, 0, OPT_I2C_BUS}, - {NULL, 0, 0, 0} -}; - -#define GEC_LOCK_TIMEOUT_SECS 30 /* 30 secs */ - -const char help_str[] = - "Commands:\n" - " adcread \n" - " Read an ADC channel.\n" - " addentropy [reset]\n" - " Add entropy to device secret\n" - " apreset\n" - " Issue AP reset\n" - " autofanctrl \n" - " Turn on automatic fan speed control.\n" - " backlight \n" - " Enable/disable LCD backlight\n" - " battery\n" - " Prints battery info\n" - " batterycutoff [at-shutdown]\n" - " Cut off battery output power\n" - " batteryparam\n" - " Read or write board-specific battery parameter\n" - " boardversion\n" - " Prints the board version\n" - " cbi\n" - " Get/Set Cros Board Info\n" - " chargecurrentlimit\n" - " Set the maximum battery charging current\n" - " chargecontrol\n" - " Force the battery to stop charging or discharge\n" - " chargeoverride\n" - " Overrides charge port selection logic\n" - " chargestate\n" - " Handle commands related to charge state v2 (and later)\n" - " chipinfo\n" - " Prints chip info\n" - " cmdversions \n" - " Prints supported version mask for a command number\n" - " console\n" - " Prints the last output to the EC debug console\n" - " cec\n" - " Read or write CEC messages and settings\n" - " echash [CMDS]\n" - " Various EC hash commands\n" - " eventclear \n" - " Clears EC host events flags where mask has bits set\n" - " eventclearb \n" - " Clears EC host events flags copy B where mask has bits set\n" - " eventget\n" - " Prints raw EC host event flags\n" - " eventgetb\n" - " Prints raw EC host event flags copy B\n" - " eventgetscimask\n" - " Prints SCI mask for EC host events\n" - " eventgetsmimask\n" - " Prints SMI mask for EC host events\n" - " eventgetwakemask\n" - " Prints wake mask for EC host events\n" - " eventsetscimask \n" - " Sets the SCI mask for EC host events\n" - " eventsetsmimask \n" - " Sets the SMI mask for EC host events\n" - " eventsetwakemask \n" - " Sets the wake mask for EC host events\n" - " extpwrlimit\n" - " Set the maximum external power limit\n" - " fanduty \n" - " Forces the fan PWM to a constant duty cycle\n" - " flasherase \n" - " Erases EC flash\n" - " flasheraseasync \n" - " Erases EC flash asynchronously\n" - " flashinfo\n" - " Prints information on the EC flash\n" - " flashspiinfo\n" - " Prints information on EC SPI flash, if present\n" - " flashpd \n" - " Flash commands over PD\n" - " flashprotect [now] [enable | disable]\n" - " Prints or sets EC flash protection state\n" - " flashread \n" - " Reads from EC flash to a file\n" - " flashwrite \n" - " Writes to EC flash from a file\n" - " forcelidopen \n" - " Forces the lid switch to open position\n" - " fpcontext\n" - " Sets the fingerprint sensor context\n" - " fpencstatus\n" - " Prints status of Fingerprint sensor encryption engine\n" - " fpframe\n" - " Retrieve the finger image as a PGM image\n" - " fpinfo\n" - " Prints information about the Fingerprint sensor\n" - " fpmode [capture|deepsleep|fingerdown|fingerup]\n" - " Configure/Read the fingerprint sensor current mode\n" - " fpseed\n" - " Sets the value of the TPM seed.\n" - " fpstats\n" - " Prints timing statisitcs relating to capture and matching\n" - " fptemplate [|]\n" - " Add a template if is provided, else dump it\n" - " gpioget \n" - " Get the value of GPIO signal\n" - " gpioset \n" - " Set the value of GPIO signal\n" - " hangdetect | stop | start\n" - " Configure or start/stop the hang detect timer\n" - " hello\n" - " Checks for basic communication with EC\n" - " hibdelay [sec]\n" - " Set the delay before going into hibernation\n" - " hostsleepstate\n" - " Report host sleep state to the EC\n" - " i2cprotect [status]\n" - " Protect EC's I2C bus\n" - " i2cread\n" - " Read I2C bus\n" - " i2cwrite\n" - " Write I2C bus\n" - " i2cxfer [write bytes...]\n" - " Perform I2C transfer on EC's I2C bus\n" - " infopddev \n" - " Get info about USB type-C accessory attached to port\n" - " inventory\n" - " Return the list of supported features\n" - " kbfactorytest\n" - " Scan out keyboard if any pins are shorted\n" - " kbid\n" - " Get keyboard ID of supported keyboards\n" - " kbinfo\n" - " Dump keyboard matrix dimensions\n" - " kbpress\n" - " Simulate key press\n" - " keyscan \n" - " Test low-level key scanning\n" - " led | =...>\n" - " Set the color of an LED or query brightness range\n" - " lightbar [CMDS]\n" - " Various lightbar control commands\n" - " mkbpget \n" - " Get MKBP buttons/switches supported mask and current state\n" - " mkbpwakemask [mask]\n" - " Get or Set the MKBP event wake mask, or host event wake mask\n" - " motionsense [CMDS]\n" - " Various motion sense control commands\n" - " panicinfo\n" - " Prints saved panic info\n" - " pause_in_s5 [on|off]\n" - " Whether or not the AP should pause in S5 on shutdown\n" - " pdcontrol [suspend|resume|reset|disable|on]\n" - " Controls the PD chip\n" - " pdchipinfo \n" - " Get PD chip information\n" - " pdlog\n" - " Prints the PD event log entries\n" - " pdwritelog \n" - " Writes a PD event log of the given \n" - " pdgetmode \n" - " Get All USB-PD alternate SVIDs and modes on \n" - " pdsetmode \n" - " Set USB-PD alternate SVID and mode on \n" - " port80flood\n" - " Rapidly write bytes to port 80\n" - " port80read\n" - " Print history of port 80 write\n" - " powerinfo\n" - " Prints power-related information\n" - " protoinfo\n" - " Prints EC host protocol information\n" - " pstoreinfo\n" - " Prints information on the EC host persistent storage\n" - " pstoreread \n" - " Reads from EC host persistent storage to a file\n" - " pstorewrite \n" - " Writes to EC host persistent storage from a file\n" - " pwmgetfanrpm [ | all]\n" - " Prints current fan RPM\n" - " pwmgetkblight\n" - " Prints current keyboard backlight percent\n" - " pwmgetnumfans\n" - " Prints the number of fans present\n" - " pwmgetduty\n" - " Prints the current 16 bit duty cycle for given PWM\n" - " pwmsetfanrpm \n" - " Set target fan RPM\n" - " pwmsetkblight \n" - " Set keyboard backlight in percent\n" - " pwmsetduty\n" - " Set 16 bit duty cycle of given PWM\n" - " rand \n" - " generate of random numbers\n" - " readtest \n" - " Reads a pattern from the EC via LPC\n" - " reboot_ec " - " [at-shutdown|switch-slot]\n" - " Reboot EC to RO or RW\n" - " rollbackinfo\n" - " Print rollback block information\n" - " rtcget\n" - " Print real-time clock\n" - " rtcgetalarm\n" - " Print # of seconds before real-time clock alarm goes off.\n" - " rtcset