diff options
Diffstat (limited to 'util')
109 files changed, 0 insertions, 45206 deletions
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 <idx> 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/bin2h.sh b/util/bin2h.sh deleted file mode 100755 index 1507bc4004..0000000000 --- a/util/bin2h.sh +++ /dev/null @@ -1,41 +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. -# -# This script converts input binary blob into output .h file, -# -# The three command line arguments are: -# -# - name of the variable to define in the output .h file -# - input binary blob to be converted to hex ASCII -# - name of the output file -# -# The output file contains a C #define statement assigning the variable to hex -# dump of the input file. -# -# This script is supposed to be invoked from the make file, no command line -# argument verification is done. - -# Make sure the user is alerted if not enough command line arguments are -# supplied. -set -u - -variable_name="${1}" -input_file="${2}" -output_file="${3}" - -key_dump="$(od -An -tx1 -w8 ${input_file} | \ - sed 's/^ /\t0x/;s/ /, 0x/g;s/$/, \\/')" - -cat > ${output_file} <<EOF -/* - * This is a generated file, do not edit. - */ - -#define ${variable_name} { \\ -${key_dump} -} - -EOF diff --git a/util/build.mk b/util/build.mk deleted file mode 100644 index 9f9430a3b4..0000000000 --- a/util/build.mk +++ /dev/null @@ -1,112 +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 -# - -# See Makefile for description. -host-util-bin-y += ectool lbplay stm32mon ec_sb_firmware_update lbcc \ - ec_parse_panicinfo cbi-util iteflash -build-util-art-y += util/export_taskinfo.so - -build-util-bin-$(CHIP_NPCX) += ecst -build-util-bin-$(BOARD_NOCTURNE_FP) += ectool_servo - -host-util-bin-y += 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/ - -# 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-objs+=../common/crc.o -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-y+=genvif -build-util-art-y+=$(BOARD)_vif.xml - -# 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) -genvif-pd-objs += $(out)/common/usb_common.o -deps-$(CONFIG_USB_POWER_DELIVERY) += $(genvif-pd-objs:%.o=%.o.d) - -$(out)/util/genvif: $(genvif-pd-objs) util/genvif.h 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) -$(out)/common/usb_common.o: common/usb_common.c - -@ mkdir -p $(@D) - $(call quiet,c_to_vif,BUILDCC) -endif # CONFIG_USB_POWER_DELIVERY - -ifneq ($(CONFIG_BOOTBLOCK),) -build-util-bin-y += 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-y += 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-y += 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) - -HOST_OPENSSL_CFLAGS := $(shell $(HOST_PKG_CONFIG) --cflags openssl) -HOST_OPENSSL_LDFLAGS := $(shell $(HOST_PKG_CONFIG) --libs openssl) - -$(out)/util/gen_touchpad_hash: BUILD_CFLAGS += $(HOST_OPENSSL_CFLAGS) -$(out)/util/gen_touchpad_hash: BUILD_LDFLAGS += $(HOST_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/build_allowed.sh b/util/build_allowed.sh deleted file mode 100755 index 6ef4fe03a5..0000000000 --- a/util/build_allowed.sh +++ /dev/null @@ -1,83 +0,0 @@ -#!/bin/bash -# -# Copyright 2021 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. - -# Taken from U-Boot and modified. - -# This grubby little script creates the list of allowed configurations. This -# file contains all the config options which are allowed to be used outside -# Kconfig. Please do not add things to the list. Instead, add your new option to -# Kconfig. -# -# Usage: -# build_allowed.sh [-u] -# -# -u : Update the existing allowed file - -export LC_ALL=C LC_COLLATE=C - -# Current list of allowed ad-hoc CONFIGs -allowed=util/config_allowed.txt - -[ "$1" == "-u" ] && update=1 - -tmp=$(mktemp -d) -kconfigs="${tmp}/kconfigs" - -# -# Look for the CONFIG options, excluding those in Kconfig and defconfig files. -# -git grep CONFIG_ | \ - grep -E -vi "(Kconfig:|defconfig:|README|\.py|\.pl:)" \ - | tr ' \t' '\n' \ - | sed -n 's/^\(CONFIG_[A-Za-z0-9_]*\).*/\1/p' \ - | sort | uniq >"${tmp}/allowed.tmp1"; - -# We need a list of the valid Kconfig options to exclude these from the allowed -# list. -find . -type f -name "Kconfig*" -exec cat {} \; | sed -n -e \ - 's/^\s*\(config\|menuconfig\) *\([A-Za-z0-9_]*\)$/CONFIG_\2/p' \ - | sort | uniq > "${kconfigs}" - -# Most Kconfigs follow the pattern of CONFIG_PLATFORM_EC_*. Strip PLATFORM_EC_ -# from the config name to match the cros-ec namespace. -sed -e 's/^CONFIG_PLATFORM_EC_/CONFIG_/p' "${kconfigs}" | sort | uniq \ - > "${tmp}/allowed.tmp2" - -# Use only the options that are present in the first file but not the second. -# These comprise new ad-hoc CONFIG options. -comm -23 "${tmp}/allowed.tmp1" "${tmp}/allowed.tmp2" \ - | sort | uniq >"${tmp}/allowed.tmp3" - -# If ${allowed} already exists, take the intersection of the current -# list and the new one. We do not want to increase the allowed options. -if [ -r "${allowed}" ]; then - comm -12 "${tmp}/allowed.tmp3" "${allowed}" > "${tmp}/allowed.tmp4" - - # Find any ad-hoc configs that now have Kconfig options - comm -13 "${tmp}/allowed.tmp4" "${allowed}" > "${tmp}/allowed.tmp5" - if [ -n "${update}" ]; then - echo >&2 "Removing these CONFIG options from the allowed list:" - comm -13 "${tmp}/allowed.tmp4" "${allowed}" - mv "${tmp}/allowed.tmp4" "${allowed}" - elif [ -s "${tmp}/allowed.tmp5" ]; then - echo >&2 "Congratulations! The following options are now in" - echo >&2 "Kconfig:" - cat "${tmp}/allowed.tmp5" - echo >&2 - echo >&2 "Please run this to update the list of allowed ad-hoc" - echo >&2 "CONFIGs and include this update in your CL." - echo >&2 - echo -e >&2 "\t./util/build_allowed.sh -u" - fi -else - # If there is no file yet, add one. This allows it to be regenerated - # from scratch if needed. - mv "${tmp}/allowed.tmp3" "${allowed}" -fi - -rm -rf "${tmp}" - -unset LC_ALL LC_COLLATE diff --git a/util/cbi-util.c b/util/cbi-util.c deleted file mode 100644 index fe0c4c2bce..0000000000 --- a/util/cbi-util.c +++ /dev/null @@ -1,593 +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 <compile_time_macros.h> -#include <errno.h> -#include <dirent.h> -#include <getopt.h> -#include <limits.h> -#include <stdarg.h> -#include <stdint.h> -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <unistd.h> - -#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_FW_CONFIG, - OPT_PCB_SUPPLIER, - OPT_SSFC, - OPT_REWORK_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}, - {"fw_config", 1, 0, OPT_FW_CONFIG}, - {"pcb_supplier", 1, 0, OPT_PCB_SUPPLIER}, - {"ssfc", 1, 0, OPT_SSFC}, - {"rework_id", 1, 0, OPT_REWORK_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", - "FW_CONFIG", - "PCB_SUPPLIER", - "SSFC", - "REWORK_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 <file> Path to output file\n" - " --board_version <value> Board version\n" - " --sku_id <value> SKU ID\n" - " --size <size> Size of output file in bytes\n" - "\n" - "Optional ARGS are:\n" - " --dram_part_num <string> DRAM PART NUM\n" - " --oem_id <value> OEM ID\n" - " --oem_name <string> OEM NAME\n" - " --erase_byte <uint8> Byte used for empty space. Default:0xff\n" - " --format_version <uint16> Data format version\n" - " --model_id <value> Model ID\n" - " --fw_config <value> Firmware configuration bit-field\n" - " --pcb_supplier <value> PCB supplier\n" - " --ssfc <value> Second Source Factory Cache bit-field\n" - " --rework_id <lvalue> REWORK_ID\n" - "\n" - "<value> must be a positive integer <= 0XFFFFFFFF, <lvalue> must be a\n" - " positive integer <= 0xFFFFFFFFFFFFFFFF and field size can be\n" - " optionally specified by <value:size> notation: e.g. 0xabcd:4.\n" - "<size> must be a positive integer <= 0XFFFF.\n" - "<string> 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 <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; -}; - -struct long_integer_field { - uint64_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 <create|show> [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 = strtoull(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 = strtoull(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 parse_uint64_field(const char *arg, struct long_integer_field *f) -{ - uint64_t val; - char *e; - char *ch; - - val = strtoul(arg, &e, 0); - /* strtoul sets an errno for invalid input. If the value read is out of - * range of representable values by an unsigned long int, the function - * returns ULONG_MAX or ULONG_MIN and the errno is set to ERANGE. - */ - if (errno == ERANGE || !*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 || 8 < val || !*ch || (e && *e)) { - fprintf(stderr, "Invalid size suffix\n"); - return -1; - } - f->size = val; - } else { - if (f->val < UINT32_MAX) - f->size = estimate_field_size(f->val); - else - f->size = 8; /* assign default long int size */ - } - - if (f->size < 8 && (f->val > (1ull << f->size * 8))) { - fprintf(stderr, "Value (0x%llx) exceeds field size (%d)\n", - (unsigned long long)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; - struct integer_field fw_config; - struct integer_field pcb_supplier; - struct integer_field ssfc; - struct long_integer_field rework; - 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 = strtoull(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 = strtoull(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; - case OPT_FW_CONFIG: - if (parse_integer_field(optarg, &bi.fw_config)) - return -1; - break; - case OPT_PCB_SUPPLIER: - if (parse_integer_field(optarg, &bi.pcb_supplier)) - return -1; - break; - case OPT_SSFC: - if (parse_integer_field(optarg, &bi.ssfc)) - return -1; - break; - case OPT_REWORK_ID: - if (parse_uint64_field(optarg, &bi.rework)) - 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_data(p, CBI_TAG_FW_CONFIG, &bi.fw_config.val, - bi.fw_config.size); - p = cbi_set_data(p, CBI_TAG_PCB_SUPPLIER, &bi.pcb_supplier.val, - bi.pcb_supplier.size); - p = cbi_set_data(p, CBI_TAG_SSFC, &bi.ssfc.val, bi.ssfc.size); - p = cbi_set_data(p, CBI_TAG_REWORK_ID, &bi.rework.val, bi.rework.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) -{ - uint64_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; - case 8: - v = *(uint64_t *)d->value; - break; - default: - printf(" %s: Integer of size %d not supported\n", - name, d->size); - return; - } - printf(" %s: %llu (0x%llx, %u, %u)\n", name, (unsigned long long)v, - (unsigned long long)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_integer(buf, CBI_TAG_FW_CONFIG); - print_integer(buf, CBI_TAG_PCB_SUPPLIER); - print_integer(buf, CBI_TAG_SSFC); - print_integer(buf, CBI_TAG_REWORK_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 9ba14d3d6a..0000000000 --- a/util/chargen +++ /dev/null @@ -1,69 +0,0 @@ -#!/usr/bin/env python3 -# 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/check_allowed.sh b/util/check_allowed.sh deleted file mode 100755 index 0881409036..0000000000 --- a/util/check_allowed.sh +++ /dev/null @@ -1,88 +0,0 @@ -#!/bin/bash -# -# Copyright 2021 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. -# -# Taken from U-Boot and modified. -# -# Check that the .config file provided does not introduce any new ad-hoc CONFIG -# options -# -# Use util/build_allowed.sh to generate the list of current ad-hoc -# CONFIG options (those which are not in Kconfig). - -# Usage -# check_allowed.sh <path to .config> <path to allow file> <source dir> -# -# For example: -# scripts/check_allowed.sh build/volteer/.config config_allowed.txt . - -set -e -set -u - -PROG_NAME="${0##*/}" - -usage() { - echo >&2 "Check that a build does not introduce new ad-hoc CONFIGs" - echo >&2 "Usage:" - echo -e >&2 "\t${PROG_NAME} <.config file> <allow file> <source dir>" - exit 1 -} - -[ $# -ge 3 ] || usage - -config="$1" -allow="$2" -srctree="$3" - -tmp=$(mktemp -d) - -# Temporary files -new_configs="${tmp}/configs" -suspects="${tmp}/suspects" -kconfigs="${tmp}/kconfigs" -ok="${tmp}/ok" -new_adhoc="${tmp}/adhoc" - -export LC_ALL=C LC_COLLATE=C - -# Get a sorted list of CONFIG options in the .config file -sed -n 's/^\(CONFIG_[A-Za-z0-9_]*\).*/\1/p' "${config}" | sort | uniq \ - >"${new_configs}" - -# Find any not mentioned in the allowed file -comm -23 "${new_configs}" "${allow}" > "${suspects}" - -# Find all the Kconfig options so far defined -find "${srctree}" -type f -name "Kconfig*" -exec cat {} \; | sed -n -e \ - 's/^\s*\(config\|menuconfig\) *\([A-Za-z0-9_]*\)$/CONFIG_\2/p' \ - | sort | uniq > "${kconfigs}" - -# Most Kconfigs follow the pattern of CONFIG_PLATFORM_EC_*. Strip PLATFORM_EC_ -# from the config name to match the cros-ec namespace. -sed -e 's/^CONFIG_PLATFORM_EC_/CONFIG_/p' "${kconfigs}" | sort | uniq > "${ok}" - -# Complain about any new ad-hoc CONFIGs -comm -23 "${suspects}" "${ok}" >"${new_adhoc}" -if [ -s "${new_adhoc}" ]; then - echo >&2 "Error: The EC is in the process of migrating to Zephyr." - echo -e >&2 "\tZephyr uses Kconfig for configuration rather than" - echo -e >&2 "\tad-hoc #defines." - echo -e >&2 "\tAny new EC CONFIG options must ALSO be added to Zephyr" - echo -e >&2 "\tso that new functionality is available in Zephyr also." - echo -e >&2 "\tThe following new ad-hoc CONFIG options were detected:" - echo >&2 - cat >&2 "${new_adhoc}" - echo >&2 - echo >&2 "Please add these via Kconfig instead. Find a suitable Kconfig" - echo >&2 "file in zephyr/ and add a 'config' or 'menuconfig' option." - echo >&2 "Also see details in http://issuetracker.google.com/181253613" - echo >&2 - echo >&2 "To temporarily disable this, use: ALLOW_CONFIG=1 make ..." -else - # Check if we can remove some things from the allowed file - ./util/build_allowed.sh -fi - -rm -rf "${tmp}" diff --git a/util/comm-dev.c b/util/comm-dev.c deleted file mode 100644 index e73538b323..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 <assert.h> -#include <errno.h> -#include <fcntl.h> -#include <poll.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/ioctl.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <unistd.h> - -#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 "<unknown>"; - 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 = (uint8_t *)(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 = (char *)(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 = (struct cros_ec_command_v2 *)(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 45d6f85a02..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 <errno.h> -#include <stdbool.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#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 = (char *)(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 d76749fbe5..0000000000 --- a/util/comm-i2c.c +++ /dev/null @@ -1,257 +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. - */ - -#ifndef _GNU_SOURCE -#define _GNU_SOURCE /* for asprintf */ -#endif - -#include <errno.h> -#include <fcntl.h> -#include <linux/i2c.h> -#include <linux/i2c-dev.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/ioctl.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <unistd.h> - -#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 = (uint8_t *)(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 = req_buf; - - resp_len = I2C_RESPONSE_HEADER_SIZE + sizeof(struct ec_host_response) - + insize; - resp_buf = (uint8_t *)(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 = 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 d1ce761fc2..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 <stdint.h> -#include <stdio.h> -#include <sys/io.h> -#include <sys/param.h> -#include <unistd.h> - -#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 = (char *)(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 ef6dc7880b..0000000000 --- a/util/comm-servo-spi.c +++ /dev/null @@ -1,358 +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 <errno.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> -#include <unistd.h> - -#include <libftdi1/ftdi.h> - -#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 = (uint8_t *)(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(uint8_t *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((uint8_t *)(&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, (const uint8_t *)(outdata), outsize) == - 0) - ret = get_response((uint8_t *)(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/compare_build.sh b/util/compare_build.sh deleted file mode 100755 index 1b6030453a..0000000000 --- a/util/compare_build.sh +++ /dev/null @@ -1,292 +0,0 @@ -#!/bin/bash - -# Copyright 2020 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. - -# Tool to compare two commits and make sure that the resulting build output is -# exactly the same. -# -# The board parameter is a space separated list containing any valid board -# or special board group listed below. Items added to the list can be prefixed -# with a + or - to enforce that it is added or removed from the active set of -# boards. Boards are added or removed in the order in which they appear. -# * all - All boards that are built by the "buildall" target -# * fp - All relevant boards for fingerprint -# * stm32 - All boards that use an STM32 chip -# * stm32f4 - All boards that use an STM32F4 family of chip -# * stm32h7 - All boards that use an STM32H7 family of chip -# * npcx - " -# * mchp - " -# * ish - " -# * it83xx - " -# * lm4 - " -# * mec1322 - " -# * max32660 - " -# * mt_scp - " -# -# Example: --boards "+all -stm32" - -# Cr50 doesn't have reproducible builds. -# The following fails: -# git commit --allow-empty -m "Test" && -# ./util/compare_build.sh --boards cr50 --ref1 HEAD --ref2 HEAD^ -# -# Note to Developers -# Although this script is a good proving ground for new testing techniques, -# care should be taken to offload functionality to other core components. - -. /usr/share/misc/shflags - -FLAGS_PRIVATE_DEFAULT="${FLAGS_FALSE}" -if [[ -d private ]]; then - FLAGS_PRIVATE_DEFAULT="${FLAGS_TRUE}" -fi - -DEFINE_string 'boards' "nocturne_fp" 'Boards to build (all, fp, stm32, hatch)' \ - 'b' -DEFINE_string 'ref1' "HEAD" 'Git reference (commit, branch, etc)' -DEFINE_string 'ref2' "HEAD^" 'Git reference (commit, branch, etc)' -DEFINE_boolean 'keep' "${FLAGS_FALSE}" \ - 'Remove the temp directory after comparison.' 'k' -# Integer type can still be passed blank ("") -DEFINE_integer 'jobs' "-1" 'Number of jobs to pass to make' 'j' -# When compiling both refs for all boards, mem usage was larger than 32GB. -# If you don't have more than 32GB, you probably don't want to build both -# refs at the same time. Use the -o flag. -DEFINE_boolean 'oneref' "${FLAGS_FALSE}" \ - 'Build only one set of boards at a time. This limits mem.' 'o' -DEFINE_boolean 'private' "${FLAGS_PRIVATE_DEFAULT}" \ - 'Link the private repo/dir into test build source tree.' - -# Usage: assoc-add-keys <associate_array_name> [item1 [item2...]] -assoc-add-keys() { - local -n arr="${1}" - shift - - for key in "${@}"; do - arr["${key}"]="${key}" - done -} - -# Usage: assoc-rm-keys <associate_array_name> [item1 [item2...] -assoc-rm-keys() { - local -n arr="${1}" - shift - - for key in "${@}"; do - unset arr["${key}"] - done -} - -# Usage: make-print-boards -# -# Cache the make print-boards output -make-print-boards() { - local file="${TMP_DIR}/make-print-boards-cache" - if [[ ! -f "${file}" ]]; then - # This command take about 1 second to run - make print-boards >"${file}" - fi - cat "${file}" -} - -# Usage: boards-with CHIP -boards-with() { - local pattern="${1}" - - for b in $(make-print-boards); do - grep -E -q "${pattern}" "board/${b}/build.mk" && echo "${b}" - done -} - -# Usage: parse-boards <associate_array_name> [board-grp1 [board-grp2...]] -parse-boards() { - # shellcheck disable=SC2034 - local -n boards="$1" - shift - - # Board groups - # - # Get all CHIP variants in use: - # grep -E 'CHIP[[:space:]]*\:' board/*/build.mk \ - # | sed 's/.*:=[[:space:]]*//' | sort -u - local -A BOARD_GROUPS=( - # make-print-boards already filters out the skipped boards - [all]="$(make-print-boards)" - [fp]="dartmonkey bloonchipper nucleo-dartmonkey nucleo-h743zi" - [stm32]="$(boards-with 'CHIP[[:space:]:=]*stm32')" - [stm32f4]="$(boards-with 'CHIP_VARIANT[[:space:]:=]*stm32f4')" - [stm32h7]="$(boards-with 'CHIP_VARIANT[[:space:]:=]*stm32h7')" - [npcx]="$(boards-with 'CHIP[[:space:]:=]*npcx')" - [mchp]="$(boards-with 'CHIP[[:space:]:=]*mchp')" - [ish]="$(boards-with 'CHIP[[:space:]:=]*ish')" - [it83xx]="$(boards-with 'CHIP[[:space:]:=]*it83xx')" - [lm4]="$(boards-with 'CHIP[[:space:]:=]*lm4')" - [mec1322]="$(boards-with 'CHIP[[:space:]:=]*mec1322')" - [max32660]="$(boards-with 'CHIP[[:space:]:=]*max32660')" - [mt_scp]="$(boards-with 'CHIP[[:space:]:=]*mt_scp')" - ) - - local -a BOARDS_VALID_RAW=( ) - mapfile -t BOARDS_VALID_RAW < <(basename -a board/*) - local -A BOARDS_VALID=( ) - assoc-add-keys BOARDS_VALID "${!BOARD_GROUPS[@]}" "${BOARDS_VALID_RAW[@]}" - - # Parse boards selection - local b name name_arr=( ) - for b; do - # Remove + or - prefix - name="$(sed -E 's/^(-|\+)//' <<<"${b}")" - # Check for a valid board - if [[ "${BOARDS_VALID[${name}]}" != "${name}" ]]; then - echo "# Error - Board '${name}' does not exist" >&2 - return 1 - fi - # Check for expansion target - if [[ -n "${BOARD_GROUPS[${name}]}" ]]; then - name="${BOARD_GROUPS[${name}]}" - fi - read -d "" -r -a name_arr <<< "${name}" - # Process addition or deletion - case "${b}" in - -*) - assoc-rm-keys boards "${name_arr[@]}" - ;; - +*|*) - assoc-add-keys boards "${name_arr[@]}" - ;; - esac - done -} - - -########################################################################## -# Argument Parsing and Parameter Setup # -########################################################################## - -TMP_DIR="$(mktemp -d -t compare_build.XXXX)" - -# Process commandline flags. -FLAGS "${@}" || exit 1 -eval set -- "${FLAGS_ARGV}" - -set -e - -# Can specify any valid git ref (e.g., commits or branches). -# We need the long sha for fetching changes -OLD_REF="$(git rev-parse "${FLAGS_ref1}")" -NEW_REF="$(git rev-parse "${FLAGS_ref2}")" - -MAKE_FLAGS=( ) -# Specify -j 1 for sequential -if (( FLAGS_jobs > 0 )); then - MAKE_FLAGS+=( "-j" "${FLAGS_jobs}" ) -else - MAKE_FLAGS+=( "-j" ) -fi - -declare -A BOARDS=( ) -read -r -a FLAGS_boards <<< "${FLAGS_boards}" -parse-boards BOARDS "${FLAGS_boards[@]}" || exit $? - -if [[ ${#BOARDS[@]} -eq 0 ]]; then - echo "# Error - No boards selected" >&2 - exit 1 -fi -echo "# Board Selection:" -printf "%s\n" "${BOARDS[@]}" | sort | column - -# Symbolically linked directories -LINKS=( ) -if [[ "${FLAGS_private}" == "${FLAGS_TRUE}" ]]; then - echo "# Requesting private directory link" - LINKS+=( private ) -fi - -########################################################################## -# Runtime # -########################################################################## - -# We want make to initiate the builds for ref1 and ref2 so that a -# single jobserver manages the process. -# We should do the build comparison in the Makefile to allow for easier -# debugging when --keep is enabled. -echo "# Preparing Makefile" -cat > "${TMP_DIR}/Makefile" <<HEREDOC -ORIGIN ?= $(realpath .) -CRYPTOC_DIR ?= $(realpath ../../third_party/cryptoc) -BOARDS ?= ${BOARDS[*]} -LINKS ?= ${LINKS[*]} - -.PHONY: all -all: build-${OLD_REF} build-${NEW_REF} - -ec-%: - git clone --quiet --no-checkout \$(ORIGIN) \$@ - git -C \$@ checkout --quiet \$(@:ec-%=%) -ifneq (\$(LINKS),) - ln -s \$(addprefix \$(ORIGIN)/,\$(LINKS)) \$@ -endif - -build-%: ec-% - \$(MAKE) --no-print-directory -C \$(@:build-%=ec-%) \\ - STATIC_VERSION=1 \\ - CRYPTOC_DIR=\$(CRYPTOC_DIR) \\ - \$(addprefix proj-,\$(BOARDS)) - @printf " MKDIR %s\n" "\$@" - @mkdir -p \$@ - @for b in \$(BOARDS); do \\ - printf " CP -l '%s' to '%s'\n" \\ - "\$(@:build-%=ec-%)/build/\$\$b/ec.bin" \\ - "\$@/\$\$b-ec.bin"; \\ - cp -l \$(@:build-%=ec-%)/build/\$\$b/ec.bin \$@/\$\$b-ec.bin; \\ - done - -# So that make doesn't try to remove them -ec-${OLD_REF}: -ec-${NEW_REF}: -HEREDOC - - -build() { - echo make --no-print-directory -C "${TMP_DIR}" "${MAKE_FLAGS[@]}" "$@" - make --no-print-directory -C "${TMP_DIR}" "${MAKE_FLAGS[@]}" "$@" - return $? -} - -echo "# Launching build. Cover your eyes." -result=0 -if [[ "${FLAGS_oneref}" == "${FLAGS_FALSE}" ]]; then - build "build-${OLD_REF}" "build-${NEW_REF}" || result=$? -else - build "build-${OLD_REF}" && build "build-${NEW_REF}" || result=$? -fi -if [[ ${result} -ne 0 ]]; then - echo >&2 - echo "# Failed to make one or more of the refs." >&2 - exit 1 -fi -echo - -echo "# Comparing Files" -echo -if diff "${TMP_DIR}/build-"{"${OLD_REF}","${NEW_REF}"}; then - echo "# Verdict: MATCH" - result=0 -else - echo "# Verdict: FAILURE" - result=1 -fi -echo - -# Do keep in mind that temp directory take a few GB if all boards are built. -if [[ "${FLAGS_keep}" == "${FLAGS_TRUE}" ]]; then - echo "# Keeping temp directory around for your inspection." - echo "# ${TMP_DIR}" -else - echo "# Removing temp directory" - rm -rf "${TMP_DIR}" -fi - -exit "${result}" diff --git a/util/config_allowed.txt b/util/config_allowed.txt deleted file mode 100644 index 16f88d5a90..0000000000 --- a/util/config_allowed.txt +++ /dev/null @@ -1,1117 +0,0 @@ -CONFIG_ -CONFIG_8042_AUX -CONFIG_ACCELGYRO_BMI160_INT2_OUTPUT -CONFIG_ACCELGYRO_BMI160_INT_EVENT -CONFIG_ACCELGYRO_BMI260_INT2_OUTPUT -CONFIG_ACCELGYRO_BMI260_INT_EVENT -CONFIG_ACCELGYRO_ICM42607_INT_EVENT -CONFIG_ACCELGYRO_ICM426XX_INT_EVENT -CONFIG_ACCELGYRO_LSM6DS0 -CONFIG_ACCELGYRO_LSM6DSM -CONFIG_ACCELGYRO_LSM6DSO -CONFIG_ACCELGYRO_SEC_ADDR_FLAGS -CONFIG_ACCEL_CAL_KASA_RADIUS_THRES -CONFIG_ACCEL_CAL_MAX_TEMP -CONFIG_ACCEL_CAL_MIN_TEMP -CONFIG_ACCEL_CAL_NEWTON_RADIUS_THRES -CONFIG_ACCEL_FORCE_MODE_MASK -CONFIG_ACCEL_KXCJ9 -CONFIG_ACCEL_LIS2DE -CONFIG_ACCEL_LIS2DH -CONFIG_ACCEL_LIS2DS -CONFIG_ACCEL_LIS2DS_INT_EVENT -CONFIG_ACCEL_LIS2DW12_INT_EVENT -CONFIG_ACCEL_LIS2DWL -CONFIG_ACCEL_LIS2DW_AS_BASE -CONFIG_ACCEL_LIS2DW_COMMON -CONFIG_ACCEL_LIS2D_COMMON -CONFIG_ACCEL_LNG2DM -CONFIG_ACCEL_LSM6DSM_INT_EVENT -CONFIG_ACCEL_LSM6DSO_INT_EVENT -CONFIG_ACCEL_STD_REF_FRAME_OLD -CONFIG_ADC_BUTTONS -CONFIG_ADC_PROFILE -CONFIG_ADC_PROFILE_FAST_CONTINUOUS -CONFIG_ADC_PROFILE_SINGLE -CONFIG_ADC_SAMPLE_TIME -CONFIG_ADC_VOLTAGE_COMPARATOR -CONFIG_ADC_WATCHDOG -CONFIG_AES -CONFIG_AES_GCM -CONFIG_ALS_AL3010 -CONFIG_ALS_BH1730 -CONFIG_ALS_BH1730_LUXTH_PARAMS -CONFIG_ALS_ISL29035 -CONFIG_ALS_LIGHTBAR_DIMMING -CONFIG_ALS_OPT3001 -CONFIG_ALS_SI114X -CONFIG_ALS_SI114X_CHECK_REVISION -CONFIG_ALS_SI114X_INT_EVENT -CONFIG_ALS_SI114X_POLLING -CONFIG_ALS_TCS3400_EMULATED_IRQ_EVENT -CONFIG_ALS_TCS3400_INT_EVENT -CONFIG_AON_PERSISTENT_BASE -CONFIG_AON_PERSISTENT_SIZE -CONFIG_AON_RAM_BASE -CONFIG_AON_RAM_SIZE -CONFIG_AP_HANG_DETECT -CONFIG_AP_WARM_RESET_INTERRUPT -CONFIG_ARCH_POSIX -CONFIG_ARM64 -CONFIG_ARMV7M_CACHE -CONFIG_ASSEMBLY_MULA32 -CONFIG_ASSERT -CONFIG_AUDIO_CODEC -CONFIG_AUDIO_CODEC_ -CONFIG_AUDIO_CODEC_CAP_WOV_AUDIO_SHM -CONFIG_AUDIO_CODEC_CAP_WOV_LANG_SHM -CONFIG_AUDIO_CODEC_DMIC -CONFIG_AUDIO_CODEC_DMIC_MAX_SOFTWARE_GAIN -CONFIG_AUDIO_CODEC_DMIC_SOFTWARE_GAIN -CONFIG_AUDIO_CODEC_I2S_RX -CONFIG_AUDIO_CODEC_WOV -CONFIG_AUDIO_CODEC_WOV_AUDIO_BUF_LEN -CONFIG_AUDIO_CODEC_WOV_AUDIO_BUF_TYPE -CONFIG_AUDIO_CODEC_WOV_LANG_BUF_LEN -CONFIG_AUDIO_CODEC_WOV_LANG_BUF_TYPE -CONFIG_AUX_TIMER_PERIOD_MS -CONFIG_BACKLIGHT_LID_ACTIVE_LOW -CONFIG_BACKLIGHT_REQ_GPIO -CONFIG_BARO_BMP280 -CONFIG_BASE32 -CONFIG_BASE_ATTACHED_SWITCH -CONFIG_BATTERY_ -CONFIG_BATTERY_BQ20Z453 -CONFIG_BATTERY_BQ27541 -CONFIG_BATTERY_BQ27621 -CONFIG_BATTERY_BQ4050 -CONFIG_BATTERY_CHECK_CHARGE_TEMP_LIMITS -CONFIG_BATTERY_COUNT -CONFIG_BATTERY_CRITICAL_SHUTDOWN_CUT_OFF -CONFIG_BATTERY_CRITICAL_SHUTDOWN_TIMEOUT -CONFIG_BATTERY_CUTOFF_DELAY_US -CONFIG_BATTERY_LEVEL_NEAR_FULL -CONFIG_BATTERY_MAX17055 -CONFIG_BATTERY_MAX17055_ALERT -CONFIG_BATTERY_MAX17055_FULL_MODEL -CONFIG_BATTERY_MAX_IMBALANCE_MV -CONFIG_BATTERY_MEASURE_IMBALANCE -CONFIG_BATTERY_MM8013 -CONFIG_BATTERY_MOCK -CONFIG_BATTERY_PRECHARGE_TIMEOUT -CONFIG_BATTERY_PRESENT_ -CONFIG_BATTERY_REQUESTS_NIL_WHEN_DEAD -CONFIG_BATTERY_RETRY_NACK -CONFIG_BATTERY_V2 -CONFIG_BATTERY_VENDOR_PARAM -CONFIG_BATT_HOST_FULL_FACTOR -CONFIG_BATT_HOST_SHUTDOWN_PERCENTAGE -CONFIG_BC12_DETECT_DATA_ROLE_TRIGGER -CONFIG_BC12_DETECT_MAX14637 -CONFIG_BC12_DETECT_PI3USB9281 -CONFIG_BC12_DETECT_PI3USB9281_CHIP_COUNT -CONFIG_BC12_MAX14637_DELAY_FROM_OFF_TO_ON_MS -CONFIG_BD9995X_DELAY_INPUT_PORT_SELECT -CONFIG_BD9995X_POWER_SAVE_MODE -CONFIG_BLANK -CONFIG_BLINK -CONFIG_BLINK_LEDS -CONFIG_BLUETOOTH_HCI_DEBUG -CONFIG_BLUETOOTH_LE -CONFIG_BLUETOOTH_LE_RADIO_TEST -CONFIG_BLUETOOTH_LE_STACK -CONFIG_BLUETOOTH_LL_DEBUG -CONFIG_BMI_ORIENTATION_SENSOR -CONFIG_BMI_SEC_I2C -CONFIG_BOARD_DEEP_SLEEP -CONFIG_BOARD_EC_HANDLES_ALL_SYS_PWRGD -CONFIG_BOARD_FORCE_RESET_PIN -CONFIG_BOARD_HAS_ALL_SYS_PWRGD -CONFIG_BOARD_HAS_RTC_RESET -CONFIG_BOARD_I2C_ADDR_FLAGS -CONFIG_BOARD_ID_CMD_ACPI_EC1 -CONFIG_BOARD_POST_GPIO_INIT -CONFIG_BOARD_PRE_INIT -CONFIG_BODY_DETECTION -CONFIG_BODY_DETECTION_CONFIDENCE_DELTA -CONFIG_BODY_DETECTION_MAX_WINDOW_SIZE -CONFIG_BODY_DETECTION_OFF_BODY_CON -CONFIG_BODY_DETECTION_ON_BODY_CON -CONFIG_BODY_DETECTION_SENSOR -CONFIG_BODY_DETECTION_STATIONARY_DURATION -CONFIG_BODY_DETECTION_VAR_NOISE_FACTOR -CONFIG_BODY_DETECTION_VAR_THRESHOLD -CONFIG_BOOTBLOCK -CONFIG_BOOTCFG_VALUE -CONFIG_BOOT_HEADER_STORAGE_OFF -CONFIG_BOOT_HEADER_STORAGE_SIZE -CONFIG_BUTTONS_RUNTIME_CONFIG -CONFIG_BUTTON_COUNT -CONFIG_BUTTON_TRIGGERED_RECOVERY -CONFIG_CAPSENSE -CONFIG_CASE_CLOSED_DEBUG_EXTERNAL -CONFIG_CEC -CONFIG_CHARGER -CONFIG_CHARGER_BATTERY_TSENSE -CONFIG_CHARGER_BD9995X -CONFIG_CHARGER_BD9995X_CHGEN -CONFIG_CHARGER_BQ24715 -CONFIG_CHARGER_BQ24770 -CONFIG_CHARGER_BQ24773 -CONFIG_CHARGER_BQ25703 -CONFIG_CHARGER_BQ25710_IDCHG_LIMIT_MA -CONFIG_CHARGER_CURRENT_LIMIT -CONFIG_CHARGER_EN_ACTIVE_LOW -CONFIG_CHARGER_EN_GPIO -CONFIG_CHARGER_ILIM_PIN_DISABLED -CONFIG_CHARGER_LIMIT_ -CONFIG_CHARGER_LIMIT_POWER_THRESH_BAT_PCT -CONFIG_CHARGER_LIMIT_POWER_THRESH_CHG_MW -CONFIG_CHARGER_MAX_INPUT_CURRENT -CONFIG_CHARGER_MIN_BAT_PCT_IMBALANCED_POWER_ON -CONFIG_CHARGER_MT6370 -CONFIG_CHARGER_MT6370_BACKLIGHT -CONFIG_CHARGER_MT6370_BC12_GPIO -CONFIG_CHARGER_PROFILE_OVERRIDE_COMMON -CONFIG_CHARGER_PROFILE_VOLTAGE_RANGES -CONFIG_CHARGER_RAA489000 -CONFIG_CHARGER_RT9466 -CONFIG_CHARGER_RT9467 -CONFIG_CHARGER_RUNTIME_CONFIG -CONFIG_CHARGER_SENSE_RESISTOR_AC_BQ25710 -CONFIG_CHARGER_SENSE_RESISTOR_AC_ISL9238 -CONFIG_CHARGER_SINGLE_CHIP -CONFIG_CHARGER_SM5803 -CONFIG_CHARGER_SY21612 -CONFIG_CHARGE_MANAGER_BAT_PCT_SAFE_MODE_EXIT -CONFIG_CHARGE_MANAGER_DRP_CHARGING -CONFIG_CHARGE_MANAGER_EXTERNAL_POWER_LIMIT -CONFIG_CHARGE_MANAGER_SAFE_MODE -CONFIG_CHARGE_STATE_DEBUG -CONFIG_CHIPSET_ALDERLAKE -CONFIG_CHIPSET_ALDERLAKE_SLG4BD44540 -CONFIG_CHIPSET_APL_GLK -CONFIG_CHIPSET_APOLLOLAKE -CONFIG_CHIPSET_BRASWELL -CONFIG_CHIPSET_CANNONLAKE -CONFIG_CHIPSET_CEZANNE -CONFIG_CHIPSET_COMETLAKE -CONFIG_CHIPSET_COMETLAKE_DISCRETE -CONFIG_CHIPSET_DEBUG -CONFIG_CHIPSET_ECDRIVEN -CONFIG_CHIPSET_GEMINILAKE -CONFIG_CHIPSET_HAS_PLATFORM_PMIC_RESET -CONFIG_CHIPSET_HAS_PLATFORM_RESET -CONFIG_CHIPSET_HAS_PRE_INIT_CALLBACK -CONFIG_CHIPSET_ICELAKE -CONFIG_CHIPSET_JASPERLAKE -CONFIG_CHIPSET_MT817X -CONFIG_CHIPSET_MT8183 -CONFIG_CHIPSET_MT8192 -CONFIG_CHIPSET_POWER_SEQ_VERSION -CONFIG_CHIPSET_PP3300_RAIL_FIRST -CONFIG_CHIPSET_RK3288 -CONFIG_CHIPSET_RK3399 -CONFIG_CHIPSET_SC7180 -CONFIG_CHIPSET_SC7280 -CONFIG_CHIPSET_SDM845 -CONFIG_CHIPSET_SKYLAKE -CONFIG_CHIPSET_SLP_S3_L_OVERRIDE -CONFIG_CHIPSET_STONEY -CONFIG_CHIPSET_TIGERLAKE -CONFIG_CHIPSET_X86_RSMRST_DELAY -CONFIG_CHIP_DATA_IN_INIT_ROM -CONFIG_CHIP_INIT_ROM_REGION -CONFIG_CHIP_LFW_USE_ROM_SPI -CONFIG_CHIP_MEMORY_REGIONS -CONFIG_CHIP_PANIC_BACKUP -CONFIG_CHIP_PRE_INIT -CONFIG_CHIP_UNCACHED_REGION -CONFIG_CLOCK_CRYSTAL -CONFIG_CLOCK_SRC_EXTERNAL -CONFIG_CMD_ACCELS -CONFIG_CMD_ACCELSPOOF -CONFIG_CMD_ACCEL_FIFO -CONFIG_CMD_ACCEL_INFO -CONFIG_CMD_ADC -CONFIG_CMD_ALS -CONFIG_CMD_APTHROTTLE -CONFIG_CMD_AP_RESET_LOG -CONFIG_CMD_BATDEBUG -CONFIG_CMD_BATTFAKE -CONFIG_CMD_BATT_MFG_ACCESS -CONFIG_CMD_CBI -CONFIG_CMD_CHARGEN -CONFIG_CMD_CHARGER -CONFIG_CMD_CHARGER_ADC_AMON_BMON -CONFIG_CMD_CHARGER_DUMP -CONFIG_CMD_CHARGER_PROFILE_OVERRIDE -CONFIG_CMD_CHARGER_PROFILE_OVERRIDE_TEST -CONFIG_CMD_CHARGE_SUPPLIER_INFO -CONFIG_CMD_CHGRAMP -CONFIG_CMD_CLOCKGATES -CONFIG_CMD_COMXTEST -CONFIG_CMD_CRASH -CONFIG_CMD_DEVICE_EVENT -CONFIG_CMD_DLOG -CONFIG_CMD_ECTEMP -CONFIG_CMD_FASTCHARGE -CONFIG_CMD_FLASH -CONFIG_CMD_FLASHINFO -CONFIG_CMD_FLASH_TRISTATE -CONFIG_CMD_FLASH_WP -CONFIG_CMD_FORCETIME -CONFIG_CMD_FPSENSOR_DEBUG -CONFIG_CMD_GETTIME -CONFIG_CMD_GL3590 -CONFIG_CMD_GPIO_EXTENDED -CONFIG_CMD_GPIO_POWER_DOWN -CONFIG_CMD_GT7288 -CONFIG_CMD_HASH -CONFIG_CMD_HCDEBUG -CONFIG_CMD_HOSTCMD -CONFIG_CMD_I2CWEDGE -CONFIG_CMD_I2C_PROTECT -CONFIG_CMD_I2C_SCAN -CONFIG_CMD_I2C_STRESS_TEST -CONFIG_CMD_I2C_STRESS_TEST_ACCEL -CONFIG_CMD_I2C_STRESS_TEST_ALS -CONFIG_CMD_I2C_STRESS_TEST_BATTERY -CONFIG_CMD_I2C_STRESS_TEST_CHARGER -CONFIG_CMD_I2C_STRESS_TEST_TCPC -CONFIG_CMD_I2C_XFER -CONFIG_CMD_I2C_XFER_RAW -CONFIG_CMD_IDLE_STATS -CONFIG_CMD_INA -CONFIG_CMD_JUMPTAGS -CONFIG_CMD_KEYBOARD -CONFIG_CMD_LEDTEST -CONFIG_CMD_MCDP -CONFIG_CMD_MD -CONFIG_CMD_MEM -CONFIG_CMD_MFALLOW -CONFIG_CMD_MMAPINFO -CONFIG_CMD_PD -CONFIG_CMD_PD_DEV_DUMP_INFO -CONFIG_CMD_PD_FLASH -CONFIG_CMD_PECI -CONFIG_CMD_PLL -CONFIG_CMD_POWERINDEBUG -CONFIG_CMD_POWERLED -CONFIG_CMD_POWER_AP -CONFIG_CMD_PPC_DUMP -CONFIG_CMD_PS2 -CONFIG_CMD_PWR_AVG -CONFIG_CMD_RAND -CONFIG_CMD_REGULATOR -CONFIG_CMD_RESET_FLAGS -CONFIG_CMD_RETIMER -CONFIG_CMD_RTC -CONFIG_CMD_RTC_ALARM -CONFIG_CMD_RW -CONFIG_CMD_S5_TIMEOUT -CONFIG_CMD_SCRATCHPAD -CONFIG_CMD_SEVEN_SEG_DISPLAY -CONFIG_CMD_SHA256_TEST -CONFIG_CMD_SHMEM -CONFIG_CMD_SLEEP -CONFIG_CMD_SLEEPMASK -CONFIG_CMD_SLEEPMASK_SET -CONFIG_CMD_SPI_FLASH -CONFIG_CMD_SPI_NOR -CONFIG_CMD_SPI_XFER -CONFIG_CMD_STACKOVERFLOW -CONFIG_CMD_SYSINFO -CONFIG_CMD_SYSJUMP -CONFIG_CMD_SYSLOCK -CONFIG_CMD_TASKREADY -CONFIG_CMD_TASK_RESET -CONFIG_CMD_TCPC_DUMP -CONFIG_CMD_TEMP_SENSOR -CONFIG_CMD_TIMERINFO -CONFIG_CMD_TYPEC -CONFIG_CMD_USART_INFO -CONFIG_CMD_USB_PD_CABLE -CONFIG_CMD_USB_PD_PE -CONFIG_CMD_WAITMS -CONFIG_CODE_RAM_SIZE -CONFIG_COMMON_GPIO -CONFIG_COMMON_GPIO_SHORTNAMES -CONFIG_COMMON_PANIC_OUTPUT -CONFIG_COMMON_RUNTIME -CONFIG_COMMON_TIMER -CONFIG_CONSOLE_CMDHELP -CONFIG_CONSOLE_COMMAND_FLAGS -CONFIG_CONSOLE_COMMAND_FLAGS_DEFAULT -CONFIG_CONSOLE_ENABLE_READ_V1 -CONFIG_CONSOLE_HISTORY -CONFIG_CONSOLE_INPUT_LINE_SIZE -CONFIG_CONSOLE_UART -CONFIG_CONSOLE_VERBOSE -CONFIG_CPU_CORTEX_M -CONFIG_CPU_PROCHOT_ACTIVE_LOW -CONFIG_CRC8 -CONFIG_CROS_EC_RO_MEM_SIZE -CONFIG_CROS_EC_RW_MEM_SIZE -CONFIG_CTN730 -CONFIG_CTS_TASK_LIST -CONFIG_CURVE25519 -CONFIG_CUSTOM_FAN_CONTROL -CONFIG_DAC -CONFIG_DATA_RAM_SIZE -CONFIG_DEBUG_BRINGUP -CONFIG_DEBUG_DISABLE_WRITE_BUFFER -CONFIG_DEBUG_EXCEPTIONS -CONFIG_DEBUG_ORIENTATION -CONFIG_DEBUG_PRINTF -CONFIG_DEBUG_STACK_OVERFLOW -CONFIG_DEDICATED_CHARGE_PORT_COUNT -CONFIG_DEDICATED_RECOVERY_BUTTON -CONFIG_DEDICATED_RECOVERY_BUTTON_2 -CONFIG_DELAY_DSW_PWROK_TO_PWRBTN -CONFIG_DETACHABLE_BASE -CONFIG_DEVICE_EVENT -CONFIG_DEVICE_STATE -CONFIG_DMA -CONFIG_DMA_DEFAULT_HANDLERS -CONFIG_DMA_HELP -CONFIG_DMA_PAGING -CONFIG_DO_NOT_INCLUDE_RV32I_PANIC_DATA -CONFIG_DPTF_MOTION_LID_NO_GMR_SENSOR -CONFIG_DPTF_MULTI_PROFILE -CONFIG_DRAM_BASE -CONFIG_DRAM_BASE_LOAD -CONFIG_DRAM_SIZE -CONFIG_DSW_PWROK_TO_PWRBTN_US -CONFIG_EC_CMD_PD_CHIP_INFO -CONFIG_EC_EC_COMM_BATTERY -CONFIG_EC_EC_COMM_BATTERY_CLIENT -CONFIG_EC_EC_COMM_BATTERY_SERVER -CONFIG_EC_EC_COMM_CLIENT -CONFIG_EC_EC_COMM_SERVER -CONFIG_EC_MAX_SENSOR_FREQ_DEFAULT_MILLIHZ -CONFIG_EC_MAX_SENSOR_FREQ_MILLIHZ -CONFIG_EC_PROTECTED_STORAGE_OFF -CONFIG_EC_PROTECTED_STORAGE_SIZE -CONFIG_EC_WRITABLE_STORAGE_OFF -CONFIG_EC_WRITABLE_STORAGE_SIZE -CONFIG_EEPROM -CONFIG_ENABLE_JTAG_SELECTION -CONFIG_ESPI_DEBUG -CONFIG_ESPI_LOG_LEVEL -CONFIG_EVENT_LOG_SIZE -CONFIG_EXPERIMENTAL_CONSOLE -CONFIG_EXTENDED_VERSION_INFO -CONFIG_EXTPOWER -CONFIG_EXTPOWER_DEBOUNCE_MS -CONFIG_FAKE_SHMEM -CONFIG_FANS -CONFIG_FAN_DSLEEP -CONFIG_FAN_DYNAMIC -CONFIG_FAN_INIT_SPEED -CONFIG_FAN_RPM_CUSTOM -CONFIG_FAN_UPDATE_PERIOD -CONFIG_FINGERPRINT_MCU -CONFIG_FLASH_BANK_SIZE -CONFIG_FLASH_DEFERRED_ERASE -CONFIG_FLASH_ERASED_VALUE32 -CONFIG_FLASH_ERASE_SIZE -CONFIG_FLASH_LOG -CONFIG_FLASH_LOG_BASE -CONFIG_FLASH_LOG_SPACE -CONFIG_FLASH_MULTIPLE_REGION -CONFIG_FLASH_PHYSICAL -CONFIG_FLASH_PROTECT_NEXT_BOOT -CONFIG_FLASH_PROTECT_RW -CONFIG_FLASH_PSTATE_BANK -CONFIG_FLASH_PSTATE_LOCKED -CONFIG_FLASH_READOUT_PROTECTION -CONFIG_FLASH_READOUT_PROTECTION_AS_PSTATE -CONFIG_FLASH_REGION_TYPE_COUNT -CONFIG_FLASH_SELECT_REQUIRED -CONFIG_FLASH_SIZE_BYTES -CONFIG_FLASH_WRITE_IDEAL_SIZE -CONFIG_FLASH_WRITE_SIZE -CONFIG_FMAP -CONFIG_FOO -CONFIG_FORCE_CONSOLE_RESUME -CONFIG_FP_SENSOR_ELAN515 -CONFIG_FP_SENSOR_ELAN80 -CONFIG_FP_SENSOR_FPC1025 -CONFIG_FP_SENSOR_FPC1035 -CONFIG_FP_SENSOR_FPC1145 -CONFIG_FRONT_PROXIMITY_SWITCH -CONFIG_FW_INCLUDE_RO -CONFIG_FW_LIMITED_IMAGE -CONFIG_FW_PSTATE_OFF -CONFIG_FW_PSTATE_SIZE -CONFIG_GESTURE_DETECTION -CONFIG_GESTURE_DETECTION_MASK -CONFIG_GESTURE_HOST_DETECTION -CONFIG_GESTURE_ORIENTATION -CONFIG_GESTURE_SAMPLING_INTERVAL_MS -CONFIG_GESTURE_SENSOR_DOUBLE_TAP -CONFIG_GESTURE_SENSOR_DOUBLE_TAP_FOR_HOST -CONFIG_GESTURE_SIGMO -CONFIG_GESTURE_SIGMO_PROOF_MS -CONFIG_GESTURE_SIGMO_SENSOR -CONFIG_GESTURE_SIGMO_SKIP_MS -CONFIG_GESTURE_SIGMO_THRES_MG -CONFIG_GESTURE_SW_DETECTION -CONFIG_GESTURE_TAP_FOR_HOST -CONFIG_GESTURE_TAP_INNER_WINDOW_T -CONFIG_GESTURE_TAP_MAX_INTERSTICE_T -CONFIG_GESTURE_TAP_MIN_INTERSTICE_T -CONFIG_GESTURE_TAP_OUTER_WINDOW_T -CONFIG_GESTURE_TAP_SENSOR -CONFIG_GESTURE_TAP_THRES_MG -CONFIG_GMR_TABLET_MODE_CUSTOM -CONFIG_GPIO_GET_EXTENDED -CONFIG_GPIO_POWER_DOWN -CONFIG_GYRO_L3GD20H -CONFIG_H2RAM_BASE -CONFIG_H2RAM_HOST_LPC_IO_BASE -CONFIG_H2RAM_SIZE -CONFIG_HAS_TASK_PD_INT -CONFIG_HIBERNATE -CONFIG_HIBERNATE_BATT_PCT -CONFIG_HIBERNATE_BATT_SEC -CONFIG_HIBERNATE_DELAY_SEC -CONFIG_HIBERNATE_PSL_COMPENSATE_RTC -CONFIG_HIBERNATE_PSL_OUT_FLAGS -CONFIG_HIBERNATE_PSL_VCC1_RST_WAKEUP -CONFIG_HIBERNATE_WAKEUP_PINS -CONFIG_HIBERNATE_WAKE_PINS_DYNAMIC -CONFIG_HID_HECI -CONFIG_HOOK_DEBUG -CONFIG_HOSTCMD_ALIGNED -CONFIG_HOSTCMD_AP_SET_SKUID -CONFIG_HOSTCMD_BATTERY_V2 -CONFIG_HOSTCMD_BUTTON -CONFIG_HOSTCMD_ESPI -CONFIG_HOSTCMD_ESPI_EC_CHAN_BITMAP -CONFIG_HOSTCMD_ESPI_EC_MAX_FREQ -CONFIG_HOSTCMD_ESPI_EC_MODE -CONFIG_HOSTCMD_ESPI_RESET_SLP_SX_VW_ON_ESPI_RST -CONFIG_HOSTCMD_ESPI_VW_SLP_S3 -CONFIG_HOSTCMD_ESPI_VW_SLP_S4 -CONFIG_HOSTCMD_EVENTS -CONFIG_HOSTCMD_FLASHPD -CONFIG_HOSTCMD_FLASH_SPI_INFO -CONFIG_HOSTCMD_HECI -CONFIG_HOSTCMD_I2C_ADDR_FLAGS -CONFIG_HOSTCMD_I2C_SLAVE_ADDR -CONFIG_HOSTCMD_LOCATE_CHIP -CONFIG_HOSTCMD_LPC -CONFIG_HOSTCMD_PD -CONFIG_HOSTCMD_PD_CHG_CTRL -CONFIG_HOSTCMD_PD_PANIC -CONFIG_HOSTCMD_RATE_LIMITING_MIN_REST -CONFIG_HOSTCMD_RATE_LIMITING_PERIOD -CONFIG_HOSTCMD_RATE_LIMITING_RECESS -CONFIG_HOSTCMD_RWHASHPD -CONFIG_HOSTCMD_SECTION_SORTED -CONFIG_HOSTCMD_SHI -CONFIG_HOSTCMD_SKUID -CONFIG_HOSTCMD_X86 -CONFIG_HOST_COMMAND_STATUS -CONFIG_HOST_ESPI_VW_POWER_SIGNAL -CONFIG_HOST_EVENT64 -CONFIG_HOST_EVENT64_REPORT_MASK -CONFIG_HOST_EVENT_REPORT_MASK -CONFIG_HWTIMER_64BIT -CONFIG_HW_CRC -CONFIG_HW_SPECIFIC_UDELAY -CONFIG_I2C_BITBANG -CONFIG_I2C_BUS_MAY_BE_UNPOWERED -CONFIG_I2C_CHIP_MAX_TRANSFER_SIZE -CONFIG_I2C_CONTROLLER -CONFIG_I2C_EXTRA_PACKET_SIZE -CONFIG_I2C_HID_TOUCHPAD -CONFIG_I2C_MULTI_PORT_CONTROLLER -CONFIG_I2C_NACK_RETRY_COUNT -CONFIG_I2C_PERIPHERAL -CONFIG_I2C_SCL_GATE_ADDR -CONFIG_I2C_SCL_GATE_ADDR_FLAGS -CONFIG_I2C_SCL_GATE_GPIO -CONFIG_I2C_SCL_GATE_PORT -CONFIG_I2C_UPDATE_IF_CHANGED -CONFIG_I2C_XFER_BOARD_CALLBACK -CONFIG_I2C_XFER_LARGE_TRANSFER -CONFIG_INA219 -CONFIG_INA231 -CONFIG_INA3221 -CONFIG_INDUCTIVE_CHARGING -CONFIG_INTEL_RVP_MECC_VERSION_0_9 -CONFIG_INTEL_RVP_MECC_VERSION_1_0 -CONFIG_IO_EXPANDER -CONFIG_IO_EXPANDER_CCGXXF -CONFIG_IO_EXPANDER_IT8801 -CONFIG_IO_EXPANDER_IT8801_PWM -CONFIG_IO_EXPANDER_NCT38XX -CONFIG_IO_EXPANDER_PCA9534 -CONFIG_IO_EXPANDER_PCA9675 -CONFIG_IO_EXPANDER_PCAL6408 -CONFIG_IO_EXPANDER_PORT_COUNT -CONFIG_IO_EXPANDER_SUPPORT_GET_PORT -CONFIG_IO_EXPANDER_TCA64XXA -CONFIG_IPC_SHARED_OBJ_ADDR -CONFIG_IPC_SHARED_OBJ_BUF_SIZE -CONFIG_IPI -CONFIG_IRQ_COUNT -CONFIG_ISH_BOOT_START -CONFIG_ISH_CLEAR_FABRIC_ERRORS -CONFIG_ISH_D0I2_MIN_USEC -CONFIG_ISH_D0I3_MIN_USEC -CONFIG_ISH_DW_UART -CONFIG_ISH_HOST2ISH_COMBINED_ISR -CONFIG_ISH_IPAPG -CONFIG_ISH_NEW_PM -CONFIG_ISH_PM_AONTASK -CONFIG_ISH_PM_D0I1 -CONFIG_ISH_PM_D0I2 -CONFIG_ISH_PM_D0I3 -CONFIG_ISH_PM_D3 -CONFIG_ISH_PM_RESET_PREP -CONFIG_ISH_UART_0 -CONFIG_ISL9241_SWITCHING_FREQ -CONFIG_IT83XX_ENABLE_MOUSE_DEVICE -CONFIG_IT83XX_FLASH_CLOCK_48MHZ -CONFIG_IT83XX_HARD_RESET_BY_GPG1 -CONFIG_IT83XX_RESET_PD_CONTRACT_IN_BRAM -CONFIG_IT83XX_SMCLK2_ON_GPC7 -CONFIG_IT83XX_TUNE_CC_PHY -CONFIG_IT83XX_VCC_1P8V -CONFIG_IT83XX_VCC_3P3V -CONFIG_ITE_FLASH_SUPPORT -CONFIG_KERNEL_INIT_PRIORITY_DEFAULT -CONFIG_KEYBOARD_ASSISTANT_KEY -CONFIG_KEYBOARD_BACKLIGHT -CONFIG_KEYBOARD_BOOT_KEYS -CONFIG_KEYBOARD_CUSTOMIZATION -CONFIG_KEYBOARD_DEBUG -CONFIG_KEYBOARD_FACTORY_TEST -CONFIG_KEYBOARD_IRQ_GPIO -CONFIG_KEYBOARD_KSO_BASE -CONFIG_KEYBOARD_KSO_HIGH_DRIVE -CONFIG_KEYBOARD_LANGUAGE_ID -CONFIG_KEYBOARD_NOT_RAW -CONFIG_KEYBOARD_POST_SCAN_CLOCKS -CONFIG_KEYBOARD_PRINT_SCAN_TIMES -CONFIG_KEYBOARD_REFRESH_ROW3 -CONFIG_KEYBOARD_RUNTIME_KEYS -CONFIG_KEYBOARD_SCANCODE_CALLBACK -CONFIG_KEYBOARD_SUPPRESS_NOISE -CONFIG_KEYBOARD_TABLET_MODE_SWITCH -CONFIG_KEYBOARD_TEST -CONFIG_KX022_ORIENTATION_SENSOR -CONFIG_LED_BAT_ACTIVE_LOW -CONFIG_LED_DRIVER_DS2413 -CONFIG_LED_DRIVER_LM3509 -CONFIG_LED_DRIVER_LM3630A -CONFIG_LED_DRIVER_LP5562 -CONFIG_LED_DRIVER_OZ554 -CONFIG_LED_ONOFF_STATES -CONFIG_LED_ONOFF_STATES_BAT_LOW -CONFIG_LED_POLICY_STD -CONFIG_LED_POWER_ACTIVE_LOW -CONFIG_LED_POWER_LED -CONFIG_LED_PWM_ACTIVE_CHARGE_PORT_ONLY -CONFIG_LED_PWM_CHARGE_COLOR -CONFIG_LED_PWM_CHARGE_ERROR_COLOR -CONFIG_LED_PWM_CHARGE_STATE_ONLY -CONFIG_LED_PWM_LOW_BATT_COLOR -CONFIG_LED_PWM_NEAR_FULL_COLOR -CONFIG_LED_PWM_SOC_ON_COLOR -CONFIG_LED_PWM_SOC_SUSPEND_COLOR -CONFIG_LFW_OFFSET -CONFIG_LIBCRYPTOC -CONFIG_LID_ANGLE_INVALID_CHECK -CONFIG_LID_ANGLE_SENSOR_BASE -CONFIG_LID_ANGLE_SENSOR_LID -CONFIG_LID_ANGLE_TABLET_MODE -CONFIG_LID_SWITCH_GPIO_LIST -CONFIG_LIGHTBAR_POWER_RAILS -CONFIG_LIGHTBAR_TAP_DIM_LAST_SEGMENT -CONFIG_LLSR_TEST -CONFIG_LN9310 -CONFIG_LOADER_MEM_OFF -CONFIG_LOADER_SIZE -CONFIG_LOADER_STORAGE_OFF -CONFIG_LOG -CONFIG_LOW_POWER_IDLE_LIMITED -CONFIG_LOW_POWER_S0 -CONFIG_LOW_POWER_USE_LFIOSC -CONFIG_LPRAM_BASE -CONFIG_LPRAM_SIZE -CONFIG_LSM6DSM_SEC_I2C -CONFIG_MAC_ADDR -CONFIG_MAC_ADDR_LEN -CONFIG_MAG_BMI_BMM150 -CONFIG_MAG_BMI_LIS2MDL -CONFIG_MAG_BMM150 -CONFIG_MAG_CALIBRATE -CONFIG_MAG_LIS2MDL -CONFIG_MAG_LSM6DSM_BMM150 -CONFIG_MAG_LSM6DSM_LIS2MDL -CONFIG_MALLOC -CONFIG_MAPPED_STORAGE_BASE -CONFIG_MATH_UTIL -CONFIG_MAX695X_SEVEN_SEGMENT_DISPLAY -CONFIG_MCDP28X0 -CONFIG_MCHP_48MHZ_OUT -CONFIG_MCHP_DEBUG_LPC -CONFIG_MCHP_DEEP_SLP_DEBUG -CONFIG_MCHP_DEEP_SLP_GPIO_PWR_DOWN -CONFIG_MCHP_ESPI_DEBUG -CONFIG_MCHP_ESPI_EC_CMD -CONFIG_MCHP_ESPI_RESET_DEASSERT_INIT -CONFIG_MCHP_ESPI_VW_SAVE_ON_SLEEP -CONFIG_MCHP_GPSPI -CONFIG_MCHP_GPSPI_TX_DMA -CONFIG_MCHP_I2C0_SLAVE_ADDRS -CONFIG_MCHP_I2C1_SLAVE_ADDRS -CONFIG_MCHP_I2C2_SLAVE_ADDRS -CONFIG_MCHP_I2C3_SLAVE_ADDRS -CONFIG_MCHP_I2C4_SLAVE_ADDRS -CONFIG_MCHP_I2C5_SLAVE_ADDRS -CONFIG_MCHP_I2C6_SLAVE_ADDRS -CONFIG_MCHP_I2C7_SLAVE_ADDRS -CONFIG_MCHP_JTAG_MODE -CONFIG_MCHP_LFW_DEBUG -CONFIG_MCHP_QMSPI_TX_DMA -CONFIG_MCHP_TFDP -CONFIG_MEC1701_TFDP -CONFIG_MEC_GPIO_EC_CMDS -CONFIG_MEC_SRAM_BASE_END -CONFIG_MEC_SRAM_BASE_START -CONFIG_MEC_SRAM_SIZE -CONFIG_MEC_TEST_EC_RORW_CRC -CONFIG_MEMORY_REGIONS -CONFIG_MFT_INPUT_LFCLK -CONFIG_MIA_WDT_VEC -CONFIG_MKBP_ -CONFIG_MKBP_USE_ -CONFIG_MKBP_USE_HECI -CONFIG_MOTION_FILL_LPC_SENSE_DATA -CONFIG_MOTION_MIN_SENSE_WAIT_TIME -CONFIG_MOTION_SENSE_RESUME_DELAY_US -CONFIG_MOTION_SENSE_SUSPEND_DELAY_US -CONFIG_MP4245 -CONFIG_NAME -CONFIG_NB7V904M_LPM_OVERRIDE -CONFIG_NO_PINHOLD -CONFIG_NUM_FIXED_BATTERIES -CONFIG_OCPC -CONFIG_OCPC_DEF_RBATT_MOHMS -CONFIG_ONEWIRE -CONFIG_ONLINE_CALIB -CONFIG_ONLINE_CALIB_SPOOF_MODE -CONFIG_ORIENTATION_SENSOR -CONFIG_OTP -CONFIG_PANIC_DATA_BASE -CONFIG_PANIC_DATA_SIZE -CONFIG_PD_RETRY_COUNT -CONFIG_PD_USE_DAC_AS_REF -CONFIG_PECI -CONFIG_PECI_COMMON -CONFIG_PECI_TJMAX -CONFIG_PERIPHERAL_CHARGER -CONFIG_PLATFORM_EC_ -CONFIG_PLATFORM_EC_CHARGER_LIMIT_POWER_THRESH_CHG_MW -CONFIG_PMIC_FW_LONG_PRESS_TIMER -CONFIG_PMU_HARD_RESET -CONFIG_POLLING_UART -CONFIG_PORT80_HISTORY_LEN -CONFIG_PORT80_PRINT_IN_INT -CONFIG_POWER_BUTTON_FLAGS -CONFIG_POWER_BUTTON_IGNORE_LID -CONFIG_POWER_BUTTON_INIT_IDLE -CONFIG_POWER_BUTTON_INIT_TIMEOUT -CONFIG_POWER_BUTTON_TO_PCH_CUSTOM -CONFIG_POWER_BUTTON_X86 -CONFIG_POWER_COMMON -CONFIG_POWER_PP5000_CONTROL -CONFIG_POWER_S0IX -CONFIG_POWER_SHUTDOWN_PAUSE_IN_S5 -CONFIG_POWER_SIGNAL_INTERRUPT_STORM_DETECT_THRESHOLD -CONFIG_POWER_SIGNAL_RUNTIME_CONFIG -CONFIG_POWER_TRACK_HOST_SLEEP_STATE -CONFIG_PRESERVE_LOGS -CONFIG_PRINTF_LEGACY_LI_FORMAT -CONFIG_PRINT_IN_INT -CONFIG_PROGRAM_MEMORY_BASE -CONFIG_PROGRAM_MEMORY_BASE_LOAD -CONFIG_PS2 -CONFIG_PSTORE -CONFIG_PVD -CONFIG_PWM_INPUT_LFCLK -CONFIG_PWR_STATE_DISCHARGE_FULL -CONFIG_RAM_BANKS -CONFIG_RAM_BANK_SIZE -CONFIG_RAM_BASE -CONFIG_RAM_SIZE -CONFIG_REGULATOR_IR357X -CONFIG_RESTRICTED_CONSOLE_COMMANDS -CONFIG_RMA_AUTH -CONFIG_RMA_AUTH_USE_P256 -CONFIG_RNG -CONFIG_ROLLBACK -CONFIG_ROLLBACK_MPU_PROTECT -CONFIG_ROLLBACK_OFF -CONFIG_ROLLBACK_SECRET_LOCAL_ENTROPY_SIZE -CONFIG_ROLLBACK_SECRET_SIZE -CONFIG_ROLLBACK_SIZE -CONFIG_ROLLBACK_UPDATE -CONFIG_ROLLBACK_VERSION -CONFIG_ROM_BASE -CONFIG_ROM_SIZE -CONFIG_RO_HDR_MEM_OFF -CONFIG_RO_HDR_SIZE -CONFIG_RO_HEAD_ROOM -CONFIG_RO_MEM_OFF -CONFIG_RO_MEM_SIZE -CONFIG_RO_PUBKEY_ADDR -CONFIG_RO_PUBKEY_SIZE -CONFIG_RO_PUBKEY_STORAGE_OFF -CONFIG_RO_ROM_RESIDENT_MEM_OFF -CONFIG_RO_ROM_RESIDENT_SIZE -CONFIG_RO_SIZE -CONFIG_RO_STORAGE_OFF -CONFIG_RPMSG_NAME_SERVICE -CONFIG_RSA -CONFIG_RSA_EXPONENT_3 -CONFIG_RSA_KEY_SIZE -CONFIG_RSA_OPTIMIZED -CONFIG_RWSIG -CONFIG_RWSIG_DONT_CHECK_ON_PIN_RESET -CONFIG_RWSIG_JUMP_TIMEOUT -CONFIG_RWSIG_TYPE_RWSIG -CONFIG_RWSIG_TYPE_USBPD1 -CONFIG_RW_A_SIGN_STORAGE_OFF -CONFIG_RW_A_STORAGE_OFF -CONFIG_RW_B -CONFIG_RW_BOOT_HEADER_STORAGE_OFF -CONFIG_RW_BOOT_HEADER_STORAGE_SIZE -CONFIG_RW_B_MEM_OFF -CONFIG_RW_B_SIGN_STORAGE_OFF -CONFIG_RW_B_SIG_ADDR -CONFIG_RW_B_STORAGE_OFF -CONFIG_RW_HEAD_ROOM -CONFIG_RW_MEM_OFF -CONFIG_RW_MEM_SIZE -CONFIG_RW_ROM_RESIDENT_MEM_OFF -CONFIG_RW_ROM_RESIDENT_SIZE -CONFIG_RW_SIG_ADDR -CONFIG_RW_SIG_SIZE -CONFIG_RW_SIZE -CONFIG_RW_STORAGE_OFF -CONFIG_SB_PASSTHROUGH -CONFIG_SCI_GPIO -CONFIG_SENSORHUB_LSM6DSM -CONFIG_SENSOR_ORIENTATION -CONFIG_SERIALNO_LEN -CONFIG_SEVEN_SEG_DISPLAY -CONFIG_SHA256 -CONFIG_SHA256_HW -CONFIG_SHA256_UNROLLED -CONFIG_SHAREDLIB -CONFIG_SHAREDLIB_MEM_OFF -CONFIG_SHAREDLIB_SIZE -CONFIG_SHAREDLIB_STORAGE_OFF -CONFIG_SHAREDMEM_MINIMUM_SIZE -CONFIG_SHAREDMEM_MINIMUM_SIZE_RWSIG -CONFIG_SIMULATED_BUTTON -CONFIG_SLEEP_TIMEOUT_MS -CONFIG_SMBUS -CONFIG_SOFTWARE_CLZ -CONFIG_SOFTWARE_CTZ -CONFIG_SOMETHING -CONFIG_SPI -CONFIG_SPI_ACCEL_PORT -CONFIG_SPI_CONTROLLER -CONFIG_SPI_CS_GPIO -CONFIG_SPI_FLASH -CONFIG_SPI_FLASH_GD25LQ40 -CONFIG_SPI_FLASH_GD25Q41B -CONFIG_SPI_FLASH_HAS_SR2 -CONFIG_SPI_FLASH_PORT -CONFIG_SPI_FLASH_READ_WAIT_MS -CONFIG_SPI_FLASH_W25Q128 -CONFIG_SPI_FLASH_W25Q40 -CONFIG_SPI_FLASH_W25Q64 -CONFIG_SPI_FLASH_W25Q80 -CONFIG_SPI_FLASH_W25X40 -CONFIG_SPI_FP_PORT -CONFIG_SPI_HALFDUPLEX -CONFIG_SPI_NOR -CONFIG_SPI_NOR_BLOCK_ERASE -CONFIG_SPI_NOR_DEBUG -CONFIG_SPI_NOR_MAX_MESSAGE_SIZE -CONFIG_SPI_NOR_MAX_READ_SIZE -CONFIG_SPI_NOR_MAX_WRITE_SIZE -CONFIG_SPI_NOR_SMART_ERASE -CONFIG_SPI_PROTOCOL_V2 -CONFIG_SPI_RX_BUF_SIZE -CONFIG_SPI_TOUCHPAD_PORT -CONFIG_SPI_TX_BUF_SIZE -CONFIG_STACK_SIZE -CONFIG_STANDARD_OUTPUT -CONFIG_STEINHART_HART_6V0_51K1_47K_4050B -CONFIG_STM32G4_UCPD_DEBUG -CONFIG_STM32L_FAKE_HIBERNATE -CONFIG_STM32_CHARGER_DETECT -CONFIG_STM32_CLOCK_HSE_HZ -CONFIG_STM32_CLOCK_LSE -CONFIG_STM32_SPI1_CONTROLLER -CONFIG_STM_HWTIMER32 -CONFIG_STREAM_SIGNATURE -CONFIG_STREAM_USART -CONFIG_STREAM_USART1 -CONFIG_STREAM_USART2 -CONFIG_STREAM_USART3 -CONFIG_STREAM_USART4 -CONFIG_STREAM_USB -CONFIG_SUPPORT_CHIP_HIBERNATION -CONFIG_SUPPRESSED_HOST_COMMANDS -CONFIG_SWITCH_DEDICATED_RECOVERY -CONFIG_SW_CRC -CONFIG_SYNC -CONFIG_SYNC_COMMAND -CONFIG_SYNC_INT_EVENT -CONFIG_SYNC_QUEUE_SIZE -CONFIG_SYV682X_HV_ILIM -CONFIG_TASK_LIST -CONFIG_TASK_PROFILING -CONFIG_TASK_RESET_LIST -CONFIG_TCPC_I2C_BASE_ADDR -CONFIG_TCPC_I2C_BASE_ADDR_FLAGS -CONFIG_TCS_USE_LUX_TABLE -CONFIG_TEMP_CACHE_STALE_THRES -CONFIG_TEMP_SENSOR_ADT7481 -CONFIG_TEMP_SENSOR_AMD_R19ME4070 -CONFIG_TEMP_SENSOR_BD99992GW -CONFIG_TEMP_SENSOR_EC_ADC -CONFIG_TEMP_SENSOR_F75303 -CONFIG_TEMP_SENSOR_G753 -CONFIG_TEMP_SENSOR_G781 -CONFIG_TEMP_SENSOR_G782 -CONFIG_TEMP_SENSOR_OTI502 -CONFIG_TEMP_SENSOR_POWER_GPIO -CONFIG_TEMP_SENSOR_SB_TSI -CONFIG_TEMP_SENSOR_TMP006 -CONFIG_TEMP_SENSOR_TMP112 -CONFIG_TEMP_SENSOR_TMP411 -CONFIG_TEMP_SENSOR_TMP432 -CONFIG_TEMP_SENSOR_TMP468 -CONFIG_TEST_1P8V -CONFIG_TEST_MOCK_LIST -CONFIG_TEST_SM -CONFIG_TEST_TASK_LIST -CONFIG_TEST_USB_PE_SM -CONFIG_THERMISTOR_NCP15WB -CONFIG_THROTTLE_AP_ON_BAT_DISCHG_CURRENT -CONFIG_THROTTLE_AP_ON_BAT_OLTAGE -CONFIG_THROTTLE_AP_ON_BAT_VOLTAGE -CONFIG_TICK -CONFIG_TOUCHPAD -CONFIG_TOUCHPAD_ELAN -CONFIG_TOUCHPAD_FW_CHUNKS -CONFIG_TOUCHPAD_GT7288 -CONFIG_TOUCHPAD_HASH_FW -CONFIG_TOUCHPAD_I2C_ADDR_FLAGS -CONFIG_TOUCHPAD_I2C_PORT -CONFIG_TOUCHPAD_ST -CONFIG_TOUCHPAD_VIRTUAL_OFF -CONFIG_TOUCHPAD_VIRTUAL_SIZE -CONFIG_TRICKLE_CHARGING -CONFIG_TUSB544_EQ_BY_REGISTER -CONFIG_UART_BAUD_RATE -CONFIG_UART_CONSOLE -CONFIG_UART_HOST -CONFIG_UART_HOST_COMMAND_BAUD_RATE -CONFIG_UART_HOST_COMMAND_HW -CONFIG_UART_INPUT_FILTER -CONFIG_UART_PAD_SWITCH -CONFIG_UART_RX_BUF_SIZE -CONFIG_UART_RX_DMA -CONFIG_UART_RX_DMA_CH -CONFIG_UART_RX_DMA_RECHECKS -CONFIG_UART_RX_REQ_CH -CONFIG_UART_TX_BUF_SIZE -CONFIG_UART_TX_DMA -CONFIG_UART_TX_DMA_CH -CONFIG_UART_TX_DMA_PH -CONFIG_UART_TX_REQ_CH -CONFIG_UNDEFINED -CONFIG_UPDATE_PDU_SIZE -CONFIG_USART_HOST_COMMAND -CONFIG_USB -CONFIG_USBC_BACKWARDS_COMPATIBLE_DFP -CONFIG_USBC_DISABLE_CHARGE_FROM_RP_DEF -CONFIG_USBC_PPC_AOZ1380 -CONFIG_USBC_PPC_NX20P3481 -CONFIG_USBC_PPC_NX20P3483 -CONFIG_USBC_RETIMER_NB7V904M -CONFIG_USBC_RETIMER_PI3DPX1207 -CONFIG_USBC_RETIMER_PI3HDX1204 -CONFIG_USBC_RETIMER_PS8802 -CONFIG_USBC_RETIMER_PS8818 -CONFIG_USBC_RETIMER_TUSB544 -CONFIG_USBC_VCONN_SWAP -CONFIG_USBC_VCONN_SWAP_DELAY_US -CONFIG_USB_ -CONFIG_USB_ALT_MODE_ADAPTER -CONFIG_USB_BOS -CONFIG_USB_CONSOLE -CONFIG_USB_CONSOLE_CRC -CONFIG_USB_CONSOLE_READ -CONFIG_USB_CONSOLE_STREAM -CONFIG_USB_CONSOLE_TX_BUF_SIZE -CONFIG_USB_DWC_FS -CONFIG_USB_FRS -CONFIG_USB_GPIO -CONFIG_USB_HID -CONFIG_USB_HID_KB_NUM_TOP_ROW_KEYS -CONFIG_USB_HID_KEYBOARD -CONFIG_USB_HID_KEYBOARD_BACKLIGHT -CONFIG_USB_HID_KEYBOARD_VIVALDI -CONFIG_USB_HID_TOUCHPAD -CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_PRESSURE -CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_X -CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_Y -CONFIG_USB_HID_TOUCHPAD_PHYSICAL_MAX_X -CONFIG_USB_HID_TOUCHPAD_PHYSICAL_MAX_Y -CONFIG_USB_HUB_GL3590 -CONFIG_USB_I2C -CONFIG_USB_I2C_MAX_READ_COUNT -CONFIG_USB_I2C_MAX_WRITE_COUNT -CONFIG_USB_INHIBIT_CONNECT -CONFIG_USB_INHIBIT_INIT -CONFIG_USB_ISOCHRONOUS -CONFIG_USB_MAXPOWER_MA -CONFIG_USB_MUX_AMD_FP5 -CONFIG_USB_MUX_AMD_FP6 -CONFIG_USB_MUX_ANX3443 -CONFIG_USB_MUX_ANX7440 -CONFIG_USB_MUX_ANX7451 -CONFIG_USB_MUX_AP_ACK_REQUEST -CONFIG_USB_MUX_IT5205H_SBU_OVP -CONFIG_USB_MUX_PI3USB30532 -CONFIG_USB_MUX_PI3USB31532 -CONFIG_USB_MUX_PS8740 -CONFIG_USB_MUX_PS8742 -CONFIG_USB_MUX_PS8822 -CONFIG_USB_MUX_TUSB1064 -CONFIG_USB_PAIRING -CONFIG_USB_PD_3A_PORTS -CONFIG_USB_PD_5V_CHARGER_CTRL -CONFIG_USB_PD_5V_EN_ACTIVE_LOW -CONFIG_USB_PD_ALT_MODE_UFP_DP -CONFIG_USB_PD_ANX7688 -CONFIG_USB_PD_CHECK_MAX_REQUEST_ALLOWED -CONFIG_USB_PD_COMM_DISABLED -CONFIG_USB_PD_COMM_LOCKED -CONFIG_USB_PD_CUSTOM_PDO -CONFIG_USB_PD_DEBUG_DR -CONFIG_USB_PD_DPS -CONFIG_USB_PD_DYNAMIC_SRC_CAP -CONFIG_USB_PD_EXTENDED_MESSAGES -CONFIG_USB_PD_FLASH -CONFIG_USB_PD_FLASH_ERASE_CHECK -CONFIG_USB_PD_GIVE_BACK -CONFIG_USB_PD_HW_DEV_ID_BOARD_MAJOR -CONFIG_USB_PD_HW_DEV_ID_BOARD_MINOR -CONFIG_USB_PD_I2C_ADDR_FLAGS -CONFIG_USB_PD_IDENTITY_HW_VERS -CONFIG_USB_PD_IDENTITY_SW_VERS -CONFIG_USB_PD_INITIAL_DRP_STATE -CONFIG_USB_PD_INTERNAL_COMP -CONFIG_USB_PD_LOW_POWER -CONFIG_USB_PD_LOW_POWER_IDLE_WHEN_CONNECTED -CONFIG_USB_PD_MANUFACTURER_INFO -CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT -CONFIG_USB_PD_MAX_TOTAL_SOURCE_CURRENT -CONFIG_USB_PD_MODEL_PART_NUMBER -CONFIG_USB_PD_PCIE_TUNNELING -CONFIG_USB_PD_PORT_LABEL -CONFIG_USB_PD_PREFER_MV -CONFIG_USB_PD_PRODUCT_REVISION -CONFIG_USB_PD_PULLUP -CONFIG_USB_PD_REQUIRE_AP_MODE_ENTRY -CONFIG_USB_PD_RESET_MIN_BATT_SOC -CONFIG_USB_PD_RX_COMP_IRQ -CONFIG_USB_PD_SECURITY_MSGS -CONFIG_USB_PD_SIMPLE_DFP -CONFIG_USB_PD_TBT_GEN3_CAPABLE -CONFIG_USB_PD_TCPC -CONFIG_USB_PD_TCPC_BOARD_INIT -CONFIG_USB_PD_TCPC_LPM_EXIT_DEBOUNCE -CONFIG_USB_PD_TCPC_ON_CHIP -CONFIG_USB_PD_TCPC_TRACK_VBUS -CONFIG_USB_PD_TCPMV1 -CONFIG_USB_PD_TCPMV1_DEBUG -CONFIG_USB_PD_TCPMV2 -CONFIG_USB_PD_TCPM_ANX3429 -CONFIG_USB_PD_TCPM_ANX740X -CONFIG_USB_PD_TCPM_ANX741X -CONFIG_USB_PD_TCPM_ANX7447 -CONFIG_USB_PD_TCPM_ANX7447_AUX_PU_PD -CONFIG_USB_PD_TCPM_ANX7447_OCM_ERASE_COMMAND -CONFIG_USB_PD_TCPM_ANX74XX -CONFIG_USB_PD_TCPM_ANX7688 -CONFIG_USB_PD_TCPM_CCGXXF -CONFIG_USB_PD_TCPM_FUSB302 -CONFIG_USB_PD_TCPM_FUSB307 -CONFIG_USB_PD_TCPM_MT6370 -CONFIG_USB_PD_TCPM_NCT38XX -CONFIG_USB_PD_TCPM_PS8 -CONFIG_USB_PD_TCPM_PS8705 -CONFIG_USB_PD_TCPM_PS875 -CONFIG_USB_PD_TCPM_PS8751_CUSTOM_MUX_DRIVER -CONFIG_USB_PD_TCPM_PS8755 -CONFIG_USB_PD_TCPM_RAA489000 -CONFIG_USB_PD_TCPM_STM32GX -CONFIG_USB_PD_TCPM_STUB -CONFIG_USB_PD_TID -CONFIG_USB_PD_TRY_SRC_MIN_BATT_SOC -CONFIG_USB_PD_TX_PHY_ONLY -CONFIG_USB_PD_USB4_DRD -CONFIG_USB_PD_VBUS_DETECT_GPIO -CONFIG_USB_PORT_ENABLE_DYNAMIC -CONFIG_USB_PORT_POWER_SMART -CONFIG_USB_PORT_POWER_SMART_CDP_SDP_ONLY -CONFIG_USB_PORT_POWER_SMART_DEFAULT_MODE -CONFIG_USB_PORT_POWER_SMART_INVERTED -CONFIG_USB_PORT_POWER_SMART_PORT_COUNT -CONFIG_USB_PORT_POWER_SMART_SIMPLE -CONFIG_USB_POWER -CONFIG_USB_RAM_ACCESS_SIZE -CONFIG_USB_RAM_ACCESS_TYPE -CONFIG_USB_RAM_BASE -CONFIG_USB_RAM_SIZE -CONFIG_USB_REMOTE_WAKEUP -CONFIG_USB_SELF_POWERED -CONFIG_USB_SERIALNO -CONFIG_USB_SPI -CONFIG_USB_SUSPEND -CONFIG_USB_UPDATE -CONFIG_VALUE -CONFIG_VBOOT_EFS -CONFIG_VBOOT_EFS2 -CONFIG_WATCHDOG_HELP -CONFIG_WATCHDOG_MAX_RETRIES -CONFIG_WEBUSB_URL -CONFIG_WIRELESS -CONFIG_WIRELESS_CHARGER_P9221_R7 -CONFIG_WIRELESS_SUSPEND -CONFIG_WLAN_POWER_ACTIVE_LOW -CONFIG_WOV_FIFO_THRESH_WORDS -CONFIG_WOV_THRESHOLD_WORDS -CONFIG_WP_ACTIVE_HIGH -CONFIG_WP_ALWAYS -CONFIG_WP_STORAGE_OFF -CONFIG_WP_STORAGE_SIZE -CONFIG_X86_64 -CONFIG_ZEPHYR -CONFIG_ZTEST diff --git a/util/config_option_check.py b/util/config_option_check.py deleted file mode 100755 index 29e8fb8611..0000000000 --- a/util/config_option_check.py +++ /dev/null @@ -1,388 +0,0 @@ -#!/usr/bin/env python3 -# 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. -# -# Ignore indention messages, since legacy scripts use 2 spaces instead of 4. -# pylint: disable=bad-indentation,docstring-section-indent -# pylint: disable=docstring-trailing-quotes - -"""Configuration Option Checker. - -Script to ensure that all configuration options for the Chrome EC are defined -in config.h. -""" -from __future__ import print_function -import enum -import os -import re -import subprocess -import sys - - -class Line(object): - """Class for each changed line in diff output. - - Attributes: - line_num: The integer line number that this line appears in the file. - string: The literal string of this line. - line_type: '+' or '-' indicating if this line was an addition or - deletion. - """ - - def __init__(self, line_num, string, line_type): - """Inits Line with the line number and the actual string.""" - self.line_num = line_num - self.string = string - self.line_type = line_type - - -class Hunk(object): - """Class for a git diff hunk. - - Attributes: - filename: The name of the file that this hunk belongs to. - lines: A list of Line objects that are a part of this hunk. - """ - - def __init__(self, filename, lines): - """Inits Hunk with the filename and the list of lines of the hunk.""" - self.filename = filename - self.lines = lines - - -# Master file which is supposed to include all CONFIG_xxxx descriptions. -CONFIG_FILE = 'include/config.h' - -# Specific files which the checker should ignore. -ALLOWLIST = [CONFIG_FILE, 'util/config_option_check.py'] - -# Specific directories which the checker should ignore. -ALLOW_PATTERN = re.compile('zephyr/.*') - -# Specific CONFIG_* flags which the checker should ignore. -ALLOWLIST_CONFIGS = ['CONFIG_ZTEST'] - -def obtain_current_config_options(): - """Obtains current config options from include/config.h. - - Scans through the master config file defined in CONFIG_FILE for all CONFIG_* - options. - - Returns: - config_options: A list of all the config options in the master CONFIG_FILE. - """ - - config_options = [] - config_option_re = re.compile(r'^#(define|undef)\s+(CONFIG_[A-Z0-9_]+)') - with open(CONFIG_FILE, 'r') as config_file: - for line in config_file: - result = config_option_re.search(line) - if not result: - continue - word = result.groups()[1] - if word not in config_options: - config_options.append(word) - return config_options - -def obtain_config_options_in_use(): - """Obtains all the config options in use in the repo. - - Scans through the entire repo looking for all CONFIG_* options actively used. - - Returns: - options_in_use: A set of all the config options in use in the repo. - """ - file_list = [] - cwd = os.getcwd() - config_option_re = re.compile(r'\b(CONFIG_[a-zA-Z0-9_]+)') - config_debug_option_re = re.compile(r'\b(CONFIG_DEBUG_[a-zA-Z0-9_]+)') - options_in_use = set() - for (dirpath, dirnames, filenames) in os.walk(cwd, topdown=True): - # Ignore the build and private directories (taken from .gitignore) - if 'build' in dirnames: - dirnames.remove('build') - if 'private' in dirnames: - dirnames.remove('private') - for f in filenames: - # Ignore hidden files. - if f.startswith('.'): - continue - # Only consider C source, assembler, and Make-style files. - if (os.path.splitext(f)[1] in ('.c', '.h', '.inc', '.S', '.mk') or - 'Makefile' in f): - file_list.append(os.path.join(dirpath, f)) - - # Search through each file and build a set of the CONFIG_* options being - # used. - - for f in file_list: - if CONFIG_FILE in f: - continue - with open(f, 'r') as cur_file: - for line in cur_file: - match = config_option_re.findall(line) - if match: - for option in match: - if not in_comment(f, line, option): - if option not in options_in_use: - options_in_use.add(option) - - # Since debug options can be turned on at any time, assume that they are - # always in use in case any aren't being used. - - with open(CONFIG_FILE, 'r') as config_file: - for line in config_file: - match = config_debug_option_re.findall(line) - if match: - for option in match: - if not in_comment(CONFIG_FILE, line, option): - if option not in options_in_use: - options_in_use.add(option) - - return options_in_use - -def print_missing_config_options(hunks, config_options): - """Searches thru all the changes in hunks for missing options and prints them. - - Args: - hunks: A list of Hunk objects which represent the hunks from the git - diff output. - config_options: A list of all the config options in the master CONFIG_FILE. - - Returns: - missing_config_option: A boolean indicating if any CONFIG_* options - are missing from the master CONFIG_FILE in this commit or if any CONFIG_* - options removed are no longer being used in the repo. - """ - missing_config_option = False - print_banner = True - deprecated_options = set() - # Determine longest CONFIG_* length to be used for formatting. - max_option_length = max(len(option) for option in config_options) - config_option_re = re.compile(r'\b(CONFIG_[a-zA-Z0-9_]+)') - - # Search for all CONFIG_* options in use in the repo. - options_in_use = obtain_config_options_in_use() - - # Check each hunk's line for a missing config option. - for h in hunks: - for l in h.lines: - # Check for the existence of a CONFIG_* in the line. - match = filter(lambda opt: opt in ALLOWLIST_CONFIGS, - config_option_re.findall(l.string)) - if not match: - continue - - # At this point, an option was found in the line. However, we need to - # verify that it is not within a comment. - violations = set() - - for option in match: - if not in_comment(h.filename, l.string, option): - # Since the CONFIG_* option is not within a comment, we've found a - # violation. We now need to determine if this line is a deletion or - # not. For deletions, we will need to verify if this CONFIG_* option - # is no longer being used in the entire repo. - - if l.line_type == '-': - if option not in options_in_use and option in config_options: - deprecated_options.add(option) - else: - violations.add(option) - - # Check to see if the CONFIG_* option is in the config file and print the - # violations. - for option in match: - if option not in config_options and option in violations: - # Print the banner once. - if print_banner: - print('The following config options were found to be missing ' - 'from %s.\n' - 'Please add new config options there along with ' - 'descriptions.\n\n' % CONFIG_FILE) - print_banner = False - missing_config_option = True - # Print the misssing config option. - print('> %-*s %s:%s' % (max_option_length, option, - h.filename, - l.line_num)) - - if deprecated_options: - print('\n\nThe following config options are being removed and also appear' - ' to be the last uses\nof that option. Please remove these ' - 'options from %s.\n\n' % CONFIG_FILE) - for option in deprecated_options: - print('> %s' % option) - missing_config_option = True - - return missing_config_option - -def in_comment(filename, line, substr): - """Checks if given substring appears in a comment. - - Args: - filename: The filename where this line is from. This is used to determine - what kind of comments to look for. - line: String of line to search in. - substr: Substring to search for in the line. - - Returns: - is_in_comment: Boolean indicating if substr was in a comment. - """ - - c_style_ext = ('.c', '.h', '.inc', '.S') - make_style_ext = ('.mk') - is_in_comment = False - - extension = os.path.splitext(filename)[1] - substr_idx = line.find(substr) - - # Different files have different comment syntax; Handle appropriately. - if extension in c_style_ext: - beg_comment_idx = line.find('/*') - end_comment_idx = line.find('*/') - if end_comment_idx == -1: - end_comment_idx = len(line) - - if beg_comment_idx == -1: - # Check to see if this line is from a multi-line comment. - if line.lstrip().startswith('* '): - # It _seems_ like it is. - is_in_comment = True - else: - # Check to see if its actually inside the comment. - if beg_comment_idx < substr_idx < end_comment_idx: - is_in_comment = True - elif extension in make_style_ext or 'Makefile' in filename: - beg_comment_idx = line.find('#') - # Ignore everything to the right of the hash. - if beg_comment_idx < substr_idx and beg_comment_idx != -1: - is_in_comment = True - return is_in_comment - -def get_hunks(): - """Gets the hunks of the most recent commit. - - States: - new_file: Searching for a new file in the git diff. - filename_search: Searching for the filename of this hunk. - hunk: Searching for the beginning of a new hunk. - lines: Counting line numbers and searching for changes. - - Returns: - hunks: A list of Hunk objects which represent the hunks in the git diff - output. - """ - - diff = [] - hunks = [] - hunk_lines = [] - line = '' - filename = '' - i = 0 - line_num = 0 - - # Regex patterns - new_file_re = re.compile(r'^diff --git') - filename_re = re.compile(r'^[+]{3} (.*)') - hunk_line_num_re = re.compile(r'^@@ -[0-9]+,[0-9]+ \+([0-9]+),[0-9]+ @@.*') - line_re = re.compile(r'^([+| |-])(.*)') - - # Get the diff output. - proc = subprocess.run(['git', 'diff', '--cached', '-GCONFIG_*', '--no-prefix', - '--no-ext-diff', 'HEAD~1'], - stdout=subprocess.PIPE, - encoding='utf-8', - check=True) - diff = proc.stdout.splitlines() - if not diff: - return [] - line = diff[0] - - state = enum.Enum('state', 'NEW_FILE FILENAME_SEARCH HUNK LINES') - current_state = state.NEW_FILE - - while True: - # Search for the beginning of a new file. - if current_state is state.NEW_FILE: - match = new_file_re.search(line) - if match: - current_state = state.FILENAME_SEARCH - - # Search the diff output for a file name. - elif current_state is state.FILENAME_SEARCH: - # Search for a file name. - match = filename_re.search(line) - if match: - filename = match.groups(1)[0] - if filename in ALLOWLIST or ALLOW_PATTERN.match(filename): - # Skip the file if it's allowlisted. - current_state = state.NEW_FILE - else: - current_state = state.HUNK - - # Search for a hunk. Each hunk starts with a line describing the line - # numbers in the file. - elif current_state is state.HUNK: - hunk_lines = [] - match = hunk_line_num_re.search(line) - if match: - # Extract the line number offset. - line_num = int(match.groups(1)[0]) - current_state = state.LINES - - # Start looking for changes. - elif current_state is state.LINES: - # Check if state needs updating. - new_hunk = hunk_line_num_re.search(line) - new_file = new_file_re.search(line) - if new_hunk: - current_state = state.HUNK - hunks.append(Hunk(filename, hunk_lines)) - continue - elif new_file: - current_state = state.NEW_FILE - hunks.append(Hunk(filename, hunk_lines)) - continue - - match = line_re.search(line) - if match: - line_type = match.groups(1)[0] - # We only care about modifications. - if line_type != ' ': - hunk_lines.append(Line(line_num, match.groups(2)[1], line_type)) - # Deletions don't count towards the line numbers. - if line_type != '-': - line_num += 1 - - # Advance to the next line - try: - i += 1 - line = diff[i] - except IndexError: - # We've reached the end of the diff. Return what we have. - if hunk_lines: - hunks.append(Hunk(filename, hunk_lines)) - return hunks - -def main(): - """Searches through committed changes for missing config options. - - Checks through committed changes for CONFIG_* options. Then checks to make - sure that all CONFIG_* options used are defined in include/config.h. Finally, - reports any missing config options. - """ - # Obtain the hunks of the commit to search through. - hunks = get_hunks() - # Obtain config options from include/config.h. - config_options = obtain_current_config_options() - # Find any missing config options from the hunks and print them. - missing_opts = print_missing_config_options(hunks, config_options) - - if missing_opts: - print('\nIt may also be possible that you have a typo.') - sys.exit(1) - -if __name__ == '__main__': - main() 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 <linux/ioctl.h> -#include <linux/types.h> -#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/dedede-relevant-paths.txt b/util/dedede-relevant-paths.txt deleted file mode 100644 index 692e7090a4..0000000000 --- a/util/dedede-relevant-paths.txt +++ /dev/null @@ -1,22 +0,0 @@ -# Here you can place files of interest to be included in the commit message for -# merge commits to firmware-dedede-13606.B -common/charge_state_v2.c -common/mkbp_* -common/ocpc.c -common/usbc/usb_tc_drp_acc_trysrc_sm.c -common/usbc/usb_sm.c -common/usbc/*_pd_* -common/usbc/dp_alt_mode.c -common/usbc/usb_prl_sm.c -common/usbc/usb_pe_drp_sm.c -common/usb_charger.c -common/usb_common.c -common/usbc_ocp.c -driver/charger/sm5803.* -driver/charger/isl923x.* -driver/tcpm/raa489000.* -driver/tcpm/it83* -include/power/icelake.h -include/intel_x86.h -power/icelake.c -power/intel_x86.c
\ No newline at end of file diff --git a/util/ec3po/OWNERS b/util/ec3po/OWNERS deleted file mode 100644 index 5d4c97339d..0000000000 --- a/util/ec3po/OWNERS +++ /dev/null @@ -1,3 +0,0 @@ -aaboagye@chromium.org -coconutruben@chromium.org -matthewb@chromium.org diff --git a/util/ec3po/__init__.py b/util/ec3po/__init__.py deleted file mode 100644 index 376ffdba04..0000000000 --- a/util/ec3po/__init__.py +++ /dev/null @@ -1,21 +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. -""" diff --git a/util/ec3po/console.py b/util/ec3po/console.py deleted file mode 100755 index 9f28c8b7bf..0000000000 --- a/util/ec3po/console.py +++ /dev/null @@ -1,1171 +0,0 @@ -#!/usr/bin/env python -# 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. -""" - -# Note: This is a py2/3 compatible file. - -from __future__ import print_function - -import argparse -import binascii -import ctypes -from datetime import datetime -import logging -import os -import pty -import re -import select -import stat -import sys -import traceback - -import six - -from ec3po import interpreter -from ec3po import threadproc_shim - - -PROMPT = b'> ' -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(br'Enhanced Console is enabled ' - br'\(v([0-9]+\.[0-9]+\.[0-9]+)\)') -NON_ENHANCED_IMAGE_RE = re.compile(br'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. -# List of modes which control when interrogations are performed with the EC. -INTERROGATION_MODES = [b'never', b'always', b'auto'] -# Format for printing host timestamp -HOST_STRFTIME="%y-%m-%d %H:%M:%S.%f" - - -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 = b'' - self.input_buffer_pos = 0 - self.partial_cmd = b'' - 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 = b'' - self.interrogation_mode = b'auto' - self.timestamp_enabled = True - self.look_buffer = b'' - 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: %r' % self.history) - string.append('history_pos: %d' % self.history_pos) - string.append('prompt: %r' % self.prompt) - string.append('partial_cmd: %r'% self.partial_cmd) - string.append('interrogation_mode: %r' % self.interrogation_mode) - string.append('look_buffer: %r' % self.look_buffer) - return '\n'.join(string) - - def LogConsoleOutput(self, data): - """Log to debug user MCU output to master_pty when line is filled. - - The logging also suppresses the Cr50 spinner lines by removing characters - when it sees backspaces. - - Args: - data: bytes - string received from MCU - """ - data = list(data) - # For compatibility with python2 and python3, standardize on the data - # being a list of integers. This requires one more transformation in py2 - if not isinstance(data[0], int): - data = [ord(c) for c in data] - - # This is a list of already filtered characters (or placeholders). - line = self.output_line_log_buffer - - # TODO(b/177480273): use raw strings here - symbols = { - ord(b'\n'): u'\\n', - ord(b'\r'): u'\\r', - ord(b'\t'): u'\\t' - } - # self.logger.debug(u'%s + %r', u''.join(line), ''.join(data)) - while data: - # Recall, data is a list of integers, namely the byte values sent by - # the MCU. - byte = data.pop(0) - # This means that |byte| is an int. - if byte == ord('\n'): - line.append(symbols[byte]) - if line: - self.logger.debug(u'%s', ''.join(line)) - line = [] - elif byte == ord('\b'): - # Backspace: trim the last character off the buffer - if line: - line.pop(-1) - elif byte in symbols: - line.append(symbols[byte]) - elif byte < ord(' ') or byte > ord('~'): - # Turn any character that isn't printable ASCII into escaped hex. - # ' ' is chr(20), and 0-19 are unprintable control characters. - # '~' is chr(126), and 127 is DELETE. 128-255 are control and Latin-1. - line.append(u'\\x%02x' % byte) - else: - # byte is printable. Thus it is safe to use chr() to get the printable - # character out of it again. - line.append(u'%s' % chr(byte)) - self.output_line_log_buffer = line - - 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 = b' %*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: %r', 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 %r', 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 = b'' - # 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, b' ') - # 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(b' ') - 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: %r', 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, b'\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: - tmp_bytes = six.int2byte(byte) - self.pending_oobm_cmd += tmp_bytes - self.logger.debug('%s', tmp_bytes) - os.write(self.master_pty, tmp_bytes) - 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 %r into OOBM command queue.', - self.pending_oobm_cmd) - - # Reset the state. - os.write(self.master_pty, b'\r\n' + self.prompt) - self.input_buffer = b'' - self.input_buffer_pos = 0 - self.receiving_oobm_cmd = False - self.pending_oobm_cmd = b'' - return - - if self.interrogation_mode == b'never': - self.logger.debug('Skipping interrogation because interrogation mode' - ' is set to never.') - elif self.interrogation_mode == b'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(six.int2byte(byte)) - # Reset the input buffer. - self.input_buffer = b'' - 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, b'\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 = b'' - self.input_buffer_pos = 0 - # Reset history buffer pos. - self.history_pos = len(self.history) - # Clear partial command. - self.partial_cmd = b'' - - # 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, six.int2byte(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] + - six.int2byte(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 = b'\033[' + str(count).encode('ascii') - if direction == 'left': - # Bind the movement. - if count > self.input_buffer_pos: - count = self.input_buffer_pos - seq += b'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 += b'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, b'\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: %r', item) - cmd = item.split(b' ') - - if cmd[0] == b'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] == b'timestamp': - mode = cmd[1].lower() - self.timestamp_enabled = (mode == b'on') - self.logger.info('%sabling uart timestamps.', - 'En' if self.timestamp_enabled else 'Dis') - - elif cmd[0] == b'rawdebug': - mode = cmd[1].lower() - self.raw_debug = (mode == b'on') - self.logger.info('%sabling per interrupt debug logs.', - 'En' if self.raw_debug else 'Dis') - - elif cmd[0] == b'interrogate' and len(cmd) >= 2: - enhanced = False - mode = cmd[1] - if len(cmd) >= 3 and cmd[2] == b'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(b'enhanced ' + str(self.enhanced_ec).encode('ascii')) - else: - self.PrintOOBMHelp() - - else: - self.PrintOOBMHelp() - - def PrintOOBMHelp(self): - """Prints out the OOBM help.""" - # Print help syntax. - os.write(self.master_pty, b'\r\n' + b'Known OOBM commands:\r\n') - os.write(self.master_pty, b' interrogate <never | always | auto> ' - b'[enhanced]\r\n') - os.write(self.master_pty, b' loglevel <int>\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(b'enhanced ' + str(self.enhanced_ec).encode('ascii')) - self.logger.debug('Enhanced EC image? %r', self.enhanced_ec) - - # Clear look buffer since a match was found. - self.look_buffer = b'' - - # Move the sliding window. - self.look_buffer = self.look_buffer[-LOOK_BUFFER_SIZE:] - - -def CanonicalizeTimeString(timestr): - """Canonicalize the timestamp string. - - Args: - timestr: A timestamp string ended with 6 digits msec. - - Returns: - A string with 3 digits msec and an extra space. - """ - return timestr[:-3].encode('ascii') + b' ' - - -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->%r', - ('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 == b'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->%r', - ('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 = CanonicalizeTimeString(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(b'\n', 0, end) - now = datetime.now() - tm = CanonicalizeTimeString(now.strftime('\n' + HOST_STRFTIME)) - data_tm = data.replace(b'\n', tm, nls_found) - else: - data_tm = data - - # timestamp required on next input - if data[end] == b'\n'[0]: - 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 - - 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 3a44e0efce..0000000000 --- a/util/ec3po/console_unittest.py +++ /dev/null @@ -1,1569 +0,0 @@ -#!/usr/bin/env python -# 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.""" - -# Note: This is a py2/3 compatible file. - -from __future__ import print_function - -import binascii -import logging -import mock -import tempfile -import unittest - -import six - -from ec3po import console -from ec3po import interpreter -from ec3po import threadproc_shim - -ESC_STRING = six.int2byte(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 += b'[' + str(count).encode('ascii') + b'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 += b'[' + str(count).encode('ascii') + b'C' - return string - -BACKSPACE_STRING = b'' -# Move cursor left 1 column. -BACKSPACE_STRING += OutputStream.MoveCursorLeft(1) -# Write a space. -BACKSPACE_STRING += b' ' -# Move cursor left 1 column. -BACKSPACE_STRING += OutputStream.MoveCursorLeft(1) - -def BytesToByteList(string): - """Converts a bytes string to list of bytes. - - Args: - string: A literal bytes to turn into a list of bytes. - - Returns: - A list of integers representing the byte value of each character in the - string. - """ - if six.PY3: - return [c for c in string] - return [ord(c) for c in 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) - -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, - (b'input buffer does not match expected.\n' - b'expected: |' + exp_input_buffer + b'|\n' - b'got: |' + test_case.console.input_buffer + - b'|\n' + str(test_case.console).encode('ascii'))) - -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], - (b'history buffer contents are incorrect.\n' - b'exp: ' + exp_history[i] + b'\n' - b'got: ' + test_case.console.history[i] + b'\n' - b'internal state:\n' + - str(test_case.console).encode('ascii'))) - - -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 mock pipes. These won't be used since we'll mock out sends - # to the interpreter. - mock_pipe_end_0, mock_pipe_end_1 = threadproc_shim.Pipe() - self.console = console.Console(self.tempfile.fileno(), self.tempfile, - tempfile.TemporaryFile(), - mock_pipe_end_0, mock_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 = b'abc' - input_stream = BytesToByteList(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 = b'spamspam' - input_stream = BytesToByteList(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 * b'o' # All allowed. - test_str += 5 * b'x' # All should be dropped. - input_stream = BytesToByteList(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 * b'o' - exp_console_out = test_str - # Try to fill it even more; these should all be dropped. - test_str += 5 * b'x' - input_stream = BytesToByteList(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(BytesToByteList(b'o')) - exp_console_out += b'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 += b'\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 += b' ' + 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 = b'' - CheckInputBuffer(self, exp_input_buffer) - - # Check that the console output is empty. - exp_console_out = b'' - 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 = b'heelp' - input_stream = BytesToByteList(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 = b'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 += b'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 = b'abc' - input_stream = BytesToByteList(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 = b'version' - input_stream = BytesToByteList(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 = b'version' - input_stream = BytesToByteList(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 = b'sysinfo' - input_stream = BytesToByteList(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 = b'tastyspam' - input_stream = BytesToByteList(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 = b'tastyspam' - input_stream = BytesToByteList(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 = b'version' - input_stream = BytesToByteList(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 = b'panicinfo' - input_stream = BytesToByteList(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 = b'' - 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, b'') - - 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 = b'' - 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, b'') - - def test_KillEntireLine(self): - """Verify that we can kill an entire line with Ctrl+K.""" - test_str = b'accelinfo on' - input_stream = BytesToByteList(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, b'') - - # 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 = b'accelread 0 1' - input_stream = BytesToByteList(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 characters within the line.""" - test_str = b'accel 0 1' # Here we forgot the 'read' part in 'accelread' - input_stream = BytesToByteList(test_str) - # We need to move over to the 'l' and add read. - insertion_point = test_str.find(b'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 = b'read' - input_stream.extend(BytesToByteList(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:i+1] - # 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(b'help') - test_commands.append(b'version') - test_commands.append(b'accelread 0 1') - input_stream = [] - for c in test_commands: - input_stream.extend(BytesToByteList(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 = [b'version', b'accelrange 0', b'battery', b'gettime'] - input_stream = [] - for command in test_commands: - input_stream.extend(BytesToByteList(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 = b'' - for i in range(len(test_commands)): - exp_console_out += test_commands[i] + b'\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 = b'' - exp_input_buffer = b'' - 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 = b'help version' - input_stream = BytesToByteList(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 + b'\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 = [b'version', b'accelrange 0', b'battery', b'gettime'] - input_stream = [] - for command in test_commands: - input_stream.extend(BytesToByteList(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 = b'' - for i in range(len(test_commands)): - exp_console_out += test_commands[i] + b'\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 = b'' # 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 = b'accelinfo' - input_stream = BytesToByteList(test_str) - input_stream.append(console.ControlKey.CARRIAGE_RETURN) - - # Enter a partial command. - partial_cmd = b'ver' - input_stream.extend(BytesToByteList(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 + b'\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 = b'' - exp_input_buffer = b'' - 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 = b'version' - input_stream = BytesToByteList(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:] + b' ' - - # 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 = [b'version', b'accelrange 0', b'battery', b'gettime'] - # Repeat the last command. - test_commands.append(test_commands[len(test_commands)-1]) - - input_stream = [] - for command in test_commands: - input_stream.extend(BytesToByteList(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. - mock_pipe_end_0, mock_pipe_end_1 = mock.MagicMock(), mock.MagicMock() - self.console = console.Console(self.tempfile.fileno(), self.tempfile, - tempfile.TemporaryFile(), - mock_pipe_end_0, mock_pipe_end_1, "EC") - - @mock.patch('ec3po.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 = b'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 = b'version' - input_stream.extend(BytesToByteList(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( - six.int2byte(console.ControlKey.CARRIAGE_RETURN))) - for char in test_command: - if six.PY3: - expected_calls.append(mock.call(bytes([char]))) - else: - expected_calls.append(mock.call(char)) - expected_calls.append(mock.call( - six.int2byte(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, b'') - CheckInputBufferPosition(self, 0) - - @mock.patch('ec3po.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 = b'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 = b'sysinfo' - input_stream = [] - input_stream.extend(BytesToByteList(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: - if six.PY3: - expected_calls.append(mock.call(bytes([char]))) - else: - 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, b'') - CheckInputBufferPosition(self, 0) - # ...and repeat the command. - input_stream = BytesToByteList(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('ec3po.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 = b'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 = b'sysinfo' - input_stream = [] - input_stream.extend(BytesToByteList(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, b'') - CheckInputBufferPosition(self, 0) - - # The carriage return should have passed through though. - expected_calls = [] - expected_calls.append(mock.call( - six.int2byte(console.ControlKey.CARRIAGE_RETURN))) - - # Since the command was dropped, repeat the command. - input_stream = BytesToByteList(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: - if six.PY3: - expected_calls.append(mock.call(bytes([char]))) - else: - expected_calls.append(mock.call(char)) - expected_calls.append(mock.call( - six.int2byte(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 = b'\xff' - self.assertFalse(self.console.CheckForEnhancedECImage()) - - def test_EnhancedCheckUsingBuffer(self): - """Verify that given reboot output, enhanced EC images are detected.""" - enhanced_output_stream = b""" ---- 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(b'\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(b'enhanced True') - - # Now test the non-enhanced EC image. - self.console.cmd_pipe.reset_mock() - non_enhanced_output_stream = b""" ---- 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(b'\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(b'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. - mock_pipe_end_0, mock_pipe_end_1 = mock.MagicMock(), mock.MagicMock() - self.console = console.Console(self.tempfile.fileno(), self.tempfile, - tempfile.TemporaryFile(), - mock_pipe_end_0, mock_pipe_end_1, "EC") - self.console.oobm_queue = mock.MagicMock() - - @mock.patch('ec3po.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 = b'interrogate never' - # Enter the OOBM prompt. - input_stream.extend(BytesToByteList(b'%')) - # Type the command - input_stream.extend(BytesToByteList(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(BytesToByteList(b'version')) - input_stream.append(console.ControlKey.CARRIAGE_RETURN) - input_stream.extend(BytesToByteList(b'flashinfo')) - input_stream.append(console.ControlKey.CARRIAGE_RETURN) - input_stream.extend(BytesToByteList(b'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 = b'interrogate auto' - # Enter the OOBM prompt. - input_stream.extend(BytesToByteList(b'%')) - # Type the command - input_stream.extend(BytesToByteList(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(BytesToByteList(b'version')) - input_stream.append(console.ControlKey.CARRIAGE_RETURN) - input_stream.extend(BytesToByteList(b'flashinfo')) - input_stream.append(console.ControlKey.CARRIAGE_RETURN) - input_stream.extend(BytesToByteList(b'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 = b'interrogate always' - # Enter the OOBM prompt. - input_stream.extend(BytesToByteList(b'%')) - # Type the command - input_stream.extend(BytesToByteList(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(BytesToByteList(b'help list')) - input_stream.append(console.ControlKey.CARRIAGE_RETURN) - input_stream.extend(BytesToByteList(b'taskinfo')) - input_stream.append(console.ControlKey.CARRIAGE_RETURN) - input_stream.extend(BytesToByteList(b'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 = b'interrogate never enhanced' - # Enter the OOBM prompt. - input_stream.extend(BytesToByteList(b'%')) - # Type the command - input_stream.extend(BytesToByteList(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(BytesToByteList(b'chgstate')) - input_stream.append(console.ControlKey.CARRIAGE_RETURN) - input_stream.extend(BytesToByteList(b'hash')) - input_stream.append(console.ControlKey.CARRIAGE_RETURN) - input_stream.extend(BytesToByteList(b'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 4e151083bd..0000000000 --- a/util/ec3po/interpreter.py +++ /dev/null @@ -1,467 +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. -""" - -# Note: This is a py2/3 compatible file. - -from __future__ import print_function - -import binascii -import copy -import logging -import os -import select -import traceback - -import six - - -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 = b'\xec' # Byte indicating EC interrogation. -EC_ACK = b'\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}) - # TODO(https://crbug.com/1162189): revist the 2 TODOs below - # TODO(https://bugs.python.org/issue27805, python3.7+): revert to ab+ - # TODO(https://bugs.python.org/issue20074): removing buffering=0 if/when - # that gets fixed, or keep two pty: one for reading and one for writing - self.ec_uart_pty = open(ec_uart_pty, 'r+b', buffering=0) - 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 = six.moves.queue.Queue() - self.last_cmd = b'' - 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 != b'\r': - # The command format is as follows. - # &&[x][x][x][x]&{cmd}\n\n - packed_cmd = [] - packed_cmd.append(b'&&') - # The first pair of hex digits are the length of the command. - packed_cmd.append(b'%02x' % len(raw_cmd)) - # Then the CRC8 of cmd. - packed_cmd.append(b'%02x' % Crc8(raw_cmd)) - packed_cmd.append(b'&') - # Now, the raw command followed by 2 newlines. - packed_cmd.append(raw_cmd) - packed_cmd.append(b'\n\n') - return b''.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 == b'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 = b'' - # 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 == b'reconnect': - if not self.connected: - self.logger.debug('UART reconnect request.') - # Reopen the PTY. - # TODO(https://bugs.python.org/issue27805, python3.7+): revert to ab+ - # TODO(https://bugs.python.org/issue20074): removing buffering=0 if/when - # that gets fixed, or keep two pty: one for reading and one for writing - fileobj = open(self.ec_uart_pty_name, 'r+b', buffering=0) - 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(b'enhanced'): - self.enhanced_ec = command.split(b' ')[1] == b'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(b' ') - - # There's nothing to do if the command is empty. - if len(command) == 0: - return - - # Handle log level change requests. - if command.startswith(b'loglevel'): - self.logger.debug('Log level change request.') - new_log_level = int(command.split(b' ')[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 = b'' - # 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 b'&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 six.iterbytes(data): - crc ^= (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 - - 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 fe4d43c351..0000000000 --- a/util/ec3po/interpreter_unittest.py +++ /dev/null @@ -1,380 +0,0 @@ -#!/usr/bin/env python -# 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.""" - -# Note: This is a py2/3 compatible file. - -from __future__ import print_function - -import logging -import mock -import tempfile -import unittest - -import six - -from ec3po import interpreter -from ec3po import threadproc_shim - - -def GetBuiltins(func): - if six.PY2: - return '__builtin__.' + func - return 'builtins.' + func - - -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(GetBuiltins('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('ec3po.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, 'r+b', buffering=0)] - # 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 = b'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 = b'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('ec3po.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, 'r+b', buffering=0)] - # 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 = b'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 = [b'&&EE', b'&&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 = b'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 = b'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('ec3po.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 = [b'[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(GetBuiltins('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(b'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(b'taskinfo') - self.itpr.HandleUserData() - self.cmd_pipe_user.send(b'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.encode('utf-8')) - 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(b'reconnect') - - with mock.patch(GetBuiltins('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(b'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(b'reconnect') - - with mock.patch(GetBuiltins('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 ba513abe30..0000000000 --- a/util/ec3po/run_tests.sh +++ /dev/null @@ -1,15 +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. - -set -e - -my_dir="$(realpath -e -- "$(dirname -- "$0")")" -parent_dir="$(realpath -e -- "$my_dir/..")" - -PYTHONPATH="$parent_dir" python3 -s -m unittest \ - ec3po.console_unittest \ - ec3po.interpreter_unittest \ - && touch -- "$my_dir/.tests-passed" diff --git a/util/ec3po/threadproc_shim.py b/util/ec3po/threadproc_shim.py deleted file mode 100644 index da5440b1f3..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 multiprocessing import Pipe -from six.moves.queue import Queue -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 ffa4eca4b7..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 <errno.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#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 = (uint8_t *)(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 ad6867fdc9..0000000000 --- a/util/ec_panicinfo.c +++ /dev/null @@ -1,192 +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 <stdint.h> -#include <stdio.h> -#include <string.h> -#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; -} - -static int parse_panic_info_rv32i(const struct panic_data *pdata) -{ - uint32_t *regs, mcause, mepc; - - regs = (uint32_t *)pdata->riscv.regs; - mcause = pdata->riscv.mcause; - mepc = pdata->riscv.mepc; - - printf("=== EXCEPTION: MCAUSE=%x ===\n", mcause); - printf("S11 %08x S10 %08x S9 %08x S8 %08x\n", - regs[0], regs[1], regs[2], regs[3]); - printf("S7 %08x S6 %08x S5 %08x S4 %08x\n", - regs[4], regs[5], regs[6], regs[7]); - printf("S3 %08x S2 %08x S1 %08x S0 %08x\n", - regs[8], regs[9], regs[10], regs[11]); - printf("T6 %08x T5 %08x T4 %08x T3 %08x\n", - regs[12], regs[13], regs[14], regs[15]); - printf("T2 %08x T1 %08x T0 %08x A7 %08x\n", - regs[16], regs[17], regs[18], regs[19]); - printf("A6 %08x A5 %08x A4 %08x A3 %08x\n", - regs[20], regs[21], regs[22], regs[23]); - printf("A2 %08x A1 %08x A0 %08x TP %08x\n", - regs[24], regs[25], regs[26], regs[27]); - printf("GP %08x RA %08x SP %08x MEPC %08x\n", - regs[28], regs[29], regs[30], mepc); - - return 0; -} - -int parse_panic_info(const char *data, size_t size) -{ - /* Size of the panic information "header". */ - const size_t header_size = 4; - /* Size of the panic information "trailer" (struct_size and magic). */ - const size_t trailer_size = sizeof(struct panic_data) - - offsetof(struct panic_data, struct_size); - - struct panic_data pdata = { 0 }; - size_t copy_size; - - if (size < (header_size + trailer_size)) { - fprintf(stderr, "ERROR: Panic data too short (%zd).\n", size); - return -1; - } - - if (size > sizeof(pdata)) { - fprintf(stderr, "WARNING: Panic data too large (%zd > %zd). " - "Following data may be incorrect!\n", - size, sizeof(pdata)); - copy_size = sizeof(pdata); - } else { - copy_size = size; - } - /* Copy the data into pdata, as the struct size may have changed. */ - memcpy(&pdata, data, copy_size); - /* Then copy the trailer in position. */ - memcpy((char *)&pdata + (sizeof(struct panic_data) - trailer_size), - data + (size - trailer_size), trailer_size); - - /* - * We only understand panic data with version <= 2. Warn the user - * of higher versions. - */ - if (pdata.struct_version > 2) - fprintf(stderr, "WARNING: 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, "WARNING: Incorrect panic magic (%d). " - "Following data may be incorrect!\n", - pdata.magic); - - if (pdata.struct_size != size) - fprintf(stderr, - "WARNING: Panic struct size inconsistent (%u vs %zd). " - "Following data may be incorrect!\n", - pdata.struct_size, size); - - 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); - case PANIC_ARCH_RISCV_RV32I: - return parse_panic_info_rv32i(&pdata); - default: - fprintf(stderr, "ERROR: 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 c61cf797e6..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 char *data, size_t size); - -#endif /* EC_PANICINFO_H */ diff --git a/util/ec_parse_panicinfo.c b/util/ec_parse_panicinfo.c deleted file mode 100644 index 3a2da4590a..0000000000 --- a/util/ec_parse_panicinfo.c +++ /dev/null @@ -1,55 +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 <stdint.h> -#include <stdio.h> -#include "compile_time_macros.h" -#include "ec_panicinfo.h" - -int main(int argc, char *argv[]) -{ - /* - * panic_data size could change with time, as new architecture are - * added (or, less likely, removed). - */ - char pdata[4096]; - size_t size = 0; - size_t read; - - BUILD_ASSERT(sizeof(pdata) > sizeof(struct panic_data)*2); - - /* - * Provide a minimal help message. - */ - if (argc > 1) { - printf("Usage: cat <PANIC_BLOB_PATH> | ec_parse_panicinfo\n"); - printf("Print the plain text panic info from a raw EC panic " - "data blob.\n\n"); - printf("Example:\n"); - printf("ec_parse_panicinfo " - "</sys/kernel/debug/cros_ec/panicinfo\n"); - return 1; - } - - while (1) { - read = fread(&pdata[size], 1, sizeof(pdata)-size, stdin); - if (read < 0) { - fprintf(stderr, "Cannot read panicinfo from stdin.\n"); - return 1; - } - if (read == 0) - break; - - size += read; - if (size == sizeof(pdata)) { - fprintf(stderr, "Too much panicinfo data in stdin.\n"); - return 1; - } - } - - return parse_panic_info(pdata, size) ? 1 : 0; -} diff --git a/util/ec_sb_firmware_update.c b/util/ec_sb_firmware_update.c deleted file mode 100644 index a959cd6fe9..0000000000 --- a/util/ec_sb_firmware_update.c +++ /dev/null @@ -1,846 +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 <errno.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#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(char *data, int offset, int size) -{ - int i = 0; - - if (data == NULL) - return; - - 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/ecst.c b/util/ecst.c deleted file mode 100644 index 95aee7b73d..0000000000 --- a/util/ecst.c +++ /dev/null @@ -1,2486 +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 "compile_time_macros.h" -#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] = {NPCX5M5G_RAM_ADDR, NPCX5M5G_RAM_SIZE}, - [NPCX5M6G] = {NPCX5M6G_RAM_ADDR, NPCX5M6G_RAM_SIZE}, - [NPCX7M5] = {NPCX7M5X_RAM_ADDR, NPCX7M5X_RAM_SIZE}, - [NPCX7M6] = {NPCX7M6X_RAM_ADDR, NPCX7M6X_RAM_SIZE}, - [NPCX7M7] = {NPCX7M7X_RAM_ADDR, NPCX7M7X_RAM_SIZE}, - [NPCX9M3] = {NPCX9M3X_RAM_ADDR, NPCX9M3X_RAM_SIZE}, - [NPCX9M6] = {NPCX9M6X_RAM_ADDR, NPCX9M6X_RAM_SIZE}, -}; -BUILD_ASSERT(ARRAY_SIZE(chip_info) == NPCX_CHIP_RAM_VAR_NONE); - -/* Support chips name strings */ -const char *supported_chips = "npcx5m5g, npcx5m6g, npcx7m5g, npcx7m6g, " - "npcx7m6f, npcx7m6fb, npcx7m6fc, npcx7m7fc, npcx7m7wb, " - "npcx7m7wc, npcx9m3f or npcx9m6f"; - -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; -} - -/** - * Convert the chip name (string) to the chip's RAM variant. - * @param chip_name - the string of the npcx chip variant. - * - * @return one of enum value of npcx_chip_ram_variant, - * NPCX_CHIP_RAM_VAR_NONE otherwise. - */ -static enum npcx_chip_ram_variant chip_to_ram_var(const char *chip_name) -{ - if (str_cmp_no_case(chip_name, "npcx9m6f") == 0) - return NPCX9M6; - else if (str_cmp_no_case(chip_name, "npcx9m3f") == 0) - return NPCX9M3; - else if (str_cmp_no_case(chip_name, "npcx7m7wb") == 0) - return NPCX7M7; - else if (str_cmp_no_case(chip_name, "npcx7m7wc") == 0) - return NPCX7M7; - else if (str_cmp_no_case(chip_name, "npcx7m7fc") == 0) - return NPCX7M7; - else if (str_cmp_no_case(chip_name, "npcx7m6f") == 0) - return NPCX7M6; - else if (str_cmp_no_case(chip_name, "npcx7m6fb") == 0) - return NPCX7M6; - else if (str_cmp_no_case(chip_name, "npcx7m6fc") == 0) - return NPCX7M6; - else if (str_cmp_no_case(chip_name, "npcx7m6g") == 0) - return NPCX7M6; - else if (str_cmp_no_case(chip_name, "npcx7m5g") == 0) - return NPCX7M5; - else if (str_cmp_no_case(chip_name, "npcx5m6g") == 0) - return NPCX5M6G; - else if (str_cmp_no_case(chip_name, "npcx5m5g") == 0) - return NPCX5M5G; - else - return NPCX_CHIP_RAM_VAR_NONE; -} - -/* - *---------------------------------------------------------------------- - * 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 { - enum npcx_chip_ram_variant ram_variant; - - ram_variant = chip_to_ram_var(main_str_temp); - if (ram_variant == NPCX_CHIP_RAM_VAR_NONE) { - my_printf(TERR, - "\nInvalid chip name (%s) ", - main_str_temp); - my_printf(TERR, ", it should be %s.\n", - supported_chips); - main_status = FALSE; - break; - } - - if ((bin_params.bin_params - & BIN_FW_LOAD_START_ADDR) == - 0x00000000) - bin_params.fw_load_addr = - chip_info[ram_variant].ram_addr; - - if ((bin_params.bin_params - & BIN_FW_ENTRY_POINT) == - 0x00000000) - bin_params.fw_ep = - chip_info[ram_variant].ram_addr; - - g_ram_start_address = - chip_info[ram_variant].ram_addr; - g_ram_size = - chip_info[ram_variant].ram_size; - - if ((ram_variant == NPCX5M5G) || - (ram_variant == NPCX5M6G)) { - is_mrider15 = TRUE; - } - } - /* -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) && - (arg_ind < MAX_ARGS); - 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 <bt|bh|api> -i <filename> [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 <type> - Operation mode: "); - my_printf(TUSG, "bt|bh|api (default is bt)"); - my_printf(TUSG, "\n -i <filename> - Input file name; "); - my_printf(TUSG, "must differ from the output file name"); - my_printf(TUSG, "\n -o <filename> - Output file name "); - my_printf(TUSG, "(default is out_<input_filename>.bin)"); - my_printf(TUSG, "\n -argfile <filename> - Arguments file name; "); - my_printf(TUSG, "includes multiple flags"); - my_printf(TUSG, "\n -chip <name> - 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 <val> - SPI Flash Maximum Clock, in"); - my_printf(TUSG, " MHz: 20|25|33|40|50 (default is 20)"); - my_printf(TUSG, "\n -spiclkratio <val> - 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 <type> - 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 <addr> - 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 <addr> - 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 <offset> - 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 <val> - 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 <val> - Firmware length, "); - my_printf(TUSG, "16B-aligned, hex format (default is file size)."); - my_printf(TUSG, "\n -flashsize <val> - Flash size, in MB: "); - my_printf(TUSG, "1|2|4|8|16 (default is 16)"); - my_printf(TUSG, "\n -ph <offset> - 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 <offset> - BootLoader Table location"); - my_printf(TUSG, " in the flash, hex format"); - my_printf(TUSG, "\n -bhoffset <offset> - 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 <type> - 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 04d696c7c5..0000000000 --- a/util/ecst.h +++ /dev/null @@ -1,290 +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 <stdlib.h> -#include <string.h> -#include <stdio.h> -#include <curses.h> - - -/*--------------------------------------------------------------------------- - 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. */ -enum npcx_chip_ram_variant { - NPCX5M5G = 0, - NPCX5M6G = 1, - NPCX7M5 = 2, - NPCX7M6 = 3, - NPCX7M7 = 4, - NPCX9M3 = 5, - NPCX9M6 = 6, - NPCX_CHIP_RAM_VAR_NONE -}; - -#define DEFAULT_CHIP NPCX5M5G - -/* NPCX5 */ -#define NPCX5M5G_RAM_ADDR 0x100A8000 -#define NPCX5M5G_RAM_SIZE 0x20000 -#define NPCX5M6G_RAM_ADDR 0x10088000 -#define NPCX5M6G_RAM_SIZE 0x40000 -/* NPCX7 */ -#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 -/* NPCX9 */ -#define NPCX9M3X_RAM_ADDR 0x10080000 -#define NPCX9M3X_RAM_SIZE 0x50000 -#define NPCX9M6X_RAM_ADDR 0x10090000 -#define NPCX9M6X_RAM_SIZE 0x40000 - -/*--------------------------------------------------------------------------- - 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 c4a3401d59..0000000000 --- a/util/ectool.c +++ /dev/null @@ -1,10964 +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 <ctype.h> -#include <errno.h> -#include <getopt.h> -#include <inttypes.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> -#include <unistd.h> -#include <signal.h> -#include <stdbool.h> - -#include "battery.h" -#include "comm-host.h" -#include "chipset.h" -#include "compile_time_macros.h" -#include "crc.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 "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 <channel>\n" - " Read an ADC channel.\n" - " addentropy [reset]\n" - " Add entropy to device secret\n" - " apreset\n" - " Issue AP reset\n" - " autofanctrl <on>\n" - " Turn on automatic fan speed control.\n" - " backlight <enabled>\n" - " Enable/disable LCD backlight\n" - " basestate [attach | detach | reset]\n" - " Manually force base state to attached, detached or reset.\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" - " button [vup|vdown|rec] <Delay-ms>\n" - " Simulates button press.\n" - " cbi\n" - " Get/Set/Remove 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 <cmd>\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 <mask>\n" - " Clears EC host events flags where mask has bits set\n" - " eventclearb <mask>\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 <mask>\n" - " Sets the SCI mask for EC host events\n" - " eventsetsmimask <mask>\n" - " Sets the SMI mask for EC host events\n" - " eventsetwakemask <mask>\n" - " Sets the wake mask for EC host events\n" - " extpwrlimit\n" - " Set the maximum external power limit\n" - " fanduty <percent>\n" - " Forces the fan PWM to a constant duty cycle\n" - " flasherase <offset> <size>\n" - " Erases EC flash\n" - " flasheraseasync <offset> <size>\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 <dev_id> <port> <filename>\n" - " Flash commands over PD\n" - " flashprotect [now] [enable | disable]\n" - " Prints or sets EC flash protection state\n" - " flashread <offset> <size> <outfile>\n" - " Reads from EC flash to a file\n" - " flashwrite <offset> <infile>\n" - " Writes to EC flash from a file\n" - " forcelidopen <enable>\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 [mode... [capture_type]]\n" - " Configure/Read the fingerprint sensor current mode\n" - " mode: capture|deepsleep|fingerdown|fingerup|enroll|match|\n" - " reset|reset_sensor|maintenance\n" - " capture_type: vendor|pattern0|pattern1|qual|test_reset\n" - " fpseed\n" - " Sets the value of the TPM seed.\n" - " fpstats\n" - " Prints timing statisitcs relating to capture and matching\n" - " fptemplate [<infile>|<index 0..2>]\n" - " Add a template if <infile> is provided, else dump it\n" - " gpioget <GPIO name>\n" - " Get the value of GPIO signal\n" - " gpioset <GPIO name>\n" - " Set the value of GPIO signal\n" - " hangdetect <flags> <event_msec> <reboot_msec> | 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" - " hostevent\n" - " Get & set host event masks.\n" - " i2cprotect <port> [status]\n" - " Protect EC's I2C bus\n" - " i2cread\n" - " Read I2C bus\n" - " i2cwrite\n" - " Write I2C bus\n" - " i2cxfer <port> <peripheral_addr> <read_count> [write bytes...]\n" - " Perform I2C transfer on EC's I2C bus\n" - " infopddev <port>\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 <beat_us> <filename>\n" - " Test low-level key scanning\n" - " led <name> <query | auto | off | <color> | <color>=<value>...>\n" - " Set the color of an LED or query brightness range\n" - " lightbar [CMDS]\n" - " Various lightbar control commands\n" - " mkbpget <buttons|switches>\n" - " Get MKBP buttons/switches supported mask and current state\n" - " mkbpwakemask <get|set> <event|hostevent> [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" - " pchg [<port>]\n" - " Get peripheral charge port count and status\n" - " pdcontrol [suspend|resume|reset|disable|on]\n" - " Controls the PD chip\n" - " pdchipinfo <port>\n" - " Get PD chip information\n" - " pdlog\n" - " Prints the PD event log entries\n" - " pdwritelog <type> <port>\n" - " Writes a PD event log of the given <type>\n" - " pdgetmode <port>\n" - " Get All USB-PD alternate SVIDs and modes on <port>\n" - " pdsetmode <port> <svid> <opos>\n" - " Set USB-PD alternate SVID and mode on <port>\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" - " pse\n" - " Get and set PoE PSE port power status\n" - " pstoreinfo\n" - " Prints information on the EC host persistent storage\n" - " pstoreread <offset> <size> <outfile>\n" - " Reads from EC host persistent storage to a file\n" - " pstorewrite <offset> <infile>\n" - " Writes to EC host persistent storage from a file\n" - " pwmgetfanrpm [<index> | 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 <targetrpm>\n" - " Set target fan RPM\n" - " pwmsetkblight <percent>\n" - " Set keyboard backlight in percent\n" - " pwmsetduty\n" - " Set 16 bit duty cycle of given PWM\n" - " rand <num_bytes>\n" - " generate <num_bytes> of random numbers\n" - " readtest <patternoffset> <size>\n" - " Reads a pattern from the EC via LPC\n" - " reboot_ec <RO|RW|cold|hibernate|hibernate-clear-ap-off|disable-jump|cold-ap-off>" - " [at-shutdown|switch-slot]\n" - " Reboot EC to RO or RW\n" - " reboot_ap_on_g3 [<delay>]\n" - " Requests that the EC will automatically reboot the AP after a\n" - " configurable number of seconds the next time we enter the G3\n" - " power state.\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 <time>\n" - " Set real-time clock\n" - " rtcsetalarm <sec>\n" - " Set real-time clock alarm to go off in <sec> seconds\n" - " rwhashpd <dev_id> <HASH[0] ... <HASH[4]>\n" - " Set entry in PD MCU's device rw_hash table.\n" - " rwsig <info|dump|action|status> ...\n" - " info: get all info about rwsig\n" - " dump: show individual rwsig field\n" - " action: Control the behavior of RWSIG task.\n" - " status: Run RW signature verification and get status.\n{" - " rwsigaction (DEPRECATED; use \"rwsig action\")\n" - " Control the behavior of RWSIG task.\n" - " rwsigstatus (DEPRECATED; use \"rwsig status\"\n" - " Run RW signature verification and get status.\n" - " sertest\n" - " Serial output test for COM2\n" - " smartdischarge\n" - " Set/Get smart discharge parameters\n" - " stress [reboot] [help]\n" - " Stress test the ec host command interface.\n" - " sysinfo [flags|reset_flags|firmware_copy]\n" - " Display system info.\n" - " switches\n" - " Prints current EC switch positions\n" - " temps <sensorid>\n" - " Print temperature.\n" - " tempsinfo <sensorid>\n" - " Print temperature sensor info.\n" - " thermalget <platform-specific args>\n" - " Get the threshold temperature values from the thermal engine.\n" - " thermalset <platform-specific args>\n" - " Set the threshold temperature values for the thermal engine.\n" - " tpselftest\n" - " Run touchpad self test.\n" - " tpframeget\n" - " Get touchpad frame data.\n" - " tmp006cal <tmp006_index> [params...]\n" - " Get/set TMP006 calibration\n" - " tmp006raw <tmp006_index>\n" - " Get raw TMP006 data\n" - " typeccontrol <port> <command>\n" - " Control USB PD policy\n" - " typecdiscovery <port> <type>\n" - " Get discovery information for port and type\n" - " typecstatus <port>\n" - " Get status information for port\n" - " uptimeinfo\n" - " Get info about how long the EC has been running and the most\n" - " recent AP resets\n" - " usbchargemode <port> <mode> [<inhibit_charge>]\n" - " Set USB charging mode\n" - " usbmux <mux>\n" - " Set USB mux switch state\n" - " usbpd <port> <auto | " - "[toggle|toggle-off|sink|source] [none|usb|dp|dock] " - "[dr_swap|pr_swap|vconn_swap]>\n" - " Control USB PD/type-C [deprecated]\n" - " usbpdmuxinfo\n" - " Get USB-C SS mux info\n" - " usbpdpower [port]\n" - " Get USB PD power information\n" - " version\n" - " Prints EC version\n" - " waitevent <type> [<timeout>]\n" - " Wait for the MKBP event of type and display it\n" - " wireless <flags> [<mask> [<suspend_flags> <suspend_mask>]]\n" - " Enable/disable WLAN/Bluetooth radio\n" - ""; - -/* Note: depends on enum ec_image */ -static const char * const image_names[] = {"unknown", "RO", "RW"}; - -/* Note: depends on enum ec_led_colors */ -static const char * const led_color_names[] = { - "red", "green", "blue", "yellow", "white", "amber"}; -BUILD_ASSERT(ARRAY_SIZE(led_color_names) == EC_LED_COLOR_COUNT); - -/* Note: depends on enum ec_led_id */ -static const char * const led_names[] = { - "battery", "power", "adapter", "left", "right", "recovery_hwreinit", - "sysrq debug" }; -BUILD_ASSERT(ARRAY_SIZE(led_names) == EC_LED_ID_COUNT); - -/* ASCII mode for printing, default off */ -static int ascii_mode = 0; - -/* Check SBS numerical value range */ -int is_battery_range(int val) -{ - return (val >= 0 && val <= 65535) ? 1 : 0; -} - -int parse_bool(const char *s, int *dest) -{ - if (!strcasecmp(s, "off") || !strncasecmp(s, "dis", 3) || - tolower(*s) == 'f' || tolower(*s) == 'n') { - *dest = 0; - return 1; - } else if (!strcasecmp(s, "on") || !strncasecmp(s, "ena", 3) || - tolower(*s) == 't' || tolower(*s) == 'y') { - *dest = 1; - return 1; - } else { - return 0; - } -} - -void print_help(const char *prog, int print_cmds) -{ - printf("Usage: %s [--dev=n] [--interface=dev|i2c|lpc] [--i2c_bus=n]", - prog); - printf("[--name=cros_ec|cros_fp|cros_pd|cros_scp|cros_ish] [--ascii] "); - printf("<command> [params]\n\n"); - printf(" --i2c_bus=n Specifies the number of an I2C bus to use. For\n" - " example, to use /dev/i2c-7, pass --i2c_bus=7.\n" - " Implies --interface=i2c.\n\n"); - if (print_cmds) - puts(help_str); - else - printf("Use '%s help' to print a list of commands.\n", prog); -} - -static uint8_t read_mapped_mem8(uint8_t offset) -{ - int ret; - uint8_t val; - - ret = ec_readmem(offset, sizeof(val), &val); - if (ret <= 0) { - fprintf(stderr, "failure in %s(): %d\n", __func__, ret); - exit(1); - } - return val; -} - -static uint16_t read_mapped_mem16(uint8_t offset) -{ - int ret; - uint16_t val; - - ret = ec_readmem(offset, sizeof(val), &val); - if (ret <= 0) { - fprintf(stderr, "failure in %s(): %d\n", __func__, ret); - exit(1); - } - return val; -} - -static uint32_t read_mapped_mem32(uint8_t offset) -{ - int ret; - uint32_t val; - - ret = ec_readmem(offset, sizeof(val), &val); - if (ret <= 0) { - fprintf(stderr, "failure in %s(): %d\n", __func__, ret); - exit(1); - } - return val; -} - -static int read_mapped_string(uint8_t offset, char *buffer, int max_size) -{ - int ret; - - ret = ec_readmem(offset, max_size, buffer); - if (ret <= 0) { - fprintf(stderr, "failure in %s(): %d\n", __func__, ret); - exit(1); - } - return ret; -} - -static int wait_event(long event_type, - struct ec_response_get_next_event_v1 *buffer, - size_t buffer_size, long timeout) -{ - int rv; - - rv = ec_pollevent(1 << event_type, buffer, buffer_size, timeout); - if (rv == 0) { - fprintf(stderr, "Timeout waiting for MKBP event\n"); - return -ETIMEDOUT; - } else if (rv < 0) { - perror("Error polling for MKBP event\n"); - return -EIO; - } - - return rv; -} - -int cmd_adc_read(int argc, char *argv[]) -{ - char *e; - struct ec_params_adc_read p; - struct ec_response_adc_read r; - int rv; - - if (argc < 2) { - fprintf(stderr, "Usage: %s <adc channel>\n", argv[0]); - return -1; - } - - p.adc_channel = (uint8_t)strtoull(argv[1], &e, 0); - if (e && *e) { - fprintf(stderr, "\"%s\": invalid channel!\n", argv[1]); - return -1; - } - - rv = ec_command(EC_CMD_ADC_READ, 0, &p, sizeof(p), &r, sizeof(r)); - if (rv > 0) { - printf("%s: %d\n", argv[1], r.adc_value); - return 0; - } - - return rv; -} - -int cmd_add_entropy(int argc, char *argv[]) -{ - struct ec_params_rollback_add_entropy p; - int rv; - int tries = 100; /* Wait for 10 seconds at most */ - - if (argc >= 2 && !strcmp(argv[1], "reset")) - p.action = ADD_ENTROPY_RESET_ASYNC; - else - p.action = ADD_ENTROPY_ASYNC; - - rv = ec_command(EC_CMD_ADD_ENTROPY, 0, &p, sizeof(p), NULL, 0); - - if (rv != EC_RES_SUCCESS) - goto out; - - while (tries--) { - usleep(100000); - - p.action = ADD_ENTROPY_GET_RESULT; - rv = ec_command(EC_CMD_ADD_ENTROPY, 0, &p, sizeof(p), NULL, 0); - - if (rv == EC_RES_SUCCESS) { - printf("Entropy added successfully\n"); - return EC_RES_SUCCESS; - } - - /* Abort if EC returns an error other than EC_RES_BUSY. */ - if (rv <= -EECRESULT && rv != -EECRESULT-EC_RES_BUSY) - goto out; - } - - rv = -EECRESULT-EC_RES_TIMEOUT; -out: - fprintf(stderr, "Failed to add entropy: %d\n", rv); - return rv; -} - -int cmd_hello(int argc, char *argv[]) -{ - struct ec_params_hello p; - struct ec_response_hello r; - int rv; - - p.in_data = 0xa0b0c0d0; - - rv = ec_command(EC_CMD_HELLO, 0, &p, sizeof(p), &r, sizeof(r)); - if (rv < 0) - return rv; - - if (r.out_data != 0xa1b2c3d4) { - fprintf(stderr, "Expected response 0x%08x, got 0x%08x\n", - 0xa1b2c3d4, r.out_data); - return -1; - } - - printf("EC says hello!\n"); - return 0; -} - -int cmd_hibdelay(int argc, char *argv[]) -{ - struct ec_params_hibernation_delay p; - struct ec_response_hibernation_delay r; - char *e; - int rv; - - if (argc < 2) { - p.seconds = 0; /* Just read the current settings. */ - } else { - p.seconds = strtoull(argv[1], &e, 0); - if (e && *e) { - fprintf(stderr, "invalid number\n"); - return -1; - } - } - - rv = ec_command(EC_CMD_HIBERNATION_DELAY, 0, &p, sizeof(p), - &r, sizeof(r)); - if (rv < 0) { - fprintf(stderr, "err: rv=%d\n", rv); - return -1; - } - - printf("Hibernation delay: %u s\n", r.hibernate_delay); - printf("Time G3: %u s\n", r.time_g3); - printf("Time left: %u s\n", r.time_remaining); - return 0; -} - -static void cmd_hostevent_help(char *cmd) -{ - fprintf(stderr, - " Usage: %s get <type>\n" - " Usage: %s set <type> <value>\n" - " <type> is one of:\n" - " 1: EC_HOST_EVENT_B\n" - " 2: EC_HOST_EVENT_SCI_MASK\n" - " 3: EC_HOST_EVENT_SMI_MASK\n" - " 4: EC_HOST_EVENT_ALWAYS_REPORT_MASK\n" - " 5: EC_HOST_EVENT_ACTIVE_WAKE_MASK\n" - " 6: EC_HOST_EVENT_LAZY_WAKE_MASK_S0IX\n" - " 7: EC_HOST_EVENT_LAZY_WAKE_MASK_S3\n" - " 8: EC_HOST_EVENT_LAZY_WAKE_MASK_S5\n" - , cmd, cmd); -} - -static int cmd_hostevent(int argc, char *argv[]) -{ - struct ec_params_host_event p; - struct ec_response_host_event r; - char *e; - int rv; - - if (argc < 2) { - fprintf(stderr, "Invalid number of params\n"); - cmd_hostevent_help(argv[0]); - return -1; - } - - if (!strcasecmp(argv[1], "get")) { - if (argc != 3) { - fprintf(stderr, "Invalid number of params\n"); - cmd_hostevent_help(argv[0]); - return -1; - } - p.action = EC_HOST_EVENT_GET; - } else if (!strcasecmp(argv[1], "set")) { - if (argc != 4) { - fprintf(stderr, "Invalid number of params\n"); - cmd_hostevent_help(argv[0]); - return -1; - } - p.action = EC_HOST_EVENT_SET; - p.value = strtoull(argv[3], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad value\n"); - return -1; - } - } else { - fprintf(stderr, "Bad subcommand: %s\n", argv[1]); - return -1; - } - - p.mask_type = strtol(argv[2], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad type\n"); - return -1; - } - - rv = ec_command(EC_CMD_HOST_EVENT, 0, &p, sizeof(p), &r, sizeof(r)); - if (rv == -EC_RES_ACCESS_DENIED - EECRESULT) { - fprintf(stderr, "%s isn't permitted for mask %d.\n", - p.action == EC_HOST_EVENT_SET ? "Set" : "Get", - p.mask_type); - return rv; - } else if (rv < 0) { - return rv; - } - - if (p.action == EC_HOST_EVENT_GET) - printf("0x%" PRIx64 "\n", r.value); - - return 0; -} - -static int get_latest_cmd_version(uint8_t cmd, int *version) -{ - struct ec_params_get_cmd_versions p; - struct ec_response_get_cmd_versions r; - int rv; - - *version = 0; - /* Figure out the latest version of the given command the EC supports */ - p.cmd = cmd; - rv = ec_command(EC_CMD_GET_CMD_VERSIONS, 0, &p, sizeof(p), - &r, sizeof(r)); - if (rv < 0) { - if (rv == -EC_RES_INVALID_PARAM) - printf("Command 0x%02x not supported by EC.\n", - EC_CMD_GET_CMD_VERSIONS); - return rv; - } - - if (r.version_mask) - *version = __fls(r.version_mask); - - return rv; -} - -int cmd_hostsleepstate(int argc, char *argv[]) -{ - struct ec_params_host_sleep_event p; - struct ec_params_host_sleep_event_v1 p1; - struct ec_response_host_sleep_event_v1 r; - void *pp = &p; - size_t psize = sizeof(p), rsize = 0; - char *afterscan; - int rv; - int version = 0, max_version = 0; - uint32_t timeout, transitions; - - if (argc < 2) { - fprintf(stderr, "Usage: %s " - "[suspend|wsuspend|resume|freeze|thaw] [timeout]\n", - argv[0]); - return -1; - } - - rv = get_latest_cmd_version(EC_CMD_HOST_SLEEP_EVENT, &max_version); - if (rv < 0) - return rv; - - if (!strcmp(argv[1], "suspend")) - p.sleep_event = HOST_SLEEP_EVENT_S3_SUSPEND; - else if (!strcmp(argv[1], "wsuspend")) - p.sleep_event = HOST_SLEEP_EVENT_S3_WAKEABLE_SUSPEND; - else if (!strcmp(argv[1], "resume")) - p.sleep_event = HOST_SLEEP_EVENT_S3_RESUME; - else if (!strcmp(argv[1], "freeze")) { - p.sleep_event = HOST_SLEEP_EVENT_S0IX_SUSPEND; - if (max_version >= 1) { - p1.sleep_event = p.sleep_event; - p1.reserved = 0; - p1.suspend_params.sleep_timeout_ms = - EC_HOST_SLEEP_TIMEOUT_DEFAULT; - - if (argc > 2) { - p1.suspend_params.sleep_timeout_ms = - strtoull(argv[2], &afterscan, 0); - - if ((*afterscan != '\0') || - (afterscan == argv[2])) { - fprintf(stderr, - "Invalid value: %s\n", - argv[2]); - - return -1; - } - } - - pp = &p1; - psize = sizeof(p1); - version = 1; - } - - } else if (!strcmp(argv[1], "thaw")) { - p.sleep_event = HOST_SLEEP_EVENT_S0IX_RESUME; - if (max_version >= 1) { - version = 1; - rsize = sizeof(r); - } - } else { - fprintf(stderr, "Unknown command: %s\n", argv[1]); - return -1; - } - - rv = ec_command(EC_CMD_HOST_SLEEP_EVENT, version, pp, psize, &r, rsize); - if (rv < 0) { - fprintf(stderr, "EC host sleep command failed: %d\n", rv); - return rv; - } - - if (rsize) { - timeout = r.resume_response.sleep_transitions & - EC_HOST_RESUME_SLEEP_TIMEOUT; - - transitions = r.resume_response.sleep_transitions & - EC_HOST_RESUME_SLEEP_TRANSITIONS_MASK; - - printf("%s%d sleep line transitions.\n", - timeout ? "Timeout: " : "", - transitions); - } - - return 0; -} - -int cmd_test(int argc, char *argv[]) -{ - struct ec_params_test_protocol p = { - .buf = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, - 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, - 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 } - }; - struct ec_response_test_protocol r; - int rv, version = 0; - char *e; - - if (argc < 3) { - fprintf(stderr, "Usage: %s result length [version]\n", - argv[0]); - return -1; - } - - p.ec_result = strtol(argv[1], &e, 0); - if (e && *e) { - fprintf(stderr, "invalid param (result)\n"); - return -1; - } - p.ret_len = strtol(argv[2], &e, 0); - if (e && *e) { - fprintf(stderr, "invalid param (length)\n"); - return -1; - } - - if (argc > 3) { - version = strtol(argv[3], &e, 0); - if (e && *e) { - fprintf(stderr, "invalid param (version)\n"); - return -1; - } - } - - rv = ec_command(EC_CMD_TEST_PROTOCOL, version, - &p, sizeof(p), &r, sizeof(r)); - printf("rv = %d\n", rv); - - return rv; -} - -int cmd_s5(int argc, char *argv[]) -{ - struct ec_params_get_set_value p; - struct ec_params_get_set_value r; - int rv, param; - - p.flags = 0; - - if (argc > 1) { - p.flags |= EC_GSV_SET; - if (!parse_bool(argv[1], ¶m)) { - fprintf(stderr, "invalid arg \"%s\"\n", argv[1]); - return -1; - } - p.value = param; - } - - rv = ec_command(EC_CMD_GSV_PAUSE_IN_S5, 0, - &p, sizeof(p), &r, sizeof(r)); - if (rv > 0) - printf("%s\n", r.value ? "on" : "off"); - - return rv < 0; -} - -static const char * const ec_feature_names[] = { - [EC_FEATURE_LIMITED] = "Limited image, load RW for more", - [EC_FEATURE_FLASH] = "Flash", - [EC_FEATURE_PWM_FAN] = "Direct Fan power management", - [EC_FEATURE_PWM_KEYB] = "Keyboard backlight", - [EC_FEATURE_LIGHTBAR] = "Lightbar", - [EC_FEATURE_LED] = "LED", - [EC_FEATURE_MOTION_SENSE] = "Motion Sensors", - [EC_FEATURE_KEYB] = "Keyboard", - [EC_FEATURE_PSTORE] = "Host Permanent Storage", - [EC_FEATURE_PORT80] = "BIOS Port 80h access", - [EC_FEATURE_THERMAL] = "Thermal management", - [EC_FEATURE_BKLIGHT_SWITCH] = "Switch backlight on/off", - [EC_FEATURE_WIFI_SWITCH] = "Switch wifi on/off", - [EC_FEATURE_HOST_EVENTS] = "Host event", - [EC_FEATURE_GPIO] = "GPIO", - [EC_FEATURE_I2C] = "I2C controller", - [EC_FEATURE_CHARGER] = "Charger", - [EC_FEATURE_BATTERY] = "Simple Battery", - [EC_FEATURE_SMART_BATTERY] = "Smart Battery", - [EC_FEATURE_HANG_DETECT] = "Host hang detection", - [EC_FEATURE_PMU] = "Power Management", - [EC_FEATURE_SUB_MCU] = "Control downstream MCU", - [EC_FEATURE_USB_PD] = "USB Cros Power Delivery", - [EC_FEATURE_USB_MUX] = "USB Multiplexer", - [EC_FEATURE_MOTION_SENSE_FIFO] = "FIFO for Motion Sensors events", - [EC_FEATURE_VSTORE] = "Temporary secure vstore", - [EC_FEATURE_USBC_SS_MUX_VIRTUAL] = "Host-controlled USB-C SS mux", - [EC_FEATURE_RTC] = "Real-time clock", - [EC_FEATURE_FINGERPRINT] = "Fingerprint", - [EC_FEATURE_TOUCHPAD] = "Touchpad", - [EC_FEATURE_RWSIG] = "RWSIG task", - [EC_FEATURE_DEVICE_EVENT] = "Device events reporting", - [EC_FEATURE_UNIFIED_WAKE_MASKS] = "Unified wake masks for LPC/eSPI", - [EC_FEATURE_HOST_EVENT64] = "64-bit host events", - [EC_FEATURE_EXEC_IN_RAM] = "Execute code in RAM", - [EC_FEATURE_CEC] = "Consumer Electronics Control", - [EC_FEATURE_MOTION_SENSE_TIGHT_TIMESTAMPS] = - "Tight timestamp for sensors events", - [EC_FEATURE_REFINED_TABLET_MODE_HYSTERESIS] = - "Refined tablet mode hysteresis", - [EC_FEATURE_EFS2] = "Early Firmware Selection v2", - [EC_FEATURE_ISH] = "Intel Integrated Sensor Hub", - [EC_FEATURE_TYPEC_CMD] = "TCPMv2 Type-C commands", - [EC_FEATURE_TYPEC_REQUIRE_AP_MODE_ENTRY] = - "Host-controlled Type-C mode entry", - [EC_FEATURE_TYPEC_MUX_REQUIRE_AP_ACK] = - "AP ack for Type-C mux configuration", -}; - -int cmd_inventory(int argc, char *argv[]) -{ - struct ec_response_get_features r; - int rv, i, j, idx; - - rv = ec_command(EC_CMD_GET_FEATURES, 0, NULL, 0, &r, sizeof(r)); - if (rv < 0) - return rv; - - printf("EC supported features:\n"); - for (i = 0, idx = 0; i < 2; i++) { - for (j = 0; j < 32; j++, idx++) { - if (r.flags[i] & BIT(j)) { - if (idx >= ARRAY_SIZE(ec_feature_names) || - !ec_feature_names[idx] || - strlen(ec_feature_names[idx]) == 0) - printf("%-4d: Unknown feature\n", idx); - else - printf("%-4d: %s support\n", - idx, ec_feature_names[idx]); - } - } - } - return 0; -} - - -int cmd_cmdversions(int argc, char *argv[]) -{ - struct ec_params_get_cmd_versions p; - struct ec_response_get_cmd_versions r; - char *e; - int cmd; - int rv; - - if (argc < 2) { - fprintf(stderr, "Usage: %s <cmd>\n", argv[0]); - return -1; - } - cmd = strtol(argv[1], &e, 0); - if ((e && *e) || cmd < 0 || cmd > 0xff) { - fprintf(stderr, "Bad command number.\n"); - return -1; - } - - p.cmd = cmd; - rv = ec_command(EC_CMD_GET_CMD_VERSIONS, 0, &p, sizeof(p), - &r, sizeof(r)); - if (rv < 0) { - if (rv == -EC_RES_INVALID_PARAM) - printf("Command 0x%02x not supported by EC.\n", cmd); - - return rv; - } - - printf("Command 0x%02x supports version mask 0x%08x\n", - cmd, r.version_mask); - return 0; -} - -/* - * Convert a reset cause ID to human-readable string, providing total coverage - * of the 'cause' space. The returned string points to static storage and must - * not be free()ed. - */ -static const char *reset_cause_to_str(uint16_t cause) -{ - static const char * const reset_causes[] = { - "(reset unknown)", - "reset: board custom", - "reset: ap hang detected", - "reset: console command", - "reset: host command", - "reset: keyboard sysreset", - "reset: keyboard warm reboot", - "reset: debug warm reboot", - "reset: at AP's request", - "reset: during EC initialization", - "reset: AP watchdog", - }; - BUILD_ASSERT(ARRAY_SIZE(reset_causes) == CHIPSET_RESET_COUNT); - - static const char * const shutdown_causes[] = { - "shutdown: power failure", - "shutdown: during EC initialization", - "shutdown: board custom", - "shutdown: battery voltage startup inhibit", - "shutdown: power wait asserted", - "shutdown: critical battery", - "shutdown: by console command", - "shutdown: entering G3", - "shutdown: thermal", - "shutdown: power button", - }; - BUILD_ASSERT(ARRAY_SIZE(shutdown_causes) == - CHIPSET_SHUTDOWN_COUNT - CHIPSET_SHUTDOWN_BEGIN); - - if (cause < CHIPSET_RESET_COUNT) - return reset_causes[cause]; - - if (cause < CHIPSET_SHUTDOWN_BEGIN) - return "(reset unknown)"; - - if (cause < CHIPSET_SHUTDOWN_COUNT) - return shutdown_causes[cause - CHIPSET_SHUTDOWN_BEGIN]; - - return "(shutdown unknown)"; -} - -int cmd_uptimeinfo(int argc, char *argv[]) -{ - struct ec_response_uptime_info r; - int rv; - int i; - int flag_count; - uint32_t flag; - static const char * const reset_flag_descs[] = { - #include "reset_flag_desc.inc" - }; - - if (argc != 1) { - fprintf(stderr, "uptimeinfo takes no arguments"); - return -1; - } - - rv = ec_command(EC_CMD_GET_UPTIME_INFO, 0, NULL, 0, &r, sizeof(r)); - if (rv < 0) { - fprintf(stderr, "ERROR: EC_CMD_GET_UPTIME_INFO failed; %d\n", - rv); - return rv; - } - - printf("EC uptime: %d.%03d seconds\n", - r.time_since_ec_boot_ms / 1000, - r.time_since_ec_boot_ms % 1000); - - printf("AP resets since EC boot: %d\n", r.ap_resets_since_ec_boot); - - printf("Most recent AP reset causes:\n"); - for (i = 0; i != ARRAY_SIZE(r.recent_ap_reset); ++i) { - if (r.recent_ap_reset[i].reset_time_ms == 0) - continue; - - printf("\t%d.%03d: %s\n", - r.recent_ap_reset[i].reset_time_ms / 1000, - r.recent_ap_reset[i].reset_time_ms % 1000, - reset_cause_to_str(r.recent_ap_reset[i].reset_cause)); - } - - printf("EC reset flags at last EC boot: "); - - if (!r.ec_reset_flags) { - printf("unknown\n"); - return 0; - } - - flag_count = 0; - for (flag = 0; flag < ARRAY_SIZE(reset_flag_descs); ++flag) { - if ((r.ec_reset_flags & BIT(flag)) != 0) { - if (flag_count) - printf(" | "); - printf(reset_flag_descs[flag]); - flag_count++; - } - } - - if (r.ec_reset_flags >= BIT(flag)) { - if (flag_count) - printf(" | "); - printf("no-desc"); - } - printf("\n"); - return 0; -} - -int cmd_version(int argc, char *argv[]) -{ - struct ec_response_get_version_v1 r; - char *build_string = (char *)ec_inbuf; - int rv; - - if (ec_cmd_version_supported(EC_CMD_GET_VERSION, 1)) { - rv = ec_command(EC_CMD_GET_VERSION, 1, NULL, 0, &r, - sizeof(struct ec_response_get_version_v1)); - } else { - /* Fall-back to version 0 if version 1 is not supported */ - rv = ec_command(EC_CMD_GET_VERSION, 0, NULL, 0, &r, - sizeof(struct ec_response_get_version)); - /* These fields are not supported in version 0, ensure empty */ - r.cros_fwid_ro[0] = '\0'; - r.cros_fwid_rw[0] = '\0'; - } - if (rv < 0) { - fprintf(stderr, "ERROR: EC_CMD_GET_VERSION failed: %d\n", rv); - goto exit; - } - - rv = ec_command(EC_CMD_GET_BUILD_INFO, 0, - NULL, 0, ec_inbuf, ec_max_insize); - if (rv < 0) { - fprintf(stderr, "ERROR: EC_CMD_GET_BUILD_INFO failed: %d\n", - rv); - goto exit; - } - - rv = 0; - - /* Ensure versions are null-terminated before we print them */ - r.version_string_ro[sizeof(r.version_string_ro) - 1] = '\0'; - r.version_string_rw[sizeof(r.version_string_rw) - 1] = '\0'; - build_string[ec_max_insize - 1] = '\0'; - r.cros_fwid_ro[sizeof(r.cros_fwid_ro) - 1] = '\0'; - r.cros_fwid_rw[sizeof(r.cros_fwid_rw) - 1] = '\0'; - /* Print versions */ - printf("RO version: %s\n", r.version_string_ro); - if (strlen(r.cros_fwid_ro)) - printf("RO cros fwid: %s\n", r.cros_fwid_ro); - printf("RW version: %s\n", r.version_string_rw); - if (strlen(r.cros_fwid_rw)) - printf("RW cros fwid: %s\n", r.cros_fwid_rw); - printf("Firmware copy: %s\n", - (r.current_image < ARRAY_SIZE(image_names) ? - image_names[r.current_image] : "?")); - printf("Build info: %s\n", build_string); -exit: - printf("Tool version: %s %s %s\n", CROS_ECTOOL_VERSION, DATE, BUILDER); - - return rv; -} - - -int cmd_read_test(int argc, char *argv[]) -{ - struct ec_params_read_test p; - struct ec_response_read_test r; - int offset, size; - int errors = 0; - int rv; - int i; - char *e; - char *buf; - uint32_t *b; - - if (argc < 3) { - fprintf(stderr, "Usage: %s <pattern_offset> <size>\n", argv[0]); - return -1; - } - offset = strtol(argv[1], &e, 0); - size = strtol(argv[2], &e, 0); - if ((e && *e) || size <= 0 || size > MAX_FLASH_SIZE) { - fprintf(stderr, "Bad size.\n"); - return -1; - } - printf("Reading %d bytes with pattern offset 0x%x...\n", size, offset); - - buf = (char *)malloc(size); - if (!buf) { - fprintf(stderr, "Unable to allocate buffer.\n"); - return -1; - } - - /* Read data in chunks */ - for (i = 0; i < size; i += sizeof(r.data)) { - p.offset = offset + i / sizeof(uint32_t); - p.size = MIN(size - i, sizeof(r.data)); - rv = ec_command(EC_CMD_READ_TEST, 0, &p, sizeof(p), - &r, sizeof(r)); - if (rv < 0) { - fprintf(stderr, "Read error at offset %d\n", i); - free(buf); - return rv; - } - memcpy(buf + i, r.data, p.size); - } - - /* Check data */ - for (i = 0, b = (uint32_t *)buf; i < size / 4; i++, b++) { - if (*b != i + offset) { - printf("Mismatch at byte offset 0x%x: " - "expected 0x%08x, got 0x%08x\n", - (int)(i * sizeof(uint32_t)), i + offset, *b); - errors++; - } - } - - free(buf); - if (errors) { - printf("Found %d errors\n", errors); - return -1; - } - - printf("done.\n"); - return 0; -} - - -int cmd_reboot_ec(int argc, char *argv[]) -{ - struct ec_params_reboot_ec p; - int rv, i; - - if (argc < 2) { - /* - * No params specified so tell the EC to reboot immediately. - * That reboots the AP as well, so unlikely we'll be around - * to see a return code from this... - */ - rv = ec_command(EC_CMD_REBOOT, 0, NULL, 0, NULL, 0); - return (rv < 0 ? rv : 0); - } - - /* Parse command */ - if (!strcmp(argv[1], "cancel")) - p.cmd = EC_REBOOT_CANCEL; - else if (!strcmp(argv[1], "RO")) - p.cmd = EC_REBOOT_JUMP_RO; - else if (!strcmp(argv[1], "RW")) - p.cmd = EC_REBOOT_JUMP_RW; - else if (!strcmp(argv[1], "cold")) - p.cmd = EC_REBOOT_COLD; - else if (!strcmp(argv[1], "disable-jump")) - p.cmd = EC_REBOOT_DISABLE_JUMP; - else if (!strcmp(argv[1], "hibernate")) - p.cmd = EC_REBOOT_HIBERNATE; - else if (!strcmp(argv[1], "hibernate-clear-ap-off")) - p.cmd = EC_REBOOT_HIBERNATE_CLEAR_AP_OFF; - else if (!strcmp(argv[1], "cold-ap-off")) - p.cmd = EC_REBOOT_COLD_AP_OFF; - else { - fprintf(stderr, "Unknown command: %s\n", argv[1]); - return -1; - } - - /* Parse flags, if any */ - p.flags = 0; - for (i = 2; i < argc; i++) { - if (!strcmp(argv[i], "at-shutdown")) { - p.flags |= EC_REBOOT_FLAG_ON_AP_SHUTDOWN; - } else if (!strcmp(argv[i], "switch-slot")) { - p.flags |= EC_REBOOT_FLAG_SWITCH_RW_SLOT; - } else { - fprintf(stderr, "Unknown flag: %s\n", argv[i]); - return -1; - } - } - - rv = ec_command(EC_CMD_REBOOT_EC, 0, &p, sizeof(p), NULL, 0); - return (rv < 0 ? rv : 0); -} - -int cmd_reboot_ap_on_g3(int argc, char *argv[]) -{ - struct ec_params_reboot_ap_on_g3_v1 p; - int rv; - char *e; - int cmdver; - - if (argc < 2) { - p.reboot_ap_at_g3_delay = 0; - } else { - p.reboot_ap_at_g3_delay = strtol(argv[1], &e, 0); - if (e && *e) { - fprintf(stderr, "invalid number\n"); - return -1; - } - } - if (ec_cmd_version_supported(EC_CMD_REBOOT_AP_ON_G3, 1)) - cmdver = 1; - else - cmdver = 0; - - rv = ec_command(EC_CMD_REBOOT_AP_ON_G3, cmdver, &p, sizeof(p), NULL, 0); - return (rv < 0 ? rv : 0); -} - -int cmd_button(int argc, char *argv[]) -{ - struct ec_params_button p; - char *e; - int argv_idx; - int button = KEYBOARD_BUTTON_COUNT; - int rv; - - if (argc < 2) { - fprintf(stderr, "Invalid num param %d.\n", argc); - return -1; - } - - p.press_ms = 50; - p.btn_mask = 0; - - for (argv_idx = 1; argv_idx < argc; argv_idx++) { - if (!strcasecmp(argv[argv_idx], "vup")) - button = KEYBOARD_BUTTON_VOLUME_UP; - else if (!strcasecmp(argv[argv_idx], "vdown")) - button = KEYBOARD_BUTTON_VOLUME_DOWN; - else if (!strcasecmp(argv[argv_idx], "rec")) - button = KEYBOARD_BUTTON_RECOVERY; - else { - /* If last parameter check if it is an integer. */ - if (argv_idx == argc - 1) { - p.press_ms = strtol(argv[argv_idx], &e, 0); - /* If integer, break out of the loop. */ - if (!*e) - break; - } - button = KEYBOARD_BUTTON_COUNT; - } - - if (button == KEYBOARD_BUTTON_COUNT) { - fprintf(stderr, "Invalid button input.\n"); - return -1; - } - - p.btn_mask |= (1 << button); - } - if (!p.btn_mask) - return 0; - - rv = ec_command(EC_CMD_BUTTON, 0, &p, sizeof(p), NULL, 0); - if (rv < 0) - return rv; - - printf("Button(s) %d set to %d ms\n", p.btn_mask, p.press_ms); - return 0; -} - -int cmd_flash_info(int argc, char *argv[]) -{ - struct ec_response_flash_info_1 r; - int cmdver = 1; - int rsize = sizeof(r); - int rv; - - memset(&r, 0, sizeof(r)); - - if (!ec_cmd_version_supported(EC_CMD_FLASH_INFO, cmdver)) { - /* Fall back to version 0 command */ - cmdver = 0; - rsize = sizeof(struct ec_response_flash_info); - } - - rv = ec_command(EC_CMD_FLASH_INFO, cmdver, NULL, 0, &r, rsize); - if (rv < 0) - return rv; - - printf("FlashSize %d\nWriteSize %d\nEraseSize %d\nProtectSize %d\n", - r.flash_size, r.write_block_size, r.erase_block_size, - r.protect_block_size); - - if (cmdver >= 1) { - /* Fields added in ver.1 available */ - printf("WriteIdealSize %d\nFlags 0x%x\n", - r.write_ideal_size, r.flags); - } - - return 0; -} - -int cmd_rand(int argc, char *argv[]) -{ - struct ec_params_rand_num p; - struct ec_response_rand_num *r; - size_t r_size; - int64_t num_bytes; - int64_t i; - char *e; - int rv = 0; - - if (argc < 2) { - fprintf(stderr, "Usage: %s <num_bytes>\n", argv[0]); - return -1; - } - - num_bytes = strtol(argv[1], &e, 0); - if ((e && *e) || (errno == ERANGE)) { - fprintf(stderr, "Invalid num_bytes argument\n"); - return -1; - } - - r = (struct ec_response_rand_num *)(ec_inbuf); - - for (i = 0; i < num_bytes; i += ec_max_insize) { - p.num_rand_bytes = ec_max_insize; - if (num_bytes - i < p.num_rand_bytes) - p.num_rand_bytes = num_bytes - i; - - r_size = p.num_rand_bytes; - - rv = ec_command(EC_CMD_RAND_NUM, EC_VER_RAND_NUM, &p, sizeof(p), - r, r_size); - if (rv < 0) { - fprintf(stderr, "Random number command failed\n"); - return -1; - } - - rv = write(STDOUT_FILENO, r->rand, r_size); - if (rv != r_size) { - fprintf(stderr, "Failed to write stdout\n"); - return -1; - } - } - - return 0; -} - -int cmd_flash_spi_info(int argc, char *argv[]) -{ - struct ec_response_flash_spi_info r; - int rv; - - memset(&r, 0, sizeof(r)); - - /* Print SPI flash info if available */ - if (!ec_cmd_version_supported(EC_CMD_FLASH_SPI_INFO, 0)) { - printf("EC has no info (does not use SPI flash?)\n"); - return -1; - } - - rv = ec_command(EC_CMD_FLASH_SPI_INFO, 0, NULL, 0, &r, sizeof(r)); - if (rv < 0) - return rv; - - printf("JEDECManufacturerID 0x%02x\n", r.jedec[0]); - printf("JEDECDeviceID 0x%02x 0x%02x\n", r.jedec[1], r.jedec[2]); - printf("JEDECCapacity %d\n", 1 << r.jedec[2]); - printf("ManufacturerID 0x%02x\n", r.mfr_dev_id[0]); - printf("DeviceID 0x%02x\n", r.mfr_dev_id[1]); - printf("StatusRegister1 0x%02x\n", r.sr1); - printf("StatusRegister2 0x%02x\n", r.sr2); - return 0; -} - -int cmd_flash_read(int argc, char *argv[]) -{ - int offset, size; - int rv; - char *e; - uint8_t *buf; - - if (argc < 4) { - fprintf(stderr, - "Usage: %s <offset> <size> <filename>\n", argv[0]); - return -1; - } - offset = strtol(argv[1], &e, 0); - if ((e && *e) || offset < 0 || offset > MAX_FLASH_SIZE) { - fprintf(stderr, "Bad offset.\n"); - return -1; - } - size = strtol(argv[2], &e, 0); - if ((e && *e) || size <= 0 || size > MAX_FLASH_SIZE) { - fprintf(stderr, "Bad size.\n"); - return -1; - } - printf("Reading %d bytes at offset %d...\n", size, offset); - - buf = (uint8_t *)malloc(size); - if (!buf) { - fprintf(stderr, "Unable to allocate buffer.\n"); - return -1; - } - - /* Read data in chunks */ - rv = ec_flash_read(buf, offset, size); - if (rv < 0) { - free(buf); - return rv; - } - - rv = write_file(argv[3], (const char *)(buf), size); - free(buf); - if (rv) - return rv; - - printf("done.\n"); - return 0; -} - -int cmd_flash_write(int argc, char *argv[]) -{ - int offset, size; - int rv; - char *e; - char *buf; - - if (argc < 3) { - fprintf(stderr, "Usage: %s <offset> <filename>\n", argv[0]); - return -1; - } - - offset = strtol(argv[1], &e, 0); - if ((e && *e) || offset < 0 || offset > MAX_FLASH_SIZE) { - fprintf(stderr, "Bad offset.\n"); - return -1; - } - - /* Read the input file */ - buf = read_file(argv[2], &size); - if (!buf) - return -1; - - printf("Writing to offset %d...\n", offset); - - /* Write data in chunks */ - rv = ec_flash_write((const uint8_t *)(buf), offset, - size); - - free(buf); - - if (rv < 0) - return rv; - - printf("done.\n"); - return 0; -} - -int cmd_flash_erase(int argc, char *argv[]) -{ - int offset, size; - char *e; - int rv; - bool async = false; - - if (argc < 3) { - fprintf(stderr, "Usage: %s <offset> <size>\n", argv[0]); - return -1; - } - - if (strcmp(argv[0], "flasheraseasync") == 0) - async = true; - - offset = strtol(argv[1], &e, 0); - if ((e && *e) || offset < 0 || offset > MAX_FLASH_SIZE) { - fprintf(stderr, "Bad offset.\n"); - return -1; - } - - size = strtol(argv[2], &e, 0); - if ((e && *e) || size <= 0 || size > MAX_FLASH_SIZE) { - fprintf(stderr, "Bad size.\n"); - return -1; - } - - printf("Erasing %d bytes at offset %d...\n", size, offset); - if (async) - rv = ec_flash_erase_async(offset, size); - else - rv = ec_flash_erase(offset, size); - if (rv < 0) - return rv; - - printf("done.\n"); - return 0; -} - - -static void print_flash_protect_flags(const char *desc, uint32_t flags) -{ - printf("%s 0x%08x", desc, flags); - if (flags & EC_FLASH_PROTECT_GPIO_ASSERTED) - printf(" wp_gpio_asserted"); - if (flags & EC_FLASH_PROTECT_RO_AT_BOOT) - printf(" ro_at_boot"); - if (flags & EC_FLASH_PROTECT_RW_AT_BOOT) - printf(" rw_at_boot"); - if (flags & EC_FLASH_PROTECT_ROLLBACK_AT_BOOT) - printf(" rollback_at_boot"); - if (flags & EC_FLASH_PROTECT_ALL_AT_BOOT) - printf(" all_at_boot"); - if (flags & EC_FLASH_PROTECT_RO_NOW) - printf(" ro_now"); - if (flags & EC_FLASH_PROTECT_RW_NOW) - printf(" rw_now"); - if (flags & EC_FLASH_PROTECT_ROLLBACK_NOW) - printf(" rollback_now"); - if (flags & EC_FLASH_PROTECT_ALL_NOW) - printf(" all_now"); - if (flags & EC_FLASH_PROTECT_ERROR_STUCK) - printf(" STUCK"); - if (flags & EC_FLASH_PROTECT_ERROR_INCONSISTENT) - printf(" INCONSISTENT"); - printf("\n"); -} - - -int cmd_flash_protect(int argc, char *argv[]) -{ - struct ec_params_flash_protect p; - struct ec_response_flash_protect r; - int rv, i; - - /* - * Set up requested flags. If no flags were specified, p.mask will - * be 0 and nothing will change. - */ - p.mask = p.flags = 0; - for (i = 1; i < argc; i++) { - if (!strcasecmp(argv[i], "now")) { - p.mask |= EC_FLASH_PROTECT_ALL_NOW; - p.flags |= EC_FLASH_PROTECT_ALL_NOW; - } else if (!strcasecmp(argv[i], "enable")) { - p.mask |= EC_FLASH_PROTECT_RO_AT_BOOT; - p.flags |= EC_FLASH_PROTECT_RO_AT_BOOT; - } else if (!strcasecmp(argv[i], "disable")) - p.mask |= EC_FLASH_PROTECT_RO_AT_BOOT; - } - - rv = ec_command(EC_CMD_FLASH_PROTECT, EC_VER_FLASH_PROTECT, - &p, sizeof(p), &r, sizeof(r)); - if (rv < 0) - return rv; - if (rv < sizeof(r)) { - fprintf(stderr, "Too little data returned.\n"); - return -1; - } - - /* Print returned flags */ - print_flash_protect_flags("Flash protect flags:", r.flags); - print_flash_protect_flags("Valid flags: ", r.valid_flags); - print_flash_protect_flags("Writable flags: ", r.writable_flags); - - /* Check if we got all the flags we asked for */ - if ((r.flags & p.mask) != (p.flags & p.mask)) { - fprintf(stderr, "Unable to set requested flags " - "(wanted mask 0x%08x flags 0x%08x)\n", - p.mask, p.flags); - if (p.mask & ~r.writable_flags) - fprintf(stderr, "Which is expected, because writable " - "mask is 0x%08x.\n", r.writable_flags); - - return -1; - } - - return 0; -} - -int cmd_rw_hash_pd(int argc, char *argv[]) -{ - struct ec_params_usb_pd_rw_hash_entry *p = - (struct ec_params_usb_pd_rw_hash_entry *)ec_outbuf; - int i, rv; - char *e; - uint32_t val; - uint8_t *rwp; - - if (argc < 7) { - fprintf(stderr, "Usage: %s <dev_id> <HASH[0]> ... <HASH[4]>\n", - argv[0]); - return -1; - } - - p->dev_id = strtol(argv[1], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad device ID\n"); - return -1; - } - - rwp = p->dev_rw_hash; - for (i = 2; i < 7; i++) { - val = strtol(argv[i], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad RW hash\n"); - return -1; - } - rwp[0] = (uint8_t) (val >> 0) & 0xff; - rwp[1] = (uint8_t) (val >> 8) & 0xff; - rwp[2] = (uint8_t) (val >> 16) & 0xff; - rwp[3] = (uint8_t) (val >> 24) & 0xff; - rwp += 4; - } - rv = ec_command(EC_CMD_USB_PD_RW_HASH_ENTRY, 0, p, sizeof(*p), NULL, 0); - - return rv; -} - -int cmd_rwsig_status(int argc, char *argv[]) -{ - int rv; - struct ec_response_rwsig_check_status resp; - - rv = ec_command(EC_CMD_RWSIG_CHECK_STATUS, 0, NULL, 0, - &resp, sizeof(resp)); - if (rv < 0) - return rv; - - printf("RW signature check: %s\n", resp.status ? "OK" : "FAILED"); - - return 0; -} - -static int rwsig_action(const char *command) -{ - struct ec_params_rwsig_action req; - - if (!strcasecmp(command, "abort")) - req.action = RWSIG_ACTION_ABORT; - else if (!strcasecmp(command, "continue")) - req.action = RWSIG_ACTION_CONTINUE; - else - return -1; - - return ec_command(EC_CMD_RWSIG_ACTION, 0, &req, sizeof(req), NULL, 0); -} - -int cmd_rwsig_action_legacy(int argc, char *argv[]) -{ - if (argc < 2) { - fprintf(stderr, "Usage: %s [abort | continue]\n", argv[0]); - return -1; - } - - return rwsig_action(argv[1]); -} - -int cmd_rwsig_action(int argc, char *argv[]) -{ - if (argc < 2) { - fprintf(stderr, "Usage: ectool rwsig action [abort | " - "continue]\n"); - return -1; - } - - return rwsig_action(argv[1]); -} - -enum rwsig_info_fields { - RWSIG_INFO_FIELD_SIG_ALG = BIT(0), - RWSIG_INFO_FIELD_KEY_VERSION = BIT(1), - RWSIG_INFO_FIELD_HASH_ALG = BIT(2), - RWSIG_INFO_FIELD_KEY_IS_VALID = BIT(3), - RWSIG_INFO_FIELD_KEY_ID = BIT(4), - RWSIG_INFO_FIELD_ALL = RWSIG_INFO_FIELD_SIG_ALG | - RWSIG_INFO_FIELD_KEY_VERSION | RWSIG_INFO_FIELD_HASH_ALG | - RWSIG_INFO_FIELD_KEY_IS_VALID | RWSIG_INFO_FIELD_KEY_ID -}; - -static int rwsig_info(enum rwsig_info_fields fields) -{ - int i; - int rv; - struct ec_response_rwsig_info r; - bool print_prefix = false; - - rv = ec_command(EC_CMD_RWSIG_INFO, EC_VER_RWSIG_INFO, NULL, 0, &r, - sizeof(r)); - if (rv < 0) { - fprintf(stderr, "rwsig info command failed\n"); - return -1; - } - - if ((fields & RWSIG_INFO_FIELD_ALL) == RWSIG_INFO_FIELD_ALL) - print_prefix = true; - - if (fields & RWSIG_INFO_FIELD_SIG_ALG) { - if (print_prefix) - printf("sig_alg: "); - - printf("%d\n", r.sig_alg); - } - if (fields & RWSIG_INFO_FIELD_KEY_VERSION) { - if (print_prefix) - printf("key_version: "); - - printf("%d\n", r.key_version); - } - if (fields & RWSIG_INFO_FIELD_HASH_ALG) { - if (print_prefix) - printf("hash_alg: "); - - printf("%d\n", r.hash_alg); - } - if (fields & RWSIG_INFO_FIELD_KEY_IS_VALID) { - if (print_prefix) - printf("key_is_valid: "); - - printf("%d\n", r.key_is_valid); - } - if (fields & RWSIG_INFO_FIELD_KEY_ID) { - if (print_prefix) - printf("key_id: "); - - for (i = 0; i < sizeof(r.key_id); i++) - printf("%02x", r.key_id[i]); - printf("\n"); - } - - return 0; -} - -static int cmd_rwsig_info(int argc, char *argv[]) -{ - int i; - - struct rwsig_dump_cmds { - const char *cmd; - enum rwsig_info_fields field; - }; - - struct rwsig_dump_cmds cmd_map[] = { - { "sig_alg", RWSIG_INFO_FIELD_SIG_ALG }, - { "key_version", RWSIG_INFO_FIELD_KEY_VERSION }, - { "hash_alg", RWSIG_INFO_FIELD_HASH_ALG }, - { "key_valid", RWSIG_INFO_FIELD_KEY_IS_VALID }, - { "key_id", RWSIG_INFO_FIELD_KEY_ID }, - }; - - if (argc == 0) - return -1; - - if (strcmp(argv[0], "info") == 0) - return rwsig_info(RWSIG_INFO_FIELD_ALL); - - if (strcmp(argv[0], "dump") == 0) { - if (argc != 2) { - fprintf(stderr, - "Usage: rwsig dump " - "[sig_alg|key_version|hash_alg|key_valid|key_id]\n"); - return -1; - } - for (i = 0; i < ARRAY_SIZE(cmd_map); i++) - if (strcmp(argv[1], cmd_map[i].cmd) == 0) - return rwsig_info(cmd_map[i].field); - - return -1; - } - - return -1; -} - -int cmd_rwsig(int argc, char **argv) -{ - struct rwsig_subcommand { - const char *subcommand; - int (*handler)(int argc, char *argv[]); - }; - - const struct rwsig_subcommand rwsig_subcommands[] = { - { "info", cmd_rwsig_info }, - { "dump", cmd_rwsig_info }, - { "action", cmd_rwsig_action }, - { "status", cmd_rwsig_status } - }; - - int i; - - if (argc < 2) { - fprintf(stderr, "Usage: %s <info|dump|action|status>\n", - argv[0]); - return -1; - } - - for (i = 0; i < ARRAY_SIZE(rwsig_subcommands); i++) - if (strcmp(argv[1], rwsig_subcommands[i].subcommand) == 0) - return rwsig_subcommands[i].handler(--argc, &argv[1]); - - return -1; -} - -enum sysinfo_fields { - SYSINFO_FIELD_NONE = 0, - SYSINFO_FIELD_RESET_FLAGS = BIT(0), - SYSINFO_FIELD_CURRENT_IMAGE = BIT(1), - SYSINFO_FIELD_FLAGS = BIT(2), - SYSINFO_INFO_FIELD_ALL = SYSINFO_FIELD_RESET_FLAGS | - SYSINFO_FIELD_CURRENT_IMAGE | - SYSINFO_FIELD_FLAGS -}; - -static int sysinfo(struct ec_response_sysinfo *info) -{ - int rv; - - rv = ec_command(EC_CMD_SYSINFO, 0, NULL, 0, info, sizeof(*info)); - if (rv < 0) { - fprintf(stderr, "ERROR: EC_CMD_SYSINFO failed: %d\n", rv); - return rv; - } - - return 0; -} - -int cmd_sysinfo(int argc, char **argv) -{ - struct ec_response_sysinfo r; - enum sysinfo_fields fields = SYSINFO_FIELD_NONE; - bool print_prefix = false; - - if (argc != 1 && argc != 2) - goto sysinfo_error_usage; - - if (argc == 1) { - fields = SYSINFO_INFO_FIELD_ALL; - print_prefix = true; - } else if (argc == 2) { - if (strcmp(argv[1], "flags") == 0) - fields = SYSINFO_FIELD_FLAGS; - else if (strcmp(argv[1], "reset_flags") == 0) - fields = SYSINFO_FIELD_RESET_FLAGS; - else if (strcmp(argv[1], "firmware_copy") == 0) - fields = SYSINFO_FIELD_CURRENT_IMAGE; - else - goto sysinfo_error_usage; - } - - memset(&r, '\0', sizeof(r)); - if (sysinfo(&r) != 0) - return -1; - - if (fields & SYSINFO_FIELD_RESET_FLAGS) { - if (print_prefix) - printf("Reset flags: "); - printf("0x%08x\n", r.reset_flags); - } - - if (fields & SYSINFO_FIELD_FLAGS) { - if (print_prefix) - printf("Flags: "); - printf("0x%08x\n", r.flags); - - } - - if (fields & SYSINFO_FIELD_CURRENT_IMAGE) { - if (print_prefix) - printf("Firmware copy: "); - printf("%d\n", r.current_image); - } - - return 0; - -sysinfo_error_usage: - fprintf(stderr, "Usage: %s " - "[flags|reset_flags|firmware_copy]\n", - argv[0]); - return -1; -} - -int cmd_rollback_info(int argc, char *argv[]) -{ - struct ec_response_rollback_info r; - int rv; - - rv = ec_command(EC_CMD_ROLLBACK_INFO, 0, NULL, 0, &r, sizeof(r)); - if (rv < 0) { - fprintf(stderr, "ERROR: EC_CMD_ROLLBACK_INFO failed: %d\n", rv); - return rv; - } - - /* Print versions */ - printf("Rollback block id: %d\n", r.id); - printf("Rollback min version: %d\n", r.rollback_min_version); - printf("RW rollback version: %d\n", r.rw_rollback_version); - - return 0; -} - -int cmd_apreset(int argc, char *argv[]) -{ - return ec_command(EC_CMD_AP_RESET, 0, NULL, 0, NULL, 0); -} - -#define FP_FRAME_INDEX_SIMPLE_IMAGE -1 - -/* - * Download a frame buffer from the FPMCU. - * - * Might be either the finger image or a finger template depending on 'index'. - * - * @param info a pointer to store the struct ec_response_fp_info retrieved by - * this command. - * @param index the specific frame to retrieve, might be: - * -1 (aka FP_FRAME_INDEX_SIMPLE_IMAGE) for the a single grayscale image. - * 0 (aka FP_FRAME_INDEX_RAW_IMAGE) for the full vendor raw finger image. - * 1..n for a finger template. - * - * @returns a pointer to the buffer allocated to contain the frame or NULL - * if case of error. The caller must call free() once it no longer needs the - * buffer. - */ -static void *fp_download_frame(struct ec_response_fp_info *info, int index) -{ - struct ec_params_fp_frame p; - int rv = 0; - size_t stride, size; - void *buffer; - uint8_t *ptr; - int cmdver = ec_cmd_version_supported(EC_CMD_FP_INFO, 1) ? 1 : 0; - int rsize = cmdver == 1 ? sizeof(*info) - : sizeof(struct ec_response_fp_info_v0); - const int max_attempts = 3; - int num_attempts; - - /* templates not supported in command v0 */ - if (index > 0 && cmdver == 0) - return NULL; - - rv = ec_command(EC_CMD_FP_INFO, cmdver, NULL, 0, info, rsize); - if (rv < 0) - return NULL; - - if (index == FP_FRAME_INDEX_SIMPLE_IMAGE) { - size = (size_t)info->width * info->bpp/8 * info->height; - index = FP_FRAME_INDEX_RAW_IMAGE; - } else if (index == FP_FRAME_INDEX_RAW_IMAGE) { - size = info->frame_size; - } else { - size = info->template_size; - } - - buffer = malloc(size); - if (!buffer) { - fprintf(stderr, "Cannot allocate memory for the image\n"); - return NULL; - } - - ptr = (uint8_t *)(buffer); - p.offset = index << FP_FRAME_INDEX_SHIFT; - while (size) { - stride = MIN(ec_max_insize, size); - p.size = stride; - num_attempts = 0; - while (num_attempts < max_attempts) { - num_attempts++; - rv = ec_command(EC_CMD_FP_FRAME, 0, &p, sizeof(p), - ptr, stride); - if (rv >= 0) - break; - if (rv == -EECRESULT - EC_RES_ACCESS_DENIED) - break; - usleep(100000); - } - if (rv < 0) { - free(buffer); - return NULL; - } - p.offset += stride; - size -= stride; - ptr += stride; - } - - return buffer; -} - -int cmd_fp_mode(int argc, char *argv[]) -{ - struct ec_params_fp_mode p; - struct ec_response_fp_mode r; - uint32_t mode = 0; - uint32_t capture_type = FP_CAPTURE_SIMPLE_IMAGE; - int i, rv; - - if (argc == 1) - mode = FP_MODE_DONT_CHANGE; - for (i = 1; i < argc; i++) { - /* modes */ - if (!strncmp(argv[i], "deepsleep", 9)) - mode |= FP_MODE_DEEPSLEEP; - else if (!strncmp(argv[i], "fingerdown", 10)) - mode |= FP_MODE_FINGER_DOWN; - else if (!strncmp(argv[i], "fingerup", 8)) - mode |= FP_MODE_FINGER_UP; - else if (!strncmp(argv[i], "enroll", 6)) - mode |= FP_MODE_ENROLL_IMAGE | FP_MODE_ENROLL_SESSION; - else if (!strncmp(argv[i], "match", 5)) - mode |= FP_MODE_MATCH; - else if (!strncmp(argv[i], "reset_sensor", 12)) - mode = FP_MODE_RESET_SENSOR; - else if (!strncmp(argv[i], "reset", 5)) - mode = 0; - else if (!strncmp(argv[i], "maintenance", 11)) - mode |= FP_MODE_SENSOR_MAINTENANCE; - else if (!strncmp(argv[i], "capture", 7)) - mode |= FP_MODE_CAPTURE; - /* capture types */ - else if (!strncmp(argv[i], "vendor", 6)) - capture_type = FP_CAPTURE_VENDOR_FORMAT; - else if (!strncmp(argv[i], "pattern0", 8)) - capture_type = FP_CAPTURE_PATTERN0; - else if (!strncmp(argv[i], "pattern1", 8)) - capture_type = FP_CAPTURE_PATTERN1; - else if (!strncmp(argv[i], "qual", 4)) - capture_type = FP_CAPTURE_QUALITY_TEST; - else if (!strncmp(argv[i], "test_reset", 10)) - capture_type = FP_CAPTURE_RESET_TEST; - } - if (mode & FP_MODE_CAPTURE) - mode |= capture_type << FP_MODE_CAPTURE_TYPE_SHIFT; - - p.mode = mode; - rv = ec_command(EC_CMD_FP_MODE, 0, &p, sizeof(p), &r, sizeof(r)); - if (rv < 0) - return rv; - - printf("FP mode: (0x%x) ", r.mode); - if (r.mode & FP_MODE_DEEPSLEEP) - printf("deepsleep "); - if (r.mode & FP_MODE_FINGER_DOWN) - printf("finger-down "); - if (r.mode & FP_MODE_FINGER_UP) - printf("finger-up "); - if (r.mode & FP_MODE_ENROLL_SESSION) - printf("enroll%s ", - r.mode & FP_MODE_ENROLL_IMAGE ? "+image" : ""); - if (r.mode & FP_MODE_MATCH) - printf("match "); - if (r.mode & FP_MODE_CAPTURE) - printf("capture "); - printf("\n"); - return 0; -} - -int cmd_fp_seed(int argc, char *argv[]) -{ - struct ec_params_fp_seed p; - char *seed; - - if (argc != 2) { - fprintf(stderr, "Usage: %s <seed>\n", argv[0]); - return 1; - } - seed = argv[1]; - if (strlen(seed) != FP_CONTEXT_TPM_BYTES) { - printf("Invalid seed '%s' is %zd bytes long instead of %d.\n", - seed, strlen(seed), FP_CONTEXT_TPM_BYTES); - return 1; - } - printf("Setting seed '%s'\n", seed); - p.struct_version = FP_TEMPLATE_FORMAT_VERSION; - memcpy(p.seed, seed, FP_CONTEXT_TPM_BYTES); - - return ec_command(EC_CMD_FP_SEED, 0, &p, sizeof(p), NULL, 0); -} - -int cmd_fp_stats(int argc, char *argv[]) -{ - struct ec_response_fp_stats r; - int rv; - unsigned long long ts; - - rv = ec_command(EC_CMD_FP_STATS, 0, NULL, 0, &r, sizeof(r)); - if (rv < 0) - return rv; - - ts = (uint64_t)r.overall_t0.hi << 32 | r.overall_t0.lo; - printf("FP stats (t0=%llu us):\n", ts); - printf("Last capture time: "); - if (r.timestamps_invalid & FPSTATS_CAPTURE_INV) - printf("Invalid\n"); - else - printf("%d us\n", r.capture_time_us); - - printf("Last matching time: "); - if (r.timestamps_invalid & FPSTATS_MATCHING_INV) - printf("Invalid\n"); - else - printf("%d us (finger: %d)\n", r.matching_time_us, - r.template_matched); - - printf("Last overall time: "); - if (r.timestamps_invalid) - printf("Invalid\n"); - else - printf("%d us\n", r.overall_time_us); - - return 0; -} - -int cmd_fp_info(int argc, char *argv[]) -{ - struct ec_response_fp_info r; - int rv; - int cmdver = ec_cmd_version_supported(EC_CMD_FP_INFO, 1) ? 1 : 0; - int rsize = cmdver == 1 ? sizeof(r) - : sizeof(struct ec_response_fp_info_v0); - uint16_t dead; - - rv = ec_command(EC_CMD_FP_INFO, cmdver, NULL, 0, &r, rsize); - if (rv < 0) - return rv; - - printf("Fingerprint sensor: vendor %x product %x model %x version %x\n", - r.vendor_id, r.product_id, r.model_id, r.version); - printf("Image: size %dx%d %d bpp\n", r.width, r.height, r.bpp); - printf("Error flags: %s%s%s%s\n", - r.errors & FP_ERROR_NO_IRQ ? "NO_IRQ " : "", - r.errors & FP_ERROR_SPI_COMM ? "SPI_COMM " : "", - r.errors & FP_ERROR_BAD_HWID ? "BAD_HWID " : "", - r.errors & FP_ERROR_INIT_FAIL ? "INIT_FAIL " : ""); - dead = FP_ERROR_DEAD_PIXELS(r.errors); - if (dead == FP_ERROR_DEAD_PIXELS_UNKNOWN) { - printf("Dead pixels: UNKNOWN\n"); - } else { - printf("Dead pixels: %u\n", dead); - } - - if (cmdver == 1) { - printf("Templates: version %d size %d count %d/%d" - " dirty bitmap %x\n", - r.template_version, r.template_size, r.template_valid, - r.template_max, r.template_dirty); - } - - return 0; -} - -static void print_fp_enc_flags(const char *desc, uint32_t flags) -{ - printf("%s 0x%08x", desc, flags); - if (flags & FP_ENC_STATUS_SEED_SET) - printf(" FPTPM_seed_set"); - printf("\n"); -} - -static int cmd_fp_context(int argc, char *argv[]) -{ - struct ec_params_fp_context_v1 p; - int rv; - int tries = 20; /* Wait at most two seconds */ - - if (argc < 2) { - fprintf(stderr, "Usage: %s <context>\n", argv[0]); - return -1; - } - - /* - * Note that we treat the resulting "userid" as raw byte array, so we - * don't want to copy the NUL from the end of the string. - */ - if (strlen(argv[1]) != sizeof(p.userid)) { - fprintf(stderr, "Context must be exactly %zu bytes\n", - sizeof(p.userid)); - return -1; - } - - p.action = FP_CONTEXT_ASYNC; - memcpy(p.userid, argv[1], sizeof(p.userid)); - - rv = ec_command(EC_CMD_FP_CONTEXT, 1, &p, sizeof(p), NULL, 0); - - if (rv != EC_RES_SUCCESS) - goto out; - - while (tries--) { - usleep(100000); - - p.action = FP_CONTEXT_GET_RESULT; - rv = ec_command(EC_CMD_FP_CONTEXT, 1, &p, sizeof(p), NULL, 0); - - if (rv == EC_RES_SUCCESS) { - printf("Set context successfully\n"); - return EC_RES_SUCCESS; - } - - /* Abort if EC returns an error other than EC_RES_BUSY. */ - if (rv <= -EECRESULT && rv != -EECRESULT - EC_RES_BUSY) - goto out; - } - - rv = -EECRESULT - EC_RES_TIMEOUT; - -out: - fprintf(stderr, "Failed to reset context: %d\n", rv); - return rv; -} - -int cmd_fp_enc_status(int argc, char *argv[]) -{ - int rv; - struct ec_response_fp_encryption_status resp = { 0 }; - - rv = ec_command(EC_CMD_FP_ENC_STATUS, 0, NULL, 0, &resp, sizeof(resp)); - if (rv < 0) { - printf("Get FP sensor encryption status failed.\n"); - } else { - print_fp_enc_flags("FPMCU encryption status:", resp.status); - print_fp_enc_flags("Valid flags: ", - resp.valid_flags); - rv = 0; - } - return rv; -} - -int cmd_fp_frame(int argc, char *argv[]) -{ - struct ec_response_fp_info r; - int idx = (argc == 2 && !strcasecmp(argv[1], "raw")) ? - FP_FRAME_INDEX_RAW_IMAGE : FP_FRAME_INDEX_SIMPLE_IMAGE; - uint8_t *buffer = (uint8_t *)(fp_download_frame(&r, idx)); - uint8_t *ptr = buffer; - int x, y; - - if (!buffer) { - fprintf(stderr, "Failed to get FP sensor frame\n"); - return -1; - } - - if (idx == FP_FRAME_INDEX_RAW_IMAGE) { - fwrite(buffer, r.frame_size, 1, stdout); - goto frame_done; - } - - /* Print 8-bpp PGM ASCII header */ - printf("P2\n%d %d\n%d\n", r.width, r.height, (1 << r.bpp) - 1); - - for (y = 0; y < r.height; y++) { - for (x = 0; x < r.width; x++, ptr++) - printf("%d ", *ptr); - printf("\n"); - } - printf("# END OF FILE\n"); -frame_done: - free(buffer); - return 0; -} - -int cmd_fp_template(int argc, char *argv[]) -{ - struct ec_response_fp_info r; - struct ec_params_fp_template *p = - (struct ec_params_fp_template *)(ec_outbuf); - /* TODO(b/78544921): removing 32 bits is a workaround for the MCU bug */ - int max_chunk = ec_max_outsize - - offsetof(struct ec_params_fp_template, data) - 4; - int idx = -1; - char *e; - int size; - char *buffer = NULL; - uint32_t offset = 0; - int rv = 0; - - if (argc < 2) { - fprintf(stderr, "Usage: %s [<infile>|<index>]\n", argv[0]); - return -1; - } - - idx = strtol(argv[1], &e, 0); - if (!(e && *e)) { - buffer = (char *)(fp_download_frame(&r, idx + 1)); - if (!buffer) { - fprintf(stderr, "Failed to get FP template %d\n", idx); - return -1; - } - fwrite(buffer, r.template_size, 1, stdout); - free(buffer); - return 0; - } - /* not an index, is it a filename ? */ - buffer = read_file(argv[1], &size); - if (!buffer) { - fprintf(stderr, "Invalid parameter: %s\n", argv[1]); - return -1; - } - printf("sending template from: %s (%d bytes)\n", argv[1], size); - while (size) { - uint32_t tlen = MIN(max_chunk, size); - - p->offset = offset; - p->size = tlen; - size -= tlen; - if (!size) - p->size |= FP_TEMPLATE_COMMIT; - memcpy(p->data, buffer + offset, tlen); - rv = ec_command(EC_CMD_FP_TEMPLATE, 0, p, tlen + - offsetof(struct ec_params_fp_template, data), - NULL, 0); - if (rv < 0) - break; - offset += tlen; - } - if (rv < 0) - fprintf(stderr, "Failed with %d\n", rv); - else - rv = 0; - free(buffer); - return rv; -} - -/** - * determine if in GFU mode or not. - * - * NOTE, Sends HOST commands that modify ec_outbuf contents. - * - * @opos return value of GFU mode object position or zero if not found - * @port port number to query - * @return 1 if in GFU mode, 0 if not, -1 if error - */ -static int in_gfu_mode(int *opos, int port) -{ - int i; - struct ec_params_usb_pd_get_mode_request *p = - (struct ec_params_usb_pd_get_mode_request *)ec_outbuf; - struct ec_params_usb_pd_get_mode_response *r = - (struct ec_params_usb_pd_get_mode_response *)ec_inbuf; - p->port = port; - p->svid_idx = 0; - do { - ec_command(EC_CMD_USB_PD_GET_AMODE, 0, p, sizeof(*p), - ec_inbuf, ec_max_insize); - if (!r->svid || (r->svid == USB_VID_GOOGLE)) - break; - p->svid_idx++; - } while (p->svid_idx < SVID_DISCOVERY_MAX); - - if (r->svid != USB_VID_GOOGLE) { - fprintf(stderr, "Google VID not returned\n"); - return -1; - } - - *opos = 0; /* invalid ... must be 1 thru 6 */ - for (i = 0; i < PDO_MODES; i++) { - if (r->vdo[i] == MODE_GOOGLE_FU) { - *opos = i + 1; - break; - } - } - - return r->opos == *opos; -} - -/** - * Enter GFU mode. - * - * NOTE, Sends HOST commands that modify ec_outbuf contents. - * - * @port port number to enter GFU on. - * @return 1 if entered GFU mode, 0 if not, -1 if error - */ -static int enter_gfu_mode(int port) -{ - int opos; - struct ec_params_usb_pd_set_mode_request *p = - (struct ec_params_usb_pd_set_mode_request *)ec_outbuf; - int gfu_mode = in_gfu_mode(&opos, port); - - if (gfu_mode < 0) { - fprintf(stderr, "Failed to query GFU mode support\n"); - return 0; - } else if (!gfu_mode) { - if (!opos) { - fprintf(stderr, "Invalid object position %d\n", opos); - return 0; - } - p->port = port; - p->svid = USB_VID_GOOGLE; - p->opos = opos; - p->cmd = PD_ENTER_MODE; - - ec_command(EC_CMD_USB_PD_SET_AMODE, 0, p, sizeof(*p), - NULL, 0); - usleep(500000); /* sleep to allow time for set mode */ - gfu_mode = in_gfu_mode(&opos, port); - } - return gfu_mode; -} - -int cmd_pd_device_info(int argc, char *argv[]) -{ - int i, rv, port; - char *e; - struct ec_params_usb_pd_info_request *p = - (struct ec_params_usb_pd_info_request *)ec_outbuf; - struct ec_params_usb_pd_rw_hash_entry *r0 = - (struct ec_params_usb_pd_rw_hash_entry *)ec_inbuf; - struct ec_params_usb_pd_discovery_entry *r1; - - if (argc < 2) { - fprintf(stderr, "Usage: %s <port>\n", argv[0]); - return -1; - } - - port = strtol(argv[1], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad port\n"); - return -1; - } - - p->port = port; - r1 = (struct ec_params_usb_pd_discovery_entry *)ec_inbuf; - rv = ec_command(EC_CMD_USB_PD_DISCOVERY, 0, p, sizeof(*p), - ec_inbuf, ec_max_insize); - if (rv < 0) - return rv; - - if (!r1->vid) - printf("Port:%d has no discovered device\n", port); - else { - printf("Port:%d ptype:%d vid:0x%04x pid:0x%04x\n", port, - r1->ptype, r1->vid, r1->pid); - } - - if (enter_gfu_mode(port) != 1) { - fprintf(stderr, "Failed to enter GFU mode\n"); - return -1; - } - - p->port = port; - rv = ec_command(EC_CMD_USB_PD_DEV_INFO, 0, p, sizeof(*p), - ec_inbuf, ec_max_insize); - if (rv < 0) - return rv; - - if (!r0->dev_id) - printf("Port:%d has no valid device\n", port); - else { - uint8_t *rwp = r0->dev_rw_hash; - printf("Port:%d DevId:%d.%d Hash:", port, - HW_DEV_ID_MAJ(r0->dev_id), HW_DEV_ID_MIN(r0->dev_id)); - for (i = 0; i < 5; i++) { - printf(" 0x%02x%02x%02x%02x", rwp[3], rwp[2], rwp[1], - rwp[0]); - rwp += 4; - } - printf(" CurImg:%s\n", image_names[r0->current_image]); - } - - return rv; -} - -int cmd_flash_pd(int argc, char *argv[]) -{ - struct ec_params_usb_pd_fw_update *p = - (struct ec_params_usb_pd_fw_update *)ec_outbuf; - int i, dev_id, port; - int rv, fsize, step = 96; - char *e; - char *buf; - char *data = (char *)p + sizeof(*p); - - if (argc < 4) { - fprintf(stderr, "Usage: %s <dev_id> <port> <filename>\n", - argv[0]); - return -1; - } - - dev_id = strtol(argv[1], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad device ID\n"); - return -1; - } - - port = strtol(argv[2], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad port\n"); - return -1; - } - - if (enter_gfu_mode(port) != 1) { - fprintf(stderr, "Failed to enter GFU mode\n"); - return -1; - } - - /* Read the input file */ - buf = read_file(argv[3], &fsize); - if (!buf) - return -1; - - /* Erase the current RW RSA signature */ - fprintf(stderr, "Erasing expected RW hash\n"); - p->dev_id = dev_id; - p->port = port; - p->cmd = USB_PD_FW_ERASE_SIG; - p->size = 0; - rv = ec_command(EC_CMD_USB_PD_FW_UPDATE, 0, - p, p->size + sizeof(*p), NULL, 0); - - if (rv < 0) - goto pd_flash_error; - - /* Reboot */ - fprintf(stderr, "Rebooting\n"); - p->dev_id = dev_id; - p->port = port; - p->cmd = USB_PD_FW_REBOOT; - p->size = 0; - rv = ec_command(EC_CMD_USB_PD_FW_UPDATE, 0, - p, p->size + sizeof(*p), NULL, 0); - - if (rv < 0) - goto pd_flash_error; - - usleep(3000000); /* 3sec to reboot and get CC line idle */ - - /* re-enter GFU after reboot */ - if (enter_gfu_mode(port) != 1) { - fprintf(stderr, "Failed to enter GFU mode\n"); - goto pd_flash_error; - } - - /* Erase RW flash */ - fprintf(stderr, "Erasing RW flash\n"); - p->dev_id = dev_id; - p->port = port; - p->cmd = USB_PD_FW_FLASH_ERASE; - p->size = 0; - rv = ec_command(EC_CMD_USB_PD_FW_UPDATE, 0, - p, p->size + sizeof(*p), NULL, 0); - - /* 3 secs should allow ample time for 2KB page erases at 40ms */ - usleep(3000000); - - if (rv < 0) - goto pd_flash_error; - - /* Write RW flash */ - fprintf(stderr, "Writing RW flash\n"); - p->dev_id = dev_id; - p->port = port; - p->cmd = USB_PD_FW_FLASH_WRITE; - p->size = step; - - for (i = 0; i < fsize; i += step) { - p->size = MIN(fsize - i, step); - memcpy(data, buf + i, p->size); - rv = ec_command(EC_CMD_USB_PD_FW_UPDATE, 0, - p, p->size + sizeof(*p), NULL, 0); - if (rv < 0) - goto pd_flash_error; - - /* - * TODO(crosbug.com/p/33905) throttle so EC doesn't watchdog on - * other tasks. Remove once issue resolved. - */ - usleep(10000); - } - - /* 100msec to guarantee writes finish */ - usleep(100000); - - /* Reboot into new RW */ - fprintf(stderr, "Rebooting PD into new RW\n"); - p->cmd = USB_PD_FW_REBOOT; - p->size = 0; - rv = ec_command(EC_CMD_USB_PD_FW_UPDATE, 0, - p, p->size + sizeof(*p), NULL, 0); - - if (rv < 0) - goto pd_flash_error; - - free(buf); - fprintf(stderr, "Complete\n"); - return 0; - -pd_flash_error: - free(buf); - fprintf(stderr, "PD flash error\n"); - return -1; -} - -int cmd_pd_set_amode(int argc, char *argv[]) -{ - char *e; - struct ec_params_usb_pd_set_mode_request *p = - (struct ec_params_usb_pd_set_mode_request *)ec_outbuf; - - if (argc < 5) { - fprintf(stderr, "Usage: %s <port> <svid> <opos> <cmd>\n", - argv[0]); - return -1; - } - - p->port = strtol(argv[1], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad port\n"); - return -1; - } - - p->svid = strtol(argv[2], &e, 0); - if ((e && *e) || !p->svid) { - fprintf(stderr, "Bad svid\n"); - return -1; - } - - p->opos = strtol(argv[3], &e, 0); - if ((e && *e) || !p->opos) { - fprintf(stderr, "Bad opos\n"); - return -1; - } - - p->cmd = strtol(argv[4], &e, 0); - if ((e && *e) || (p->cmd >= PD_MODE_CMD_COUNT)) { - fprintf(stderr, "Bad cmd\n"); - return -1; - } - return ec_command(EC_CMD_USB_PD_SET_AMODE, 0, p, sizeof(*p), NULL, 0); -} - -int cmd_pd_get_amode(int argc, char *argv[]) -{ - int i; - char *e; - struct ec_params_usb_pd_get_mode_request *p = - (struct ec_params_usb_pd_get_mode_request *)ec_outbuf; - struct ec_params_usb_pd_get_mode_response *r = - (struct ec_params_usb_pd_get_mode_response *)ec_inbuf; - - if (argc < 2) { - fprintf(stderr, "Usage: %s <port>\n", argv[0]); - return -1; - } - - p->port = strtol(argv[1], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad port\n"); - return -1; - } - - p->svid_idx = 0; - do { - ec_command(EC_CMD_USB_PD_GET_AMODE, 0, p, sizeof(*p), - ec_inbuf, ec_max_insize); - if (!r->svid) - break; - printf("%cSVID:0x%04x ", (r->opos) ? '*' : ' ', - r->svid); - for (i = 0; i < PDO_MODES; i++) { - printf("%c0x%08x ", (r->opos && (r->opos == i + 1)) ? - '*' : ' ', r->vdo[i]); - } - printf("\n"); - p->svid_idx++; - } while (p->svid_idx < SVID_DISCOVERY_MAX); - return -1; -} - -/* The I/O asm funcs exist only on x86. */ -#if defined(__i386__) || defined(__x86_64__) -#include <sys/io.h> - -int cmd_serial_test(int argc, char *argv[]) -{ - const char *c = "COM2 sample serial output from host!\r\n"; - - printf("Writing sample serial output to COM2\n"); - - while (*c) { - /* Wait for space in transmit FIFO */ - while (!(inb(0x2fd) & 0x20)) - ; - - /* Put the next character */ - outb(*c++, 0x2f8); - } - - printf("done.\n"); - return 0; -} - - -int cmd_port_80_flood(int argc, char *argv[]) -{ - int i; - - for (i = 0; i < 256; i++) - outb(i, 0x80); - return 0; -} -#else -int cmd_serial_test(int argc, char *argv[]) -{ - printf("x86 specific command\n"); - return -1; -} - -int cmd_port_80_flood(int argc, char *argv[]) -{ - printf("x86 specific command\n"); - return -1; -} -#endif - -static void cmd_smart_discharge_usage(const char *command) -{ - printf("Usage: %s [hours_to_zero [hibern] [cutoff]]\n", command); - printf("\n"); - printf("Set/Get smart discharge parameters\n"); - printf("hours_to_zero: Desired hours for state of charge to zero\n"); - printf("hibern: Discharge rate in hibernation (uA)\n"); - printf("cutoff: Discharge rate in battery cutoff (uA)\n"); -} - -int cmd_smart_discharge(int argc, char *argv[]) -{ - struct ec_params_smart_discharge *p = - (struct ec_params_smart_discharge *)(ec_outbuf); - struct ec_response_smart_discharge *r = - (struct ec_response_smart_discharge *)(ec_inbuf); - uint32_t cap; - char *e; - int rv; - - if (argc > 1) { - if (strcmp(argv[1], "help") == 0) { - cmd_smart_discharge_usage(argv[0]); - return 0; - } - p->flags = EC_SMART_DISCHARGE_FLAGS_SET; - p->hours_to_zero = strtol(argv[1], &e, 0); - if (p->hours_to_zero < 0 || (e && *e)) { - perror("Bad value for [hours_to_zero]"); - return -1; - } - if (argc == 4) { - p->drate.hibern = strtol(argv[2], &e, 0); - if (p->drate.hibern < 0 || (e && *e)) { - perror("Bad value for [hibern]"); - return -1; - } - p->drate.cutoff = strtol(argv[3], &e, 0); - if (p->drate.cutoff < 0 || (e && *e)) { - perror("Bad value for [cutoff]"); - return -1; - } - } else if (argc != 2) { - /* If argc != 4, it has to be 2. */ - perror("Invalid number of parameters"); - return -1; - } - } - - rv = ec_command(EC_CMD_SMART_DISCHARGE, 0, p, sizeof(*p), - r, ec_max_insize); - if (rv < 0) { - perror("ERROR: EC_CMD_SMART_DISCHARGE failed"); - return rv; - } - - cap = read_mapped_mem32(EC_MEMMAP_BATT_LFCC); - if (!is_battery_range(cap)) { - perror("WARN: Failed to read battery capacity"); - cap = 0; - } - - printf("%-27s %5d h\n", "Hours to zero capacity:", r->hours_to_zero); - printf("%-27s %5d mAh (%d %%)\n", "Stay-up threshold:", - r->dzone.stayup, cap > 0 ? r->dzone.stayup * 100 / cap : -1); - printf("%-27s %5d mAh (%d %%)\n", "Cutoff threshold:", - r->dzone.cutoff, cap > 0 ? r->dzone.cutoff * 100 / cap : -1); - printf("%-27s %5d uA\n", "Hibernate discharge rate:", r->drate.hibern); - printf("%-27s %5d uA\n", "Cutoff discharge rate:", r->drate.cutoff); - - return 0; -} - -/* - * This boolean variable and handler are used for - * catching signals that translate into a quit/shutdown - * of a runtime loop. - * This is used in cmd_stress_test. - */ -static bool sig_quit; -static void sig_quit_handler(int sig) -{ - sig_quit = true; -} - -int cmd_stress_test(int argc, char *argv[]) -{ - int i; - bool reboot = false; - time_t now; - time_t start_time, last_update_time; - unsigned int rand_seed = 0; - uint64_t round = 1, attempt = 1; - uint64_t failures = 0; - - const int max_sleep_usec = 1000; /* 1ms */ - const int loop_update_interval = 10000; - - for (i = 1; i < argc; i++) { - if (strcmp(argv[i], "help") == 0) { - printf("Usage: %s [reboot] [help]\n", argv[0]); - printf("Stress tests the host command interface by" - " repeatedly issuing common host commands.\n"); - printf("The intent is to expose errors in kernel<->mcu" - " communication, such as exceeding timeouts.\n"); - printf("\n"); - printf("reboot - Reboots the target before" - " starting the stress test.\n"); - printf(" This may force restart the host," - " if the main ec is the target.\n"); - return 0; - } else if (strcmp(argv[i], "reboot") == 0) { - reboot = true; - } else { - fprintf(stderr, "Error - Unknown argument '%s'\n", - argv[i]); - return 1; - } - } - - printf("Stress test tool version: %s %s %s\n", - CROS_ECTOOL_VERSION, DATE, BUILDER); - - start_time = time(NULL); - last_update_time = start_time; - printf("Start time: %s\n", ctime(&start_time)); - - if (reboot) { - printf("Issuing ec reboot. Expect a few early failed" - " ioctl messages.\n"); - ec_command(EC_CMD_REBOOT, 0, NULL, 0, NULL, 0); - sleep(2); - } - - sig_quit = false; - signal(SIGINT, sig_quit_handler); - while (!sig_quit) { - int rv; - struct ec_response_get_version ver_r; - char *build_string = (char *)ec_inbuf; - struct ec_params_flash_protect flash_p; - struct ec_response_flash_protect flash_r; - struct ec_params_hello hello_p; - struct ec_response_hello hello_r; - - /* Request EC Version Strings */ - rv = ec_command(EC_CMD_GET_VERSION, 0, - NULL, 0, &ver_r, sizeof(ver_r)); - if (rv < 0) { - failures++; - perror("ERROR: EC_CMD_GET_VERSION failed"); - } - ver_r.version_string_ro[sizeof(ver_r.version_string_ro) - 1] - = '\0'; - ver_r.version_string_rw[sizeof(ver_r.version_string_rw) - 1] - = '\0'; - if (strlen(ver_r.version_string_ro) == 0) { - failures++; - fprintf(stderr, "RO version string is empty\n"); - } - if (strlen(ver_r.version_string_rw) == 0) { - failures++; - fprintf(stderr, "RW version string is empty\n"); - } - - usleep(rand_r(&rand_seed) % max_sleep_usec); - - /* Request EC Build String */ - rv = ec_command(EC_CMD_GET_BUILD_INFO, 0, - NULL, 0, ec_inbuf, ec_max_insize); - if (rv < 0) { - failures++; - perror("ERROR: EC_CMD_GET_BUILD_INFO failed"); - } - build_string[ec_max_insize - 1] = '\0'; - if (strlen(build_string) == 0) { - failures++; - fprintf(stderr, "Build string is empty\n"); - } - - usleep(rand_r(&rand_seed) % max_sleep_usec); - - /* Request Flash Protect Status */ - rv = ec_command(EC_CMD_FLASH_PROTECT, EC_VER_FLASH_PROTECT, - &flash_p, sizeof(flash_p), &flash_r, - sizeof(flash_r)); - if (rv < 0) { - failures++; - perror("ERROR: EC_CMD_FLASH_PROTECT failed"); - } - - usleep(rand_r(&rand_seed) % max_sleep_usec); - - /* Request Hello */ - hello_p.in_data = 0xa0b0c0d0; - rv = ec_command(EC_CMD_HELLO, 0, &hello_p, sizeof(hello_p), - &hello_r, sizeof(hello_r)); - if (rv < 0) { - failures++; - perror("ERROR: EC_CMD_HELLO failed"); - } - if (hello_r.out_data != HELLO_RESP(hello_p.in_data)) { - failures++; - fprintf(stderr, "Hello response was invalid.\n"); - } - - usleep(rand_r(&rand_seed) % max_sleep_usec); - - if ((attempt % loop_update_interval) == 0) { - now = time(NULL); - printf("Update: attempt %" PRIu64 " round %" PRIu64 - " | took %.f seconds\n", - attempt, round, - difftime(now, last_update_time)); - last_update_time = now; - } - - if (attempt++ == UINT64_MAX) - round++; - } - printf("\n"); - - now = time(NULL); - printf("End time: %s\n", ctime(&now)); - printf("Total runtime: %.f seconds\n", - difftime(time(NULL), start_time)); - printf("Total failures: %" PRIu64 "\n", failures); - return 0; -} - -int read_mapped_temperature(int id) -{ - int rv; - - if (!read_mapped_mem8(EC_MEMMAP_THERMAL_VERSION)) { - /* - * The temp_sensor_init() is not called, which implies no - * temp sensor is defined. - */ - rv = EC_TEMP_SENSOR_NOT_PRESENT; - } else if (id < EC_TEMP_SENSOR_ENTRIES) - rv = read_mapped_mem8(EC_MEMMAP_TEMP_SENSOR + id); - else if (read_mapped_mem8(EC_MEMMAP_THERMAL_VERSION) >= 2) - rv = read_mapped_mem8(EC_MEMMAP_TEMP_SENSOR_B + - id - EC_TEMP_SENSOR_ENTRIES); - else { - /* Sensor in second bank, but second bank isn't supported */ - rv = EC_TEMP_SENSOR_NOT_PRESENT; - } - return rv; -} - - -int cmd_temperature(int argc, char *argv[]) -{ - int rv; - int id; - char *e; - - if (argc != 2) { - fprintf(stderr, "Usage: %s <sensorid> | all\n", argv[0]); - return -1; - } - - if (strcmp(argv[1], "all") == 0) { - for (id = 0; - id < EC_TEMP_SENSOR_ENTRIES + EC_TEMP_SENSOR_B_ENTRIES; - id++) { - rv = read_mapped_temperature(id); - switch (rv) { - case EC_TEMP_SENSOR_NOT_PRESENT: - break; - case EC_TEMP_SENSOR_ERROR: - fprintf(stderr, "Sensor %d error\n", id); - break; - case EC_TEMP_SENSOR_NOT_POWERED: - fprintf(stderr, "Sensor %d disabled\n", id); - break; - case EC_TEMP_SENSOR_NOT_CALIBRATED: - fprintf(stderr, "Sensor %d not calibrated\n", - id); - break; - default: - printf("%d: %d K\n", id, - rv + EC_TEMP_SENSOR_OFFSET); - } - } - return 0; - } - - id = strtol(argv[1], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad sensor ID.\n"); - return -1; - } - - if (id < 0 || - id >= EC_TEMP_SENSOR_ENTRIES + EC_TEMP_SENSOR_B_ENTRIES) { - printf("Sensor ID invalid.\n"); - return -1; - } - - printf("Reading temperature..."); - rv = read_mapped_temperature(id); - - switch (rv) { - case EC_TEMP_SENSOR_NOT_PRESENT: - printf("Sensor not present\n"); - return -1; - case EC_TEMP_SENSOR_ERROR: - printf("Error\n"); - return -1; - case EC_TEMP_SENSOR_NOT_POWERED: - printf("Sensor disabled/unpowered\n"); - return -1; - case EC_TEMP_SENSOR_NOT_CALIBRATED: - fprintf(stderr, "Sensor not calibrated\n"); - return -1; - default: - printf("%d K\n", rv + EC_TEMP_SENSOR_OFFSET); - return 0; - } -} - - -int cmd_temp_sensor_info(int argc, char *argv[]) -{ - struct ec_params_temp_sensor_get_info p; - struct ec_response_temp_sensor_get_info r; - int rv; - char *e; - - if (argc != 2) { - fprintf(stderr, "Usage: %s <sensorid> | all\n", argv[0]); - return -1; - } - - if (strcmp(argv[1], "all") == 0) { - for (p.id = 0; - p.id < EC_TEMP_SENSOR_ENTRIES + EC_TEMP_SENSOR_B_ENTRIES; - p.id++) { - if (read_mapped_temperature(p.id) == - EC_TEMP_SENSOR_NOT_PRESENT) - continue; - rv = ec_command(EC_CMD_TEMP_SENSOR_GET_INFO, 0, - &p, sizeof(p), &r, sizeof(r)); - if (rv < 0) - continue; - printf("%d: %d %s\n", p.id, r.sensor_type, - r.sensor_name); - } - return 0; - } - - p.id = strtol(argv[1], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad sensor ID.\n"); - return -1; - } - - rv = ec_command(EC_CMD_TEMP_SENSOR_GET_INFO, 0, - &p, sizeof(p), &r, sizeof(r)); - if (rv < 0) - return rv; - - printf("Sensor name: %s\n", r.sensor_name); - printf("Sensor type: %d\n", r.sensor_type); - - return 0; -} - - -int cmd_thermal_get_threshold_v0(int argc, char *argv[]) -{ - struct ec_params_thermal_get_threshold p; - struct ec_response_thermal_get_threshold r; - char *e; - int rv; - - if (argc != 3) { - fprintf(stderr, - "Usage: %s <sensortypeid> <thresholdid>\n", argv[0]); - return -1; - } - - p.sensor_type = strtol(argv[1], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad sensor type ID.\n"); - return -1; - } - - p.threshold_id = strtol(argv[2], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad threshold ID.\n"); - return -1; - } - - rv = ec_command(EC_CMD_THERMAL_GET_THRESHOLD, 0, - &p, sizeof(p), &r, sizeof(r)); - if (rv < 0) - return rv; - - printf("Threshold %d for sensor type %d is %d K.\n", - p.threshold_id, p.sensor_type, r.value); - - return 0; -} - - -int cmd_thermal_set_threshold_v0(int argc, char *argv[]) -{ - struct ec_params_thermal_set_threshold p; - char *e; - int rv; - - if (argc != 4) { - fprintf(stderr, - "Usage: %s <sensortypeid> <thresholdid> <value>\n", - argv[0]); - return -1; - } - - p.sensor_type = strtol(argv[1], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad sensor type ID.\n"); - return -1; - } - - p.threshold_id = strtol(argv[2], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad threshold ID.\n"); - return -1; - } - - p.value = strtol(argv[3], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad threshold value.\n"); - return -1; - } - - rv = ec_command(EC_CMD_THERMAL_SET_THRESHOLD, 0, - &p, sizeof(p), NULL, 0); - if (rv < 0) - return rv; - - printf("Threshold %d for sensor type %d set to %d.\n", - p.threshold_id, p.sensor_type, p.value); - - return 0; -} - - -int cmd_thermal_get_threshold_v1(int argc, char *argv[]) -{ - struct ec_params_thermal_get_threshold_v1 p; - struct ec_thermal_config r; - struct ec_params_temp_sensor_get_info pi; - struct ec_response_temp_sensor_get_info ri; - int rv; - int i; - - printf("sensor warn high halt fan_off fan_max name\n"); - for (i = 0; i < 99; i++) { /* number of sensors is unknown */ - - /* ask for one */ - p.sensor_num = i; - rv = ec_command(EC_CMD_THERMAL_GET_THRESHOLD, 1, - &p, sizeof(p), &r, sizeof(r)); - if (rv <= 0) /* stop on first failure */ - break; - - /* ask for its name, too */ - pi.id = i; - rv = ec_command(EC_CMD_TEMP_SENSOR_GET_INFO, 0, - &pi, sizeof(pi), &ri, sizeof(ri)); - - /* print what we know */ - printf(" %2d %3d %3d %3d %3d %3d %s\n", - i, - r.temp_host[EC_TEMP_THRESH_WARN], - r.temp_host[EC_TEMP_THRESH_HIGH], - r.temp_host[EC_TEMP_THRESH_HALT], - r.temp_fan_off, r.temp_fan_max, - rv > 0 ? ri.sensor_name : "?"); - } - if (i) - printf("(all temps in degrees Kelvin)\n"); - - return 0; -} - -int cmd_thermal_set_threshold_v1(int argc, char *argv[]) -{ - struct ec_params_thermal_get_threshold_v1 p; - struct ec_thermal_config r; - struct ec_params_thermal_set_threshold_v1 s; - int i, n, val, rv; - char *e; - - if (argc < 3 || argc > 7) { - printf("Usage: %s" - " sensor warn [high [shutdown [fan_off [fan_max]]]]\n", - argv[0]); - return 1; - } - - n = strtod(argv[1], &e); - if (e && *e) { - printf("arg %d is invalid\n", 1); - return 1; - } - - p.sensor_num = n; - rv = ec_command(EC_CMD_THERMAL_GET_THRESHOLD, 1, - &p, sizeof(p), &r, sizeof(r)); - if (rv <= 0) - return rv; - - s.sensor_num = n; - s.cfg = r; - - for (i = 2; i < argc; i++) { - val = strtod(argv[i], &e); - if (e && *e) { - printf("arg %d is invalid\n", i); - return 1; - } - - if (val < 0) - continue; - switch (i) { - case 2: - case 3: - case 4: - s.cfg.temp_host[i-2] = val; - break; - case 5: - s.cfg.temp_fan_off = val; - break; - case 6: - s.cfg.temp_fan_max = val; - break; - } - } - - rv = ec_command(EC_CMD_THERMAL_SET_THRESHOLD, 1, - &s, sizeof(s), NULL, 0); - - return rv; -} - -int cmd_thermal_get_threshold(int argc, char *argv[]) -{ - if (ec_cmd_version_supported(EC_CMD_THERMAL_GET_THRESHOLD, 1)) - return cmd_thermal_get_threshold_v1(argc, argv); - else if (ec_cmd_version_supported(EC_CMD_THERMAL_GET_THRESHOLD, 0)) - return cmd_thermal_get_threshold_v0(argc, argv); - - printf("I got nuthin.\n"); - return -1; -} - -int cmd_thermal_set_threshold(int argc, char *argv[]) -{ - if (ec_cmd_version_supported(EC_CMD_THERMAL_SET_THRESHOLD, 1)) - return cmd_thermal_set_threshold_v1(argc, argv); - else if (ec_cmd_version_supported(EC_CMD_THERMAL_SET_THRESHOLD, 0)) - return cmd_thermal_set_threshold_v0(argc, argv); - - printf("I got nuthin.\n"); - return -1; -} - - -static int get_num_fans(void) -{ - int idx, rv; - struct ec_response_get_features r; - - /* - * iff the EC supports the GET_FEATURES, - * check whether it has fan support enabled. - */ - rv = ec_command(EC_CMD_GET_FEATURES, 0, NULL, 0, &r, sizeof(r)); - if (rv >= 0 && !(r.flags[0] & BIT(EC_FEATURE_PWM_FAN))) - return 0; - - for (idx = 0; idx < EC_FAN_SPEED_ENTRIES; idx++) { - rv = read_mapped_mem16(EC_MEMMAP_FAN + 2 * idx); - if (rv == EC_FAN_SPEED_NOT_PRESENT) - break; - } - - return idx; -} - -int cmd_thermal_auto_fan_ctrl(int argc, char *argv[]) -{ - int rv, num_fans; - struct ec_params_auto_fan_ctrl_v1 p_v1; - char *e; - int cmdver = 1; - - if (!ec_cmd_version_supported(EC_CMD_THERMAL_AUTO_FAN_CTRL, cmdver) - || (argc == 1)) { - /* If no argument is provided then enable auto fan ctrl */ - /* for all fans by using version 0 of the host command */ - - rv = ec_command(EC_CMD_THERMAL_AUTO_FAN_CTRL, 0, - NULL, 0, NULL, 0); - if (rv < 0) - return rv; - - printf("Automatic fan control is now on for all fans.\n"); - return 0; - } - - if (argc > 2 || !strcmp(argv[1], "help")) { - printf("Usage: %s [idx]\n", argv[0]); - return -1; - } - - num_fans = get_num_fans(); - p_v1.fan_idx = strtol(argv[1], &e, 0); - if ((e && *e) || (p_v1.fan_idx >= num_fans)) { - fprintf(stderr, "Bad fan index.\n"); - return -1; - } - - rv = ec_command(EC_CMD_THERMAL_AUTO_FAN_CTRL, cmdver, - &p_v1, sizeof(p_v1), NULL, 0); - if (rv < 0) - return rv; - - printf("Automatic fan control is now on for fan %d\n", p_v1.fan_idx); - - return 0; -} - -static int print_fan(int idx) -{ - int rv = read_mapped_mem16(EC_MEMMAP_FAN + 2 * idx); - - switch (rv) { - case EC_FAN_SPEED_NOT_PRESENT: - return -1; - case EC_FAN_SPEED_STALLED: - printf("Fan %d stalled!\n", idx); - break; - default: - printf("Fan %d RPM: %d\n", idx, rv); - break; - } - - return 0; -} - -int cmd_pwm_get_num_fans(int argc, char *argv[]) -{ - int num_fans; - - num_fans = get_num_fans(); - - printf("Number of fans = %d\n", num_fans); - - return 0; -} - -int cmd_pwm_get_fan_rpm(int argc, char *argv[]) -{ - int i, num_fans; - - num_fans = get_num_fans(); - if (argc < 2 || !strcasecmp(argv[1], "all")) { - /* Print all the fan speeds */ - for (i = 0; i < num_fans; i++) - print_fan(i); - } else { - char *e; - int idx; - - idx = strtol(argv[1], &e, 0); - if ((e && *e) || idx < 0 || idx >= num_fans) { - fprintf(stderr, "Bad index.\n"); - return -1; - } - - print_fan(idx); - } - - return 0; -} - - -int cmd_pwm_set_fan_rpm(int argc, char *argv[]) -{ - struct ec_params_pwm_set_fan_target_rpm_v1 p_v1; - char *e; - int rv, num_fans; - int cmdver = 1; - - if (!ec_cmd_version_supported(EC_CMD_PWM_SET_FAN_TARGET_RPM, cmdver)) { - struct ec_params_pwm_set_fan_target_rpm_v0 p_v0; - - /* Fall back to command version 0 command */ - cmdver = 0; - - if (argc != 2) { - fprintf(stderr, - "Usage: %s <targetrpm>\n", argv[0]); - return -1; - } - p_v0.rpm = strtol(argv[1], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad RPM.\n"); - return -1; - } - - rv = ec_command(EC_CMD_PWM_SET_FAN_TARGET_RPM, cmdver, - &p_v0, sizeof(p_v0), NULL, 0); - if (rv < 0) - return rv; - - printf("Fan target RPM set for all fans.\n"); - return 0; - } - - if (argc > 3 || (argc == 2 && !strcmp(argv[1], "help")) || argc == 1) { - printf("Usage: %s [idx] <targetrpm>\n", argv[0]); - printf("'%s 0 3000' - Set fan 0 RPM to 3000\n", argv[0]); - printf("'%s 3000' - Set all fans RPM to 3000\n", argv[0]); - return -1; - } - - num_fans = get_num_fans(); - p_v1.rpm = strtol(argv[argc - 1], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad RPM.\n"); - return -1; - } - - if (argc == 2) { - /* Reuse version 0 command if we're setting targetrpm - * for all fans */ - struct ec_params_pwm_set_fan_target_rpm_v0 p_v0; - - cmdver = 0; - p_v0.rpm = p_v1.rpm; - - rv = ec_command(EC_CMD_PWM_SET_FAN_TARGET_RPM, cmdver, - &p_v0, sizeof(p_v0), NULL, 0); - if (rv < 0) - return rv; - - printf("Fan target RPM set for all fans.\n"); - } else { - p_v1.fan_idx = strtol(argv[1], &e, 0); - if ((e && *e) || (p_v1.fan_idx >= num_fans)) { - fprintf(stderr, "Bad fan index.\n"); - return -1; - } - - rv = ec_command(EC_CMD_PWM_SET_FAN_TARGET_RPM, cmdver, - &p_v1, sizeof(p_v1), NULL, 0); - if (rv < 0) - return rv; - - printf("Fan %d target RPM set.\n", p_v1.fan_idx); - } - - return 0; -} - -int cmd_pwm_get_keyboard_backlight(int argc, char *argv[]) -{ - struct ec_response_pwm_get_keyboard_backlight r; - int rv; - - rv = ec_command(EC_CMD_PWM_GET_KEYBOARD_BACKLIGHT, 0, - NULL, 0, &r, sizeof(r)); - if (rv < 0) - return rv; - - if (r.enabled == 1) - printf("Current keyboard backlight percent: %d\n", r.percent); - else - printf("Keyboard backlight disabled.\n"); - - return 0; -} - - -int cmd_pwm_set_keyboard_backlight(int argc, char *argv[]) -{ - struct ec_params_pwm_set_keyboard_backlight p; - char *e; - int rv; - - if (argc != 2) { - fprintf(stderr, "Usage: %s <percent>\n", argv[0]); - return -1; - } - p.percent = strtol(argv[1], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad percent.\n"); - return -1; - } - - rv = ec_command(EC_CMD_PWM_SET_KEYBOARD_BACKLIGHT, 0, - &p, sizeof(p), NULL, 0); - if (rv < 0) - return rv; - - printf("Keyboard backlight set.\n"); - return 0; -} - -int cmd_pwm_get_duty(int argc, char *argv[]) -{ - struct ec_params_pwm_get_duty p; - struct ec_response_pwm_get_duty r; - char *e; - int rv; - - if (argc != 2) { - fprintf(stderr, "Usage: %s <pwm_idx> | kb | disp\n", argv[0]); - return -1; - } - - if (!strcmp(argv[1], "kb")) { - p.pwm_type = EC_PWM_TYPE_KB_LIGHT; - p.index = 0; - } else if (!strcmp(argv[1], "disp")) { - p.pwm_type = EC_PWM_TYPE_DISPLAY_LIGHT; - p.index = 0; - } else { - p.pwm_type = EC_PWM_TYPE_GENERIC; - p.index = strtol(argv[1], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad pwm_idx\n"); - return -1; - } - } - - rv = ec_command(EC_CMD_PWM_GET_DUTY, 0, &p, sizeof(p), &r, sizeof(r)); - if (rv < 0) - return rv; - - printf("Current PWM duty: %d\n", r.duty); - return 0; -} - - -int cmd_pwm_set_duty(int argc, char *argv[]) -{ - struct ec_params_pwm_set_duty p; - char *e; - int rv; - - if (argc != 3) { - fprintf(stderr, "Usage: %s <pwm_idx> | kb | disp <duty>\n", - argv[0]); - return -1; - } - - if (!strcmp(argv[1], "kb")) { - p.pwm_type = EC_PWM_TYPE_KB_LIGHT; - p.index = 0; - } else if (!strcmp(argv[1], "disp")) { - p.pwm_type = EC_PWM_TYPE_DISPLAY_LIGHT; - p.index = 0; - } else { - p.pwm_type = EC_PWM_TYPE_GENERIC; - p.index = strtol(argv[1], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad pwm_idx\n"); - return -1; - } - } - - p.duty = strtol(argv[2], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad duty.\n"); - return -1; - } - - rv = ec_command(EC_CMD_PWM_SET_DUTY, 0, - &p, sizeof(p), NULL, 0); - if (rv < 0) - return rv; - - printf("PWM set.\n"); - return 0; -} - -int cmd_fanduty(int argc, char *argv[]) -{ - struct ec_params_pwm_set_fan_duty_v1 p_v1; - char *e; - int rv, num_fans; - int cmdver = 1; - - if (!ec_cmd_version_supported(EC_CMD_PWM_SET_FAN_DUTY, cmdver)) { - struct ec_params_pwm_set_fan_duty_v0 p_v0; - - if (argc != 2) { - fprintf(stderr, - "Usage: %s <percent>\n", argv[0]); - return -1; - } - p_v0.percent = strtol(argv[1], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad percent arg.\n"); - return -1; - } - - rv = ec_command(EC_CMD_PWM_SET_FAN_DUTY, 0, - &p_v0, sizeof(p_v0), NULL, 0); - if (rv < 0) - return rv; - - printf("Fan duty cycle set.\n"); - return 0; - } - - if (argc > 3 || (argc == 2 && !strcmp(argv[1], "help")) || argc == 1) { - printf("Usage: %s [idx] <percent>\n", argv[0]); - printf("'%s 0 50' - Set fan 0 duty cycle to 50 percent\n", - argv[0]); - printf("'%s 30' - Set all fans duty cycle to 30 percent\n", - argv[0]); - return -1; - } - - num_fans = get_num_fans(); - p_v1.percent = strtol(argv[argc - 1], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad percent arg.\n"); - return -1; - } - - if (argc == 2) { - /* Reuse version 0 command if we're setting duty cycle - * for all fans */ - struct ec_params_pwm_set_fan_duty_v0 p_v0; - - cmdver = 0; - p_v0.percent = p_v1.percent; - - rv = ec_command(EC_CMD_PWM_SET_FAN_DUTY, cmdver, - &p_v0, sizeof(p_v0), NULL, 0); - if (rv < 0) - return rv; - - printf("Fan duty cycle set for all fans.\n"); - } else { - p_v1.fan_idx = strtol(argv[1], &e, 0); - if ((e && *e) || (p_v1.fan_idx >= num_fans)) { - fprintf(stderr, "Bad fan index.\n"); - return -1; - } - - rv = ec_command(EC_CMD_PWM_SET_FAN_DUTY, cmdver, - &p_v1, sizeof(p_v1), NULL, 0); - if (rv < 0) - return rv; - - printf("Fan %d duty cycle set.\n", p_v1.fan_idx); - } - - return 0; -} - -#define LBMSG(state) #state -#include "lightbar_msg_list.h" -static const char * const lightbar_cmds[] = { - LIGHTBAR_MSG_LIST -}; -#undef LBMSG - -/* Size of field <FLD> in structure <ST> */ -#define ST_FLD_SIZE(ST, FLD) sizeof(((struct ST *)0)->FLD) - -#define ST_CMD_SIZE ST_FLD_SIZE(ec_params_lightbar, cmd) -#define ST_PRM_SIZE(SUBCMD) \ - (ST_CMD_SIZE + ST_FLD_SIZE(ec_params_lightbar, SUBCMD)) -#define ST_RSP_SIZE(SUBCMD) ST_FLD_SIZE(ec_response_lightbar, SUBCMD) - -static const struct { - uint8_t insize; - uint8_t outsize; -} lb_command_paramcount[] = { - { ST_CMD_SIZE, ST_RSP_SIZE(dump) }, - { ST_CMD_SIZE, 0 }, - { ST_CMD_SIZE, 0 }, - { ST_CMD_SIZE, 0 }, - { ST_PRM_SIZE(set_brightness), 0}, - { ST_PRM_SIZE(seq), 0}, - { ST_PRM_SIZE(reg), 0}, - { ST_PRM_SIZE(set_rgb), 0}, - { ST_CMD_SIZE, ST_RSP_SIZE(get_seq) }, - { ST_PRM_SIZE(demo), 0}, - { ST_CMD_SIZE, ST_RSP_SIZE(get_params_v0) }, - { ST_PRM_SIZE(set_params_v0), 0}, - { ST_CMD_SIZE, ST_RSP_SIZE(version) }, - { ST_CMD_SIZE, ST_RSP_SIZE(get_brightness) }, - { ST_PRM_SIZE(get_rgb), ST_RSP_SIZE(get_rgb) }, - { ST_CMD_SIZE, ST_RSP_SIZE(get_demo) }, - { ST_CMD_SIZE, ST_RSP_SIZE(get_params_v1) }, - { ST_PRM_SIZE(set_params_v1), 0}, - { ST_PRM_SIZE(set_program), 0}, - { ST_PRM_SIZE(manual_suspend_ctrl), 0}, - { ST_CMD_SIZE, 0 }, - { ST_CMD_SIZE, 0 }, - { ST_CMD_SIZE, ST_RSP_SIZE(get_params_v2_timing) }, - { ST_PRM_SIZE(set_v2par_timing), 0}, - { ST_CMD_SIZE, ST_RSP_SIZE(get_params_v2_tap) }, - { ST_PRM_SIZE(set_v2par_tap), 0}, - { ST_CMD_SIZE, ST_RSP_SIZE(get_params_v2_osc) }, - { ST_PRM_SIZE(set_v2par_osc), 0}, - { ST_CMD_SIZE, ST_RSP_SIZE(get_params_v2_bright) }, - { ST_PRM_SIZE(set_v2par_bright), 0}, - { ST_CMD_SIZE, ST_RSP_SIZE(get_params_v2_thlds) }, - { ST_PRM_SIZE(set_v2par_thlds), 0}, - { ST_CMD_SIZE, ST_RSP_SIZE(get_params_v2_colors) }, - { ST_PRM_SIZE(set_v2par_colors), 0}, -}; -BUILD_ASSERT(ARRAY_SIZE(lb_command_paramcount) == LIGHTBAR_NUM_CMDS); - -#undef ST_CMD_SIZE -#undef ST_PRM_SIZE -#undef ST_RSP_SIZE - -static int lb_help(const char *cmd) -{ - printf("Usage:\n"); - printf(" %s - dump all regs\n", cmd); - printf(" %s off - enter standby\n", cmd); - printf(" %s on - leave standby\n", cmd); - printf(" %s init - load default vals\n", cmd); - printf(" %s brightness [NUM] - get/set intensity(0-ff)\n", cmd); - printf(" %s seq [NUM|SEQUENCE] - run given pattern" - " (no arg for list)\n", cmd); - printf(" %s CTRL REG VAL - set LED controller regs\n", cmd); - printf(" %s LED RED GREEN BLUE - set color manually" - " (LED=4 for all)\n", cmd); - printf(" %s LED - get current LED color\n", cmd); - printf(" %s demo [0|1] - turn demo mode on & off\n", cmd); - printf(" %s params [setfile] - get params" - " (or set from file)\n", cmd); - printf(" %s params2 group [setfile] - get params by group\n" - " (or set from file)\n", cmd); - printf(" %s program file - load program from file\n", cmd); - return 0; -} - -static uint8_t lb_find_msg_by_name(const char *str) -{ - uint8_t i; - for (i = 0; i < LIGHTBAR_NUM_SEQUENCES; i++) - if (!strcasecmp(str, lightbar_cmds[i])) - return i; - - return LIGHTBAR_NUM_SEQUENCES; -} - -static int lb_do_cmd(enum lightbar_command cmd, - struct ec_params_lightbar *in, - struct ec_response_lightbar *out) -{ - int rv; - in->cmd = cmd; - rv = ec_command(EC_CMD_LIGHTBAR_CMD, 0, - in, lb_command_paramcount[cmd].insize, - out, lb_command_paramcount[cmd].outsize); - return (rv < 0 ? rv : 0); -} - -static int lb_show_msg_names(void) -{ - int i, current_state; - struct ec_params_lightbar param; - struct ec_response_lightbar resp; - - i = lb_do_cmd(LIGHTBAR_CMD_GET_SEQ, ¶m, &resp); - if (i < 0) - return i; - current_state = resp.get_seq.num; - - printf("sequence names:"); - for (i = 0; i < LIGHTBAR_NUM_SEQUENCES; i++) - printf(" %s", lightbar_cmds[i]); - printf("\nCurrent = 0x%x %s\n", current_state, - lightbar_cmds[current_state]); - - return 0; -} - -static int lb_read_params_v0_from_file(const char *filename, - struct lightbar_params_v0 *p) -{ - FILE *fp; - char buf[80]; - int val[4]; - int r = 1; - int line = 0; - int want, got; - int i; - - fp = fopen(filename, "rb"); - if (!fp) { - fprintf(stderr, "Can't open %s: %s\n", - filename, strerror(errno)); - return 1; - } - - /* We must read the correct number of params from each line */ -#define READ(N) do { \ - line++; \ - want = (N); \ - got = -1; \ - if (!fgets(buf, sizeof(buf), fp)) \ - goto done; \ - got = sscanf(buf, "%i %i %i %i", \ - &val[0], &val[1], &val[2], &val[3]); \ - if (want != got) \ - goto done; \ - } while (0) - - - /* Do it */ - READ(1); p->google_ramp_up = val[0]; - READ(1); p->google_ramp_down = val[0]; - READ(1); p->s3s0_ramp_up = val[0]; - READ(1); p->s0_tick_delay[0] = val[0]; - READ(1); p->s0_tick_delay[1] = val[0]; - READ(1); p->s0a_tick_delay[0] = val[0]; - READ(1); p->s0a_tick_delay[1] = val[0]; - READ(1); p->s0s3_ramp_down = val[0]; - READ(1); p->s3_sleep_for = val[0]; - READ(1); p->s3_ramp_up = val[0]; - READ(1); p->s3_ramp_down = val[0]; - READ(1); p->new_s0 = val[0]; - - READ(2); - p->osc_min[0] = val[0]; - p->osc_min[1] = val[1]; - READ(2); - p->osc_max[0] = val[0]; - p->osc_max[1] = val[1]; - READ(2); - p->w_ofs[0] = val[0]; - p->w_ofs[1] = val[1]; - - READ(2); - p->bright_bl_off_fixed[0] = val[0]; - p->bright_bl_off_fixed[1] = val[1]; - - READ(2); - p->bright_bl_on_min[0] = val[0]; - p->bright_bl_on_min[1] = val[1]; - - READ(2); - p->bright_bl_on_max[0] = val[0]; - p->bright_bl_on_max[1] = val[1]; - - READ(3); - p->battery_threshold[0] = val[0]; - p->battery_threshold[1] = val[1]; - p->battery_threshold[2] = val[2]; - - READ(4); - p->s0_idx[0][0] = val[0]; - p->s0_idx[0][1] = val[1]; - p->s0_idx[0][2] = val[2]; - p->s0_idx[0][3] = val[3]; - - READ(4); - p->s0_idx[1][0] = val[0]; - p->s0_idx[1][1] = val[1]; - p->s0_idx[1][2] = val[2]; - p->s0_idx[1][3] = val[3]; - - READ(4); - p->s3_idx[0][0] = val[0]; - p->s3_idx[0][1] = val[1]; - p->s3_idx[0][2] = val[2]; - p->s3_idx[0][3] = val[3]; - - READ(4); - p->s3_idx[1][0] = val[0]; - p->s3_idx[1][1] = val[1]; - p->s3_idx[1][2] = val[2]; - p->s3_idx[1][3] = val[3]; - - for (i = 0; i < ARRAY_SIZE(p->color); i++) { - READ(3); - p->color[i].r = val[0]; - p->color[i].g = val[1]; - p->color[i].b = val[2]; - } - -#undef READ - - /* Yay */ - r = 0; -done: - if (r) - fprintf(stderr, "problem with line %d: wanted %d, got %d\n", - line, want, got); - fclose(fp); - return r; -} - -static void lb_show_params_v0(const struct lightbar_params_v0 *p) -{ - int i; - - printf("%d\t\t# .google_ramp_up\n", p->google_ramp_up); - printf("%d\t\t# .google_ramp_down\n", p->google_ramp_down); - printf("%d\t\t# .s3s0_ramp_up\n", p->s3s0_ramp_up); - printf("%d\t\t# .s0_tick_delay (battery)\n", p->s0_tick_delay[0]); - printf("%d\t\t# .s0_tick_delay (AC)\n", p->s0_tick_delay[1]); - printf("%d\t\t# .s0a_tick_delay (battery)\n", p->s0a_tick_delay[0]); - printf("%d\t\t# .s0a_tick_delay (AC)\n", p->s0a_tick_delay[1]); - printf("%d\t\t# .s0s3_ramp_down\n", p->s0s3_ramp_down); - printf("%d\t# .s3_sleep_for\n", p->s3_sleep_for); - printf("%d\t\t# .s3_ramp_up\n", p->s3_ramp_up); - printf("%d\t\t# .s3_ramp_down\n", p->s3_ramp_down); - printf("%d\t\t# .new_s0\n", p->new_s0); - printf("0x%02x 0x%02x\t# .osc_min (battery, AC)\n", - p->osc_min[0], p->osc_min[1]); - printf("0x%02x 0x%02x\t# .osc_max (battery, AC)\n", - p->osc_max[0], p->osc_max[1]); - printf("%d %d\t\t# .w_ofs (battery, AC)\n", - p->w_ofs[0], p->w_ofs[1]); - printf("0x%02x 0x%02x\t# .bright_bl_off_fixed (battery, AC)\n", - p->bright_bl_off_fixed[0], p->bright_bl_off_fixed[1]); - printf("0x%02x 0x%02x\t# .bright_bl_on_min (battery, AC)\n", - p->bright_bl_on_min[0], p->bright_bl_on_min[1]); - printf("0x%02x 0x%02x\t# .bright_bl_on_max (battery, AC)\n", - p->bright_bl_on_max[0], p->bright_bl_on_max[1]); - printf("%d %d %d\t\t# .battery_threshold\n", - p->battery_threshold[0], - p->battery_threshold[1], - p->battery_threshold[2]); - printf("%d %d %d %d\t\t# .s0_idx[] (battery)\n", - p->s0_idx[0][0], p->s0_idx[0][1], - p->s0_idx[0][2], p->s0_idx[0][3]); - printf("%d %d %d %d\t\t# .s0_idx[] (AC)\n", - p->s0_idx[1][0], p->s0_idx[1][1], - p->s0_idx[1][2], p->s0_idx[1][3]); - printf("%d %d %d %d\t# .s3_idx[] (battery)\n", - p->s3_idx[0][0], p->s3_idx[0][1], - p->s3_idx[0][2], p->s3_idx[0][3]); - printf("%d %d %d %d\t# .s3_idx[] (AC)\n", - p->s3_idx[1][0], p->s3_idx[1][1], - p->s3_idx[1][2], p->s3_idx[1][3]); - for (i = 0; i < ARRAY_SIZE(p->color); i++) - printf("0x%02x 0x%02x 0x%02x\t# color[%d]\n", - p->color[i].r, - p->color[i].g, - p->color[i].b, i); -} - -static int lb_read_params_v1_from_file(const char *filename, - struct lightbar_params_v1 *p) -{ - FILE *fp; - char buf[80]; - int val[4]; - int r = 1; - int line = 0; - int want, got; - int i; - - fp = fopen(filename, "rb"); - if (!fp) { - fprintf(stderr, "Can't open %s: %s\n", - filename, strerror(errno)); - return 1; - } - - /* We must read the correct number of params from each line */ -#define READ(N) do { \ - line++; \ - want = (N); \ - got = -1; \ - if (!fgets(buf, sizeof(buf), fp)) \ - goto done; \ - got = sscanf(buf, "%i %i %i %i", \ - &val[0], &val[1], &val[2], &val[3]); \ - if (want != got) \ - goto done; \ - } while (0) - - - /* Do it */ - READ(1); p->google_ramp_up = val[0]; - READ(1); p->google_ramp_down = val[0]; - READ(1); p->s3s0_ramp_up = val[0]; - READ(1); p->s0_tick_delay[0] = val[0]; - READ(1); p->s0_tick_delay[1] = val[0]; - READ(1); p->s0a_tick_delay[0] = val[0]; - READ(1); p->s0a_tick_delay[1] = val[0]; - READ(1); p->s0s3_ramp_down = val[0]; - READ(1); p->s3_sleep_for = val[0]; - READ(1); p->s3_ramp_up = val[0]; - READ(1); p->s3_ramp_down = val[0]; - READ(1); p->tap_tick_delay = val[0]; - READ(1); p->tap_gate_delay = val[0]; - READ(1); p->tap_display_time = val[0]; - - READ(1); p->tap_pct_red = val[0]; - READ(1); p->tap_pct_green = val[0]; - READ(1); p->tap_seg_min_on = val[0]; - READ(1); p->tap_seg_max_on = val[0]; - READ(1); p->tap_seg_osc = val[0]; - READ(3); - p->tap_idx[0] = val[0]; - p->tap_idx[1] = val[1]; - p->tap_idx[2] = val[2]; - - READ(2); - p->osc_min[0] = val[0]; - p->osc_min[1] = val[1]; - READ(2); - p->osc_max[0] = val[0]; - p->osc_max[1] = val[1]; - READ(2); - p->w_ofs[0] = val[0]; - p->w_ofs[1] = val[1]; - - READ(2); - p->bright_bl_off_fixed[0] = val[0]; - p->bright_bl_off_fixed[1] = val[1]; - - READ(2); - p->bright_bl_on_min[0] = val[0]; - p->bright_bl_on_min[1] = val[1]; - - READ(2); - p->bright_bl_on_max[0] = val[0]; - p->bright_bl_on_max[1] = val[1]; - - READ(3); - p->battery_threshold[0] = val[0]; - p->battery_threshold[1] = val[1]; - p->battery_threshold[2] = val[2]; - - READ(4); - p->s0_idx[0][0] = val[0]; - p->s0_idx[0][1] = val[1]; - p->s0_idx[0][2] = val[2]; - p->s0_idx[0][3] = val[3]; - - READ(4); - p->s0_idx[1][0] = val[0]; - p->s0_idx[1][1] = val[1]; - p->s0_idx[1][2] = val[2]; - p->s0_idx[1][3] = val[3]; - - READ(4); - p->s3_idx[0][0] = val[0]; - p->s3_idx[0][1] = val[1]; - p->s3_idx[0][2] = val[2]; - p->s3_idx[0][3] = val[3]; - - READ(4); - p->s3_idx[1][0] = val[0]; - p->s3_idx[1][1] = val[1]; - p->s3_idx[1][2] = val[2]; - p->s3_idx[1][3] = val[3]; - - for (i = 0; i < ARRAY_SIZE(p->color); i++) { - READ(3); - p->color[i].r = val[0]; - p->color[i].g = val[1]; - p->color[i].b = val[2]; - } - -#undef READ - - /* Yay */ - r = 0; -done: - if (r) - fprintf(stderr, "problem with line %d: wanted %d, got %d\n", - line, want, got); - fclose(fp); - return r; -} - -static void lb_show_params_v1(const struct lightbar_params_v1 *p) -{ - int i; - - printf("%d\t\t# .google_ramp_up\n", p->google_ramp_up); - printf("%d\t\t# .google_ramp_down\n", p->google_ramp_down); - printf("%d\t\t# .s3s0_ramp_up\n", p->s3s0_ramp_up); - printf("%d\t\t# .s0_tick_delay (battery)\n", p->s0_tick_delay[0]); - printf("%d\t\t# .s0_tick_delay (AC)\n", p->s0_tick_delay[1]); - printf("%d\t\t# .s0a_tick_delay (battery)\n", p->s0a_tick_delay[0]); - printf("%d\t\t# .s0a_tick_delay (AC)\n", p->s0a_tick_delay[1]); - printf("%d\t\t# .s0s3_ramp_down\n", p->s0s3_ramp_down); - printf("%d\t\t# .s3_sleep_for\n", p->s3_sleep_for); - printf("%d\t\t# .s3_ramp_up\n", p->s3_ramp_up); - printf("%d\t\t# .s3_ramp_down\n", p->s3_ramp_down); - printf("%d\t\t# .tap_tick_delay\n", p->tap_tick_delay); - printf("%d\t\t# .tap_gate_delay\n", p->tap_gate_delay); - printf("%d\t\t# .tap_display_time\n", p->tap_display_time); - printf("%d\t\t# .tap_pct_red\n", p->tap_pct_red); - printf("%d\t\t# .tap_pct_green\n", p->tap_pct_green); - printf("%d\t\t# .tap_seg_min_on\n", p->tap_seg_min_on); - printf("%d\t\t# .tap_seg_max_on\n", p->tap_seg_max_on); - printf("%d\t\t# .tap_seg_osc\n", p->tap_seg_osc); - printf("%d %d %d\t\t# .tap_idx\n", - p->tap_idx[0], p->tap_idx[1], p->tap_idx[2]); - printf("0x%02x 0x%02x\t# .osc_min (battery, AC)\n", - p->osc_min[0], p->osc_min[1]); - printf("0x%02x 0x%02x\t# .osc_max (battery, AC)\n", - p->osc_max[0], p->osc_max[1]); - printf("%d %d\t\t# .w_ofs (battery, AC)\n", - p->w_ofs[0], p->w_ofs[1]); - printf("0x%02x 0x%02x\t# .bright_bl_off_fixed (battery, AC)\n", - p->bright_bl_off_fixed[0], p->bright_bl_off_fixed[1]); - printf("0x%02x 0x%02x\t# .bright_bl_on_min (battery, AC)\n", - p->bright_bl_on_min[0], p->bright_bl_on_min[1]); - printf("0x%02x 0x%02x\t# .bright_bl_on_max (battery, AC)\n", - p->bright_bl_on_max[0], p->bright_bl_on_max[1]); - printf("%d %d %d\t# .battery_threshold\n", - p->battery_threshold[0], - p->battery_threshold[1], - p->battery_threshold[2]); - printf("%d %d %d %d\t\t# .s0_idx[] (battery)\n", - p->s0_idx[0][0], p->s0_idx[0][1], - p->s0_idx[0][2], p->s0_idx[0][3]); - printf("%d %d %d %d\t\t# .s0_idx[] (AC)\n", - p->s0_idx[1][0], p->s0_idx[1][1], - p->s0_idx[1][2], p->s0_idx[1][3]); - printf("%d %d %d %d\t# .s3_idx[] (battery)\n", - p->s3_idx[0][0], p->s3_idx[0][1], - p->s3_idx[0][2], p->s3_idx[0][3]); - printf("%d %d %d %d\t# .s3_idx[] (AC)\n", - p->s3_idx[1][0], p->s3_idx[1][1], - p->s3_idx[1][2], p->s3_idx[1][3]); - for (i = 0; i < ARRAY_SIZE(p->color); i++) - printf("0x%02x 0x%02x 0x%02x\t# color[%d]\n", - p->color[i].r, - p->color[i].g, - p->color[i].b, i); -} - -static int lb_rd_timing_v2par_from_file(const char *filename, - struct lightbar_params_v2_timing *p) -{ - FILE *fp; - char buf[80]; - int val[4]; - int r = 1; - int line = 0; - int want, got; - - fp = fopen(filename, "rb"); - if (!fp) { - fprintf(stderr, "Can't open %s: %s\n", - filename, strerror(errno)); - return 1; - } - - /* We must read the correct number of params from each line */ -#define READ(N) do { \ - line++; \ - want = (N); \ - got = -1; \ - if (!fgets(buf, sizeof(buf), fp)) \ - goto done; \ - got = sscanf(buf, "%i %i %i %i", \ - &val[0], &val[1], &val[2], &val[3]); \ - if (want != got) \ - goto done; \ - } while (0) - - READ(1); p->google_ramp_up = val[0]; - READ(1); p->google_ramp_down = val[0]; - READ(1); p->s3s0_ramp_up = val[0]; - READ(1); p->s0_tick_delay[0] = val[0]; - READ(1); p->s0_tick_delay[1] = val[0]; - READ(1); p->s0a_tick_delay[0] = val[0]; - READ(1); p->s0a_tick_delay[1] = val[0]; - READ(1); p->s0s3_ramp_down = val[0]; - READ(1); p->s3_sleep_for = val[0]; - READ(1); p->s3_ramp_up = val[0]; - READ(1); p->s3_ramp_down = val[0]; - READ(1); p->tap_tick_delay = val[0]; - READ(1); p->tap_gate_delay = val[0]; - READ(1); p->tap_display_time = val[0]; -#undef READ - - /* Yay */ - r = 0; -done: - if (r) - fprintf(stderr, "problem with line %d: wanted %d, got %d\n", - line, want, got); - fclose(fp); - return r; -} - -static int lb_rd_tap_v2par_from_file(const char *filename, - struct lightbar_params_v2_tap *p) -{ - FILE *fp; - char buf[80]; - int val[4]; - int r = 1; - int line = 0; - int want, got; - - fp = fopen(filename, "rb"); - if (!fp) { - fprintf(stderr, "Can't open %s: %s\n", - filename, strerror(errno)); - return 1; - } - - /* We must read the correct number of params from each line */ -#define READ(N) do { \ - line++; \ - want = (N); \ - got = -1; \ - if (!fgets(buf, sizeof(buf), fp)) \ - goto done; \ - got = sscanf(buf, "%i %i %i %i", \ - &val[0], &val[1], &val[2], &val[3]); \ - if (want != got) \ - goto done; \ - } while (0) - - READ(1); p->tap_pct_red = val[0]; - READ(1); p->tap_pct_green = val[0]; - READ(1); p->tap_seg_min_on = val[0]; - READ(1); p->tap_seg_max_on = val[0]; - READ(1); p->tap_seg_osc = val[0]; - READ(3); - p->tap_idx[0] = val[0]; - p->tap_idx[1] = val[1]; - p->tap_idx[2] = val[2]; -#undef READ - - /* Yay */ - r = 0; -done: - if (r) - fprintf(stderr, "problem with line %d: wanted %d, got %d\n", - line, want, got); - fclose(fp); - return r; -} - -static int lb_rd_osc_v2par_from_file(const char *filename, - struct lightbar_params_v2_oscillation *p) -{ - FILE *fp; - char buf[80]; - int val[4]; - int r = 1; - int line = 0; - int want, got; - - fp = fopen(filename, "rb"); - if (!fp) { - fprintf(stderr, "Can't open %s: %s\n", - filename, strerror(errno)); - return 1; - } - - /* We must read the correct number of params from each line */ -#define READ(N) do { \ - line++; \ - want = (N); \ - got = -1; \ - if (!fgets(buf, sizeof(buf), fp)) \ - goto done; \ - got = sscanf(buf, "%i %i %i %i", \ - &val[0], &val[1], &val[2], &val[3]); \ - if (want != got) \ - goto done; \ - } while (0) - - READ(2); - p->osc_min[0] = val[0]; - p->osc_min[1] = val[1]; - READ(2); - p->osc_max[0] = val[0]; - p->osc_max[1] = val[1]; - READ(2); - p->w_ofs[0] = val[0]; - p->w_ofs[1] = val[1]; -#undef READ - - /* Yay */ - r = 0; -done: - if (r) - fprintf(stderr, "problem with line %d: wanted %d, got %d\n", - line, want, got); - fclose(fp); - return r; -} - -static int lb_rd_bright_v2par_from_file(const char *filename, - struct lightbar_params_v2_brightness *p) -{ - FILE *fp; - char buf[80]; - int val[4]; - int r = 1; - int line = 0; - int want, got; - - fp = fopen(filename, "rb"); - if (!fp) { - fprintf(stderr, "Can't open %s: %s\n", - filename, strerror(errno)); - return 1; - } - - /* We must read the correct number of params from each line */ -#define READ(N) do { \ - line++; \ - want = (N); \ - got = -1; \ - if (!fgets(buf, sizeof(buf), fp)) \ - goto done; \ - got = sscanf(buf, "%i %i %i %i", \ - &val[0], &val[1], &val[2], &val[3]); \ - if (want != got) \ - goto done; \ - } while (0) - - READ(2); - p->bright_bl_off_fixed[0] = val[0]; - p->bright_bl_off_fixed[1] = val[1]; - - READ(2); - p->bright_bl_on_min[0] = val[0]; - p->bright_bl_on_min[1] = val[1]; - - READ(2); - p->bright_bl_on_max[0] = val[0]; - p->bright_bl_on_max[1] = val[1]; -#undef READ - - /* Yay */ - r = 0; -done: - if (r) - fprintf(stderr, "problem with line %d: wanted %d, got %d\n", - line, want, got); - fclose(fp); - return r; -} - -static int lb_rd_thlds_v2par_from_file(const char *filename, - struct lightbar_params_v2_thresholds *p) -{ - FILE *fp; - char buf[80]; - int val[4]; - int r = 1; - int line = 0; - int want, got; - - fp = fopen(filename, "rb"); - if (!fp) { - fprintf(stderr, "Can't open %s: %s\n", - filename, strerror(errno)); - return 1; - } - - /* We must read the correct number of params from each line */ -#define READ(N) do { \ - line++; \ - want = (N); \ - got = -1; \ - if (!fgets(buf, sizeof(buf), fp)) \ - goto done; \ - got = sscanf(buf, "%i %i %i %i", \ - &val[0], &val[1], &val[2], &val[3]); \ - if (want != got) \ - goto done; \ - } while (0) - - READ(3); - p->battery_threshold[0] = val[0]; - p->battery_threshold[1] = val[1]; - p->battery_threshold[2] = val[2]; -#undef READ - - /* Yay */ - r = 0; -done: - if (r) - fprintf(stderr, "problem with line %d: wanted %d, got %d\n", - line, want, got); - fclose(fp); - return r; -} - -static int lb_rd_colors_v2par_from_file(const char *filename, - struct lightbar_params_v2_colors *p) -{ - FILE *fp; - char buf[80]; - int val[4]; - int r = 1; - int line = 0; - int want, got; - int i; - - fp = fopen(filename, "rb"); - if (!fp) { - fprintf(stderr, "Can't open %s: %s\n", - filename, strerror(errno)); - return 1; - } - - /* We must read the correct number of params from each line */ -#define READ(N) do { \ - line++; \ - want = (N); \ - got = -1; \ - if (!fgets(buf, sizeof(buf), fp)) \ - goto done; \ - got = sscanf(buf, "%i %i %i %i", \ - &val[0], &val[1], &val[2], &val[3]); \ - if (want != got) \ - goto done; \ - } while (0) - - READ(4); - p->s0_idx[0][0] = val[0]; - p->s0_idx[0][1] = val[1]; - p->s0_idx[0][2] = val[2]; - p->s0_idx[0][3] = val[3]; - - READ(4); - p->s0_idx[1][0] = val[0]; - p->s0_idx[1][1] = val[1]; - p->s0_idx[1][2] = val[2]; - p->s0_idx[1][3] = val[3]; - - READ(4); - p->s3_idx[0][0] = val[0]; - p->s3_idx[0][1] = val[1]; - p->s3_idx[0][2] = val[2]; - p->s3_idx[0][3] = val[3]; - - READ(4); - p->s3_idx[1][0] = val[0]; - p->s3_idx[1][1] = val[1]; - p->s3_idx[1][2] = val[2]; - p->s3_idx[1][3] = val[3]; - for (i = 0; i < ARRAY_SIZE(p->color); i++) { - READ(3); - p->color[i].r = val[0]; - p->color[i].g = val[1]; - p->color[i].b = val[2]; - } - -#undef READ - - /* Yay */ - r = 0; -done: - if (r) - fprintf(stderr, "problem with line %d: wanted %d, got %d\n", - line, want, got); - fclose(fp); - return r; -} - -static void lb_show_v2par_timing(const struct lightbar_params_v2_timing *p) -{ - printf("%d\t\t# .google_ramp_up\n", p->google_ramp_up); - printf("%d\t\t# .google_ramp_down\n", p->google_ramp_down); - printf("%d\t\t# .s3s0_ramp_up\n", p->s3s0_ramp_up); - printf("%d\t\t# .s0_tick_delay (battery)\n", p->s0_tick_delay[0]); - printf("%d\t\t# .s0_tick_delay (AC)\n", p->s0_tick_delay[1]); - printf("%d\t\t# .s0a_tick_delay (battery)\n", p->s0a_tick_delay[0]); - printf("%d\t\t# .s0a_tick_delay (AC)\n", p->s0a_tick_delay[1]); - printf("%d\t\t# .s0s3_ramp_down\n", p->s0s3_ramp_down); - printf("%d\t\t# .s3_sleep_for\n", p->s3_sleep_for); - printf("%d\t\t# .s3_ramp_up\n", p->s3_ramp_up); - printf("%d\t\t# .s3_ramp_down\n", p->s3_ramp_down); - printf("%d\t\t# .tap_tick_delay\n", p->tap_tick_delay); - printf("%d\t\t# .tap_gate_delay\n", p->tap_gate_delay); - printf("%d\t\t# .tap_display_time\n", p->tap_display_time); -} - -static void lb_show_v2par_tap(const struct lightbar_params_v2_tap *p) -{ - printf("%d\t\t# .tap_pct_red\n", p->tap_pct_red); - printf("%d\t\t# .tap_pct_green\n", p->tap_pct_green); - printf("%d\t\t# .tap_seg_min_on\n", p->tap_seg_min_on); - printf("%d\t\t# .tap_seg_max_on\n", p->tap_seg_max_on); - printf("%d\t\t# .tap_seg_osc\n", p->tap_seg_osc); - printf("%d %d %d\t\t# .tap_idx\n", - p->tap_idx[0], p->tap_idx[1], p->tap_idx[2]); -} - -static void lb_show_v2par_osc(const struct lightbar_params_v2_oscillation *p) -{ - printf("0x%02x 0x%02x\t# .osc_min (battery, AC)\n", - p->osc_min[0], p->osc_min[1]); - printf("0x%02x 0x%02x\t# .osc_max (battery, AC)\n", - p->osc_max[0], p->osc_max[1]); - printf("%d %d\t\t# .w_ofs (battery, AC)\n", - p->w_ofs[0], p->w_ofs[1]); -} - -static void lb_show_v2par_bright(const struct lightbar_params_v2_brightness *p) -{ - printf("0x%02x 0x%02x\t# .bright_bl_off_fixed (battery, AC)\n", - p->bright_bl_off_fixed[0], p->bright_bl_off_fixed[1]); - printf("0x%02x 0x%02x\t# .bright_bl_on_min (battery, AC)\n", - p->bright_bl_on_min[0], p->bright_bl_on_min[1]); - printf("0x%02x 0x%02x\t# .bright_bl_on_max (battery, AC)\n", - p->bright_bl_on_max[0], p->bright_bl_on_max[1]); -} - -static void lb_show_v2par_thlds(const struct lightbar_params_v2_thresholds *p) -{ - printf("%d %d %d\t# .battery_threshold\n", - p->battery_threshold[0], - p->battery_threshold[1], - p->battery_threshold[2]); -} - -static void lb_show_v2par_colors(const struct lightbar_params_v2_colors *p) -{ - int i; - - printf("%d %d %d %d\t\t# .s0_idx[] (battery)\n", - p->s0_idx[0][0], p->s0_idx[0][1], - p->s0_idx[0][2], p->s0_idx[0][3]); - printf("%d %d %d %d\t\t# .s0_idx[] (AC)\n", - p->s0_idx[1][0], p->s0_idx[1][1], - p->s0_idx[1][2], p->s0_idx[1][3]); - printf("%d %d %d %d\t# .s3_idx[] (battery)\n", - p->s3_idx[0][0], p->s3_idx[0][1], - p->s3_idx[0][2], p->s3_idx[0][3]); - printf("%d %d %d %d\t# .s3_idx[] (AC)\n", - p->s3_idx[1][0], p->s3_idx[1][1], - p->s3_idx[1][2], p->s3_idx[1][3]); - - for (i = 0; i < ARRAY_SIZE(p->color); i++) - printf("0x%02x 0x%02x 0x%02x\t# color[%d]\n", - p->color[i].r, - p->color[i].g, - p->color[i].b, i); -} - -static int lb_load_program(const char *filename, struct lightbar_program *prog) -{ - FILE *fp; - size_t got; - int rc; - - fp = fopen(filename, "rb"); - if (!fp) { - fprintf(stderr, "Can't open %s: %s\n", - filename, strerror(errno)); - return 1; - } - - rc = fseek(fp, 0, SEEK_END); - if (rc) { - fprintf(stderr, "Couldn't find end of file %s", - filename); - fclose(fp); - return 1; - } - rc = (int) ftell(fp); - if (rc > EC_LB_PROG_LEN) { - fprintf(stderr, "File %s is too long, aborting\n", filename); - fclose(fp); - return 1; - } - rewind(fp); - - memset(prog->data, 0, EC_LB_PROG_LEN); - got = fread(prog->data, 1, EC_LB_PROG_LEN, fp); - if (rc != got) - fprintf(stderr, "Warning: did not read entire file\n"); - prog->size = got; - fclose(fp); - return 0; -} - -static int cmd_lightbar_params_v0(int argc, char **argv) -{ - struct ec_params_lightbar param; - struct ec_response_lightbar resp; - int r; - - if (argc > 2) { - r = lb_read_params_v0_from_file(argv[2], - ¶m.set_params_v0); - if (r) - return r; - return lb_do_cmd(LIGHTBAR_CMD_SET_PARAMS_V0, - ¶m, &resp); - } - r = lb_do_cmd(LIGHTBAR_CMD_GET_PARAMS_V0, ¶m, &resp); - if (!r) - lb_show_params_v0(&resp.get_params_v0); - return r; -} - -static int cmd_lightbar_params_v1(int argc, char **argv) -{ - struct ec_params_lightbar param; - struct ec_response_lightbar resp; - int r; - - if (argc > 2) { - r = lb_read_params_v1_from_file(argv[2], - ¶m.set_params_v1); - if (r) - return r; - return lb_do_cmd(LIGHTBAR_CMD_SET_PARAMS_V1, - ¶m, &resp); - } - r = lb_do_cmd(LIGHTBAR_CMD_GET_PARAMS_V1, ¶m, &resp); - if (!r) - lb_show_params_v1(&resp.get_params_v1); - return r; -} - -static void lb_param_v2_help(void) -{ - printf("Usage:\n"); - printf("lightbar params2 group [setfile]\n"); - printf("group list:\n"); - printf(" timing\n"); - printf(" tap\n"); - printf(" oscillation\n"); - printf(" brightness\n"); - printf(" thresholds\n"); - printf(" colors\n"); - - return; -} - -static int cmd_lightbar_params_v2(int argc, char **argv) -{ - struct ec_params_lightbar p; - struct ec_response_lightbar resp; - int r = 0; - int set = 0; - - memset(&p, 0, sizeof(struct ec_params_lightbar)); - memset(&resp, 0, sizeof(struct ec_response_lightbar)); - - if (argc < 3) { - lb_param_v2_help(); - return 1; - } - - /* Set new params if provided with a setfile */ - if (argc > 3) - set = 1; - - /* Show selected v2 params */ - if (!strncasecmp(argv[2], "timing", 6)) { - if (set) { - r = lb_rd_timing_v2par_from_file(argv[3], - &p.set_v2par_timing); - if (r) - return r; - r = lb_do_cmd(LIGHTBAR_CMD_SET_PARAMS_V2_TIMING, - &p, &resp); - if (r) - return r; - } - r = lb_do_cmd(LIGHTBAR_CMD_GET_PARAMS_V2_TIMING, &p, &resp); - if (r) - return r; - lb_show_v2par_timing(&resp.get_params_v2_timing); - } else if (!strcasecmp(argv[2], "tap")) { - if (set) { - r = lb_rd_tap_v2par_from_file(argv[3], - &p.set_v2par_tap); - if (r) - return r; - r = lb_do_cmd(LIGHTBAR_CMD_SET_PARAMS_V2_TAP, - &p, &resp); - if (r) - return r; - } - r = lb_do_cmd(LIGHTBAR_CMD_GET_PARAMS_V2_TAP, &p, &resp); - if (r) - return r; - lb_show_v2par_tap(&resp.get_params_v2_tap); - } else if (!strncasecmp(argv[2], "oscillation", 11)) { - if (set) { - r = lb_rd_osc_v2par_from_file(argv[3], - &p.set_v2par_osc); - if (r) - return r; - r = lb_do_cmd(LIGHTBAR_CMD_SET_PARAMS_V2_OSCILLATION, - &p, &resp); - if (r) - return r; - } - r = lb_do_cmd(LIGHTBAR_CMD_GET_PARAMS_V2_OSCILLATION, &p, - &resp); - if (r) - return r; - lb_show_v2par_osc(&resp.get_params_v2_osc); - } else if (!strncasecmp(argv[2], "brightness", 10)) { - if (set) { - r = lb_rd_bright_v2par_from_file(argv[3], - &p.set_v2par_bright); - if (r) - return r; - r = lb_do_cmd(LIGHTBAR_CMD_SET_PARAMS_V2_BRIGHTNESS, - &p, &resp); - if (r) - return r; - } - r = lb_do_cmd(LIGHTBAR_CMD_GET_PARAMS_V2_BRIGHTNESS, &p, - &resp); - if (r) - return r; - lb_show_v2par_bright(&resp.get_params_v2_bright); - } else if (!strncasecmp(argv[2], "thresholds", 10)) { - if (set) { - r = lb_rd_thlds_v2par_from_file(argv[3], - &p.set_v2par_thlds); - if (r) - return r; - r = lb_do_cmd(LIGHTBAR_CMD_SET_PARAMS_V2_THRESHOLDS, - &p, &resp); - if (r) - return r; - } - r = lb_do_cmd(LIGHTBAR_CMD_GET_PARAMS_V2_THRESHOLDS, &p, - &resp); - if (r) - return r; - lb_show_v2par_thlds(&resp.get_params_v2_thlds); - } else if (!strncasecmp(argv[2], "colors", 6)) { - if (set) { - r = lb_rd_colors_v2par_from_file(argv[3], - &p.set_v2par_colors); - if (r) - return r; - r = lb_do_cmd(LIGHTBAR_CMD_SET_PARAMS_V2_COLORS, - &p, &resp); - if (r) - return r; - } - r = lb_do_cmd(LIGHTBAR_CMD_GET_PARAMS_V2_COLORS, &p, &resp); - if (r) - return r; - lb_show_v2par_colors(&resp.get_params_v2_colors); - } else { - lb_param_v2_help(); - } - - return r; -} - -static int cmd_lightbar(int argc, char **argv) -{ - int i, r; - struct ec_params_lightbar param; - struct ec_response_lightbar resp; - - if (1 == argc) { /* no args = dump 'em all */ - r = lb_do_cmd(LIGHTBAR_CMD_DUMP, ¶m, &resp); - if (r) - return r; - for (i = 0; i < ARRAY_SIZE(resp.dump.vals); i++) { - printf(" %02x %02x %02x\n", - resp.dump.vals[i].reg, - resp.dump.vals[i].ic0, - resp.dump.vals[i].ic1); - } - return 0; - } - - if (argc == 2 && !strcasecmp(argv[1], "init")) - return lb_do_cmd(LIGHTBAR_CMD_INIT, ¶m, &resp); - - if (argc == 2 && !strcasecmp(argv[1], "off")) - return lb_do_cmd(LIGHTBAR_CMD_OFF, ¶m, &resp); - - if (argc == 2 && !strcasecmp(argv[1], "on")) - return lb_do_cmd(LIGHTBAR_CMD_ON, ¶m, &resp); - - if (!strcasecmp(argv[1], "params0")) - return cmd_lightbar_params_v0(argc, argv); - - if (!strcasecmp(argv[1], "params1")) - return cmd_lightbar_params_v1(argc, argv); - - if (!strcasecmp(argv[1], "params2")) - return cmd_lightbar_params_v2(argc, argv); - - if (!strcasecmp(argv[1], "params")) { - /* Just try them both */ - fprintf(stderr, "trying params1 ...\n"); - if (0 == cmd_lightbar_params_v1(argc, argv)) - return 0; - fprintf(stderr, "trying params0 ...\n"); - return cmd_lightbar_params_v0(argc, argv); - } - - if (!strcasecmp(argv[1], "version")) { - r = lb_do_cmd(LIGHTBAR_CMD_VERSION, ¶m, &resp); - if (!r) - printf("version %d flags 0x%x\n", - resp.version.num, resp.version.flags); - return r; - } - - if (argc > 1 && !strcasecmp(argv[1], "brightness")) { - char *e; - int rv; - if (argc > 2) { - param.set_brightness.num = 0xff & - strtoull(argv[2], &e, 16); - return lb_do_cmd(LIGHTBAR_CMD_SET_BRIGHTNESS, - ¶m, &resp); - } - rv = lb_do_cmd(LIGHTBAR_CMD_GET_BRIGHTNESS, - ¶m, &resp); - if (rv) - return rv; - printf("%02x\n", resp.get_brightness.num); - return 0; - } - - if (argc > 1 && !strcasecmp(argv[1], "demo")) { - int rv; - if (argc > 2) { - if (!strcasecmp(argv[2], "on") || argv[2][0] == '1') - param.demo.num = 1; - else if (!strcasecmp(argv[2], "off") || - argv[2][0] == '0') - param.demo.num = 0; - else { - fprintf(stderr, "Invalid arg\n"); - return -1; - } - return lb_do_cmd(LIGHTBAR_CMD_DEMO, ¶m, &resp); - } - - rv = lb_do_cmd(LIGHTBAR_CMD_GET_DEMO, ¶m, &resp); - if (rv) - return rv; - printf("%s\n", resp.get_demo.num ? "on" : "off"); - return 0; - } - - if (argc >= 2 && !strcasecmp(argv[1], "seq")) { - char *e; - uint8_t num; - if (argc == 2) - return lb_show_msg_names(); - num = 0xff & strtoull(argv[2], &e, 16); - if (e && *e) - num = lb_find_msg_by_name(argv[2]); - if (num >= LIGHTBAR_NUM_SEQUENCES) { - fprintf(stderr, "Invalid arg\n"); - return -1; - } - param.seq.num = num; - return lb_do_cmd(LIGHTBAR_CMD_SEQ, ¶m, &resp); - } - - if (argc >= 3 && !strcasecmp(argv[1], "program")) { - lb_load_program(argv[2], ¶m.set_program); - return lb_do_cmd(LIGHTBAR_CMD_SET_PROGRAM, ¶m, &resp); - } - - if (argc == 4) { - char *e; - param.reg.ctrl = 0xff & strtoull(argv[1], &e, 16); - param.reg.reg = 0xff & strtoull(argv[2], &e, 16); - param.reg.value = 0xff & strtoull(argv[3], &e, 16); - return lb_do_cmd(LIGHTBAR_CMD_REG, ¶m, &resp); - } - - if (argc == 5) { - char *e; - param.set_rgb.led = strtoull(argv[1], &e, 16); - param.set_rgb.red = strtoull(argv[2], &e, 16); - param.set_rgb.green = strtoull(argv[3], &e, 16); - param.set_rgb.blue = strtoull(argv[4], &e, 16); - return lb_do_cmd(LIGHTBAR_CMD_SET_RGB, ¶m, &resp); - } - - /* Only thing left is to try to read an LED value */ - if (argc == 2) { - char *e; - param.get_rgb.led = strtoull(argv[1], &e, 0); - if (!(e && *e)) { - r = lb_do_cmd(LIGHTBAR_CMD_GET_RGB, ¶m, &resp); - if (r) - return r; - printf("%02x %02x %02x\n", - resp.get_rgb.red, - resp.get_rgb.green, - resp.get_rgb.blue); - return 0; - } - } - - return lb_help(argv[0]); -} - -/* Create an array to store sizes of motion sense param and response structs. */ -#define ST_CMD_SIZE ST_FLD_SIZE(ec_params_motion_sense, cmd) -#define ST_PRM_SIZE(SUBCMD) \ - (ST_CMD_SIZE + ST_FLD_SIZE(ec_params_motion_sense, SUBCMD)) -#define ST_RSP_SIZE(SUBCMD) ST_FLD_SIZE(ec_response_motion_sense, SUBCMD) -#define ST_BOTH_SIZES(SUBCMD) { ST_PRM_SIZE(SUBCMD), ST_RSP_SIZE(SUBCMD) } - -/* - * For ectool only, assume no more than 16 sensors. More advanced - * implementation would allocate the right amount of memory depending on the - * number of sensors. - */ -#define ECTOOL_MAX_SENSOR 16 - -static const struct { - uint8_t outsize; - uint8_t insize; -} ms_command_sizes[] = { - { - ST_PRM_SIZE(dump), - ST_RSP_SIZE(dump) + - sizeof(struct ec_response_motion_sensor_data) * - ECTOOL_MAX_SENSOR - }, - ST_BOTH_SIZES(info_4), - ST_BOTH_SIZES(ec_rate), - ST_BOTH_SIZES(sensor_odr), - ST_BOTH_SIZES(sensor_range), - ST_BOTH_SIZES(kb_wake_angle), - ST_BOTH_SIZES(data), - { - ST_CMD_SIZE, - ST_RSP_SIZE(fifo_info) + sizeof(uint16_t) * ECTOOL_MAX_SENSOR - }, - ST_BOTH_SIZES(fifo_flush), - ST_BOTH_SIZES(fifo_read), - ST_BOTH_SIZES(perform_calib), - ST_BOTH_SIZES(sensor_offset), - ST_BOTH_SIZES(list_activities), - { ST_PRM_SIZE(set_activity), 0 }, - { ST_CMD_SIZE, ST_RSP_SIZE(lid_angle) }, - ST_BOTH_SIZES(fifo_int_enable), - ST_BOTH_SIZES(spoof), - ST_BOTH_SIZES(tablet_mode_threshold), - ST_BOTH_SIZES(sensor_scale), - ST_BOTH_SIZES(online_calib_read), - ST_BOTH_SIZES(get_activity), -}; -BUILD_ASSERT(ARRAY_SIZE(ms_command_sizes) == MOTIONSENSE_NUM_CMDS); - -#undef ST_CMD_SIZE -#undef ST_PRM_SIZE -#undef ST_RSP_SIZE -#undef ST_BOTH_SIZES - -static int ms_help(const char *cmd) -{ - printf("Usage:\n"); - printf(" %s - dump all motion data\n", - cmd); - printf(" %s active - print active flag\n", cmd); - printf(" %s info NUM - print sensor info\n", cmd); - printf(" %s ec_rate [RATE_MS] - set/get sample rate\n", - cmd); - printf(" %s odr NUM [ODR [ROUNDUP]] - set/get sensor ODR\n", - cmd); - printf(" %s range NUM [RANGE [ROUNDUP]] - set/get sensor range\n", - cmd); - printf(" %s offset NUM [-- X Y Z [TEMP]] - set/get sensor offset\n", - cmd); - printf(" %s kb_wake NUM - set/get KB wake ang\n", - cmd); - printf(" %s fifo_info - print fifo info\n", cmd); - printf(" %s fifo_int_enable [0/1] - enable/disable/get fifo " - "interrupt status\n", cmd); - printf(" %s fifo_read MAX_DATA - read fifo data\n", cmd); - printf(" %s fifo_flush NUM - trigger fifo interrupt\n", - cmd); - printf(" %s list_activities - list supported " - "activities\n", cmd); - printf(" %s set_activity ACT EN - enable/disable activity\n", - cmd); - printf(" %s get_activity ACT - get activity status\n", - cmd); - printf(" %s lid_angle - print lid angle\n", cmd); - printf(" %s spoof -- NUM [0/1] [X Y Z] - enable/disable spoofing\n", - cmd); - printf(" %s spoof -- NUM activity ACT [0/1] [STATE] - enable/disable " - "activity spoofing\n", cmd); - printf(" %s tablet_mode_angle ANG HYS - set/get tablet mode " - "angle\n", cmd); - printf(" %s calibrate NUM - run sensor calibration\n", - cmd); - - return 0; -} - -static void motionsense_display_activities(uint32_t activities) -{ - if (activities & BIT(MOTIONSENSE_ACTIVITY_SIG_MOTION)) - printf("%d: Significant motion\n", - MOTIONSENSE_ACTIVITY_SIG_MOTION); - if (activities & BIT(MOTIONSENSE_ACTIVITY_DOUBLE_TAP)) - printf("%d: Double tap\n", - MOTIONSENSE_ACTIVITY_DOUBLE_TAP); - if (activities & BIT(MOTIONSENSE_ACTIVITY_ORIENTATION)) - printf("%d: Orientation\n", - MOTIONSENSE_ACTIVITY_ORIENTATION); - if (activities & BIT(MOTIONSENSE_ACTIVITY_BODY_DETECTION)) - printf("%d: Body Detection\n", - MOTIONSENSE_ACTIVITY_BODY_DETECTION); -} - -static int cmd_motionsense(int argc, char **argv) -{ - int i, rv, status_only = (argc == 2); - struct ec_params_motion_sense param; - /* The largest size using resp as a response buffer */ - uint8_t resp_buffer[ms_command_sizes[MOTIONSENSE_CMD_DUMP].insize]; - struct ec_response_motion_sense *resp = - (struct ec_response_motion_sense *)resp_buffer; - char *e; - /* - * Warning: the following strings printed out are read in an - * autotest. Do not change string without consulting autotest - * for kernel_CrosECSysfsAccel. - */ - const char *motion_status_string[2][2] = { - { "Motion sensing inactive", "0"}, - { "Motion sensing active", "1"}, - }; - - /* No motionsense command has more than 7 args. */ - if (argc > 7) - return ms_help(argv[0]); - - if ((argc == 1) || - (argc == 2 && !strcasecmp(argv[1], "active"))) { - param.cmd = MOTIONSENSE_CMD_DUMP; - param.dump.max_sensor_count = ECTOOL_MAX_SENSOR; - rv = ec_command( - EC_CMD_MOTION_SENSE_CMD, 1, - ¶m, ms_command_sizes[param.cmd].outsize, - resp, ms_command_sizes[param.cmd].insize); - if (rv > 0) { - printf("%s\n", motion_status_string[ - !!(resp->dump.module_flags & - MOTIONSENSE_MODULE_FLAG_ACTIVE)][ - status_only]); - if (status_only) - return 0; - - if (resp->dump.sensor_count > ECTOOL_MAX_SENSOR) { - printf("Too many sensors to handle: %d", - resp->dump.sensor_count); - return -1; - } - for (i = 0; i < resp->dump.sensor_count; i++) { - /* - * Warning: the following string printed out - * is read by an autotest. Do not change string - * without consulting autotest for - * kernel_CrosECSysfsAccel. - */ - printf("Sensor %d: ", i); - if (resp->dump.sensor[i].flags & - MOTIONSENSE_SENSOR_FLAG_PRESENT) - printf("%d\t%d\t%d\n", - resp->dump.sensor[i].data[0], - resp->dump.sensor[i].data[1], - resp->dump.sensor[i].data[2]); - else - printf("None\n"); - } - return 0; - } else { - return rv; - } - } - - if (argc == 3 && !strcasecmp(argv[1], "info")) { - int version = 0; - - rv = get_latest_cmd_version(EC_CMD_MOTION_SENSE_CMD, &version); - if (rv < 0) - return rv; - - param.cmd = MOTIONSENSE_CMD_INFO; - param.sensor_odr.sensor_num = strtol(argv[2], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad %s arg.\n", argv[2]); - return -1; - } - - rv = ec_command(EC_CMD_MOTION_SENSE_CMD, version, - ¶m, ms_command_sizes[param.cmd].outsize, - resp, ms_command_sizes[param.cmd].insize); - if (rv < 0) - return rv; - - printf("Type: "); - switch (resp->info.type) { - case MOTIONSENSE_TYPE_ACCEL: - printf("accel\n"); - break; - case MOTIONSENSE_TYPE_GYRO: - printf("gyro\n"); - break; - case MOTIONSENSE_TYPE_MAG: - printf("magnetometer\n"); - break; - case MOTIONSENSE_TYPE_LIGHT: - printf("light\n"); - break; - case MOTIONSENSE_TYPE_LIGHT_RGB: - printf("rgb light\n"); - break; - case MOTIONSENSE_TYPE_PROX: - printf("proximity\n"); - break; - case MOTIONSENSE_TYPE_ACTIVITY: - printf("activity\n"); - break; - case MOTIONSENSE_TYPE_BARO: - printf("barometer\n"); - break; - case MOTIONSENSE_TYPE_SYNC: - printf("sync\n"); - break; - default: - printf("unknown\n"); - } - - printf("Location: "); - switch (resp->info.location) { - case MOTIONSENSE_LOC_BASE: - printf("base\n"); - break; - case MOTIONSENSE_LOC_LID: - printf("lid\n"); - break; - case MOTIONSENSE_LOC_CAMERA: - printf("camera\n"); - break; - default: - printf("unknown\n"); - } - - printf("Chip: "); - switch (resp->info.chip) { - case MOTIONSENSE_CHIP_KXCJ9: - printf("kxcj9\n"); - break; - case MOTIONSENSE_CHIP_LSM6DS0: - printf("lsm6ds0\n"); - break; - case MOTIONSENSE_CHIP_BMI160: - printf("bmi160\n"); - break; - case MOTIONSENSE_CHIP_SI1141: - printf("si1141\n"); - break; - case MOTIONSENSE_CHIP_KX022: - printf("kx022\n"); - break; - case MOTIONSENSE_CHIP_L3GD20H: - printf("l3gd20h\n"); - break; - case MOTIONSENSE_CHIP_BMA255: - printf("bma255\n"); - break; - case MOTIONSENSE_CHIP_BMP280: - printf("bmp280\n"); - break; - case MOTIONSENSE_CHIP_OPT3001: - printf("opt3001\n"); - break; - case MOTIONSENSE_CHIP_BH1730: - printf("bh1730\n"); - break; - case MOTIONSENSE_CHIP_GPIO: - printf("gpio\n"); - break; - case MOTIONSENSE_CHIP_LIS2DH: - printf("lis2dh\n"); - break; - case MOTIONSENSE_CHIP_LSM6DSM: - printf("lsm6dsm\n"); - break; - case MOTIONSENSE_CHIP_LIS2DE: - printf("lis2de\n"); - break; - case MOTIONSENSE_CHIP_LIS2MDL: - printf("lis2mdl\n"); - break; - case MOTIONSENSE_CHIP_LSM6DS3: - printf("lsm6ds3\n"); - break; - case MOTIONSENSE_CHIP_LSM6DSO: - printf("lsm6dso\n"); - break; - case MOTIONSENSE_CHIP_LNG2DM: - printf("lng2dm\n"); - break; - case MOTIONSENSE_CHIP_TCS3400: - printf("tcs3400\n"); - break; - case MOTIONSENSE_CHIP_LIS2DW12: - printf("lis2dw12\n"); - break; - case MOTIONSENSE_CHIP_LIS2DWL: - printf("lis2dwl\n"); - break; - case MOTIONSENSE_CHIP_LIS2DS: - printf("lis2ds\n"); - break; - case MOTIONSENSE_CHIP_BMI260: - printf("bmi260\n"); - break; - case MOTIONSENSE_CHIP_ICM426XX: - printf("icm426xx\n"); - break; - case MOTIONSENSE_CHIP_ICM42607: - printf("icm42607\n"); - break; - case MOTIONSENSE_CHIP_BMI323: - printf("bmi323\n"); - break; - case MOTIONSENSE_CHIP_BMA422: - printf("bma422\n"); - break; - default: - printf("unknown\n"); - } - - if (version >= 3) { - printf("Min Frequency: %d mHz\n", - resp->info_3.min_frequency); - printf("Max Frequency: %d mHz\n", - resp->info_3.max_frequency); - printf("FIFO Max Event Count: %d\n", - resp->info_3.fifo_max_event_count); - } - if (version >= 4) { - printf("Flags: %d\n", - resp->info_4.flags); - } - return 0; - } - - if (argc < 4 && !strcasecmp(argv[1], "ec_rate")) { - param.cmd = MOTIONSENSE_CMD_EC_RATE; - param.ec_rate.data = EC_MOTION_SENSE_NO_VALUE; - - if (argc == 3) { - param.ec_rate.data = strtol(argv[2], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad %s arg.\n", argv[2]); - return -1; - } - } - - rv = ec_command(EC_CMD_MOTION_SENSE_CMD, 1, - ¶m, ms_command_sizes[param.cmd].outsize, - resp, ms_command_sizes[param.cmd].insize); - - if (rv < 0) - return rv; - - printf("%d\n", resp->ec_rate.ret); - return 0; - } - - if (argc > 2 && !strcasecmp(argv[1], "odr")) { - param.cmd = MOTIONSENSE_CMD_SENSOR_ODR; - param.sensor_odr.data = EC_MOTION_SENSE_NO_VALUE; - param.sensor_odr.roundup = 1; - - param.sensor_odr.sensor_num = strtol(argv[2], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad %s arg.\n", argv[2]); - return -1; - } - - if (argc >= 4) { - param.sensor_odr.data = strtol(argv[3], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad %s arg.\n", argv[3]); - return -1; - } - } - - if (argc == 5) { - param.sensor_odr.roundup = strtol(argv[4], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad %s arg.\n", argv[4]); - return -1; - } - } - - rv = ec_command(EC_CMD_MOTION_SENSE_CMD, 1, - ¶m, ms_command_sizes[param.cmd].outsize, - resp, ms_command_sizes[param.cmd].insize); - - if (rv < 0) - return rv; - - printf("%d\n", resp->sensor_odr.ret); - return 0; - } - - if (argc > 2 && !strcasecmp(argv[1], "range")) { - param.cmd = MOTIONSENSE_CMD_SENSOR_RANGE; - param.sensor_range.data = EC_MOTION_SENSE_NO_VALUE; - param.sensor_range.roundup = 1; - - param.sensor_range.sensor_num = strtol(argv[2], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad %s arg.\n", argv[2]); - return -1; - } - - if (argc >= 4) { - param.sensor_range.data = strtol(argv[3], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad %s arg.\n", argv[3]); - return -1; - } - } - - if (argc == 5) { - param.sensor_odr.roundup = strtol(argv[4], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad %s arg.\n", argv[4]); - return -1; - } - } - - rv = ec_command(EC_CMD_MOTION_SENSE_CMD, 1, - ¶m, ms_command_sizes[param.cmd].outsize, - resp, ms_command_sizes[param.cmd].insize); - - if (rv < 0) - return rv; - - printf("%d\n", resp->sensor_range.ret); - return 0; - } - - if (argc < 4 && !strcasecmp(argv[1], "kb_wake")) { - param.cmd = MOTIONSENSE_CMD_KB_WAKE_ANGLE; - param.kb_wake_angle.data = EC_MOTION_SENSE_NO_VALUE; - - if (argc == 3) { - param.kb_wake_angle.data = strtol(argv[2], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad %s arg.\n", argv[2]); - return -1; - } - } - - rv = ec_command(EC_CMD_MOTION_SENSE_CMD, 1, - ¶m, ms_command_sizes[param.cmd].outsize, - resp, ms_command_sizes[param.cmd].insize); - - if (rv < 0) - return rv; - - printf("%d\n", resp->kb_wake_angle.ret); - return 0; - } - - if (argc < 5 && !strcasecmp(argv[1], "tablet_mode_angle")) { - param.cmd = MOTIONSENSE_CMD_TABLET_MODE_LID_ANGLE; - /* - * EC_MOTION_SENSE_NO_VALUE indicates to the EC that host is - * attempting to only read the current values. - */ - param.tablet_mode_threshold.lid_angle = - EC_MOTION_SENSE_NO_VALUE; - param.tablet_mode_threshold.hys_degree = - EC_MOTION_SENSE_NO_VALUE; - - if (argc == 4) { - param.tablet_mode_threshold.lid_angle = strtol(argv[2], - &e, 0); - - if (e && *e) { - fprintf(stderr, "Bad %s arg.\n", argv[2]); - return -1; - } - - param.tablet_mode_threshold.hys_degree = strtol(argv[3], - &e, 0); - if (e && *e) { - fprintf(stderr, "Bad %s arg.\n", argv[3]); - return -1; - } - } else if (argc != 2) { - return ms_help(argv[0]); - } - - rv = ec_command(EC_CMD_MOTION_SENSE_CMD, 2, - ¶m, ms_command_sizes[param.cmd].outsize, - resp, ms_command_sizes[param.cmd].insize); - - if (rv < 0) - return rv; - - printf("tablet_mode_angle=%d hys=%d\n", - resp->tablet_mode_threshold.lid_angle, - resp->tablet_mode_threshold.hys_degree); - - return 0; - } - - if (argc == 2 && !strcasecmp(argv[1], "fifo_info")) { - int sensor_count; - - param.cmd = MOTIONSENSE_CMD_DUMP; - param.dump.max_sensor_count = 0; - rv = ec_command(EC_CMD_MOTION_SENSE_CMD, 1, - ¶m, ms_command_sizes[param.cmd].outsize, - resp, ms_command_sizes[param.cmd].insize); - if (rv < 0) - return rv; - sensor_count = resp->dump.sensor_count; - - param.cmd = MOTIONSENSE_CMD_FIFO_INFO; - rv = ec_command(EC_CMD_MOTION_SENSE_CMD, 2, - ¶m, ms_command_sizes[param.cmd].outsize, - resp, ms_command_sizes[param.cmd].insize); - if (rv < 0) - return rv; - - printf("Size: %d\n", resp->fifo_info.size); - printf("Count: %d\n", resp->fifo_info.count); - printf("Timestamp:%" PRIx32 "\n", resp->fifo_info.timestamp); - printf("Total lost: %d\n", resp->fifo_info.total_lost); - for (i = 0; i < sensor_count; i++) { - int lost = resp->fifo_info.lost[i]; - if (lost != 0) - printf("Lost %d: %d\n", i, lost); - } - return 0; - } - - if (argc >= 2 && !strcasecmp(argv[1], "fifo_int_enable")) { - param.cmd = MOTIONSENSE_CMD_FIFO_INT_ENABLE; - if (argc == 3) - param.fifo_int_enable.enable = strtol(argv[2], &e, 0); - else - param.fifo_int_enable.enable = EC_MOTION_SENSE_NO_VALUE; - rv = ec_command(EC_CMD_MOTION_SENSE_CMD, 2, - ¶m, ms_command_sizes[param.cmd].outsize, - resp, ms_command_sizes[param.cmd].insize); - if (rv < 0) - return rv; - - printf("%d\n", resp->fifo_int_enable.ret); - return 0; - } - - if (argc == 3 && !strcasecmp(argv[1], "fifo_read")) { - /* large number to test fragmentation */ - struct { - uint32_t number_data; - struct ec_response_motion_sensor_data data[512]; - } fifo_read_buffer = { - .number_data = UINT32_MAX, - }; - int print_data = 0, max_data = strtol(argv[2], &e, 0); - - if (e && *e) { - fprintf(stderr, "Bad %s arg.\n", argv[2]); - return -1; - } - while (fifo_read_buffer.number_data != 0 && - print_data < max_data) { - struct ec_response_motion_sensor_data *vector; - param.cmd = MOTIONSENSE_CMD_FIFO_READ; - param.fifo_read.max_data_vector = - MIN(ARRAY_SIZE(fifo_read_buffer.data), - max_data - print_data); - - rv = ec_command(EC_CMD_MOTION_SENSE_CMD, 2, - ¶m, - ms_command_sizes[param.cmd].outsize, - &fifo_read_buffer, ec_max_insize); - if (rv < 0) - return rv; - - print_data += fifo_read_buffer.number_data; - for (i = 0; i < fifo_read_buffer.number_data; i++) { - vector = &fifo_read_buffer.data[i]; - if (vector->flags & - (MOTIONSENSE_SENSOR_FLAG_TIMESTAMP | - MOTIONSENSE_SENSOR_FLAG_FLUSH)) { - - printf("Timestamp:%" PRIx32 "%s\n", - vector->timestamp, - (vector->flags & - MOTIONSENSE_SENSOR_FLAG_FLUSH ? - " - Flush" : "")); - } else { - printf("Sensor %d: %d\t%d\t%d " - "(as uint16: %u\t%u\t%u)\n", - vector->sensor_num, - vector->data[0], - vector->data[1], - vector->data[2], - vector->data[0], - vector->data[1], - vector->data[2]); - } - } - } - return 0; - } - if (argc == 3 && !strcasecmp(argv[1], "fifo_flush")) { - param.cmd = MOTIONSENSE_CMD_FIFO_FLUSH; - - param.sensor_odr.sensor_num = strtol(argv[2], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad %s arg.\n", argv[2]); - return -1; - } - - rv = ec_command(EC_CMD_MOTION_SENSE_CMD, 1, - ¶m, ms_command_sizes[param.cmd].outsize, - resp, ms_command_sizes[param.cmd].insize); - - return rv < 0 ? rv : 0; - } - - if (argc == 3 && !strcasecmp(argv[1], "calibrate")) { - param.cmd = MOTIONSENSE_CMD_PERFORM_CALIB; - param.perform_calib.enable = 1; - param.perform_calib.sensor_num = strtol(argv[2], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad %s arg.\n", argv[2]); - return -1; - } - - rv = ec_command(EC_CMD_MOTION_SENSE_CMD, 1, - ¶m, ms_command_sizes[param.cmd].outsize, - resp, ms_command_sizes[param.cmd].insize); - - if (rv < 0) - return rv; - - printf("--- Calibrated well ---\n"); - printf("New offset vector: X:%d, Y:%d, Z:%d\n", - resp->perform_calib.offset[0], - resp->perform_calib.offset[1], - resp->perform_calib.offset[2]); - if ((uint16_t)resp->perform_calib.temp == - EC_MOTION_SENSE_INVALID_CALIB_TEMP) - printf("Temperature at calibration unknown\n"); - else - printf("Temperature at calibration: %d.%02d C\n", - resp->perform_calib.temp / 100, - resp->perform_calib.temp % 100); - return 0; - } - - if (argc >= 3 && !strcasecmp(argv[1], "offset")) { - param.cmd = MOTIONSENSE_CMD_SENSOR_OFFSET; - param.sensor_offset.flags = 0; - param.sensor_offset.temp = EC_MOTION_SENSE_INVALID_CALIB_TEMP; - - param.sensor_offset.sensor_num = strtol(argv[2], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad %s arg.\n", argv[2]); - return -1; - } - - if (argc >= 4) { - /* Regarded as a command to set offset */ - if (argc >= 6 && argc < 8) { - /* Set offset : X, Y, Z */ - param.sensor_offset.flags = MOTION_SENSE_SET_OFFSET; - for (i = 0; i < 3; i++) { - param.sensor_offset.offset[i] = strtol(argv[3+i], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad %s arg.\n", argv[3+i]); - return -1; - } - } - if (argc == 7) { - /* Set offset : Temperature */ - param.sensor_offset.temp = strtol(argv[6], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad %s arg.\n", argv[6]); - return -1; - } - } - } else { - return ms_help(argv[0]); - } - } - - rv = ec_command(EC_CMD_MOTION_SENSE_CMD, 1, - ¶m, ms_command_sizes[param.cmd].outsize, - resp, ms_command_sizes[param.cmd].insize); - - if (rv < 0) - return rv; - - printf("Offset vector: X:%d, Y:%d, Z:%d\n", - resp->sensor_offset.offset[0], - resp->sensor_offset.offset[1], - resp->sensor_offset.offset[2]); - if ((uint16_t)resp->sensor_offset.temp == - EC_MOTION_SENSE_INVALID_CALIB_TEMP) - printf("temperature at calibration unknown\n"); - else - printf("temperature at calibration: %d.%02d C\n", - resp->sensor_offset.temp / 100, - resp->sensor_offset.temp % 100); - return 0; - } - - if (argc == 2 && !strcasecmp(argv[1], "list_activities")) { - param.cmd = MOTIONSENSE_CMD_LIST_ACTIVITIES; - rv = ec_command(EC_CMD_MOTION_SENSE_CMD, 2, - ¶m, ms_command_sizes[param.cmd].outsize, - resp, ms_command_sizes[param.cmd].insize); - if (rv < 0) - return rv; - - printf("Enabled:\n"); - motionsense_display_activities(resp->list_activities.enabled); - printf("Disabled:\n"); - motionsense_display_activities(resp->list_activities.disabled); - return 0; - } - if (argc == 4 && !strcasecmp(argv[1], "set_activity")) { - param.cmd = MOTIONSENSE_CMD_SET_ACTIVITY; - param.set_activity.activity = strtol(argv[2], &e, 0); - param.set_activity.enable = strtol(argv[3], &e, 0); - - rv = ec_command(EC_CMD_MOTION_SENSE_CMD, 2, - ¶m, ms_command_sizes[param.cmd].outsize, - resp, ms_command_sizes[param.cmd].insize); - if (rv < 0) - return rv; - return 0; - } - if (argc == 3 && !strcasecmp(argv[1], "get_activity")) { - param.cmd = MOTIONSENSE_CMD_GET_ACTIVITY; - param.get_activity.activity = strtol(argv[2], &e, 0); - - rv = ec_command(EC_CMD_MOTION_SENSE_CMD, 2, - ¶m, ms_command_sizes[param.cmd].outsize, - resp, ms_command_sizes[param.cmd].insize); - if (rv < 0) - return rv; - printf("State: %d\n", resp->get_activity.state); - return 0; - } - if (argc == 2 && !strcasecmp(argv[1], "lid_angle")) { - param.cmd = MOTIONSENSE_CMD_LID_ANGLE; - rv = ec_command(EC_CMD_MOTION_SENSE_CMD, 2, - ¶m, ms_command_sizes[param.cmd].outsize, - resp, ms_command_sizes[param.cmd].insize); - if (rv < 0) - return rv; - - printf("Lid angle: "); - if (resp->lid_angle.value == LID_ANGLE_UNRELIABLE) - printf("unreliable\n"); - else - printf("%d\n", resp->lid_angle.value); - - return 0; - } - - if (argc >= 3 && !strcasecmp(argv[1], "spoof")) { - param.cmd = MOTIONSENSE_CMD_SPOOF; - /* By default, just query the current spoof status. */ - param.spoof.spoof_enable = MOTIONSENSE_SPOOF_MODE_QUERY; - param.spoof.sensor_id = strtol(argv[2], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad %s arg.\n", argv[2]); - return -1; - } - /* spoof activity state */ - if (argc >= 5 && !strcasecmp(argv[3], "activity")) { - int enable = 0; - - param.spoof.activity_num = strtol(argv[4], &e, 0); - if (e && *e) { - fprintf(stderr, "Base %s arg.\n", argv[4]); - return -1; - } - if (argc >= 6) { - enable = strtol(argv[5], &e, 0); - if ((e && *e) || (enable != 0 && enable != 1)) { - fprintf(stderr, "Bad %s arg.\n", - argv[5]); - return -1; - } - } - if ((enable == 1) && (argc == 6)) { - /* Enable spoofing, but lock to current state */ - param.spoof.spoof_enable = - MOTIONSENSE_SPOOF_MODE_LOCK_CURRENT; - } else if ((enable == 1) && (argc == 7)) { - /* Enable spoofing, but use provided state */ - int state = strtol(argv[6], &e, 0); - - if ((e && *e) || (state != 0 && state != 1)) { - fprintf(stderr, "Bad %s arg.\n", - argv[6]); - return -1; - } - param.spoof.activity_state = state; - param.spoof.spoof_enable = - MOTIONSENSE_SPOOF_MODE_CUSTOM; - } else if ((enable == 0) && (argc == 6)) { - param.spoof.spoof_enable = - MOTIONSENSE_SPOOF_MODE_DISABLE; - } else if (argc != 5) { - return ms_help(argv[0]); - } - /* spoof accel data */ - } else if (argc >= 4) { - int enable, i; - int16_t val; - - enable = strtol(argv[3], &e, 0); - if ((e && *e) || (enable != 0 && enable != 1)) { - fprintf(stderr, "Bad %s arg.\n", argv[3]); - return -1; - } - - if ((enable == 1) && (argc == 4)) { - /* - * Enable spoofing, but lock to current sensor - * values. - */ - param.spoof.spoof_enable = - MOTIONSENSE_SPOOF_MODE_LOCK_CURRENT; - } else if ((enable == 1) && (argc == 7)) { - /* - * Enable spoofing, but use provided component - * values. - */ - param.spoof.spoof_enable = - MOTIONSENSE_SPOOF_MODE_CUSTOM; - for (i = 0; i < 3; i++) { - val = strtol(argv[4+i], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad %s arg.\n", - argv[4+i]); - return -1; - } - param.spoof.components[i] = val; - } - } else if (enable == 0) { - param.spoof.spoof_enable = - MOTIONSENSE_SPOOF_MODE_DISABLE; - } else { - return ms_help(argv[0]); - } - } - - rv = ec_command(EC_CMD_MOTION_SENSE_CMD, 2, - ¶m, ms_command_sizes[param.cmd].outsize, - resp, ms_command_sizes[param.cmd].insize); - if (rv < 0) - return rv; - - if (param.spoof.spoof_enable == MOTIONSENSE_SPOOF_MODE_QUERY) - /* - * Response is the current spoof status of the - * sensor. - */ - printf("Sensor %d spoof mode is %s.\n", - param.spoof.sensor_id, - resp->spoof.ret ? "enabled" : "disabled"); - - return 0; - } - - return ms_help(argv[0]); -} - -int cmd_next_event(int argc, char *argv[]) -{ - uint8_t *rdata = (uint8_t *)ec_inbuf; - int rv; - int i; - - rv = ec_command(EC_CMD_GET_NEXT_EVENT, 0, - NULL, 0, rdata, ec_max_insize); - if (rv < 0) - return rv; - - printf("Next event is 0x%02x\n", rdata[0]); - if (rv > 1) { - printf("Event data:\n"); - for (i = 1; i < rv; ++i) { - printf("%02x ", rdata[i]); - if (!(i & 0xf)) - printf("\n"); - } - printf("\n"); - } - - return 0; -} - -static int find_led_color_by_name(const char *color) -{ - int i; - - for (i = 0; i < EC_LED_COLOR_COUNT; ++i) - if (!strcasecmp(color, led_color_names[i])) - return i; - - return -1; -} - -static int find_led_id_by_name(const char *led) -{ - int i; - - for (i = 0; i < EC_LED_ID_COUNT; ++i) - if (!strcasecmp(led, led_names[i])) - return i; - - return -1; -} - -int cmd_led(int argc, char *argv[]) -{ - struct ec_params_led_control p; - struct ec_response_led_control r; - char *e, *ptr; - int rv, i, j; - - memset(p.brightness, 0, sizeof(p.brightness)); - p.flags = 0; - - if (argc < 3) { - fprintf(stderr, - "Usage: %s <name> <query | auto | " - "off | <color> | <color>=<value>...>\n", argv[0]); - return -1; - } - - p.led_id = find_led_id_by_name(argv[1]); - if (p.led_id == (uint8_t)-1) { - fprintf(stderr, "Bad LED name: %s\n", argv[1]); - fprintf(stderr, "Valid LED names: "); - for (i = 0; i < EC_LED_ID_COUNT; i++) - fprintf(stderr, "%s ", led_names[i]); - fprintf(stderr, "\n"); - return -1; - } - - if (!strcasecmp(argv[2], "query")) { - p.flags = EC_LED_FLAGS_QUERY; - rv = ec_command(EC_CMD_LED_CONTROL, 1, &p, sizeof(p), - &r, sizeof(r)); - printf("Brightness range for LED %d:\n", p.led_id); - if (rv < 0) { - fprintf(stderr, "Error: Unsupported LED.\n"); - return rv; - } - for (i = 0; i < EC_LED_COLOR_COUNT; ++i) - printf("\t%s\t: 0x%x\n", - led_color_names[i], - r.brightness_range[i]); - return 0; - } - - if (!strcasecmp(argv[2], "off")) { - /* Brightness initialized to 0 for each color. */ - } else if (!strcasecmp(argv[2], "auto")) { - p.flags = EC_LED_FLAGS_AUTO; - } else if ((i = find_led_color_by_name(argv[2])) != -1) { - p.brightness[i] = 0xff; - } else { - for (i = 2; i < argc; ++i) { - ptr = strtok(argv[i], "="); - j = find_led_color_by_name(ptr); - if (j == -1) { - fprintf(stderr, "Bad color name: %s\n", ptr); - fprintf(stderr, "Valid colors: "); - for (j = 0; j < EC_LED_COLOR_COUNT; j++) - fprintf(stderr, "%s ", - led_color_names[j]); - fprintf(stderr, "\n"); - return -1; - } - ptr = strtok(NULL, "="); - if (ptr == NULL) { - fprintf(stderr, "Missing brightness value\n"); - return -1; - } - p.brightness[j] = strtol(ptr, &e, 0); - if (e && *e) { - fprintf(stderr, "Bad brightness: %s\n", ptr); - return -1; - } - } - } - - rv = ec_command(EC_CMD_LED_CONTROL, 1, &p, sizeof(p), &r, sizeof(r)); - return (rv < 0 ? rv : 0); -} - - -int cmd_usb_charge_set_mode(int argc, char *argv[]) -{ - struct ec_params_usb_charge_set_mode p; - char *e; - int rv; - - if (argc != 3 && argc != 4) { - fprintf(stderr, - "Usage: %s <port_id> <mode_id> [<inhibit_charge>]\n", - argv[0]); - return -1; - } - p.usb_port_id = strtol(argv[1], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad port ID.\n"); - return -1; - } - p.mode = strtol(argv[2], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad mode ID.\n"); - return -1; - } - p.inhibit_charge = 0; - if (argc == 4) { - p.inhibit_charge = strtol(argv[3], &e, 0); - if ((e && *e) || (p.inhibit_charge != 0 && - p.inhibit_charge != 1)) { - fprintf(stderr, "Bad value\n"); - return -1; - } - } - - printf("Setting port %d to mode %d inhibit_charge %d...\n", - p.usb_port_id, p.mode, p.inhibit_charge); - - rv = ec_command(EC_CMD_USB_CHARGE_SET_MODE, 0, - &p, sizeof(p), NULL, 0); - if (rv < 0) - return rv; - - printf("USB charging mode set.\n"); - return 0; -} - - -int cmd_usb_mux(int argc, char *argv[]) -{ - struct ec_params_usb_mux p; - char *e; - int rv; - - if (argc != 2) { - fprintf(stderr, "Usage: %s <mux>\n", argv[0]); - return -1; - } - - p.mux = strtol(argv[1], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad mux value.\n"); - return -1; - } - - rv = ec_command(EC_CMD_USB_MUX, 0, - &p, sizeof(p), NULL, 0); - if (rv < 0) - return rv; - - printf("Set USB mux to 0x%x.\n", p.mux); - - return 0; -} - - -int cmd_usb_pd(int argc, char *argv[]) -{ - const char *role_str[] = {"", "toggle", "toggle-off", "sink", "source", - "freeze"}; - const char *mux_str[] = {"", "none", "usb", "dp", "dock", "auto"}; - const char *swap_str[] = {"", "dr_swap", "pr_swap", "vconn_swap"}; - struct ec_params_usb_pd_control p; - struct ec_response_usb_pd_control_v2 *r_v2 = - (struct ec_response_usb_pd_control_v2 *)ec_inbuf; - struct ec_response_usb_pd_control_v1 *r_v1 = - (struct ec_response_usb_pd_control_v1 *)ec_inbuf; - struct ec_response_usb_pd_control *r = - (struct ec_response_usb_pd_control *)ec_inbuf; - int rv, i, j; - int option_ok; - char *e; - int cmdver; - - BUILD_ASSERT(ARRAY_SIZE(role_str) == USB_PD_CTRL_ROLE_COUNT); - BUILD_ASSERT(ARRAY_SIZE(mux_str) == USB_PD_CTRL_MUX_COUNT); - BUILD_ASSERT(ARRAY_SIZE(swap_str) == USB_PD_CTRL_SWAP_COUNT); - p.role = USB_PD_CTRL_ROLE_NO_CHANGE; - p.mux = USB_PD_CTRL_MUX_NO_CHANGE; - p.swap = USB_PD_CTRL_SWAP_NONE; - - if (argc < 2) { - fprintf(stderr, "No port specified.\n"); - return -1; - } - - p.port = strtol(argv[1], &e, 0); - if (e && *e) { - fprintf(stderr, "Invalid param (port)\n"); - return -1; - } - - for (i = 2; i < argc; ++i) { - option_ok = 0; - if (!strcmp(argv[i], "auto")) { - if (argc != 3) { - fprintf(stderr, "\"auto\" may not be used " - "with other options.\n"); - return -1; - } - p.role = USB_PD_CTRL_ROLE_TOGGLE_ON; - p.mux = USB_PD_CTRL_MUX_AUTO; - continue; - } - - for (j = 0; j < ARRAY_SIZE(role_str); ++j) { - if (!strcmp(argv[i], role_str[j])) { - if (p.role != USB_PD_CTRL_ROLE_NO_CHANGE) { - fprintf(stderr, - "Only one role allowed.\n"); - return -1; - } - p.role = j; - option_ok = 1; - break; - } - } - if (option_ok) - continue; - - for (j = 0; j < ARRAY_SIZE(mux_str); ++j) { - if (!strcmp(argv[i], mux_str[j])) { - if (p.mux != USB_PD_CTRL_MUX_NO_CHANGE) { - fprintf(stderr, - "Only one mux type allowed.\n"); - return -1; - } - p.mux = j; - option_ok = 1; - break; - } - } - if (option_ok) - continue; - - for (j = 0; j < ARRAY_SIZE(swap_str); ++j) { - if (!strcmp(argv[i], swap_str[j])) { - if (p.swap != USB_PD_CTRL_SWAP_NONE) { - fprintf(stderr, - "Only one swap type allowed.\n"); - return -1; - } - p.swap = j; - option_ok = 1; - break; - } - } - - - if (!option_ok) { - fprintf(stderr, "Unknown option: %s\n", argv[i]); - return -1; - } - } - - if (ec_cmd_version_supported(EC_CMD_USB_PD_CONTROL, 2)) - cmdver = 2; - else if (ec_cmd_version_supported(EC_CMD_USB_PD_CONTROL, 1)) - cmdver = 1; - else - cmdver = 0; - - rv = ec_command(EC_CMD_USB_PD_CONTROL, cmdver, &p, sizeof(p), - ec_inbuf, ec_max_insize); - - if (rv < 0 || argc != 2) - return (rv < 0) ? rv : 0; - - if (cmdver == 0) { - printf("Port C%d is %sabled, Role:%s Polarity:CC%d State:%d\n", - p.port, (r->enabled) ? "en" : "dis", - r->role == PD_ROLE_SOURCE ? "SRC" : "SNK", - r->polarity + 1, r->state); - } else { - printf("Port C%d: %s, %s State:%s\n" - "Role:%s %s%s, Polarity:CC%d\n", - p.port, - (r_v1->enabled & PD_CTRL_RESP_ENABLED_COMMS) ? - "enabled" : "disabled", - (r_v1->enabled & PD_CTRL_RESP_ENABLED_CONNECTED) ? - "connected" : "disconnected", - r_v1->state, - - (r_v1->role & PD_CTRL_RESP_ROLE_POWER) ? "SRC" : "SNK", - (r_v1->role & PD_CTRL_RESP_ROLE_DATA) ? "DFP" : "UFP", - (r_v1->role & PD_CTRL_RESP_ROLE_VCONN) ? " VCONN" : "", - r_v1->polarity + 1); - - if (cmdver == 2) { - printf("CC State:"); - if (r_v2->cc_state == PD_CC_NONE) - printf("None"); - else if (r_v2->cc_state == PD_CC_UFP_AUDIO_ACC) - printf("UFP Audio accessory"); - else if (r_v2->cc_state == PD_CC_UFP_DEBUG_ACC) - printf("UFP Debug accessory"); - else if (r_v2->cc_state == PD_CC_UFP_ATTACHED) - printf("UFP attached"); - else if (r_v2->cc_state == PD_CC_DFP_DEBUG_ACC) - printf("DFP Debug accessory"); - else if (r_v2->cc_state == PD_CC_DFP_ATTACHED) - printf("DFP attached"); - else - printf("UNKNOWN"); - printf("\n"); - - if (r_v2->dp_mode) { - printf("DP pin mode:"); - if (r_v2->dp_mode == MODE_DP_PIN_A) - printf("A"); - else if (r_v2->dp_mode == MODE_DP_PIN_B) - printf("B"); - else if (r_v2->dp_mode == MODE_DP_PIN_C) - printf("C"); - else if (r_v2->dp_mode == MODE_DP_PIN_D) - printf("D"); - else if (r_v2->dp_mode == MODE_DP_PIN_E) - printf("E"); - else if (r_v2->dp_mode == MODE_DP_PIN_F) - printf("F"); - else - printf("UNKNOWN"); - printf("\n"); - } - - printf("Cable type:%s\n", - r_v2->control_flags & USB_PD_CTRL_ACTIVE_CABLE ? - "Active" : "Passive"); - - printf("TBT Adapter type:%s\n", - r_v2->control_flags & - USB_PD_CTRL_TBT_LEGACY_ADAPTER ? - "Legacy" : "Gen3"); - - printf("Optical Cable:%s\n", - r_v2->control_flags & - USB_PD_CTRL_OPTICAL_CABLE ? "True" : "False"); - - printf("Link LSRX Communication:%s-directional\n", - r_v2->control_flags & - USB_PD_CTRL_ACTIVE_LINK_UNIDIR ? "Uni" : "Bi"); - - printf("TBT Cable Speed:"); - switch (r_v2->cable_speed) { - case TBT_SS_U31_GEN1: - printf("TBT Gen1"); - break; - case TBT_SS_U32_GEN1_GEN2: - printf("TBT Gen1 and TBT Gen2"); - break; - case TBT_SS_TBT_GEN3: - printf("TBT Gen3"); - break; - default: - printf("UNKNOWN"); - } - printf("\n"); - - printf("Rounded support: 3rd Gen %srounded support\n", - r_v2->cable_gen ? "and 4th Gen " : ""); - } - /* If connected to a PD device, then print port partner info */ - if ((r_v1->enabled & PD_CTRL_RESP_ENABLED_CONNECTED) && - (r_v1->enabled & PD_CTRL_RESP_ENABLED_PD_CAPABLE)) - printf("PD Partner Capabilities:\n%s%s%s%s", - (r_v1->role & PD_CTRL_RESP_ROLE_DR_POWER) ? - " DR power\n" : "", - (r_v1->role & PD_CTRL_RESP_ROLE_DR_DATA) ? - " DR data\n" : "", - (r_v1->role & PD_CTRL_RESP_ROLE_USB_COMM) ? - " USB capable\n" : "", - (r_v1->role & PD_CTRL_RESP_ROLE_UNCONSTRAINED) ? - " Unconstrained power\n" : ""); - } - return 0; -} - -static void print_pd_power_info(struct ec_response_usb_pd_power_info *r) -{ - switch (r->role) { - case USB_PD_PORT_POWER_DISCONNECTED: - printf("Disconnected"); - break; - case USB_PD_PORT_POWER_SOURCE: - printf("SRC"); - break; - case USB_PD_PORT_POWER_SINK: - printf("SNK"); - break; - case USB_PD_PORT_POWER_SINK_NOT_CHARGING: - printf("SNK (not charging)"); - break; - default: - printf("Unknown"); - } - - if ((r->role == USB_PD_PORT_POWER_SOURCE) && - (r->meas.current_max)) - printf(" %dmA", r->meas.current_max); - - if ((r->role == USB_PD_PORT_POWER_DISCONNECTED) || - (r->role == USB_PD_PORT_POWER_SOURCE)) { - printf("\n"); - return; - } - - printf(r->dualrole ? " DRP" : " Charger"); - switch (r->type) { - case USB_CHG_TYPE_PD: - printf(" PD"); - break; - case USB_CHG_TYPE_C: - printf(" Type-C"); - break; - case USB_CHG_TYPE_PROPRIETARY: - printf(" Proprietary"); - break; - case USB_CHG_TYPE_BC12_DCP: - printf(" DCP"); - break; - case USB_CHG_TYPE_BC12_CDP: - printf(" CDP"); - break; - case USB_CHG_TYPE_BC12_SDP: - printf(" SDP"); - break; - case USB_CHG_TYPE_OTHER: - printf(" Other"); - break; - case USB_CHG_TYPE_VBUS: - printf(" VBUS"); - break; - case USB_CHG_TYPE_UNKNOWN: - printf(" Unknown"); - break; - } - printf(" %dmV / %dmA, max %dmV / %dmA", - r->meas.voltage_now, r->meas.current_lim, r->meas.voltage_max, - r->meas.current_max); - if (r->max_power) - printf(" / %dmW", r->max_power / 1000); - printf("\n"); -} - -int cmd_usb_pd_mux_info(int argc, char *argv[]) -{ - struct ec_params_usb_pd_mux_info p; - struct ec_response_usb_pd_mux_info r; - int num_ports, rv, i; - - rv = ec_command(EC_CMD_USB_PD_PORTS, 0, NULL, 0, - ec_inbuf, ec_max_insize); - if (rv < 0) - return rv; - num_ports = ((struct ec_response_usb_pd_ports *)ec_inbuf)->num_ports; - - for (i = 0; i < num_ports; i++) { - p.port = i; - rv = ec_command(EC_CMD_USB_PD_MUX_INFO, 0, - &p, sizeof(p), - &r, sizeof(r)); - if (rv < 0) - return rv; - - printf("Port %d: ", i); - printf("USB=%d ", !!(r.flags & USB_PD_MUX_USB_ENABLED)); - printf("DP=%d ", !!(r.flags & USB_PD_MUX_DP_ENABLED)); - printf("POLARITY=%s ", r.flags & USB_PD_MUX_POLARITY_INVERTED ? - "INVERTED" : "NORMAL"); - printf("HPD_IRQ=%d ", !!(r.flags & USB_PD_MUX_HPD_IRQ)); - printf("HPD_LVL=%d ", !!(r.flags & USB_PD_MUX_HPD_LVL)); - printf("SAFE=%d ", !!(r.flags & USB_PD_MUX_SAFE_MODE)); - printf("TBT=%d ", !!(r.flags & USB_PD_MUX_TBT_COMPAT_ENABLED)); - printf("USB4=%d ", !!(r.flags & USB_PD_MUX_USB4_ENABLED)); - printf("\n"); - } - - return 0; -} - -int cmd_usb_pd_power(int argc, char *argv[]) -{ - struct ec_params_usb_pd_power_info p; - struct ec_response_usb_pd_power_info *r = - (struct ec_response_usb_pd_power_info *)ec_inbuf; - int num_ports, i, rv; - char *e; - - rv = ec_command(EC_CMD_USB_PD_PORTS, 0, NULL, 0, - ec_inbuf, ec_max_insize); - if (rv < 0) - return rv; - num_ports = ((struct ec_response_usb_pd_ports *)r)->num_ports; - - if (argc < 2) { - for (i = 0; i < num_ports; i++) { - p.port = i; - rv = ec_command(EC_CMD_USB_PD_POWER_INFO, 0, - &p, sizeof(p), - ec_inbuf, ec_max_insize); - if (rv < 0) - return rv; - - printf("Port %d: ", i); - print_pd_power_info(r); - } - } else { - p.port = strtol(argv[1], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad port.\n"); - return -1; - } - rv = ec_command(EC_CMD_USB_PD_POWER_INFO, 0, - &p, sizeof(p), - ec_inbuf, ec_max_insize); - if (rv < 0) - return rv; - - printf("Port %d: ", p.port); - print_pd_power_info(r); - } - - return 0; -} - -int cmd_kbpress(int argc, char *argv[]) -{ - struct ec_params_mkbp_simulate_key p; - char *e; - int rv; - - if (argc != 4) { - fprintf(stderr, - "Usage: %s <row> <col> <0|1>\n", argv[0]); - return -1; - } - p.row = strtol(argv[1], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad row.\n"); - return -1; - } - p.col = strtol(argv[2], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad column.\n"); - return -1; - } - p.pressed = strtol(argv[3], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad pressed flag.\n"); - return -1; - } - - printf("%s row %d col %d.\n", p.pressed ? "Pressing" : "Releasing", - p.row, - p.col); - - rv = ec_command(EC_CMD_MKBP_SIMULATE_KEY, 0, - &p, sizeof(p), NULL, 0); - if (rv < 0) - return rv; - printf("Done.\n"); - return 0; -} - -int cmd_keyboard_factory_test(int argc, char *argv[]) -{ - struct ec_response_keyboard_factory_test r; - int rv; - - rv = ec_command(EC_CMD_KEYBOARD_FACTORY_TEST, 0, - NULL, 0, &r, sizeof(r)); - if (rv < 0) - return rv; - - if (r.shorted != 0) - printf("Keyboard %d and %d pin are shorted.\n", - r.shorted & 0x00ff, r.shorted >> 8); - else - printf("Keyboard factory test passed.\n"); - - return 0; -} - -int cmd_panic_info(int argc, char *argv[]) -{ - int rv; - - rv = ec_command(EC_CMD_GET_PANIC_INFO, 0, NULL, 0, - ec_inbuf, ec_max_insize); - if (rv < 0) - return rv; - - if (rv == 0) { - printf("No panic data.\n"); - return 0; - } - - return parse_panic_info((char *)(ec_inbuf), rv); -} - - -int cmd_power_info(int argc, char *argv[]) -{ - struct ec_response_power_info_v1 r; - int rv; - - rv = ec_command(EC_CMD_POWER_INFO, 1, NULL, 0, &r, sizeof(r)); - if (rv < 0) - return rv; - - printf("Power source:\t"); - switch (r.system_power_source) { - case POWER_SOURCE_UNKNOWN: - printf("Unknown\n"); - break; - case POWER_SOURCE_BATTERY: - printf("Battery\n"); - break; - case POWER_SOURCE_AC: - printf("AC\n"); - break; - case POWER_SOURCE_AC_BATTERY: - printf("AC + battery\n"); - break; - } - - printf("Battery state-of-charge: %d%%\n", r.battery_soc); - printf("Max AC power: %d Watts\n", r.ac_adapter_100pct); - printf("Battery 1Cd rate: %d\n", r.battery_1cd); - printf("RoP Avg: %d Watts\n", r.rop_avg); - printf("RoP Peak: %d Watts\n", r.rop_peak); - printf("Battery DBPT support level: %d\n", - r.intel.batt_dbpt_support_level); - printf("Battery DBPT Max Peak Power: %d Watts\n", - r.intel.batt_dbpt_max_peak_power); - printf("Battery DBPT Sus Peak Power: %d Watts\n", - r.intel.batt_dbpt_sus_peak_power); - return 0; -} - - -int cmd_pse(int argc, char *argv[]) -{ - struct ec_params_pse p; - struct ec_response_pse_status r; - int rsize = 0; - char *e; - int rv; - - if (argc < 2 || argc > 3 || !strcmp(argv[1], "help")) { - printf("Usage: %s <port> [<subcmd>]\n", argv[0]); - printf("'pse <port> [status]' - Get port status\n"); - printf("'pse <port> disable' - Disable port\n"); - printf("'pse <port> enable' - Enable port\n"); - return -1; - } - - p.port = strtol(argv[1], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad port.\n"); - return -1; - } - - if (argc == 2 || !strcmp(argv[2], "status")) { - p.cmd = EC_PSE_STATUS; - rsize = sizeof(r); - } else if (!strcmp(argv[2], "disable")) { - p.cmd = EC_PSE_DISABLE; - } else if (!strcmp(argv[2], "enable")) { - p.cmd = EC_PSE_ENABLE; - } else { - fprintf(stderr, "Unknown command: %s\n", argv[2]); - return -1; - } - - rv = ec_command(EC_CMD_PSE, 0, &p, sizeof(p), &r, rsize); - if (rv < 0) - return rv; - - if (p.cmd == EC_PSE_STATUS) { - const char *status; - - switch (r.status) { - case EC_PSE_STATUS_DISABLED: - status = "disabled"; - break; - case EC_PSE_STATUS_ENABLED: - status = "enabled"; - break; - case EC_PSE_STATUS_POWERED: - status = "powered"; - break; - default: - status = "unknown"; - break; - } - - printf("Port %d: %s\n", p.port, status); - } - - return 0; -} - - -int cmd_pstore_info(int argc, char *argv[]) -{ - struct ec_response_pstore_info r; - int rv; - - rv = ec_command(EC_CMD_PSTORE_INFO, 0, NULL, 0, &r, sizeof(r)); - if (rv < 0) - return rv; - - printf("PstoreSize %d\nAccessSize %d\n", r.pstore_size, r.access_size); - return 0; -} - - -int cmd_pstore_read(int argc, char *argv[]) -{ - struct ec_params_pstore_read p; - uint8_t rdata[EC_PSTORE_SIZE_MAX]; - int offset, size; - int rv; - int i; - char *e; - char *buf; - - if (argc < 4) { - fprintf(stderr, - "Usage: %s <offset> <size> <filename>\n", argv[0]); - return -1; - } - offset = strtol(argv[1], &e, 0); - if ((e && *e) || offset < 0 || offset > 0x10000) { - fprintf(stderr, "Bad offset.\n"); - return -1; - } - size = strtol(argv[2], &e, 0); - if ((e && *e) || size <= 0 || size > 0x10000) { - fprintf(stderr, "Bad size.\n"); - return -1; - } - printf("Reading %d bytes at offset %d...\n", size, offset); - - buf = (char *)malloc(size); - if (!buf) { - fprintf(stderr, "Unable to allocate buffer.\n"); - return -1; - } - - /* Read data in chunks */ - for (i = 0; i < size; i += EC_PSTORE_SIZE_MAX) { - p.offset = offset + i; - p.size = MIN(size - i, EC_PSTORE_SIZE_MAX); - rv = ec_command(EC_CMD_PSTORE_READ, 0, - &p, sizeof(p), rdata, sizeof(rdata)); - if (rv < 0) { - fprintf(stderr, "Read error at offset %d\n", i); - free(buf); - return rv; - } - memcpy(buf + i, rdata, p.size); - } - - rv = write_file(argv[3], buf, size); - free(buf); - if (rv) - return rv; - - printf("done.\n"); - return 0; -} - - -int cmd_pstore_write(int argc, char *argv[]) -{ - struct ec_params_pstore_write p; - int offset, size; - int rv; - int i; - char *e; - char *buf; - - if (argc < 3) { - fprintf(stderr, "Usage: %s <offset> <filename>\n", argv[0]); - return -1; - } - offset = strtol(argv[1], &e, 0); - if ((e && *e) || offset < 0 || offset > 0x10000) { - fprintf(stderr, "Bad offset.\n"); - return -1; - } - - /* Read the input file */ - buf = read_file(argv[2], &size); - if (!buf) - return -1; - - printf("Writing to offset %d...\n", offset); - - /* Write data in chunks */ - for (i = 0; i < size; i += EC_PSTORE_SIZE_MAX) { - p.offset = offset + i; - p.size = MIN(size - i, EC_PSTORE_SIZE_MAX); - memcpy(p.data, buf + i, p.size); - rv = ec_command(EC_CMD_PSTORE_WRITE, 0, - &p, sizeof(p), NULL, 0); - if (rv < 0) { - fprintf(stderr, "Write error at offset %d\n", i); - free(buf); - return rv; - } - } - - free(buf); - printf("done.\n"); - return 0; -} - - -int cmd_host_event_get_raw(int argc, char *argv[]) -{ - uint32_t events = read_mapped_mem32(EC_MEMMAP_HOST_EVENTS); - - if (events & EC_HOST_EVENT_MASK(EC_HOST_EVENT_INVALID)) { - printf("Current host events: invalid\n"); - return -1; - } - - printf("Current host events: 0x%08x\n", events); - return 0; -} - - -int cmd_host_event_get_b(int argc, char *argv[]) -{ - struct ec_response_host_event_mask r; - int rv; - - rv = ec_command(EC_CMD_HOST_EVENT_GET_B, 0, - NULL, 0, &r, sizeof(r)); - if (rv < 0) - return rv; - if (rv < sizeof(r)) { - fprintf(stderr, "Insufficient data received.\n"); - return -1; - } - - if (r.mask & EC_HOST_EVENT_MASK(EC_HOST_EVENT_INVALID)) { - printf("Current host events-B: invalid\n"); - return -1; - } - - printf("Current host events-B: 0x%08x\n", r.mask); - return 0; -} - - -int cmd_host_event_get_smi_mask(int argc, char *argv[]) -{ - struct ec_response_host_event_mask r; - int rv; - - rv = ec_command(EC_CMD_HOST_EVENT_GET_SMI_MASK, 0, - NULL, 0, &r, sizeof(r)); - if (rv < 0) - return rv; - - printf("Current host event SMI mask: 0x%08x\n", r.mask); - return 0; -} - - -int cmd_host_event_get_sci_mask(int argc, char *argv[]) -{ - struct ec_response_host_event_mask r; - int rv; - - rv = ec_command(EC_CMD_HOST_EVENT_GET_SCI_MASK, 0, - NULL, 0, &r, sizeof(r)); - if (rv < 0) - return rv; - - printf("Current host event SCI mask: 0x%08x\n", r.mask); - return 0; -} - - -int cmd_host_event_get_wake_mask(int argc, char *argv[]) -{ - struct ec_response_host_event_mask r; - int rv; - - rv = ec_command(EC_CMD_HOST_EVENT_GET_WAKE_MASK, 0, - NULL, 0, &r, sizeof(r)); - if (rv < 0) - return rv; - - printf("Current host event wake mask: 0x%08x\n", r.mask); - return 0; -} - - -int cmd_host_event_set_smi_mask(int argc, char *argv[]) -{ - struct ec_params_host_event_mask p; - char *e; - int rv; - - if (argc != 2) { - fprintf(stderr, "Usage: %s <mask>\n", argv[0]); - return -1; - } - p.mask = strtol(argv[1], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad mask.\n"); - return -1; - } - - rv = ec_command(EC_CMD_HOST_EVENT_SET_SMI_MASK, 0, - &p, sizeof(p), NULL, 0); - if (rv < 0) - return rv; - - printf("Mask set.\n"); - return 0; -} - - -int cmd_host_event_set_sci_mask(int argc, char *argv[]) -{ - struct ec_params_host_event_mask p; - char *e; - int rv; - - if (argc != 2) { - fprintf(stderr, "Usage: %s <mask>\n", argv[0]); - return -1; - } - p.mask = strtol(argv[1], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad mask.\n"); - return -1; - } - - rv = ec_command(EC_CMD_HOST_EVENT_SET_SCI_MASK, 0, - &p, sizeof(p), NULL, 0); - if (rv < 0) - return rv; - - printf("Mask set.\n"); - return 0; -} - - -int cmd_host_event_set_wake_mask(int argc, char *argv[]) -{ - struct ec_params_host_event_mask p; - char *e; - int rv; - - if (argc != 2) { - fprintf(stderr, "Usage: %s <mask>\n", argv[0]); - return -1; - } - p.mask = strtol(argv[1], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad mask.\n"); - return -1; - } - - rv = ec_command(EC_CMD_HOST_EVENT_SET_WAKE_MASK, 0, - &p, sizeof(p), NULL, 0); - if (rv < 0) - return rv; - - printf("Mask set.\n"); - return 0; -} - - -int cmd_host_event_clear(int argc, char *argv[]) -{ - struct ec_params_host_event_mask p; - char *e; - int rv; - - if (argc != 2) { - fprintf(stderr, "Usage: %s <mask>\n", argv[0]); - return -1; - } - p.mask = strtol(argv[1], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad mask.\n"); - return -1; - } - - rv = ec_command(EC_CMD_HOST_EVENT_CLEAR, 0, - &p, sizeof(p), NULL, 0); - if (rv < 0) - return rv; - - printf("Host events cleared.\n"); - return 0; -} - - -int cmd_host_event_clear_b(int argc, char *argv[]) -{ - struct ec_params_host_event_mask p; - char *e; - int rv; - - if (argc != 2) { - fprintf(stderr, "Usage: %s <mask>\n", argv[0]); - return -1; - } - p.mask = strtol(argv[1], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad mask.\n"); - return -1; - } - - rv = ec_command(EC_CMD_HOST_EVENT_CLEAR_B, 0, - &p, sizeof(p), NULL, 0); - if (rv < 0) - return rv; - - printf("Host events-B cleared.\n"); - return 0; -} - - -int cmd_switches(int argc, char *argv[]) -{ - uint8_t s = read_mapped_mem8(EC_MEMMAP_SWITCHES); - printf("Current switches: 0x%02x\n", s); - printf("Lid switch: %s\n", - (s & EC_SWITCH_LID_OPEN ? "OPEN" : "CLOSED")); - printf("Power button: %s\n", - (s & EC_SWITCH_POWER_BUTTON_PRESSED ? "DOWN" : "UP")); - printf("Write protect: %sABLED\n", - (s & EC_SWITCH_WRITE_PROTECT_DISABLED ? "DIS" : "EN")); - printf("Dedicated recovery: %sABLED\n", - (s & EC_SWITCH_DEDICATED_RECOVERY ? "EN" : "DIS")); - - return 0; -} - - -int cmd_wireless(int argc, char *argv[]) -{ - char *e; - int rv; - int now_flags; - - if (argc < 2) { - fprintf(stderr, - "Usage: %s <flags> [<mask> [<susflags> <susmask>]]\n", - argv[0]); - fprintf(stderr, " 0x1 = WLAN radio\n" - " 0x2 = Bluetooth radio\n" - " 0x4 = WWAN power\n" - " 0x8 = WLAN power\n"); - return -1; - } - - now_flags = strtol(argv[1], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad flags.\n"); - return -1; - } - - if (argc < 3) { - /* Old-style - current flags only */ - struct ec_params_switch_enable_wireless_v0 p; - - p.enabled = now_flags; - rv = ec_command(EC_CMD_SWITCH_ENABLE_WIRELESS, 0, - &p, sizeof(p), NULL, 0); - if (rv < 0) - return rv; - - printf("Success.\n"); - } else { - /* New-style - masks and suspend flags */ - struct ec_params_switch_enable_wireless_v1 p; - struct ec_response_switch_enable_wireless_v1 r; - - memset(&p, 0, sizeof(p)); - - p.now_flags = now_flags; - - p.now_mask = strtol(argv[2], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad mask.\n"); - return -1; - } - - if (argc > 4) { - p.suspend_flags = strtol(argv[3], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad suspend flags.\n"); - return -1; - } - - p.suspend_mask = strtol(argv[4], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad suspend mask.\n"); - return -1; - } - } - - rv = ec_command(EC_CMD_SWITCH_ENABLE_WIRELESS, - EC_VER_SWITCH_ENABLE_WIRELESS, - &p, sizeof(p), &r, sizeof(r)); - if (rv < 0) - return rv; - - printf("Now=0x%x, suspend=0x%x\n", - r.now_flags, r.suspend_flags); - } - - return 0; -} - - -int cmd_i2c_protect(int argc, char *argv[]) -{ - struct ec_params_i2c_passthru_protect p; - char *e; - int rv; - - if (argc != 2 && (argc != 3 || strcmp(argv[2], "status"))) { - fprintf(stderr, "Usage: %s <port> [status]\n", - argv[0]); - return -1; - } - - p.port = strtol(argv[1], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad port.\n"); - return -1; - } - - if (argc == 3) { - struct ec_response_i2c_passthru_protect r; - - p.subcmd = EC_CMD_I2C_PASSTHRU_PROTECT_STATUS; - - rv = ec_command(EC_CMD_I2C_PASSTHRU_PROTECT, 0, &p, sizeof(p), - &r, sizeof(r)); - - if (rv < 0) - return rv; - - printf("I2C port %d: %s (%d)\n", p.port, - r.status ? "Protected" : "Unprotected", r.status); - } else { - p.subcmd = EC_CMD_I2C_PASSTHRU_PROTECT_ENABLE; - - rv = ec_command(EC_CMD_I2C_PASSTHRU_PROTECT, 0, &p, sizeof(p), - NULL, 0); - - if (rv < 0) - return rv; - } - return 0; -} - - -int do_i2c_xfer(unsigned int port, unsigned int addr, - uint8_t *write_buf, int write_len, - uint8_t **read_buf, int read_len) { - struct ec_params_i2c_passthru *p = - (struct ec_params_i2c_passthru *)ec_outbuf; - struct ec_response_i2c_passthru *r = - (struct ec_response_i2c_passthru *)ec_inbuf; - struct ec_params_i2c_passthru_msg *msg = p->msg; - uint8_t *pdata; - int size; - int rv; - - p->port = port; - p->num_msgs = (read_len != 0) + (write_len != 0); - - size = sizeof(*p) + p->num_msgs * sizeof(*msg); - if (size + write_len > ec_max_outsize) { - fprintf(stderr, "Params too large for buffer\n"); - return -1; - } - if (sizeof(*r) + read_len > ec_max_insize) { - fprintf(stderr, "Read length too big for buffer\n"); - return -1; - } - - pdata = (uint8_t *)p + size; - if (write_len) { - msg->addr_flags = addr; - msg->len = write_len; - - memcpy(pdata, write_buf, write_len); - msg++; - } - - if (read_len) { - msg->addr_flags = addr | EC_I2C_FLAG_READ; - msg->len = read_len; - } - - rv = ec_command(EC_CMD_I2C_PASSTHRU, 0, p, size + write_len, - r, sizeof(*r) + read_len); - if (rv < 0) - return rv; - - /* Parse response */ - if (r->i2c_status & (EC_I2C_STATUS_NAK | EC_I2C_STATUS_TIMEOUT)) { - fprintf(stderr, "Transfer failed with status=0x%x\n", - r->i2c_status); - return -1; - } - - if (rv < sizeof(*r) + read_len) { - fprintf(stderr, "Truncated read response\n"); - return -1; - } - - if (read_len) - *read_buf = r->data; - - return 0; -} - -static void cmd_i2c_help(void) -{ - fprintf(stderr, - " Usage: i2cread <8 | 16> <port> <addr8> <offset>\n" - " Usage: i2cwrite <8 | 16> <port> <addr8> <offset> <data>\n" - " Usage: i2cxfer <port> <addr7> <read_count> [bytes...]\n" - " <port> i2c port number\n" - " <addr8> 8-bit i2c address\n" - " <addr7> 7-bit i2c address\n" - " <offset> offset to read from or write to\n" - " <data> data to write\n" - " <read_count> number of bytes to read\n" - " [bytes ...] data to write\n" - ); - -} - -int cmd_i2c_read(int argc, char *argv[]) -{ - unsigned int port, addr8, addr7; - int read_len, write_len; - uint8_t write_buf[1]; - uint8_t *read_buf = NULL; - char *e; - int rv; - - if (argc != 5) { - cmd_i2c_help(); - return -1; - } - - read_len = strtol(argv[1], &e, 0); - if ((e && *e) || (read_len != 8 && read_len != 16)) { - fprintf(stderr, "Bad read size.\n"); - return -1; - } - read_len = read_len / 8; - - port = strtol(argv[2], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad port.\n"); - return -1; - } - - addr8 = strtol(argv[3], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad address.\n"); - return -1; - } - addr7 = addr8 >> 1; - - write_buf[0] = strtol(argv[4], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad offset.\n"); - return -1; - } - write_len = 1; - - rv = do_i2c_xfer(port, addr7, write_buf, write_len, &read_buf, - read_len); - - if (rv < 0) - return rv; - - printf("Read from I2C port %d at 0x%x offset 0x%x = 0x%x\n", - port, addr8, write_buf[0], *(uint16_t *)read_buf); - return 0; -} - - -int cmd_i2c_write(int argc, char *argv[]) -{ - unsigned int port, addr8, addr7; - int write_len; - uint8_t write_buf[3]; - char *e; - int rv; - - if (argc != 6) { - cmd_i2c_help(); - return -1; - } - - write_len = strtol(argv[1], &e, 0); - if ((e && *e) || (write_len != 8 && write_len != 16)) { - fprintf(stderr, "Bad write size.\n"); - return -1; - } - /* Include offset (length 1) */ - write_len = 1 + write_len / 8; - - port = strtol(argv[2], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad port.\n"); - return -1; - } - - addr8 = strtol(argv[3], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad address.\n"); - return -1; - } - addr7 = addr8 >> 1; - - write_buf[0] = strtol(argv[4], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad offset.\n"); - return -1; - } - - *((uint16_t *)&write_buf[1]) = strtol(argv[5], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad data.\n"); - return -1; - } - - rv = do_i2c_xfer(port, addr7, write_buf, write_len, NULL, 0); - - if (rv < 0) - return rv; - - printf("Wrote 0x%x to I2C port %d at 0x%x offset 0x%x.\n", - *((uint16_t *)&write_buf[1]), port, addr8, write_buf[0]); - return 0; -} - -int cmd_i2c_xfer(int argc, char *argv[]) -{ - unsigned int port, addr; - int read_len, write_len; - uint8_t *write_buf = NULL; - uint8_t *read_buf; - char *e; - int rv, i; - - if (argc < 4) { - cmd_i2c_help(); - return -1; - } - - port = strtol(argv[1], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad port.\n"); - return -1; - } - - addr = strtol(argv[2], &e, 0) & 0x7f; - if (e && *e) { - fprintf(stderr, "Bad peripheral address.\n"); - return -1; - } - - read_len = strtol(argv[3], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad read length.\n"); - return -1; - } - - /* Skip over params to bytes to write */ - argc -= 4; - argv += 4; - write_len = argc; - - if (write_len) { - write_buf = (uint8_t *)(malloc(write_len)); - if (write_buf == NULL) - return -1; - for (i = 0; i < write_len; i++) { - write_buf[i] = strtol(argv[i], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad write byte %d\n", i); - free(write_buf); - return -1; - } - } - } - - rv = do_i2c_xfer(port, addr, write_buf, write_len, &read_buf, read_len); - - if (write_len) - free(write_buf); - - if (rv) - return rv; - - if (read_len) { - if (ascii_mode) { - for (i = 0; i < read_len; i++) - printf(isprint(read_buf[i]) ? "%c" : "\\x%02x", - read_buf[i]); - } else { - printf("Read bytes:"); - for (i = 0; i < read_len; i++) - printf(" %#02x", read_buf[i]); - } - printf("\n"); - } else { - printf("Write successful.\n"); - } - - return 0; -} - -static void cmd_locate_chip_help(const char *const cmd) -{ - fprintf(stderr, - "Usage: %s <type> <index>\n" - " <type> is one of:\n" - " 0: CBI_EEPROM\n" - " 1: TCPCs\n" - " <index> instance # of <type>\n", - cmd); -} - -static const char *bus_type[] = { - "I2C", - "EMBEDDED" -}; - -int cmd_locate_chip(int argc, char *argv[]) -{ - struct ec_params_locate_chip p; - struct ec_response_locate_chip r = {0}; - char *e; - int rv; - - if (argc != 3) { - cmd_locate_chip_help(argv[0]); - return -1; - } - - p.type = strtol(argv[1], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad type.\n"); - cmd_locate_chip_help(argv[0]); - return -1; - } - - p.index = strtol(argv[2], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad index.\n"); - cmd_locate_chip_help(argv[0]); - return -1; - } - - rv = ec_command(EC_CMD_LOCATE_CHIP, 0, &p, sizeof(p), &r, sizeof(r)); - - if (rv == -EC_RES_INVALID_PARAM - EECRESULT) { - fprintf(stderr, "Bus type %d not supported.\n", p.type); - return rv; - } - - if (rv == -EC_RES_UNAVAILABLE - EECRESULT) { - fprintf(stderr, "Chip not found\n"); - return rv; - } - - if (rv == -EC_RES_OVERFLOW - EECRESULT) { - fprintf(stderr, "Index too large\n"); - return rv; - } - - if (rv < 0) - return rv; - - if (r.bus_type >= EC_BUS_TYPE_COUNT - || r.bus_type >= ARRAY_SIZE(bus_type)) { - fprintf(stderr, "Unknown bus type (%d)\n", r.bus_type); - return -1; - } - - /* - * When changing the format of this print, make sure FAFT - * (firmware_ECCbiEeprom) still passes. It may silently skip the test. - */ - printf("Bus: %s; Port: %d; Address: 0x%02x (7-bit format)\n", - bus_type[r.bus_type], r.i2c_info.port, - I2C_STRIP_FLAGS(r.i2c_info.addr_flags)); - - return 0; -} - -int cmd_lcd_backlight(int argc, char *argv[]) -{ - struct ec_params_switch_enable_backlight p; - char *e; - int rv; - - if (argc != 2) { - fprintf(stderr, "Usage: %s <0|1>\n", argv[0]); - return -1; - } - p.enabled = strtol(argv[1], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad value.\n"); - return -1; - } - - rv = ec_command(EC_CMD_SWITCH_ENABLE_BKLIGHT, 0, - &p, sizeof(p), NULL, 0); - if (rv < 0) - return rv; - - printf("Success.\n"); - return 0; -} - -static void cmd_basestate_help(void) -{ - fprintf(stderr, - "Usage: ectool basestate [attach | detach | reset]\n"); -} - -int cmd_basestate(int argc, char *argv[]) -{ - struct ec_params_set_base_state p; - - if (argc != 2) { - cmd_basestate_help(); - return -1; - } - - if (!strncmp(argv[1], "attach", 6)) { - p.cmd = EC_SET_BASE_STATE_ATTACH; - } else if (!strncmp(argv[1], "detach", 6)) { - p.cmd = EC_SET_BASE_STATE_DETACH; - } else if (!strncmp(argv[1], "reset", 5)) { - p.cmd = EC_SET_BASE_STATE_RESET; - } else { - cmd_basestate_help(); - return -1; - } - - return ec_command(EC_CMD_SET_BASE_STATE, 0, - &p, sizeof(p), NULL, 0); -} - -int cmd_ext_power_limit(int argc, char *argv[]) -{ - /* Version 1 is used, no support for obsolete version 0 */ - struct ec_params_external_power_limit_v1 p; - char *e; - - if (argc != 3) { - fprintf(stderr, - "Usage: %s <max_current_mA> <max_voltage_mV>\n", - argv[0]); - return -1; - } - - p.current_lim = strtol(argv[1], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad param1.\n"); - return -1; - } - - p.voltage_lim = strtol(argv[2], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad param2.\n"); - return -1; - } - - /* Send version 1 of command */ - return ec_command(EC_CMD_EXTERNAL_POWER_LIMIT, 1, &p, sizeof(p), - NULL, 0); -} - - -int cmd_charge_current_limit(int argc, char *argv[]) -{ - struct ec_params_current_limit p; - int rv; - char *e; - - if (argc != 2) { - fprintf(stderr, "Usage: %s <max_current_mA>\n", argv[0]); - return -1; - } - - p.limit = strtol(argv[1], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad value.\n"); - return -1; - } - - rv = ec_command(EC_CMD_CHARGE_CURRENT_LIMIT, 0, &p, sizeof(p), - NULL, 0); - return rv; -} - -static void cmd_charge_control_help(const char *cmd, const char *msg) -{ - if (msg) - fprintf(stderr, "ERROR: %s\n", msg); - - fprintf(stderr, - "\n" - " Usage: %s\n" - " Get current settings.\n" - " Usage: %s normal|idle|discharge\n" - " Set charge mode (and disable battery sustainer).\n" - " Usage: %s normal <lower> <upper>\n" - " Enable battery sustainer. <lower> and <upper> are battery SoC\n" - " between which EC tries to keep the battery level.\n" - "\n", - cmd, cmd, cmd); -} - -int cmd_charge_control(int argc, char *argv[]) -{ - struct ec_params_charge_control p; - struct ec_response_charge_control r; - int version = 2; - const char * const charge_mode_text[] = EC_CHARGE_MODE_TEXT; - char *e; - int rv; - - if (!ec_cmd_version_supported(EC_CMD_CHARGE_CONTROL, 2)) - version = 1; - - if (argc == 1) { - if (version < 2) { - cmd_charge_control_help(argv[0], - "Old EC doesn't support GET."); - return -1; - } - p.cmd = EC_CHARGE_CONTROL_CMD_GET; - rv = ec_command(EC_CMD_CHARGE_CONTROL, version, - &p, sizeof(p), &r, sizeof(r)); - if (rv < 0) { - fprintf(stderr, "Command failed.\n"); - return rv; - } - printf("Charge mode = %s (%d)\n", - r.mode < ARRAY_SIZE(charge_mode_text) - ? charge_mode_text[r.mode] : "UNDEFINED", - r.mode); - printf("Battery sustainer = %s (%d%% ~ %d%%)\n", - (r.sustain_soc.lower != -1 && r.sustain_soc.upper != -1) - ? "on" : "off", - r.sustain_soc.lower, r.sustain_soc.upper); - return 0; - } - - p.cmd = EC_CHARGE_CONTROL_CMD_SET; - if (!strcasecmp(argv[1], "normal")) { - p.mode = CHARGE_CONTROL_NORMAL; - if (argc == 2) { - p.sustain_soc.lower = -1; - p.sustain_soc.upper = -1; - } else if (argc == 4) { - if (version < 2) { - cmd_charge_control_help(argv[0], - "Old EC doesn't support sustainer."); - return -1; - } - p.sustain_soc.lower = strtol(argv[2], &e, 0); - if (e && *e) { - cmd_charge_control_help(argv[0], - "Bad character in <lower>"); - return -1; - } - p.sustain_soc.upper = strtol(argv[3], &e, 0); - if (e && *e) { - cmd_charge_control_help(argv[0], - "Bad character in <upper>"); - return -1; - } - } else { - cmd_charge_control_help(argv[0], "Bad arguments"); - return -1; - } - } else if (!strcasecmp(argv[1], "idle")) { - if (argc != 2) { - cmd_charge_control_help(argv[0], "Bad arguments"); - return -1; - } - p.mode = CHARGE_CONTROL_IDLE; - } else if (!strcasecmp(argv[1], "discharge")) { - if (argc != 2) { - cmd_charge_control_help(argv[0], "Bad arguments"); - return -1; - } - p.mode = CHARGE_CONTROL_DISCHARGE; - } else { - cmd_charge_control_help(argv[0], "Bad sub-command"); - return -1; - } - - rv = ec_command(EC_CMD_CHARGE_CONTROL, version, &p, sizeof(p), NULL, 0); - if (rv < 0) { - fprintf(stderr, "Is AC connected?\n"); - return rv; - } - - switch (p.mode) { - case CHARGE_CONTROL_NORMAL: - printf("Charge state machine is in normal mode%s.\n", - (p.sustain_soc.lower == -1 || p.sustain_soc.upper == -1) - ? "" : " with sustainer enabled"); - break; - case CHARGE_CONTROL_IDLE: - printf("Charge state machine force idle.\n"); - break; - case CHARGE_CONTROL_DISCHARGE: - printf("Charge state machine force discharge.\n"); - break; - default: - break; - } - return 0; -} - - -#define ST_CMD_SIZE ST_FLD_SIZE(ec_params_charge_state, cmd) -#define ST_PRM_SIZE(SUBCMD) \ - (ST_CMD_SIZE + ST_FLD_SIZE(ec_params_charge_state, SUBCMD)) -#define ST_RSP_SIZE(SUBCMD) ST_FLD_SIZE(ec_response_charge_state, SUBCMD) - -/* Table of subcommand sizes for EC_CMD_CHARGE_STATE */ -static const struct { - uint8_t to_ec_size; - uint8_t from_ec_size; -} cs_paramcount[] = { - /* Order must match enum charge_state_command */ - { ST_CMD_SIZE, ST_RSP_SIZE(get_state) }, - { ST_PRM_SIZE(get_param), ST_RSP_SIZE(get_param) }, - { ST_PRM_SIZE(set_param), 0}, -}; -BUILD_ASSERT(ARRAY_SIZE(cs_paramcount) == CHARGE_STATE_NUM_CMDS); - -#undef ST_CMD_SIZE -#undef ST_PRM_SIZE -#undef ST_RSP_SIZE - -static int cs_do_cmd(struct ec_params_charge_state *to_ec, - struct ec_response_charge_state *from_ec) -{ - int rv; - int cmd = to_ec->cmd; - - rv = ec_command(EC_CMD_CHARGE_STATE, 0, - to_ec, cs_paramcount[cmd].to_ec_size, - from_ec, cs_paramcount[cmd].from_ec_size); - - return (rv < 0 ? 1 : 0); -} - -static const char * const base_params[] = { - "chg_voltage", - "chg_current", - "chg_input_current", - "chg_status", - "chg_option", - "limit_power", -}; -BUILD_ASSERT(ARRAY_SIZE(base_params) == CS_NUM_BASE_PARAMS); - -static int cmd_charge_state(int argc, char **argv) -{ - struct ec_params_charge_state param; - struct ec_response_charge_state resp; - uint32_t p, v; - int i, r; - char *e; - - if (argc > 1 && !strcasecmp(argv[1], "show")) { - param.cmd = CHARGE_STATE_CMD_GET_STATE; - r = cs_do_cmd(¶m, &resp); - if (r) - return r; - printf("ac = %d\n", resp.get_state.ac); - printf("chg_voltage = %dmV\n", resp.get_state.chg_voltage); - printf("chg_current = %dmA\n", resp.get_state.chg_current); - printf("chg_input_current = %dmA\n", - resp.get_state.chg_input_current); - printf("batt_state_of_charge = %d%%\n", - resp.get_state.batt_state_of_charge); - return 0; - } - - if (argc > 1 && !strcasecmp(argv[1], "param")) { - switch (argc) { - case 3: - if (!strcasecmp(argv[2], "help")) - break; - param.cmd = CHARGE_STATE_CMD_GET_PARAM; - p = strtoull(argv[2], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad param: %s\n", argv[2]); - return -1; - } - param.get_param.param = p; - r = cs_do_cmd(¶m, &resp); - if (r) - return r; - v = resp.get_param.value; - if (p < CS_NUM_BASE_PARAMS) - printf("%d (0x%x) # %s\n", v, v, - base_params[p]); - else - printf("%d (0x%x)\n", v, v); - return 0; - case 4: - param.cmd = CHARGE_STATE_CMD_SET_PARAM; - p = strtoull(argv[2], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad param: %s\n", argv[2]); - return -1; - } - v = strtoull(argv[3], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad value: %s\n", argv[3]); - return -1; - } - param.set_param.param = p; - param.set_param.value = v; - return cs_do_cmd(¶m, &resp); - } - - printf("base params:\n"); - for (i = 0; i < CS_NUM_BASE_PARAMS; i++) - printf(" %d %s\n", i, base_params[i]); - printf("custom profile params:\n"); - printf(" 0x%x - 0x%x\n", CS_PARAM_CUSTOM_PROFILE_MIN, - CS_PARAM_CUSTOM_PROFILE_MAX); - - return 0; - } - - printf("Usage:\n"); - printf(" %s show - show current state\n", argv[0]); - printf(" %s param NUM [VALUE] - get/set param NUM\n", argv[0]); - printf(" %s param help - show known param NUMs\n", argv[0]); - return 0; -} - -int cmd_gpio_get(int argc, char *argv[]) -{ - struct ec_params_gpio_get_v1 p_v1; - struct ec_response_gpio_get_v1 r_v1; - int i, rv, subcmd, num_gpios; - int cmdver = 1; - - if (!ec_cmd_version_supported(EC_CMD_GPIO_GET, cmdver)) { - struct ec_params_gpio_get p; - struct ec_response_gpio_get r; - - /* Fall back to version 0 command */ - cmdver = 0; - if (argc != 2) { - fprintf(stderr, "Usage: %s <GPIO name>\n", argv[0]); - return -1; - } - - if (strlen(argv[1]) + 1 > sizeof(p.name)) { - fprintf(stderr, "GPIO name too long.\n"); - return -1; - } - strcpy(p.name, argv[1]); - - rv = ec_command(EC_CMD_GPIO_GET, cmdver, &p, - sizeof(p), &r, sizeof(r)); - if (rv < 0) - return rv; - - printf("GPIO %s = %d\n", p.name, r.val); - return 0; - } - - if (argc > 2 || (argc == 2 && !strcmp(argv[1], "help"))) { - printf("Usage: %s [<subcmd> <GPIO name>]\n", argv[0]); - printf("'gpioget <GPIO_NAME>' - Get value by name\n"); - printf("'gpioget count' - Get count of GPIOS\n"); - printf("'gpioget all' - Get info for all GPIOs\n"); - return -1; - } - - /* Keeping it consistent with console command behavior */ - if (argc == 1) - subcmd = EC_GPIO_GET_INFO; - else if (!strcmp(argv[1], "count")) - subcmd = EC_GPIO_GET_COUNT; - else if (!strcmp(argv[1], "all")) - subcmd = EC_GPIO_GET_INFO; - else - subcmd = EC_GPIO_GET_BY_NAME; - - if (subcmd == EC_GPIO_GET_BY_NAME) { - p_v1.subcmd = EC_GPIO_GET_BY_NAME; - if (strlen(argv[1]) + 1 > sizeof(p_v1.get_value_by_name.name)) { - fprintf(stderr, "GPIO name too long.\n"); - return -1; - } - strcpy(p_v1.get_value_by_name.name, argv[1]); - - rv = ec_command(EC_CMD_GPIO_GET, cmdver, &p_v1, - sizeof(p_v1), &r_v1, sizeof(r_v1)); - - if (rv < 0) - return rv; - - printf("GPIO %s = %d\n", p_v1.get_value_by_name.name, - r_v1.get_value_by_name.val); - return 0; - } - - /* Need GPIO count for EC_GPIO_GET_COUNT or EC_GPIO_GET_INFO */ - p_v1.subcmd = EC_GPIO_GET_COUNT; - rv = ec_command(EC_CMD_GPIO_GET, cmdver, &p_v1, - sizeof(p_v1), &r_v1, sizeof(r_v1)); - if (rv < 0) - return rv; - - if (subcmd == EC_GPIO_GET_COUNT) { - printf("GPIO COUNT = %d\n", r_v1.get_count.val); - return 0; - } - - /* subcmd EC_GPIO_GET_INFO */ - num_gpios = r_v1.get_count.val; - p_v1.subcmd = EC_GPIO_GET_INFO; - - for (i = 0; i < num_gpios; i++) { - p_v1.get_info.index = i; - - rv = ec_command(EC_CMD_GPIO_GET, cmdver, &p_v1, - sizeof(p_v1), &r_v1, sizeof(r_v1)); - if (rv < 0) - return rv; - - printf("%2d %-32s 0x%04X\n", r_v1.get_info.val, - r_v1.get_info.name, r_v1.get_info.flags); - } - - return 0; -} - - -int cmd_gpio_set(int argc, char *argv[]) -{ - struct ec_params_gpio_set p; - char *e; - int rv; - - if (argc != 3) { - fprintf(stderr, "Usage: %s <GPIO name> <0 | 1>\n", argv[0]); - return -1; - } - - if (strlen(argv[1]) + 1 > sizeof(p.name)) { - fprintf(stderr, "GPIO name too long.\n"); - return -1; - } - strcpy(p.name, argv[1]); - - p.val = strtol(argv[2], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad value.\n"); - return -1; - } - - rv = ec_command(EC_CMD_GPIO_SET, 0, &p, sizeof(p), NULL, 0); - if (rv < 0) - return rv; - - printf("GPIO %s set to %d\n", p.name, p.val); - return 0; -} - -void print_battery_flags(int flags) -{ - printf(" Flags 0x%02x", flags); - if (flags & EC_BATT_FLAG_AC_PRESENT) - printf(" AC_PRESENT"); - if (flags & EC_BATT_FLAG_BATT_PRESENT) - printf(" BATT_PRESENT"); - if (flags & EC_BATT_FLAG_DISCHARGING) - printf(" DISCHARGING"); - if (flags & EC_BATT_FLAG_CHARGING) - printf(" CHARGING"); - if (flags & EC_BATT_FLAG_LEVEL_CRITICAL) - printf(" LEVEL_CRITICAL"); - printf("\n"); -} - -int get_battery_command(int index) -{ - struct ec_params_battery_static_info static_p; - struct ec_response_battery_static_info_v1 static_r; - struct ec_params_battery_dynamic_info dynamic_p; - struct ec_response_battery_dynamic_info dynamic_r; - int rv; - - printf("Battery %d info:\n", index); - - static_p.index = index; - rv = ec_command(EC_CMD_BATTERY_GET_STATIC, 1, - &static_p, sizeof(static_p), - &static_r, sizeof(static_r)); - if (rv < 0) - return -1; - - dynamic_p.index = index; - rv = ec_command(EC_CMD_BATTERY_GET_DYNAMIC, 0, - &dynamic_p, sizeof(dynamic_p), - &dynamic_r, sizeof(dynamic_r)); - if (rv < 0) - return -1; - - if (dynamic_r.flags & EC_BATT_FLAG_INVALID_DATA) { - printf(" Invalid data (not present?)\n"); - return -1; - } - - if (!is_string_printable(static_r.manufacturer_ext)) - goto cmd_error; - printf(" OEM name: %s\n", static_r.manufacturer_ext); - - if (!is_string_printable(static_r.model_ext)) - goto cmd_error; - printf(" Model number: %s\n", static_r.model_ext); - - if (!is_string_printable(static_r.type_ext)) - goto cmd_error; - printf(" Chemistry : %s\n", static_r.type_ext); - - if (!is_string_printable(static_r.serial_ext)) - goto cmd_error; - printf(" Serial number: %s\n", static_r.serial_ext); - - if (!is_battery_range(static_r.design_capacity)) - goto cmd_error; - printf(" Design capacity: %u mAh\n", static_r.design_capacity); - - if (!is_battery_range(dynamic_r.full_capacity)) - goto cmd_error; - printf(" Last full charge: %u mAh\n", dynamic_r.full_capacity); - - if (!is_battery_range(static_r.design_voltage)) - goto cmd_error; - printf(" Design output voltage %u mV\n", static_r.design_voltage); - - if (!is_battery_range(static_r.cycle_count)) - goto cmd_error; - printf(" Cycle count %u\n", static_r.cycle_count); - - if (!is_battery_range(dynamic_r.actual_voltage)) - goto cmd_error; - printf(" Present voltage %u mV\n", dynamic_r.actual_voltage); - - /* current can be negative */ - printf(" Present current %d mA\n", dynamic_r.actual_current); - - if (!is_battery_range(dynamic_r.remaining_capacity)) - goto cmd_error; - printf(" Remaining capacity %u mAh\n", - dynamic_r.remaining_capacity); - - if (!is_battery_range(dynamic_r.desired_voltage)) - goto cmd_error; - printf(" Desired voltage %u mV\n", dynamic_r.desired_voltage); - - if (!is_battery_range(dynamic_r.desired_current)) - goto cmd_error; - printf(" Desired current %u mA\n", dynamic_r.desired_current); - - print_battery_flags(dynamic_r.flags); - return 0; - -cmd_error: - fprintf(stderr, "Bad battery info value.\n"); - return -1; -} - -int cmd_battery(int argc, char *argv[]) -{ - char batt_text[EC_MEMMAP_TEXT_MAX]; - int rv, val; - char *e; - int index = 0; - - if (argc > 2) { - fprintf(stderr, "Usage: %s [index]\n", argv[0]); - return -1; - } else if (argc == 2) { - index = strtol(argv[1], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad battery index.\n"); - return -1; - } - } - - /* - * Read non-primary batteries through hostcmd, and all batteries - * if longer strings are supported for static info. - */ - if (index > 0 || - ec_cmd_version_supported(EC_CMD_BATTERY_GET_STATIC, 1)) - return get_battery_command(index); - - val = read_mapped_mem8(EC_MEMMAP_BATTERY_VERSION); - if (val < 1) { - fprintf(stderr, "Battery version %d is not supported\n", val); - return -1; - } - - printf("Battery info:\n"); - - rv = read_mapped_string(EC_MEMMAP_BATT_MFGR, batt_text, - sizeof(batt_text)); - if (rv < 0 || !is_string_printable(batt_text)) - goto cmd_error; - printf(" OEM name: %s\n", batt_text); - - rv = read_mapped_string(EC_MEMMAP_BATT_MODEL, batt_text, - sizeof(batt_text)); - if (rv < 0 || !is_string_printable(batt_text)) - goto cmd_error; - printf(" Model number: %s\n", batt_text); - - rv = read_mapped_string(EC_MEMMAP_BATT_TYPE, batt_text, - sizeof(batt_text)); - if (rv < 0 || !is_string_printable(batt_text)) - goto cmd_error; - printf(" Chemistry : %s\n", batt_text); - - rv = read_mapped_string(EC_MEMMAP_BATT_SERIAL, batt_text, - sizeof(batt_text)); - printf(" Serial number: %s\n", batt_text); - - val = read_mapped_mem32(EC_MEMMAP_BATT_DCAP); - if (!is_battery_range(val)) - goto cmd_error; - printf(" Design capacity: %u mAh\n", val); - - val = read_mapped_mem32(EC_MEMMAP_BATT_LFCC); - if (!is_battery_range(val)) - goto cmd_error; - printf(" Last full charge: %u mAh\n", val); - - val = read_mapped_mem32(EC_MEMMAP_BATT_DVLT); - if (!is_battery_range(val)) - goto cmd_error; - printf(" Design output voltage %u mV\n", val); - - val = read_mapped_mem32(EC_MEMMAP_BATT_CCNT); - if (!is_battery_range(val)) - goto cmd_error; - printf(" Cycle count %u\n", val); - - val = read_mapped_mem32(EC_MEMMAP_BATT_VOLT); - if (!is_battery_range(val)) - goto cmd_error; - printf(" Present voltage %u mV\n", val); - - val = read_mapped_mem32(EC_MEMMAP_BATT_RATE); - if (!is_battery_range(val)) - goto cmd_error; - printf(" Present current %u mA\n", val); - - val = read_mapped_mem32(EC_MEMMAP_BATT_CAP); - if (!is_battery_range(val)) - goto cmd_error; - printf(" Remaining capacity %u mAh\n", val); - - val = read_mapped_mem8(EC_MEMMAP_BATT_FLAG); - print_battery_flags(val); - - return 0; -cmd_error: - fprintf(stderr, "Bad battery info value. Check protocol version.\n"); - return -1; -} - -int cmd_battery_cut_off(int argc, char *argv[]) -{ - struct ec_params_battery_cutoff p; - int cmd_version; - int rv; - - memset(&p, 0, sizeof(p)); - if (ec_cmd_version_supported(EC_CMD_BATTERY_CUT_OFF, 1)) { - cmd_version = 1; - if (argc > 1) { - if (!strcasecmp(argv[1], "at-shutdown")) { - p.flags = EC_BATTERY_CUTOFF_FLAG_AT_SHUTDOWN; - } else { - fprintf(stderr, "Bad parameter: %s\n", argv[1]); - return -1; - } - } - } else { - /* Fall back to version 0 command */ - cmd_version = 0; - if (argc > 1) { - if (!strcasecmp(argv[1], "at-shutdown")) { - fprintf(stderr, "Explicit 'at-shutdown' "); - fprintf(stderr, "parameter not supported.\n"); - } else { - fprintf(stderr, "Bad parameter: %s\n", argv[1]); - } - return -1; - } - } - - rv = ec_command(EC_CMD_BATTERY_CUT_OFF, cmd_version, &p, sizeof(p), - NULL, 0); - rv = (rv < 0 ? rv : 0); - - if (rv < 0) { - fprintf(stderr, "Failed to cut off battery, rv=%d\n", rv); - fprintf(stderr, "It is expected if the rv is -%d " - "(EC_RES_INVALID_COMMAND) if the battery " - "doesn't support cut-off function.\n", - EC_RES_INVALID_COMMAND); - } else { - printf("\n"); - printf("SUCCESS. The battery has arranged a cut-off.\n"); - - if (cmd_version == 1 && - (p.flags & EC_BATTERY_CUTOFF_FLAG_AT_SHUTDOWN)) - printf("The battery will be cut off after shutdown.\n"); - else - printf("The system should be shutdown immediately.\n"); - - printf("\n"); - } - return rv; -} - -int cmd_battery_vendor_param(int argc, char *argv[]) -{ - struct ec_params_battery_vendor_param p; - struct ec_response_battery_vendor_param r; - char *e; - int rv; - - if (argc < 3) - goto cmd_battery_vendor_param_usage; - - if (!strcasecmp(argv[1], "get")) - p.mode = BATTERY_VENDOR_PARAM_MODE_GET; - else if (!strcasecmp(argv[1], "set")) - p.mode = BATTERY_VENDOR_PARAM_MODE_SET; - else - goto cmd_battery_vendor_param_usage; - - p.param = strtol(argv[2], &e, 0); - if (e && *e) { - fprintf(stderr, "Invalid param.\n"); - goto cmd_battery_vendor_param_usage; - } - - if (p.mode == BATTERY_VENDOR_PARAM_MODE_SET) { - if (argc != 4) { - fprintf(stderr, "Missing value.\n"); - goto cmd_battery_vendor_param_usage; - } - - p.value = strtol(argv[3], &e, 0); - if (e && *e) { - fprintf(stderr, "Invalid value.\n"); - goto cmd_battery_vendor_param_usage; - } - } - - rv = ec_command(EC_CMD_BATTERY_VENDOR_PARAM, 0, &p, sizeof(p), - &r, sizeof(r)); - - if (rv < 0) - return rv; - - printf("0x%08x\n", r.value); - - return 0; - -cmd_battery_vendor_param_usage: - fprintf(stderr, - "Usage:\t %s get <param>\n" - "\t %s set <param> <value>\n", - argv[0], argv[0]); - return -1; -} - -int cmd_board_version(int argc, char *argv[]) -{ - struct ec_response_board_version response; - int rv; - - rv = ec_command(EC_CMD_GET_BOARD_VERSION, 0, NULL, 0, &response, - sizeof(response)); - if (rv < 0) - return rv; - - printf("%d\n", response.board_version); - return rv; -} - -static void cmd_cbi_help(char *cmd) -{ - fprintf(stderr, - " Usage: %s get <tag> [get_flag]\n" - " Usage: %s set <tag> <value/string> <size> [set_flag]\n" - " Usage: %s remove <tag> [set_flag]\n" - " <tag> is one of:\n" - " 0: BOARD_VERSION\n" - " 1: OEM_ID\n" - " 2: SKU_ID\n" - " 3: DRAM_PART_NUM (string)\n" - " 4: OEM_NAME (string)\n" - " 5: MODEL_ID\n" - " 6: FW_CONFIG\n" - " 7: PCB_VENDOR\n" - " 8: SSFC\n" - " 9: REWORK_ID\n" - " <size> is the size of the data in byte. It should be zero for\n" - " string types.\n" - " <value/string> is an integer or a string to be set\n" - " [get_flag] is combination of:\n" - " 01b: Invalidate cache and reload data from EEPROM\n" - " [set_flag] is combination of:\n" - " 01b: Skip write to EEPROM. Use for back-to-back writes\n" - " 10b: Set all fields to defaults first\n", cmd, cmd, cmd); -} - -static int cmd_cbi_is_string_field(enum cbi_data_tag tag) -{ - return tag == CBI_TAG_DRAM_PART_NUM || tag == CBI_TAG_OEM_NAME; -} - -/* - * Write value to CBI - * - * TODO: Support asynchronous write - */ -static int cmd_cbi(int argc, char *argv[]) -{ - enum cbi_data_tag tag; - char *e; - int rv; - - if (argc < 3) { - fprintf(stderr, "Invalid number of params\n"); - cmd_cbi_help(argv[0]); - return -1; - } - - /* Tag */ - tag = (enum cbi_data_tag)(strtol(argv[2], &e, 0)); - if (e && *e) { - fprintf(stderr, "Bad tag\n"); - return -1; - } - - if (!strcasecmp(argv[1], "get")) { - struct ec_params_get_cbi p = { 0 }; - int i; - - p.tag = tag; - if (argc > 3) { - p.flag = strtol(argv[3], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad flag\n"); - return -1; - } - } - rv = ec_command(EC_CMD_GET_CROS_BOARD_INFO, 0, &p, sizeof(p), - ec_inbuf, ec_max_insize); - if (rv < 0) { - fprintf(stderr, "Error code: %d\n", rv); - return rv; - } - if (rv < sizeof(uint8_t)) { - fprintf(stderr, "Invalid size: %d\n", rv); - return -1; - } - if (cmd_cbi_is_string_field(tag)) { - printf("%.*s", rv, (const char *)ec_inbuf); - } else { - const uint8_t * const buffer = - (const uint8_t *const)(ec_inbuf); - uint64_t int_value = 0; - for(i = 0; i < rv; i++) - int_value |= (uint64_t)buffer[i] << (i * 8); - - printf("As uint: %llu (0x%llx)\n", - (unsigned long long)int_value, - (unsigned long long)int_value); - printf("As binary:"); - for (i = 0; i < rv; i++) { - if (i % 32 == 31) - printf("\n"); - printf(" %02x", buffer[i]); - } - } - printf("\n"); - return 0; - } else if (!strcasecmp(argv[1], "set")) { - struct ec_params_set_cbi *p = - (struct ec_params_set_cbi *)ec_outbuf; - void *val_ptr; - uint64_t val = 0; - uint8_t size; - uint8_t bad_size = 0; - if (argc < 5) { - fprintf(stderr, "Invalid number of params\n"); - cmd_cbi_help(argv[0]); - return -1; - } - memset(p, 0, ec_max_outsize); - p->tag = tag; - - if (cmd_cbi_is_string_field(tag)) { - val_ptr = argv[3]; - size = strlen((char *)(val_ptr)) + 1; - } else { - val = strtoul(argv[3], &e, 0); - /* strtoul sets an errno for invalid input. If the value - * read is out of range of representable values by an - * unsigned long int, the function returns ULONG_MAX - * or ULONG_MIN and the errno is set to ERANGE. - */ - if ((e && *e) || errno == ERANGE) { - fprintf(stderr, "Bad value\n"); - return -1; - } - size = strtol(argv[4], &e, 0); - if (tag == CBI_TAG_REWORK_ID) { - if ((e && *e) || size < 1 || size > 8 || - (size < 8 && val >= (1ull << size*8))) - bad_size = 1; - } else { - if ((e && *e) || size < 1 || 4 < size || - val >= (1ull << size*8)) - bad_size = 1; - } - if (bad_size == 1) { - fprintf(stderr, "Bad size: %d\n", size); - return -1; - } - - val_ptr = &val; - } - - if (size > ec_max_outsize - sizeof(*p)) { - fprintf(stderr, "Size exceeds parameter buffer: %d\n", - size); - return -1; - } - /* Little endian */ - memcpy(p->data, val_ptr, size); - p->size = size; - if (argc > 5) { - p->flag = strtol(argv[5], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad flag\n"); - return -1; - } - } - rv = ec_command(EC_CMD_SET_CROS_BOARD_INFO, 0, - p, sizeof(*p) + size, NULL, 0); - if (rv < 0) { - if (rv == -EC_RES_ACCESS_DENIED - EECRESULT) - fprintf(stderr, "Write-protect is enabled or " - "EC explicitly refused to change the " - "requested field.\n"); - else - fprintf(stderr, "Error code: %d\n", rv); - return rv; - } - return 0; - } else if (!strcasecmp(argv[1], "remove")) { - struct ec_params_set_cbi p = { 0 }; - - p.tag = tag; - p.size = 0; - if (argc > 3) { - p.flag = strtol(argv[3], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad flag\n"); - return -1; - } - } - rv = ec_command(EC_CMD_SET_CROS_BOARD_INFO, 0, - &p, sizeof(p), NULL, 0); - if (rv < 0) { - if (rv == -EC_RES_ACCESS_DENIED - EECRESULT) - fprintf(stderr, "Write-protect is enabled or " - "EC explicitly refused to change the " - "requested field.\n"); - else - fprintf(stderr, "Error code: %d\n", rv); - return rv; - } - return 0; - } - - fprintf(stderr, "Invalid sub command: %s\n", argv[1]); - cmd_cbi_help(argv[0]); - - return -1; -} - -int cmd_chipinfo(int argc, char *argv[]) -{ - struct ec_response_get_chip_info info; - int rv; - - printf("Chip info:\n"); - - rv = ec_command(EC_CMD_GET_CHIP_INFO, 0, NULL, 0, &info, sizeof(info)); - if (rv < 0) - return rv; - printf(" vendor: %s\n", info.vendor); - printf(" name: %s\n", info.name); - printf(" revision: %s\n", info.revision); - - return 0; -} - -int cmd_proto_info(int argc, char *argv[]) -{ - struct ec_response_get_protocol_info info; - int rv; - int i; - - printf("Protocol info:\n"); - - rv = ec_command(EC_CMD_GET_PROTOCOL_INFO, 0, NULL, 0, - &info, sizeof(info)); - if (rv < 0) { - fprintf(stderr, "Protocol info unavailable. EC probably only " - "supports protocol version 2.\n"); - return rv; - } - - printf(" protocol versions:"); - for (i = 0; i < 32; i++) { - if (info.protocol_versions & BIT(i)) - printf(" %d", i); - } - printf("\n"); - - printf(" max request: %4d bytes\n", info.max_request_packet_size); - printf(" max response: %4d bytes\n", info.max_response_packet_size); - printf(" flags: 0x%08x\n", info.flags); - if (info.flags & EC_PROTOCOL_INFO_IN_PROGRESS_SUPPORTED) - printf(" EC_RES_IN_PROGRESS supported\n"); - return 0; -} - -static int ec_hash_help(const char *cmd) -{ - printf("Usage:\n"); - printf(" %s - get last hash\n", cmd); - printf(" %s abort - abort hashing\n", cmd); - printf(" %s start [<offset> <size> [<nonce>]] - start hashing\n", cmd); - printf(" %s recalc [<offset> <size> [<nonce>]] - sync rehash\n", cmd); - printf("\n" - "If <offset> is RO or RW, offset and size are computed\n" - "automatically for the EC-RO or EC-RW firmware image.\n"); - - return 0; -} - - -static int ec_hash_print(const struct ec_response_vboot_hash *r) -{ - int i; - - if (r->status == EC_VBOOT_HASH_STATUS_BUSY) { - printf("status: busy\n"); - return 0; - } else if (r->status == EC_VBOOT_HASH_STATUS_NONE) { - printf("status: unavailable\n"); - return 0; - } else if (r->status != EC_VBOOT_HASH_STATUS_DONE) { - printf("status: %d\n", r->status); - return 0; - } - - printf("status: done\n"); - if (r->hash_type == EC_VBOOT_HASH_TYPE_SHA256) - printf("type: SHA-256\n"); - else - printf("type: %d\n", r->hash_type); - - printf("offset: 0x%08x\n", r->offset); - printf("size: 0x%08x\n", r->size); - - printf("hash: "); - for (i = 0; i < r->digest_size; i++) - printf("%02x", r->hash_digest[i]); - printf("\n"); - return 0; -} - - -int cmd_ec_hash(int argc, char *argv[]) -{ - struct ec_params_vboot_hash p; - struct ec_response_vboot_hash r; - char *e; - int rv; - - memset(&p, 0, sizeof(p)); - if (argc < 2) { - /* Get hash status */ - p.cmd = EC_VBOOT_HASH_GET; - rv = ec_command(EC_CMD_VBOOT_HASH, 0, - &p, sizeof(p), &r, sizeof(r)); - if (rv < 0) - return rv; - - return ec_hash_print(&r); - } - - if (argc == 2 && !strcasecmp(argv[1], "abort")) { - /* Abort hash calculation */ - p.cmd = EC_VBOOT_HASH_ABORT; - rv = ec_command(EC_CMD_VBOOT_HASH, 0, - &p, sizeof(p), &r, sizeof(r)); - return (rv < 0 ? rv : 0); - } - - /* The only other commands are start and recalc */ - if (!strcasecmp(argv[1], "start")) - p.cmd = EC_VBOOT_HASH_START; - else if (!strcasecmp(argv[1], "recalc")) - p.cmd = EC_VBOOT_HASH_RECALC; - else - return ec_hash_help(argv[0]); - - p.hash_type = EC_VBOOT_HASH_TYPE_SHA256; - - if (argc < 3) { - fprintf(stderr, "Must specify offset\n"); - return -1; - } - - if (!strcasecmp(argv[2], "ro")) { - p.offset = EC_VBOOT_HASH_OFFSET_RO; - p.size = 0; - printf("Hashing EC-RO...\n"); - } else if (!strcasecmp(argv[2], "rw")) { - p.offset = EC_VBOOT_HASH_OFFSET_ACTIVE; - p.size = 0; - printf("Hashing EC-RW...\n"); - } else if (argc < 4) { - fprintf(stderr, "Must specify size\n"); - return -1; - } else { - p.offset = strtol(argv[2], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad offset.\n"); - return -1; - } - p.size = strtol(argv[3], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad size.\n"); - return -1; - } - printf("Hashing %d bytes at offset %d...\n", p.size, p.offset); - } - - if (argc == 5) { - /* - * Technically nonce can be any binary data up to 64 bytes, - * but this command only supports a 32-bit value. - */ - uint32_t nonce = strtol(argv[4], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad nonce integer.\n"); - return -1; - } - memcpy(p.nonce_data, &nonce, sizeof(nonce)); - p.nonce_size = sizeof(nonce); - } else - p.nonce_size = 0; - - rv = ec_command(EC_CMD_VBOOT_HASH, 0, &p, sizeof(p), &r, sizeof(r)); - if (rv < 0) - return rv; - - /* Start command doesn't wait for hashing to finish */ - if (p.cmd == EC_VBOOT_HASH_START) - return 0; - - /* Recalc command does wait around, so a result is ready now */ - return ec_hash_print(&r); -} - - -int cmd_rtc_get(int argc, char *argv[]) -{ - struct ec_response_rtc r; - int rv; - - rv = ec_command(EC_CMD_RTC_GET_VALUE, 0, NULL, 0, &r, sizeof(r)); - if (rv < 0) - return rv; - - printf("Current time: 0x%08x (%d)\n", r.time, r.time); - return 0; -} - - -int cmd_rtc_set(int argc, char *argv[]) -{ - struct ec_params_rtc p; - char *e; - int rv; - - if (argc != 2) { - fprintf(stderr, "Usage: %s <time>\n", argv[0]); - return -1; - } - p.time = strtol(argv[1], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad time.\n"); - return -1; - } - - rv = ec_command(EC_CMD_RTC_SET_VALUE, 0, &p, sizeof(p), NULL, 0); - if (rv < 0) - return rv; - - printf("Time set.\n"); - return 0; -} - -int cmd_rtc_set_alarm(int argc, char *argv[]) -{ - struct ec_params_rtc p; - char *e; - int rv; - - if (argc != 2) { - fprintf(stderr, "Usage: %s <sec>\n", argv[0]); - return -1; - } - p.time = strtol(argv[1], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad time.\n"); - return -1; - } - - rv = ec_command(EC_CMD_RTC_SET_ALARM, 0, &p, sizeof(p), NULL, 0); - if (rv < 0) - return rv; - - if (p.time == 0) - printf("Disabling alarm.\n"); - else - printf("Alarm set to go off in %d secs.\n", p.time); - return 0; -} - -int cmd_rtc_get_alarm(int argc, char *argv[]) -{ - struct ec_response_rtc r; - int rv; - - rv = ec_command(EC_CMD_RTC_GET_ALARM, 0, NULL, 0, &r, sizeof(r)); - if (rv < 0) - return rv; - - if (r.time == 0) - printf("Alarm not set\n"); - else - printf("Alarm to go off in %d secs\n", r.time); - return 0; -} - -int cmd_console(int argc, char *argv[]) -{ - char *out = (char *)ec_inbuf; - int rv; - - /* Snapshot the EC console */ - rv = ec_command(EC_CMD_CONSOLE_SNAPSHOT, 0, NULL, 0, NULL, 0); - if (rv < 0) - return rv; - - /* Loop and read from the snapshot until it's done */ - while (1) { - rv = ec_command(EC_CMD_CONSOLE_READ, 0, - NULL, 0, ec_inbuf, ec_max_insize); - if (rv < 0) - return rv; - - /* Empty response means done */ - if (!rv || !*out) - break; - - /* Make sure output is null-terminated, then dump it */ - out[ec_max_insize - 1] = '\0'; - fputs(out, stdout); - } - printf("\n"); - return 0; -} -struct param_info { - const char *name; /* name of this parameter */ - const char *help; /* help message */ - int size; /* size in bytes */ - int offset; /* offset within structure */ -}; - -#define FIELD(fname, field, help_str) \ - { \ - .name = fname, \ - .help = help_str, \ - .size = sizeof(((struct ec_mkbp_config *)NULL)->field), \ - .offset = __builtin_offsetof(struct ec_mkbp_config, field), \ - } - -static const struct param_info keyconfig_params[] = { - FIELD("scan_period", scan_period_us, "period between scans"), - FIELD("poll_timeout", poll_timeout_us, - "revert to irq mode after no activity for this long"), - FIELD("min_post_scan_delay", min_post_scan_delay_us, - "minimum post-scan delay before starting a new scan"), - FIELD("output_settle", output_settle_us, - "delay to wait for output to settle"), - FIELD("debounce_down", debounce_down_us, - "time for debounce on key down"), - FIELD("debounce_up", debounce_up_us, "time for debounce on key up"), - FIELD("fifo_max_depth", fifo_max_depth, - "maximum depth to allow for fifo (0 = disable)"), - FIELD("flags", flags, "0 to disable scanning, 1 to enable"), -}; - -static const struct param_info *find_field(const struct param_info *params, - int count, const char *name, unsigned int *nump) -{ - const struct param_info *param; - int i; - - for (i = 0, param = params; i < count; i++, param++) { - if (0 == strcmp(param->name, name)) { - if (nump) - *nump = i; - return param; - } - } - - fprintf(stderr, "Unknown parameter '%s'\n", name); - return NULL; -} - -static int get_value(const struct param_info *param, const char *config) -{ - const char *field; - - field = config + param->offset; - switch (param->size) { - case 1: - return *(uint8_t *)field; - case 2: - return *(uint16_t *)field; - case 4: - return *(uint32_t *)field; - default: - fprintf(stderr, "Internal error: unknown size %d\n", - param->size); - } - - return -1; -} - -static int show_fields(struct ec_mkbp_config *config, int argc, char *argv[]) -{ - const struct param_info *param; - uint32_t mask; - int i; - - if (!argc) { - mask = -1U; /* show all fields */ - } else { - mask = 0; - while (argc > 0) { - unsigned int num; - - param = find_field(keyconfig_params, - ARRAY_SIZE(keyconfig_params), - argv[0], &num); - if (!param) - return -1; - mask |= 1 << num; - argc--; - argv++; - } - } - - param = keyconfig_params; - for (i = 0; i < ARRAY_SIZE(keyconfig_params); i++, param++) { - if (mask & BIT(i)) { - fprintf(stderr, "%-12s %u\n", param->name, - get_value(param, (char *)config)); - } - } - - return 0; -} - -static int cmd_kbinfo(int argc, char *argv[]) -{ - struct ec_params_mkbp_info info = { - .info_type = EC_MKBP_INFO_KBD, - }; - struct ec_response_mkbp_info resp; - int rv; - - if (argc > 1) { - fprintf(stderr, "Too many args\n"); - return -1; - } - rv = ec_command(EC_CMD_MKBP_INFO, 0, &info, sizeof(info), &resp, - sizeof(resp)); - if (rv < 0) - return rv; - - printf("Matrix rows: %d\n", resp.rows); - printf("Matrix columns: %d\n", resp.cols); - - return 0; -} - -static int cmd_kbid(int argc, char *argv[]) -{ - struct ec_response_keyboard_id response; - int rv; - - if (argc > 1) { - fprintf(stderr, "Too many args\n"); - return -1; - } - - rv = ec_command(EC_CMD_GET_KEYBOARD_ID, 0, NULL, 0, &response, - sizeof(response)); - if (rv < 0) - return rv; - switch (response.keyboard_id) { - case KEYBOARD_ID_UNSUPPORTED: - /* Keyboard ID was not supported */ - printf("Keyboard doesn't support ID\n"); - break; - case KEYBOARD_ID_UNREADABLE: - /* Ghosting ID was detected */ - printf("Reboot and keep hands off the keyboard during" - " next boot-up\n"); - break; - default: - /* Valid keyboard ID value was reported*/ - printf("%x\n", response.keyboard_id); - } - return rv; -} - -static int cmd_keyconfig(int argc, char *argv[]) -{ - struct ec_params_mkbp_set_config req; - int cmd; - int rv; - - if (argc < 2) { - const struct param_info *param; - int i; - - fprintf(stderr, "Usage: %s get [<param>] - print params\n" - "\t%s set [<param>> <value>]\n" - " Available params are: (all time values are in us)", - argv[0], argv[0]); - - param = keyconfig_params; - for (i = 0; i < ARRAY_SIZE(keyconfig_params); i++, param++) { - fprintf(stderr, "%-12s %s\n", param->name, - param->name); - } - return -1; - } - - /* Get the command */ - if (0 == strcmp(argv[1], "get")) { - cmd = EC_CMD_MKBP_GET_CONFIG; - } else if (0 == strcmp(argv[1], "set")) { - cmd = EC_CMD_MKBP_SET_CONFIG; - } else { - fprintf(stderr, "Invalid command '%s\n", argv[1]); - return -1; - } - - switch (cmd) { - case EC_CMD_MKBP_GET_CONFIG: - /* Read the existing config */ - rv = ec_command(cmd, 0, NULL, 0, &req, sizeof(req)); - if (rv < 0) - return rv; - show_fields(&req.config, argc - 2, argv + 2); - break; - } - - return 0; -} - -static const char * const mkbp_button_strings[] = { - [EC_MKBP_POWER_BUTTON] = "Power", - [EC_MKBP_VOL_UP] = "Volume up", - [EC_MKBP_VOL_DOWN] = "Volume down", - [EC_MKBP_RECOVERY] = "Recovery", -}; - -static const char * const mkbp_switch_strings[] = { - [EC_MKBP_LID_OPEN] = "Lid open", - [EC_MKBP_TABLET_MODE] = "Tablet mode", - [EC_MKBP_BASE_ATTACHED] = "Base attached", -}; - -static int cmd_mkbp_get(int argc, char *argv[]) -{ - struct ec_params_mkbp_info p; - union ec_response_get_next_data r; - int rv; - int i; - uint32_t supported; - - if (argc < 2) { - fprintf(stderr, "Usage: %s <buttons|switches>\n", argv[0]); - return -1; - } - - if (strncmp(argv[1], "button", 6) == 0) { - p.event_type = EC_MKBP_EVENT_BUTTON; - } else if (strncmp(argv[1], "switch", 6) == 0) { - p.event_type = EC_MKBP_EVENT_SWITCH; - } else { - fprintf(stderr, "Invalid param: '%s'\n", argv[1]); - return -1; - } - - p.info_type = EC_MKBP_INFO_SUPPORTED; - rv = ec_command(EC_CMD_MKBP_INFO, 0, &p, sizeof(p), &r, - sizeof(r)); - if (rv < 0) - return rv; - if (p.event_type == EC_MKBP_EVENT_BUTTON) - supported = r.buttons; - else if (p.event_type == EC_MKBP_EVENT_SWITCH) - supported = r.switches; - else - return -1; - - p.info_type = EC_MKBP_INFO_CURRENT; - rv = ec_command(EC_CMD_MKBP_INFO, 0, &p, sizeof(p), &r, - sizeof(r)); - if (rv < 0) - return rv; - - if (p.event_type == EC_MKBP_EVENT_BUTTON) { - printf("MKBP buttons state: 0x%04x (supported: 0x%04x)\n", - r.buttons, supported); - for (i = 0; i < ARRAY_SIZE(mkbp_button_strings); i++) { - if (supported & BIT(i) && mkbp_button_strings[i]) { - printf("%s: %s\n", mkbp_button_strings[i], - r.buttons & BIT(i) ? "ON" : "OFF"); - supported &= ~BIT(i); - } - } - if (supported) - printf("Unknown buttons: 0x%04x\n", supported); - } else if (p.event_type == EC_MKBP_EVENT_SWITCH) { - printf("MKBP switches state: 0x%04x (supported: 0x%04x)\n", - r.switches, supported); - for (i = 0; i < ARRAY_SIZE(mkbp_switch_strings); i++) { - if (supported & BIT(i) && mkbp_switch_strings[i]) { - printf("%s: %s\n", mkbp_switch_strings[i], - r.switches & BIT(i) ? "ON" : "OFF"); - supported &= ~BIT(i); - } - } - if (supported) - printf("Unknown switches: 0x%04x\n", supported); - } - - return 0; -} - -static int cmd_mkbp_wake_mask(int argc, char *argv[]) -{ - struct ec_params_mkbp_event_wake_mask p; - struct ec_response_mkbp_event_wake_mask r; - int rv; - - if (argc < 3) { - fprintf(stderr, "Usage: %s get <event|hostevent>\n" - "\t%s set <event|hostevent> <mask>\n", argv[0], - argv[0]); - return -1; - } - - /* Determine if the user want to get or set the wake mask. */ - if (strncmp(argv[1], "get", 3) == 0) { - p.action = GET_WAKE_MASK; - } else if (strncmp(argv[1], "set", 3) == 0) { - p.action = SET_WAKE_MASK; - } else { - fprintf(stderr, "Invalid param: '%s'\n", argv[1]); - return -1; - } - - /* Determine which mask is of interest. */ - if (strncmp(argv[2], "event", 5) == 0) { - p.mask_type = EC_MKBP_EVENT_WAKE_MASK; - } else if (strncmp(argv[2], "hostevent", 9) == 0) { - p.mask_type = EC_MKBP_HOST_EVENT_WAKE_MASK; - } else { - fprintf(stderr, "Invalid param: '%s'\n", argv[2]); - return -1; - } - - if (p.action == SET_WAKE_MASK) { - char *e; - - if (argc < 4) { - fprintf(stderr, "Missing mask value!"); - return -1; - } - - p.new_wake_mask = strtol(argv[3], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad mask: '%s'", argv[1]); - return -1; - } - } - - rv = ec_command(EC_CMD_MKBP_WAKE_MASK, 0, &p, sizeof(p), &r, - sizeof(r)); - if (rv < 0) { - if (rv == -EECRESULT-EC_RES_INVALID_PARAM) { - fprintf(stderr, "Unknown mask, or mask is not in use. " - "You may need to enable the " - "CONFIG_MKBP_%s_WAKEUP_MASK option in the EC.\n" - , p.mask_type == EC_MKBP_EVENT_WAKE_MASK ? - "EVENT" : "HOSTEVENT"); - } - return rv; - } - - if (p.action == GET_WAKE_MASK) - printf("MBKP %s wake mask: 0x%08x\n", argv[2], r.wake_mask); - else if (p.action == SET_WAKE_MASK) - printf("MKBP %s wake mask set.\n", argv[2]); - - return 0; -} - -/* Index is already checked. argv[0] is first param value */ -static int cmd_tmp006cal_v0(int idx, int argc, char *argv[]) -{ - struct ec_params_tmp006_get_calibration pg; - struct ec_response_tmp006_get_calibration_v0 rg; - struct ec_params_tmp006_set_calibration_v0 ps; - float val; - char *e; - int i, rv; - - /* Get current values */ - pg.index = idx; - rv = ec_command(EC_CMD_TMP006_GET_CALIBRATION, 0, - &pg, sizeof(pg), &rg, sizeof(rg)); - if (rv < 0) - return rv; - - if (!argc) { - /* If no new values are given, just print what we have */ - printf("S0: %e\n", rg.s0); - printf("b0: %e\n", rg.b0); - printf("b1: %e\n", rg.b1); - printf("b2: %e\n", rg.b2); - return EC_SUCCESS; - } - - /* Prepare to reuse the current values */ - memset(&ps, 0, sizeof(ps)); - ps.index = idx; - ps.s0 = rg.s0; - ps.b0 = rg.b0; - ps.b1 = rg.b1; - ps.b2 = rg.b2; - - /* Parse up to four args, skipping any that are just "-" */ - for (i = 0; i < argc && i < 4; i++) { - if (!strcmp(argv[i], "-")) - continue; - val = strtod(argv[i], &e); - if (e && *e) { - fprintf(stderr, - "Bad arg \"%s\". Use \"-\" to skip a param.\n", - argv[i]); - return -1; - } - switch (i) { - case 0: - ps.s0 = val; - break; - case 1: - ps.b0 = val; - break; - case 2: - ps.b1 = val; - break; - case 3: - ps.b2 = val; - break; - } - } - - /* Set 'em */ - return ec_command(EC_CMD_TMP006_SET_CALIBRATION, 0, - &ps, sizeof(ps), NULL, 0); -} - -/* Index is already checked. argv[0] is first param value */ -static int cmd_tmp006cal_v1(int idx, int argc, char *argv[]) -{ - struct ec_params_tmp006_get_calibration pg; - struct ec_response_tmp006_get_calibration_v1 *rg = - (struct ec_response_tmp006_get_calibration_v1 *)(ec_inbuf); - struct ec_params_tmp006_set_calibration_v1 *ps = - (struct ec_params_tmp006_set_calibration_v1 *)(ec_outbuf); - float val; - char *e; - int i, rv, cmdsize; - - /* Algorithm 1 parameter names */ - static const char * const alg1_pname[] = { - "s0", "a1", "a2", "b0", "b1", "b2", "c2", - "d0", "d1", "ds", "e0", "e1", - }; - - /* Get current values */ - pg.index = idx; - rv = ec_command(EC_CMD_TMP006_GET_CALIBRATION, 1, - &pg, sizeof(pg), rg, ec_max_insize); - if (rv < 0) - return rv; - - if (!argc) { - /* If no new values are given, just print what we have */ - printf("algorithm: %d\n", rg->algorithm); - printf("params:\n"); - /* We only know about alg 1 at the moment */ - if (rg->algorithm == 1) - for (i = 0; i < rg->num_params; i++) - printf(" %s %e\n", alg1_pname[i], rg->val[i]); - else - for (i = 0; i < rg->num_params; i++) - printf(" param%d %e\n", i, rg->val[i]); - return EC_SUCCESS; - } - - /* Prepare to reuse the current values */ - memset(ps, 0, ec_max_outsize); - ps->index = idx; - ps->algorithm = rg->algorithm; - ps->num_params = rg->num_params; - for (i = 0; i < rg->num_params; i++) - ps->val[i] = rg->val[i]; - - /* Parse the args, skipping any that are just "-" */ - for (i = 0; i < argc && i < rg->num_params; i++) { - if (!strcmp(argv[i], "-")) - continue; - val = strtod(argv[i], &e); - if (e && *e) { - fprintf(stderr, - "Bad arg \"%s\". Use \"-\" to skip a param.\n", - argv[i]); - return -1; - } - ps->val[i] = val; - } - - /* Set 'em */ - cmdsize = sizeof(*ps) + ps->num_params * sizeof(ps->val[0]); - return ec_command(EC_CMD_TMP006_SET_CALIBRATION, 1, - ps, cmdsize, NULL, 0); -} - -int cmd_tmp006cal(int argc, char *argv[]) -{ - char *e; - int idx; - - if (argc < 2) { - fprintf(stderr, "Must specify tmp006 index.\n"); - return -1; - } - - idx = strtol(argv[1], &e, 0); - if ((e && *e) || idx < 0 || idx > 255) { - fprintf(stderr, "Bad index.\n"); - return -1; - } - - /* Pass just the params (if any) to the helper function */ - argc -= 2; - argv += 2; - - if (ec_cmd_version_supported(EC_CMD_TMP006_GET_CALIBRATION, 1)) - return cmd_tmp006cal_v1(idx, argc, argv); - - if (ec_cmd_version_supported(EC_CMD_TMP006_GET_CALIBRATION, 0)) - return cmd_tmp006cal_v0(idx, argc, argv); - - printf("The EC is being stupid\n"); - return -1; -} - -int cmd_tmp006raw(int argc, char *argv[]) -{ - struct ec_params_tmp006_get_raw p; - struct ec_response_tmp006_get_raw r; - char *e; - int idx; - int rv; - - if (argc != 2) { - fprintf(stderr, "Must specify tmp006 index.\n"); - return -1; - } - - idx = strtol(argv[1], &e, 0); - if ((e && *e) || idx < 0 || idx > 255) { - fprintf(stderr, "Bad index.\n"); - return -1; - } - - p.index = idx; - - rv = ec_command(EC_CMD_TMP006_GET_RAW, 0, &p, sizeof(p), &r, sizeof(r)); - if (rv < 0) - return rv; - - printf("T: %d.%02d K\n", r.t / 100, r.t % 100); - printf("V: %d nV\n", r.v); - return EC_SUCCESS; -} - -static int cmd_hang_detect(int argc, char *argv[]) -{ - struct ec_params_hang_detect req; - char *e; - - memset(&req, 0, sizeof(req)); - - if (argc == 2 && !strcasecmp(argv[1], "stop")) { - req.flags = EC_HANG_STOP_NOW; - return ec_command(EC_CMD_HANG_DETECT, 0, &req, sizeof(req), - NULL, 0); - } - - if (argc == 2 && !strcasecmp(argv[1], "start")) { - req.flags = EC_HANG_START_NOW; - return ec_command(EC_CMD_HANG_DETECT, 0, &req, sizeof(req), - NULL, 0); - } - - if (argc == 4) { - req.flags = strtol(argv[1], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad flags.\n"); - return -1; - } - - req.host_event_timeout_msec = strtol(argv[2], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad event timeout.\n"); - return -1; - } - - req.warm_reboot_timeout_msec = strtol(argv[3], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad reboot timeout.\n"); - return -1; - } - - printf("hang flags=0x%x\n" - "event_timeout=%d ms\n" - "reboot_timeout=%d ms\n", - req.flags, req.host_event_timeout_msec, - req.warm_reboot_timeout_msec); - - return ec_command(EC_CMD_HANG_DETECT, 0, &req, sizeof(req), - NULL, 0); - } - - fprintf(stderr, - "Must specify start/stop or <flags> <event_ms> <reboot_ms>\n"); - return -1; -} - -enum port_80_event { - PORT_80_EVENT_RESUME = 0x1001, /* S3->S0 transition */ - PORT_80_EVENT_RESET = 0x1002, /* RESET transition */ -}; - -int cmd_port80_read(int argc, char *argv[]) -{ - struct ec_params_port80_read p; - int cmdver = 1, rv; - int i, head, tail; - uint16_t *history; - uint32_t writes, history_size; - struct ec_response_port80_read rsp; - int printed = 0; - - if (!ec_cmd_version_supported(EC_CMD_PORT80_READ, cmdver)) { - /* fall back to last boot */ - struct ec_response_port80_last_boot r; - rv = ec_command(EC_CMD_PORT80_LAST_BOOT, 0, - NULL, 0, &r, sizeof(r)); - fprintf(stderr, "Last boot %2x\n", r.code); - printf("done.\n"); - return 0; - } - - - /* read writes and history_size */ - p.subcmd = EC_PORT80_GET_INFO; - rv = ec_command(EC_CMD_PORT80_READ, cmdver, - &p, sizeof(p), &rsp, sizeof(rsp)); - if (rv < 0) { - fprintf(stderr, "Read error at writes\n"); - return rv; - } - writes = rsp.get_info.writes; - history_size = rsp.get_info.history_size; - - history = (uint16_t *)( - malloc(history_size * sizeof(uint16_t))); - if (!history) { - fprintf(stderr, "Unable to allocate buffer.\n"); - return -1; - } - /* As the history buffer is quite large, we read data in chunks, with - size in bytes of EC_PORT80_SIZE_MAX in each chunk. - Incrementing offset until all history buffer has been read. To - simplify the design, chose HISTORY_LEN is always multiple of - EC_PORT80_SIZE_MAX. - - offset: entry offset from the beginning of history buffer. - num_entries: number of entries requested. - */ - p.subcmd = EC_PORT80_READ_BUFFER; - for (i = 0; i < history_size; i += EC_PORT80_SIZE_MAX) { - p.read_buffer.offset = i; - p.read_buffer.num_entries = EC_PORT80_SIZE_MAX; - rv = ec_command(EC_CMD_PORT80_READ, cmdver, - &p, sizeof(p), &rsp, sizeof(rsp)); - if (rv < 0) { - fprintf(stderr, "Read error at offset %d\n", i); - free(history); - return rv; - } - memcpy((void *)(history + i), rsp.data.codes, - EC_PORT80_SIZE_MAX*sizeof(uint16_t)); - } - - head = writes; - if (head > history_size) - tail = head - history_size; - else - tail = 0; - - fprintf(stderr, "Port 80 writes"); - for (i = tail; i < head; i++) { - int e = history[i % history_size]; - switch (e) { - case PORT_80_EVENT_RESUME: - fprintf(stderr, "\n(S3->S0)"); - printed = 0; - break; - case PORT_80_EVENT_RESET: - fprintf(stderr, "\n(RESET)"); - printed = 0; - break; - default: - if (!(printed++ % 20)) - fprintf(stderr, "\n "); - fprintf(stderr, " %02x", e); - } - } - fprintf(stderr, " <--new\n"); - - free(history); - printf("done.\n"); - return 0; -} - -int cmd_force_lid_open(int argc, char *argv[]) -{ - struct ec_params_force_lid_open p; - char *e; - int rv; - - if (argc != 2) { - fprintf(stderr, "Usage: %s <0|1>\n", argv[0]); - return -1; - } - p.enabled = strtol(argv[1], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad value.\n"); - return -1; - } - - rv = ec_command(EC_CMD_FORCE_LID_OPEN, 0, &p, sizeof(p), NULL, 0); - if (rv < 0) - return rv; - printf("Success.\n"); - return 0; -} - -int cmd_charge_port_override(int argc, char *argv[]) -{ - struct ec_params_charge_port_override p; - char *e; - int rv; - - if (argc < 2) { - fprintf(stderr, "Usage: %s <port# | dontcharge | off>\n", - argv[0]); - return -1; - } - - if (!strcasecmp(argv[1], "dontcharge")) - p.override_port = OVERRIDE_DONT_CHARGE; - else if (!strcasecmp(argv[1], "off")) - p.override_port = OVERRIDE_OFF; - else { - p.override_port = strtol(argv[1], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad parameter.\n"); - return -1; - } - } - - rv = ec_command(EC_CMD_PD_CHARGE_PORT_OVERRIDE, 0, &p, sizeof(p), - NULL, 0); - if (rv < 0) - return rv; - - printf("Override port set to %d\n", p.override_port); - return 0; -} - -static void cmd_pchg_help(char *cmd) -{ - fprintf(stderr, - " Usage1: %s\n" - " Print the number of ports.\n" - "\n" - " Usage2: %s <port>\n" - " Print the status of <port>.\n" - "\n" - " Usage3: %s <port> reset\n" - " Reset <port>.\n" - "\n" - " Usage4: %s <port> update <version> <addr1> <file1> <addr2> <file2> ...\n" - " Update firmware of <port>.\n", - cmd, cmd, cmd, cmd); -} - -static int cmd_pchg_info(const struct ec_response_pchg *res) -{ - static const char * const pchg_state_text[] = EC_PCHG_STATE_TEXT; - - BUILD_ASSERT(ARRAY_SIZE(pchg_state_text) == PCHG_STATE_COUNT); - - printf("State: %s (%d)\n", res->state < PCHG_STATE_COUNT - ? pchg_state_text[res->state] : "UNDEF", res->state); - printf("Battery: %u%%\n", res->battery_percentage); - printf("Errors: 0x%x\n", res->error); - printf("FW Version: 0x%x\n", res->fw_version); - printf("Dropped events: %u\n", res->dropped_event_count); - return 0; -} - -static int cmd_pchg_wait_event(int port, uint32_t expected) -{ - struct ec_response_get_next_event_v1 event; - const long timeout = 5000; - uint32_t *e = &event.data.host_event; - int rv; - - rv = wait_event(EC_MKBP_EVENT_PCHG, &event, sizeof(event), timeout); - if (rv < 0) - return rv; - - if (EC_MKBP_PCHG_EVENT_TO_PORT(*e) == port) { - if (*e & EC_MKBP_PCHG_UPDATE_ERROR) { - fprintf(stderr, "\nReceived update error\n"); - return -1; - } - if (*e & expected) - return 0; - } - - fprintf(stderr, "\nExpected event=0x%x but received 0x%x\n", - expected, *e); - return -1; -} - -static int cmd_pchg_update_open(int port, uint32_t version, - uint32_t *block_size, uint32_t *crc) -{ - struct ec_params_pchg_update *p = - (struct ec_params_pchg_update *)(ec_outbuf); - struct ec_response_pchg_update *r = - (struct ec_response_pchg_update *)(ec_inbuf); - int rv; - - /* Open session. */ - p->port = port; - p->cmd = EC_PCHG_UPDATE_CMD_OPEN; - p->version = version; - rv = ec_command(EC_CMD_PCHG_UPDATE, 0, p, sizeof(*p), r, sizeof(*r)); - if (rv < 0) { - fprintf(stderr, "\nFailed to open update session: %d\n", rv); - return rv; - } - - if (r->block_size + sizeof(*p) > ec_max_outsize) { - fprintf(stderr, "\nBlock size (%d) is too large.\n", - r->block_size); - return -1; - } - - rv = cmd_pchg_wait_event(port, EC_MKBP_PCHG_UPDATE_OPENED); - if (rv) - return rv; - - printf("Opened update session (port=%d ver=0x%x bsize=%d):\n", - port, version, r->block_size); - - *block_size = r->block_size; - crc32_ctx_init(crc); - - return 0; -} - -static int cmd_pchg_update_write(int port, uint32_t address, - const char *filename, uint32_t block_size, - uint32_t *crc) -{ - struct ec_params_pchg_update *p = - (struct ec_params_pchg_update *)(ec_outbuf); - FILE *fp; - size_t len, total; - int progress = 0; - int rv; - - fp = fopen(filename, "rb"); - if (!fp) { - fprintf(stderr, "\nCan't open %s: %s\n", - filename, strerror(errno)); - return -1; - } - - fseek(fp, 0L, SEEK_END); - total = ftell(fp); - rewind(fp); - printf("Writing %s (%zu bytes).\n", filename, total); - - p->cmd = EC_PCHG_UPDATE_CMD_WRITE; - p->addr = address; - - /* Write firmware in blocks. */ - len = fread(p->data, 1, block_size, fp); - while (len > 0) { - int previous_progress = progress; - int i; - - crc32_ctx_hash(crc, p->data, len); - p->size = len; - rv = ec_command(EC_CMD_PCHG_UPDATE, 0, p, - sizeof(*p) + len, NULL, 0); - if (rv < 0) { - fprintf(stderr, "\nFailed to write FW: %d\n", rv); - fclose(fp); - return rv; - } - - rv = cmd_pchg_wait_event(port, EC_MKBP_PCHG_WRITE_COMPLETE); - if (rv) - return rv; - - p->addr += len; - progress = (p->addr - address) * 100 / total; - for (i = 0; i < progress - previous_progress; i++) { - printf("*"); - fflush(stdout); - } - - len = fread(p->data, 1, block_size, fp); - } - - printf("\n"); - fclose(fp); - - return 0; -} - -static int cmd_pchg_update_close(int port, uint32_t *crc) -{ - struct ec_params_pchg_update *p = - (struct ec_params_pchg_update *)(ec_outbuf); - int rv; - - p->cmd = EC_PCHG_UPDATE_CMD_CLOSE; - p->crc32 = crc32_ctx_result(crc); - rv = ec_command(EC_CMD_PCHG_UPDATE, 0, p, sizeof(*p), NULL, 0); - - if (rv < 0) { - fprintf(stderr, "\nFailed to close update session: %d\n", rv); - return rv; - } - - rv = cmd_pchg_wait_event(port, EC_MKBP_PCHG_UPDATE_CLOSED); - if (rv) - return rv; - - printf("Firmware was updated successfully (CRC32=0x%x).\n", p->crc32); - - return 0; -} - -static int cmd_pchg(int argc, char *argv[]) -{ - const size_t max_input_files = 8; - int port, port_count; - struct ec_response_pchg_count rcnt; - struct ec_params_pchg p; - struct ec_response_pchg r; - char *e; - int rv; - - rv = ec_command(EC_CMD_PCHG_COUNT, 0, NULL, 0, &rcnt, sizeof(rcnt)); - if (rv < 0) { - fprintf(stderr, "\nFailed to get port count: %d\n", rv); - return rv; - } - port_count = rcnt.port_count; - - if (argc == 1) { - /* Usage.1 */ - printf("%d\n", port_count); - return 0; - } - - port = strtol(argv[1], &e, 0); - if ((e && *e) || port >= port_count) { - fprintf(stderr, "\nBad port index: %s\n", argv[1]); - cmd_pchg_help(argv[0]); - return -1; - } - - p.port = port; - rv = ec_command(EC_CMD_PCHG, 1, &p, sizeof(p), &r, sizeof(r)); - if (rv < 0) { - fprintf(stderr, "\nError code: %d\n", rv); - return rv; - } - - if (argc == 2) { - /* Usage.2 */ - return cmd_pchg_info(&r); - } else if (argc == 3 && !strcmp(argv[2], "reset")) { - /* Usage.3 */ - struct ec_params_pchg_update *u = - (struct ec_params_pchg_update *)(ec_outbuf); - - u->cmd = EC_PCHG_UPDATE_CMD_RESET_TO_NORMAL; - rv = ec_command(EC_CMD_PCHG_UPDATE, 0, u, sizeof(*u), NULL, 0); - if (rv < 0) { - fprintf(stderr, "\nFailed to reset port %d: %d\n", - port, rv); - cmd_pchg_help(argv[0]); - return rv; - } - printf("Reset port %d complete.\n", port); - return 0; - } else if (argc >= 6 && !strcmp(argv[2], "update")) { - /* - * Usage.4: - * argv[3]: <version> - * argv[4]: <addr1> - * argv[5]: <file1> - * argv[6]: <addr2> - * argv[7]: <file2> - * ... - */ - uint32_t address, version; - uint32_t block_size = 0; - uint32_t crc; - int i; - - if (argc > 4 + max_input_files * 2) { - fprintf(stderr, "\nToo many input files.\n"); - return -1; - } - - version = strtol(argv[3], &e, 0); - if (e && *e) { - fprintf(stderr, "\nBad version: %s.\n", argv[3]); - cmd_pchg_help(argv[0]); - return -1; - } - - rv = cmd_pchg_update_open(port, version, &block_size, &crc); - if (rv < 0 || block_size == 0) { - fprintf(stderr, "\nFailed to open update session: %d\n", - rv); - return -1; - } - - /* Write files one by one. */ - for (i = 4; i + 1 < argc; i += 2) { - address = strtol(argv[i], &e, 0); - if (e && *e) { - fprintf(stderr, "\nBad address: %s\n", argv[i]); - cmd_pchg_help(argv[0]); - return -1; - } - rv = cmd_pchg_update_write(port, address, argv[i+1], - block_size, &crc); - if (rv < 0) { - fprintf(stderr, - "\nFailed to write file '%s': %d", - argv[i+i], rv); - return -1; - } - } - - rv = cmd_pchg_update_close(port, &crc); - if (rv < 0) { - fprintf(stderr, "\nFailed to close update session: %d", - rv); - return -1; - } - - return 0; - } - - fprintf(stderr, "Invalid parameter\n\n"); - cmd_pchg_help(argv[0]); - - return -1; -} - -int cmd_pd_log(int argc, char *argv[]) -{ - union { - struct ec_response_pd_log r; - uint32_t words[8]; /* space for the payload */ - } u; - struct mcdp_info minfo; - struct ec_response_usb_pd_power_info pinfo; - int rv; - unsigned long long milliseconds; - unsigned seconds; - time_t now; - struct tm ltime; - char time_str[64]; - - while (1) { - now = time(NULL); - rv = ec_command(EC_CMD_PD_GET_LOG_ENTRY, 0, - NULL, 0, &u, sizeof(u)); - if (rv < 0) - return rv; - - if (u.r.type == PD_EVENT_NO_ENTRY) { - printf("--- END OF LOG ---\n"); - break; - } - - /* the timestamp is in 1024th of seconds */ - milliseconds = ((uint64_t)u.r.timestamp << - PD_LOG_TIMESTAMP_SHIFT) / 1000; - /* the timestamp is the number of milliseconds in the past */ - seconds = (milliseconds + 999) / 1000; - milliseconds -= seconds * 1000; - now -= seconds; - localtime_r(&now, <ime); - strftime(time_str, sizeof(time_str), "%F %T", <ime); - printf("%s.%03lld P%d ", time_str, -milliseconds, - PD_LOG_PORT(u.r.size_port)); - if (u.r.type == PD_EVENT_MCU_CHARGE) { - if (u.r.data & CHARGE_FLAGS_OVERRIDE) - printf("override "); - if (u.r.data & CHARGE_FLAGS_DELAYED_OVERRIDE) - printf("pending_override "); - memcpy(&pinfo.meas, u.r.payload, - sizeof(struct usb_chg_measures)); - pinfo.dualrole = !!(u.r.data & CHARGE_FLAGS_DUAL_ROLE); - pinfo.role = u.r.data & CHARGE_FLAGS_ROLE_MASK; - pinfo.type = (u.r.data & CHARGE_FLAGS_TYPE_MASK) - >> CHARGE_FLAGS_TYPE_SHIFT; - pinfo.max_power = 0; - print_pd_power_info(&pinfo); - } else if (u.r.type == PD_EVENT_MCU_CONNECT) { - printf("New connection\n"); - } else if (u.r.type == PD_EVENT_MCU_BOARD_CUSTOM) { - printf("Board-custom event\n"); - } else if (u.r.type == PD_EVENT_ACC_RW_FAIL) { - printf("RW signature check failed\n"); - } else if (u.r.type == PD_EVENT_PS_FAULT) { - static const char * const fault_names[] = { - "---", "OCP", "fast OCP", "OVP", "Discharge" - }; - const char *fault = u.r.data < ARRAY_SIZE(fault_names) ? - fault_names[u.r.data] : "???"; - printf("Power supply fault: %s\n", fault); - } else if (u.r.type == PD_EVENT_VIDEO_DP_MODE) { - printf("DP mode %sabled\n", (u.r.data == 1) ? - "en" : "dis"); - } else if (u.r.type == PD_EVENT_VIDEO_CODEC) { - memcpy(&minfo, u.r.payload, - sizeof(struct mcdp_info)); - printf("HDMI info: family:%04x chipid:%04x " - "irom:%d.%d.%d fw:%d.%d.%d\n", - MCDP_FAMILY(minfo.family), - MCDP_CHIPID(minfo.chipid), - minfo.irom.major, minfo.irom.minor, - minfo.irom.build, minfo.fw.major, - minfo.fw.minor, minfo.fw.build); - } else { /* Unknown type */ - int i; - printf("Event %02x (%04x) [", u.r.type, u.r.data); - for (i = 0; i < PD_LOG_SIZE(u.r.size_port); i++) - printf("%02x ", u.r.payload[i]); - printf("]\n"); - } - } - - return 0; -} - -int cmd_pd_control(int argc, char *argv[]) -{ - struct ec_params_pd_control p; - int rv; - - if (argc < 2) { - fprintf(stderr, "Missing parameter\n"); - return -1; - } - - /* Parse command */ - if (!strcmp(argv[1], "reset")) - p.subcmd = PD_RESET; - else if (!strcmp(argv[1], "suspend")) - p.subcmd = PD_SUSPEND; - else if (!strcmp(argv[1], "resume")) - p.subcmd = PD_RESUME; - else if (!strcmp(argv[1], "disable")) - p.subcmd = PD_CONTROL_DISABLE; - else if (!strcmp(argv[1], "on") || !strcmp(argv[1], "chip_on")) - p.subcmd = PD_CHIP_ON; - else { - fprintf(stderr, "Unknown command: %s\n", argv[1]); - return -1; - } - - if (argc == 2) { - p.chip = 0; - } else { - char *e; - p.chip = strtol(argv[2], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad port number '%s'.\n", argv[2]); - return -1; - } - } - - rv = ec_command(EC_CMD_PD_CONTROL, 0, &p, sizeof(p), NULL, 0); - return (rv < 0 ? rv : 0); -} - -int cmd_pd_chip_info(int argc, char *argv[]) -{ - struct ec_params_pd_chip_info p; - struct ec_response_pd_chip_info_v1 r; - char *e; - int rv; - int cmdver = 1; - - if (argc < 2 || 3 < argc) { - fprintf(stderr, "Usage: %s <port> [<live>]\n" - "live parameter can take values 0 or 1\n" - "0 -> Return hard-coded value for VID/PID and\n" - " cached value for Firmware Version\n" - "1 -> Return live chip value for VID/PID/FW Version\n", - argv[0]); - return -1; - } - - p.port = strtol(argv[1], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad port number.\n"); - return -1; - } - - p.live = 0; - if (argc == 3) { - p.live = strtol(argv[2], &e, 0); - if (e && *e) { - fprintf(stderr, "invalid arg \"%s\"\n", argv[2]); - return -1; - } - } - - if (!ec_cmd_version_supported(EC_CMD_PD_CHIP_INFO, cmdver)) - cmdver = 0; - - rv = ec_command(EC_CMD_PD_CHIP_INFO, cmdver, &p, sizeof(p), &r, - sizeof(r)); - if (rv < 0) - return rv; - - printf("vendor_id: 0x%x\n", r.vendor_id); - printf("product_id: 0x%x\n", r.product_id); - printf("device_id: 0x%x\n", r.device_id); - - if (r.fw_version_number != -1) - printf("fw_version: 0x%" PRIx64 "\n", r.fw_version_number); - else - printf("fw_version: UNSUPPORTED\n"); - - if (cmdver >= 1) - printf("min_req_fw_version: 0x%" PRIx64 "\n", - r.min_req_fw_version_number); - else - printf("min_req_fw_version: UNSUPPORTED\n"); - - return 0; -} - -int cmd_pd_write_log(int argc, char *argv[]) -{ - struct ec_params_pd_write_log_entry p; - char *e; - - if (argc < 3) { - fprintf(stderr, "Usage: %s <log_type> <port>\n", - argv[0]); - return -1; - } - - if (!strcasecmp(argv[1], "charge")) - p.type = PD_EVENT_MCU_CHARGE; - else { - p.type = strtol(argv[1], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad log_type parameter.\n"); - return -1; - } - } - - p.port = strtol(argv[2], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad port parameter.\n"); - return -1; - } - - return ec_command(EC_CMD_PD_WRITE_LOG_ENTRY, 0, &p, sizeof(p), NULL, 0); -} - -int cmd_typec_control(int argc, char *argv[]) -{ - struct ec_params_typec_control p; - long conversion_result; - char *endptr; - int rv; - - if (argc < 3) { - fprintf(stderr, - "Usage: %s <port> <command> [args]\n" - " <port> is the type-c port to query\n" - " <command> is one of:\n" - " 0: Exit modes\n" - " 1: Clear events\n" - " args: <event mask>\n" - " 2: Enter mode\n" - " args: <0: DP, 1:TBT, 2:USB4>\n", - argv[0]); - return -1; - } - - p.port = strtol(argv[1], &endptr, 0); - if (endptr && *endptr) { - fprintf(stderr, "Bad port\n"); - return -1; - } - - p.command = strtol(argv[2], &endptr, 0); - if (endptr && *endptr) { - fprintf(stderr, "Bad command\n"); - return -1; - } - - switch (p.command) { - case TYPEC_CONTROL_COMMAND_CLEAR_EVENTS: - if (argc < 4) { - fprintf(stderr, "Missing event mask\n"); - return -1; - } - - p.clear_events_mask = strtol(argv[3], &endptr, 0); - if (endptr && *endptr) { - fprintf(stderr, "Bad event mask\n"); - return -1; - } - break; - case TYPEC_CONTROL_COMMAND_ENTER_MODE: - if (argc < 4) { - fprintf(stderr, "Missing mode\n"); - return -1; - } - - conversion_result = strtol(argv[3], &endptr, 0); - if ((endptr && *endptr) || conversion_result > UINT8_MAX || - conversion_result < 0) { - fprintf(stderr, "Bad mode\n"); - return -1; - } - p.mode_to_enter = conversion_result; - } - - rv = ec_command(EC_CMD_TYPEC_CONTROL, 0, &p, sizeof(p), - ec_inbuf, ec_max_insize); - if (rv < 0) - return -1; - - return 0; -} - -int cmd_typec_discovery(int argc, char *argv[]) -{ - struct ec_params_typec_discovery p; - struct ec_response_typec_discovery *r = - (struct ec_response_typec_discovery *)ec_inbuf; - char *e; - int rv, i, j; - - if (argc < 3) { - fprintf(stderr, - "Usage: %s <port> <type>\n" - " <port> is the type-c port to query\n" - " <type> is one of:\n" - " 0: SOP\n" - " 1: SOP prime\n", argv[0]); - return -1; - } - - p.port = strtol(argv[1], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad port\n"); - return -1; - } - - p.partner_type = strtol(argv[2], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad type\n"); - return -1; - } - - rv = ec_command(EC_CMD_TYPEC_DISCOVERY, 0, &p, sizeof(p), - ec_inbuf, ec_max_insize); - if (rv < 0) - return -1; - - if (r->identity_count == 0) { - printf("No identity discovered\n"); - return 0; - } - - printf("Identity VDOs:\n"); - for (i = 0; i < r->identity_count; i++) - printf("0x%08x\n", r->discovery_vdo[i]); - - if (r->svid_count == 0) { - printf("No SVIDs discovered\n"); - return 0; - } - - for (i = 0; i < r->svid_count; i++) { - printf("SVID 0x%04x Modes:\n", r->svids[i].svid); - for (j = 0; j < r->svids[i].mode_count; j++) - printf("0x%08x\n", r->svids[i].mode_vdo[j]); - } - - return 0; -} - -/* Print shared fields of sink and source cap PDOs */ -static inline void print_pdo_fixed(uint32_t pdo) -{ - printf(" Fixed: %dmV %dmA %s%s%s%s", - PDO_FIXED_VOLTAGE(pdo), - PDO_FIXED_CURRENT(pdo), - pdo & PDO_FIXED_DUAL_ROLE ? "DRP " : "", - pdo & PDO_FIXED_UNCONSTRAINED ? "UP " : "", - pdo & PDO_FIXED_COMM_CAP ? "USB " : "", - pdo & PDO_FIXED_DATA_SWAP ? "DRD" : ""); -} - -static inline void print_pdo_battery(uint32_t pdo) -{ - printf(" Battery: max %dmV min %dmV max %dmW\n", - PDO_BATT_MAX_VOLTAGE(pdo), - PDO_BATT_MIN_VOLTAGE(pdo), - PDO_BATT_MAX_POWER(pdo)); -} - -static inline void print_pdo_variable(uint32_t pdo) -{ - printf(" Variable: max %dmV min %dmV max %dmA\n", - PDO_VAR_MAX_VOLTAGE(pdo), - PDO_VAR_MIN_VOLTAGE(pdo), - PDO_VAR_MAX_CURRENT(pdo)); -} - -static inline void print_pdo_augmented(uint32_t pdo) -{ - printf(" Augmented: max %dmV min %dmV max %dmA\n", - PDO_AUG_MAX_VOLTAGE(pdo), - PDO_AUG_MIN_VOLTAGE(pdo), - PDO_AUG_MAX_CURRENT(pdo)); -} - -int cmd_typec_status(int argc, char *argv[]) -{ - struct ec_params_typec_status p; - struct ec_response_typec_status *r = - (struct ec_response_typec_status *)ec_inbuf; - char *endptr; - int rv, i; - const char *desc; - - if (argc != 2) { - fprintf(stderr, - "Usage: %s <port>\n" - " <port> is the type-c port to query\n", argv[0]); - return -1; - } - - p.port = strtol(argv[1], &endptr, 0); - if (endptr && *endptr) { - fprintf(stderr, "Bad port\n"); - return -1; - } - - rv = ec_command(EC_CMD_TYPEC_STATUS, 0, &p, sizeof(p), - ec_inbuf, ec_max_insize); - if (rv == -EC_RES_INVALID_COMMAND - EECRESULT) - /* Fall back to PD_CONTROL to support older ECs */ - return cmd_usb_pd(argc, argv); - else if (rv < 0) - return -1; - - printf("Port C%d: %s, %s State:%s\n" - "Role:%s %s%s, Polarity:CC%d\n", - p.port, - r->pd_enabled ? "enabled" : "disabled", - r->dev_connected ? "connected" : "disconnected", - r->tc_state, - (r->power_role == PD_ROLE_SOURCE) ? "SRC" : "SNK", - (r->data_role == PD_ROLE_DFP) ? "DFP" : - (r->data_role == PD_ROLE_UFP) ? "UFP" : "", - (r->vconn_role == PD_ROLE_VCONN_SRC) ? " VCONN" : "", - (r->polarity % 2 + 1)); - - switch (r->cc_state) { - case PD_CC_NONE: - desc = "None"; - break; - case PD_CC_UFP_AUDIO_ACC: - desc = "UFP Audio accessory"; - break; - case PD_CC_UFP_DEBUG_ACC: - desc = "UFP Debug accessory"; - break; - case PD_CC_UFP_ATTACHED: - desc = "UFP attached"; - break; - case PD_CC_DFP_DEBUG_ACC: - desc = "DFP Debug accessory"; - break; - case PD_CC_DFP_ATTACHED: - desc = "DFP attached"; - break; - default: - desc = "UNKNOWN"; - break; - } - printf("CC State: %s\n", desc); - - if (r->dp_pin) { - switch (r->dp_pin) { - case MODE_DP_PIN_A: - desc = "A"; - break; - case MODE_DP_PIN_B: - desc = "B"; - break; - case MODE_DP_PIN_C: - desc = "C"; - break; - case MODE_DP_PIN_D: - desc = "D"; - break; - case MODE_DP_PIN_E: - desc = "E"; - break; - case MODE_DP_PIN_F: - desc = "F"; - break; - default: - desc = "UNKNOWN"; - break; - } - printf("DP pin mode: %s\n", desc); - } - - if (r->mux_state) { - printf("MUX: USB=%d DP=%d POLARITY=%s HPD_IRQ=%d HPD_LVL=%d\n" - " SAFE=%d TBT=%d USB4=%d\n", - !!(r->mux_state & USB_PD_MUX_USB_ENABLED), - !!(r->mux_state & USB_PD_MUX_DP_ENABLED), - (r->mux_state & USB_PD_MUX_POLARITY_INVERTED) ? - "INVERTED" : "NORMAL", - !!(r->mux_state & USB_PD_MUX_HPD_IRQ), - !!(r->mux_state & USB_PD_MUX_HPD_LVL), - !!(r->mux_state & USB_PD_MUX_SAFE_MODE), - !!(r->mux_state & USB_PD_MUX_TBT_COMPAT_ENABLED), - !!(r->mux_state & USB_PD_MUX_USB4_ENABLED)); - } - - printf("Port events: 0x%08x\n", r->events); - - if (r->sop_revision) - printf("SOP PD Rev: %d.%d\n", - PD_STATUS_REV_GET_MAJOR(r->sop_revision), - PD_STATUS_REV_GET_MINOR(r->sop_revision)); - - if (r->sop_prime_revision) - printf("SOP' PD Rev: %d.%d\n", - PD_STATUS_REV_GET_MAJOR(r->sop_prime_revision), - PD_STATUS_REV_GET_MINOR(r->sop_prime_revision)); - - for (i = 0; i < r->source_cap_count; i++) { - /* - * Bits 31:30 always indicate the type of PDO - * - * Table 6-7 PD Rev 3.0 Ver 2.0 - */ - uint32_t pdo = r->source_cap_pdos[i]; - int pdo_type = pdo & PDO_TYPE_MASK; - - if (i == 0) - printf("Source Capabilities:\n"); - - if (pdo_type == PDO_TYPE_FIXED) { - print_pdo_fixed(pdo); - printf("\n"); - } else if (pdo_type == PDO_TYPE_BATTERY) { - print_pdo_battery(pdo); - } else if (pdo_type == PDO_TYPE_VARIABLE) { - print_pdo_variable(pdo); - } else { - print_pdo_augmented(pdo); - } - } - - for (i = 0; i < r->sink_cap_count; i++) { - /* - * Bits 31:30 always indicate the type of PDO - * - * Table 6-7 PD Rev 3.0 Ver 2.0 - */ - uint32_t pdo = r->sink_cap_pdos[i]; - int pdo_type = pdo & PDO_TYPE_MASK; - - if (i == 0) - printf("Sink Capabilities:\n"); - - if (pdo_type == PDO_TYPE_FIXED) { - print_pdo_fixed(pdo); - /* Note: FRS bits are reserved in PD 2.0 spec */ - printf("%s\n", pdo & PDO_FIXED_FRS_CURR_MASK ? - "FRS" : ""); - } else if (pdo_type == PDO_TYPE_BATTERY) { - print_pdo_battery(pdo); - } else if (pdo_type == PDO_TYPE_VARIABLE) { - print_pdo_variable(pdo); - } else { - print_pdo_augmented(pdo); - } - } - - return 0; -} - -int cmd_tp_self_test(int argc, char* argv[]) -{ - int rv; - - rv = ec_command(EC_CMD_TP_SELF_TEST, 0, NULL, 0, NULL, 0); - if (rv < 0) - return rv; - - printf("Touchpad self test: %s\n", - rv == EC_RES_SUCCESS ? "passed" : "failed"); - - return rv; -} - -int cmd_tp_frame_get(int argc, char* argv[]) -{ - int i, j; - uint32_t remaining = 0, offset = 0; - int rv = EC_SUCCESS; - uint8_t *data; - struct ec_response_tp_frame_info* r; - struct ec_params_tp_frame_get p; - - data = (uint8_t *)(malloc(ec_max_insize)); - r = (struct ec_response_tp_frame_info *)(malloc(ec_max_insize)); - - if (data == NULL || r == NULL) { - fprintf(stderr, "Couldn't allocate memory.\n"); - free(r); - free(data); - return EC_ERROR_UNKNOWN; - } - - rv = ec_command(EC_CMD_TP_FRAME_INFO, 0, NULL, 0, r, ec_max_insize); - if (rv < 0) { - fprintf(stderr, "Failed to get touchpad frame info.\n"); - goto err; - } - - rv = ec_command(EC_CMD_TP_FRAME_SNAPSHOT, 0, NULL, 0, NULL, 0); - if (rv < 0) { - fprintf(stderr, "Failed to snapshot frame.\n"); - goto err; - } - - for (i = 0; i < r->n_frames; i++) { - p.frame_index = i; - offset = 0; - remaining = r->frame_sizes[i]; - - while (remaining > 0) { - p.offset = offset; - p.size = MIN(remaining, ec_max_insize); - - rv = ec_command(EC_CMD_TP_FRAME_GET, 0, - &p, sizeof(p), data, p.size); - if (rv < 0) { - fprintf(stderr, "Failed to get frame data " - "at offset 0x%x\n", offset); - goto err; - } - - for (j = 0; j < p.size; j++) - printf("%02x ", data[j]); - - offset += p.size; - remaining -= p.size; - } - printf("\n"); - } - -err: - free(data); - free(r); - - return rv < 0; -} - -int cmd_wait_event(int argc, char *argv[]) -{ - int rv, i; - struct ec_response_get_next_event_v1 buffer; - long timeout = 5000; - long event_type; - char *e; - - if (!ec_pollevent) { - fprintf(stderr, "Polling for MKBP event not supported\n"); - return -EINVAL; - } - - if (argc < 2) { - fprintf(stderr, "Usage: %s <type> [<timeout>]\n", - argv[0]); - return -1; - } - - event_type = strtol(argv[1], &e, 0); - if ((e && *e) || event_type < 0 || event_type >= EC_MKBP_EVENT_COUNT) { - fprintf(stderr, "Bad event type '%s'.\n", argv[1]); - return -1; - } - if (argc >= 3) { - timeout = strtol(argv[2], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad timeout value '%s'.\n", argv[2]); - return -1; - } - } - - rv = wait_event(event_type, &buffer, sizeof(buffer), timeout); - if (rv < 0) - return rv; - - printf("MKBP event %d data: ", buffer.event_type); - for (i = 0; i < rv - 1; ++i) - printf("%02x ", buffer.data.key_matrix[i]); - printf("\n"); - - return 0; -} - -static void cmd_cec_help(const char *cmd) -{ - fprintf(stderr, - " Usage: %s write [write bytes...]\n" - " Write message on the CEC bus\n" - " Usage: %s read [timeout]\n" - " [timeout] in seconds\n" - " Usage: %s get <param>\n" - " Usage: %s set <param> <val>\n" - " <param> is one of:\n" - " address: CEC receive address\n" - " <val> is the new CEC address\n" - " enable: Enable or disable CEC\n" - " <val> is 1 to enable, 0 to disable\n", - cmd, cmd, cmd, cmd); - -} - -static int cmd_cec_write(int argc, char *argv[]) -{ - char *e; - long val; - int rv, i, msg_len; - struct ec_params_cec_write p; - struct ec_response_get_next_event_v1 buffer; - - if (argc < 3 || argc > 18) { - fprintf(stderr, "Invalid number of params\n"); - cmd_cec_help(argv[0]); - return -1; - } - - msg_len = argc - 2; - for (i = 0; i < msg_len; i++) { - val = strtol(argv[i + 2], &e, 16); - if (e && *e) - return -1; - if (val < 0 || val > 0xff) - return -1; - p.msg[i] = (uint8_t)val; - } - - printf("Write to CEC: "); - for (i = 0; i < msg_len; i++) - printf("0x%02x ", p.msg[i]); - printf("\n"); - - rv = ec_command(EC_CMD_CEC_WRITE_MSG, 0, &p, msg_len, NULL, 0); - if (rv < 0) - return rv; - - rv = wait_event(EC_MKBP_EVENT_CEC_EVENT, &buffer, sizeof(buffer), 1000); - if (rv < 0) - return rv; - - if (buffer.data.cec_events & EC_MKBP_CEC_SEND_OK) - return 0; - - if (buffer.data.cec_events & EC_MKBP_CEC_SEND_FAILED) { - fprintf(stderr, "Send failed\n"); - return -1; - } - - fprintf(stderr, "No send result received\n"); - - return -1; -} - -static int cmd_cec_read(int argc, char *argv[]) -{ - int i, rv; - char *e; - struct ec_response_get_next_event_v1 buffer; - long timeout = 5000; - - if (!ec_pollevent) { - fprintf(stderr, "Polling for MKBP event not supported\n"); - return -EINVAL; - } - - if (argc >= 3) { - timeout = strtol(argv[2], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad timeout value '%s'.\n", argv[2]); - return -1; - } - } - - rv = wait_event(EC_MKBP_EVENT_CEC_MESSAGE, &buffer, - sizeof(buffer), timeout); - if (rv < 0) - return rv; - - printf("CEC data: "); - for (i = 0; i < rv - 1; i++) - printf("0x%02x ", buffer.data.cec_message[i]); - printf("\n"); - - return 0; -} - -static int cec_cmd_from_str(const char *str) -{ - if (!strcmp("address", str)) - return CEC_CMD_LOGICAL_ADDRESS; - if (!strcmp("enable", str)) - return CEC_CMD_ENABLE; - return -1; -} - -static int cmd_cec_set(int argc, char *argv[]) -{ - char *e; - struct ec_params_cec_set p; - uint8_t val; - int cmd; - - if (argc != 4) { - fprintf(stderr, "Invalid number of params\n"); - cmd_cec_help(argv[0]); - return -1; - } - - val = (uint8_t)strtol(argv[3], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad parameter '%s'.\n", argv[3]); - return -1; - } - - cmd = cec_cmd_from_str(argv[2]); - if (cmd < 0) { - fprintf(stderr, "Invalid command '%s'.\n", argv[2]); - return -1; - } - p.cmd = cmd; - p.val = val; - - return ec_command(EC_CMD_CEC_SET, - 0, &p, sizeof(p), NULL, 0); -} - - -static int cmd_cec_get(int argc, char *argv[]) -{ - int rv, cmd; - struct ec_params_cec_get p; - struct ec_response_cec_get r; - - - if (argc != 3) { - fprintf(stderr, "Invalid number of params\n"); - cmd_cec_help(argv[0]); - return -1; - } - - cmd = cec_cmd_from_str(argv[2]); - if (cmd < 0) { - fprintf(stderr, "Invalid command '%s'.\n", argv[2]); - return -1; - } - p.cmd = cmd; - - - rv = ec_command(EC_CMD_CEC_GET, 0, &p, sizeof(p), &r, sizeof(r)); - if (rv < 0) - return rv; - - printf("%d\n", r.val); - - return 0; -} - -int cmd_cec(int argc, char *argv[]) -{ - if (argc < 2) { - fprintf(stderr, "Invalid number of params\n"); - cmd_cec_help(argv[0]); - return -1; - } - if (!strcmp(argv[1], "write")) - return cmd_cec_write(argc, argv); - if (!strcmp(argv[1], "read")) - return cmd_cec_read(argc, argv); - if (!strcmp(argv[1], "get")) - return cmd_cec_get(argc, argv); - if (!strcmp(argv[1], "set")) - return cmd_cec_set(argc, argv); - - fprintf(stderr, "Invalid sub command: %s\n", argv[1]); - cmd_cec_help(argv[0]); - - return -1; -} - -/* NULL-terminated list of commands */ -const struct command commands[] = { - {"adcread", cmd_adc_read}, - {"addentropy", cmd_add_entropy}, - {"apreset", cmd_apreset}, - {"autofanctrl", cmd_thermal_auto_fan_ctrl}, - {"backlight", cmd_lcd_backlight}, - {"basestate", cmd_basestate}, - {"battery", cmd_battery}, - {"batterycutoff", cmd_battery_cut_off}, - {"batteryparam", cmd_battery_vendor_param}, - {"boardversion", cmd_board_version}, - {"button", cmd_button}, - {"cbi", cmd_cbi}, - {"chargecurrentlimit", cmd_charge_current_limit}, - {"chargecontrol", cmd_charge_control}, - {"chargeoverride", cmd_charge_port_override}, - {"chargestate", cmd_charge_state}, - {"chipinfo", cmd_chipinfo}, - {"cmdversions", cmd_cmdversions}, - {"console", cmd_console}, - {"cec", cmd_cec}, - {"echash", cmd_ec_hash}, - {"eventclear", cmd_host_event_clear}, - {"eventclearb", cmd_host_event_clear_b}, - {"eventget", cmd_host_event_get_raw}, - {"eventgetb", cmd_host_event_get_b}, - {"eventgetscimask", cmd_host_event_get_sci_mask}, - {"eventgetsmimask", cmd_host_event_get_smi_mask}, - {"eventgetwakemask", cmd_host_event_get_wake_mask}, - {"eventsetscimask", cmd_host_event_set_sci_mask}, - {"eventsetsmimask", cmd_host_event_set_smi_mask}, - {"eventsetwakemask", cmd_host_event_set_wake_mask}, - {"extpwrlimit", cmd_ext_power_limit}, - {"fanduty", cmd_fanduty}, - {"flasherase", cmd_flash_erase}, - {"flasheraseasync", cmd_flash_erase}, - {"flashprotect", cmd_flash_protect}, - {"flashread", cmd_flash_read}, - {"flashwrite", cmd_flash_write}, - {"flashinfo", cmd_flash_info}, - {"flashspiinfo", cmd_flash_spi_info}, - {"flashpd", cmd_flash_pd}, - {"forcelidopen", cmd_force_lid_open}, - {"fpcontext", cmd_fp_context}, - {"fpencstatus", cmd_fp_enc_status}, - {"fpframe", cmd_fp_frame}, - {"fpinfo", cmd_fp_info}, - {"fpmode", cmd_fp_mode}, - {"fpseed", cmd_fp_seed}, - {"fpstats", cmd_fp_stats}, - {"fptemplate", cmd_fp_template}, - {"gpioget", cmd_gpio_get}, - {"gpioset", cmd_gpio_set}, - {"hangdetect", cmd_hang_detect}, - {"hello", cmd_hello}, - {"hibdelay", cmd_hibdelay}, - {"hostevent", cmd_hostevent}, - {"hostsleepstate", cmd_hostsleepstate}, - {"locatechip", cmd_locate_chip}, - {"i2cprotect", cmd_i2c_protect}, - {"i2cread", cmd_i2c_read}, - {"i2cwrite", cmd_i2c_write}, - {"i2cxfer", cmd_i2c_xfer}, - {"infopddev", cmd_pd_device_info}, - {"inventory", cmd_inventory}, - {"led", cmd_led}, - {"lightbar", cmd_lightbar}, - {"kbfactorytest", cmd_keyboard_factory_test}, - {"kbid", cmd_kbid}, - {"kbinfo", cmd_kbinfo}, - {"kbpress", cmd_kbpress}, - {"keyconfig", cmd_keyconfig}, - {"keyscan", cmd_keyscan}, - {"mkbpget", cmd_mkbp_get}, - {"mkbpwakemask", cmd_mkbp_wake_mask}, - {"motionsense", cmd_motionsense}, - {"nextevent", cmd_next_event}, - {"panicinfo", cmd_panic_info}, - {"pause_in_s5", cmd_s5}, - {"pchg", cmd_pchg}, - {"pdgetmode", cmd_pd_get_amode}, - {"pdsetmode", cmd_pd_set_amode}, - {"port80read", cmd_port80_read}, - {"pdlog", cmd_pd_log}, - {"pdcontrol", cmd_pd_control}, - {"pdchipinfo", cmd_pd_chip_info}, - {"pdwritelog", cmd_pd_write_log}, - {"powerinfo", cmd_power_info}, - {"protoinfo", cmd_proto_info}, - {"pse", cmd_pse}, - {"pstoreinfo", cmd_pstore_info}, - {"pstoreread", cmd_pstore_read}, - {"pstorewrite", cmd_pstore_write}, - {"pwmgetfanrpm", cmd_pwm_get_fan_rpm}, - {"pwmgetkblight", cmd_pwm_get_keyboard_backlight}, - {"pwmgetnumfans", cmd_pwm_get_num_fans}, - {"pwmgetduty", cmd_pwm_get_duty}, - {"pwmsetfanrpm", cmd_pwm_set_fan_rpm}, - {"pwmsetkblight", cmd_pwm_set_keyboard_backlight}, - {"pwmsetduty", cmd_pwm_set_duty}, - {"rand", cmd_rand}, - {"readtest", cmd_read_test}, - {"reboot_ec", cmd_reboot_ec}, - {"rollbackinfo", cmd_rollback_info}, - {"rtcget", cmd_rtc_get}, - {"rtcgetalarm", cmd_rtc_get_alarm}, - {"rtcset", cmd_rtc_set}, - {"rtcsetalarm", cmd_rtc_set_alarm}, - {"rwhashpd", cmd_rw_hash_pd}, - {"rwsig", cmd_rwsig}, - {"rwsigaction", cmd_rwsig_action_legacy}, - {"rwsigstatus", cmd_rwsig_status}, - {"sertest", cmd_serial_test}, - {"smartdischarge", cmd_smart_discharge}, - {"stress", cmd_stress_test}, - {"sysinfo", cmd_sysinfo}, - {"port80flood", cmd_port_80_flood}, - {"switches", cmd_switches}, - {"temps", cmd_temperature}, - {"tempsinfo", cmd_temp_sensor_info}, - {"test", cmd_test}, - {"thermalget", cmd_thermal_get_threshold}, - {"thermalset", cmd_thermal_set_threshold}, - {"tpselftest", cmd_tp_self_test}, - {"tpframeget", cmd_tp_frame_get}, - {"tmp006cal", cmd_tmp006cal}, - {"tmp006raw", cmd_tmp006raw}, - {"typeccontrol", cmd_typec_control}, - {"typecdiscovery", cmd_typec_discovery}, - {"typecstatus", cmd_typec_status}, - {"uptimeinfo", cmd_uptimeinfo}, - {"usbchargemode", cmd_usb_charge_set_mode}, - {"usbmux", cmd_usb_mux}, - {"usbpd", cmd_usb_pd}, - {"usbpdmuxinfo", cmd_usb_pd_mux_info}, - {"usbpdpower", cmd_usb_pd_power}, - {"version", cmd_version}, - {"waitevent", cmd_wait_event}, - {"wireless", cmd_wireless}, - {"reboot_ap_on_g3", cmd_reboot_ap_on_g3}, - {NULL, NULL} -}; - -int main(int argc, char *argv[]) -{ - const struct command *cmd; - int dev = 0; - int interfaces = COMM_ALL; - int i2c_bus = -1; - char device_name[41] = CROS_EC_DEV_NAME; - int rv = 1; - int parse_error = 0; - char *e; - int i; - - BUILD_ASSERT(ARRAY_SIZE(lb_command_paramcount) == LIGHTBAR_NUM_CMDS); - - while ((i = getopt_long(argc, argv, "?", long_opts, NULL)) != -1) { - switch (i) { - case '?': - /* Unhandled option */ - parse_error = 1; - break; - - case OPT_DEV: - dev = strtoull(optarg, &e, 0); - if (!*optarg || (e && *e)) { - fprintf(stderr, "Invalid --dev\n"); - parse_error = 1; - } - break; - - case OPT_INTERFACE: - if (!strcasecmp(optarg, "dev")) { - interfaces = COMM_DEV; - } else if (!strcasecmp(optarg, "lpc")) { - interfaces = COMM_LPC; - } else if (!strcasecmp(optarg, "i2c")) { - interfaces = COMM_I2C; - } else if (!strcasecmp(optarg, "servo")) { - interfaces = COMM_SERVO; - } else { - fprintf(stderr, "Invalid --interface\n"); - parse_error = 1; - } - break; - case OPT_NAME: - strncpy(device_name, optarg, 40); - device_name[40] = '\0'; - break; - case OPT_I2C_BUS: - i2c_bus = strtoull(optarg, &e, 0); - if (*optarg == '\0' || (e && *e != '\0') - || i2c_bus < 0) { - fprintf(stderr, "Invalid --i2c_bus\n"); - parse_error = 1; - } - break; - case OPT_ASCII: - ascii_mode = 1; - break; - } - } - - if (i2c_bus != -1) { - if (!(interfaces & COMM_I2C)) { - fprintf(stderr, "--i2c_bus is specified, but --interface is set to something other than I2C\n"); - parse_error = 1; - } else { - interfaces = COMM_I2C; - } - } - - /* Must specify a command */ - if (!parse_error && optind == argc) - parse_error = 1; - - /* 'ectool help' prints help with commands */ - if (!parse_error && !strcasecmp(argv[optind], "help")) { - print_help(argv[0], 1); - exit(1); - } - - /* Handle sub-devices command offset */ - if (dev > 0 && dev < 4) { - set_command_offset(EC_CMD_PASSTHRU_OFFSET(dev)); - } else if (dev == 8) { - /* Special offset for Fingerprint MCU */ - strcpy(device_name, "cros_fp"); - } else if (dev != 0) { - fprintf(stderr, "Bad device number %d\n", dev); - parse_error = 1; - } - - if (parse_error) { - print_help(argv[0], 0); - exit(1); - } - - /* Prefer /dev method, which supports built-in mutex */ - if (!(interfaces & COMM_DEV) || comm_init_dev(device_name)) { - /* If dev is excluded or isn't supported, find alternative */ - if (acquire_gec_lock(GEC_LOCK_TIMEOUT_SECS) < 0) { - fprintf(stderr, "Could not acquire GEC lock.\n"); - exit(1); - } - if (comm_init_alt(interfaces, device_name, i2c_bus)) { - fprintf(stderr, "Couldn't find EC\n"); - goto out; - } - } - - if (comm_init_buffer()) { - fprintf(stderr, "Couldn't initialize buffers\n"); - goto out; - } - - /* Handle commands */ - for (cmd = commands; cmd->name; cmd++) { - if (!strcasecmp(argv[optind], cmd->name)) { - rv = cmd->handler(argc - optind, argv + optind); - goto out; - } - } - - /* If we're still here, command was unknown */ - fprintf(stderr, "Unknown command '%s'\n\n", argv[optind]); - print_help(argv[0], 0); - -out: - release_gec_lock(); - return !!rv; -} diff --git a/util/ectool.h b/util/ectool.h deleted file mode 100644 index c47edbf27c..0000000000 --- a/util/ectool.h +++ /dev/null @@ -1,42 +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. - */ - -/** @brief A handler for an `ectool` command. */ -struct command { - /** The name of the command. */ - const char *name; - - /** - * The function to handle the command. - * - * @param argc The length of `argv` - * @param argv The arguments passed, including the command itself but - * not 'ectool'. - * @return 0 if successful, or a negative `enum ec_status` value. - */ - int (*handler)(int argc, char *argv[]); -}; - -/** - * Test low-level key scanning - * - * ectool keyscan <beat_us> <filename> - * - * <beat_us> is the length of a beat in microseconds. This indicates the - * typing speed. Typically we scan at 10ms in the EC, so the beat period - * will typically be 1-5ms, with the scan changing only every 20-30ms at - * most. - * <filename> specifies a file containing keys that are depressed on each - * beat in the following format: - * - * <beat> <keys_pressed> - * - * <beat> is a beat number (0, 1, 2). The timestamp of this event will - * be <start_time> + <beat> * <beat_us>. - * <keys_pressed> is a (possibly empty) list of ASCII keys - * - * The key matrix is read from the fdt. - */ -int cmd_keyscan(int argc, char *argv[]); diff --git a/util/ectool_keyscan.c b/util/ectool_keyscan.c deleted file mode 100644 index 4f5393157d..0000000000 --- a/util/ectool_keyscan.c +++ /dev/null @@ -1,679 +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. - */ - -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <termios.h> -#include <unistd.h> -#include <sys/stat.h> -#include <endian.h> - -#include "comm-host.h" -#include "keyboard_config.h" -#include "ectool.h" - -enum { - /* Alloc this many more scans when needed */ - KEYSCAN_ALLOC_STEP = 64, - KEYSCAN_MAX_TESTS = 10, /* Maximum number of tests supported */ - KEYSCAN_MAX_INPUT_LEN = 20, /* Maximum characters we can receive */ -}; - -/* A single entry of the key matrix */ -struct matrix_entry { - int row; /* key matrix row */ - int col; /* key matrix column */ - int keycode; /* corresponding linux key code */ -}; - -struct keyscan_test_item { - uint32_t beat; /* Beat number */ - uint8_t scan[KEYBOARD_COLS_MAX]; /* Scan data */ -}; - -/* A single test, consisting of a list of key scans and expected ascii input */ -struct keyscan_test { - char *name; /* name of test */ - char *expect; /* resulting input we expect to see */ - int item_count; /* number of items in data */ - int item_alloced; /* number of items alloced in data */ - struct keyscan_test_item *items; /* key data for EC */ -}; - -/* A list of tests that we can run */ -struct keyscan_info { - unsigned int beat_us; /* length of each beat in microseconds */ - struct keyscan_test tests[KEYSCAN_MAX_TESTS]; /* the tests */ - int test_count; /* number of tests */ - struct matrix_entry *matrix; /* the key matrix info */ - int matrix_count; /* number of keys in matrix */ -}; - -/** - * Read the key matrix from the device tree - * - * Keymap entries in the fdt take the form of 0xRRCCKKKK where - * RR=Row CC=Column KKKK=Key Code - * - * @param keyscan keyscan information - * @param path path to device tree file containing data - * @return 0 if ok, -1 on error - */ -static int keyscan_read_fdt_matrix(struct keyscan_info *keyscan, - const char *path) -{ - struct stat buf; - uint32_t word; - int upto; - FILE *f; - int err; - - /* Allocate memory for key matrix */ - if (stat(path, &buf)) { - fprintf(stderr, "Cannot stat key matrix file '%s'\n", path); - return -1; - } - keyscan->matrix_count = buf.st_size / 4; - keyscan->matrix = (struct matrix_entry *)(calloc( - keyscan->matrix_count, sizeof(*keyscan->matrix))); - if (!keyscan->matrix) { - fprintf(stderr, "Out of memory for key matrix\n"); - return -1; - } - - f = fopen(path, "rb"); - if (!f) { - fprintf(stderr, "Cannot open key matrix file '%s'\n", path); - return -1; - } - - /* Now read the data */ - upto = err = 0; - while (fread(&word, 1, sizeof(word), f) == sizeof(word)) { - struct matrix_entry *matrix = &keyscan->matrix[upto++]; - - word = be32toh(word); - matrix->row = word >> 24; - matrix->col = (word >> 16) & 0xff; - matrix->keycode = word & 0xffff; - - /* Hard-code some limits for now */ - if (matrix->row >= KEYBOARD_ROWS || - matrix->col >= KEYBOARD_COLS_MAX) { - fprintf(stderr, "Matrix pos out of range (%d,%d)\n", - matrix->row, matrix->col); - fclose(f); - return -1; - } - } - fclose(f); - if (!err && upto != keyscan->matrix_count) { - fprintf(stderr, "Read mismatch from matrix file '%s'\n", path); - err = -1; - } - - return err; -} - -/* - * translate Linux's KEY_... values into ascii. We change space into 0xfe - * since we use the numeric value (&32) for space. That avoids ambiguity - * when we see a space in a key sequence file. - */ -static const unsigned char kbd_plain_xlate[] = { - 0xff, 0x1b, '1', '2', '3', '4', '5', '6', - '7', '8', '9', '0', '-', '=', '\b', '\t', /* 0x00 - 0x0f */ - 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', - 'o', 'p', '[', ']', '\r', 0xff, 'a', 's', /* 0x10 - 0x1f */ - 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', - '\'', '`', 0xff, '\\', 'z', 'x', 'c', 'v', /* 0x20 - 0x2f */ - 'b', 'n', 'm', ',' , '.', '/', 0xff, 0xff, 0xff, - 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x30 - 0x3f */ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, '7', - '8', '9', '-', '4', '5', '6', '+', '1', /* 0x40 - 0x4f */ - '2', '3', '0', '.', 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x50 - 0x5F */ - '\r', 0xff, 0xff, '\0' -}; - -/** - * Add a new key to a scan - * - * Given a new key, this looks it up in the matrix and adds it to the scan, - * so that if this scan were reported by the EC, the AP would the given key. - * - * The format of keys is a list of ascii characters, or & followed by a numeric - * ascii value, or * followed by a numeric keycode value. Spaces are ignored - * (use '*32' for space). - * - * Examples: - * a - a - * &20 - space - * *58 - KEY_CAPSLOCK - * - * @param keyscan keyscan information - * @param keysp point to the current key string on entry; on exit it - * is updated to point to just after the string, plus any - * following space - * @param path path to device tree file containing data - * @return 0 if ok, -1 on error - */ -static int keyscan_add_to_scan(struct keyscan_info *keyscan, char **keysp, - uint8_t scan[]) -{ - const uint8_t *pos; - struct matrix_entry *matrix; - int keycode = -1, i; - char *keys = *keysp; - int key = ' '; - - if (*keys == '&') { - /* Numeric ascii code */ - keys++; - key = strtol(keys, &keys, 10); - if (!key || keys == *keysp) { - fprintf(stderr, "Invalid numeric ascii\n"); - return -1; - } - if (*keys == ' ') - keys++; - else if (*keys) { - fprintf(stderr, "Expect space after numeric ascii\n"); - return -1; - } - } else if (*keys == '*') { - /* Numeric ascii code */ - keys++; - keycode = strtol(keys, &keys, 10); - if (!keycode || keys == *keysp) { - fprintf(stderr, "Invalid numeric keycode\n"); - return -1; - } - if (*keys == ' ') - keys++; - else if (*keys) { - fprintf(stderr, "Expect space after num. keycode\n"); - return -1; - } - } else { - key = *keys++; - } - - /* Convert keycode to key if needed */ - if (keycode == -1) { - pos = (uint8_t *)(strchr((char *)kbd_plain_xlate, key)); - if (!pos) { - fprintf(stderr, "Key '%c' not found in xlate table\n", - key); - return -1; - } - keycode = pos - kbd_plain_xlate; - } - - /* Look up keycode in matrix */ - for (i = 0, matrix = keyscan->matrix; i < keyscan->matrix_count; - i++, matrix++) { - if (matrix->keycode == keycode) { -#ifdef DEBUG - printf("%d: %d,%d\n", matrix->keycode, matrix->row, - matrix->col); -#endif - scan[matrix->col] |= 1 << matrix->row; - *keysp = keys; - return 0; - } - } - fprintf(stderr, "Key '%c' (keycode %d) not found in matrix\n", key, - keycode); - - return -1; -} - -/** - * Add a new keyscan to the given test - * - * This processes a new keyscan, consisting of a beat number and a sequence - * of keys. - * - * The format of keys is a beat number followed by a list of keys, each - * either ascii characters, or & followed by a numeric ascii value, or * - * followed by a numeric keycode value. Spaces are ignored (use '*32' for - * space). - * - * Examples: - * 0 abc - beat 0, press a, b and c - * 4 a &20 - beat 4, press a and space - * 8 *58 &13 - beat 8, press KEY_CAPSLOCK - * - * @param keyscan keyscan information - * @param linenum line number we are reading from (for error reporting) - * @param test test to add this scan to - * @param keys key string to process - * @return 0 if ok, -1 on error - */ -static int keyscan_process_keys(struct keyscan_info *keyscan, int linenum, - struct keyscan_test *test, char *keys) -{ - struct keyscan_test_item *item; - unsigned long int beat; - - /* Allocate more items if needed */ - if (!test->item_alloced || test->item_count == test->item_alloced) { - int size, new_size; - - size = test->item_alloced * sizeof(struct keyscan_test_item); - new_size = size + KEYSCAN_ALLOC_STEP * - sizeof(struct keyscan_test_item); - test->items = (struct keyscan_test_item *)(realloc(test->items, - new_size)); - if (!test->items) { - fprintf(stderr, "Out of memory realloc()\n"); - return -1; - } - memset((char *)test->items + size, '\0', new_size - size); - test->item_alloced += KEYSCAN_ALLOC_STEP; - new_size = size; - } - - /* read the beat number */ - item = &test->items[test->item_count]; - beat = strtol(keys, &keys, 10); - item->beat = beat; - - /* Read keys and add them to our scan */ - if (*keys == ' ') { - keys++; - while (*keys) { - if (keyscan_add_to_scan(keyscan, &keys, item->scan)) { - fprintf(stderr, "Line %d: Cannot parse" - " key input '%s'\n", linenum, - keys); - return -1; - } - } - } else if (*keys) { - fprintf(stderr, "Line %d: Need space after beat\n", - linenum); - return -1; - } - test->item_count++; - - return 0; -} - -/* These are the commands we understand in a key sequence file */ -enum keyscan_cmd { - KEYSCAN_CMD_TEST, /* start a new test */ - KEYSCAN_CMD_ENDTEST, /* end a test */ - KEYSCAN_CMD_SEQ, /* add a keyscan to a test sequence */ - KEYSCAN_CMD_EXPECT, /* indicate what input is expected */ - - KEYSCAN_CMD_COUNT -}; - -/* Names for each of the keyscan commands */ -static const char *keyscan_cmd_name[KEYSCAN_CMD_COUNT] = { - "test", - "endtest", - "seq", - "expect", -}; - -/** - * Read a command from a string and return it - * - * @param str String containing command - * @param len Length of command string - * @return detected command, or -1 if none - */ -static enum keyscan_cmd keyscan_read_cmd(const char *str, int len) -{ - int i; - - for (i = 0; i < KEYSCAN_CMD_COUNT; i++) { - if (!strncmp(keyscan_cmd_name[i], str, len)) - return (enum keyscan_cmd)(i); - } - - return (enum keyscan_cmd)(-1); -} - -/** - * Process a key sequence file a build up a list of tets from it - * - * @param f File containing keyscan info - * @param keyscan keyscan information - * @return 0 if ok, -1 on error - */ -static int keyscan_process_file(FILE *f, struct keyscan_info *keyscan) -{ - struct keyscan_test *cur_test; - char line[256]; - char *str; - int linenum; - - keyscan->test_count = 0; - - linenum = 0; - cur_test = NULL; - while (str = fgets(line, sizeof(line), f), str) { - char *args, *end; - int cmd, len; - - linenum++; - len = strlen(str); - - /* chomp the trailing newline */ - if (len > 0 && str[len - 1] == '\n') { - len--; - str[len] = '\0'; - } - - /* deal with blank lines and comments */ - if (!len || *str == '#') - continue; - - /* get the command */ - for (end = str; *end && *end != ' '; end++) - ; - - cmd = keyscan_read_cmd(str, end - str); - args = end + (*end != '\0'); - switch (cmd) { - case KEYSCAN_CMD_TEST: - /* Start a new test */ - if (keyscan->test_count == KEYSCAN_MAX_TESTS) { - fprintf(stderr, "KEYSCAN_MAX_TESTS " - "exceeded\n"); - return -1; - } - cur_test = &keyscan->tests[keyscan->test_count]; - cur_test->name = strdup(args); - if (!cur_test->name) { - fprintf(stderr, "Line %d: out of memory\n", - linenum); - } - break; - case KEYSCAN_CMD_EXPECT: - /* Get expect string */ - if (!cur_test) { - fprintf(stderr, "Line %d: expect should be " - "inside test\n", linenum); - return -1; - } - cur_test->expect = strdup(args); - if (!cur_test->expect) { - fprintf(stderr, "Line %d: out of memory\n", - linenum); - } - break; - case KEYSCAN_CMD_ENDTEST: - /* End of a test */ - keyscan->test_count++; - cur_test = NULL; - break; - case KEYSCAN_CMD_SEQ: - if (keyscan_process_keys(keyscan, linenum, cur_test, - args)) { - fprintf(stderr, "Line %d: Cannot parse key " - "input '%s'\n", linenum, args); - return -1; - } - break; - default: - fprintf(stderr, "Line %d: Uknown command '%1.*s'\n", - linenum, (int)(end - str), str); - return -1; - } - } - - return 0; -} - -/** - * Print out a list of all tests - * - * @param keyscan keyscan information - */ -static void keyscan_print(struct keyscan_info *keyscan) -{ - int testnum; - int i; - - for (testnum = 0; testnum < keyscan->test_count; testnum++) { - struct keyscan_test *test = &keyscan->tests[testnum]; - - printf("Test: %s\n", test->name); - for (i = 0; i < test->item_count; i++) { - struct keyscan_test_item *item; - int j; - - item = &test->items[i]; - printf("%2d %7d: ", i, item->beat); - for (j = 0; j < sizeof(item->scan); j++) - printf("%02x ", item->scan[j]); - printf("\n"); - } - printf("\n"); - } -} - -/** - * Set the terminal to raw mode, or cooked - * - * @param tty_fd Terminal file descriptor to change - * @Param raw 0 for cooked, non-zero for raw - */ -static void set_to_raw(int tty_fd, int raw) -{ - struct termios tty_attr; - int value; - - value = fcntl(tty_fd, F_GETFL); - - tcgetattr(tty_fd, &tty_attr); - if (raw) { - tty_attr.c_lflag &= ~ICANON; - value |= O_NONBLOCK; - } else { - tty_attr.c_lflag |= ICANON; - value &= ~O_NONBLOCK; - } - tcsetattr(tty_fd, TCSANOW, &tty_attr); - fcntl(tty_fd, F_SETFL, value); -} - -/** - * Read input for a whlie until wee see no more - * - * @param fd File descriptor for input - * @param input Place to put input string - * @param max_len Maximum length of input string - * @param wait Number of microseconds to wait for input - */ -static void keyscan_get_input(int fd, char *input, int max_len, int wait) -{ - int len; - - usleep(wait); - input[0] = '\0'; - len = read(fd, input, max_len - 1); - if (len > 0) - input[len] = '\0'; -} - -static int keyscan_send_sequence(struct keyscan_info *keyscan, - struct keyscan_test *test) -{ - struct ec_params_keyscan_seq_ctrl *req; - struct keyscan_test_item *item; - int upto, size, rv; - - size = sizeof(*req) + sizeof(item->scan); - req = (struct ec_params_keyscan_seq_ctrl *)malloc(size); - if (!req) { - fprintf(stderr, "Out of memory for message\n"); - return -1; - } - for (upto = rv = 0, item = test->items; rv >= 0 && - upto < test->item_count; upto++, item++) { - req->cmd = EC_KEYSCAN_SEQ_ADD; - req->add.time_us = item->beat * keyscan->beat_us; - memcpy(req->add.scan, item->scan, sizeof(item->scan)); - rv = ec_command(EC_CMD_KEYSCAN_SEQ_CTRL, 0, req, size, NULL, 0); - } - free(req); - if (rv < 0) - return rv; - - return 0; -} - -/** - * Run a single test - * - * @param keyscan keyscan information - * @param test test to run - * @return 0 if test passes, -ve if some error occurred - */ -static int run_test(struct keyscan_info *keyscan, struct keyscan_test *test) -{ - struct ec_params_keyscan_seq_ctrl ctrl; - char input[KEYSCAN_MAX_INPUT_LEN]; - struct ec_result_keyscan_seq_ctrl *resp; - int wait_us; - int size; - int rv; - int fd = 0; - int i; - - /* First clear the sequence */ - ctrl.cmd = EC_KEYSCAN_SEQ_CLEAR; - rv = ec_command(EC_CMD_KEYSCAN_SEQ_CTRL, 0, &ctrl, sizeof(ctrl), - NULL, 0); - if (rv < 0) - return rv; - - rv = keyscan_send_sequence(keyscan, test); - if (rv < 0) - return rv; - - /* Start it */ - set_to_raw(fd, 1); - ctrl.cmd = EC_KEYSCAN_SEQ_START; - rv = ec_command(EC_CMD_KEYSCAN_SEQ_CTRL, 0, &ctrl, sizeof(ctrl), - NULL, 0); - if (rv < 0) - return rv; - - /* Work out how long we need to wait */ - wait_us = 100 * 1000; /* Wait 100ms to at least */ - if (test->item_count) { - struct keyscan_test_item *ksi; - - ksi = &test->items[test->item_count - 1]; - wait_us += ksi->beat * keyscan->beat_us; - } - - /* Wait for input */ - keyscan_get_input(fd, input, sizeof(input), wait_us); - set_to_raw(fd, 0); - - /* Ask EC for results */ - size = sizeof(*resp) + test->item_count; - resp = (struct ec_result_keyscan_seq_ctrl *)(malloc(size)); - if (!resp) { - fprintf(stderr, "Out of memory for results\n"); - return -1; - } - ctrl.cmd = EC_KEYSCAN_SEQ_COLLECT; - ctrl.collect.start_item = 0; - ctrl.collect.num_items = test->item_count; - rv = ec_command(EC_CMD_KEYSCAN_SEQ_CTRL, 0, &ctrl, sizeof(ctrl), - resp, size); - if (rv < 0) - return rv; - - /* Check what scans were skipped */ - for (i = 0; i < resp->collect.num_items; i++) { - struct ec_collect_item *item; - struct keyscan_test_item *ksi; - - item = &resp->collect.item[i]; - ksi = &test->items[i]; - if (!(item->flags & EC_KEYSCAN_SEQ_FLAG_DONE)) - printf(" [skip %d at beat %u] ", i, ksi->beat); - } - - if (strcmp(input, test->expect)) { - printf("Expected '%s', got '%s' ", test->expect, input); - return -1; - } - - return 0; -} - -/** - * Run all tests - * - * @param keyscan keyscan information - * @return 0 if ok, -1 on error - */ -static int keyscan_run_tests(struct keyscan_info *keyscan) -{ - int testnum; - int any_err = 0; - - for (testnum = 0; testnum < keyscan->test_count; testnum++) { - struct keyscan_test *test = &keyscan->tests[testnum]; - int err; - - fflush(stdout); - err = run_test(keyscan, test); - any_err |= err; - if (err) { - printf("%d: %s: : FAIL\n", testnum, test->name); - } - } - - return any_err ? -1 : 0; -} - -int cmd_keyscan(int argc, char *argv[]) -{ - struct keyscan_info keyscan; - FILE *f; - int err; - - argc--; - argv++; - if (argc < 2) { - fprintf(stderr, "Must specify beat period and filename\n"); - return -1; - } - memset(&keyscan, '\0', sizeof(keyscan)); - keyscan.beat_us = atoi(argv[0]); - if (keyscan.beat_us < 100) - fprintf(stderr, "Warning: beat period is normally > 100us\n"); - f = fopen(argv[1], "r"); - if (!f) { - perror("Cannot open file\n"); - return -1; - } - - /* TODO(crosbug.com/p/23826): Read key matrix from fdt */ - err = keyscan_read_fdt_matrix(&keyscan, "test/test-matrix.bin"); - if (!err) - err = keyscan_process_file(f, &keyscan); - if (!err) - keyscan_print(&keyscan); - if (!err) - err = keyscan_run_tests(&keyscan); - fclose(f); - - return err; -} diff --git a/util/env_changed.sh b/util/env_changed.sh deleted file mode 100755 index 5bab64760d..0000000000 --- a/util/env_changed.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash -# 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. - -# This script accepts two parameters: a file name and a string. -# -# If the file does not exist, or does not contain the passed in string wrapped -# in '/*... */, the file is written with the wrapped passed in string. - -h_file="$1" -current_set="/* $2 */" - -if [[ -f "${h_file}" ]]; then - old_set="$(cat "${h_file}")" - if [[ "${current_set}" == "${old_set}" ]]; then - exit 0 - fi -else - dest_dir="$(dirname "${h_file}")" - [[ -d "${dest_dir}" ]] || mkdir -p "${dest_dir}" -fi -printf "${current_set}" > "${h_file}" diff --git a/util/export_taskinfo.c b/util/export_taskinfo.c deleted file mode 100644 index 4c09bafb90..0000000000 --- a/util/export_taskinfo.c +++ /dev/null @@ -1,43 +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. - * - * The cmd_c_to_taskinfo will compile this file with different - * section definitions to export different tasklists. - */ - -#include <stdint.h> - -#include "config.h" -#include "task_id.h" - -#ifdef SECTION_IS_RO -#define GET_TASKINFOS_FUNC get_ro_taskinfos -#elif defined(SECTION_IS_RW) -#define GET_TASKINFOS_FUNC get_rw_taskinfos -#else -#error "Current section (RO/RW) is not defined." -#endif - -struct taskinfo { - char *name; - char *routine; - uint32_t stack_size; -}; - -#define TASK(n, r, d, s, ...) { \ - .name = #n, \ - .routine = #r, \ - .stack_size = s, \ -}, -static const struct taskinfo taskinfos[] = { - CONFIG_TASK_LIST -}; -#undef TASK - -uint32_t GET_TASKINFOS_FUNC(const struct taskinfo **infos) -{ - *infos = taskinfos; - /* Calculate the number of tasks */ - return sizeof(taskinfos) / sizeof(*taskinfos); -} diff --git a/util/fingerprint-relevant-paths.txt b/util/fingerprint-relevant-paths.txt deleted file mode 100644 index e530c038cd..0000000000 --- a/util/fingerprint-relevant-paths.txt +++ /dev/null @@ -1,6 +0,0 @@ -# Paths of interest to be included in the commit message for -# merge commits to the firmware-fpmcu-<BOARD>-release branch when -# using update_release_branch.py. -common/fpsensor -docs/fingerprint -driver/fingerprint diff --git a/util/flash_cr50.py b/util/flash_cr50.py deleted file mode 100755 index 760a788627..0000000000 --- a/util/flash_cr50.py +++ /dev/null @@ -1,771 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# Copyright 2020 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. -"""Flash Cr50 using gsctool or cr50-rescue. - -gsctool example: -util/flash_cr50.py --image cr50.bin.prod -util/flash_cr50.py --release prod - -cr50-rescue example: -util/flash_cr50.py --image cr50.bin.prod -c cr50-rescue -p 9999 -util/flash_cr50.py --release prod -c cr50-rescue -p 9999 -""" - -import argparse -import logging -import os -import pprint -import re -import select -import shutil -import subprocess -import sys -import tempfile -import threading -import time - -from chromite.lib import cros_build_lib - -CR50_FIRMWARE_BASE = '/opt/google/cr50/firmware/cr50.bin.' -RELEASE_PATHS = { - 'prepvt': CR50_FIRMWARE_BASE + 'prepvt', - 'prod': CR50_FIRMWARE_BASE + 'prod', -} -# Dictionary mapping a setup to controls used to verify that the setup is -# correct. The keys are strings and the values are lists of strings. -REQUIRED_CONTROLS = { - 'cr50_uart': [ - r'raw_cr50_uart_pty:\S+', - r'cr50_ec3po_interp_connect:\S+', - ], - 'cr50_reset_odl': [ - r'cr50_reset_odl:\S+', - ], - 'ec_uart': [ - r'ec_board:\S+', - ], - 'flex': [ - r'servo_type:.*servo_.[^4]', - ], - 'type-c_servo_v4': [ - r'servo_v4_type:type-c', - r'servo_v4_role:\S+', - ], -} -# Supported methods to resetting cr50. -SUPPORTED_RESETS = ( - 'battery_cutoff', - 'cr50_reset_odl', - 'manual_reset', -) - - -class Error(Exception): - """Exception class for flash_cr50 utility.""" - - -def run_command(cmd, check_error=True): - """Run the given command. - - Args: - cmd: The command to run as a list of arguments. - check_error: Raise an error if the command fails. - - Returns: - (exit_status, The command output) - - Raises: - The command error if the command fails and check_error is True. - """ - try: - result = cros_build_lib.run(cmd, - check=check_error, - print_cmd=True, - capture_output=True, - encoding='utf-8', - stderr=subprocess.STDOUT, - debug_level=logging.DEBUG, - log_output=True) - except cros_build_lib.RunCommandError as cmd_error: - if check_error: - raise - # OSErrors are handled differently. They're raised even if check is - # False. Return the errno and message for OS errors. - return cmd_error.exception.errno, cmd_error.msg - return result.returncode, result.stdout.strip() - - -class Cr50Image(object): - """Class to handle cr50 image conversions.""" - - SUFFIX_LEN = 6 - RW_NAME_BASE = 'cr50.rw.' - - def __init__(self, image, artifacts_dir): - """Create an image object that can be used by cr50 updaters.""" - self._remove_dir = False - if not os.path.exists(image): - raise Error('Could not find image: %s' % image) - if not artifacts_dir: - self._remove_dir = tempfile.mkdtemp() - artifacts_dir = self._remove_dir - if not os.path.isdir(artifacts_dir): - raise Error('Directory does not exist: %s' % artifacts_dir) - self._original_image = image - self._artifacts_dir = artifacts_dir - self._generate_file_names() - - def __del__(self): - """Remove temporary files.""" - if self._remove_dir: - shutil.rmtree(self._remove_dir) - - def _generate_file_names(self): - """Create some filenames to use for image conversion artifacts.""" - self._tmp_rw_bin = os.path.join(self._artifacts_dir, - self.RW_NAME_BASE + '.bin') - self._tmp_rw_hex = os.path.join(self._artifacts_dir, - self.RW_NAME_BASE + '.hex') - self._tmp_cr50_bin = os.path.join(self._artifacts_dir, - self.RW_NAME_BASE + '.orig.bin') - - def extract_rw_a_hex(self): - """Extract RW_A.hex from the original image.""" - run_command(['cp', self.get_bin(), self._tmp_cr50_bin]) - run_command(['dd', 'if=' + self._tmp_cr50_bin, 'of=' + self._tmp_rw_bin, - 'skip=16384', 'count=233472', 'bs=1']) - run_command(['objcopy', '-I', 'binary', '-O', 'ihex', - '--change-addresses', '0x44000', self._tmp_rw_bin, - self._tmp_rw_hex]) - - def get_rw_hex(self): - """cr50-rescue uses the .hex file.""" - if not os.path.exists(self._tmp_rw_hex): - self.extract_rw_a_hex() - return self._tmp_rw_hex - - def get_bin(self): - """Get the filename of the update image.""" - return self._original_image - - def get_original_basename(self): - """Get the basename of the original image.""" - return os.path.basename(self._original_image) - - -class Servo(object): - """Class to interact with servo.""" - - # Wait 3 seconds for device to settle after running the dut control command. - SHORT_WAIT = 3 - - def __init__(self, port): - """Initialize servo class. - - Args: - port: The servo port for the device being updated. - """ - self._port = port - - def dut_control(self, cmd, check_error=True, wait=False): - """Run dut control commands - - Args: - cmd: the command to run - check_error: Raise RunCommandError if the command returns a non-zero - exit status. - wait: If True, wait SHORT_WAIT seconds after running the command - - Returns: - (exit_status, output string) - The exit_status will be non-zero if - the command failed and check_error is True. - - Raises: - RunCommandError if the command fails and check_error is False - """ - dut_control_cmd = ['dut-control', cmd, '-p', self._port] - exit_status, output = run_command(dut_control_cmd, check_error) - if wait: - time.sleep(self.SHORT_WAIT) - return exit_status, output.split(':', 1)[-1] - - def get_raw_cr50_pty(self): - """Return raw_cr50_pty. Disable ec3po, so the raw pty can be used.""" - # Disconnect EC3PO, raw_cr50_uart_pty will control the cr50 - # output and input. - self.dut_control('cr50_ec3po_interp_connect:off', wait=True) - return self.dut_control('raw_cr50_uart_pty')[1] - - def get_cr50_version(self): - """Return the current cr50 version string.""" - # Make sure ec3po is enabled, so getting cr50_version works. - self.dut_control('cr50_ec3po_interp_connect:on', wait=True) - return self.dut_control('cr50_version')[1] - - -class Cr50Reset(object): - """Class to enter and exit cr50 reset.""" - - # A list of requirements for the setup. The requirement strings must match - # something in the REQUIRED_CONTROLS dictionary. - REQUIRED_SETUP = () - - def __init__(self, servo, name): - """Make sure the setup supports the given reset_type. - - Args: - servo: The Servo object for the device. - name: The reset type. - """ - self._servo = servo - self._reset_name = name - self.verify_setup() - self._original_watchdog_state = self.ccd_watchdog_enabled() - self._servo_type = self._servo.dut_control('servo_type')[1] - - def verify_setup(self): - """Verify the setup has all required controls to flash cr50. - - Raises: - Error if something is wrong with the setup. - """ - # If this failed before and didn't cleanup correctly, the device may be - # cutoff. Try to set the servo_v4_role to recover the device before - # checking the device state. - self._servo.dut_control('servo_v4_role:src', check_error=False) - - logging.info('Requirements for %s: %s', self._reset_name, - pprint.pformat(self.REQUIRED_SETUP)) - - # Get the specific control requirements for the necessary categories. - required_controls = [] - for category in self.REQUIRED_SETUP: - required_controls.extend(REQUIRED_CONTROLS[category]) - - logging.debug('Required controls for %r:\n%s', self._reset_name, - pprint.pformat(required_controls)) - setup_issues = [] - # Check the setup has all required controls in the correct state. - for required_control in required_controls: - control, exp_response = required_control.split(':') - returncode, output = self._servo.dut_control(control, False) - logging.debug('%s: got %s expect %s', control, output, exp_response) - match = re.search(exp_response, output) - if returncode: - setup_issues.append('%s: %s' % (control, output)) - elif not match: - setup_issues.append('%s: need %s found %s' % - (control, exp_response, output)) - else: - logging.debug('matched control: %s:%s', control, match.string) - # Save controls, so they can be restored during cleanup. - setattr(self, '_' + control, output) - - if setup_issues: - raise Error('Cannot run update using %s. Setup issues: %s' % - (self._reset_name, setup_issues)) - logging.info('Device Setup: ok') - logging.info('Reset Method: %s', self._reset_name) - - def cleanup(self): - """Try to get the device out of reset and restore all controls.""" - logging.info('Cleaning up') - self.restore_control('cr50_ec3po_interp_connect') - - # Toggle the servo v4 role if possible to try and get the device out of - # cutoff. - self._servo.dut_control('servo_v4_role:snk', check_error=False) - self._servo.dut_control('servo_v4_role:src', check_error=False) - self.restore_control('servo_v4_role') - - # Restore the ccd watchdog. - self.enable_ccd_watchdog(self._original_watchdog_state) - - def restore_control(self, control): - """Restore the control setting, if it has been saved. - - Args: - control: The name of the servo control to restore. - """ - setting = getattr(self, control, None) - if setting is None: - return - self._servo.dut_control('%s:%s' % (control, setting)) - - def ccd_watchdog_enabled(self): - """Return True if servod is monitoring ccd""" - if 'ccd_cr50' not in self._servo_type: - return False - watchdog_state = self._servo.dut_control('watchdog')[1] - logging.debug(watchdog_state) - return not re.search('ccd:.*disconnect ok', watchdog_state) - - def enable_ccd_watchdog(self, enable): - """Control the CCD watchdog. - - Servo will die if it's watching CCD and cr50 is held in reset. Disable - the CCD watchdog, so it's ok for CCD to disconnect. - - This function does nothing if ccd_cr50 isn't in the servo type. - - Args: - enable: If True, enable the CCD watchdog. Otherwise disable it. - """ - if 'ccd_cr50' not in self._servo_type: - logging.debug('Servo is not watching ccd device.') - return - - if enable: - self._servo.dut_control('watchdog_add:ccd') - else: - self._servo.dut_control('watchdog_remove:ccd') - - if self.ccd_watchdog_enabled() != enable: - raise Error('Could not %sable ccd watchdog' % - ('en' if enable else 'dis')) - - def enter_reset(self): - """Disable the CCD watchdog then run the reset cr50 function.""" - logging.info('Using %r to enter reset', self._reset_name) - # Disable the CCD watchdog before putting servo into reset otherwise - # servo will die in the middle of flashing cr50. - self.enable_ccd_watchdog(False) - try: - self.run_reset() - except Exception as e: - logging.warning('%s enter reset failed: %s', self._reset_name, e) - raise - - def exit_reset(self): - """Exit cr50 reset.""" - logging.info('Recovering from %s', self._reset_name) - try: - self.recover_from_reset() - except Exception as e: - logging.warning('%s exit reset failed: %s', self._reset_name, e) - raise - - def run_reset(self): - """Start the cr50 reset process. - - Cr50 doesn't have to enter reset in this function. It just needs to do - whatever setup is necessary for the exit reset function. - """ - raise NotImplementedError() - - def recover_from_reset(self): - """Recover from Cr50 reset. - - Cr50 has to hard or power-on reset during this function for rescue to - work. Uart is disabled on deep sleep recovery, so deep sleep is not a - valid reset. - """ - raise NotImplementedError() - - -class Cr50ResetODLReset(Cr50Reset): - """Class for using the servo cr50_reset_odl to reset cr50.""" - - REQUIRED_SETUP = ( - # Rescue is done through Cr50 uart. It requires a flex cable not ccd. - 'flex', - # cr50_reset_odl is used to hold cr50 in reset. This control only exists - # if it actually resets cr50. - 'cr50_reset_odl', - # Cr50 rescue is done through cr50 uart. - 'cr50_uart', - ) - - def cleanup(self): - """Use the Cr50 reset signal to hold Cr50 in reset.""" - try: - self.restore_control('cr50_reset_odl') - finally: - super(Cr50ResetODLReset, self).cleanup() - - def run_reset(self): - """Use cr50_reset_odl to hold Cr50 in reset.""" - logging.info('cr50_reset_odl:on') - self._servo.dut_control('cr50_reset_odl:on') - - def recover_from_reset(self): - """Release the reset signal.""" - logging.info('cr50_reset_odl:off') - self._servo.dut_control('cr50_reset_odl:off') - - -class BatteryCutoffReset(Cr50Reset): - """Class for using a battery cutoff through EC commands to reset cr50.""" - - REQUIRED_SETUP = ( - # Rescue is done through Cr50 uart. It requires a flex cable not ccd. - 'flex', - # We need type c servo v4 to recover from battery_cutoff. - 'type-c_servo_v4', - # Cr50 rescue is done through cr50 uart. - 'cr50_uart', - # EC console needs to be read-write to issue cutoff command. - 'ec_uart', - ) - - def run_reset(self): - """Use EC commands to cutoff the battery.""" - self._servo.dut_control('servo_v4_role:snk') - - if self._servo.dut_control('ec_board', check_error=False)[0]: - logging.warning('EC is unresponsive. Cutoff may not work.') - - self._servo.dut_control('ec_uart_cmd:cutoff', check_error=False, - wait=True) - self._servo.dut_control('ec_uart_cmd:reboot', check_error=False, - wait=True) - - if not self._servo.dut_control('ec_board', check_error=False)[0]: - raise Error('EC still responsive after cutoff') - logging.info('Device is cutoff') - - def recover_from_reset(self): - """Connect power using servo v4 to recover from cutoff.""" - logging.info('"Connecting" adapter') - self._servo.dut_control('servo_v4_role:src', wait=True) - - -class ManualReset(Cr50Reset): - """Class for using a manual reset to reset Cr50.""" - - REQUIRED_SETUP = ( - # Rescue is done through Cr50 uart. It requires a flex cable not ccd. - 'flex', - # Cr50 rescue is done through cr50 uart. - 'cr50_uart', - ) - - PROMPT_WAIT = 5 - USER_RESET_TIMEOUT = 60 - - def run_reset(self): - """Nothing to do. User will reset cr50.""" - - def recover_from_reset(self): - """Wait for the user to reset cr50.""" - end_time = time.time() + self.USER_RESET_TIMEOUT - while time.time() < end_time: - logging.info('Press enter after you reset cr50') - user_input = select.select([sys.stdin], [], [], self.PROMPT_WAIT)[0] - if user_input: - logging.info('User reset done') - return - logging.warning('User input timeout: assuming cr50 reset') - - -class FlashCr50(object): - """Class for updating cr50.""" - - NAME = 'FlashCr50' - PACKAGE = '' - DEFAULT_UPDATER = '' - - def __init__(self, cmd): - """Verify the update command exists. - - Args: - cmd: The updater command. - - Raises: - Error if no valid updater command was found. - """ - updater = self.get_updater(cmd) - if not updater: - emerge_msg = (('Try emerging ' + self.PACKAGE) if self.PACKAGE - else '') - raise Error('Could not find %s command.%s' % (self, emerge_msg)) - self._updater = updater - - def get_updater(self, cmd): - """Find a valid updater command. - - Args: - cmd: the updater command. - - Returns: - A command string or None if none of the commands ran successfully. - The command string will be the one supplied or the DEFAULT_UPDATER - command. - """ - if not self.updater_works(cmd): - return cmd - - use_default = (self.DEFAULT_UPDATER and - not self.updater_works(self.DEFAULT_UPDATER)) - if use_default: - logging.debug('%r failed using %r to update.', cmd, - self.DEFAULT_UPDATER) - return self.DEFAULT_UPDATER - return None - - @staticmethod - def updater_works(cmd): - """Verify the updater command. - - Returns: - non-zero status if the command failed. - """ - logging.debug('Testing update command %r.', cmd) - exit_status, output = run_command([cmd, '-h'], check_error=False) - if 'Usage' in output: - return 0 - if exit_status: - logging.debug('Could not run %r (%s): %s', cmd, exit_status, output) - return exit_status - - def update(self, image): - """Try to update cr50 to the given image.""" - raise NotImplementedError() - - def __str__(self): - """Use the updater name for the tostring.""" - return self.NAME - - -class GsctoolUpdater(FlashCr50): - """Class to flash cr50 using gsctool.""" - - NAME = 'gsctool' - PACKAGE = 'ec-utils' - DEFAULT_UPDATER = '/usr/sbin/gsctool' - - # Common failures exit with this status. Use STANDARD_ERRORS to map the - # exit status to reasons for the failure. - STANDARD_ERROR_REGEX = r'Error: status (\S+)' - STANDARD_ERRORS = { - '0x8': 'Rejected image with old header.', - '0x9': 'Update too soon.', - '0xc': 'Board id mismatch', - } - - def __init__(self, cmd, serial=None): - """Generate the gsctool command. - - Args: - cmd: gsctool updater command. - serial: The serial number of the CCD device being updated. - """ - super(GsctoolUpdater, self).__init__(cmd) - self._gsctool_cmd = [self._updater] - if serial: - self._gsctool_cmd.extend(['-n', serial]) - - def update(self, image): - """Use gsctool to update cr50. - - Args: - image: Cr50Image object. - """ - update_cmd = self._gsctool_cmd[:] - update_cmd.append(image.get_bin()) - exit_status, output = run_command(update_cmd, check_error=False) - if not exit_status or (exit_status == 1 and 'image updated' in output): - logging.info('update ok') - return - if exit_status == 3: - match = re.search(self.STANDARD_ERROR_REGEX, output) - if match: - update_error = match.group(1) - logging.info('Update error %s', update_error) - raise Error(self.STANDARD_ERRORS[update_error]) - raise Error('gsctool update error: %s' % output.splitlines()[-1]) - - -class Cr50RescueUpdater(FlashCr50): - """Class to flash cr50 through servo micro uart.""" - - NAME = 'cr50-rescue' - PACKAGE = 'cr50-utils' - DEFAULT_UPDATER = '/usr/bin/cr50-rescue' - - WAIT_FOR_UPDATE = 120 - RESCUE_RESET_DELAY = 5 - - def __init__(self, cmd, port, reset_type): - """Initialize cr50-rescue updater. - - cr50-rescue can only be done through servo, because it needs access to - a lot of dut-controls and cr50 uart through servo micro. During rescue - Cr50 has to do a hard reset, so the user should supply a valid reset - method for the setup that's being used. - - Args: - cmd: The cr50-rescue command. - port: The servo port of the device being updated. - reset_type: A string (one of SUPPORTED_RESETS) that describes how - to reset Cr50 during cr50-rescue. - """ - super(Cr50RescueUpdater, self).__init__(cmd) - self._servo = Servo(port) - self._rescue_thread = None - self._rescue_process = None - self._cr50_reset = self.get_cr50_reset(reset_type) - - def get_cr50_reset(self, reset_type): - """Get the cr50 reset object for the given reset_type. - - Args: - reset_type: a string describing how cr50 will be reset. It must be - in SUPPORTED_RESETS. - - Returns: - The Cr50Reset object for the given reset_type. - """ - assert reset_type in SUPPORTED_RESETS, '%s is unsupported.' % reset_type - if reset_type == 'battery_cutoff': - return BatteryCutoffReset(self._servo, reset_type) - elif reset_type == 'cr50_reset_odl': - return Cr50ResetODLReset(self._servo, reset_type) - return ManualReset(self._servo, reset_type) - - def update(self, image): - """Use cr50-rescue to update cr50 then cleanup. - - Args: - image: Cr50Image object. - """ - update_file = image.get_rw_hex() - try: - self.run_update(update_file) - finally: - self.restore_state() - - def start_rescue_process(self, update_file): - """Run cr50-rescue in a process, so it can be killed it if it hangs.""" - pty = self._servo.get_raw_cr50_pty() - - rescue_cmd = [self._updater, '-v', '-i', update_file, '-d', pty] - logging.info('Starting cr50-rescue: %s', - cros_build_lib.CmdToStr(rescue_cmd)) - - self._rescue_process = subprocess.Popen(rescue_cmd) - self._rescue_process.communicate() - logging.info('Rescue Finished') - - def start_rescue_thread(self, update_file): - """Start cr50-rescue.""" - self._rescue_thread = threading.Thread(target=self.start_rescue_process, - args=[update_file]) - self._rescue_thread.start() - - def run_update(self, update_file): - """Run the Update""" - # Enter reset before starting rescue, so any extra cr50 messages won't - # interfere with cr50-rescue. - self._cr50_reset.enter_reset() - - self.start_rescue_thread(update_file) - - time.sleep(self.RESCUE_RESET_DELAY) - # Resume from cr50 reset. - self._cr50_reset.exit_reset() - - self._rescue_thread.join(self.WAIT_FOR_UPDATE) - - logging.info('cr50_version:%s', self._servo.get_cr50_version()) - - def restore_state(self): - """Try to get the device out of reset and restore all controls""" - try: - self._cr50_reset.cleanup() - finally: - self.cleanup_rescue_thread() - - def cleanup_rescue_thread(self): - """Cleanup the rescue process and handle any errors.""" - if not self._rescue_thread: - return - if self._rescue_thread.is_alive(): - logging.info('Killing cr50-rescue process') - self._rescue_process.terminate() - self._rescue_thread.join() - - self._rescue_thread = None - if self._rescue_process.returncode: - logging.info('cr50-rescue failed.') - logging.info('stderr: %s', self._rescue_process.stderr) - logging.info('stdout: %s', self._rescue_process.stdout) - logging.info('returncode: %s', self._rescue_process.returncode) - raise Error('cr50-rescue failed (%d)' % - self._rescue_process.returncode) - - -def parse_args(argv): - """Parse commandline arguments. - - Args: - argv: command line args - - Returns: - options: an argparse.Namespace. - """ - usage = ('%s -i $IMAGE [ -c cr50-rescue -p $SERVO_PORT [ -r ' - '$RESET_METHOD]]' % os.path.basename(argv[0])) - parser = argparse.ArgumentParser(usage=usage, description=__doc__) - parser.add_argument('-d', '--debug', action='store_true', default=False, - help='enable debug messages.') - parser.add_argument('-i', '--image', type=str, - help='Path to cr50 binary image.') - parser.add_argument('-R', '--release', type=str, - choices=RELEASE_PATHS.keys(), - help='Type of cr50 release. Use instead of the image ' - 'arg.') - parser.add_argument('-c', '--updater-cmd', type=str, default='gsctool', - help='Tool to update cr50. Either gsctool or ' - 'cr50-rescue') - parser.add_argument('-s', '--serial', type=str, default='', - help='serial number to pass to gsctool.') - parser.add_argument('-p', '--port', type=str, default='', - help='port servod is listening on (required for ' - 'rescue).') - parser.add_argument('-r', '--reset-type', default='battery_cutoff', - choices=SUPPORTED_RESETS, - type=str, help='The method for cr50 reset.') - parser.add_argument('-a', '--artifacts-dir', default=None, type=str, - help='Location to store artifacts') - opts = parser.parse_args(argv[1:]) - if 'cr50-rescue' in opts.updater_cmd and not opts.port: - raise parser.error('Servo port is required for cr50 rescue') - return opts - - -def get_updater(opts): - """Get the updater object.""" - if 'cr50-rescue' in opts.updater_cmd: - return Cr50RescueUpdater(opts.updater_cmd, opts.port, opts.reset_type) - if 'gsctool' in opts.updater_cmd: - return GsctoolUpdater(opts.updater_cmd, opts.serial) - raise Error('Unsupported update command %r' % opts.updater_cmd) - - -def main(argv): - """Update cr50 using gsctool or cr50-rescue.""" - opts = parse_args(argv) - - loglevel = logging.INFO - log_format = '%(asctime)s - %(levelname)7s' - if opts.debug: - loglevel = logging.DEBUG - log_format += ' - %(lineno)3d:%(funcName)-15s' - log_format += ' - %(message)s' - logging.basicConfig(level=loglevel, format=log_format) - - image = Cr50Image(RELEASE_PATHS.get(opts.release, opts.image), - opts.artifacts_dir) - flash_cr50 = get_updater(opts) - - logging.info('Using %s to update to %s', flash_cr50, - image.get_original_basename()) - flash_cr50.update(image) - - -if __name__ == '__main__': - sys.exit(main(sys.argv)) diff --git a/util/flash_ec b/util/flash_ec deleted file mode 100755 index 8fcde8d14b..0000000000 --- a/util/flash_ec +++ /dev/null @@ -1,1615 +0,0 @@ -#!/bin/bash - -# 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. - -SCRIPT="$(readlink -f "$0")" -SCRIPT_DIR="$(dirname "$SCRIPT")" - -EC_DIR="$(readlink -f "${SCRIPT_DIR}/..")" -if [[ "$(basename "${EC_DIR}")" != "ec" ]]; then - EC_DIR= -fi - -# Loads script libraries. -. "/usr/share/misc/shflags" || exit 1 - -# Redirects tput to stderr, and drop any error messages. -tput2() { - tput "$@" 1>&2 2>/dev/null || true -} - -error() { - tput2 bold && tput2 setaf 1 - echo "ERROR: $*" >&2 - tput2 sgr0 -} - - -info() { - tput2 bold && tput2 setaf 2 - echo "INFO: $*" >&2 - tput2 sgr0 -} - -warn() { - tput2 bold && tput2 setaf 3 - echo "WARNING: $*" >&2 - tput2 sgr0 -} - -die() { - [ -z "$*" ] || error "$@" - exit 1 -} - - -# Include a board name to the BOARDS_${EC_CHIP} array below ONLY IF servod is -# not aware of its 'ec_chip'. If servod becomes able to answer 'ec_chip' -# for the board, remove it from BOARDS_XXXX array below. -BOARDS_IT83XX=( - adlrvpm_ite - adlrvpp_ite - it83xx_evb - jslrvp_ite - reef_it8320 - tglrvpu_ite - tglrvpu_ite_tcpmv1 - tglrvpy_ite - tglrvpy_ite_tcpmv1 -) - -BOARDS_IT83XX_SPI_PROGRAMMING=( - it8xxx2_evb - it8xxx2_pdevb -) - -BOARDS_STM32=( - bloonchipper - chell_pd - coffeecake - chocodile_bec - chocodile_vpdmcu - dartmonkey - glados_pd - hatch_fp - jerry - minimuffin - nami_fp - nocturne_fp - oak_pd - pit - plankton - rainier - strago_pd - zinger -) -BOARDS_STM32_PROG_EN=( - plankton -) - -BOARDS_STM32_DFU=( - c2d2 - dingdong - hoho - twinkie - discovery - servo_v4 - servo_v4p1 - servo_micro - sweetberry - polyberry - stm32f446e-eval - tigertail - fluffy -) - -BOARDS_NPCX_5M5G_JTAG=( - npcx_evb - npcx_evb_arm -) - -BOARDS_NPCX_5M6G_JTAG=( -) - -BOARDS_NPCX_7M6X_JTAG=( -) - -BOARDS_NPCX_7M7X_JTAG=( - npcx7_evb -) - -BOARDS_NPCX_SPI=( -) - -BOARDS_NPCX_INT_SPI=( - adlrvpp_npcx -) - -BOARDS_SPI_1800MV=( - coral - reef -) - -BOARDS_RAIDEN=( - coral - eve - fizz - kukui - nami - nautilus - poppy - rammus - reef - scarlet - soraka -) - -DEFAULT_PORT="${SERVOD_PORT:-9999}" -BITBANG_RATE="57600" # Could be overwritten by a command line option. - -# Flags -DEFINE_integer bitbang_rate "${BITBANG_RATE}" \ - "UART baud rate to use when bit bang programming, "\ -"standard UART rates from 9600 to 57600 are supported." -DEFINE_string board "${DEFAULT_BOARD}" \ - "The board to run debugger on." -DEFINE_string chip "" \ - "The chip to run debugger on." -DEFINE_boolean dry_run "${FLAGS_FALSE}" \ - "Print the commands to be run instead of actually running them." -DEFINE_string image "" \ - "Full pathname of the EC firmware image to flash." -DEFINE_string logfile "" \ - "Stm32 only: pathname of the file to store communications log." -DEFINE_string offset "0" \ - "Offset where to program the image from." -DEFINE_integer port "${DEFAULT_PORT}" \ - "Port to communicate to servo on." -DEFINE_boolean raiden "${FLAGS_FALSE}" \ - "Use raiden_debug_spi programmer" -DEFINE_string read "" "Pathname of the file to store EC firmware image." -DEFINE_boolean ro "${FLAGS_FALSE}" \ - "Write only the read-only partition" -DEFINE_boolean servo_micro_uart_rx_rework "${FLAGS_FALSE}" \ - "The servo micro for flashing has b/143163043#comment3 rework" -DEFINE_integer timeout 600 \ - "Timeout for flashing the EC, measured in seconds." -DEFINE_boolean verbose "${FLAGS_FALSE}" \ - "Verbose hw control logging" -DEFINE_boolean verify "${FLAGS_FALSE}" \ - "Verify EC firmware image after programming." -DEFINE_boolean zephyr "${FLAGS_FALSE}" \ - "Program a Zephyr EC image instead of a CrOS EC image" - -# Parse command line -FLAGS_HELP="usage: $0 [flags]" -FLAGS "$@" || exit 1 -eval set -- "${FLAGS_ARGV}" -if [[ $# -gt 0 ]]; then - die "invalid arguments: \"$*\"" -fi - -# Error messages -MSG_PROGRAM_FAIL="Failed to flash EC firmware image" -MSG_READ_FAIL="Failed to read EC firmware image" -MSG_VERIFY_FAIL="Failed to verify EC firmware image." - -set -e - -DUT_CONTROL_CMD=( "dut-control" "--port=${FLAGS_port}" ) -DUT_CTRL_PREFIX="" - -# Run a command which mutates the state of an attached device. -# This is used by the --dry_run flag, when enabled, the command will -# only print. When disabled, the command will run without printing -# any message. -function print_or_run() { - if [ "${FLAGS_dry_run}" = "${FLAGS_TRUE}" ]; then - local arg - local -a quoted_args - - # Quote each of the arguments so it can easily be - # copy-pasted into a shell. - for arg in "$@"; do - quoted_args+=("$(printf "%q" "${arg}")") - done - - tput2 bold && tput2 setaf 4 - echo "DRY RUN:" "${quoted_args[@]}" >&2 - tput2 sgr0 - else - "$@" - fi -} - -function dut_control() { - local DUT_CTRL_CML=( "${DUT_CONTROL_CMD[@]}" ) - - for p in $@ ; do - # Only add the prefix if the arg is a control name. - if [[ ${p} != -* ]] ; then - p="${DUT_CTRL_PREFIX}${p}" - fi - DUT_CTRL_CML+=( "$p" ) - done - - if [ "${FLAGS_verbose}" = ${FLAGS_TRUE} ]; then - echo "${DUT_CTRL_CML[*]}" 1>&2 - fi - - print_or_run "${DUT_CTRL_CML[@]}" >/dev/null -} - -function dut_control_or_die { - dut_control "$@" || die "command exited $? (non-zero): dut-control $*" -} - -function dut_control_get() { - if [ $# -gt 1 ]; then - error "${FUNCNAME[0]} failed: more than one argument: $@" - return 1 - fi - - local ARGS DUT_GETVAL RETVAL - ARGS=( "${DUT_CONTROL_CMD[@]}" "--value_only" "${DUT_CTRL_PREFIX}$1" ) - RETVAL=0 - # || statement is attached to avoid an exit if error exit is enabled. - DUT_GETVAL=$( "${ARGS[@]}" ) || RETVAL="$?" - if (( "${RETVAL}" )) ; then - warn "${FUNCNAME[0]} failed: ${ARGS[*]} returned ${RETVAL}." - return "${RETVAL}" - fi - - echo "${DUT_GETVAL}" -} - -function dut_control_get_or_die { - dut_control_get "$@" || \ - die "command exited $? (non-zero): dut-control --value_only $*" -} - -: ${BOARD:=${FLAGS_board}} - -# Find the Zephyr project directory for the specified board. Zephyr projects -# organized under ./zephyr/projects as <baseboard>/<board> directory. -: ${ZEPHYR_DIR:=$(find zephyr/projects -mindepth 2 -maxdepth 2 \ - -type d -name "${BOARD}")} - -in_array() { - local n=$# - local value=${!n} - - for (( i=1; i<$#; i++ )) do - if [ "${!i}" == "${value}" ]; then - return 0 - fi - done - return 1 -} - -declare -a SUPPORTED_CHIPS - -if $(in_array "${BOARDS_STM32[@]}" "${BOARD}"); then - SUPPORTED_CHIPS+=("stm32") -fi - -if $(in_array "${BOARDS_STM32_DFU[@]}" "${BOARD}"); then - SUPPORTED_CHIPS+=("stm32_dfu") -fi - -if $(in_array "${BOARDS_NPCX_5M5G_JTAG[@]}" "${BOARD}"); then - SUPPORTED_CHIPS+=("npcx_5m5g_jtag") -fi - -if $(in_array "${BOARDS_NPCX_5M6G_JTAG[@]}" "${BOARD}"); then - SUPPORTED_CHIPS+=("npcx_5m6g_jtag") -fi - -if $(in_array "${BOARDS_NPCX_7M6X_JTAG[@]}" "${BOARD}"); then - SUPPORTED_CHIPS+=("npcx_7m6x_jtag") -fi - -if $(in_array "${BOARDS_NPCX_7M7X_JTAG[@]}" "${BOARD}"); then - SUPPORTED_CHIPS+=("npcx_7m7x_jtag") -fi - -if $(in_array "${BOARDS_NPCX_SPI[@]}" "${BOARD}"); then - SUPPORTED_CHIPS+=("npcx_spi") -fi - -if $(in_array "${BOARDS_NPCX_INT_SPI[@]}" "${BOARD}"); then - SUPPORTED_CHIPS+=("npcx_int_spi") -fi - -if $(in_array "${BOARDS_IT83XX[@]}" "${BOARD}"); then - SUPPORTED_CHIPS+=("it83xx") -fi - -if $(in_array "${BOARDS_IT83XX_SPI_PROGRAMMING[@]}" "${BOARD}"); then - SUPPORTED_CHIPS+=("ite_spi") -fi - -if [[ ${#SUPPORTED_CHIPS[@]} -eq 0 && -n "${FLAGS_chip}" ]]; then - SUPPORTED_CHIPS+="${FLAGS_chip}" -fi - -if [[ ${#SUPPORTED_CHIPS[@]} -eq 0 ]]; then - SERVO_EC_CHIP="$(dut_control_get ec_chip)" - SERVO_EC_CHIP="${SERVO_EC_CHIP,,}" - if [[ "${SERVO_EC_CHIP}" =~ "unknown" || -z "${SERVO_EC_CHIP}" ]]; then - die "Please check that servod is running or," \ - "manually specify either --board or --chip." - fi - SUPPORTED_CHIPS+=("${SERVO_EC_CHIP}") -fi - -if [[ ${#SUPPORTED_CHIPS[@]} -eq 0 ]]; then - # This happens if ${FLAGS_board} is not known in this flash_ec yet, - # ${FLAGS_chip} is not given, and servod doesn't know ec_chip. - # In this case, '--chip' should be specified in the command line. - die "board '${BOARD}' not supported." \ - "Please check that servod is running, or manually specify --chip." -elif [[ ${#SUPPORTED_CHIPS[@]} -eq 1 ]]; then - CHIP="${SUPPORTED_CHIPS[0]}" -elif [ -n "${FLAGS_chip}" ]; then - if $(in_array "${SUPPORTED_CHIPS[@]}" "${FLAGS_chip}"); then - CHIP="${FLAGS_chip}" - else - die "board ${BOARD} only supports (${SUPPORTED_CHIPS[@]})," \ - "not ${FLAGS_chip}." - fi -else - # Ideally, ec_chip per servo_type should be specified in servo overlay - # file, instead of having multiple board-to-chip mapping info in this - # script. Please refer to crrev.com/c/1496460 for example. - die "board ${BOARD} supports multiple chips" \ - "(${FILTERED_CHIPS[@]}). Use --chip= to choose one." -fi - -if [ -n "${FLAGS_chip}" -a "${CHIP}" != "${FLAGS_chip}" ]; then - die "board ${BOARD} doesn't use chip ${FLAGS_chip}" -fi - -if [[ "${CHIP}" = "stm32_dfu" ]]; then - NEED_SERVO="no" -fi - -# Servo variables management -case "${BOARD}" in - chocodile_bec ) MCU="usbpd" ;; - oak_pd|strago_pd ) MCU="usbpd" ;; - chell_pd|glados_pd ) MCU="usbpd" ;; - bloonchipper|dartmonkey|hatch_fp|nami_fp|nocturne_fp ) MCU="fpmcu" ;; - dingdong|hoho|twinkie ) DUT_CONTROL_CMD=( "true" ); MCU="ec" ;; - *) MCU="ec" ;; -esac - -case "${CHIP}" in - "stm32"|"npcx_spi"|"npcx_int_spi"|"it83xx"|"npcx_uut"|"ite_spi"| \ - "ite_spi_ccd_i2c") - ;; - *) - if [[ -n "${FLAGS_read}" ]]; then - die "The flag is not yet supported on ${CHIP}." - fi - - # If verification is not supported, then show a warning message. - # Keep it running however. - if [[ "${FLAGS_verify}" == ${FLAGS_TRUE} ]]; then - warn "Ignoring '--verify'" \ - "since read is not supported on ${CHIP}." - fi - ;; -esac - -SERVO_TYPE="$(dut_control_get servo_type || :)" - -if [[ "${SERVO_TYPE}" =~ ^servo_v4(p1)?_with_.*$ ]]; then - ACTIVE_DEVICE="$(dut_control_get active_dut_controller)" -else - ACTIVE_DEVICE="${SERVO_TYPE}" -fi - -if [[ "${SERVO_TYPE}" =~ ^servo_v4(p1)?_with_.*_and_.*$ ]]; then - # If there are two devices, servo v4 type will show both devices. The - # default device is first. The other device is second. - # servo_type:servo_v4{p1}_with_servo_micro_and_ccd_cr50 - SECOND_DEVICE="${SERVO_TYPE#*_and_}" - # servo_v4p1 can shared the same type with servo_v4, since there's no - # difference handling the flash. - SERVO_TYPE="servo_v4_with_${ACTIVE_DEVICE}" - # Controls sent through the default device don't have a prefix. The - # second device controls do. If the default device isn't active, we - # need to use the second device controls to send commands. Use the - # prefix for all dut control commands. - if [[ "${SECOND_DEVICE}" = "${ACTIVE_DEVICE}" ]]; then - DUT_CTRL_PREFIX="${ACTIVE_DEVICE}." - fi -fi - -servo_is_ccd() { - [[ "${SERVO_TYPE}" =~ "ccd_cr50" ]] || \ - [[ "${SERVO_TYPE}" =~ "ccd_ti50" ]] -} - -servo_has_warm_reset() { - dut_control -i warm_reset >/dev/null 2>&1 -} - -servo_has_cold_reset() { - dut_control -i cold_reset >/dev/null 2>&1 -} - -servo_has_dut_i2c_mux() { - dut_control -i dut_i2c_mux >/dev/null 2>&1 -} - -servo_ec_hard_reset_or_die() { - dut_control_or_die cold_reset:on - dut_control_or_die cold_reset:off - - # Cold reset on C2D2 is H1 reset, which will double reset the EC - # We need to wait a little bit to ensure we catch final EC reset - if [[ "${SERVO_TYPE}" =~ "c2d2" ]]; then - print_or_run sleep 0.2 - fi -} - -servo_ec_hard_reset() { - dut_control cold_reset:on - dut_control cold_reset:off -} - -c2d2_ec_hard_reset() { - # This is an H1-level reset (instead of just an EC-level reset) - dut_control cold_reset:on - dut_control cold_reset:off -} - -servo_usbpd_hard_reset() { - dut_control usbpd_reset:on sleep:0.5 usbpd_reset:off -} - -servo_fpmcu_hard_reset() { - dut_control fpmcu_reset:on sleep:0.5 fpmcu_reset:off -} - -servo_sh_hard_reset() { - dut_control sh_reset:on - dut_control sh_reset:off -} - -ec_reset() { - local stype - - if [[ "${SERVO_TYPE}" =~ "servo" ]] || servo_is_ccd; then - stype="servo" - else - stype=${SERVO_TYPE} - fi - - if [[ -n "${stype}" ]]; then - eval ${stype}_${MCU}_hard_reset - fi -} - -ccd_ec_boot0() { - local on_value="${1}" - local boot_mode="${2}" - - info "Using CCD ${boot_mode}." - - if [[ "${on_value}" == "on" ]] && [[ "${boot_mode}" == "uut" ]] ; then - # Ti50 requires EC reset to be asserted before UUT mode can be - # enabled, Cr50 should not mind. - dut_control cold_reset:on - fi - - dut_control "ccd_ec_boot_mode_${boot_mode}":"${on_value}" -} - -servo_micro_ec_boot0() { - # Some devices (e.g. hatch) control the RX UART pin via an on-board - # circuit that is controlled by the EC_FLASH_ODL pin. For those boards, - # we want to continue to drive the EC_FLASH_ODL if they do not have the - # servo micro rework listed below. - if [[ "${FLAGS_servo_micro_uart_rx_rework}" == ${FLAGS_TRUE} ]]; then - info "Servo micro $2 mode: $1 (using rx_rework)" - - # Setting the test point allows the EC_TX_SERVO_RX line - # to be driven by the servo for 'on' value. 'off' value - # lets the EC drive the EC_TX_SERVO_RX net. - # - # HW Rework (b/143163043#comment3): - # - Disconnect U45.1 from ground - # - Connected U45.1 to TP1 pad - dut_control tp1:$1 - dut_control servo_micro_ec_boot_mode_$2:$1 - else - info "Servo micro $2 mode: $1 (using FW_UP_L)" - dut_control ec_boot_mode:$1 - fi -} - -servo_ec_boot0() { - dut_control ec_boot_mode:$1 -} - -c2d2_ec_boot0() { - dut_control ec_boot_mode_uut:$1 -} - -servo_usbpd_boot0() { - dut_control usbpd_boot_mode:$1 -} - -servo_fpmcu_boot0() { - dut_control fpmcu_boot_mode:"$1" -} - -servo_micro_fpmcu_boot0() { - servo_fpmcu_boot0 "$@" -} - -servo_micro_usbpd_boot0() { - servo_usbpd_boot0 "$@" -} - -servo_sh_boot0() { - dut_control sh_boot_mode:$1 -} - -ec_switch_boot0() { - local on_value=$1 - # Enable programming GPIOs - if $(in_array "${BOARDS_STM32_PROG_EN[@]}" "${BOARD}"); then - servo_save_add "prog_en" - - dut_control prog_en:yes - fi - if servo_is_ccd ; then - stype=ccd - elif [[ "${SERVO_TYPE}" =~ "servo_micro" ]] ; then - stype=servo_micro - elif [[ "${SERVO_TYPE}" =~ "servo" ]] ; then - stype=servo - else - stype=${SERVO_TYPE} - fi - eval ${stype}_${MCU}_boot0 "${on_value}" $2 -} - -ec_enable_boot0() { - ec_switch_boot0 "on" $1 -} - -ec_disable_boot0() { - ec_switch_boot0 "off" $1 -} - -# Returns 0 on success (if on beaglebone) -on_servov3() { - grep -qs '^CHROMEOS_RELEASE_BOARD=beaglebone_servo' /etc/lsb-release -} - -# Returns 0 on success (if raiden should be used instead of servo) -error_reported= # Avoid double printing the error message. -on_raiden() { - if [[ "${SERVO_TYPE}" =~ "servo_v4" ]] || \ - servo_is_ccd || \ - [[ "${SERVO_TYPE}" =~ "servo_micro" ]]; then - return 0 - fi - if [ -z "${BOARD}" ]; then - [ "${FLAGS_raiden}" = ${FLAGS_TRUE} ] && return 0 || return 1 - fi - if [ "${FLAGS_raiden}" = ${FLAGS_TRUE} ]; then - if in_array "${BOARDS_RAIDEN[@]}" "${BOARD}"; then - return 0 - fi - if [ -z "${error_reported}" ]; then - error_reported="y" - die "raiden mode not supported on ${BOARD}" >&2 - fi - fi - return 1 -} - -declare -a DELETE_LIST # Array of file/dir names to delete at exit - -# Put back the servo and the system in a clean state at exit -FROZEN_PIDS="" -cleanup() { - for pid in ${FROZEN_PIDS}; do - info "Sending SIGCONT to process ${pid}!" - kill -CONT "${pid}" - done - - # Delete all files or directories in DELETE_LIST. - for item in "${DELETE_LIST[@]}"; do - if [[ -e "${item}" ]]; then - print_or_run rm -rf "${item}" &> /dev/null - fi - done - - if [ "${CHIP}" = "it83xx" ]; then - if [ "${SERVO_TYPE}" = "servo_v2" ]; then - info "Reinitializing ftdi_i2c interface" - # Ask servod to close its FTDI I2C interface because it - # could be open or closed at this point. Using - # ftdii2c_cmd:close when it's already closed is okay, - # however ftdii2c_cmd:open when it's already open - # triggers an error. - # - # If there is a simple, reliable way to detect whether - # servod FTDI I2C interface is open or closed, it would - # be preferable to check and only re-initialize if it's - # closed. Patches welcome. - dut_control ftdii2c_cmd:close - dut_control ftdii2c_cmd:init - dut_control ftdii2c_cmd:open - dut_control ftdii2c_cmd:setclock - fi - fi - - servo_restore - - if [ "${CHIP}" = "stm32" -o "${CHIP}" = "npcx_uut" ]; then - dut_control "${MCU}"_boot_mode:off - fi - - if servo_is_ccd; then - dut_control ccd_ec_boot_mode_uut:off - dut_control ccd_ec_boot_mode_bitbang:off - fi - - if ! on_raiden || servo_has_cold_reset; then - ec_reset - fi -} -trap cleanup EXIT - -# TODO: the name of the RO images created for zephyr vary based on whether -# the RO image includes a header. -# NPCX images use "build-ro/zephyr/zephyr.npcx.bin" -# ITE images use "build-ro/zephyr/zephyr.bin" -if [ "${FLAGS_ro}" = ${FLAGS_TRUE} ] && [ "${FLAGS_zephyr}" = ${FLAGS_TRUE} ] -then - die "The --ro flag is not supported with the --zephyr flag" -fi - -# Possible default EC images -if [ "${FLAGS_ro}" = ${FLAGS_TRUE} ] ; then - EC_FILE=ec.RO.flat -elif [ "${FLAGS_zephyr}" = ${FLAGS_TRUE} ] ; then - EC_FILE=zephyr.bin -else - EC_FILE=ec.bin -fi - -LOCAL_BUILD= -if [[ -n "${EC_DIR}" ]]; then - if [ "${FLAGS_ro}" = ${FLAGS_TRUE} ] ; then - LOCAL_BUILD="${EC_DIR}/build/${BOARD}/RO/${EC_FILE}" - elif [ "${FLAGS_zephyr}" = ${FLAGS_TRUE} ] ; then - LOCAL_BUILD="${EC_DIR}/build/${ZEPHYR_DIR}/output/${EC_FILE}" - else - LOCAL_BUILD="${EC_DIR}/build/${BOARD}/${EC_FILE}" - fi -fi - -# Get baseboard from build system if present -BASEBOARD= - -# We do not want to exit script if make call fails; we turn -e back on after -# setting BASEBOARD -set +e -if [[ -n "${EC_DIR}" ]]; then - BASEBOARD=$(make --quiet -C ${EC_DIR} BOARD=${BOARD} print-baseboard \ - 2>/dev/null) -elif [[ -d "${HOME}/trunk/src/platform/ec" ]]; then - BASEBOARD=$(make --quiet -C ${HOME}/trunk/src/platform/ec \ - BOARD=${BOARD} print-baseboard 2>/dev/null) -else - info "Could not find ec build folder to calculate baseboard." -fi -if [ $? -ne 0 ]; then - info "EC build system didn't recognize ${BOARD}. Assuming no baseboard." -fi -set -e - -if [[ -n "${BASEBOARD}" ]]; then - EMERGE_BUILD=/build/${BASEBOARD}/firmware/${BOARD}/${EC_FILE} -else - EMERGE_BUILD=/build/${BOARD}/firmware/${EC_FILE} -fi - -# Find the EC image to use -function ec_image() { - # No image specified on the command line, try default ones - if [[ -n "${FLAGS_image}" ]] ; then - if [ -f "${FLAGS_image}" ] || \ - [ "${FLAGS_image}" == "-" ]; then - echo "${FLAGS_image}" - return - fi - die "Invalid image path : ${FLAGS_image}" - else - if [ -f "${LOCAL_BUILD}" ]; then - echo "${LOCAL_BUILD}" - return - fi - if [ -f "${EMERGE_BUILD}" ]; then - echo "${EMERGE_BUILD}" - return - fi - fi - die "no EC image found : build one or specify one." -} - -# Get the correct UART for flashing. The resulting string is concatenated with -# the various UART control suffixes, such as "_pty", "_en", "_parity", etc. -function servo_ec_uart_prefix() { - if [[ "${MCU}" == "fpmcu" ]]; then - # The FPMCU has multiple UARTs. Use the platform UART since it's a - # bootloader capable UART on all devices. See - # http://go/cros-fingerprint-reference-designs#uart-console. - echo "fpmcu_platform_uart" - return - fi - - echo "${MCU}_uart" -} - -# Find the EC UART provided by servo. -function servo_ec_uart() { - SERVOD_FAIL="Cannot communicate with servod. Is servod running?" - local EC_UART_PREFIX - EC_UART_PREFIX="$(servo_ec_uart_prefix)" - PTY=$(dut_control_get "raw_${EC_UART_PREFIX}_pty" || - dut_control_get "${EC_UART_PREFIX}_pty") - if [[ -z "${PTY}" ]]; then - die "${SERVOD_FAIL}" - fi - echo $PTY -} - -# Not every control is supported on every servo type. Therefore, define which -# controls are supported by each servo type. -servo_v2_VARS=( "cold_reset" ) -servo_micro_VARS=( "cold_reset" ) -servo_v4_with_ccd_cr50_VARS=( "cold_reset" ) -c2d2_VARS=( "cold_reset" ) - -# Some servo boards use the same controls. -servo_v3_VARS=( "${servo_v2_VARS[@]}" ) -servo_v4_with_servo_micro_VARS=( "${servo_micro_VARS[@]}" ) - -declare -a save - -####################################### -# Store DUT control value to restore in LIFO order. -# Arguments: -# $1: Control name -# $2: (optional) Value to restore for the name at exit. -####################################### -function servo_save_add() { - local CTRL_RESULT= - case $# in - 1) CTRL_RESULT="$( "${DUT_CONTROL_CMD[@]}" \ - "${DUT_CTRL_PREFIX}$@" )" - if [[ -n "${CTRL_RESULT}" ]]; then - # Don't save the control with the prefix, because - # dut_control will add the prefix again when we restore - # the settings. - save=( "${CTRL_RESULT#$DUT_CTRL_PREFIX}" "${save[@]}" ) - fi - ;; - 2) save=( "$1:$2" "${save[@]}" ) - ;; - *) die "${FUNCNAME[0]} failed: arguments error" - ;; - esac -} - -function servo_save() { - local SERVO_VARS_NAME="${SERVO_TYPE}_VARS[@]" - for ctrl in "${!SERVO_VARS_NAME}"; do - servo_save_add "${ctrl}" - done - - if [[ "${SERVO_TYPE}" == "servo_v2" ]]; then - servo_save_add "i2c_mux_en" - servo_save_add "i2c_mux" - - dut_control i2c_mux_en:on - dut_control i2c_mux:remote_adc - fi -} - -function servo_restore() { - info "Restoring servo settings..." - for ctrl in "${save[@]}"; do - if [[ -n "${ctrl}" ]]; then - dut_control "${ctrl}" - fi - done -} - -function claim_pty() { - if grep -q cros_sdk /proc/1/cmdline; then - die "You must run this tool in a chroot that was entered with" \ - "'cros_sdk --no-ns-pid' (see crbug.com/444931 for details)" - fi - - if [[ -z "$1" ]]; then - warn "No parameter passed to claim_pty()" - return - fi - - # Disconnect the EC-3PO interpreter from the UART since it will - # interfere with flashing. - servo_save_add "${MCU}_ec3po_interp_connect" - - dut_control ${MCU}_ec3po_interp_connect:off || \ - warn "hdctools cannot disconnect the EC-3PO interpreter from" \ - "the UART." - - pids=$(lsof -FR 2>/dev/null -- $1 | grep -v '^f' | tr -d 'pR') - FROZEN_PIDS="" - - # reverse order to SIGSTOP parents before children - for pid in $(echo ${pids} | tac -s " "); do - if ps -o cmd= "${pid}" | grep -qE "(servod|/sbin/init)"; then - info "Skip stopping servod or init: process ${pid}." - else - info "Sending SIGSTOP to process ${pid}!" - FROZEN_PIDS+=" ${pid}" - sleep 0.02 - kill -STOP ${pid} - fi - done -} - -# Returns the serialnumber of the specified servo. -function get_serial() { - if [[ "${SERVO_TYPE}" =~ ^servo_v4(p1)?_with_servo_micro ]]; then - if [[ -z "${BOARD}" ]]; then - sn_ctl="servo_micro_" - elif [[ "$(dut_control_get "servo_micro_for_${BOARD}_serialname")" =~ \ - "unknown" ]] ; then - # Fall back to servo_micro_ if S/N is uknown. - sn_ctl="servo_micro_" - else - sn_ctl="servo_micro_for_${BOARD}_" - fi - elif [[ "${SERVO_TYPE}" =~ "_with_ccd" ]] ; then - sn_ctl="ccd_" - else - # If it's none of the above, the main serialname will do. - sn_ctl="" - fi - - dut_control_get "${sn_ctl}serialname" -} - -function c2d2_wait_for_h1_power_on_or_reset() { - # Ensure we have the latest c2d2 fw and hdctools. This could - # be removed eventually (estimate removal 2020/06/01) - dut_control h1_vref_present || die "Need to kill servod and run: -repo sync && sudo emerge hdctools servo-firmware && sudo servo_updater -b c2d2" - - # Handle the case when flash_ec starts before DUT power is - # applied. Otherwise just use h1-level reset. - if [[ "$(dut_control_get h1_vref_present)" = "off" ]] ; then - info "Please attach C2D2 to DUT and power DUT now!" - # Waits ~40 seconds for Vref presence before timeout - local LOOP_COUNTER=100 - while [[ "$(dut_control_get h1_vref_present)" = "off" \ - && "${LOOP_COUNTER}" -gt 1 ]] ; do - sleep 0.1 - let LOOP_COUNTER=LOOP_COUNTER-1 - done - # If we ran out of time, then just die now - if [[ "${LOOP_COUNTER}" -eq 1 ]] ; then - die "H1 Vref not present after waiting" - fi - else - # Ensure DUT is in clean state with H1 Reset - dut_control cold_reset:on - dut_control cold_reset:off - fi -} - -# Board specific flashing scripts - -# helper function for using servo v2/3 with openocd -function flash_openocd() { - OCD_CFG="servo.cfg" - if [[ -z "${EC_DIR}" ]]; then - # check if we're on beaglebone - if [[ -e "/usr/share/ec-devutils" ]]; then - OCD_PATH="/usr/share/ec-devutils" - else - die "Cannot locate openocd configs" - fi - else - OCD_PATH="${EC_DIR}/util/openocd" - fi - - servo_save_add "jtag_buf_on_flex_en" - servo_save_add "jtag_buf_en" - - dut_control jtag_buf_on_flex_en:on - dut_control jtag_buf_en:on - - print_or_run sudo timeout -k 10 -s 9 "${FLAGS_timeout}" \ - openocd -s "${OCD_PATH}" -f "${OCD_CFG}" -f "${OCD_CHIP_CFG}" \ - -c "${OCD_CMDS}" || \ - die "Failed to program ${IMG}" -} - -# helper function for using servo with flashrom -function flash_flashrom() { - TOOL_PATH="${EC_DIR}/build/${BOARD}/util:$PATH:/usr/sbin" - FLASHROM=$(PATH="${TOOL_PATH}" which flashrom) - - if on_servov3; then - FLASHROM_ARGS="-p linux_spi" - elif on_raiden; then - if [[ "${SERVO_TYPE}" =~ "servo_micro" ]]; then - # Servo micro doesn't use the "target" parameter. - FLASHROM_ARGS="-p raiden_debug_spi:" - else - FLASHROM_ARGS="-p raiden_debug_spi:target=EC," - fi - else - FLASHROM_ARGS="-p ft2232_spi:type=google-servo-v2,port=B," - fi - - if [ ! -x "$FLASHROM" ]; then - die "no flashrom util found." - fi - - if ! on_servov3; then - SERIALNAME=$(get_serial) - if [[ "$SERIALNAME" != "" ]] ; then - FLASHROM_ARGS+="serial=${SERIALNAME}" - fi - fi - - if ! on_raiden || [[ "${SERVO_TYPE}" =~ "servo_micro" ]] ; then - if $(in_array "${BOARDS_SPI_1800MV[@]}" "${BOARD}"); then - SPI_VOLTAGE="pp1800" - elif [[ "${CHIP}" == "ite_spi" || "${CHIP}" == "ite_spi_ccd_i2c" ]]; then - SPI_VOLTAGE="pp1800" - else - SPI_VOLTAGE="pp3300" - fi - - dut_control cold_reset:on - - # If spi flash is in npcx's ec, enable gang programer mode - if [[ "${CHIP}" == "npcx_int_spi" ]]; then - servo_save_add "fw_up" "off" - - # Set GP_SEL# as low then start ec - dut_control fw_up:on - sleep 0.1 - dut_control cold_reset:off - fi - - # Enable SPI programming mode. - if [[ "${CHIP}" == "ite_spi" || "${CHIP}" == "ite_spi_ccd_i2c" ]]; then - # Set hardware strap pin (GPG6) of SPI programming as low then start ec - dut_control fw_up:on - sleep 0.1 - dut_control cold_reset:off - sleep 0.1 - # We have to release the HW strap pin because it also SPI clock pin. - dut_control fw_up:off - fi - - servo_save_add "spi1_vref" "off" - servo_save_add "spi1_buf_en" "off" - - # Turn on SPI1 interface on servo for SPI Flash Chip - dut_control spi1_vref:${SPI_VOLTAGE} spi1_buf_en:on - if [[ ! "${SERVO_TYPE}" =~ "servo_micro" ]]; then - # Servo micro doesn't support this control. - servo_save_add "spi1_buf_on_flex_en" "off" - dut_control spi1_buf_on_flex_en:on - fi - else - if [[ "${CHIP}" == "npcx_int_spi" ]]; then - servo_save_add "fw_up" "off" - - # Set GP_SEL# as low then start ec - dut_control cold_reset:on - dut_control fw_up:on - # sleep 0.1 - dut_control cold_reset:off - else - # Assert EC reset. - dut_control cold_reset:on - fi - - # Temp layout - L=/tmp/flash_spi_layout_$$ - DELETE_LIST+=( "${L}" ) - - [[ -z "${FLAGS_read}" ]] && dump_fmap -F "${IMG}" > "${L}" - - FLASHROM_OPTIONS="-i EC_RW -i WP_RO -l "${L}" --noverify-all" - fi - - # Generate the correct flashrom command base. - FLASHROM_CMDLINE="${FLASHROM} ${FLASHROM_ARGS}" - if [[ -z "${FLAGS_read}" ]]; then - # Program EC image. - # flashrom should report the image size at the end of the output. - local FLASHROM_GETSIZE="sudo ${FLASHROM_CMDLINE} --flash-size" - if [[ "${FLAGS_verbose}" == ${FLAGS_TRUE} ]]; then - info "Running flashrom:" 1>&2 - echo " ${FLASHROM_GETSIZE}" 1>&2 - fi - SPI_SIZE=$(${FLASHROM_GETSIZE} | grep -oe '[0-9]\+$' | - tail -n1) || die "Failed to determine chip size!" - [[ ${SPI_SIZE} -eq 0 ]] && die "Chip size is 0!" - - PATCH_SIZE=$((${SPI_SIZE} - ${IMG_SIZE})) - - # Temp image - T=/tmp/flash_spi_$$ - DELETE_LIST+=( "${T}" ) - - if [[ "${CHIP}" =~ ^npcx(|_int)_spi$ ]] || \ - [[ "${CHIP}" =~ "ite_spi_ccd_i2c" ]] || - [[ "${CHIP}" =~ "ite_spi" ]] ; then - { # Patch temp image up to SPI_SIZE - cat "$IMG" - if [[ ${IMG_SIZE} -lt ${SPI_SIZE} ]] ; then - dd if=/dev/zero bs=${PATCH_SIZE} count=1 | \ - tr '\0' '\377' - fi - } > $T - else - { # Patch temp image up to SPI_SIZE - if [[ ${IMG_SIZE} -lt ${SPI_SIZE} ]] ; then - dd if=/dev/zero bs=${PATCH_SIZE} count=1 | \ - tr '\0' '\377' - fi - cat "$IMG" - } > $T - fi - - info "Programming EC firmware image." - local FLASHROM_WRITE="${FLASHROM_CMDLINE} ${FLASHROM_OPTIONS}" - if [[ "${FLAGS_verbose}" == ${FLAGS_TRUE} ]]; then - info "Running flashrom:" 1>&2 - echo " ${FLASHROM_WRITE} -w ${T}" 1>&2 - fi - print_or_run sudo timeout -k 10 -s 9 "${FLAGS_timeout}" \ - ${FLASHROM_WRITE} -w "${T}" \ - || die "${MSG_PROGRAM_FAIL}" - else - # Read EC image. - info "Reading EC firmware image." - if [[ "${FLAGS_verbose}" == ${FLAGS_TRUE} ]]; then - info "Running flashrom:" 1>&2 - echo " ${FLASHROM_CMDLINE} -r ${FLAGS_read}" 1>&2 - fi - print_or_run sudo timeout -k 10 -s 9 "${FLAGS_timeout}" \ - ${FLASHROM_CMDLINE} -r "${FLAGS_read}" \ - || die "${MSG_READ_FAIL}" - fi -} - -function flash_stm32() { - local STM32MON - local STM32MON_OPT - - if ! servo_has_cold_reset; then - die "Cold reset must be available for STM32 programming" - fi - - TOOL_PATH="${EC_DIR}/build/${BOARD}/util:$PATH" - STM32MON=$(PATH="${TOOL_PATH}" which stm32mon) - EC_UART="$(servo_ec_uart)" - EC_UART_PREFIX="$(servo_ec_uart_prefix)" - if [ ! -x "$STM32MON" ]; then - die "no stm32mon util found." - fi - - info "Using serial flasher : ${STM32MON}" - info "${MCU} UART pty : ${EC_UART}" - claim_pty ${EC_UART} - STM32MON_OPT="-d ${EC_UART}" - - # Make sure EC reboots in serial monitor mode. - ec_enable_boot0 "bitbang" - - # Pulse EC reset. - ec_reset - - if ! on_raiden && [[ "${SERVO_TYPE}" =~ "servo" ]] ; then - servo_save_add "${EC_UART_PREFIX}_en" - - dut_control "${EC_UART_PREFIX}_en:on" - fi - - servo_save_add "${EC_UART_PREFIX}_parity" - - dut_control "${EC_UART_PREFIX}_parity:even" - - if servo_is_ccd ; then - case "${FLAGS_bitbang_rate}" in - (9600|19200|38400|57600) : ;; - (*) - die "${FLAGS_bitbang_rate} is not a valid" \ - "bit bang rate" - ;; - esac - info "Programming at ${FLAGS_bitbang_rate} baud" - - servo_save_add "${EC_UART_PREFIX}_baudrate" - servo_save_add "${EC_UART_PREFIX}_bitbang_en" - - dut_control "${EC_UART_PREFIX}_baudrate:${FLAGS_bitbang_rate}" - dut_control "${EC_UART_PREFIX}_bitbang_en:on" - else - servo_save_add "${EC_UART_PREFIX}_baudrate" - - dut_control "${EC_UART_PREFIX}_baudrate:115200" - fi - - # Add a delay long enough for cr50 to update the ccdstate. Cr50 updates - # ccdstate once a second, so a 2 second delay should be safe. - if servo_is_ccd ; then - sleep 2 - STM32MON_OPT+=" -c" - fi - - if [ -n "${FLAGS_logfile}" ]; then - info "Saving log in ${FLAGS_logfile}" - STM32MON_OPT+=" -L ${FLAGS_logfile}" - fi - - local IMG_READ="${FLAGS_read}" - # Program EC image. - if [[ -z "${IMG_READ}" ]]; then - info "Programming EC firmware image." - # Unprotect flash, erase, and write - local STM32MON_COMMAND="${STM32MON} ${STM32MON_OPT} -U -u -e -w" - if [[ "${FLAGS_verbose}" == ${FLAGS_TRUE} ]]; then - echo "${STM32MON_COMMAND} ${IMG}" - fi - print_or_run timeout -k 10 -s 9 "${FLAGS_timeout}" \ - ${STM32MON_COMMAND} "${IMG}" \ - || die "${MSG_PROGRAM_FAIL}" - - # If it is a program-verify request, then make a temporary - # directory to store the image - if [[ "${FLAGS_verify}" == ${FLAGS_TRUE} ]]; then - local TEMP_SUFFIX=".$(basename ${SCRIPT}).${CHIP}" - local TEMP_DIR="$(mktemp -d --suffix="${TEMP_SUFFIX}")" - - IMG_READ="${TEMP_DIR}/ec.read.bin" - DELETE_LIST+=( "${TEMP_DIR}" ) - fi - fi - - # Read EC image. - if [[ -n "${IMG_READ}" ]]; then - info "Reading EC firmware image." - local STM32MON_READ_CMD="${STM32MON} ${STM32MON_OPT} -U -r" - if [[ "${FLAGS_verbose}" == ${FLAGS_TRUE} ]]; then - echo "${STM32MON_READ_CMD} ${IMG_READ}" - fi - print_or_run timeout -k 10 -s 9 "${FLAGS_timeout}" \ - ${STM32MON_READ_CMD} "${IMG_READ}" \ - || die "${MSG_READ_FAIL}" - fi - - # Verify the flash by comparing the source image to the read image, - # only if it was a flash write request. - if [[ -z "${FLAGS_read}" && "${FLAGS_verify}" == ${FLAGS_TRUE} ]]; then - info "Verifying EC firmware image." - if [[ "${FLAGS_verbose}" == ${FLAGS_TRUE} ]]; then - echo "cmp -n ${IMG_SIZE} ${IMG} ${IMG_READ}" - fi - cmp -s -n "${IMG_SIZE}" "${IMG}" "${IMG_READ}" \ - || die "${MSG_VERIFY_FAIL}" - fi - - # Remove the Application processor reset - # TODO(crosbug.com/p/30738): we cannot rely on servo_VARS to restore it - if servo_has_warm_reset; then - dut_control warm_reset:off - fi -} - -function flash_stm32_dfu() { - DFU_DEVICE=0483:df11 - ADDR=0x08000000 - DFU_UTIL='dfu-util' - which $DFU_UTIL &> /dev/null || die \ - "no dfu-util util found. Did you 'sudo emerge dfu-util'" - - info "Using dfu flasher : ${DFU_UTIL}" - - dev_cnt=$(lsusb -d $DFU_DEVICE | wc -l) - if [ $dev_cnt -eq 0 ] ; then - die "unable to locate dfu device at $DFU_DEVICE" - elif [ $dev_cnt -ne 1 ] ; then - die "too many dfu devices (${dev_cnt}). Disconnect all but one." - fi - - SIZE=$(wc -c ${IMG} | cut -d' ' -f1) - # Remove read protection - print_or_run sudo timeout -k 10 -s 9 "${FLAGS_timeout}" $DFU_UTIL -a 0 \ - -d "${DFU_DEVICE}" -s ${ADDR}:${SIZE}:force:unprotect -D "${IMG}" - # Wait for mass-erase and reboot after unprotection - print_or_run sleep 1 - # Actual image flashing - print_or_run sudo timeout -k 10 -s 9 "${FLAGS_timeout}" $DFU_UTIL -a 0 \ - -d "${DFU_DEVICE}" -s ${ADDR}:${SIZE} -D "${IMG}" -} - -function dut_i2c_dev() { - if [ -n "$DUT_I2C_DEV" ]; then - [ -e "$DUT_I2C_DEV" ] || - die "\$DUT_I2C_DEV is a non-existent path: $DUT_I2C_DEV" - echo "$DUT_I2C_DEV" - return - fi - - local adap_num= - adap_num="$(dut_control_get_or_die \ - "${ACTIVE_DEVICE}_i2c_pseudo_adapter_num")" - echo /dev/i2c-"$adap_num" -} - -function flash_it83xx() { - local TOOL_PATH="${EC_DIR}/build/${BOARD}/util:$PATH" - local ITEFLASH_BIN=$(PATH="${TOOL_PATH}" which iteflash) - - if [[ ! -x "$ITEFLASH_BIN" ]]; then - die "no iteflash util found." - fi - - # We need to ensure that c2d2 and dut-side path are set up for i2c - if [[ "${SERVO_TYPE}" =~ "c2d2" ]]; then - c2d2_wait_for_h1_power_on_or_reset - - # Don't let the EC come out of reset after H1 reset - dut_control ec_reset:on - - # Enable i2c bus on C2D2 at 400kbps - servo_save_add "i2c_ec_bus_speed" - dut_control_or_die i2c_ec_bus_speed:400 - - # We need to swing the DUT-side muxes to I2C instead of UART. - # This is done by convention with EC_FLASH_SELECT pin from H1 - dut_control_or_die ec_flash_select:on - fi - - # Now the we have enabled the I2C mux on the servo to talk to the dut, - # we need to switch the I2C mux on the dut to allow ec programing (if - # there is a mux on the dut) - if servo_has_dut_i2c_mux; then - info "Switching DUT I2C Mux to ${CHIP}" - servo_save_add "dut_i2c_mux" - dut_control dut_i2c_mux:ec_prog - fi - - # We need to send the special waveform very soon after the EC powers on - if [[ "${SERVO_TYPE}" =~ "c2d2" ]]; then - # The EC was held in reset above - dut_control ec_reset:off - elif servo_has_cold_reset; then - servo_ec_hard_reset_or_die - fi - - # Send the special waveform to the ITE EC. - if [[ "${SERVO_TYPE}" =~ "servo_micro" || \ - "${SERVO_TYPE}" =~ "c2d2" ]] ; then - info "Asking servo to send the dbgr special waveform to ${CHIP}" - dut_control_or_die enable_ite_dfu - elif servo_is_ccd; then - local CCD_I2C_CAP="$(dut_control_get ccd_i2c_en)" - if [[ "${CCD_I2C_CAP,,}" != "always" ]]; then - die "CCD I2C capability is not set as 'Always'" \ - ": ${CCD_I2C_CAP}" - fi - - info "Asking CR50 to send the dbgr special waveform to ${CHIP}" - sleep 2 - dut_control_or_die cr50_i2c_ctrl:ite_debugger_mode - sleep 3 - elif [[ "${SERVO_TYPE}" == "servo_v2" ]]; then - info "Closing servod connection to ftdi_i2c interface" - dut_control_or_die ftdii2c_cmd:close - else - die "This servo type is not yet supported: ${SERVO_TYPE}" - fi - - # Build the iteflash command line. - local ITEFLASH_ARGS=( "${ITEFLASH_BIN}" ) - - if [[ "${SERVO_TYPE}" == "servo_v2" ]]; then - ITEFLASH_ARGS+=( "--send-waveform=1" "--i2c-interface=ftdi" ) - else - ITEFLASH_ARGS=( "sudo" "--" "${ITEFLASH_ARGS[@]}" \ - "--send-waveform=0" "--i2c-interface=linux" \ - "--i2c-dev-path=$(dut_i2c_dev)" ) - if servo_is_ccd; then - ITEFLASH_ARGS+=( "--block-write-size=256" ) - fi - fi - - local ERROR_MSG - if [[ -n "${FLAGS_read}" ]]; then - ITEFLASH_ARGS+=( "--read=${FLAGS_read}" ) - info "Reading EC firmware image using iteflash..." - ERROR_MSG="${MSG_READ_FAIL}" - else - ITEFLASH_ARGS+=( "--erase" "--write=${IMG}" ) - info "Programming EC firmware image using iteflash..." - ERROR_MSG="${MSG_PROGRAM_FAIL}" - fi - - if [[ "${FLAGS_verify}" == "${FLAGS_FALSE}" ]]; then - ITEFLASH_ARGS+=( "--noverify" ) - fi - - if [[ "${FLAGS_verbose}" == ${FLAGS_TRUE} ]]; then - ITEFLASH_ARGS+=( "--debug" ) - echo "${ITEFLASH_ARGS[@]}" - fi - - # Ensure the CR50 doesn't go into low power while flashing - # otherwise the DUT side muxes will get cut. Note this also needs to - # happen once the CR50 hooks have settled and H1 realizes that the - # "AP [is] Off", since that over writes the idle action with sleep. - if [[ "${SERVO_TYPE}" =~ "c2d2" ]]; then - dut_control cr50_idle_level:active - fi - - print_or_run "${ITEFLASH_ARGS[@]}" || die "${ERROR_MSG}" -} - -function flash_ite_spi() { - flash_flashrom -} - -function flash_ite_spi_ccd_i2c() { - if [[ "${SERVO_TYPE}" =~ "servo_micro" || \ - "${SERVO_TYPE}" =~ "servo_v2" ]] ; then - flash_flashrom - else - flash_it83xx - fi -} - -function flash_lm4() { - OCD_CHIP_CFG="lm4_chip.cfg" - OCD_CMDS="init; flash_lm4 ${IMG} ${FLAGS_offset}; shutdown;" - - flash_openocd - -} - -function flash_nrf51() { - OCD_CHIP_CFG="nrf51_chip.cfg" - OCD_CMDS="init; flash_nrf51 ${IMG} ${FLAGS_offset}; exit_debug_mode_nrf51; shutdown;" - - flash_openocd - - # waiting 100us for the reset pulse is not necessary, it takes ~2.5ms - dut_control swd_reset:on swd_reset:off -} - -function flash_npcx_jtag() { - IMG_PATH="${EC_DIR}/build/${BOARD}" - OCD_CHIP_CFG="npcx_chip.cfg" - if [ "${FLAGS_ro}" = ${FLAGS_TRUE} ] ; then - # Program RO region only - OCD_CMDS="init; flash_npcx_ro ${CHIP} ${IMG_PATH} ${FLAGS_offset}; shutdown;" - else - # Program all EC regions - OCD_CMDS="init; flash_npcx_all ${CHIP} ${IMG_PATH} ${FLAGS_offset}; shutdown;" - fi - - # Reset the EC - ec_reset - - flash_openocd -} - -function flash_npcx_uut() { - local TOOL_PATH="${EC_DIR}/build/${BOARD}/util:$PATH" - local NPCX_UUT=$(PATH="${TOOL_PATH}" which uartupdatetool) - local EC_UART="$(servo_ec_uart)" - - # Look for npcx_monitor.bin in multiple directories, starting with - # the same path as the EC binary. - local MON="" - for dir in \ - "$(dirname "$IMG")/chip/npcx/spiflashfw" \ - "$(dirname "$IMG")" \ - "${EC_DIR}/build/${BOARD}/chip/npcx/spiflashfw" \ - "${EC_DIR}/build/${ZEPHYR_DIR}/output" \ - "$(dirname "$LOCAL_BUILD")" \ - "$(dirname "$EMERGE_BUILD")" ; - do - if [ -f "$dir/npcx_monitor.bin" ] ; then - MON="$dir/npcx_monitor.bin" - break - fi - done - if [ -z "${MON}" ] ; then - echo "Failed to find npcx_monitor.bin" - exit 1 - fi - info "Using NPCX image : ${MON}" - - # The start address to restore monitor firmware binary - local MON_ADDR="0x200C3020" - - if [ ! -x "$NPCX_UUT" ]; then - die "no NPCX UART Update Tool found." - fi - - info "Using: NPCX UART Update Tool" - info "${MCU} UART pty : ${EC_UART}" - claim_pty ${EC_UART} - - if [[ "${SERVO_TYPE}" =~ "ccd_cr50" ]] ; then - # Ti50 does not yet support ccd_keepalive option which - # requires ccdstate command on the GSC console. - # TODO(b/161483597) remove the check when Ti50 CCD is on par. - servo_save_add ccd_keepalive_en - dut_control ccd_keepalive_en:on - fi - - # C2D2 does not use waits and has to ensure that the EC does not come - # out of reset after using a H1-level reset - if [[ "${SERVO_TYPE}" =~ "c2d2" ]] ; then - c2d2_wait_for_h1_power_on_or_reset - - # Don't let the EC come out of reset after H1 reset - dut_control ec_reset:on - - # Force the EC to boot in UART update mode coming out of reset - ec_enable_boot0 "uut" - dut_control ec_reset:off - - # Ensure normal UART operation - ec_disable_boot0 "uut" - else - # Force the EC to boot in UART update mode - ec_enable_boot0 "uut" - ec_reset - - # Have to wait a bit for EC boot-up - print_or_run sleep 0.1 - - # Ensure normal UART operation - ec_disable_boot0 "uut" - print_or_run sleep 0.1 - fi - - # Remove the prefix "/dev/" because uartupdatetool will add it. - local UUT_ARGS=( "--port=${EC_UART#/dev/}" " --baudrate=115200" ) - local IMG_READ="${FLAGS_read}" - - # Program EC image. - if [[ -z "${IMG_READ}" ]]; then - info "Loading monitor binary." - local UUT_MON=( "${NPCX_UUT}" "${UUT_ARGS[@]}" \ - "--opr=wr" "--addr=${MON_ADDR}" \ - "--file=${MON}" ) - - # Load monitor binary to address 0x200C3020 - if [[ "${FLAGS_verbose}" = ${FLAGS_TRUE} ]]; then - echo "${UUT_MON[*]}" - fi - print_or_run timeout -k 10 -s 9 "${FLAGS_timeout}" \ - "${UUT_MON[@]}" || die "Failed to load monitor binary." - - info "Programming EC firmware image." - local UUT_WR=( "${NPCX_UUT}" "${UUT_ARGS[@]}" \ - "--auto" "--offset=${FLAGS_offset}" \ - "--file=${IMG}" ) - if [[ "${FLAGS_verbose}" = ${FLAGS_TRUE} ]]; then - echo "${UUT_WR[*]}" - fi - print_or_run timeout -k 10 -s 9 "${FLAGS_timeout}" \ - "${UUT_WR[@]}" || die "${MSG_PROGRAM_FAIL}" - - # If it is a program-verify request, then make a temporary - # directory to store the image. - if [[ "${FLAGS_verify}" == ${FLAGS_TRUE} ]]; then - local TEMP_SUFFIX=".$(basename ${SCRIPT}).${CHIP}.$$" - local TEMP_DIR="$(mktemp -d --suffix="${TEMP_SUFFIX}")" - - IMG_READ="${TEMP_DIR}/ec.read.bin" - DELETE_LIST+=( "${TEMP_DIR}" ) - fi - fi - - # Read EC image. - if [[ -n "${IMG_READ}" ]]; then - info "Reading EC firmware image." - - local UUT_RD=( "${NPCX_UUT}" "${UUT_ARGS[@]}" \ - "--read-flash" "--file=${IMG_READ}" ) - - if [[ "${FLAGS_verbose}" == ${FLAGS_TRUE} ]]; then - echo "${UUT_RD[*]}" - fi - print_or_run timeout -k 10 -s 9 "${FLAGS_timeout}" \ - "${UUT_RD[@]}" || die "${MSG_READ_FAIL}" - fi - - # Verify the flash by comparing the source image to the read image, - # only if it was a flash write request. - if [[ -z "${FLAGS_read}" && "${FLAGS_verify}" == ${FLAGS_TRUE} ]]; then - info "Verifying EC firmware image." - - if [[ "${FLAGS_verbose}" == ${FLAGS_TRUE} ]]; then - echo "cmp -n ${IMG_SIZE} ${IMG} ${IMG_READ}" - fi - - print_or_run cmp -s -n "${IMG_SIZE}" "${IMG}" "${IMG_READ}" \ - || die "${MSG_VERIFY_FAIL}" - fi -} - -function flash_npcx_5m5g_jtag() { - flash_npcx_jtag -} - -function flash_npcx_5m6g_jtag() { - flash_npcx_jtag -} - -function flash_npcx_7m6x_jtag() { - flash_npcx_jtag -} - -function flash_npcx_7m7x_jtag() { - flash_npcx_jtag -} - -function flash_npcx_spi() { - flash_flashrom -} - -function flash_npcx_int_spi() { - flash_flashrom -} - -function flash_mec1322() { - flash_flashrom -} - -info "Using ${SERVO_TYPE}." - -# Only if it is a flash program request, call ec_image. -if [[ -z "${FLAGS_read}" ]]; then - IMG="$(ec_image)" - info "Using ${MCU} image : ${IMG}" - IMG_SIZE=$(stat -c%s "${IMG}") -fi - -if [ "${NEED_SERVO}" != "no" ] ; then - servo_save -fi - -info "Flashing chip ${CHIP}." -flash_${CHIP} -info "Flashing done." diff --git a/util/flash_fp_mcu b/util/flash_fp_mcu deleted file mode 100644 index 679478f1e2..0000000000 --- a/util/flash_fp_mcu +++ /dev/null @@ -1,750 +0,0 @@ -#!/bin/bash -# 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. - -. /usr/share/misc/shflags - -readonly DEFAULT_RETRIES=${DEFAULT_RETRIES:-4} -readonly STM32MON_CONNECT_RETRIES=${STM32MON_CONNECT_RETRIES:-6} -readonly STM32MON_SERIAL_BAUDRATE=${STM32MON_SERIAL_BAUDRATE:-115200} - -DEFINE_boolean 'read' "${FLAGS_FALSE}" 'Read instead of write' 'r' -# Both flash read and write protection are removed by default, but you -# can optionally enable them (for testing purposes). -DEFINE_boolean 'remove_flash_read_protect' "${FLAGS_TRUE}" \ - 'Remove flash read protection while performing command' 'U' -DEFINE_boolean 'remove_flash_write_protect' "${FLAGS_TRUE}" \ - 'Remove flash write protection while performing command' 'u' -DEFINE_integer 'retries' "${DEFAULT_RETRIES}" 'Specify number of retries' 'R' -DEFINE_integer 'baudrate' "${STM32MON_SERIAL_BAUDRATE}" 'Specify UART baudrate' 'B' -DEFINE_boolean 'hello' "${FLAGS_FALSE}" 'Only ping the bootloader' 'H' -DEFINE_boolean 'services' "${FLAGS_TRUE}" \ - 'Stop and restart conflicting fingerprint services' 's' -FLAGS_HELP="Usage: ${0} [flags] [ec.bin]" - -# EXIT_SUCCESS=0 -# EXIT_FAILURE=1 -# EXIT_BASHBUILTIN=2 -readonly EXIT_ARGUMENT=3 -readonly EXIT_CONFIG=4 -readonly EXIT_PRECONDITION=5 -readonly EXIT_RUNTIME=6 - -# Process commandline flags -FLAGS "${@}" || exit "${EXIT_ARGUMENT}" -eval set -- "${FLAGS_ARGV}" - -readonly CROS_EC_SPI_MODALIAS_STR="of:NcrfpTCgoogle,cros-ec-spi" - -readonly CROS_EC_UART_MODALIAS_STR="of:NcrfpTCgoogle,cros-ec-uart" - -klog() { - echo "flash_fp_mcu: $*" > /dev/kmsg -} - -check_hardware_write_protect_disabled() { - local hardware_write_protect_state - if ! hardware_write_protect_state="$(crossystem wpsw_cur)"; then - echo "Failed to get hardware write protect status" >&2 - exit "${EXIT_PRECONDITION}" - fi - if [[ "${hardware_write_protect_state}" != "0" ]]; then - echo "Please make sure hardware write protect is disabled." - echo "See https://www.chromium.org/chromium-os/firmware-porting-guide/firmware-ec-write-protection" - exit "${EXIT_PRECONDITION}" - fi -} - -# Get the spiid for the fingerprint sensor based on the modalias -# string: https://crbug.com/955117 -get_spiid() { - # TODO(b/179533783): Fix modalias on strongbad and remove this bypass. - if [[ -n "${DEVICEID}" ]]; then - echo "${DEVICEID}" - return 0 - fi - - for dev in /sys/bus/spi/devices/*; do - if [[ "$(cat "${dev}/modalias")" == "${CROS_EC_SPI_MODALIAS_STR}" ]]; then - basename "${dev}" - return 0 - fi - done - - return 1 -} - -# Get the uartid for the fingerprint sensor based on the modalias -get_uartid() { - for dev in /sys/bus/serial/devices/*; do - if [ -f "${dev}/modalias" ]; then - if [[ "$(cat "${dev}/modalias")" == "${CROS_EC_UART_MODALIAS_STR}" ]]; then - basename "${dev}" - return 0 - fi - fi - done - - return 1 -} - -# Usage: gpio <unexport|export|in|out|0|1|get> <signal> [signal...] -gpio() { - local cmd="$1" - shift - - for signal in "$@"; do - case "${cmd}" in - unexport|export) - klog "Set gpio ${signal} to ${cmd}" - echo "${signal}" > "/sys/class/gpio/${cmd}" - ;; - in|out) - local direction="${cmd}" - klog "Set gpio ${signal} direction to ${direction}" - echo "${direction}" > "/sys/class/gpio/gpio${signal}/direction" - ;; - 0|1) - local value="${cmd}" - klog "Set gpio ${signal} to ${value}" - echo "${value}" > "/sys/class/gpio/gpio${signal}/value" - ;; - get) - local value="${cmd}" - klog "Get gpio ${signal}" - cat "/sys/class/gpio/gpio${signal}/value" - ;; - *) - echo "Invalid gpio command: ${cmd}" >&2 - exit "${EXIT_RUNTIME}" - ;; - esac - done -} - -# Usage: warn_gpio <signal> <expected_value> <msg> -warn_gpio() { - local signal=$1 - local expected_value=$2 - local msg=$3 - - local value - if ! value="$(gpio get "${signal}")"; then - echo "Error fetching gpio value ${signal}" >&2 - exit "${EXIT_RUNTIME}" - fi - - if [[ "${value}" != "${expected_value}" ]]; then - echo "${msg}" >&2 - return 1 - fi -} - -# Taken verbatim from -# https://chromium.googlesource.com/chromiumos/docs/+/master/lsb-release.md#shell -# This should not be used by anything except get_platform_name. -# See https://crbug.com/98462. -lsbval() { - local key="$1" - local lsbfile="${2:-/etc/lsb-release}" - - if ! echo "${key}" | grep -Eq '^[a-zA-Z0-9_]+$'; then - return 1 - fi - - sed -E -n -e \ - "/^[[:space:]]*${key}[[:space:]]*=/{ - s:^[^=]+=[[:space:]]*:: - s:[[:space:]]+$:: - p - }" "${lsbfile}" -} - -# Get the underlying board (reference design) that we're running on (not the -# FPMCU or sensor). -# This may be an extended platform name, like nami-kernelnext, hatch-arc-r, -# or hatch-borealis. -get_platform_name() { - local platform_name - - # We used to use "cros_config /identity platform-name", but that is specific - # to mosys and does not actually provide the board name in all cases. - # cros_config intentionally does not provide a way to get the board - # name: b/156650654. - - # If there was a way to get the board name from cros_config, it's possible - # that it could fail in the following cases: - # - # 1) We're running on a non-unibuild device (the only one with FP is nocturne) - # 2) We're running on a proto device during bringup and the cros_config - # settings haven't yet been setup. - # - # In all cases we can fall back to /etc/lsb-release. It's not recommended - # to do this, but we don't have any other options in this case. - echo "Getting platform name from /etc/lsb-release." 1>&2 - platform_name="$(lsbval "CHROMEOS_RELEASE_BOARD")" - if [[ -z "${platform_name}" ]]; then - return 1 - fi - - echo "${platform_name}" -} - -# Given a full platform name, extract the base platform. -# -# Tests are also run on modified images, like hatch-arc-r, hatch-borealis, or -# hatch-kernelnext. These devices still have fingerprint and are expected to -# pass tests. The full platform name reflects these modifications and might -# be needed to apply an alternative configuration (kernelnext). Other modified -# tests (arc-r) just need to default to the base platform config, which is -# identified by this function. -# See b/186697064. -# -# Examples: -# * platform_base_name "hatch-kernelnext" --> "hatch" -# * platform_base_name "hatch-arc-r" --> "hatch" -# * platform_base_name "hatch-borealis" --> "hatch" -# * platform_base_name "hatch" --> "hatch" -# -# Usage: platform_base_name <platform_name> -platform_base_name() { - local platform_name="$1" - - # We remove any suffix starting at the first '-'. - echo "${platform_name%%-*}" -} - -get_default_fw() { - local board - board="$(cros_config /fingerprint board)" - - # If cros_config returns "", that is okay assuming there is only - # one firmware file on disk. - - local -a fws - mapfile -t fws < <(find /opt/google/biod/fw -name "${board}*.bin") - - if [[ "${#fws[@]}" -ne 1 ]]; then - return 1 - fi - - echo "${fws[0]}" -} - -# Find processes that have the named file, active or deleted, open. -# -# Deleted files are important because unbinding/rebinding cros-ec -# with biod/timberslide running will result in the processes holding open -# a deleted version of the files. Issues can arise if the process continue -# to interact with the deleted files (ex kernel panic) while the raw driver -# is being used in flash_fp_mcu. The lsof and fuser tools can't seem to -# identify usages of the deleted named file directly, without listing all -# files. This takes a large amount out time on Chromebooks, thus we need this -# custom search routine. -# -# Usage: proc_open_file [file_pattern] -proc_open_file() { - local file_pattern="$1" - - # Avoid overloading kernel max arguments with the number of file names. - local -a FDS=( /proc/*/fd/* ) - xargs ls -l <<<"${FDS[*]}" 2>/dev/null | grep "${file_pattern}" | \ - awk '{split($9,p,"/"); print "PID", p[3], "->", $11, $12}' - return "${PIPESTATUS[1]}" -} - -flash_fp_mcu_stm32() { - local transport="${1}" - local device="${2}" - local gpio_nrst="${3}" - local gpio_boot0="${4}" - local gpio_pwren="${5}" - local file="${6}" - local deviceid - - local stm32mon_flags="-p --retries ${STM32MON_CONNECT_RETRIES}" - - if [[ "${transport}" == "UART" ]]; then - stm32mon_flags+=" --baudrate ${FLAGS_baudrate} --device ${device}" - else - stm32mon_flags+=" -s ${device}" - fi - - if [[ "${FLAGS_hello}" -eq "${FLAGS_FALSE}" ]]; then - if [[ "${FLAGS_remove_flash_write_protect}" -eq "${FLAGS_TRUE}" ]]; then - stm32mon_flags+=" -u" - fi - - if [[ "${FLAGS_remove_flash_read_protect}" -eq "${FLAGS_TRUE}" ]]; then - stm32mon_flags+=" -U" - fi - - if [[ "${FLAGS_read}" -eq "${FLAGS_TRUE}" ]]; then - # Read from FPMCU to file - if [[ -e "${file}" ]]; then - echo "Output file already exists: ${file}" - return "${EXIT_PRECONDITION}" - fi - echo "# Reading to '${file}' over ${transport}" - stm32mon_flags+=" -r ${file}" - else - # Write to FPMCU from file - if [[ ! -f "${file}" ]]; then - echo "Invalid image file: ${file}" - return "${EXIT_PRECONDITION}" - fi - echo "# Flashing '${file}' over ${transport}" - stm32mon_flags+=" -e -w ${file}" - fi - else - echo "# Saying hello over ${transport}" - fi - - - check_hardware_write_protect_disabled - - if [[ "${transport}" == "UART" ]]; then - if ! deviceid="$(get_uartid)"; then - echo "Unable to find FP sensor UART device: ${CROS_EC_UART_MODALIAS_STR}" - return "${EXIT_PRECONDITION}" - fi - else - - if ! deviceid="$(get_spiid)"; then - echo "Unable to find FP sensor SPI device: ${CROS_EC_SPI_MODALIAS_STR}" - return "${EXIT_PRECONDITION}" - fi - fi - - echo "Flashing ${transport} device ID: ${deviceid}" - - # Remove cros_fp if present - klog "Unbinding cros-ec driver" - if [[ "${transport}" == "UART" ]]; then - echo "${deviceid}" > /sys/bus/serial/drivers/cros-ec-uart/unbind - else - echo "${deviceid}" > /sys/bus/spi/drivers/cros-ec-spi/unbind - fi - - # Configure the MCU Boot0 and NRST GPIOs - gpio export "${gpio_boot0}" "${gpio_nrst}" - gpio out "${gpio_boot0}" "${gpio_nrst}" - - # Reset sequence to enter bootloader mode - gpio 1 "${gpio_boot0}" - gpio 0 "${gpio_nrst}" - sleep 0.001 - - klog "Binding raw driver" - if [[ "${transport}" == "UART" ]]; then - # load AMDI0020:01 ttyS1 - echo AMDI0020:01 > /sys/bus/platform/drivers/dw-apb-uart/unbind; - echo AMDI0020:01 > /sys/bus/platform/drivers/dw-apb-uart/bind; - else - echo spidev > "/sys/bus/spi/devices/${deviceid}/driver_override" - echo "${deviceid}" > /sys/bus/spi/drivers/spidev/bind - # The following sleep is a workaround to mitigate the effects of a - # poorly behaved chip select line. See b/145023809. - fi - sleep 0.5 - - # We do not expect the drivers to change the pin state when binding. - # If you receive this warning, the driver needs to be fixed on this board - # and this flash attempt will probably fail. - warn_gpio "${gpio_boot0}" 1 \ - "WARNING: One of the drivers changed BOOT0 pin state on bind attempt." - warn_gpio "${gpio_nrst}" 0 \ - "WARNING: One of the drivers changed NRST pin state on bind attempt." - - if [[ ! -c "${device}" ]]; then - echo "Failed to bind raw device driver." >&2 - return "${EXIT_RUNTIME}" - fi - - local attempt=0 - local cmd_exit_status=1 - local cmd="stm32mon ${stm32mon_flags}" - - for attempt in $(seq "${FLAGS_retries}"); do - # Reset sequence to enter bootloader mode - gpio 0 "${gpio_nrst}" - sleep 0.01 - - # Release reset as the SPI bus is now ready - gpio 1 "${gpio_nrst}" - - # As per section '68: Bootloader timings' from application note below: - # https://www.st.com/resource/en/application_note/cd00167594-stm32-microcontroller-system-memory-boot-mode-stmicroelectronics.pdf - # bootloader startup time is 16.63 ms for STM32F74xxx/75xxx and 53.975 ms - # for STM32H74xxx/75xxx. SPI needs 1 us delay for one SPI byte sending. - # Keeping some margin, add delay of 100 ms to consider minimum bootloader - # startup time after the reset for stm32 devices. - sleep 0.1 - - # Print out the actual underlying command we're running and run it - echo "# ${cmd}" - ${cmd} - cmd_exit_status=$? - - if [[ "${cmd_exit_status}" -eq 0 ]]; then - break - fi - echo "# Attempt ${attempt} failed." - echo - sleep 1 - done - - # unload device - if [[ "${transport}" != "UART" ]]; then - klog "Unbinding raw driver" - echo "${deviceid}" > /sys/bus/spi/drivers/spidev/unbind - fi - - # Go back to normal mode - gpio out "${gpio_nrst}" - gpio 0 "${gpio_boot0}" "${gpio_nrst}" - gpio 1 "${gpio_nrst}" - - # Give up GPIO control, unless we need to keep these driving as - # outputs because they're not open-drain signals. - # TODO(b/179839337): Make this the default and properly support - # open-drain outputs on other platforms. - if [[ "${PLATFORM_NAME}" != "strongbad" ]] && - [[ "${PLATFORM_NAME}" != "herobrine" ]]; then - gpio in "${gpio_boot0}" "${gpio_nrst}" - fi - gpio unexport "${gpio_boot0}" "${gpio_nrst}" - - # Dartmonkey's RO has a flashprotect logic issue that forces reboot loops - # when SW-WP is enabled and HW-WP is disabled. It is avoided if a POR is - # detected on boot. We force a POR here to ensure we avoid this reboot loop. - # See to b/146428434. - if [[ "${gpio_pwren}" -gt 0 ]]; then - echo "Power cycling the FPMCU." - gpio export "${gpio_pwren}" - gpio out "${gpio_pwren}" - gpio 0 "${gpio_pwren}" - # Must outlast hardware soft start, which is typically ~3ms. - sleep 0.5 - gpio 1 "${gpio_pwren}" - # Power enable line is externally pulled down, so leave as output-high. - gpio unexport "${gpio_pwren}" - fi - - # Put back cros_fp driver if transport is SPI - if [[ "${transport}" != "UART" ]]; then - # wait for FP MCU to come back up (including RWSIG delay) - sleep 2 - klog "Binding cros-ec driver" - echo "" > "/sys/bus/spi/devices/${deviceid}/driver_override" - echo "${deviceid}" > /sys/bus/spi/drivers/cros-ec-spi/bind - fi - - if [[ "${cmd_exit_status}" -ne 0 ]]; then - return "${EXIT_RUNTIME}" - fi - - # Inform user to reboot if transport is UART. - # Display fw version is transport is SPI - if [[ "${transport}" == "UART" ]]; then - echo "Please reboot this device." - else - # Test it - klog "Query version and reset flags" - ectool --name=cros_fp version - ectool --name=cros_fp uptimeinfo - fi -} - -config_hatch() { - readonly TRANSPORT="SPI" - readonly DEVICE="/dev/spidev1.1" - # See - # third_party/coreboot/src/soc/intel/cannonlake/include/soc/gpio_soc_defs.h - # for pin name to number mapping. - # Examine `cat /sys/kernel/debug/pinctrl/INT34BB:00/gpio-ranges` on a hatch - # device to determine gpio number from pin number. - readonly GPIO_CHIP="gpiochip200" - # FPMCU RST_ODL is on GPP_A12 = 200 + 12 = 212 - readonly GPIO_NRST=212 - # FPMCU BOOT0 is on GPP_A22 = 200 + 22 = 222 - readonly GPIO_BOOT0=222 - # FP_PWR_EN is on GPP_C11 = 456 + (192 - 181) = 456 + 11 = 467 - readonly GPIO_PWREN=467 -} - -config_herobrine() { - readonly TRANSPORT="SPI" - readonly DEVICE="/dev/spidev11.0" - # TODO(b/179533783): Fix this script to look for non-ACPI modalias - readonly DEVICEID="spi11.0" - - readonly GPIO_CHIP="gpiochip336" - # FPMCU RST_ODL is $(gpiofind FP_RST_L) is gpiochip0 78 - readonly GPIO_NRST=$((336 + $(gpiofind FP_RST_L|cut -f2 -d" "))) - # FPMCU BOOT0 is $(gpiofind FPMCU_BOOT0) is gpiochip0 77 - readonly GPIO_BOOT0=$((336 + $(gpiofind FPMCU_BOOT0|cut -f2 -d" "))) - # EN FP RAILS is $(gpiofind EN_FP_RAILS) is gpiochip0 42 - readonly GPIO_PWREN=$((336 + $(gpiofind EN_FP_RAILS|cut -f2 -d" "))) -} - -config_nami() { - readonly TRANSPORT="SPI" - readonly DEVICE="/dev/spidev32765.0" - - readonly GPIO_CHIP="gpiochip360" - # FPMCU RST_ODL is on GPP_C9 = 360 + 57 = 417 - readonly GPIO_NRST=417 - # FPMCU BOOT0 is on GPP_D5 = 360 + 77 = 437 - readonly GPIO_BOOT0=437 - # FP_PWR_EN is on GPP_B11 = 360 + 35 = 395 - readonly GPIO_PWREN=395 -} - -config_nami-kernelnext() { - readonly TRANSPORT="SPI" - readonly DEVICE="/dev/spidev1.0" - - readonly GPIO_CHIP="gpiochip360" - # FPMCU RST_ODL is on GPP_C9 = 360 + 57 = 417 - readonly GPIO_NRST=417 - # FPMCU BOOT0 is on GPP_D5 = 360 + 77 = 437 - readonly GPIO_BOOT0=437 - # FP_PWR_EN is on GPP_B11 = 360 + 35 = 395 - readonly GPIO_PWREN=395 -} - -config_nocturne() { - readonly TRANSPORT="SPI" - readonly DEVICE="/dev/spidev32765.0" - - readonly GPIO_CHIP="gpiochip360" - # FPMCU RST_ODL is on GPP_C10 = 360 + 58 = 418 - readonly GPIO_NRST=418 - # FPMCU BOOT0 is on GPP_C8 = 360 + 56 = 416 - readonly GPIO_BOOT0=416 - # FP_PWR_EN is on GPP_A11 = 360 + 11 = 371 - readonly GPIO_PWREN=371 -} - -config_nocturne-kernelnext() { - readonly TRANSPORT="SPI" - readonly DEVICE="/dev/spidev1.0" - - readonly GPIO_CHIP="gpiochip360" - # FPMCU RST_ODL is on GPP_C10 = 360 + 58 = 418 - readonly GPIO_NRST=418 - # FPMCU BOOT0 is on GPP_C8 = 360 + 56 = 416 - readonly GPIO_BOOT0=416 - # FP_PWR_EN is on GPP_A11 = 360 + 11 = 371 - readonly GPIO_PWREN=371 -} - -config_strongbad() { - readonly TRANSPORT="SPI" - readonly DEVICE="/dev/spidev10.0" - # TODO(b/179533783): Fix modalias on strongbad and remove this bypass. - readonly DEVICEID="spi10.0" - - readonly GPIO_CHIP="gpiochip392" - # FPMCU RST_ODL is $(gpiofind FP_RST_L) is gpiochip0 22 - readonly GPIO_NRST=$((392 + $(gpiofind FP_RST_L|cut -f2 -d" "))) - # FPMCU BOOT0 is $(gpiofind FPMCU_BOOT0) is gpiochip0 10 - readonly GPIO_BOOT0=$((392 + $(gpiofind FPMCU_BOOT0|cut -f2 -d" "))) - # TODO(b/179839337): Hardware currently doesn't support PWREN, but the - # next revision will. Add a comment here about the power enable gpio. - readonly GPIO_PWREN=-1 -} - -config_volteer() { - readonly TRANSPORT="SPI" - readonly DEVICE="/dev/spidev1.0" - - # See kernel/v5.4/drivers/pinctrl/intel/pinctrl-tigerlake.c - # for pin name and pin number. - # Examine `cat /sys/kernel/debug/pinctrl/INT34C5:00/gpio-ranges` on a - # volteer device to determine gpio number from pin number. - # For example: GPP_C23 is UART2_CTS which can be queried from EDS - # the pin number is 194. From the gpio-ranges, the gpio value is - # 408 + (194-171) = 431 - - readonly GPIO_CHIP="gpiochip152" - # FPMCU RST_ODL is on GPP_C23 = 408 + (194 - 171) = 431 - readonly GPIO_NRST=431 - # FPMCU BOOT0 is on GPP_C22 = 408 + (193 - 171) = 430 - readonly GPIO_BOOT0=430 - # FP_PWR_EN is on GPP_A21 = 216 + (63 - 42) = 237 - readonly GPIO_PWREN=237 -} - -config_brya() { - readonly TRANSPORT="SPI" - readonly DEVICE="/dev/spidev0.0" - - # See kernel/v5.10/drivers/pinctrl/intel/pinctrl-tigerlake.c - # for pin name and pin number. - # Examine `cat /sys/kernel/debug/pinctrl/INTC1055:00/gpio-ranges` on a - # brya device to determine gpio number from pin number. - # For example: GPP_D1 is ISH_GP_1 which can be queried from EDS - # the pin number is 100 from the pinctrl-tigerlake.c. - # From the gpio-ranges, the gpio value is 312 + (100-99) = 313 - - readonly GPIO_CHIP="gpiochip152" - # FPMCU RST_ODL is on GPP_D1 = 312 + (100 - 99) = 313 - readonly GPIO_NRST=313 - # FPMCU BOOT0 is on GPP_D0 = 312 + (99 - 99) = 312 - readonly GPIO_BOOT0=312 - # FP_PWR_EN is on GPP_D2 = 312 + (101 - 99) = 314 - readonly GPIO_PWREN=314 -} - -config_zork() { - readonly TRANSPORT="UART" - readonly DEVICE="/dev/ttyS1" - - readonly GPIO_CHIP="gpiochip256" - # FPMCU RST_ODL is on AGPIO 11 = 256 + 11 = 267 - readonly GPIO_NRST=267 - # FPMCU BOOT0 is on AGPIO 69 = 256 + 69 = 325 - readonly GPIO_BOOT0=325 - # FPMCU PWR_EN is on AGPIO 32 = 256 + 32 = 288, but should not be - # necessary for flashing. Set invalid value. - readonly GPIO_PWREN=-1 -} - -config_guybrush() { - readonly TRANSPORT="UART" - - readonly DEVICE="/dev/ttyS1" - - readonly GPIO_CHIP="gpiochip256" - # FPMCU RST_ODL is on AGPIO 11 = 256 + 11 = 267 - readonly GPIO_NRST=267 - # FPMCU BOOT0 is on AGPIO 144 = 256 + 144 = 400 - readonly GPIO_BOOT0=400 - # FPMCU PWR_EN is on AGPIO 32 = 256 + 32 = 288, but should not be - # necessary for flashing. Set invalid value. - readonly GPIO_PWREN=-1 -} - -main() { - local filename="$1" - - # print out canonical path to differentiate between /usr/local/bin and - # /usr/bin installs - readlink -f "$0" - - # The "platform name" corresponds to the underlying board (reference design) - # that we're running on (not the FPMCU or sensor). At the moment all of the - # reference designs use the same GPIOs. If for some reason a design differs in - # the future, we will want to add a nested check in the config_<platform_name> - # function. Doing it in this manner allows us to reduce the number of - # configurations that we have to maintain (and reduces the amount of testing - # if we're only updating a specific config_<platform_name>). - if ! PLATFORM_NAME="$(get_platform_name)"; then - echo "Failed to get platform name" - exit "${EXIT_CONFIG}" - fi - readonly PLATFORM_NAME - - if ! PLATFORM_BASE_NAME="$(platform_base_name "${PLATFORM_NAME}")"; then - echo "Failed to get platform base name" - exit "${EXIT_CONFIG}" - fi - readonly PLATFORM_BASE_NAME - - echo "Platform name is ${PLATFORM_NAME} (${PLATFORM_BASE_NAME})." - - # Check that the config function exists - if [[ "$(type -t "config_${PLATFORM_NAME}")" == "function" ]]; then - readonly PLATFORM_CONFIG="${PLATFORM_NAME}" - elif [[ "$(type -t "config_${PLATFORM_BASE_NAME}")" == "function" ]]; then - readonly PLATFORM_CONFIG="${PLATFORM_BASE_NAME}" - else - echo "No config for platform ${PLATFORM_NAME}." >&2 - exit "${EXIT_CONFIG}" - fi - - echo "Using config for ${PLATFORM_CONFIG}." - - if ! "config_${PLATFORM_CONFIG}"; then - echo "Configuration failed for platform ${PLATFORM_CONFIG}." >&2 - exit "${EXIT_CONFIG}" - fi - - # Help the user out with defaults, if no *file* was given. - if [[ "$#" -eq 0 ]]; then - # If we are actually reading, set to a timestamped temp file. - if [[ "${FLAGS_read}" -eq "${FLAGS_TRUE}" ]]; then - filename="/tmp/fpmcu-fw-$(date --iso-8601=seconds).bin" - else - # Assume we are "writing" the default firmware to the FPMCU. - if ! filename="$(get_default_fw)"; then - echo "Failed to identify a default firmware file" >&2 - exit "${EXIT_CONFIG}" - fi - fi - fi - - # Check that the gpiochip exists - if [[ ! -e "/sys/class/gpio/${GPIO_CHIP}" ]]; then - echo "Cannot find GPIO chip: ${GPIO_CHIP}" - exit "${EXIT_CONFIG}" - fi - - if [[ "${FLAGS_services}" -eq "${FLAGS_TRUE}" ]]; then - echo "# Stopping biod and timberslide" - stop biod - stop timberslide LOG_PATH=/sys/kernel/debug/cros_fp/console_log - fi - - # If cros-ec driver isn't bound on startup, this means the final rebinding - # may fail. - if [[ ! -c "/dev/cros_fp" ]]; then - echo "WARNING: The cros-ec driver was not bound on startup." >&2 - fi - if [[ -c "${DEVICE}" ]]; then - echo "WARNING: The raw driver was bound on startup." >&2 - fi - local files_open - # Ensure no processes have cros_fp device or debug device open. - # This might be biod and/or timberslide. - if files_open=$(proc_open_file "/dev/cros_fp\|/sys/kernel/debug/cros_fp/*") - then - echo "WARNING: Another process has a cros_fp device file open." >&2 - echo "${files_open}" >&2 - echo "Try 'stop biod' and" >&2 - echo "'stop timberslide LOG_PATH=/sys/kernel/debug/cros_fp/console_log'" >&2 - echo "before running this script." >&2 - echo "See b/188985272." >&2 - fi - # Ensure no processes are using the raw driver. This might be a wedged - # stm32mon process spawned by this script. - if files_open=$(proc_open_file "${DEVICE}"); then - echo "WARNING: Another process has ${DEVICE} open." >&2 - echo "${files_open}" >&2 - echo "Try 'fuser -k ${DEVICE}' before running this script." >&2 - echo "See b/188985272." >&2 - fi - - local ret - flash_fp_mcu_stm32 \ - "${TRANSPORT}" \ - "${DEVICE}" \ - "${GPIO_NRST}" \ - "${GPIO_BOOT0}" \ - "${GPIO_PWREN}" \ - "${filename}" - ret=$? - - if [[ "${FLAGS_services}" -eq "${FLAGS_TRUE}" ]]; then - echo "# Restarting biod and timberslide" - start timberslide LOG_PATH=/sys/kernel/debug/cros_fp/console_log - start biod - fi - - exit "${ret}" -} - -main "$@" diff --git a/util/flash_jlink.py b/util/flash_jlink.py deleted file mode 100755 index d2fd4dec15..0000000000 --- a/util/flash_jlink.py +++ /dev/null @@ -1,208 +0,0 @@ -#!/usr/bin/env python3 - -# Copyright 2020 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. - -"""Flashes firmware using Segger J-Link. - -This script requires Segger hardware attached via JTAG/SWD. - -See -https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/docs/fingerprint/fingerprint-debugging.md#flash -for instructions. -""" - -import argparse -import logging -import os -import shutil -import socket -import subprocess -import sys -import tempfile -import time - - -DEFAULT_SEGGER_REMOTE_PORT = 19020 - -# Commands are documented here: https://wiki.segger.com/J-Link_Commander -JLINK_COMMANDS = ''' -exitonerror 1 -r -loadfile {FIRMWARE} {FLASH_ADDRESS} -r -go -exit -''' - - -class BoardConfig: - def __init__(self, interface, device, flash_address): - self.interface = interface - self.device = device - self.flash_address = flash_address - - -SWD_INTERFACE = 'SWD' -STM32_DEFAULT_FLASH_ADDRESS = '0x8000000' -DRAGONCLAW_CONFIG = BoardConfig(interface=SWD_INTERFACE, device='STM32F412CG', - flash_address=STM32_DEFAULT_FLASH_ADDRESS) -ICETOWER_CONFIG = BoardConfig(interface=SWD_INTERFACE, device='STM32H743ZI', - flash_address=STM32_DEFAULT_FLASH_ADDRESS) - -BOARD_CONFIGS = { - 'dragonclaw': DRAGONCLAW_CONFIG, - 'bloonchipper': DRAGONCLAW_CONFIG, - 'nucleo-f412zg': DRAGONCLAW_CONFIG, - 'dartmonkey': ICETOWER_CONFIG, - 'icetower': ICETOWER_CONFIG, - 'nucleo-dartmonkey': ICETOWER_CONFIG, - 'nucleo-h743zi': ICETOWER_CONFIG, -} - - -def is_tcp_port_open(host: str, tcp_port: int) -> bool: - """Checks if the TCP host port is open.""" - - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - sock.settimeout(2) # 2 Second Timeout - try: - sock.connect((host, tcp_port)) - sock.shutdown(socket.SHUT_RDWR) - except ConnectionRefusedError: - return False - except socket.timeout: - return False - finally: - sock.close() - # Other errors are propagated as odd exceptions. - - # We shutdown and closed the connection, but the server may need a second - # to start listening again. If the following error is seen, this timeout - # should be increased. 300ms seems to be the minimum. - # - # Connecting to J-Link via IP...FAILED: Can not connect to J-Link via \ - # TCP/IP (127.0.0.1, port 19020) - time.sleep(0.5) - return True - - -def create_jlink_command_file(firmware_file, config): - tmp = tempfile.NamedTemporaryFile() - tmp.write(JLINK_COMMANDS.format(FIRMWARE=firmware_file, - FLASH_ADDRESS=config.flash_address).encode( - 'utf-8')) - tmp.flush() - return tmp - - -def flash(jlink_exe, remote, device, interface, cmd_file): - cmd = [ - jlink_exe, - ] - - if remote: - logging.debug(f'Connecting to J-Link over TCP/IP {remote}.') - remote_components = remote.split(':') - if len(remote_components) not in [1, 2]: - logging.debug(f'Given remote "{remote}" is malformed.') - return 1 - - host = remote_components[0] - try: - ip = socket.gethostbyname(host) - except socket.gaierror as e: - logging.error(f'Failed to resolve host "{host}": {e}.') - return 1 - logging.debug(f'Resolved {host} as {ip}.') - port = DEFAULT_SEGGER_REMOTE_PORT - - if len(remote_components) == 2: - try: - port = int(remote_components[1]) - except ValueError: - logging.error( - f'Given remote port "{remote_components[1]}" is malformed.') - return 1 - - remote = f'{ip}:{port}' - - logging.debug(f'Checking connection to {remote}.') - if not is_tcp_port_open(ip, port): - logging.error( - f'JLink server doesn\'t seem to be listening on {remote}.') - logging.error('Ensure that JLinkRemoteServerCLExe is running.') - return 1 - cmd.extend(['-ip', remote]) - - cmd.extend([ - '-device', device, - '-if', interface, - '-speed', 'auto', - '-autoconnect', '1', - '-CommandFile', cmd_file, - ]) - logging.debug('Running command: "%s"', ' '.join(cmd)) - completed_process = subprocess.run(cmd) - logging.debug('JLink return code: %d', completed_process.returncode) - return completed_process.returncode - - -def main(argv: list): - - parser = argparse.ArgumentParser() - - default_jlink = './JLink_Linux_V684a_x86_64/JLinkExe' - if shutil.which(default_jlink) is None: - default_jlink = 'JLinkExe' - parser.add_argument( - '--jlink', '-j', - help='JLinkExe path (default: ' + default_jlink + ')', - default=default_jlink) - - parser.add_argument( - '--remote', '-n', - help='Use TCP/IP host[:port] to connect to a J-Link or ' - 'JLinkRemoteServerCLExe. If unspecified, connect over USB.') - - default_board = 'bloonchipper' - parser.add_argument( - '--board', '-b', - help='Board (default: ' + default_board + ')', - default=default_board) - - default_firmware = os.path.join('./build', default_board, 'ec.bin') - parser.add_argument( - '--image', '-i', - help='Firmware binary (default: ' + default_firmware + ')', - default=default_firmware) - - log_level_choices = ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'] - parser.add_argument( - '--log_level', '-l', - choices=log_level_choices, - default='DEBUG' - ) - - args = parser.parse_args(argv) - logging.basicConfig(level=args.log_level) - - if args.board not in BOARD_CONFIGS: - logging.error('Unable to find a config for board: "%s"', args.board) - sys.exit(1) - - config = BOARD_CONFIGS[args.board] - - args.image = os.path.realpath(args.image) - args.jlink = args.jlink - - cmd_file = create_jlink_command_file(args.image, config) - ret_code = flash(args.jlink, args.remote, config.device, config.interface, - cmd_file.name) - cmd_file.close() - return ret_code - - -if __name__ == '__main__': - sys.exit(main(sys.argv[1:])) diff --git a/util/fptool.py b/util/fptool.py deleted file mode 100755 index 9c59c1014c..0000000000 --- a/util/fptool.py +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/env python3 -# Copyright 2021 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. - -"""A tool to manage the fingerprint system on Chrome OS.""" - -import argparse -import os -import shutil -import subprocess -import sys - - -def cmd_flash(args: argparse.Namespace) -> int: - """ - Flash the entire firmware FPMCU using the native bootloader. - - This requires the Chromebook to be in dev mode with hardware write protect - disabled. - """ - - if not shutil.which('flash_fp_mcu'): - print('Error - The flash_fp_mcu utility does not exist.') - return 1 - - cmd = ['flash_fp_mcu'] - if args.image: - if not os.path.isfile(args.image): - print(f'Error - image {args.image} is not a file.') - return 1 - cmd.append(args.image) - - print(f'Running {" ".join(cmd)}.') - sys.stdout.flush() - p = subprocess.run(cmd) - return p.returncode - - -def main(argv: list) -> int: - parser = argparse.ArgumentParser(description=__doc__) - subparsers = parser.add_subparsers(dest='subcommand', title='subcommands') - # This method of setting required is more compatible with older python. - subparsers.required = True - - # Parser for "flash" subcommand. - parser_decrypt = subparsers.add_parser('flash', help=cmd_flash.__doc__) - parser_decrypt.add_argument( - 'image', nargs='?', help='Path to the firmware image') - parser_decrypt.set_defaults(func=cmd_flash) - opts = parser.parse_args(argv) - return opts.func(opts) - - -if __name__ == '__main__': - sys.exit(main(sys.argv[1:])) diff --git a/util/gdbinit b/util/gdbinit deleted file mode 100644 index ff71e4c39c..0000000000 --- a/util/gdbinit +++ /dev/null @@ -1,219 +0,0 @@ -# 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. - -# This file is intended to be used as a .gdbinit for an EC debugging session. -# It defines some useful functions for analyzing the EC state. -# -# Setup Automatic Import: -# ln -s util/gdbinit .gdbinit -# -# Environment Variables: -# BOARD=[nocturne_fp|bloonchipper|...] -# GDBSERVER=[segger|openocd] -# GDBPORT=[gdb-server-port-number] -# -# Warning, this is a working collection that is not guaranteed to function -# properly on all platforms. The ec-tasks functions is a good example of a -# function that works well on most simple platforms, but may have issues on -# platforms with data cache enabled. -# -# Note, this file must maintain space indention to allow easy copy/paste -# while in active debugging. Using tabs interferes with the embedded python -# during copy/paste. - -##################################################################### -# Environment Setup and Initialization # -##################################################################### - -set verbose on - -# Start of python code - -# Setup environment and pull in object files for the particular BOARD. -# This requires setting the environment variables mentioned above. -python -import distutils.util -import os - -BOARD = os.getenv('BOARD', '') -GDBSERVER = os.getenv('GDBSERVER', 'openocd') -USING_CLION = distutils.util.strtobool(os.getenv('USING_CLION', 'FALSE')) -# BIN_NAME can be changed to be the name of a unit test, such as "sha256" -BIN_NAME = os.getenv('BIN_NAME', 'ec') - -BIN_DIR = '' -if BIN_NAME != 'ec': - BIN_DIR = BIN_NAME - -if GDBSERVER == "openocd": - DEFAULT_GDB_PORT = '3333' -else: - DEFAULT_GDB_PORT = '2331' - -GDBPORT = os.getenv('GDBPORT', DEFAULT_GDB_PORT) - -EC_DIR = os.getenv('EC_DIR', os.path.join(os.getenv('HOME'), - 'chromiumos/src/platform/ec')) - -if not os.path.isdir(EC_DIR): - print('Error - EC_DIR "' + EC_DIR + '" doesn\'t exist. Aborting.') - gdb.execute('quit') - -# Monitor commands must be run after connecting to the remote target -# See https://stackoverflow.com/a/39828850 -# https://youtrack.jetbrains.com/issue/CPP-7322 -# https://sourceware.org/gdb/onlinedocs/gdb/Hooks.html -post_remote_hook=''' -define target hookpost-remote - echo \ Flashing EC binary - load {EC_DIR}/build/{BOARD}/{BIN_DIR}/{BIN_NAME}.obj - echo \ Resetting target - monitor reset - echo \ Setting breakpoint on main - b main -end\n -'''.format(BOARD=BOARD, EC_DIR=EC_DIR, BIN_DIR=BIN_DIR, BIN_NAME=BIN_NAME) - -gdb.execute('set $BOARD = "%s"'%BOARD) -gdb.execute('set $GDBSERVER = "%s"'%GDBSERVER) -gdb.execute('set $GDBPORT = "%s"'%GDBPORT) - -build = os.path.join(EC_DIR, 'build', BOARD) -if BOARD != "": - if not os.path.isdir(build): - print('Error - Build path "' + build + '" doesn\'t exist. Aborting.') - gdb.execute('quit') - - # When using gdb from CLion, this kills gdb. - if not USING_CLION: - gdb.execute('file ' + os.path.join(build, 'ec.obj')) - gdb.execute('add-symbol-file ' + os.path.join(build, BIN_DIR, 'RO', BIN_NAME + '.RO.elf')) - gdb.execute('add-symbol-file ' + os.path.join(build, BIN_DIR, 'RW', BIN_NAME + '.RW.elf')) - -if GDBSERVER == "openocd": - gdb.execute('set $GDBSERVER_OPENOCD = 1') - gdb.execute('set $GDBSERVER_SEGGER = 0') -elif GDBSERVER == "segger": - gdb.execute('set $GDBSERVER_OPENOCD = 0') - gdb.execute('set $GDBSERVER_SEGGER = 1') - gdb.execute(post_remote_hook) -else: - print('Error - GDBSERVER="' + GDBSERVER + '" is invalid.') - gdb.execute('quit') - -# End of python code -end - -# OpenOCD specific config -if $GDBSERVER_OPENOCD - # Don't auto choose hw/sw breakpoints from memory-map - set breakpoint auto-hw off -end - -# Segger specific config -if $GDBSERVER_SEGGER - # If enabled, disable flash breakpoints. - #monitor flash breakpoints = 0 -end - -# If enabled, force breakpoints to be inserted at all times. -# They will not be reinserted on reconnects. -#set breakpoint always-inserted on - -##################################################################### -# Helper Functions # -##################################################################### - -# Usage: ec-reg32 <address> [offset] -# Read a 32 bit register -define ec-reg32 - set $a = $arg0 - if $argc > 1 - set $a += $arg1 - end - set $v = *((uint32_t *)$a) - print $v - print /x $v - print /t $v -end -alias reg32 = ec-reg32 - -# Usage: ec-connect -# Issue the overly long target connect command using the -# specified gdb server port. -define ec-connect -python -# May want to only use "target remote". -gdb.execute(f'target extended-remote :{GDBPORT}') -end -end -alias connect = ec-connect - -# Usage: ec-reset -# Issue the reset sequence for the debugger to halt on boot. -define ec-reset - if $GDBSERVER_OPENOCD - monitor halt - monitor reset halt - else - monitor halt - monitor reset - end -end -alias reset = ec-reset - -# Usage: ec-tasks -# Prints out information about current EC task set and tries to determine -# if the task's stack has been overrun. -# This function may not work properly if MCU data cache is enabled. -define ec-tasks - set $taskid_cur = current_task - tasks - set $id = 0 - set $taskcount = sizeof(tasks)/sizeof(tasks[0]) - printf "Task Ready Name Events Time (s) StkUsed\n" - while $id < $taskcount - set $is_ready = (tasks_ready & (1<<$id)) ? 'R' : ' ' - set $unused = (uint32_t)0xdeadd00d - set $stacksize = tasks_init[$id].stack_size - set $stackused = $stacksize - set $s = tasks[$id].stack - while $s < (uint32_t *)tasks[$id].sp && *$s == $unused - set $stackused -= sizeof(uint32_t) - set $s++ - end - printf "%4d %-5c %-16s %08x %11.6ld %3d/%3d", $id, $is_ready, task_names[$id], tasks[$id].events, tasks[$id].runtime, $stackused, tasks_init[$id].stack_size - if $stackused == $stacksize - printf "\t [overrun]" - end - if $id == $taskid_cur - printf "\t*" - end - printf "\n" - set $id++ - end - if $taskid_cur == scratchpad - printf "Current task is set to scratchpad\n" - end -end - -# Usage: ec-stayro -# Adds magic breakpoint that changes the outcome of the RW signature -# validation step that forces the MCU to stay in the RO section. -# This function needs improvements to not be dependent on line numbers. -define ec-stayro - break common/rwsig.c:282 - commands - set evt = 1 - printf "Continuing as RO\n" - continue - end -end - -# Usage: ec-brexception -# Set breakpoints on EC exception handlers. -define ec-brexception - break exception_panic - break bus_fault_handler - break panic_assert_fail -end diff --git a/util/gen_emmc_transfer_data.c b/util/gen_emmc_transfer_data.c deleted file mode 100644 index 98417beb9b..0000000000 --- a/util/gen_emmc_transfer_data.c +++ /dev/null @@ -1,158 +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. - * - * Generate transferring data from a file. The transferring data emulates the - * eMMC protocol. - */ - -#include <err.h> -#include <errno.h> -#include <getopt.h> -#include <stdint.h> -#include <stdio.h> -#include <string.h> - -#include <compile_time_macros.h> - -/* eMMC transfer block size */ -#define BLOCK_SIZE 512 -#define BLOCK_RAW_DATA "bootblock_raw_data" - -uint16_t crc16_arg(uint8_t data, uint16_t previous_crc) -{ - unsigned int crc = previous_crc << 8; - int i; - - crc ^= (data << 16); - for (i = 8; i; i--) { - if (crc & 0x800000) - crc ^= (0x11021 << 7); - crc <<= 1; - } - - return (uint16_t)(crc >> 8); -} - -void header_format(FILE *fin, FILE *fout) -{ - uint8_t data[BLOCK_SIZE]; - int blk, j; - uint16_t crc16; - size_t cnt = 0; - - fprintf(fout, "/* This file is auto-generated. Do not modify. */\n" - "#ifndef __CROS_EC_BOOTBLOCK_DATA_H\n" - "#define __CROS_EC_BOOTBLOCK_DATA_H\n" - "\n" - "#include <stdint.h>\n" - "\n" - ); - - fprintf(fout, - "static const uint8_t %s[] __attribute__((aligned(4))) =\n" - "{\n" - "\t0xff, 0x97, /* Acknowledge boot mode: 1 S=0 010 E=1 11 */\n" - "\t0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\n", - BLOCK_RAW_DATA); - - for (blk = 0;; blk++) { - crc16 = 0; - if (fin) - cnt = fread(data, 1, BLOCK_SIZE, fin); - - if (cnt == 0) - break; - else if (cnt < BLOCK_SIZE) - memset(&data[cnt], 0xff, BLOCK_SIZE-cnt); - - fprintf(fout, "\t/* Block %d (%ld) */\n", blk, cnt); - fprintf(fout, "\t0xff, 0xfe, /* idle, start bit. */"); - for (j = 0; j < sizeof(data); j++) { - fprintf(fout, "%s0x%02x,", - (j % 8) == 0 ? "\n\t" : " ", data[j]); - crc16 = crc16_arg(data[j], crc16); - } - fprintf(fout, "\n"); - - fprintf(fout, "\t0x%02x, 0x%02x, 0xff," - " /* CRC, end bit, idle */\n", - crc16 >> 8, crc16 & 0xff); - } - - fprintf(fout, "\t/* Last block: idle */\n"); - fprintf(fout, "\t0xff, 0xff, 0xff, 0xff\n"); - fprintf(fout, "};\n"); - fprintf(fout, "#endif /* __CROS_EC_BOOTBLOCK_DATA_H */\n"); -} - -int main(int argc, char **argv) -{ - int nopt; - int ret = 0; - const char *output_name = NULL; - char *input_name = NULL; - FILE *fin = NULL; - FILE *fout = NULL; - - const char short_opts[] = "i:ho:"; - const struct option long_opts[] = { - { "input", 1, NULL, 'i' }, - { "help", 0, NULL, 'h' }, - { "out", 1, NULL, 'o' }, - { NULL } - }; - const char usage[] = "USAGE: %s [-i <input>] -o <output>\n"; - - while ((nopt = getopt_long(argc, argv, short_opts, long_opts, - NULL)) != -1) { - switch (nopt) { - case 'i': /* -i or --input*/ - input_name = optarg; - break; - case 'h': /* -h or --help */ - fprintf(stdout, usage, argv[0]); - return 0; - case 'o': /* -o or --out */ - output_name = optarg; - break; - default: /* Invalid parameter. */ - fprintf(stderr, usage, argv[0]); - return 1; - } - } - - if (output_name == NULL) { - fprintf(stderr, usage, argv[0]); - return 1; - } - - if (input_name == NULL) { - printf("No bootblock provided, outputting default file.\n"); - } else { - fin = fopen(input_name, "r"); - if (!fin) { - printf("Cannot open input file: %s\n", input_name); - ret = 1; - goto out; - } - } - - fout = fopen(output_name, "w"); - - if (!fout) { - printf("Cannot open output file: %s\n", output_name); - ret = 1; - goto out; - } - - header_format(fin, fout); - - fclose(fout); - -out: - if (fin) - fclose(fin); - - return ret; -} diff --git a/util/gen_ipi_table.c b/util/gen_ipi_table.c deleted file mode 100644 index 07a3a39be0..0000000000 --- a/util/gen_ipi_table.c +++ /dev/null @@ -1,58 +0,0 @@ -/* 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. - * - * Generate IPI tables, and inputs come from IPI_COUNT macro in board.h. - */ - -#include <stdio.h> - -/* Prevent from including gpio configs . */ -#define __ASSEMBLER__ - -#include "board.h" - -#define FPRINTF(format, args...) fprintf(fout, format, ## args) - -int main(int argc, char **argv) -{ - FILE *fout; - int i; - - if (argc != 2) { - fprintf(stderr, "USAGE: %s <output>\n", argv[0]); - return 1; - } - - fout = fopen(argv[1], "w"); - - if (!fout) { - fprintf(stderr, "Cannot open output file %s\n", argv[1]); - return 1; - } - - FPRINTF("/* This is a generated file. Do not modify. */\n"); - FPRINTF("\n"); - FPRINTF("/*\n"); - FPRINTF(" * Table to hold all the IPI handler function pointer.\n"); - FPRINTF(" */\n"); - FPRINTF("table(ipi_handler_t, ipi_handler_table,\n"); - - for (i = 0; i < IPI_COUNT; ++i) - FPRINTF("ipi_x_func(handler, ipi_arguments, %d)\n", i); - - FPRINTF(");\n"); - - FPRINTF("/*\n"); - FPRINTF(" * Table to hold all the wake-up bool address.\n"); - FPRINTF(" */\n"); - FPRINTF("table(int *, ipi_wakeup_table,\n"); - - for (i = 0; i < IPI_COUNT; ++i) - FPRINTF("ipi_x_var(wakeup, %d)\n", i); - - FPRINTF(");\n"); - - fclose(fout); - return 0; -} diff --git a/util/gen_touchpad_hash.c b/util/gen_touchpad_hash.c deleted file mode 100644 index e03c4638f3..0000000000 --- a/util/gen_touchpad_hash.c +++ /dev/null @@ -1,174 +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 <err.h> -#include <getopt.h> -#include <stdio.h> -#include <stdint.h> -#include <string.h> -#include <unistd.h> - -#include <openssl/sha.h> - -#include "config.h" - -static void print_hex(FILE *out, uint8_t *digest, int len, int last) -{ - int i; - - fputs("{ ", out); - for (i = 0; i < len; i++) - fprintf(out, "0x%02x, ", digest[i]); - - fprintf(out, "}%c\n", last ? ';' : ','); -} - -/* Output blank hashes */ -static int hash_fw_blank(FILE *hashes) -{ - uint8_t digest[SHA256_DIGEST_LENGTH] = { 0 }; - int len; - - fprintf(hashes, "const uint8_t touchpad_fw_hashes[%d][%d] = {\n", - CONFIG_TOUCHPAD_VIRTUAL_SIZE / CONFIG_UPDATE_PDU_SIZE, - SHA256_DIGEST_LENGTH); - for (len = 0; len < CONFIG_TOUCHPAD_VIRTUAL_SIZE; - len += CONFIG_UPDATE_PDU_SIZE) { - print_hex(hashes, digest, sizeof(digest), 0); - } - fputs("};\n", hashes); - - fprintf(hashes, "const uint8_t touchpad_fw_full_hash[%d] =\n\t", - SHA256_DIGEST_LENGTH); - print_hex(hashes, digest, SHA256_DIGEST_LENGTH, 1); - - return 0; -} - -static int hash_fw(FILE *tp_fw, FILE *hashes) -{ - uint8_t buffer[CONFIG_UPDATE_PDU_SIZE]; - int len = 0; - int rb; - SHA256_CTX ctx; - SHA256_CTX ctx_all; - uint8_t digest[SHA256_DIGEST_LENGTH]; - - SHA256_Init(&ctx_all); - fprintf(hashes, "const uint8_t touchpad_fw_hashes[%d][%d] = {\n", - CONFIG_TOUCHPAD_VIRTUAL_SIZE / CONFIG_UPDATE_PDU_SIZE, - SHA256_DIGEST_LENGTH); - while (1) { - rb = fread(buffer, 1, sizeof(buffer), tp_fw); - len += rb; - - if (rb == 0) - break; - - /* Calculate hash for the block. */ - SHA256_Init(&ctx); - SHA256_Update(&ctx, buffer, rb); - SHA256_Final(digest, &ctx); - - SHA256_Update(&ctx_all, buffer, rb); - - print_hex(hashes, digest, sizeof(digest), 0); - - if (rb < sizeof(buffer)) - break; - } - fputs("};\n", hashes); - - SHA256_Final(digest, &ctx_all); - fprintf(hashes, "const uint8_t touchpad_fw_full_hash[%d] =\n\t", - SHA256_DIGEST_LENGTH); - print_hex(hashes, digest, SHA256_DIGEST_LENGTH, 1); - - if (!feof(tp_fw) || ferror(tp_fw)) { - warn("Error reading input file"); - return 1; - } - - if (len != CONFIG_TOUCHPAD_VIRTUAL_SIZE) { - warnx("Incorrect TP FW size (%d vs %d)", len, - CONFIG_TOUCHPAD_VIRTUAL_SIZE); - return 1; - } - - return 0; -} - -int main(int argc, char **argv) -{ - int nopt; - int ret; - const char *out = NULL; - char *tp_fw_name = NULL; - FILE *tp_fw = NULL; - FILE *hashes; - const char short_opt[] = "f:ho:"; - const struct option long_opts[] = { - { "firmware", 1, NULL, 'f' }, - { "help", 0, NULL, 'h' }, - { "out", 1, NULL, 'o' }, - { NULL } - }; - const char usage[] = "USAGE: %s -f <touchpad FW> -o <output file>\n"; - - while ((nopt = getopt_long(argc, argv, short_opt, - long_opts, NULL)) != -1) { - switch (nopt) { - case 'f': /* -f or --firmware */ - tp_fw_name = optarg; - break; - - case 'h': /* -h or --help */ - fprintf(stdout, usage, argv[0]); - return 0; - - case 'o': /* -o or --out */ - out = optarg; - break; - - default: /* Invalid parameter. */ - fprintf(stderr, usage, argv[0]); - return 1; - } - }; - - if (out == NULL) - return 1; - - hashes = fopen(out, "we"); - if (!hashes) - err(1, "Cannot open output file"); - - fputs("#include <stdint.h>\n\n", hashes); - if (tp_fw_name) { - tp_fw = fopen(tp_fw_name, "re"); - - if (!tp_fw) { - warn("Cannot open firmware"); - ret = 1; - goto out; - } - - ret = hash_fw(tp_fw, hashes); - - fclose(tp_fw); - } else { - printf("No touchpad FW provided, outputting blank hashes.\n"); - ret = hash_fw_blank(hashes); - } - -out: - fclose(hashes); - - /* In case of failure, remove output file. */ - if (ret != 0) - unlink(out); - - return ret; -} diff --git a/util/genvif.c b/util/genvif.c deleted file mode 100644 index 6722df9349..0000000000 --- a/util/genvif.c +++ /dev/null @@ -1,3860 +0,0 @@ -/* Copyright 2020 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 <errno.h> -#include <stdarg.h> -#include <stdbool.h> -#include <stdint.h> -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <getopt.h> -#include <dirent.h> -#include <limits.h> -#include <ctype.h> - -#include "config.h" -#include "usb_pd.h" -#include "usb_pd_tcpm.h" -#include "charge_manager.h" - -#include "genvif.h" - -#define VIF_APP_VENDOR_VALUE "Google" -#define VIF_APP_NAME_VALUE "EC GENVIF" -#define VIF_APP_VERSION_VALUE "3.0.0.10" -#define VENDOR_NAME_VALUE "Google" - -#define DEFAULT_MISSING_TID 0xFFFF -#define DEFAULT_MISSING_PID 0xFFFF -#define DEFAULT_MISSING_BCD_DEV 0x0000 - -const uint32_t *src_pdo; -uint32_t src_pdo_cnt; - -struct vif_t vif; - -/* - * local type to make decisions on the output for Source, Sink and DRP - */ -enum dtype { - SRC = 0, - SNK, - DRP -}; - -enum ptype { - PORT_CONSUMER_ONLY = 0, - PORT_CONSUMER_PRODUCER = 1, - PORT_PRODUCER_CONSUMER = 2, - PORT_PROVIDER_ONLY = 3, - PORT_DRP = 4, - PORT_EMARKER = 5, -}; - -/* - * Device_Speed options, defined in the VIF specification - */ -enum usb_speed { - USB_2 = 0, - USB_GEN11 = 1, - USB_GEN21 = 2, - USB_GEN12 = 3, - USB_GEN22 = 4 -}; - -/* - * BC_1_2_SUPPORT options - */ -enum bc_1_2_support { - BC_1_2_SUPPORT_NONE = 0, - BC_1_2_SUPPORT_PORTABLE_DEVICE = 1, - BC_1_2_SUPPORT_CHARGING_PORT = 2, - BC_1_2_SUPPORT_BOTH = 3 -}; - -enum power_source { - POWER_EXTERNAL = 0, - POWER_UFP = 1, - POWER_BOTH = 2, -}; - -/* - * index of component being set - */ -int component_index; - -/* - * TAG Name Strings - */ -#define NAME_INIT(str) [str] = #str - -const char *vif_name[] = { - NAME_INIT(VIF_Specification), - NAME_INIT(Vendor_Name), - NAME_INIT(Model_Part_Number), - NAME_INIT(Product_Revision), - NAME_INIT(TID), - NAME_INIT(VIF_Product_Type), - NAME_INIT(Certification_Type), -}; -BUILD_ASSERT(ARRAY_SIZE(vif_name) == VIF_Indexes); - -const char *vif_app_name[] = { - NAME_INIT(Vendor), - NAME_INIT(Name), - NAME_INIT(Version), -}; -BUILD_ASSERT(ARRAY_SIZE(vif_app_name) == VIF_App_Indexes); - -const char *vif_component_name[] = { - NAME_INIT(Port_Label), - NAME_INIT(Connector_Type), - NAME_INIT(USB4_Supported), - NAME_INIT(USB_PD_Support), - NAME_INIT(PD_Port_Type), - NAME_INIT(Type_C_State_Machine), - NAME_INIT(Port_Battery_Powered), - NAME_INIT(BC_1_2_Support), - NAME_INIT(PD_Spec_Revision_Major), - NAME_INIT(PD_Spec_Revision_Minor), - NAME_INIT(PD_Spec_Version_Major), - NAME_INIT(PD_Spec_Version_Minor), - NAME_INIT(PD_Specification_Revision), - NAME_INIT(SOP_Capable), - NAME_INIT(SOP_P_Capable), - NAME_INIT(SOP_PP_Capable), - NAME_INIT(SOP_P_Debug_Capable), - NAME_INIT(SOP_PP_Debug_Capable), - NAME_INIT(Manufacturer_Info_Supported_Port), - NAME_INIT(Manufacturer_Info_VID_Port), - NAME_INIT(Manufacturer_Info_PID_Port), - NAME_INIT(USB_Comms_Capable), - NAME_INIT(DR_Swap_To_DFP_Supported), - NAME_INIT(DR_Swap_To_UFP_Supported), - NAME_INIT(Unconstrained_Power), - NAME_INIT(VCONN_Swap_To_On_Supported), - NAME_INIT(VCONN_Swap_To_Off_Supported), - NAME_INIT(Responds_To_Discov_SOP_UFP), - NAME_INIT(Responds_To_Discov_SOP_DFP), - NAME_INIT(Attempts_Discov_SOP), - NAME_INIT(Chunking_Implemented_SOP), - NAME_INIT(Unchunked_Extended_Messages_Supported), - NAME_INIT(Security_Msgs_Supported_SOP), - NAME_INIT(Num_Fixed_Batteries), - NAME_INIT(Num_Swappable_Battery_Slots), - NAME_INIT(ID_Header_Connector_Type_SOP), - NAME_INIT(Type_C_Can_Act_As_Host), - NAME_INIT(Type_C_Can_Act_As_Device), - NAME_INIT(Type_C_Implements_Try_SRC), - NAME_INIT(Type_C_Implements_Try_SNK), - NAME_INIT(Type_C_Supports_Audio_Accessory), - NAME_INIT(Type_C_Supports_VCONN_Powered_Accessory), - NAME_INIT(Type_C_Is_VCONN_Powered_Accessory), - NAME_INIT(Type_C_Is_Debug_Target_SRC), - NAME_INIT(Type_C_Is_Debug_Target_SNK), - NAME_INIT(Captive_Cable), - NAME_INIT(RP_Value), - NAME_INIT(Type_C_Port_On_Hub), - NAME_INIT(Type_C_Power_Source), - NAME_INIT(Type_C_Sources_VCONN), - NAME_INIT(Type_C_Is_Alt_Mode_Controller), - NAME_INIT(Type_C_Is_Alt_Mode_Adapter), - NAME_INIT(USB4_Router_Index), - NAME_INIT(USB4_Lane_0_Adapter), - NAME_INIT(USB4_Max_Speed), - NAME_INIT(USB4_DFP_Supported), - NAME_INIT(USB4_UFP_Supported), - NAME_INIT(USB4_USB3_Tunneling_Supported), - NAME_INIT(USB4_DP_Tunneling_Supported), - NAME_INIT(USB4_PCIe_Tunneling_Supported), - NAME_INIT(USB4_TBT3_Compatibility_Supported), - NAME_INIT(USB4_CL1_State_Supported), - NAME_INIT(USB4_CL2_State_Supported), - NAME_INIT(USB4_Num_Retimers), - NAME_INIT(USB4_DP_Bit_Rate), - NAME_INIT(USB4_Num_DP_Lanes), - NAME_INIT(Host_Supports_USB_Data), - NAME_INIT(Host_Speed), - NAME_INIT(Host_Contains_Captive_Retimer), - NAME_INIT(Host_Truncates_DP_For_tDHPResponse), - NAME_INIT(Host_Gen1x1_tLinkTurnaround), - NAME_INIT(Host_Gen2x1_tLinkTurnaround), - NAME_INIT(Host_Is_Embedded), - NAME_INIT(Host_Suspend_Supported), - NAME_INIT(Is_DFP_On_Hub), - NAME_INIT(Hub_Port_Number), - NAME_INIT(Device_Supports_USB_Data), - NAME_INIT(Device_Speed), - NAME_INIT(Device_Contains_Captive_Retimer), - NAME_INIT(Device_Truncates_DP_For_tDHPResponse), - NAME_INIT(Device_Gen1x1_tLinkTurnaround), - NAME_INIT(Device_Gen2x1_tLinkTurnaround), - NAME_INIT(BC_1_2_Charging_Port_Type), - NAME_INIT(PD_Power_As_Source), - NAME_INIT(USB_Suspend_May_Be_Cleared), - NAME_INIT(Sends_Pings), - NAME_INIT(Accepts_PR_Swap_As_Src), - NAME_INIT(Accepts_PR_Swap_As_Snk), - NAME_INIT(Requests_PR_Swap_As_Src), - NAME_INIT(Requests_PR_Swap_As_Snk), - NAME_INIT(FR_Swap_Supported_As_Initial_Sink), - NAME_INIT(FR_Swap_Type_C_Current_Capability_As_Initial_Sink), - NAME_INIT(FR_Swap_Reqd_Type_C_Current_As_Initial_Source), - NAME_INIT(Master_Port), - NAME_INIT(Num_Src_PDOs), - NAME_INIT(PD_OC_Protection), - NAME_INIT(PD_OCP_Method), - NAME_INIT(PD_Power_As_Sink), - NAME_INIT(No_USB_Suspend_May_Be_Set), - NAME_INIT(GiveBack_May_Be_Set), - NAME_INIT(Higher_Capability_Set), - NAME_INIT(Num_Snk_PDOs), - NAME_INIT(XID_SOP), - NAME_INIT(Data_Capable_As_USB_Host_SOP), - NAME_INIT(Data_Capable_As_USB_Device_SOP), - NAME_INIT(Product_Type_UFP_SOP), - NAME_INIT(Product_Type_DFP_SOP), - NAME_INIT(DFP_VDO_Port_Number), - NAME_INIT(Modal_Operation_Supported_SOP), - NAME_INIT(USB_VID_SOP), - NAME_INIT(PID_SOP), - NAME_INIT(bcdDevice_SOP), - NAME_INIT(SVID_Fixed_SOP), - NAME_INIT(Num_SVIDs_Min_SOP), - NAME_INIT(Num_SVIDs_Max_SOP), - NAME_INIT(AMA_HW_Vers), - NAME_INIT(AMA_FW_Vers), - NAME_INIT(AMA_VCONN_Reqd), - NAME_INIT(AMA_VCONN_Power), - NAME_INIT(AMA_VBUS_Reqd), - NAME_INIT(AMA_Superspeed_Support), - NAME_INIT(Product_Total_Source_Power_mW), - NAME_INIT(Port_Source_Power_Type), - NAME_INIT(Port_Source_Power_Gang), - NAME_INIT(Port_Source_Power_Gang_Max_Power), - NAME_INIT(XID), - NAME_INIT(Data_Capable_As_USB_Host), - NAME_INIT(Data_Capable_As_USB_Device), - NAME_INIT(Product_Type), - NAME_INIT(Modal_Operation_Supported), - NAME_INIT(USB_VID), - NAME_INIT(PID), - NAME_INIT(bcdDevice), - NAME_INIT(Cable_HW_Vers), - NAME_INIT(Cable_FW_Vers), - NAME_INIT(Type_C_To_Type_A_B_C), - NAME_INIT(Type_C_To_Type_C_Capt_Vdm_V2), - NAME_INIT(Cable_Latency), - NAME_INIT(Cable_Termination_Type), - NAME_INIT(VBUS_Through_Cable), - NAME_INIT(Cable_VBUS_Current), - NAME_INIT(Cable_Superspeed_Support), - NAME_INIT(Cable_USB_Highest_Speed), - NAME_INIT(Max_VBUS_Voltage_Vdm_V2), - NAME_INIT(Manufacturer_Info_Supported), - NAME_INIT(Manufacturer_Info_VID), - NAME_INIT(Manufacturer_Info_PID), - NAME_INIT(Chunking_Implemented), - NAME_INIT(Security_Msgs_Supported), - NAME_INIT(ID_Header_Connector_Type), - NAME_INIT(SVID_Fixed), - NAME_INIT(Cable_Num_SVIDs_Min), - NAME_INIT(Cable_Num_SVIDs_Max), - NAME_INIT(VPD_HW_Vers), - NAME_INIT(VPD_FW_Vers), - NAME_INIT(VPD_Max_VBUS_Voltage), - NAME_INIT(VPD_Charge_Through_Support), - NAME_INIT(VPD_Charge_Through_Current), - NAME_INIT(VPD_VBUS_Impedance), - NAME_INIT(VPD_Ground_Impedance), - NAME_INIT(Cable_SOP_PP_Controller), - NAME_INIT(SBU_Supported), - NAME_INIT(SBU_Type), - NAME_INIT(Active_Cable_Operating_Temp_Support), - NAME_INIT(Active_Cable_Max_Operating_Temp), - NAME_INIT(Active_Cable_Shutdown_Temp_Support), - NAME_INIT(Active_Cable_Shutdown_Temp), - NAME_INIT(Active_Cable_U3_CLd_Power), - NAME_INIT(Active_Cable_U3_U0_Trans_Mode), - NAME_INIT(Active_Cable_Physical_Connection), - NAME_INIT(Active_Cable_Active_Element), - NAME_INIT(Active_Cable_USB4_Support), - NAME_INIT(Active_Cable_USB2_Hub_Hops_Consumed), - NAME_INIT(Active_Cable_USB2_Supported), - NAME_INIT(Active_Cable_USB32_Supported), - NAME_INIT(Active_Cable_USB_Lanes), - NAME_INIT(Active_Cable_Optically_Isolated), - NAME_INIT(Active_Cable_USB_Gen), - NAME_INIT(Repeater_One_Type), - NAME_INIT(Repeater_Two_Type), -}; -BUILD_ASSERT(ARRAY_SIZE(vif_component_name) == Component_Indexes); - -const char *vif_component_snk_pdo_name[] = { - NAME_INIT(Snk_PDO_Supply_Type), - NAME_INIT(Snk_PDO_Voltage), - NAME_INIT(Snk_PDO_Op_Power), - NAME_INIT(Snk_PDO_Min_Voltage), - NAME_INIT(Snk_PDO_Max_Voltage), - NAME_INIT(Snk_PDO_Op_Current), -}; -BUILD_ASSERT(ARRAY_SIZE(vif_component_snk_pdo_name) == Snk_PDO_Indexes); - -const char *vif_component_src_pdo_name[] = { - NAME_INIT(Src_PDO_Supply_Type), - NAME_INIT(Src_PDO_Peak_Current), - NAME_INIT(Src_PDO_Voltage), - NAME_INIT(Src_PDO_Max_Current), - NAME_INIT(Src_PDO_Min_Voltage), - NAME_INIT(Src_PDO_Max_Voltage), - NAME_INIT(Src_PDO_Max_Power), - NAME_INIT(Src_PD_OCP_OC_Debounce), - NAME_INIT(Src_PD_OCP_OC_Threshold), - NAME_INIT(Src_PD_OCP_UV_Debounce), - NAME_INIT(Src_PD_OCP_UV_Threshold_Type), - NAME_INIT(Src_PD_OCP_UV_Threshold), -}; -BUILD_ASSERT(ARRAY_SIZE(vif_component_src_pdo_name) == Src_PDO_Indexes); - -const char *vif_component_sop_svid_mode_name[] = { - NAME_INIT(SVID_Mode_Enter_SOP), - NAME_INIT(SVID_Mode_Recog_Mask_SOP), - NAME_INIT(SVID_Mode_Recog_Value_SOP), -}; -BUILD_ASSERT(ARRAY_SIZE(vif_component_sop_svid_mode_name) == - SopSVID_Mode_Indexes); - -const char *vif_component_sop_svid_name[] = { - NAME_INIT(SVID_SOP), - NAME_INIT(SVID_Modes_Fixed_SOP), - NAME_INIT(SVID_Num_Modes_Min_SOP), - NAME_INIT(SVID_Num_Modes_Max_SOP), -}; -BUILD_ASSERT(ARRAY_SIZE(vif_component_sop_svid_name) == SopSVID_Indexes); - -const char *vif_cable_mode_name[] = { - NAME_INIT(SVID_Mode_Enter), - NAME_INIT(SVID_Mode_Recog_Mask), - NAME_INIT(SVID_Mode_Recog_Value), -}; -BUILD_ASSERT(ARRAY_SIZE(vif_cable_mode_name) == CableSVID_Mode_Indexes); - -const char *vif_cable_svid_name[] = { - NAME_INIT(SVID), - NAME_INIT(SVID_Modes_Fixed), - NAME_INIT(SVID_Num_Modes_Min), - NAME_INIT(SVID_Num_Modes_Max), -}; -BUILD_ASSERT(ARRAY_SIZE(vif_cable_svid_name) == CableSVID_Indexes); - -const char *vif_product_name[] = { - NAME_INIT(Product_VID), - NAME_INIT(USB4_Dock), - NAME_INIT(USB4_Num_Internal_Host_Controllers), - NAME_INIT(USB4_Num_PCIe_DN_Bridges), - NAME_INIT(USB4_Audio_Supported), - NAME_INIT(USB4_HID_Supported), - NAME_INIT(USB4_Printer_Supported), - NAME_INIT(USB4_Mass_Storage_Supported), - NAME_INIT(USB4_Video_Supported), - NAME_INIT(USB4_Comms_Networking_Supported), - NAME_INIT(USB4_Media_Transfer_Protocol_Supported), - NAME_INIT(USB4_Smart_Card_Supported), - NAME_INIT(USB4_Still_Image_Capture_Supported), - NAME_INIT(USB4_Monitor_Device_Supported), -}; -BUILD_ASSERT(ARRAY_SIZE(vif_product_name) == Product_Indexes); - -const char *vif_product_pcie_endpoint_name[] = { - NAME_INIT(USB4_PCIe_Endpoint_Vendor_ID), - NAME_INIT(USB4_PCIe_Endpoint_Device_ID), - NAME_INIT(USB4_PCIe_Endpoint_Class_Code), -}; -BUILD_ASSERT(ARRAY_SIZE(vif_product_pcie_endpoint_name) == - PCIe_Endpoint_Indexes); - -const char *vif_product_usb4_router_name[] = { - NAME_INIT(USB4_Router_ID), - NAME_INIT(USB4_Silicon_VID), - NAME_INIT(USB4_Num_Lane_Adapters), - NAME_INIT(USB4_Num_USB3_DN_Adapters), - NAME_INIT(USB4_Num_DP_IN_Adapters), - NAME_INIT(USB4_Num_DP_OUT_Adapters), - NAME_INIT(USB4_Num_PCIe_DN_Adapters), - NAME_INIT(USB4_TBT3_Not_Supported), - NAME_INIT(USB4_PCIe_Wake_Supported), - NAME_INIT(USB4_USB3_Wake_Supported), - NAME_INIT(USB4_Num_Unused_Adapters), - NAME_INIT(USB4_TBT3_VID), - NAME_INIT(USB4_PCIe_Switch_Vendor_ID), - NAME_INIT(USB4_PCIe_Switch_Device_ID), - NAME_INIT(USB4_Num_PCIe_Endpoints), -}; -BUILD_ASSERT(ARRAY_SIZE(vif_product_usb4_router_name) == USB4_Router_Indexes); - - -static bool streq(const char *str1, const char *str2) -{ - return strcasecmp(str1, str2) == 0; -} - -/***************************************************************************** - * VIF Structure Override Value Retrieve Functions - */ -/** Number **/ -static bool get_vif_field_tag_number(struct vif_field_t *vif_field, int *value) -{ - if (vif_field->tag_value == NULL) - return false; - - *value = atoi(vif_field->tag_value); - return true; -} -static bool get_vif_field_str_number(struct vif_field_t *vif_field, int *value) -{ - if (vif_field->str_value == NULL) - return false; - - *value = atoi(vif_field->str_value); - return true; -} -static bool get_vif_field_number(struct vif_field_t *vif_field, int *value) -{ - bool rv; - - rv = get_vif_field_tag_number(vif_field, value); - if (!rv) - rv = get_vif_field_str_number(vif_field, value); - - return rv; -} -__maybe_unused -static bool get_vif_number(struct vif_field_t *vif_field, int default_value) -{ - int ret_value; - - if (!get_vif_field_number(vif_field, &ret_value)) - ret_value = default_value; - - return ret_value; -} - -/** Boolean **/ -static bool get_vif_field_tag_bool(struct vif_field_t *vif_field, bool *value) -{ - if (vif_field->tag_value == NULL) - return false; - - *value = streq(vif_field->tag_value, "true"); - return true; -} -static bool get_vif_field_str_bool(struct vif_field_t *vif_field, bool *value) -{ - if (vif_field->str_value == NULL) - return false; - - *value = streq(vif_field->str_value, "YES"); - return true; -} -static bool get_vif_field_bool(struct vif_field_t *vif_field, bool *value) -{ - bool rv; - - rv = get_vif_field_tag_bool(vif_field, value); - if (!rv) - rv = get_vif_field_str_bool(vif_field, value); - - return rv; -} -static bool get_vif_bool(struct vif_field_t *vif_field, bool default_value) -{ - bool ret_value; - - if (!get_vif_field_bool(vif_field, &ret_value)) - ret_value = default_value; - - return ret_value; -} - -/** String **/ -__maybe_unused -static bool get_vif_field_tag_str(struct vif_field_t *vif_field, char **value) -{ - if (vif_field->tag_value == NULL) - return false; - - *value = vif_field->tag_value; - return true; -} -__maybe_unused -static bool get_vif_field_str_str(struct vif_field_t *vif_field, char **value) -{ - if (vif_field->str_value == NULL) - return false; - - *value = vif_field->str_value; - return true; -} -/* - * VIF Structure Override Value Retrieve Functions - *****************************************************************************/ - - -/***************************************************************************** - * Generic Helper Functions - */ -static bool is_src(void) -{ - int override_value; - bool was_overridden; - - /* Determine if we are DRP, SRC or SNK */ - was_overridden = get_vif_field_tag_number( - &vif.Component[component_index] - .vif_field[Type_C_State_Machine], - &override_value); - if (was_overridden) { - switch (override_value) { - case SRC: - case DRP: - return true; - case SNK: - return false; - default: - was_overridden = false; - break; - } - } - if (!was_overridden) { - was_overridden = get_vif_field_tag_number( - &vif.Component[component_index] - .vif_field[PD_Port_Type], - &override_value); - if (was_overridden) { - switch (override_value) { - case PORT_PROVIDER_ONLY: /* SRC */ - case PORT_DRP: /* DRP */ - return true; - case PORT_CONSUMER_ONLY: /* SNK */ - return false; - default: - was_overridden = false; - } - } - } - return src_pdo_cnt; -} -static bool is_snk(void) -{ - int override_value; - bool was_overridden; - - /* Determine if we are DRP, SRC or SNK */ - was_overridden = get_vif_field_tag_number( - &vif.Component[component_index] - .vif_field[Type_C_State_Machine], - &override_value); - if (was_overridden) { - switch (override_value) { - case SNK: - case DRP: - return true; - case SRC: - return false; - default: - was_overridden = false; - break; - } - } - if (!was_overridden) { - was_overridden = get_vif_field_tag_number( - &vif.Component[component_index] - .vif_field[PD_Port_Type], - &override_value); - if (was_overridden) { - switch (override_value) { - case PORT_CONSUMER_ONLY: /* SNK */ - case PORT_DRP: /* DRP */ - return true; - case PORT_PROVIDER_ONLY: /* SRC */ - return false; - default: - was_overridden = false; - } - } - } - return (IS_ENABLED(CONFIG_USB_PD_DUAL_ROLE)) ? pd_snk_pdo_cnt : 0; -} -static bool is_drp(void) -{ - int override_value; - bool was_overridden; - - /* Determine if we are DRP, SRC or SNK */ - was_overridden = get_vif_field_tag_number( - &vif.Component[component_index] - .vif_field[Type_C_State_Machine], - &override_value); - if (was_overridden) { - switch (override_value) { - case DRP: - return true; - case SNK: - return false; - case SRC: - default: - was_overridden = false; - break; - } - } - if (!was_overridden) { - was_overridden = get_vif_field_tag_number( - &vif.Component[component_index] - .vif_field[PD_Port_Type], - &override_value); - if (was_overridden) { - switch (override_value) { - case PORT_DRP: /* DRP */ - return true; - case PORT_CONSUMER_ONLY: /* SNK */ - return false; - case PORT_PROVIDER_ONLY: /* SRC */ - default: - was_overridden = false; - } - } - } - if (is_src()) - return !!(src_pdo[0] & PDO_FIXED_DUAL_ROLE); - return false; -} - -static bool can_act_as_device(void) -{ - return get_vif_bool(&vif.Component[component_index] - .vif_field[Type_C_Can_Act_As_Device], -#if defined(USB_DEV_CLASS) && defined(USB_CLASS_BILLBOARD) - USB_DEV_CLASS == USB_CLASS_BILLBOARD -#else - false -#endif - ); -} - -static bool can_act_as_host(void) -{ - return get_vif_bool(&vif.Component[component_index] - .vif_field[Type_C_Can_Act_As_Host], - (!(IS_ENABLED(CONFIG_USB_CTVPD) || - IS_ENABLED(CONFIG_USB_VPD)))); -} - -static bool is_usb4_supported(void) -{ - return get_vif_bool(&vif.Component[component_index] - .vif_field[USB4_Supported], - IS_ENABLED(CONFIG_USB_PD_USB4)); -} - -static bool is_usb_pd_supported(void) -{ - return get_vif_bool(&vif.Component[component_index] - .vif_field[USB_PD_Support], - (is_usb4_supported() || - IS_ENABLED(CONFIG_USB_PRL_SM) || - IS_ENABLED(CONFIG_USB_POWER_DELIVERY))); -} - -static bool is_usb_comms_capable(void) -{ - return get_vif_bool(&vif.Component[component_index] - .vif_field[USB_Comms_Capable], - is_usb4_supported() || - (!(IS_ENABLED(CONFIG_USB_VPD) || - IS_ENABLED(CONFIG_USB_CTVPD)))); -} - -static bool is_alt_mode_controller(void) -{ - return get_vif_bool(&vif.Component[component_index] - .vif_field[Type_C_Is_Alt_Mode_Controller], - IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP)); -} - -static bool does_respond_to_discov_sop_ufp(void) -{ - return get_vif_bool(&vif.Component[component_index] - .vif_field[Responds_To_Discov_SOP_UFP], - (is_usb4_supported() || - IS_ENABLED(CONFIG_USB_PD_TBT_COMPAT_MODE))); -} - -static bool does_respond_to_discov_sop_dfp(void) -{ - return get_vif_bool(&vif.Component[component_index] - .vif_field[Responds_To_Discov_SOP_DFP], - (is_usb4_supported() || - IS_ENABLED(CONFIG_USB_PD_TBT_COMPAT_MODE))); -} - -static bool does_support_device_usb_data(void) -{ - return get_vif_bool(&vif.Component[component_index] - .vif_field[Device_Supports_USB_Data], - (is_usb4_supported() || - can_act_as_device())); -} - -static bool does_support_host_usb_data(void) -{ - int type_c_state_machine; - - if (!get_vif_field_tag_number( - &vif.Component[component_index] - .vif_field[Type_C_State_Machine], - &type_c_state_machine)) - return false; - - return get_vif_bool(&vif.Component[component_index] - .vif_field[Host_Supports_USB_Data], - can_act_as_host()); -} - -static void init_src_pdos(void) -{ - if (IS_ENABLED(CONFIG_USB_PD_DYNAMIC_SRC_CAP)) { - src_pdo_cnt = charge_manager_get_source_pdo(&src_pdo, 0); - } else { - if (IS_ENABLED(CONFIG_USB_PD_CUSTOM_PDO)) { - src_pdo_cnt = pd_src_pdo_cnt; - src_pdo = pd_src_pdo; - } else { - src_pdo_cnt = pd_src_pdo_max_cnt; - src_pdo = pd_src_pdo_max; - } - } -} - -static bool vif_fields_present(struct vif_field_t *vif_fields, int count) -{ - int index; - - for (index = 0; index < count; ++index) { - if (vif_fields[index].str_value || - vif_fields[index].tag_value) { - return true; - } - } - return false; -} -/* - * Generic Helper Functions - *****************************************************************************/ - - -/***************************************************************************** - * VIF XML Output Functions - */ -static void vif_out_str(FILE *vif_file, int level, char *str) -{ - while (level-- > 0) - fprintf(vif_file, " "); - fprintf(vif_file, "%s\r\n", str); -} - -static void vif_out_field(FILE *vif_file, int level, - struct vif_field_t *vif_field) -{ - if (vif_field->str_value || vif_field->tag_value) { - while (level-- > 0) - fprintf(vif_file, " "); - - fprintf(vif_file, "<%s", vif_field->name); - if (vif_field->tag_value) - fprintf(vif_file, " value=\"%s\"", - vif_field->tag_value); - if (vif_field->str_value) - fprintf(vif_file, ">%s</%s>\r\n", - vif_field->str_value, - vif_field->name); - else - fprintf(vif_file, " />\r\n"); - } -} - -static void vif_out_fields_range(FILE *vif_file, int level, - struct vif_field_t *vif_fields, - int start, int count) -{ - int index; - - for (index = start; index < count; ++index) - vif_out_field(vif_file, level, &vif_fields[index]); -} - -static void vif_out_fields(FILE *vif_file, int level, - struct vif_field_t *vif_fields, int count) -{ - vif_out_fields_range(vif_file, level, vif_fields, 0, count); -} - - - -static void vif_output_vif_component_cable_svid_mode_list(FILE *vif_file, - struct vif_cableSVIDList_t *svid_list, int level) -{ - int index; - - if (!vif_fields_present(svid_list->CableSVIDModeList[0].vif_field, - CableSVID_Mode_Indexes)) - return; - - vif_out_str(vif_file, level++, "<CableSVIDModeList>"); - for (index = 0; index < MAX_NUM_CABLE_SVID_MODES; ++index) { - struct vif_cableSVIDModeList_t *mode_list = - &svid_list->CableSVIDModeList[index]; - - if (!vif_fields_present(mode_list->vif_field, - CableSVID_Mode_Indexes)) - break; - - vif_out_str(vif_file, level++, "<SOPSVIDMode>"); - vif_out_fields(vif_file, level, - mode_list->vif_field, CableSVID_Mode_Indexes); - vif_out_str(vif_file, --level, "</SOPSVIDMode>"); - } - vif_out_str(vif_file, --level, "</CableSVIDModeList>"); -} - -static void vif_output_vif_component_cable_svid_list(FILE *vif_file, - struct vif_Component_t *component, int level) -{ - int index; - - if (!vif_fields_present(component->CableSVIDList[0].vif_field, - CableSVID_Indexes)) - return; - - vif_out_str(vif_file, level++, "<CableSVIDList>"); - for (index = 0; index < MAX_NUM_CABLE_SVIDS; ++index) { - struct vif_cableSVIDList_t *svid_list = - &component->CableSVIDList[index]; - - if (!vif_fields_present(svid_list->vif_field, - CableSVID_Indexes)) - break; - - vif_out_str(vif_file, level++, "<CableSVID>"); - vif_out_fields(vif_file, level, - svid_list->vif_field, CableSVID_Indexes); - vif_output_vif_component_cable_svid_mode_list(vif_file, - svid_list, level); - vif_out_str(vif_file, --level, "</CableSVID>"); - } - vif_out_str(vif_file, --level, "</CableSVIDList>"); -} - -static void vif_output_vif_component_sop_svid_mode_list(FILE *vif_file, - struct vif_sopSVIDList_t *svid_list, int level) -{ - int index; - - if (!vif_fields_present(svid_list->SOPSVIDModeList[0].vif_field, - SopSVID_Mode_Indexes)) - return; - - vif_out_str(vif_file, level++, "<SOPSVIDModeList>"); - for (index = 0; index < MAX_NUM_SOP_SVID_MODES; ++index) { - struct vif_sopSVIDModeList_t *mode_list = - &svid_list->SOPSVIDModeList[index]; - - if (!vif_fields_present(mode_list->vif_field, - SopSVID_Mode_Indexes)) - break; - - vif_out_str(vif_file, level++, "<SOPSVIDMode>"); - vif_out_fields(vif_file, level, - mode_list->vif_field, SopSVID_Mode_Indexes); - vif_out_str(vif_file, --level, "</SOPSVIDMode>"); - } - vif_out_str(vif_file, --level, "</SOPSVIDModeList>"); -} - -static void vif_output_vif_component_sop_svid_list(FILE *vif_file, - struct vif_Component_t *component, int level) -{ - int index; - - if (!vif_fields_present(component->SOPSVIDList[0].vif_field, - SopSVID_Indexes)) - return; - - vif_out_str(vif_file, level++, "<SOPSVIDList>"); - for (index = 0; index < MAX_NUM_SOP_SVIDS; ++index) { - struct vif_sopSVIDList_t *svid_list = - &component->SOPSVIDList[index]; - - if (!vif_fields_present(svid_list->vif_field, - SopSVID_Indexes)) - break; - - vif_out_str(vif_file, level++, "<SOPSVID>"); - vif_out_fields(vif_file, level, - svid_list->vif_field, SopSVID_Indexes); - vif_output_vif_component_sop_svid_mode_list(vif_file, - svid_list, level); - vif_out_str(vif_file, --level, "</SOPSVID>"); - } - vif_out_str(vif_file, --level, "</SOPSVIDList>"); -} - -static void vif_output_vif_component_snk_pdo_list(FILE *vif_file, - struct vif_Component_t *component, int level) -{ - int index; - - if (!vif_fields_present(component->SnkPdoList[0].vif_field, - Snk_PDO_Indexes)) - return; - - vif_out_str(vif_file, level++, "<SnkPdoList>"); - for (index = 0; index < MAX_NUM_SNK_PDOS; ++index) { - struct vif_snkPdoList_t *pdo_list = - &component->SnkPdoList[index]; - - if (!vif_fields_present(pdo_list->vif_field, - Snk_PDO_Indexes)) - break; - - vif_out_str(vif_file, level++, "<SnkPDO>"); - vif_out_fields(vif_file, level, - pdo_list->vif_field, Snk_PDO_Indexes); - vif_out_str(vif_file, --level, "</SnkPDO>"); - } - vif_out_str(vif_file, --level, "</SnkPdoList>"); -} - -static void vif_output_vif_component_src_pdo_list(FILE *vif_file, - struct vif_Component_t *component, int level) -{ - int index; - - if (!vif_fields_present(component->SrcPdoList[0].vif_field, - Src_PDO_Indexes)) - return; - - vif_out_str(vif_file, level++, "<SrcPdoList>"); - for (index = 0; index < MAX_NUM_SRC_PDOS; ++index) { - struct vif_srcPdoList_t *pdo_list = - &component->SrcPdoList[index]; - - if (!vif_fields_present(pdo_list->vif_field, - Src_PDO_Indexes)) - break; - - vif_out_str(vif_file, level++, "<SrcPDO>"); - vif_out_fields(vif_file, level, - pdo_list->vif_field, Src_PDO_Indexes); - vif_out_str(vif_file, --level, "</SrcPDO>"); - } - vif_out_str(vif_file, --level, "</SrcPdoList>"); -} - -static void vif_output_vif_component(FILE *vif_file, - struct vif_t *vif, int level) -{ - int index; - - for (index = 0; index < MAX_NUM_COMPONENTS; ++index) { - struct vif_Component_t *component = &vif->Component[index]; - - if (!vif_fields_present(component->vif_field, - Component_Indexes)) - return; - - vif_out_str(vif_file, level++, "<Component>"); - vif_out_fields(vif_file, level, - component->vif_field, Component_Indexes); - vif_output_vif_component_snk_pdo_list(vif_file, - component, - level); - vif_output_vif_component_src_pdo_list(vif_file, - component, - level); - vif_output_vif_component_sop_svid_list(vif_file, - component, - level); - vif_output_vif_component_cable_svid_list(vif_file, - component, - level); - vif_out_str(vif_file, --level, "</Component>"); - } -} - -static void vif_output_vif_product_usb4router_endpoint(FILE *vif_file, - struct vif_Usb4RouterListType_t *router, int level) -{ - int index; - - if (!vif_fields_present(router->PCIeEndpointList[0].vif_field, - PCIe_Endpoint_Indexes)) - return; - - vif_out_str(vif_file, level++, "<PCIeEndpointList>"); - for (index = 0; index < MAX_NUM_PCIE_ENDPOINTS; ++index) { - struct vif_PCIeEndpointListType_t *endpont = - &router->PCIeEndpointList[index]; - - if (!vif_fields_present(endpont->vif_field, - PCIe_Endpoint_Indexes)) - break; - - vif_out_str(vif_file, level++, "<PCIeEndpoint>"); - vif_out_fields(vif_file, level, - endpont->vif_field, PCIe_Endpoint_Indexes); - vif_out_str(vif_file, --level, "</PCIeEndpoint>"); - } - vif_out_str(vif_file, --level, "</PCIeEndpointList>"); -} - -static void vif_output_vif_product_usb4router(FILE *vif_file, - struct vif_t *vif, int level) -{ - int index; - - if (!vif_fields_present(vif->Product.USB4RouterList[0].vif_field, - USB4_Router_Indexes)) - return; - - vif_out_str(vif_file, level++, "<USB4RouterList>"); - for (index = 0; index < MAX_NUM_USB4_ROUTERS; ++index) { - struct vif_Usb4RouterListType_t *router = - &vif->Product.USB4RouterList[index]; - - if (!vif_fields_present(router->vif_field, - USB4_Router_Indexes)) - break; - - vif_out_str(vif_file, level++, "<Usb4Router>"); - vif_out_fields(vif_file, level, - router->vif_field, USB4_Router_Indexes); - vif_output_vif_product_usb4router_endpoint(vif_file, - router, - level); - vif_out_str(vif_file, --level, "</Usb4Router>"); - } - vif_out_str(vif_file, --level, "</USB4RouterList>"); -} - -static void vif_output_vif_product(FILE *vif_file, - struct vif_t *vif, int level) -{ - if (!vif_fields_present(vif->Product.vif_field, Product_Indexes)) - return; - - vif_out_str(vif_file, level++, "<Product>"); - vif_out_fields(vif_file, level, - vif->Product.vif_field, Product_Indexes); - vif_output_vif_product_usb4router(vif_file, vif, level); - vif_out_str(vif_file, --level, "</Product>"); -} - -static void vif_output_vif_xml(FILE *vif_file, struct vif_t *vif, int level) -{ - vif_out_field(vif_file, level, &vif->vif_field[VIF_Specification]); - - vif_out_str(vif_file, level++, "<VIF_App>"); - vif_out_fields(vif_file, level, vif->vif_app_field, VIF_App_Indexes); - vif_out_str(vif_file, --level, "</VIF_App>"); - - vif_out_fields_range(vif_file, level, - vif->vif_field, Vendor_Name, VIF_Indexes); -} - -static int vif_output_xml(const char *name, struct vif_t *vif) -{ - int level = 0; - FILE *vif_file; - - vif_file = fopen(name, "w+"); - if (vif_file == NULL) { - fprintf(stderr, "Output file '%s' could not be created\n", - name); - return 1; - } - - vif_out_str(vif_file, level, - "<?xml version=\"1.0\" encoding=\"utf-8\"?>"); - vif_out_str(vif_file, level++, - "<VIF xmlns=\"http://usb.org/VendorInfoFile.xsd\">"); - - vif_output_vif_xml(vif_file, vif, level); - vif_output_vif_product(vif_file, vif, level); - vif_output_vif_component(vif_file, vif, level); - - vif_out_str(vif_file, --level, "</VIF>"); - - fclose(vif_file); - return 0; -} -/* - * VIF XML Output Functions - *****************************************************************************/ - - -/***************************************************************************** - * VIF Structure Override from XML file functions - */ -FILE *override_file; - -int pushback_cnt; -char pushback_stack[20]; - -static bool ov_open(const char *over_name) -{ - override_file = fopen(over_name, "r"); - - pushback_cnt = 0; - return override_file != NULL; -} -static int ov_getc(void) -{ - if (!override_file) - return EOF; - - if (pushback_cnt) - return pushback_stack[--pushback_cnt]; - return getc(override_file); -} -static void ovpre_getc(int cnt) -{ - if (pushback_cnt < cnt) { - int new_pushback_cnt = cnt; - - while (cnt > 0) - pushback_stack[--cnt] = ov_getc(); - pushback_cnt = new_pushback_cnt; - } -} -static void ovpre_drop(int cnt) -{ - pushback_cnt -= cnt; - if (pushback_cnt < 0) - pushback_cnt = 0; -} -static int ovpre_peek(int index) -{ - return pushback_stack[pushback_cnt - index - 1]; -} -static void ov_pushback(int ch) -{ - pushback_stack[pushback_cnt++] = ch; -} -static void ov_close(void) -{ - if (override_file) - fclose(override_file); - - pushback_cnt = 0; - override_file = NULL; -} - - -static void set_override_vif_field(struct vif_field_t *vif_field, - const char *name, - const char *tag_value, - const char *str_value) -{ - char *ptr; - - if (vif_field->str_value) { - free(vif_field->str_value); - vif_field->str_value = NULL; - } - if (vif_field->tag_value) { - free(vif_field->tag_value); - vif_field->tag_value = NULL; - } - - vif_field->name = name; - if (tag_value && tag_value[0]) { - ptr = malloc(strlen(tag_value)+1); - strcpy(ptr, tag_value); - vif_field->tag_value = ptr; - - /* - * If the tag_value was provided and the str_value was - * not and this is a boolean value, then fill in the - * str_value - */ - if (!str_value || str_value[0] == '\0') { - if (streq(tag_value, "true")) - str_value = "YES"; - else if (streq(tag_value, "false")) - str_value = "NO"; - } - } - if (str_value && str_value[0]) { - ptr = malloc(strlen(str_value)+1); - strcpy(ptr, str_value); - vif_field->str_value = ptr; - } -} - -static void ignore_xml_version_tag(void) -{ - int ch; - - while ((ch = ov_getc()) != EOF) { - if (ch == '?') { - ch = ov_getc(); - if (ch == '>') - break; - ov_pushback(ch); - } - } -} -static void ignore_comment_tag(void) -{ - int ch; - - while ((ch = ov_getc()) != EOF) { - if (ch == '-') { - ovpre_getc(2); - if (ovpre_peek(0) == '-' && - ovpre_peek(1) == '>') { - /* --> */ - ovpre_drop(2); - break; - } - } - } -} -static void ignore_white_space(void) -{ - int ch; - - while ((ch = ov_getc()) != EOF) { - if (!isspace(ch)) { - ov_pushback(ch); - break; - } - } -} -static void ignore_to_end_tag(void) -{ - int ch; - - while ((ch = ov_getc()) != EOF) { - if (ch == '>') - break; - } -} -static bool get_next_tag(char *name, - char *tag_value, - char *str_value) -{ - int ch; - int name_index = 0; - int tag_index = 0; - int str_index = 0; - - name[0] = '\0'; - tag_value[0] = '\0'; - str_value[0] = '\0'; - - /* - * Ignore <? .... ?> - * Ignore <!-- ... --> - * Find tags <X/>, <X> and </X> - */ - while ((ch = ov_getc()) != EOF) { - if (ch == '<') { - /* - * Ignore XML version <? ... ?> - */ - ovpre_getc(1); - if (ovpre_peek(0) == '?') { - ovpre_drop(1); - ignore_xml_version_tag(); - continue; - } - - /* - * Ignore XML comment <!-- ... --> - */ - ovpre_getc(3); - if (ovpre_peek(0) == '!' && - ovpre_peek(1) == '-' && - ovpre_peek(2) == '-') { - ovpre_drop(3); - ignore_comment_tag(); - continue; - } - - /* Looking for terminating tag */ - ovpre_getc(1); - if (ovpre_peek(0) == '/') { - while ((ch = ov_getc()) != EOF) { - if (ch == '>') - break; - name[name_index++] = ch; - } - name[name_index] = '\0'; - return true; - } - - /* Looking for a tag name */ - while ((ch = ov_getc()) != EOF) { - if (ch == '_' || isalpha(ch) || isdigit(ch)) { - name[name_index++] = ch; - } else { - ov_pushback(ch); - break; - } - } - name[name_index] = '\0'; - - /* Consume any whitespace */ - ignore_white_space(); - - /* See if there is a tag_string value */ - ovpre_getc(7); - if (ovpre_peek(0) == 'v' && - ovpre_peek(1) == 'a' && - ovpre_peek(2) == 'l' && - ovpre_peek(3) == 'u' && - ovpre_peek(4) == 'e' && - ovpre_peek(5) == '=' && - ovpre_peek(6) == '"') { - ovpre_drop(7); - while ((ch = ov_getc()) != EOF) { - if (ch == '"') - break; - tag_value[tag_index++] = ch; - } - tag_value[tag_index] = '\0'; - } - - /* Consume any whitespace */ - ignore_white_space(); - - /* /> ending the tag will conclude this tag */ - ovpre_getc(2); - if (ovpre_peek(0) == '/' && - ovpre_peek(1) == '>') { - ovpre_drop(2); - return true; - } - if (ovpre_peek(0) == '>') { - ovpre_drop(1); - while ((ch = ov_getc()) != EOF) { - if (ch == '<') { - ov_pushback(ch); - break; - } - str_value[str_index++] = ch; - } - str_value[str_index] = '\0'; - - ovpre_getc(2); - if (ovpre_peek(0) == '<' && - ovpre_peek(1) == '/') { - ovpre_drop(2); - ignore_to_end_tag(); - } - } - return true; - } - } - return false; -} - -static void override_vif_product_pcie_endpoint_field( - struct vif_PCIeEndpointListType_t *endpoint) -{ - char name[80]; - char tag_value[80]; - char str_value[80]; - - while (get_next_tag(name, tag_value, str_value)) { - int i; - - if (streq(name, "/PCIeEndpoint")) - break; - - for (i = 0; i < PCIe_Endpoint_Indexes; i++) - if (streq(name, vif_product_pcie_endpoint_name[i])) - break; - if (i != PCIe_Endpoint_Indexes) - set_override_vif_field( - &endpoint->vif_field[i], - vif_product_pcie_endpoint_name[i], - tag_value, - str_value); - else - fprintf(stderr, - "VIF/Component/Usb4Router/PCIeEndpoint:" - " Unknown tag '%s'\n", name); - } -} -static void override_vif_product_pcie_endpoint_list_field( - struct vif_PCIeEndpointListType_t *endpoint_list) -{ - char name[80]; - char tag_value[80]; - char str_value[80]; - int endpoint_index = 0; - - while (get_next_tag(name, tag_value, str_value)) { - if (streq(name, "/PCIeEndpointList")) - break; - - if (streq(name, "PCIeEndpoint")) - override_vif_product_pcie_endpoint_field( - &endpoint_list[endpoint_index++]); - else - fprintf(stderr, - "VIF/Product/Usb4Router/PCIeEndpointList:" - " Unknown tag '%s'\n", name); - } -} - -static void override_vif_product_usb4router_fields( - struct vif_Usb4RouterListType_t *router) -{ - char name[80]; - char tag_value[80]; - char str_value[80]; - int endpoint_index = 0; - - while (get_next_tag(name, tag_value, str_value)) { - if (streq(name, "/Usb4Router")) - break; - - if (streq(name, "PCIeEndpointList")) - override_vif_product_pcie_endpoint_list_field( - &router->PCIeEndpointList[endpoint_index++]); - else { - int i; - - for (i = 0; i < USB4_Router_Indexes; i++) - if (streq(name, - vif_product_usb4_router_name[i])) - break; - if (i != USB4_Router_Indexes) - set_override_vif_field( - &router->vif_field[i], - vif_product_usb4_router_name[i], - tag_value, - str_value); - else - fprintf(stderr, - "VIF/Component/Usb4Router:" - " Unknown tag '%s'\n", name); - } - } -} -static void override_vif_product_usb4routerlist_fields( - struct vif_Usb4RouterListType_t *router_list) -{ - char name[80]; - char tag_value[80]; - char str_value[80]; - int router_index = 0; - - while (get_next_tag(name, tag_value, str_value)) { - if (streq(name, "/USB4RouterList")) - break; - - if (streq(name, "Usb4Router")) - override_vif_product_usb4router_fields( - &router_list[router_index++]); - else - fprintf(stderr, - "VIF/Product/USB4RouterList:" - " Unknown tag '%s'\n", name); - } -} - -static void override_vif_product_fields(struct vif_Product_t *vif_product) -{ - char name[80]; - char tag_value[80]; - char str_value[80]; - - while (get_next_tag(name, tag_value, str_value)) { - if (streq(name, "/Product")) - break; - - if (streq(name, "USB4RouterList")) - override_vif_product_usb4routerlist_fields( - vif_product->USB4RouterList); - else { - int i; - - for (i = 0; i < Product_Indexes; i++) - if (streq(name, vif_product_name[i])) - break; - if (i != Product_Indexes) - set_override_vif_field( - &vif_product->vif_field[i], - vif_product_name[i], - tag_value, - str_value); - else - fprintf(stderr, - "VIFF/Product:" - " Unknown tag '%s'\n", name); - } - } -} - -static void override_vif_component_src_pdo_fields( - struct vif_srcPdoList_t *vif_src_pdo) -{ - char name[80]; - char tag_value[80]; - char str_value[80]; - - while (get_next_tag(name, tag_value, str_value)) { - int i; - - if (streq(name, "/SrcPdo")) - break; - - for (i = 0; i < Src_PDO_Indexes; i++) - if (streq(name, vif_component_src_pdo_name[i])) - break; - if (i != Src_PDO_Indexes) - set_override_vif_field( - &vif_src_pdo->vif_field[i], - vif_component_src_pdo_name[i], - tag_value, - str_value); - else - fprintf(stderr, - "VIF/Component/SrcPdo:" - " Unknown tag '%s'\n", name); - } -} -static void override_vif_component_src_pdo_list_fields( - struct vif_srcPdoList_t *vif_src_pdo_list) -{ - char name[80]; - char tag_value[80]; - char str_value[80]; - int src_pdo_index = 0; - - while (get_next_tag(name, tag_value, str_value)) { - if (streq(name, "/SrcPdoList")) - break; - - if (streq(name, "SrcPdo")) - override_vif_component_src_pdo_fields( - &vif_src_pdo_list[src_pdo_index++]); - else - fprintf(stderr, - "VIF/Component/SrcPdoList:" - " Unknown tag '%s'\n", name); - } -} - -static void override_vif_component_snk_pdo_fields( - struct vif_snkPdoList_t *vif_snk_pdo) -{ - char name[80]; - char tag_value[80]; - char str_value[80]; - - while (get_next_tag(name, tag_value, str_value)) { - int i; - - if (streq(name, "/SnkPdo")) - break; - - for (i = 0; i < Snk_PDO_Indexes; i++) - if (streq(name, vif_component_snk_pdo_name[i])) - break; - if (i != Snk_PDO_Indexes) - set_override_vif_field( - &vif_snk_pdo->vif_field[i], - vif_component_snk_pdo_name[i], - tag_value, - str_value); - else - fprintf(stderr, - "VIF/Component/SnkPdo:" - " Unknown tag '%s'\n", name); - } -} -static void override_vif_component_snk_pdo_list_fields( - struct vif_snkPdoList_t *vif_snk_pdo_list) -{ - char name[80]; - char tag_value[80]; - char str_value[80]; - int snk_pdo_index = 0; - - while (get_next_tag(name, tag_value, str_value)) { - if (streq(name, "/SnkPdoList")) - break; - - if (streq(name, "SnkPdo")) - override_vif_component_snk_pdo_fields( - &vif_snk_pdo_list[snk_pdo_index++]); - else - fprintf(stderr, - "VIF/Component/SnkPdoList:" - " Unknown tag '%s'\n", name); - } -} - -static void override_vif_component_sop_svid_mode_fields( - struct vif_sopSVIDModeList_t *svid_mode) -{ - char name[80]; - char tag_value[80]; - char str_value[80]; - - while (get_next_tag(name, tag_value, str_value)) { - int i; - - if (streq(name, "/SOPSVIDMode")) - break; - - for (i = 0; i < SopSVID_Indexes; i++) - if (streq(name, vif_component_sop_svid_mode_name[i])) - break; - if (i != SopSVID_Indexes) - set_override_vif_field( - &svid_mode->vif_field[i], - vif_component_sop_svid_mode_name[i], - tag_value, - str_value); - else - fprintf(stderr, - "VIF/Component/SOPSVIDMode:" - " Unknown tag '%s'\n", name); - } -} -static void override_vif_component_sop_svid_mode_list_fields( - struct vif_sopSVIDModeList_t *svid_mode_list) -{ - char name[80]; - char tag_value[80]; - char str_value[80]; - int mode_index = 0; - - while (get_next_tag(name, tag_value, str_value)) { - if (streq(name, "/SOPSVIDModeList")) - break; - - if (streq(name, "SOPSVIDMode")) - override_vif_component_sop_svid_mode_fields( - &svid_mode_list[mode_index++]); - else - fprintf(stderr, - "VIF/Component/SOPSVIDModeList:" - " Unknown tag '%s'\n", name); - } -} - -static void override_vif_component_sop_svid_fields( - struct vif_sopSVIDList_t *vif_sop_svid) -{ - char name[80]; - char tag_value[80]; - char str_value[80]; - - while (get_next_tag(name, tag_value, str_value)) { - if (streq(name, "/SOPSVID")) - break; - - if (streq(name, "SOPSVIDModeList")) - override_vif_component_sop_svid_mode_list_fields( - vif_sop_svid->SOPSVIDModeList); - else { - int i; - - for (i = 0; i < SopSVID_Indexes; i++) - if (streq(name, - vif_component_sop_svid_name[i])) - break; - if (i != SopSVID_Indexes) - set_override_vif_field( - &vif_sop_svid->vif_field[i], - vif_component_sop_svid_name[i], - tag_value, - str_value); - else - fprintf(stderr, - "VIF/Component/SOPSVID:" - " Unknown tag '%s'\n", name); - } - } -} -static void override_vif_component_sop_svid_list_fields( - struct vif_sopSVIDList_t *vif_sop_svid_list) -{ - char name[80]; - char tag_value[80]; - char str_value[80]; - int sop_svid_index = 0; - - while (get_next_tag(name, tag_value, str_value)) { - if (streq(name, "/SOPSVIDList")) - break; - - if (streq(name, "SOPSVID")) - override_vif_component_sop_svid_fields( - &vif_sop_svid_list[sop_svid_index++]); - else - fprintf(stderr, - "VIF/Component/SOPSVIDList:" - " Unknown tag '%s'\n", name); - } -} - -static void override_vif_component_cable_svid_mode_fields( - struct vif_cableSVIDModeList_t *vif_cable_mode) -{ - char name[80]; - char tag_value[80]; - char str_value[80]; - - while (get_next_tag(name, tag_value, str_value)) { - int i; - - if (streq(name, "/CableSVIDMode")) - break; - - for (i = 0; i < CableSVID_Mode_Indexes; i++) - if (streq(name, vif_cable_mode_name[i])) - break; - if (i != CableSVID_Mode_Indexes) - set_override_vif_field( - &vif_cable_mode->vif_field[i], - vif_cable_mode_name[i], - tag_value, - str_value); - else - fprintf(stderr, - "VIF/Component/CableSVIDMode:" - " Unknown tag '%s'\n", name); - } -} -static void override_vif_component_cable_svid_mode_list_fields( - struct vif_cableSVIDModeList_t *vif_cable_mode_list) -{ - char name[80]; - char tag_value[80]; - char str_value[80]; - int mode_index = 0; - - while (get_next_tag(name, tag_value, str_value)) { - if (streq(name, "/CableSVIDModeList")) - break; - - if (streq(name, "CableSVIDMode")) - override_vif_component_cable_svid_mode_fields( - &vif_cable_mode_list[mode_index++]); - else - fprintf(stderr, - "VIF/Component/CableSVIDModeList:" - " Unknown tag '%s'\n", name); - } -} - -static void override_vif_component_cable_svid_fields( - struct vif_cableSVIDList_t *vif_cable_svid) -{ - char name[80]; - char tag_value[80]; - char str_value[80]; - int mode_index = 0; - - while (get_next_tag(name, tag_value, str_value)) { - if (streq(name, "/CableSVID")) - break; - - if (streq(name, "CableSVIDModeList")) - override_vif_component_cable_svid_mode_list_fields( - &vif_cable_svid->CableSVIDModeList[ - mode_index++]); - else { - int i; - - for (i = 0; i < CableSVID_Indexes; i++) - if (streq(name, vif_cable_svid_name[i])) - break; - if (i != CableSVID_Indexes) - set_override_vif_field( - &vif_cable_svid->vif_field[i], - vif_cable_svid_name[i], - tag_value, - str_value); - else - fprintf(stderr, - "VIF/Component/CableSVID:" - " Unknown tag '%s'\n", name); - } - } -} -static void override_vif_component_cable_svid_list_fields( - struct vif_cableSVIDList_t *vif_cable_svid_list) -{ - char name[80]; - char tag_value[80]; - char str_value[80]; - int cable_svid_index = 0; - - while (get_next_tag(name, tag_value, str_value)) { - if (streq(name, "/CableSVIDList")) - break; - - if (streq(name, "CableSVID")) - override_vif_component_cable_svid_fields( - &vif_cable_svid_list[cable_svid_index++]); - else - fprintf(stderr, - "VIF/Component/CableSVIDList:" - " Unknown tag '%s'\n", name); - } -} - -static void override_vif_component_fields( - struct vif_Component_t *vif_component) -{ - char name[80]; - char tag_value[80]; - char str_value[80]; - - while (get_next_tag(name, tag_value, str_value)) { - if (streq(name, "/Component")) - break; - - if (streq(name, "SrcPdoList")) - override_vif_component_src_pdo_list_fields( - vif_component->SrcPdoList); - else if (streq(name, "SnkPdoList")) - override_vif_component_snk_pdo_list_fields( - vif_component->SnkPdoList); - else if (streq(name, "SOPSVIDList")) - override_vif_component_sop_svid_list_fields( - vif_component->SOPSVIDList); - else if (streq(name, "CableSVIDList")) - override_vif_component_cable_svid_list_fields( - vif_component->CableSVIDList); - else { - int i; - - for (i = 0; i < Component_Indexes; i++) - if (streq(name, vif_component_name[i])) - break; - if (i != Component_Indexes) - set_override_vif_field( - &vif_component->vif_field[i], - vif_component_name[i], - tag_value, - str_value); - else - fprintf(stderr, - "VIF/Component:" - " Unknown tag '%s'\n", name); - } - } -} - -static void override_vif_app_fields(struct vif_t *vif) -{ - char name[80]; - char tag_value[80]; - char str_value[80]; - - while (get_next_tag(name, tag_value, str_value)) { - int i; - - if (streq(name, "/VIF_App")) - break; - - for (i = 0; i < VIF_App_Indexes; i++) - if (streq(name, vif_app_name[i])) - break; - if (i == VIF_App_Indexes) - fprintf(stderr, - "VIFF/VIF_App:" - " Unknown tag '%s'\n", name); - } -} - -static void override_vif_fields(struct vif_t *vif) -{ - char name[80]; - char tag_value[80]; - char str_value[80]; - - component_index = 0; - while (get_next_tag(name, tag_value, str_value)) { - if (streq(name, "/VIF")) - break; - - if (streq(name, "VIF_App")) - override_vif_app_fields(vif); - else if (streq(name, "Component")) - override_vif_component_fields( - &vif->Component[component_index++]); - else if (streq(name, "Product")) - override_vif_product_fields(&vif->Product); - else { - int i; - - for (i = 0; i < VIF_Indexes; i++) - if (streq(name, vif_name[i])) - break; - if (i != VIF_Indexes) - set_override_vif_field( - &vif->vif_field[i], - vif_name[i], - tag_value, - str_value); - else - fprintf(stderr, - "VIF:" - " Unknown tag '%s'\n", name); - } - } - - /* - * Don't care what they requested, I am making the file and that - * means VIF/VIF_App is to be set by me. - */ - set_override_vif_field(&vif->vif_app_field[Vendor], - vif_app_name[Vendor], - NULL, - VIF_APP_VENDOR_VALUE); - - set_override_vif_field(&vif->vif_app_field[Name], - vif_app_name[Name], - NULL, - VIF_APP_NAME_VALUE); - - set_override_vif_field(&vif->vif_app_field[Version], - vif_app_name[Version], - NULL, - VIF_APP_VERSION_VALUE); -} - -static int override_gen_vif(char *over_name, struct vif_t *vif) -{ - char name[80]; - char tag_value[80]; - char str_value[80]; - - if (!ov_open(over_name)) { - fprintf(stderr, "Override file '%s' could not be opened\n", - over_name); - return 1; - } - - while (get_next_tag(name, tag_value, str_value)) { - if (streq(name, "VIF")) - override_vif_fields(vif); - else - fprintf(stderr, - "Unknown tag '%s'\n", name); - } - - ov_close(); - return 0; -} -/* - * VIF Structure Override from XML file functions - *****************************************************************************/ - - -/***************************************************************************** - * VIF Structure Initialization Helper Functions - */ -static void set_vif_field(struct vif_field_t *vif_field, - const char *name, - const char *tag_value, - const char *str_value) -{ - char *ptr; - - /* - * Override already set or trying to set to nothing should do - * nothing. Just return - */ - if ((vif_field->name || vif_field->str_value || vif_field->tag_value) || - (str_value == NULL && tag_value == NULL)) - return; - - vif_field->name = name; - if (tag_value) { - ptr = malloc(strlen(tag_value)+1); - strcpy(ptr, tag_value); - vif_field->tag_value = ptr; - } - if (str_value) { - ptr = malloc(strlen(str_value)+1); - strcpy(ptr, str_value); - vif_field->str_value = ptr; - } -} -__maybe_unused static void set_vif_field_b(struct vif_field_t *vif_field, - const char *name, - const bool val) -{ - if (val) - set_vif_field(vif_field, name, "true", "YES"); - else - set_vif_field(vif_field, name, "false", "NO"); -} -__maybe_unused static void set_vif_field_stis(struct vif_field_t *vif_field, - const char *name, - const char *tag_value, - const int str_value) -{ - char str_str[20]; - - sprintf(str_str, "%d", str_value); - set_vif_field(vif_field, name, tag_value, str_str); -} -__maybe_unused static void set_vif_field_itss(struct vif_field_t *vif_field, - const char *name, - const int tag_value, - const char *str_value) -{ - char str_tag[20]; - - sprintf(str_tag, "%d", tag_value); - set_vif_field(vif_field, name, str_tag, str_value); -} -__maybe_unused static void set_vif_field_itis(struct vif_field_t *vif_field, - const char *name, - const int tag_value, - const int str_value) -{ - char str_tag[20]; - char str_str[20]; - - sprintf(str_tag, "%d", tag_value); - sprintf(str_str, "%d", str_value); - set_vif_field(vif_field, name, str_tag, str_str); -} -/* - * VIF Structure Initialization Helper Functions - *****************************************************************************/ - -/***************************************************************************** - * VIF Structure Initialization from Config Functions - */ -/* - * TODO: Generic todo to fill in additional fields as the need presents - * itself - * - * Fields that are not currently being initialized - * - * vif_Component USB4 Port Fields - * USB4_Lane_0_Adapter numericFieldType - * USB4_Max_Speed numericFieldType - * USB4_DFP_Supported booleanFieldType - * USB4_UFP_Supported booleanFieldType - * USB4_USB3_Tunneling_Supported booleanFieldType - * USB4_DP_Tunneling_Supported booleanFieldType - * USB4_PCIe_Tunneling_Supported booleanFieldType - * USB4_TBT3_Compatibility_Supported booleanFieldType - * USB4_CL1_State_Supported booleanFieldType - * USB4_CL2_State_Supported booleanFieldType - * USB4_Num_Retimers numericFieldType - * USB4_DP_Bit_Rate numericFieldType - * USB4_Num_DP_Lanes numericFieldType - * - * vif_Component USB4 Product Fields - * USB4_Dock booleanFieldType - * USB4_Num_Internal_Host_Controllers numericFieldType - * USB4_Num_PCIe_DN_Bridges numericFieldType - * - * vif_Component USB4 Device Class Fallback Support - * USB4_Audio_Supported booleanFieldType - * USB4_HID_Supported booleanFieldType - * USB4_Printer_Supported booleanFieldType - * USB4_Mass_Storage_Supported booleanFieldType - * USB4_Video_Supported booleanFieldType - * USB4_Comms_Networking_Supported booleanFieldType - * USB4_Media_Transfer_Protocol_Supported booleanFieldType - * USB4_Smart_Card_Supported booleanFieldType - * USB4_Still_Image_Capture_Supported booleanFieldType - * USB4_Monitor_Device_Supported booleanFieldType - * - * vif_Usb4RouterListType USB4 Router Fields - * USB4_Router_ID numericFieldType - * USB4_Silicon_VID numericFieldType - * USB4_Num_Lane_Adapters numericFieldType - * USB4_Num_USB3_DN_Adapters numericFieldType - * USB4_Num_DP_IN_Adapters numericFieldType - * USB4_Num_DP_OUT_Adapters numericFieldType - * USB4_Num_PCIe_DN_Adapters numericFieldType - * USB4_TBT3_Not_Supported numericFieldType - * USB4_PCIe_Wake_Supported booleanFieldType - * USB4_USB3_Wake_Supported booleanFieldType - * USB4_Num_Unused_Adapters numericFieldType - * USB4_TBT3_VID numericFieldType - * USB4_PCIe_Switch_Vendor_ID numericFieldType - * USB4_PCIe_Switch_Device_ID numericFieldType - * USB4_Num_PCIe_Endpoints numericFieldType - * - * vif_PCIeEndpointListType PCIe Endpoint Fields - * USB4_PCIe_Endpoint_Vendor_ID numericFieldType - * USB4_PCIe_Endpoint_Device_ID numericFieldType - * USB4_PCIe_Endpoint_Class_Code numericFieldType - * - * vif_sopSVIDList SOP SVIDs - * SVID_SOP numericFieldType - * SVID_Modes_Fixed_SOP booleanFieldType - * SVID_Num_Modes_Min_SOP numericFieldType - * SVID_Num_Modes_Max_SOP numericFieldType - * - * vif_sopSVIDModeList SOP SVID Modes - * SVID_Mode_Enter_SOP booleanFieldType - * SVID_Mode_Recog_Mask_SOP numericFieldType - * SVID_Mode_Recog_Value_SOP numericFieldType - * - * vif_Component Alternate Mode Adapter Fields - * AMA_HW_Vers numericFieldType - * AMA_FW_Vers numericFieldType - * AMA_VCONN_Power booleanFieldType - * AMA_VCONN_Reqd booleanFieldType - * AMA_VBUS_Reqd booleanFieldType - * AMA_Superspeed_Support numericFieldType - * - * vif_Component Cable/eMarker Fields - * XID numericFieldType - * Data_Capable_As_USB_Host booleanFieldType - * Data_Capable_As_USB_Device booleanFieldType - * Product_Type numericFieldType - * Modal_Operation_Supported booleanFieldType - * USB_VID numericFieldType - * PID numericFieldType - * bcdDevice numericFieldType - * Cable_HW_Vers numericFieldType - * Cable_FW_Vers numericFieldType - * Type_C_To_Type_A_B_C numericFieldType - * Type_C_To_Type_C_Capt_Vdm_V2 numericFieldType - * Cable_Latency numericFieldType - * Cable_Termination_Type numericFieldType - * Cable_VBUS_Current numericFieldType - * VBUS_Through_Cable booleanFieldType - * Cable_Superspeed_Support numericFieldType - * Cable_USB_Highest_Speed numericFieldType - * Max_VBUS_Voltage_Vdm_V2 numericFieldType - * Manufacturer_Info_Supported, booleanFieldType - * Manufacturer_Info_VID, numericFieldType - * Manufacturer_Info_PID, numericFieldType - * Chunking_Implemented booleanFieldType - * Security_Msgs_Supported booleanFieldType - * ID_Header_Connector_Type numericFieldType - * Cable_Num_SVIDs_Min numericFieldType - * Cable_Num_SVIDs_Max numericFieldType - * SVID_Fixed booleanFieldType - * - * vif_cableSVIDList Cable SVIDs - * SVID numericFieldType - * SVID_Modes_Fixed booleanFieldType - * SVID_Num_Modes_Min numericFieldType - * SVID_Num_Modes_Max numericFieldType - * - * vif_cableSVIDModeList Cable SVID Modes - * SVID_Mode_Enter booleanFieldType - * SVID_Mode_Recog_Mask numericFieldType - * SVID_Mode_Recog_Value numericFieldType - * - * vif_Component Active Cable Fields - * Cable_SOP_PP_Controller booleanFieldType - * SBU_Supported booleanFieldType - * SBU_Type numericFieldType - * Active_Cable_Operating_Temp_Support booleanFieldType - * Active_Cable_Max_Operating_Temp numericFieldType - * Active_Cable_Shutdown_Temp_Support booleanFieldType - * Active_Cable_Shutdown_Temp numericFieldType - * Active_Cable_U3_CLd_Power numericFieldType - * Active_Cable_U3_U0_Trans_Mode numericFieldType - * Active_Cable_Physical_Connection numericFieldType - * Active_Cable_Active_Element numericFieldType - * Active_Cable_USB4_Support booleanFieldType - * Active_Cable_USB2_Supported booleanFieldType - * Active_Cable_USB2_Hub_Hops_Consumed numericFieldType - * Active_Cable_USB32_Supported booleanFieldType - * Active_Cable_USB_Lanes numericFieldType - * Active_Cable_Optically_Isolated booleanFieldType - * Active_Cable_USB_Gen numericFieldType - * - * vif_Component VCONN Powered Device - * VPD_HW_Vers numericFieldType - * VPD_FW_Vers numericFieldType - * VPD_Max_VBUS_Voltage numericFieldType - * VPD_Charge_Through_Support booleanFieldType - * VPD_Charge_Through_Current numericFieldType - * VPD_VBUS_Impedance numericFieldType - * VPD_Ground_Impedance numericFieldType - * - * vif_Component Repeater Fields - * Repeater_One_Type numericFieldType - * Repeater_Two_Type numericFieldType - */ - -__maybe_unused static int32_t init_vif_snk_pdo(struct vif_snkPdoList_t *snkPdo, - uint32_t pdo) -{ - int32_t power_mw; - char str[40]; - - /********************************************************************* - * Sink PDOs - */ - if ((pdo & PDO_TYPE_MASK) == PDO_TYPE_FIXED) { - uint32_t current = pdo & 0x3ff; - uint32_t current_ma = current * 10; - uint32_t voltage = (pdo >> 10) & 0x3ff; - uint32_t voltage_mv = voltage * 50; - - power_mw = (current_ma * voltage_mv) / 1000; - - set_vif_field(&snkPdo->vif_field[Snk_PDO_Supply_Type], - vif_component_snk_pdo_name[Snk_PDO_Supply_Type], - "0", "Fixed"); - sprintf(str, "%d mV", voltage_mv); - set_vif_field_itss(&snkPdo->vif_field[Snk_PDO_Voltage], - vif_component_snk_pdo_name[Snk_PDO_Voltage], - voltage, str); - sprintf(str, "%d mA", current_ma); - set_vif_field_itss(&snkPdo->vif_field[Snk_PDO_Op_Current], - vif_component_snk_pdo_name[Snk_PDO_Op_Current], - current, str); - - } else if ((pdo & PDO_TYPE_MASK) == PDO_TYPE_BATTERY) { - uint32_t max_voltage = (pdo >> 20) & 0x3ff; - uint32_t max_voltage_mv = max_voltage * 50; - uint32_t min_voltage = (pdo >> 10) & 0x3ff; - uint32_t min_voltage_mv = min_voltage * 50; - int32_t power; - - power = pdo & 0x3ff; - power_mw = power * 250; - - set_vif_field(&snkPdo->vif_field[Snk_PDO_Supply_Type], - vif_component_snk_pdo_name[Snk_PDO_Supply_Type], - "1", "Battery"); - sprintf(str, "%d mV", min_voltage_mv); - set_vif_field_itss(&snkPdo->vif_field[Snk_PDO_Min_Voltage], - vif_component_snk_pdo_name[Snk_PDO_Min_Voltage], - min_voltage, str); - sprintf(str, "%d mV", max_voltage_mv); - set_vif_field_itss(&snkPdo->vif_field[Snk_PDO_Max_Voltage], - vif_component_snk_pdo_name[Snk_PDO_Max_Voltage], - max_voltage, str); - sprintf(str, "%d mW", power_mw); - set_vif_field_itss(&snkPdo->vif_field[Snk_PDO_Op_Power], - vif_component_snk_pdo_name[Snk_PDO_Op_Power], - power, str); - - } else if ((pdo & PDO_TYPE_MASK) == PDO_TYPE_VARIABLE) { - uint32_t max_voltage = (pdo >> 20) & 0x3ff; - uint32_t max_voltage_mv = max_voltage * 50; - uint32_t min_voltage = (pdo >> 10) & 0x3ff; - uint32_t min_voltage_mv = min_voltage * 50; - uint32_t current = pdo & 0x3ff; - uint32_t current_ma = current * 10; - - power_mw = (current_ma * max_voltage_mv) / 1000; - - set_vif_field(&snkPdo->vif_field[Snk_PDO_Supply_Type], - vif_component_snk_pdo_name[Snk_PDO_Supply_Type], - "2", "Variable"); - sprintf(str, "%d mV", min_voltage_mv); - set_vif_field_itss(&snkPdo->vif_field[Snk_PDO_Min_Voltage], - vif_component_snk_pdo_name[Snk_PDO_Min_Voltage], - min_voltage, str); - sprintf(str, "%d mV", max_voltage_mv); - set_vif_field_itss(&snkPdo->vif_field[Snk_PDO_Max_Voltage], - vif_component_snk_pdo_name[Snk_PDO_Max_Voltage], - max_voltage, str); - sprintf(str, "%d mA", current_ma); - set_vif_field_itss(&snkPdo->vif_field[Snk_PDO_Op_Current], - vif_component_snk_pdo_name[Snk_PDO_Op_Current], - current, str); - - } else if ((pdo & PDO_TYPE_MASK) == PDO_TYPE_AUGMENTED) { - uint32_t pps = (pdo >> 28) & 3; - uint32_t pps_max_voltage = (pdo >> 17) & 0xff; - uint32_t pps_max_voltage_mv = pps_max_voltage * 100; - uint32_t pps_min_voltage = (pdo >> 8) & 0xff; - uint32_t pps_min_voltage_mv = pps_min_voltage * 100; - uint32_t pps_current = pdo & 0x7f; - uint32_t pps_current_ma = pps_current * 50; - - if (pps) { - fprintf(stderr, "ERROR: Invalid PDO_TYPE %d.\n", pdo); - return -1; - } - - power_mw = (pps_current_ma * pps_max_voltage_mv) / 1000; - - set_vif_field(&snkPdo->vif_field[Snk_PDO_Supply_Type], - vif_component_snk_pdo_name[Snk_PDO_Supply_Type], - "3", "PPS"); - sprintf(str, "%d mA", pps_current_ma); - set_vif_field_itss(&snkPdo->vif_field[Snk_PDO_Op_Current], - vif_component_snk_pdo_name[Snk_PDO_Op_Current], - pps_current, str); - sprintf(str, "%d mV", pps_min_voltage_mv); - set_vif_field_itss(&snkPdo->vif_field[Snk_PDO_Min_Voltage], - vif_component_snk_pdo_name[Snk_PDO_Min_Voltage], - pps_min_voltage, str); - sprintf(str, "%d mV", pps_max_voltage_mv); - set_vif_field_itss(&snkPdo->vif_field[Snk_PDO_Max_Voltage], - vif_component_snk_pdo_name[Snk_PDO_Max_Voltage], - pps_max_voltage, str); - } else { - fprintf(stderr, "ERROR: Invalid PDO_TYPE %d.\n", pdo); - return -1; - } - - return power_mw; -} - -__maybe_unused static int32_t init_vif_src_pdo(struct vif_srcPdoList_t *srcPdo, - uint32_t pdo) -{ - int32_t power_mw; - char str[40]; - - /********************************************************************* - * Source PDOs - * - * TODO: Generic todo to fill in additional fields as the need presents - * itself - * - * Fields that are not currently being initialized - * - * vif_srcPdoList - * Src_PD_OCP_OC_Debounce numericFieldType - * Src_PD_OCP_OC_Threshold numericFieldType - * Src_PD_OCP_UV_Debounce numericFieldType - * Src_PD_OCP_UV_Threshold_Type numericFieldType - * Src_PD_OCP_UV_Threshold numericFieldType - */ - if ((pdo & PDO_TYPE_MASK) == PDO_TYPE_FIXED) { - uint32_t current = pdo & 0x3ff; - uint32_t current_ma = current * 10; - uint32_t voltage = (pdo >> 10) & 0x3ff; - uint32_t voltage_mv = voltage * 50; - - power_mw = (current_ma * voltage_mv) / 1000; - - set_vif_field(&srcPdo->vif_field[Src_PDO_Supply_Type], - vif_component_src_pdo_name[Src_PDO_Supply_Type], - "0", "Fixed"); - set_vif_field(&srcPdo->vif_field[Src_PDO_Peak_Current], - vif_component_src_pdo_name[Src_PDO_Peak_Current], - "0", "100% IOC"); - sprintf(str, "%d mV", voltage_mv); - set_vif_field_itss(&srcPdo->vif_field[Src_PDO_Voltage], - vif_component_src_pdo_name[Src_PDO_Voltage], - voltage, str); - sprintf(str, "%d mA", current_ma); - set_vif_field_itss(&srcPdo->vif_field[Src_PDO_Max_Current], - vif_component_src_pdo_name[Src_PDO_Max_Current], - current, str); - - } else if ((pdo & PDO_TYPE_MASK) == PDO_TYPE_BATTERY) { - uint32_t max_voltage = (pdo >> 20) & 0x3ff; - uint32_t max_voltage_mv = max_voltage * 50; - uint32_t min_voltage = (pdo >> 10) & 0x3ff; - uint32_t min_voltage_mv = min_voltage * 50; - int32_t power; - - power = pdo & 0x3ff; - power_mw = power * 250; - - set_vif_field(&srcPdo->vif_field[Src_PDO_Supply_Type], - vif_component_src_pdo_name[Src_PDO_Supply_Type], - "1", "Battery"); - sprintf(str, "%d mV", min_voltage_mv); - set_vif_field_itss(&srcPdo->vif_field[Src_PDO_Min_Voltage], - vif_component_src_pdo_name[Src_PDO_Min_Voltage], - min_voltage, str); - sprintf(str, "%d mV", max_voltage_mv); - set_vif_field_itss(&srcPdo->vif_field[Src_PDO_Max_Voltage], - vif_component_src_pdo_name[Src_PDO_Max_Voltage], - max_voltage, str); - sprintf(str, "%d mW", power_mw); - set_vif_field_itss(&srcPdo->vif_field[Src_PDO_Max_Power], - vif_component_src_pdo_name[Src_PDO_Max_Power], - power, str); - - } else if ((pdo & PDO_TYPE_MASK) == PDO_TYPE_VARIABLE) { - uint32_t max_voltage = (pdo >> 20) & 0x3ff; - uint32_t max_voltage_mv = max_voltage * 50; - uint32_t min_voltage = (pdo >> 10) & 0x3ff; - uint32_t min_voltage_mv = min_voltage * 50; - uint32_t current = pdo & 0x3ff; - uint32_t current_ma = current * 10; - - power_mw = (current_ma * max_voltage_mv) / 1000; - - set_vif_field(&srcPdo->vif_field[Src_PDO_Supply_Type], - vif_component_src_pdo_name[Src_PDO_Supply_Type], - "2", "Variable"); - set_vif_field(&srcPdo->vif_field[Src_PDO_Peak_Current], - vif_component_src_pdo_name[Src_PDO_Peak_Current], - "0", "100% IOC"); - sprintf(str, "%d mV", min_voltage_mv); - set_vif_field_itss(&srcPdo->vif_field[Src_PDO_Min_Voltage], - vif_component_src_pdo_name[Src_PDO_Min_Voltage], - min_voltage, str); - sprintf(str, "%d mV", max_voltage_mv); - set_vif_field_itss(&srcPdo->vif_field[Src_PDO_Max_Voltage], - vif_component_src_pdo_name[Src_PDO_Max_Voltage], - max_voltage, str); - sprintf(str, "%d mA", current_ma); - set_vif_field_itss(&srcPdo->vif_field[Src_PDO_Max_Current], - vif_component_src_pdo_name[Src_PDO_Max_Current], - current, str); - - } else if ((pdo & PDO_TYPE_MASK) == PDO_TYPE_AUGMENTED) { - uint32_t pps = (pdo >> 28) & 3; - uint32_t pps_max_voltage = (pdo >> 17) & 0xff; - uint32_t pps_max_voltage_mv = pps_max_voltage * 100; - uint32_t pps_min_voltage = (pdo >> 8) & 0xff; - uint32_t pps_min_voltage_mv = pps_min_voltage * 100; - uint32_t pps_current = pdo & 0x7f; - uint32_t pps_current_ma = pps_current * 50; - - if (pps) { - fprintf(stderr, "ERROR: Invalid PDO_TYPE %d.\n", pdo); - return -1; - } - - power_mw = (pps_current_ma * pps_max_voltage_mv) / 1000; - - set_vif_field(&srcPdo->vif_field[Src_PDO_Supply_Type], - vif_component_src_pdo_name[Src_PDO_Supply_Type], - "3", "PPS"); - sprintf(str, "%d mA", pps_current_ma); - set_vif_field_itss(&srcPdo->vif_field[Src_PDO_Max_Current], - vif_component_src_pdo_name[Src_PDO_Max_Current], - pps_current, str); - sprintf(str, "%d mV", pps_min_voltage_mv); - set_vif_field_itss(&srcPdo->vif_field[Src_PDO_Min_Voltage], - vif_component_src_pdo_name[Src_PDO_Min_Voltage], - pps_min_voltage, str); - sprintf(str, "%d mV", pps_max_voltage_mv); - set_vif_field_itss(&srcPdo->vif_field[Src_PDO_Max_Voltage], - vif_component_src_pdo_name[Src_PDO_Max_Voltage], - pps_max_voltage, str); - - } else { - fprintf(stderr, "ERROR: Invalid PDO_TYPE %d.\n", pdo); - return -1; - } - - return power_mw; -} - -/********************************************************************* - * Init VIF Fields - */ -static void init_vif_fields(struct vif_field_t *vif_fields, - struct vif_field_t *vif_app_fields, - const char *board) -{ - set_vif_field(&vif_fields[VIF_Specification], - vif_name[VIF_Specification], - NULL, - "3.12"); - - set_vif_field(&vif_app_fields[Vendor], - vif_app_name[Vendor], - NULL, - VIF_APP_VENDOR_VALUE); - - set_vif_field(&vif_app_fields[Name], - vif_app_name[Name], - NULL, - VIF_APP_NAME_VALUE); - - set_vif_field(&vif_app_fields[Version], - vif_app_name[Version], - NULL, - VIF_APP_VERSION_VALUE); - - set_vif_field(&vif_fields[Vendor_Name], - vif_name[Vendor_Name], - NULL, - VENDOR_NAME_VALUE); - - #if defined(CONFIG_USB_PD_MODEL_PART_NUMBER) - set_vif_field(&vif_fields[Model_Part_Number], - vif_name[Model_Part_Number], - NULL, - CONFIG_USB_PD_MODEL_PART_NUMBER); - #else - if (board && strlen(board) > 0) - set_vif_field(&vif_fields[Model_Part_Number], - vif_name[Model_Part_Number], - NULL, - board); - else - set_vif_field(&vif_fields[Model_Part_Number], - vif_name[Model_Part_Number], - NULL, - "FIX-ME"); - #endif - - #if defined(CONFIG_USB_PD_PRODUCT_REVISION) - set_vif_field(&vif_fields[Product_Revision], - vif_name[Product_Revision], - NULL, - CONFIG_USB_PD_PRODUCT_REVISION); - #else - set_vif_field(&vif_fields[Product_Revision], - vif_name[Product_Revision], - NULL, - "FIX-ME"); - #endif - - #if defined(CONFIG_USB_PD_TID) - set_vif_field_stis(&vif_fields[TID], - vif_name[TID], - NULL, - CONFIG_USB_PD_TID); - #else - set_vif_field_stis(&vif_fields[TID], - vif_name[TID], - NULL, - DEFAULT_MISSING_TID); - #endif - - set_vif_field(&vif_fields[VIF_Product_Type], - vif_name[VIF_Product_Type], - "0", - "Port Product"); - - set_vif_field(&vif_fields[Certification_Type], - vif_name[Certification_Type], - "0", - "End Product"); -} - -/********************************************************************* - * Init VIF/Product Fields - */ -static void init_vif_product_fields(struct vif_field_t *vif_fields) -{ - char hex_str[10]; - - sprintf(hex_str, "%04X", USB_VID_GOOGLE); - set_vif_field_itss(&vif_fields[Product_VID], - vif_product_name[Product_VID], - USB_VID_GOOGLE, hex_str); -} - -/********************************************************************* - * Init VIF/Component[] Fields - */ -static void init_vif_component_fields(struct vif_field_t *vif_fields, - enum bc_1_2_support *bc_support, - enum dtype type) -{ - #if defined(CONFIG_USB_PD_PORT_LABEL) - set_vif_field_stis(&vif_fields[Port_Label], - vif_component_name[Port_Label], - NULL, - CONFIG_USB_PD_PORT_LABEL); - #else - set_vif_field_stis(&vif_fields[Port_Label], - vif_component_name[Port_Label], - NULL, - component_index); - #endif - - set_vif_field(&vif_fields[Connector_Type], - vif_component_name[Connector_Type], - "2", - "Type-C®"); - - if (is_usb4_supported()) { - int router_index; - - set_vif_field_b(&vif_fields[USB4_Supported], - vif_component_name[USB4_Supported], - true); - - if (!get_vif_field_tag_number( - &vif.Product.USB4RouterList[0] - .vif_field[USB4_Router_ID], - &router_index)) { - router_index = 0; - } - set_vif_field_itss(&vif_fields[USB4_Router_Index], - vif_component_name[USB4_Router_Index], - router_index, - NULL); - } else { - set_vif_field_b(&vif_fields[USB4_Supported], - vif_component_name[USB4_Supported], - false); - } - - set_vif_field_b(&vif_fields[USB_PD_Support], - vif_component_name[USB_PD_Support], - is_usb_pd_supported()); - - if (is_usb_pd_supported()) { - switch (type) { - case SNK: - set_vif_field(&vif_fields[PD_Port_Type], - vif_component_name[PD_Port_Type], - "0", - "Consumer Only"); - break; - case SRC: - set_vif_field(&vif_fields[PD_Port_Type], - vif_component_name[PD_Port_Type], - "3", - "Provider Only"); - break; - case DRP: - set_vif_field(&vif_fields[PD_Port_Type], - vif_component_name[PD_Port_Type], - "4", - "DRP"); - break; - } - } - - switch (type) { - case SNK: - set_vif_field(&vif_fields[Type_C_State_Machine], - vif_component_name[Type_C_State_Machine], - "1", - "SNK"); - break; - case SRC: - set_vif_field(&vif_fields[Type_C_State_Machine], - vif_component_name[Type_C_State_Machine], - "0", - "SRC"); - break; - case DRP: - set_vif_field(&vif_fields[Type_C_State_Machine], - vif_component_name[Type_C_State_Machine], - "2", - "DRP"); - break; - } - - set_vif_field_b(&vif_fields[Captive_Cable], - vif_component_name[Captive_Cable], - false); - - set_vif_field_b(&vif_fields[Port_Battery_Powered], - vif_component_name[Port_Battery_Powered], - IS_ENABLED(CONFIG_BATTERY)); - - *bc_support = BC_1_2_SUPPORT_NONE; - if (IS_ENABLED(CONFIG_BC12_DETECT_MAX14637)) - *bc_support = BC_1_2_SUPPORT_PORTABLE_DEVICE; - if (IS_ENABLED(CONFIG_BC12_DETECT_MT6360)) - *bc_support = BC_1_2_SUPPORT_PORTABLE_DEVICE; - if (IS_ENABLED(CONFIG_BC12_DETECT_PI3USB9201)) - *bc_support = BC_1_2_SUPPORT_BOTH; - if (IS_ENABLED(CONFIG_BC12_DETECT_PI3USB9281)) - *bc_support = BC_1_2_SUPPORT_PORTABLE_DEVICE; - - switch (*bc_support) { - case BC_1_2_SUPPORT_NONE: - set_vif_field(&vif_fields[BC_1_2_Support], - vif_component_name[BC_1_2_Support], - "0", - "None"); - break; - case BC_1_2_SUPPORT_PORTABLE_DEVICE: - set_vif_field(&vif_fields[BC_1_2_Support], - vif_component_name[BC_1_2_Support], - "1", - "Portable Device"); - break; - case BC_1_2_SUPPORT_CHARGING_PORT: - set_vif_field(&vif_fields[BC_1_2_Support], - vif_component_name[BC_1_2_Support], - "2", - "Charging Port"); - break; - case BC_1_2_SUPPORT_BOTH: - set_vif_field(&vif_fields[BC_1_2_Support], - vif_component_name[BC_1_2_Support], - "3", - "Both"); - break; - } -} - -/********************************************************************* - * Init VIF/Component[] General PD Fields - */ -static void init_vif_component_general_pd_fields( - struct vif_field_t *vif_fields, - enum dtype type) -{ - if (IS_ENABLED(CONFIG_USB_PD_REV30) || IS_ENABLED(CONFIG_USB_PRL_SM)) { - set_vif_field(&vif_fields[PD_Spec_Revision_Major], - vif_component_name[PD_Spec_Revision_Major], - "3", - NULL); - set_vif_field(&vif_fields[PD_Spec_Revision_Minor], - vif_component_name[PD_Spec_Revision_Minor], - "0", - NULL); - set_vif_field(&vif_fields[PD_Spec_Version_Major], - vif_component_name[PD_Spec_Version_Major], - "2", - NULL); - set_vif_field(&vif_fields[PD_Spec_Version_Minor], - vif_component_name[PD_Spec_Version_Minor], - "0", - NULL); - - set_vif_field(&vif_fields[PD_Specification_Revision], - vif_component_name[PD_Specification_Revision], - "2", - "Revision 3"); - } else { - set_vif_field(&vif_fields[PD_Spec_Revision_Major], - vif_component_name[PD_Spec_Revision_Major], - "2", - NULL); - set_vif_field(&vif_fields[PD_Spec_Revision_Minor], - vif_component_name[PD_Spec_Revision_Minor], - "0", - NULL); - set_vif_field(&vif_fields[PD_Spec_Version_Major], - vif_component_name[PD_Spec_Version_Major], - "1", - NULL); - set_vif_field(&vif_fields[PD_Spec_Version_Minor], - vif_component_name[PD_Spec_Version_Minor], - "3", - NULL); - - set_vif_field(&vif_fields[PD_Specification_Revision], - vif_component_name[PD_Specification_Revision], - "1", - "Revision 2"); - } - - set_vif_field_b(&vif_fields[USB_Comms_Capable], - vif_component_name[USB_Comms_Capable], - is_usb_comms_capable()); - - /* - * DR_Swap_To_DFP_Supported - * - * Set to YES if Qualifying Product can respond with an Accept to a - * DR_Swap request to switch from a UFP to a DFP. - * - * If Type_C_State_Machine is set to DRP and Type_C_Can_Act_As_Host - * is set to YES and Type_C_Can_Act_As_Device is set to NO then this - * field shall be set to YES. - * - * If Type_C_State_Machine is set to SNK and either - * Type_C_Can_Act_As_Host or Type_C_Is_Alt_Mode_Controller is set to - * YES, then this field shall be set to YES. - * - * If Type_C_State_Machine is set to SRC and Type_C_Can_Act_As_Device - * is set to YES, then this field shall be set to YES. - * - * If VIF_Product_Type is set to 1 (Cable) or PD_Port_Type is set to - * 5 (eMarker) then this field shall be ignored by Testers. - * - * TODO(b/172437046): USB4 has not been added and this last statement - * needs to be handled when it is: - * If USB4_DFP_Supported is set to YES and Type_C_Port_On_Hub is set - * to NO, then this field shall be set to YES. - */ - { - bool supports_to_dfp = false; - - switch (type) { - case SRC: - supports_to_dfp = can_act_as_device(); - break; - case SNK: - supports_to_dfp = (can_act_as_host() || - is_alt_mode_controller()); - break; - case DRP: - supports_to_dfp = (can_act_as_host() && - !can_act_as_device()); - break; - } - - set_vif_field_b(&vif_fields[DR_Swap_To_DFP_Supported], - vif_component_name[DR_Swap_To_DFP_Supported], - supports_to_dfp); - } - - /* - * DR_Swap_To_UFP_Supported - * - * Set to YES if Qualifying Product can respond with an Accept to a - * DR_Swap request to switch from a DFP to a UFP. - * - * If Type_C_State_Machine is set to DRP and Type_C_Can_Act_As_Device - * is set to YES and Type_C_Can_Act_As_Host is set to NO then this - * field shall be set to YES. - * - * If Type_C_State_Machine is set to SNK and either - * Type_C_Can_Act_As_Host or Type_C_Is_Alt_Mode_Controller is set to - * YES, then this field shall be set to YES. - * - * If Type_C_State_Machine is set to SRC and Type_C_Can_Act_As_Device - * is set to YES, then this field shall be set to YES. - * - * If VIF_Product_Type is set to 1 (Cable) or PD_Port_Type is set to - * 5 (eMarker) then this field shall be ignored by Testers. - */ - { - bool supports_to_ufp = false; - - switch (type) { - case SRC: - supports_to_ufp = can_act_as_device(); - break; - case SNK: - supports_to_ufp = (can_act_as_host() || - is_alt_mode_controller()); - break; - case DRP: - supports_to_ufp = (can_act_as_device() && - !can_act_as_host()); - break; - } - - set_vif_field_b(&vif_fields[DR_Swap_To_UFP_Supported], - vif_component_name[DR_Swap_To_UFP_Supported], - supports_to_ufp); - } - - if (is_src()) { - /* SRC capable */ - if (IS_ENABLED(CONFIG_CHARGER)) - /* USB-C UP bit set */ - set_vif_field_b(&vif_fields[Unconstrained_Power], - vif_component_name[Unconstrained_Power], - (src_pdo[0] & PDO_FIXED_UNCONSTRAINED)); - else { - /* Barrel charger being used */ - int32_t dedicated_charge_port_count = 0; - - #ifdef CONFIG_DEDICATED_CHARGE_PORT_COUNT - dedicated_charge_port_count = - CONFIG_DEDICATED_CHARGE_PORT_COUNT; - #endif - - set_vif_field_b(&vif_fields[Unconstrained_Power], - vif_component_name[Unconstrained_Power], - (dedicated_charge_port_count > 0)); - } - } else { - /* Not SRC capable */ - set_vif_field_b(&vif_fields[Unconstrained_Power], - vif_component_name[Unconstrained_Power], - false); - } - - set_vif_field_b(&vif_fields[VCONN_Swap_To_On_Supported], - vif_component_name[VCONN_Swap_To_On_Supported], - IS_ENABLED(CONFIG_USBC_VCONN_SWAP)); - - set_vif_field_b(&vif_fields[VCONN_Swap_To_Off_Supported], - vif_component_name[VCONN_Swap_To_Off_Supported], - IS_ENABLED(CONFIG_USBC_VCONN_SWAP)); - - set_vif_field_b(&vif_fields[Responds_To_Discov_SOP_UFP], - vif_component_name[Responds_To_Discov_SOP_UFP], - does_respond_to_discov_sop_ufp()); - - set_vif_field_b(&vif_fields[Responds_To_Discov_SOP_DFP], - vif_component_name[Responds_To_Discov_SOP_DFP], - does_respond_to_discov_sop_dfp()); - - set_vif_field_b(&vif_fields[Attempts_Discov_SOP], - vif_component_name[Attempts_Discov_SOP], - ((!IS_ENABLED(CONFIG_USB_PD_SIMPLE_DFP)) || - (type != SRC))); - - set_vif_field_b(&vif_fields[Chunking_Implemented_SOP], - vif_component_name[Chunking_Implemented_SOP], - (IS_ENABLED(CONFIG_USB_PD_REV30) && - IS_ENABLED(CONFIG_USB_PRL_SM))); - - set_vif_field_b(&vif_fields[Unchunked_Extended_Messages_Supported], - vif_component_name[Unchunked_Extended_Messages_Supported], - false); - - if (IS_ENABLED(CONFIG_USB_PD_MANUFACTURER_INFO)) { - char hex_str[10]; - - set_vif_field_b(&vif_fields[Manufacturer_Info_Supported_Port], - vif_component_name[Manufacturer_Info_Supported_Port], - true); - - sprintf(hex_str, "%04X", USB_VID_GOOGLE); - set_vif_field_itss(&vif_fields[Manufacturer_Info_VID_Port], - vif_component_name[Manufacturer_Info_VID_Port], - USB_VID_GOOGLE, hex_str); - - #if defined(CONFIG_USB_PID) - sprintf(hex_str, "%04X", CONFIG_USB_PID); - set_vif_field_itss(&vif_fields[ - Manufacturer_Info_PID_Port], - vif_component_name[Manufacturer_Info_PID_Port], - CONFIG_USB_PID, hex_str); - #else - sprintf(hex_str, "%04X", DEFAULT_MISSING_PID); - set_vif_field_itss(&vif_fields[ - Manufacturer_Info_PID_Port], - vif_component_name[Manufacturer_Info_PID_Port], - DEFAULT_MISSING_PID, hex_str); - #endif - } else { - set_vif_field_b(&vif_fields[Manufacturer_Info_Supported_Port], - vif_component_name[Manufacturer_Info_Supported_Port], - false); - } - - set_vif_field_b(&vif_fields[Security_Msgs_Supported_SOP], - vif_component_name[Security_Msgs_Supported_SOP], - IS_ENABLED(CONFIG_USB_PD_SECURITY_MSGS)); - - #if defined(CONFIG_NUM_FIXED_BATTERIES) - set_vif_field_itss(&vif_fields[Num_Fixed_Batteries], - vif_component_name[Num_Fixed_Batteries], - CONFIG_NUM_FIXED_BATTERIES, NULL); - #elif defined(CONFIG_USB_CTVPD) || defined(CONFIG_USB_VPD) - set_vif_field(&vif_fields[Num_Fixed_Batteries], - vif_component_name[Num_Fixed_Batteries], - "0", NULL); - #else - set_vif_field(&vif_fields[Num_Fixed_Batteries], - vif_component_name[Num_Fixed_Batteries], - "1", NULL); - #endif - - set_vif_field(&vif_fields[Num_Swappable_Battery_Slots], - vif_component_name[Num_Swappable_Battery_Slots], - "0", NULL); - - set_vif_field(&vif_fields[ID_Header_Connector_Type_SOP], - vif_component_name[ID_Header_Connector_Type_SOP], - "2", "USB Type-C® Receptacle"); -} - -/********************************************************************* - * Init VIF/Component[] SOP* Capabilities Fields - */ -static void init_vif_component_sop_capabilities_fields( - struct vif_field_t *vif_fields) -{ - set_vif_field_b(&vif_fields[SOP_Capable], - vif_component_name[SOP_Capable], - can_act_as_host()); - - set_vif_field_b(&vif_fields[SOP_P_Capable], - vif_component_name[SOP_P_Capable], - IS_ENABLED(CONFIG_USB_PD_DECODE_SOP)); - - set_vif_field_b(&vif_fields[SOP_PP_Capable], - vif_component_name[SOP_PP_Capable], - IS_ENABLED(CONFIG_USB_PD_DECODE_SOP)); - - set_vif_field_b(&vif_fields[SOP_P_Debug_Capable], - vif_component_name[SOP_P_Debug_Capable], - false); - - set_vif_field_b(&vif_fields[SOP_PP_Debug_Capable], - vif_component_name[SOP_PP_Debug_Capable], - false); -} - -/********************************************************************* - * Init VIF/Component[] USB Type-C Fields - */ -static void init_vif_component_usb_type_c_fields( - struct vif_field_t *vif_fields, - enum dtype type) -{ - set_vif_field_b(&vif_fields[Type_C_Implements_Try_SRC], - vif_component_name[Type_C_Implements_Try_SRC], - IS_ENABLED(CONFIG_USB_PD_TRY_SRC)); - - set_vif_field_b(&vif_fields[Type_C_Implements_Try_SNK], - vif_component_name[Type_C_Implements_Try_SNK], - false); - - { - int rp = CONFIG_USB_PD_PULLUP; - - #if defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT) - rp = CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT; - #endif - - switch (rp) { - case 0: - set_vif_field(&vif_fields[RP_Value], - vif_component_name[RP_Value], - "0", "Default"); - break; - case 1: - set_vif_field(&vif_fields[RP_Value], - vif_component_name[RP_Value], - "1", "1.5A"); - break; - case 2: - set_vif_field(&vif_fields[RP_Value], - vif_component_name[RP_Value], - "2", "3A"); - break; - default: - set_vif_field_itss(&vif_fields[RP_Value], - vif_component_name[RP_Value], - rp, NULL); - } - } - - if (type == SNK) - set_vif_field_b( - &vif_fields[Type_C_Supports_VCONN_Powered_Accessory], - vif_component_name - [Type_C_Supports_VCONN_Powered_Accessory], - false); - - set_vif_field_b(&vif_fields[Type_C_Is_VCONN_Powered_Accessory], - vif_component_name[Type_C_Is_VCONN_Powered_Accessory], - false); - - set_vif_field_b(&vif_fields[Type_C_Is_Debug_Target_SRC], - vif_component_name[Type_C_Is_Debug_Target_SRC], - true); - - set_vif_field_b(&vif_fields[Type_C_Is_Debug_Target_SNK], - vif_component_name[Type_C_Is_Debug_Target_SNK], - true); - - set_vif_field_b(&vif_fields[Type_C_Can_Act_As_Host], - vif_component_name[Type_C_Can_Act_As_Host], - can_act_as_host()); - - set_vif_field_b(&vif_fields[Type_C_Is_Alt_Mode_Controller], - vif_component_name[Type_C_Is_Alt_Mode_Controller], - is_alt_mode_controller()); - - if (can_act_as_device()) { - set_vif_field_b(&vif_fields[Type_C_Can_Act_As_Device], - vif_component_name[Type_C_Can_Act_As_Device], - true); - - if (is_usb_pd_supported() && - does_respond_to_discov_sop_ufp()) - set_vif_field_b(&vif_fields[Type_C_Is_Alt_Mode_Adapter], - vif_component_name[Type_C_Is_Alt_Mode_Adapter], - IS_ENABLED(CONFIG_USB_ALT_MODE_ADAPTER)); - } else { - set_vif_field_b(&vif_fields[Type_C_Can_Act_As_Device], - vif_component_name[Type_C_Can_Act_As_Device], - false); - } - - { - int ps = POWER_UFP; - - if (IS_ENABLED(CONFIG_BATTERY)) - ps = POWER_BOTH; -#if defined(CONFIG_DEDICATED_CHARGE_PORT_COUNT) - else if (CONFIG_DEDICATED_CHARGE_PORT_COUNT == 1) - ps = POWER_EXTERNAL; - else if (CONFIG_DEDICATED_CHARGE_PORT_COUNT > 1) - ps = POWER_BOTH; -#endif - - switch (ps) { - case POWER_EXTERNAL: - set_vif_field(&vif_fields[Type_C_Power_Source], - vif_component_name[Type_C_Power_Source], - "0", "Externally Powered"); - break; - case POWER_UFP: - set_vif_field(&vif_fields[Type_C_Power_Source], - vif_component_name[Type_C_Power_Source], - "1", "UFP-powered"); - break; - case POWER_BOTH: - set_vif_field(&vif_fields[Type_C_Power_Source], - vif_component_name[Type_C_Power_Source], - "2", "Both"); - break; - default: - set_vif_field_itss(&vif_fields[Type_C_Power_Source], - vif_component_name[Type_C_Power_Source], - ps, NULL); - } - } - - set_vif_field_b(&vif_fields[Type_C_Port_On_Hub], - vif_component_name[Type_C_Port_On_Hub], - false); - - set_vif_field_b(&vif_fields[Type_C_Supports_Audio_Accessory], - vif_component_name[Type_C_Supports_Audio_Accessory], - false); - - set_vif_field_b(&vif_fields[Type_C_Sources_VCONN], - vif_component_name[Type_C_Sources_VCONN], - IS_ENABLED(CONFIG_USBC_VCONN)); -} - -/********************************************************************* - * Init VIF/Component[] USB Data - Upstream Facing Port Fields - * - * TODO: Generic todo to fill in additional fields as the need presents - * itself - * - * Fields that are not currently being initialized - * - * vif_Component - * Device_Contains_Captive_Retimer booleanFieldType - * Device_Truncates_DP_For_tDHPResponse booleanFieldType - * Device_Gen1x1_tLinkTurnaround numericFieldType - * Device_Gen2x1_tLinkTurnaround numericFieldType - */ -static void init_vif_component_usb_data_ufp_fields( - struct vif_field_t *vif_fields) -{ - /* - * TOTO(b:172441959) Adjust the speed based on CONFIG_ - */ - enum usb_speed ds = USB_GEN11; - bool supports_usb_data; - - /* - * The fields in this section shall be ignored by Testers unless - * Connector_Type is set to 1 (Type-B) or 3 (Micro A/B), or - * Connector_Type is set to 2 (Type-C) and Type_C_Can_Act_As_Device - * is set to YES. - * - * NOTE: We currently are always a Connector_Type of 2 (Type-C) - */ - if (!can_act_as_device()) - return; - - supports_usb_data = does_support_device_usb_data(); - set_vif_field_b( - &vif_fields[Device_Supports_USB_Data], - vif_component_name[Device_Supports_USB_Data], - supports_usb_data); - - if (supports_usb_data) { - switch (ds) { - case USB_2: - set_vif_field_itss(&vif_fields[Device_Speed], - vif_component_name[Device_Speed], - USB_2, "USB 2"); - break; - case USB_GEN11: - set_vif_field_itss(&vif_fields[Device_Speed], - vif_component_name[Device_Speed], - USB_GEN11, "USB 3.2 GEN 1x1"); - break; - case USB_GEN21: - set_vif_field_itss(&vif_fields[Device_Speed], - vif_component_name[Device_Speed], - USB_GEN21, "USB 3.2 GEN 2x1"); - break; - case USB_GEN12: - set_vif_field_itss(&vif_fields[Device_Speed], - vif_component_name[Device_Speed], - USB_GEN12, "USB 3.2 GEN 1x2"); - break; - case USB_GEN22: - set_vif_field_itss(&vif_fields[Device_Speed], - vif_component_name[Device_Speed], - USB_GEN22, "USB 3.2 GEN 2x2"); - break; - } - } -} - -/********************************************************************* - * Init VIF/Component[] USB Data - Downstream Facing Port Fields - * - * TODO: Generic todo to fill in additional fields as the need presents - * itself - * - * Fields that are not currently being initialized - * - * vif_Component - * Hub_Port_Number numericFieldType - * Host_Truncates_DP_For_tDHPResponse booleanFieldType - * Host_Gen1x1_tLinkTurnaround numericFieldType - * Host_Gen2x1_tLinkTurnaround numericFieldType - * Host_Suspend_Supported booleanFieldType - */ -static void init_vif_component_usb_data_dfp_fields( - struct vif_field_t *vif_fields) -{ - /* - * TOTO(b:172438944) Adjust the speed based on CONFIG_ - */ - enum usb_speed ds = USB_GEN11; - bool supports_usb_data; - bool is_dfp_on_hub; - - /* - * The fields in this section shall be ignored by Testers unless - * Connector_Type is set to 0 (Type-A), or - * COnnector Type is set to 3 (Micro A/B); or - * Connector_Type is set to 2 (Type-C) and Type_C_Can_Act_As_Host - * is set to YES - * - * NOTE: We currently are always a Connector_Type of 2 (Type-C) - */ - if (!can_act_as_host()) - return; - - supports_usb_data = does_support_host_usb_data(); - set_vif_field_b(&vif_fields[Host_Supports_USB_Data], - vif_component_name[Host_Supports_USB_Data], - supports_usb_data); - - if (supports_usb_data) { - switch (ds) { - case USB_2: - set_vif_field_itss(&vif_fields[Host_Speed], - vif_component_name[Host_Speed], - USB_2, "USB 2"); - break; - case USB_GEN11: - set_vif_field_itss(&vif_fields[Host_Speed], - vif_component_name[Host_Speed], - USB_GEN11, "USB 3.2 GEN 1x1"); - break; - case USB_GEN21: - set_vif_field_itss(&vif_fields[Host_Speed], - vif_component_name[Host_Speed], - USB_GEN21, "USB 3.2 GEN 2x1"); - break; - case USB_GEN12: - set_vif_field_itss(&vif_fields[Host_Speed], - vif_component_name[Host_Speed], - USB_GEN12, "USB 3.2 GEN 1x2"); - break; - case USB_GEN22: - set_vif_field_itss(&vif_fields[Host_Speed], - vif_component_name[Host_Speed], - USB_GEN22, "USB 3.2 GEN 2x2"); - break; - } - - if (!get_vif_field_tag_bool( - &vif_fields[Type_C_Port_On_Hub], - &is_dfp_on_hub)) - is_dfp_on_hub = false; - - set_vif_field_b(&vif_fields[Is_DFP_On_Hub], - vif_component_name[Is_DFP_On_Hub], - is_dfp_on_hub); - - set_vif_field_b(&vif_fields[Host_Contains_Captive_Retimer], - vif_component_name[Host_Contains_Captive_Retimer], - false); - - set_vif_field_b(&vif_fields[Host_Is_Embedded], - vif_component_name[Host_Is_Embedded], - false); - } -} - -/********************************************************************* - * Init VIF/Component[] PD Source Fields - */ -static int init_vif_component_pd_source_fields( - struct vif_field_t *vif_fields, - struct vif_srcPdoList_t *comp_src_pdo_list, - int32_t *src_max_power, - enum dtype type) -{ - if (type == DRP || type == SRC) { - int i; - char str[40]; - - /* Source PDOs */ - for (i = 0; i < src_pdo_cnt; i++) { - int32_t pwr; - - pwr = init_vif_src_pdo(&comp_src_pdo_list[i], - src_pdo[i]); - if (pwr < 0) { - fprintf(stderr, "ERROR: Setting SRC PDO.\n"); - return 1; - } - - if (pwr > *src_max_power) - *src_max_power = pwr; - } - - sprintf(str, "%d mW", *src_max_power); - set_vif_field_itss(&vif_fields[PD_Power_As_Source], - vif_component_name[PD_Power_As_Source], - *src_max_power, str); - } - - if (type == DRP || type == SRC) - set_vif_field_b(&vif_fields[USB_Suspend_May_Be_Cleared], - vif_component_name[USB_Suspend_May_Be_Cleared], - false); - - if (type == DRP || type == SRC) - set_vif_field_b(&vif_fields[Sends_Pings], - vif_component_name[Sends_Pings], - false); - - if (IS_ENABLED(CONFIG_USB_PD_DUAL_ROLE) && - type == DRP && - IS_ENABLED(CONFIG_USB_PD_FRS)) - set_vif_field(&vif_fields[ - FR_Swap_Type_C_Current_Capability_As_Initial_Sink], - vif_component_name - [FR_Swap_Type_C_Current_Capability_As_Initial_Sink], - "3", "3A @ 5V"); - else - set_vif_field(&vif_fields[ - FR_Swap_Type_C_Current_Capability_As_Initial_Sink], - vif_component_name - [FR_Swap_Type_C_Current_Capability_As_Initial_Sink], - "0", "FR_Swap not supported"); - - if (IS_ENABLED(CONFIG_USB_PD_REV30) || IS_ENABLED(CONFIG_USB_PRL_SM)) - set_vif_field_b(&vif_fields[Master_Port], - vif_component_name[Master_Port], - false); - - if (type == DRP || type == SRC) - set_vif_field_itss(&vif_fields[Num_Src_PDOs], - vif_component_name[Num_Src_PDOs], - src_pdo_cnt, NULL); - - if (type == DRP || type == SRC) { - if (IS_ENABLED(CONFIG_USBC_OCP)) { - int resp = 0; - - set_vif_field_b(&vif_fields[PD_OC_Protection], - vif_component_name[PD_OC_Protection], - true); - - switch (resp) { - case 0: - set_vif_field(&vif_fields[PD_OCP_Method], - vif_component_name[PD_OCP_Method], - "0", "Over-Current Response"); - break; - case 1: - set_vif_field(&vif_fields[PD_OCP_Method], - vif_component_name[PD_OCP_Method], - "1", "Under-Voltage Response"); - break; - case 2: - set_vif_field(&vif_fields[PD_OCP_Method], - vif_component_name[PD_OCP_Method], - "2", "Both"); - break; - default: - set_vif_field_itss(&vif_fields[PD_OCP_Method], - vif_component_name[PD_OCP_Method], - resp, NULL); - } - } else { - set_vif_field_b(&vif_fields[PD_OC_Protection], - vif_component_name[PD_OC_Protection], - false); - } - } - - return 0; -} - -/********************************************************************* - * Init VIF/Component[] PD Sink Fields - */ -static int init_vif_component_pd_sink_fields( - struct vif_field_t *vif_fields, - struct vif_snkPdoList_t *comp_snk_pdo_list, - enum dtype type) -{ - int i; - int32_t snk_max_power = 0; - char str[40]; - - if (!IS_ENABLED(CONFIG_USB_PD_DUAL_ROLE) || type == SRC) - return 0; - - /* Sink PDOs */ - for (i = 0; i < pd_snk_pdo_cnt; i++) { - int32_t pwr; - - pwr = init_vif_snk_pdo(&comp_snk_pdo_list[i], - pd_snk_pdo[i]); - if (pwr < 0) { - fprintf(stderr, "ERROR: Setting SNK PDO.\n"); - return 1; - } - - if (pwr > snk_max_power) - snk_max_power = pwr; - } - - sprintf(str, "%d mW", snk_max_power); - set_vif_field_itss(&vif_fields[PD_Power_As_Sink], - vif_component_name[PD_Power_As_Sink], - snk_max_power, str); - - set_vif_field_b(&vif_fields[No_USB_Suspend_May_Be_Set], - vif_component_name[No_USB_Suspend_May_Be_Set], - true); - - set_vif_field_b(&vif_fields[GiveBack_May_Be_Set], - vif_component_name[GiveBack_May_Be_Set], - IS_ENABLED(CONFIG_USB_PD_GIVE_BACK)); - - set_vif_field_b(&vif_fields[Higher_Capability_Set], - vif_component_name[Higher_Capability_Set], - false); - - set_vif_field(&vif_fields[ - FR_Swap_Reqd_Type_C_Current_As_Initial_Source], - vif_component_name - [FR_Swap_Reqd_Type_C_Current_As_Initial_Source], - "0", "FR_Swap not supported"); - - set_vif_field_itss(&vif_fields[Num_Snk_PDOs], - vif_component_name[Num_Snk_PDOs], - pd_snk_pdo_cnt, NULL); - - return 0; -} - -/********************************************************************* - * Init VIF/Component[] PD Dual Role Fields - */ -static void init_vif_component_pd_dual_role_fields( - struct vif_field_t *vif_fields, - enum dtype type) -{ - if (!IS_ENABLED(CONFIG_USB_PD_DUAL_ROLE) || type != DRP) - return; - - set_vif_field_b(&vif_fields[Accepts_PR_Swap_As_Src], - vif_component_name[Accepts_PR_Swap_As_Src], - true); - - set_vif_field_b(&vif_fields[Accepts_PR_Swap_As_Snk], - vif_component_name[Accepts_PR_Swap_As_Snk], - true); - - set_vif_field_b(&vif_fields[Requests_PR_Swap_As_Src], - vif_component_name[Requests_PR_Swap_As_Src], - true); - - set_vif_field_b(&vif_fields[Requests_PR_Swap_As_Snk], - vif_component_name[Requests_PR_Swap_As_Snk], - true); - - set_vif_field_b(&vif_fields[FR_Swap_Supported_As_Initial_Sink], - vif_component_name[FR_Swap_Supported_As_Initial_Sink], - IS_ENABLED(CONFIG_USB_PD_FRS)); -} - -/********************************************************************* - * Init VIF/Component[] SOP Discovery Fields - * - * TODO: Generic todo to fill in additional fields as the need presents - * itself - * - * Fields that are not currently being initialized - * - * vif_Component - * Product_Type_UFP_SOP numericFieldType - * Product_Type_DFP_SOP numericFieldType - * Modal_Operation_Supported_SOP booleanFieldType - * Num_SVIDs_Min_SOP numericFieldType - * Num_SVIDs_Max_SOP numericFieldType - * SVID_Fixed_SOP booleanFieldType - */ -static void init_vif_component_sop_discovery_fields( - struct vif_field_t *vif_fields) -{ - char hex_str[10]; - - /* - * The fields in this section shall be ignored by Testers unless at - * least one of Responds_To_Discov_SOP_UFP and - * Responds_To_Discov_SOP_DFP is set to YES. - */ - if (!does_respond_to_discov_sop_ufp() && - !does_respond_to_discov_sop_dfp()) - return; - - set_vif_field(&vif_fields[XID_SOP], - vif_component_name[XID_SOP], - "0", - NULL); - - set_vif_field_b(&vif_fields[Data_Capable_As_USB_Host_SOP], - vif_component_name[Data_Capable_As_USB_Host_SOP], - can_act_as_host()); - - set_vif_field_b(&vif_fields[Data_Capable_As_USB_Device_SOP], - vif_component_name[Data_Capable_As_USB_Device_SOP], - can_act_as_device()); - - if (does_respond_to_discov_sop_dfp() && - is_usb4_supported()) { -#if defined(CONFIG_USB_PD_PORT_LABEL) - set_vif_field_stis(&vif_fields[DFP_VDO_Port_Number], - vif_component_name[DFP_VDO_Port_Number], - NULL, - CONFIG_USB_PD_PORT_LABEL); -#else - set_vif_field_stis(&vif_fields[DFP_VDO_Port_Number], - vif_component_name[DFP_VDO_Port_Number], - NULL, - component_index); -#endif - } - - sprintf(hex_str, "%04X", USB_VID_GOOGLE); - set_vif_field_itss(&vif_fields[USB_VID_SOP], - vif_component_name[USB_VID_SOP], - USB_VID_GOOGLE, hex_str); - - #if defined(CONFIG_USB_PID) - sprintf(hex_str, "%04X", CONFIG_USB_PID); - set_vif_field_itss(&vif_fields[PID_SOP], - vif_component_name[PID_SOP], - CONFIG_USB_PID, hex_str); - #else - sprintf(hex_str, "%04X", DEFAULT_MISSING_PID); - set_vif_field_itss(&vif_fields[PID_SOP], - vif_component_name[PID_SOP], - DEFAULT_MISSING_PID, hex_str); - #endif - - #if defined(CONFIG_USB_BCD_DEV) - sprintf(hex_str, "%04X", CONFIG_USB_BCD_DEV); - set_vif_field_itss(&vif_fields[bcdDevice_SOP], - vif_component_name[bcdDevice_SOP], - CONFIG_USB_BCD_DEV, hex_str); - #else - sprintf(hex_str, "%04X", DEFAULT_MISSING_BCD_DEV); - set_vif_field_itss(&vif_fields[bcdDevice_SOP], - vif_component_name[bcdDevice_SOP], - DEFAULT_MISSING_BCD_DEV, hex_str); - #endif -} - -/********************************************************************* - * Init VIF/Component[] Battery Charging 1.2 Fields - */ -static void init_vif_component_bc_1_2_fields( - struct vif_field_t *vif_fields, - enum bc_1_2_support bc_support) -{ - if (bc_support == BC_1_2_SUPPORT_CHARGING_PORT || - bc_support == BC_1_2_SUPPORT_BOTH) - set_vif_field(&vif_fields[BC_1_2_Charging_Port_Type], - vif_component_name[BC_1_2_Charging_Port_Type], - "1", - "CDP"); -} - -/********************************************************************* - * Init VIF/Component[] Product Power Fields - * - * TODO: Generic todo to fill in additional fields as the need presents - * itself - * - * Fields that are not currently being initialized - * - * vif_Component - * Port_Source_Power_Gang nonEmptyString - * Port_Source_Power_Gang_Max_Power numericFieldType - */ -static void init_vif_component_product_power_fields( - struct vif_field_t *vif_fields, - int32_t src_max_power, - enum dtype type) -{ - if (type == DRP || type == SRC) { - char str[10]; - - sprintf(str, "%d mW", src_max_power); - set_vif_field_itss(&vif_fields[Product_Total_Source_Power_mW], - vif_component_name[Product_Total_Source_Power_mW], - src_max_power, str); - } - - if (type == DRP || type == SRC) - set_vif_field(&vif_fields[Port_Source_Power_Type], - vif_component_name[Port_Source_Power_Type], - "0", "Assured"); -} - -static int gen_vif(const char *board, - struct vif_t *vif) -{ - int max_component_index = board_get_usb_pd_port_count(); - - /********************************************************************* - * Initialize the vif structure - */ - init_vif_fields( - vif->vif_field, - vif->vif_app_field, - board); - - init_vif_product_fields( - vif->Product.vif_field); - - for (component_index = 0; - component_index < max_component_index; - component_index++) { - int override_value; - bool was_overridden; - enum dtype type; - int32_t src_max_power = 0; - enum bc_1_2_support bc_support = BC_1_2_SUPPORT_NONE; - - /* Determine if we are DRP, SRC or SNK */ - was_overridden = - get_vif_field_tag_number( - &vif->Component[component_index] - .vif_field[Type_C_State_Machine], - &override_value); - if (was_overridden) { - switch (override_value) { - case SRC: - case SNK: - case DRP: - type = (enum dtype)override_value; - break; - default: - was_overridden = false; - } - } - if (!was_overridden) { - was_overridden = - get_vif_field_tag_number( - &vif->Component[component_index] - .vif_field[PD_Port_Type], - &override_value); - if (was_overridden) { - switch (override_value) { - case PORT_CONSUMER_ONLY: /* SNK */ - type = SNK; - break; - case PORT_PROVIDER_ONLY: /* SRC */ - type = SRC; - break; - case PORT_DRP: /* DRP */ - type = DRP; - break; - default: - was_overridden = false; - } - } - } - if (!was_overridden) { - if (is_drp()) - type = DRP; - else if (is_src() && is_snk()) - /* - * No DRP with SRC and SNK PDOs detected. So - * ignore. ie. Twinkie or Plankton - */ - return 0; - else if (is_src()) - type = SRC; - else if (is_snk()) - type = SNK; - else - return 1; - } - - - init_vif_component_fields( - vif->Component[component_index].vif_field, - &bc_support, - type); - - init_vif_component_general_pd_fields( - vif->Component[component_index].vif_field, - type); - - init_vif_component_sop_capabilities_fields( - vif->Component[component_index].vif_field); - - init_vif_component_usb_type_c_fields( - vif->Component[component_index].vif_field, - type); - - init_vif_component_usb_data_ufp_fields( - vif->Component[component_index].vif_field); - - init_vif_component_usb_data_dfp_fields( - vif->Component[component_index].vif_field); - - if (init_vif_component_pd_source_fields( - vif->Component[component_index].vif_field, - vif->Component[component_index].SrcPdoList, - &src_max_power, - type)) - return 1; - - if (init_vif_component_pd_sink_fields( - vif->Component[component_index].vif_field, - vif->Component[component_index].SnkPdoList, - type)) - return 1; - - init_vif_component_pd_dual_role_fields( - vif->Component[component_index].vif_field, - type); - - init_vif_component_sop_discovery_fields( - vif->Component[component_index].vif_field); - - init_vif_component_bc_1_2_fields( - vif->Component[component_index].vif_field, - bc_support); - - init_vif_component_product_power_fields( - vif->Component[component_index].vif_field, - src_max_power, - type); - } - - return 0; -} -/* - * VIF Structure Initialization from Config Functions - *****************************************************************************/ - -int main(int argc, char **argv) -{ - int nopt; - int ret; - const char *out = NULL; - const char *board = NULL; - bool do_config_init = true; - DIR *vifdir; - char *name; - int name_size; - const char * const short_opt = "hb:o:nv:"; - const struct option long_opts[] = { - { "help", 0, NULL, 'h' }, - { "board", 1, NULL, 'b' }, - { "out", 1, NULL, 'o' }, - { "no-config", 0, NULL, 'n' }, - { "over", 1, NULL, 'v' }, - { NULL } - }; - - /* Clear the VIF structure */ - memset(&vif, 0, sizeof(struct vif_t)); - - do { - nopt = getopt_long(argc, argv, short_opt, long_opts, NULL); - switch (nopt) { - case 'h': /* -h or --help */ - printf("USAGE: genvif -b|--board <board name>\n" - " -o|--out <out directory>\n" - " [-n|--no-config]\n" - " [-v|--over <override XML file>]\n"); - return 1; - - case 'b': /* -b or --board */ - board = optarg; - break; - - case 'o': /* -o or --out */ - out = optarg; - break; - - case 'n': /* -n or --no-config */ - do_config_init = false; - break; - - case 'v': /* -v or --over */ - /* Handle overrides */ - if (override_gen_vif(optarg, &vif)) - return 1; - break; - - case -1: - break; - - default: - abort(); - } - } while (nopt != -1); - - if (out == NULL || board == NULL) - return 1; - - /* Make sure VIF directory exists */ - vifdir = opendir(out); - if (vifdir == NULL) { - fprintf(stderr, "ERROR: %s directory does not exist.\n", out); - return 1; - } - closedir(vifdir); - - init_src_pdos(); - - /* Finish CONFIG initialization file */ - if (do_config_init) { - ret = gen_vif(board, &vif); - if (ret) - return 1; - } - - name_size = asprintf(&name, "%s/%s_vif.xml", out, board); - if (name_size < 0) { - fprintf(stderr, "ERROR: Out of memory.\n"); - return 1; - } - - /* Format the structure in XML and output it to file */ - ret = vif_output_xml(name, &vif); - - free(name); - return ret; -} diff --git a/util/genvif.h b/util/genvif.h deleted file mode 100644 index 634dbfc861..0000000000 --- a/util/genvif.h +++ /dev/null @@ -1,403 +0,0 @@ -/* Copyright 2020 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 __GENVIF_H__ -#define __GENVIF_H__ - -#define MAX_NUM_CABLE_SVIDS 10 -#define MAX_NUM_CABLE_SVID_MODES 10 -#define MAX_NUM_COMPONENTS 10 -#define MAX_NUM_PCIE_ENDPOINTS 10 -#define MAX_NUM_SNK_PDOS 10 -#define MAX_NUM_SRC_PDOS 10 -#define MAX_NUM_SOP_SVIDS 10 -#define MAX_NUM_SOP_SVID_MODES 10 -#define MAX_NUM_USB4_ROUTERS 16 - - -struct vif_field_t { - const char *name; - char *tag_value; - char *str_value; -}; - - -enum vif_cableSVIDModeList_indexes { - SVID_Mode_Enter, /* booleanFieldType */ - SVID_Mode_Recog_Mask, /* numericFieldType */ - SVID_Mode_Recog_Value, /* numericFieldType */ - CableSVID_Mode_Indexes -}; -struct vif_cableSVIDModeList_t { - struct vif_field_t vif_field[CableSVID_Mode_Indexes]; -}; - - -enum vif_cableSVIDList_indexes { - SVID, /* numericFieldType */ - SVID_Modes_Fixed, /* booleanFieldType */ - SVID_Num_Modes_Min, /* numericFieldType */ - SVID_Num_Modes_Max, /* numericFieldType */ - CableSVID_Indexes -}; -struct vif_cableSVIDList_t { - struct vif_field_t vif_field[CableSVID_Indexes]; - - struct vif_cableSVIDModeList_t - CableSVIDModeList[MAX_NUM_CABLE_SVID_MODES]; -}; - - -enum vif_sopSVIDModeList_indexes { - SVID_Mode_Enter_SOP, /* booleanFieldType */ - SVID_Mode_Recog_Mask_SOP, /* numericFieldType */ - SVID_Mode_Recog_Value_SOP, /* numericFieldType */ - SopSVID_Mode_Indexes -}; -struct vif_sopSVIDModeList_t { - struct vif_field_t vif_field[SopSVID_Mode_Indexes]; -}; - - -enum vif_sopSVIDList_indexes { - SVID_SOP, /* numericFieldType */ - SVID_Modes_Fixed_SOP, /* booleanFieldType */ - SVID_Num_Modes_Min_SOP, /* numericFieldType */ - SVID_Num_Modes_Max_SOP, /* numericFieldType */ - SopSVID_Indexes -}; -struct vif_sopSVIDList_t { - struct vif_field_t vif_field[SopSVID_Indexes]; - - struct vif_sopSVIDModeList_t - SOPSVIDModeList[MAX_NUM_SOP_SVID_MODES]; -}; - - -enum vif_snkPdoList_indexes { - Snk_PDO_Supply_Type, /* numericFieldType */ - Snk_PDO_Voltage, /* numericFieldType */ - Snk_PDO_Op_Power, /* numericFieldType */ - Snk_PDO_Min_Voltage, /* numericFieldType */ - Snk_PDO_Max_Voltage, /* numericFieldType */ - Snk_PDO_Op_Current, /* numericFieldType */ - Snk_PDO_Indexes -}; -struct vif_snkPdoList_t { - struct vif_field_t vif_field[Snk_PDO_Indexes]; -}; - - -enum vif_srcPdoList_indexes { - Src_PDO_Supply_Type, /* numericFieldType */ - Src_PDO_Peak_Current, /* numericFieldType */ - Src_PDO_Voltage, /* numericFieldType */ - Src_PDO_Max_Current, /* numericFieldType */ - Src_PDO_Min_Voltage, /* numericFieldType */ - Src_PDO_Max_Voltage, /* numericFieldType */ - Src_PDO_Max_Power, /* numericFieldType */ - Src_PD_OCP_OC_Debounce, /* numericFieldType */ - Src_PD_OCP_OC_Threshold, /* numericFieldType */ - Src_PD_OCP_UV_Debounce, /* numericFieldType */ - Src_PD_OCP_UV_Threshold_Type, /* numericFieldType */ - Src_PD_OCP_UV_Threshold, /* numericFieldType */ - Src_PDO_Indexes -}; -struct vif_srcPdoList_t { - struct vif_field_t vif_field[Src_PDO_Indexes]; -}; - - -enum vif_PCIeEndpointListType_indexes { - USB4_PCIe_Endpoint_Vendor_ID, /* numericFieldType */ - USB4_PCIe_Endpoint_Device_ID, /* numericFieldType */ - USB4_PCIe_Endpoint_Class_Code, /* numericFieldType */ - PCIe_Endpoint_Indexes -}; -struct vif_PCIeEndpointListType_t { - struct vif_field_t vif_field[PCIe_Endpoint_Indexes]; -}; - - -enum vif_Usb4RouterListType_indexes { - USB4_Router_ID, /* numericFieldType */ - USB4_Silicon_VID, /* numericFieldType */ - USB4_Num_Lane_Adapters, /* numericFieldType */ - USB4_Num_USB3_DN_Adapters, /* numericFieldType */ - USB4_Num_DP_IN_Adapters, /* numericFieldType */ - USB4_Num_DP_OUT_Adapters, /* numericFieldType */ - USB4_Num_PCIe_DN_Adapters, /* numericFieldType */ - USB4_TBT3_Not_Supported, /* numericFieldType */ - USB4_PCIe_Wake_Supported, /* booleanFieldType */ - USB4_USB3_Wake_Supported, /* booleanFieldType */ - USB4_Num_Unused_Adapters, /* numericFieldType */ - USB4_TBT3_VID, /* numericFieldType */ - USB4_PCIe_Switch_Vendor_ID, /* numericFieldType */ - USB4_PCIe_Switch_Device_ID, /* numericFieldType */ - USB4_Num_PCIe_Endpoints, /* numericFieldType */ - USB4_Router_Indexes -}; -struct vif_Usb4RouterListType_t { - struct vif_field_t vif_field[USB4_Router_Indexes]; - - struct vif_PCIeEndpointListType_t - PCIeEndpointList[MAX_NUM_PCIE_ENDPOINTS]; -}; - - -enum vif_Component_indexes { - Port_Label, /* nonEmptyString */ - Connector_Type, /* numericFieldType */ - USB4_Supported, /* booleanFieldType */ - USB4_Router_Index, /* numericFieldType */ - USB_PD_Support, /* booleanFieldType */ - PD_Port_Type, /* numericFieldType */ - Type_C_State_Machine, /* numericFieldType */ - Captive_Cable, /* booleanFieldType */ - Port_Battery_Powered, /* booleanFieldType */ - BC_1_2_Support, /* numericFieldType */ - PD_Spec_Revision_Major, /* numericFieldType */ - PD_Spec_Revision_Minor, /* numericFieldType */ - PD_Spec_Version_Major, /* numericFieldType */ - PD_Spec_Version_Minor, /* numericFieldType */ - PD_Specification_Revision, /* numericFieldType */ - USB_Comms_Capable, /* booleanFieldType */ - DR_Swap_To_DFP_Supported, /* booleanFieldType */ - DR_Swap_To_UFP_Supported, /* booleanFieldType */ - Unconstrained_Power, /* booleanFieldType */ - VCONN_Swap_To_On_Supported, /* booleanFieldType */ - VCONN_Swap_To_Off_Supported, /* booleanFieldType */ - Responds_To_Discov_SOP_UFP, /* booleanFieldType */ - Responds_To_Discov_SOP_DFP, /* booleanFieldType */ - Attempts_Discov_SOP, /* booleanFieldType */ - Chunking_Implemented_SOP, /* booleanFieldType */ - Unchunked_Extended_Messages_Supported, /* booleanFieldType */ - Manufacturer_Info_Supported_Port, /* booleanFieldType */ - Manufacturer_Info_VID_Port, /* numericFieldType */ - Manufacturer_Info_PID_Port, /* numericFieldType */ - Security_Msgs_Supported_SOP, /* booleanFieldType */ - Num_Fixed_Batteries, /* numericFieldType */ - Num_Swappable_Battery_Slots, /* numericFieldType */ - ID_Header_Connector_Type_SOP, /* numericFieldType */ - SOP_Capable, /* booleanFieldType */ - SOP_P_Capable, /* booleanFieldType */ - SOP_PP_Capable, /* booleanFieldType */ - SOP_P_Debug_Capable, /* booleanFieldType */ - SOP_PP_Debug_Capable, /* booleanFieldType */ - Type_C_Implements_Try_SRC, /* booleanFieldType */ - Type_C_Implements_Try_SNK, /* booleanFieldType */ - RP_Value, /* numericFieldType */ - Type_C_Supports_VCONN_Powered_Accessory,/* booleanFieldType */ - Type_C_Is_VCONN_Powered_Accessory, /* booleanFieldType */ - Type_C_Is_Debug_Target_SRC, /* booleanFieldType */ - Type_C_Is_Debug_Target_SNK, /* booleanFieldType */ - Type_C_Can_Act_As_Host, /* booleanFieldType */ - Type_C_Is_Alt_Mode_Controller, /* booleanFieldType */ - Type_C_Can_Act_As_Device, /* booleanFieldType */ - Type_C_Is_Alt_Mode_Adapter, /* booleanFieldType */ - Type_C_Power_Source, /* numericFieldType */ - Type_C_Port_On_Hub, /* booleanFieldType */ - Type_C_Supports_Audio_Accessory, /* booleanFieldType */ - Type_C_Sources_VCONN, /* booleanFieldType */ - USB4_Lane_0_Adapter, /* numericFieldType */ - USB4_Max_Speed, /* numericFieldType */ - USB4_DFP_Supported, /* booleanFieldType */ - USB4_UFP_Supported, /* booleanFieldType */ - USB4_USB3_Tunneling_Supported, /* booleanFieldType */ - USB4_DP_Tunneling_Supported, /* booleanFieldType */ - USB4_PCIe_Tunneling_Supported, /* booleanFieldType */ - USB4_TBT3_Compatibility_Supported, /* booleanFieldType */ - USB4_CL1_State_Supported, /* booleanFieldType */ - USB4_CL2_State_Supported, /* booleanFieldType */ - USB4_Num_Retimers, /* numericFieldType */ - USB4_DP_Bit_Rate, /* numericFieldType */ - USB4_Num_DP_Lanes, /* numericFieldType */ - Device_Supports_USB_Data, /* booleanFieldType */ - Device_Speed, /* numericFieldType */ - Device_Contains_Captive_Retimer, /* booleanFieldType */ - Device_Truncates_DP_For_tDHPResponse, /* booleanFieldType */ - Device_Gen1x1_tLinkTurnaround, /* numericFieldType */ - Device_Gen2x1_tLinkTurnaround, /* numericFieldType */ - Host_Supports_USB_Data, /* booleanFieldType */ - Host_Speed, /* numericFieldType */ - Is_DFP_On_Hub, /* booleanFieldType */ - Hub_Port_Number, /* numericFieldType */ - Host_Contains_Captive_Retimer, /* booleanFieldType */ - Host_Truncates_DP_For_tDHPResponse, /* booleanFieldType */ - Host_Gen1x1_tLinkTurnaround, /* numericFieldType */ - Host_Gen2x1_tLinkTurnaround, /* numericFieldType */ - Host_Is_Embedded, /* booleanFieldType */ - Host_Suspend_Supported, /* booleanFieldType */ - PD_Power_As_Source, /* numericFieldType */ - USB_Suspend_May_Be_Cleared, /* booleanFieldType */ - Sends_Pings, /* booleanFieldType */ - FR_Swap_Type_C_Current_Capability_As_Initial_Sink,/* numericFieldType */ - Master_Port, /* booleanFieldType */ - Num_Src_PDOs, /* numericFieldType */ - PD_OC_Protection, /* booleanFieldType */ - PD_OCP_Method, /* numericFieldType */ - PD_Power_As_Sink, /* numericFieldType */ - No_USB_Suspend_May_Be_Set, /* booleanFieldType */ - GiveBack_May_Be_Set, /* booleanFieldType */ - Higher_Capability_Set, /* booleanFieldType */ - FR_Swap_Reqd_Type_C_Current_As_Initial_Source,/* numericFieldType */ - Num_Snk_PDOs, /* numericFieldType */ - Accepts_PR_Swap_As_Src, /* booleanFieldType */ - Accepts_PR_Swap_As_Snk, /* booleanFieldType */ - Requests_PR_Swap_As_Src, /* booleanFieldType */ - Requests_PR_Swap_As_Snk, /* booleanFieldType */ - FR_Swap_Supported_As_Initial_Sink, /* booleanFieldType */ - XID_SOP, /* numericFieldType */ - Data_Capable_As_USB_Host_SOP, /* booleanFieldType */ - Data_Capable_As_USB_Device_SOP, /* booleanFieldType */ - Product_Type_UFP_SOP, /* numericFieldType */ - Product_Type_DFP_SOP, /* numericFieldType */ - DFP_VDO_Port_Number, /* numericFieldType */ - Modal_Operation_Supported_SOP, /* booleanFieldType */ - USB_VID_SOP, /* numericFieldType */ - PID_SOP, /* numericFieldType */ - bcdDevice_SOP, /* numericFieldType */ - Num_SVIDs_Min_SOP, /* numericFieldType */ - Num_SVIDs_Max_SOP, /* numericFieldType */ - SVID_Fixed_SOP, /* booleanFieldType */ - AMA_HW_Vers, /* numericFieldType */ - AMA_FW_Vers, /* numericFieldType */ - AMA_VCONN_Power, /* booleanFieldType */ - AMA_VCONN_Reqd, /* booleanFieldType */ - AMA_VBUS_Reqd, /* booleanFieldType */ - AMA_Superspeed_Support, /* numericFieldType */ - BC_1_2_Charging_Port_Type, /* numericFieldType */ - XID, /* numericFieldType */ - Data_Capable_As_USB_Host, /* booleanFieldType */ - Data_Capable_As_USB_Device, /* booleanFieldType */ - Product_Type, /* numericFieldType */ - Modal_Operation_Supported, /* booleanFieldType */ - USB_VID, /* numericFieldType */ - PID, /* numericFieldType */ - bcdDevice, /* numericFieldType */ - Cable_HW_Vers, /* numericFieldType */ - Cable_FW_Vers, /* numericFieldType */ - Type_C_To_Type_A_B_C, /* numericFieldType */ - Type_C_To_Type_C_Capt_Vdm_V2, /* numericFieldType */ - Cable_Latency, /* numericFieldType */ - Cable_Termination_Type, /* numericFieldType */ - Cable_VBUS_Current, /* numericFieldType */ - VBUS_Through_Cable, /* booleanFieldType */ - Cable_Superspeed_Support, /* numericFieldType */ - Cable_USB_Highest_Speed, /* numericFieldType */ - Max_VBUS_Voltage_Vdm_V2, /* numericFieldType */ - Manufacturer_Info_Supported, /* booleanFieldType */ - Manufacturer_Info_VID, /* numericFieldType */ - Manufacturer_Info_PID, /* numericFieldType */ - Chunking_Implemented, /* booleanFieldType */ - Security_Msgs_Supported, /* booleanFieldType */ - ID_Header_Connector_Type, /* numericFieldType */ - Cable_Num_SVIDs_Min, /* numericFieldType */ - Cable_Num_SVIDs_Max, /* numericFieldType */ - SVID_Fixed, /* booleanFieldType */ - Cable_SOP_PP_Controller, /* booleanFieldType */ - SBU_Supported, /* booleanFieldType */ - SBU_Type, /* numericFieldType */ - Active_Cable_Operating_Temp_Support, /* booleanFieldType */ - Active_Cable_Max_Operating_Temp, /* numericFieldType */ - Active_Cable_Shutdown_Temp_Support, /* booleanFieldType */ - Active_Cable_Shutdown_Temp, /* numericFieldType */ - Active_Cable_U3_CLd_Power, /* numericFieldType */ - Active_Cable_U3_U0_Trans_Mode, /* numericFieldType */ - Active_Cable_Physical_Connection, /* numericFieldType */ - Active_Cable_Active_Element, /* numericFieldType */ - Active_Cable_USB4_Support, /* booleanFieldType */ - Active_Cable_USB2_Supported, /* booleanFieldType */ - Active_Cable_USB2_Hub_Hops_Consumed, /* numericFieldType */ - Active_Cable_USB32_Supported, /* booleanFieldType */ - Active_Cable_USB_Lanes, /* numericFieldType */ - Active_Cable_Optically_Isolated, /* booleanFieldType */ - Active_Cable_USB_Gen, /* numericFieldType */ - VPD_HW_Vers, /* numericFieldType */ - VPD_FW_Vers, /* numericFieldType */ - VPD_Max_VBUS_Voltage, /* numericFieldType */ - VPD_Charge_Through_Support, /* booleanFieldType */ - VPD_Charge_Through_Current, /* numericFieldType */ - VPD_VBUS_Impedance, /* numericFieldType */ - VPD_Ground_Impedance, /* numericFieldType */ - Repeater_One_Type, /* numericFieldType */ - Repeater_Two_Type, /* numericFieldType */ - Product_Total_Source_Power_mW, /* numericFieldType */ - Port_Source_Power_Type, /* numericFieldType */ - Port_Source_Power_Gang, /* nonEmptyString */ - Port_Source_Power_Gang_Max_Power, /* numericFieldType */ - Component_Indexes -}; -struct vif_Component_t { - struct vif_field_t vif_field[Component_Indexes]; - - struct vif_srcPdoList_t SrcPdoList[MAX_NUM_SRC_PDOS]; - struct vif_snkPdoList_t SnkPdoList[MAX_NUM_SNK_PDOS]; - struct vif_sopSVIDList_t SOPSVIDList[MAX_NUM_SOP_SVIDS]; - struct vif_cableSVIDList_t CableSVIDList[MAX_NUM_CABLE_SVIDS]; - - - /* - * The following fields are deprecated. They should not be written - * to file in this version or any later version of the schema. - * - * Deprecated in VIF Version 3.10 - * vif_numericFieldType_t type_c_to_plug_receptacle; - * vif_numericFieldType_t retimer_type; - * Deprecated in VIF Version 3.12 - * vif_numericFieldType_t active_cable_usb2_hub_hops_supported; - * vif_booleanFieldType_t active_cable_optically_isololated; - */ -}; - - -enum vif_Product_indexes { - Product_VID, /* numericFieldType */ - USB4_Dock, /* booleanFieldType */ - USB4_Num_Internal_Host_Controllers, /* numericFieldType */ - USB4_Num_PCIe_DN_Bridges, /* numericFieldType */ - USB4_Audio_Supported, /* booleanFieldType */ - USB4_HID_Supported, /* booleanFieldType */ - USB4_Printer_Supported, /* booleanFieldType */ - USB4_Mass_Storage_Supported, /* booleanFieldType */ - USB4_Video_Supported, /* booleanFieldType */ - USB4_Comms_Networking_Supported, /* booleanFieldType */ - USB4_Media_Transfer_Protocol_Supported, /* booleanFieldType */ - USB4_Smart_Card_Supported, /* booleanFieldType */ - USB4_Still_Image_Capture_Supported, /* booleanFieldType */ - USB4_Monitor_Device_Supported, /* booleanFieldType */ - Product_Indexes -}; -struct vif_Product_t { - struct vif_field_t vif_field[Product_Indexes]; - - struct vif_Usb4RouterListType_t USB4RouterList[MAX_NUM_USB4_ROUTERS]; -}; - - -enum vif_indexes { - VIF_Specification, /* version */ - Vendor_Name, /* nonEmptyString */ - Model_Part_Number, /* nonEmptyString */ - Product_Revision, /* nonEmptyString */ - TID, /* nonEmptyString */ - VIF_Product_Type, /* numericFieldType */ - Certification_Type, /* numericFieldType */ - VIF_Indexes -}; -enum vif_app_indexes { - Vendor, /* nonEmptyString */ - Name, /* nonEmptyString */ - Version, /* version */ - VIF_App_Indexes -}; -struct vif_t { - struct vif_field_t vif_field[VIF_Indexes]; - struct vif_field_t vif_app_field[VIF_App_Indexes]; - - struct vif_Product_t Product; - struct vif_Component_t Component[MAX_NUM_COMPONENTS]; -}; - -#endif /* __GENVIF_H__ */ diff --git a/util/gpios_to_zephyr_dts.c b/util/gpios_to_zephyr_dts.c deleted file mode 100644 index 166c16dde7..0000000000 --- a/util/gpios_to_zephyr_dts.c +++ /dev/null @@ -1,117 +0,0 @@ -/* Copyright 2021 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 code is intended for developer use to convert a CrOS EC OS - * "gpio.inc" file into the expected device-tree format for Zephyr. - * The only use of it is to do a proof-of-concept build of a CrOS EC - * device using Zephyr OS, as Zephyr-only devices won't have a - * equivalent CrOS EC build. - * - * It does not handle all cases (i.e., low voltage selection), and - * some manual modifications to the output may be required. - * - ********************************************************************** - * DO NOT CREATE TESTS, SYSTEMS, OR INFRASTRUCTURE WHICH RELIES ON * - * THIS CODE. It's seriously ugly code that's probably prone to * - * breakage. It leaks memory. In other words, consider it * - * "contrib-quality" code that should be deleted one day (once we are * - * no longer doing proof-of-concept Zephyr builds). * - ********************************************************************** - * - * To compile: - * gcc -Iboard/${BOARD} -std=gnu11 util/gpios_to_zephyr_dts.c \ - * -o /tmp/print_gpios - * - * Then run /tmp/print_gpios and paste the result into your gpio DTS - * overlay. - */ - -#define _POSIX_C_SOURCE 200809L - -#include <ctype.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> - -/* - * Implement the macros used in the gpio.inc files, but print DTS - * format equivalents. - */ -#define GPIO_INT_RISING GPIO_INPUT -#define GPIO_INT_FALLING GPIO_INPUT -#define GPIO_INT_BOTH GPIO_INPUT -#define GPIO_HIB_WAKE_HIGH 0 -#define GPIO_HIB_WAKE_LOW 0 -#define GPIO_LOCKED 0 -#define GPIO_SEL_1P8V 0 -#define GPIO_INT(name, pin, opts, int) GPIO(name, pin, opts) -#define GPIO(name, pin, opts) _gpio(#name, pin, opts) -#define UNUSED(pin) -#define UNIMPLEMENTED(name) -#define _gpio(name, pin, opts) \ - printf("%s {\n\tgpios = <&%s %s>;\n\tlabel = %s;\n};\n", \ - strlower(name), strlower(pin), \ - maybe_parens(strip_zero_ors(#opts)), #name); -#define PIN(A, B) "gpio" #A " " #B -#define ALTERNATE(...) -#define IOEX(...) -#define IOEX_INT(...) - -/* Strip out " | 0" and "0 | " from a string */ -static char *strip_zero_ors(const char *s) -{ - char *out = malloc(strlen(s) + 2); - const char *rd_ptr = s; - char *wr_ptr = out; - - while (*rd_ptr) { - if (!strncmp(rd_ptr, " | 0", 4) || - !strncmp(rd_ptr, "0 | ", 4)) { - rd_ptr += 4; - } else { - *wr_ptr = *rd_ptr; - rd_ptr++; - wr_ptr++; - } - } - - *wr_ptr = '\0'; - return out; -} - -/* - * Add parenthesis around the outside of a string if it contains the - * '|' character. - */ -static char *maybe_parens(const char *s) -{ - size_t out_sz = strlen(s) + 3; - char *out = malloc(out_sz); - - if (strchr(s, '|')) - snprintf(out, out_sz, "(%s)", s); - else - snprintf(out, out_sz, "%s", s); - - return out; -} - -/* Convert a string to lowercase */ -static char *strlower(const char *s) -{ - char *out = strdup(s); - - for (int i = 0; out[i]; i++) - out[i] = tolower(out[i]); - - return out; -} - -int main(int argc, char *argv[]) -{ -#include "gpio.inc" - return 0; -} diff --git a/util/host_command_check.sh b/util/host_command_check.sh deleted file mode 100755 index f699803b2e..0000000000 --- a/util/host_command_check.sh +++ /dev/null @@ -1,138 +0,0 @@ -#!/bin/bash -# -# 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. - -excludes=( --exclude-dir=build --exclude=TAGS ) - -####################################### -# Test if the following conditions hold for the ec host command -# The alpha numeric value of the define starts with 0x -# The alpha numeric value of the define is 4-hex digits -# The hex digits "A B C D E F" are capitalized -# Arguments: -# string - ec host command to check -# Returns: -# 0 if command is ok, else 1 -######################################## -check_cmd() { - IFS=" " - # Remove any tabs that may exist - tts=$(echo "$1" | sed 's/\t/ /g') - arr=( $tts ) - - # Check for 0x - if [[ "${arr[2]}" != 0x* ]]; then - return 1 - fi - - # Check that length is 6. 0x + 4 hex digits - if [[ ${#arr[2]} != 6 ]]; then - return 1 - fi - - # Check that hex digits are valid and uppercase - hd=${arr[2]:2} - if ! [[ $hd =~ ^[0-9A-F]{4}$ ]]; then - return 1 - fi - - # command is ok - return 0 -} - -####################################### -# Test if the string arg is in one of the following formats: -# file.X:#define EC_CMD_X XxXXXX -# file.X:#define EC_PRV_CMD_X XxXXXX -# Arguments: -# string - potential ec host command -# Returns: -# 0 if command is formated properly, else 1 -######################################## -should_check() { - IFS=" " - arr=( $1 ) - - # Check for file.X:#define - IFS=":" - temp=( ${arr[0]} ) - # Check for file.X - if [ ! -f "${temp[0]}" ]; then - return 1 - fi - - # Check for #define - if [[ "${temp[1]}" != "#define" ]]; then - return 1 - fi - - # Check for EC_CMD_XXX or EC_PRV_CMD_XXX - if [[ "${arr[1]}" != EC_CMD_* ]] && [[ "${arr[1]}" != EC_PRV_CMD_* ]]; then - return 1 - fi - - # Check for EC_XXX_XXX(n) - if [[ "${arr[1]}" =~ ')'$ ]]; then - return 1 - fi - - return 0 -} - -main() { - - # Do not run the check unless an EC_[xxx]CMD change is present. - if [[ -z "$(git diff --no-ext-diff "${PRESUBMIT_COMMIT}~" \ - "${PRESUBMIT_COMMIT}" -U0 | - egrep 'EC_[^ ]*CMD')" ]]; then - exit 0 - fi - - ec_errors=() - ei=0 - # Search all file occurrences of "EC_CMD" and store in array - IFS=$'\n' - ec_cmds=($(grep "${excludes[@]}" -r "EC_CMD")) - - # Loop through and find valid occurrences of "EC_CMD" to check - length=${#ec_cmds[@]} - for ((i = 0; i != length; i++)); do - if should_check "${ec_cmds[i]}"; then - if ! check_cmd "${ec_cmds[i]}"; then - ec_errors[$ei]="${ec_cmds[i]}" - ((ei++)) - fi - fi - done - - # Search all file occurrances of "EC_PRV_CMD" and store in array - IFS=$'\n' - ec_prv_cmds=($(grep "${excludes[@]}" -r "EC_PRV_CMD")) - - # Loop through and find valid occurrences of "EC_PRV_CMD" to check - length=${#ec_prv_cmds[@]} - for ((i = 0; i != length; i++)); do - if should_check "${ec_prv_cmds[i]}"; then - if ! check_cmd "${ec_prv_cmds[i]}"; then - ec_errors[$ei]="${ec_prv_cmds[i]}" - ((ei++)) - fi - fi - done - - # Check if any malformed ec host commands were found - if [ ! $ei -eq 0 ]; then - echo "The following host commands are malformed:" - # print all malformed host commands - for ((i = 0; i != ei; i++)); do - echo "FILE: ${ec_errors[i]}" - done - exit 1 - fi - - exit 0 -} - -main "$@" diff --git a/util/ide-config.sh b/util/ide-config.sh deleted file mode 100755 index 25edca2407..0000000000 --- a/util/ide-config.sh +++ /dev/null @@ -1,475 +0,0 @@ -#!/bin/bash -# Copyright 2020 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. -# -# Usage: ./util/ide-config.sh vscode all all:RO | tee .vscode/c_cpp_properties.json -# This tool needs to be run from the base ec directory. -# -# Future works should be put towards adding new IDE generators and adding -# mechanism for passing IDE specific parameters to the IDE generator. - -DEFAULT_IMAGE=RW -INDENT_WIDTH=${INDENT_WIDTH:-1} -INDENT_CHAR=${INDENT_CHAR:-$'\t'} -INCLUDES_DROP_ROOT=${INCLUDES_DROP_ROOT:-false} -PARALLEL_CACHE_FILL=${PARALLEL_CACHE_FILL:-true} -FORCE_INCLUDE_CONFIG_H=${FORCE_INCLUDE_CONFIG_H:-false} -# JOB_BATCH_SIZE is the number of jobs allowed to spawn at any given point. -# This is an inefficient manner of resource management, but at least it -# throttles process creation. Due to the low utilization or each job, -# multiply the number of real processors by 2. -JOB_BATCH_SIZE=${JOB_BATCH_SIZE:-$(($(nproc) * 2))} - -MAKE_CACHE_DIR="" - -init() { - MAKE_CACHE_DIR=$(mktemp -t -d ide-config.XXXX) - mkdir -p "${MAKE_CACHE_DIR}/defines" - mkdir -p "${MAKE_CACHE_DIR}/includes" - trap deinit EXIT -} - -deinit() { - rm -rf "${MAKE_CACHE_DIR}" -} - -usage() { - cat <<-HEREDOC - Usage: ide-config.sh <vscode|eclipse> [BOARD:IMAGE] [BOARD:IMAGE...] - Generate a C language configuration for a given IDE and EC board. - - Examples: - ide-config.sh vscode all:RW all:RO | tee .vscode/c_cpp_properties.json - ide-config.sh vscode nocturne # implicitly :RW - ide-config.sh vscode nocturne_fp:RO - ide-config.sh vscode nocturne:RO hatch:RW - ide-config.sh vscode all # implicitly :RW - ide-config.sh eclipse nocturne_fp > ~/Downloads/nocturne_fp-RW.xml - HEREDOC -} - -# Usage: iprintf <indent-level> <printf-fmt> [printf-args...] -iprintf() { - local level=$1 - shift - - local n=$((INDENT_WIDTH*level)) - if [[ $n -ne 0 ]]; then - eval printf '"${INDENT_CHAR}%.0s"' "{1..$n}" - fi - # shellcheck disable=SC2059 - printf "$@" - return $? -} - -# Usage: parse-cfg-board <cfg-string> -# -# Example: parse-cfg-board nocturne:RW -parse-cfg-board() { - local cfg=$1 - # Remove possible :RW or :RO - local board=${cfg%%:*} - if [[ -z ${board} ]]; then - return 1 - fi - echo "${board}" -} - -# Usage: parse-cfg-image <cfg-string> -# -# Example: parse-cfg-image nocturne:RW -# Example: parse-cfg-image nocturne -parse-cfg-image() { - local cfg=$1 - - local board - if ! board=$(parse-cfg-board "${cfg}"); then - return 1 - fi - # Remove known board part - cfg=${cfg#${board}} - cfg=${cfg#":"} - # Use default image if none set - cfg=${cfg:-${DEFAULT_IMAGE}} - - case ${cfg} in - RW|RO) - echo "${cfg}" - return 0 - ;; - *) - return 1 - ;; - esac -} - -# Usage: make-defines <board> <RO|RW> -make-defines() { - local board=$1 - local image=$2 - - local cache="${MAKE_CACHE_DIR}/defines/${board}-${image}" - - if [[ ! -f "${cache}" ]]; then - make print-defines BOARD="${board}" BLD="${image}" >"${cache}" - fi - - cat "${cache}" -} - -# Usage: make-includes <board> <RO|RW> -# -# Rerun a newline separated list of include directories relative to the ec's -# root directory. -make-includes() { - local board=$1 - local image=$2 - - local cache="${MAKE_CACHE_DIR}/includes/${board}-${image}" - - if [[ ! -f "${cache}" ]]; then - make print-includes BOARD="${board}" BLD="${image}" \ - | xargs realpath --relative-to=. \ - | { - if [[ "${INCLUDES_DROP_ROOT}" == true ]]; then - grep -v "^\.$" - else - cat - fi - } >"${cache}" - fi - - cat "${cache}" -} - -# Usage: make-boards -make-boards() { - local cache="${MAKE_CACHE_DIR}/boards" - - if [[ ! -f "${cache}" ]]; then - make print-boards >"${cache}" - fi - - cat "${cache}" -} - -# Usage: <newline-list> | join <left> <right> <separator> -# -# JSON: includes nocturne_fp RW | join '"' '"' ',\n' -# C: includes nocturne_fp RW | join '"' '",' '\n' -join() { - local left=$1 - local right=$2 - local sep=$3 - - local first=true - while read -r line; do - # JSON is ridiculous for not allowing a trailing , - if [[ "${first}" == true ]]; then - first=false - else - printf "%b" "${sep}" - fi - printf "%b%s%b" "${left}" "${line}" "${right}" - done - echo -} - -# Usage: <content> | encap <header> <footer> [indent] -# -# Encapsulate the content from stdin with a header, footer, and indentation. -encap() { - local header=$1 - local footer=$2 - local indent=${3:-0} - - iprintf "${indent}" "%b" "${header}" - while IFS="" read -r line; do - iprintf $((1+indent)) "%s\n" "${line}" - done - iprintf "${indent}" "%b" "${footer}" -} - -########################################################################## - -# Usage: vscode [cfg...] -# -# Generate the content for one c_cpp_properties.json that contains -# multiple selectable configurations for each board-image pair. -# In VSCode you can select the config in the bottom right, next to the -# "Select Language Mode". You will only see this option when a C/C++ file -# is open. Additionally, you can select a configuration by pressing -# Ctrl-Shift-P and selecting the "C/C++ Select a Configuration..." option. -vscode() { - local first=true - { - for cfg; do - local board image - if ! board=$(parse-cfg-board "${cfg}"); then - echo "Failed to parse board from cfg '${cfg}'" - return 1 - fi - if ! image=$(parse-cfg-image "${cfg}"); then - echo "Failed to parse image from cfg '${cfg}'" - return 1 - fi - { - printf '"name": "%s",\n' "${board}:${image}" - make-includes "${board}" "${image}" \ - | join '"' '"' ',\n' \ - | encap '"includePath": [\n' '],\n' - make-defines "${board}" "${image}" \ - | join '"' '"' ',\n' \ - | encap '"defines": [\n' '],\n' - - if [[ "${FORCE_INCLUDE_CONFIG_H}" == true ]]; then - echo '"include/config.h"' \ - | encap '"forcedInclude": [\n' '],\n' - fi - - echo '"compilerPath": "/usr/bin/arm-none-eabi-gcc",' - # echo '"compilerArgs": [],' - # The macro __STDC_VERSION__ is 201710L, which corresponds to c18. - # VSCode doesn't have a C18 option, so go with C17. Since we seem - # to use a lot of GNUC features, let's go with gnu17 instead of c17. - echo '"cStandard": "gnu17",' - # echo '"cppStandard": "c++17",' - echo '"intelliSenseMode": "gcc-x64"' - } | { - # A single named configuration - if [[ "${first}" == true ]]; then - encap '{\n' '}' - else - encap ',\n{\n' '}' - fi - } - first=false - done - echo - } \ - | { - encap '"configurations": [\n' '],\n' - echo '"version": 4' - } \ - | encap '{\n' '}\n' -} - -# Usage: eclipse-cdt-import [cfg...] -# -# * Add odd EC "File Types" -# - *.tasklist *.mocklist *.testlist *.irqlist "C Header File" -# - *.inc "C Header File" -# - gpio.wrap "C Header File" -# * Enable the indexer to follow current build configuration -# - Enable "Index all header variants" -# - Enable "Use active build configuration" (ensure this options sticks) -# - Probably bump up the Cache Limit->"Absolute Limit" -# * Remove default system includes -# - Depending on your eclipse toolchain configuration, it may be possible -# to remove the standard C headers. -# This helps satisfy the EC's -nostdinc usage. -eclipse-cdt-import() { - if [[ $# -gt 1 ]]; then - echo "Error - eclipse generator can only process one board cfg" >&2 - return 1 - fi - - local cfg=$1 - local board image - - board=$(parse-cfg-board "${cfg}") - image=$(parse-cfg-image "${cfg}") - - local includes - # Grab workspace/project local paths - includes+="$(make-includes "${board}" "${image}" | grep -v "^\.\." \ - | join '<includepath workspace_path="true">' '</includepath>' '\n\t\t\t')" - # Add separator manually - includes+="$(printf "\n\t\t\t")" - # Grab external paths (wil start with .. because forced relative) - # shellcheck disable=SC2016 - includes+="$(make-includes "${board}" "${image}" | grep "^\.\." \ - | join '<includepath>${ProjDirPath}/' '</includepath>' '\n\t\t\t')" - - local macros - macros="$( - while read -r name value; do - { - join '<name>' '</name>' '' <<<"${name}" - join '<value>' '</value>' '' <<<"${value}" - } | encap '<macro>\n' '</macro>\n' 3 - done < <(make-defines "${board}" "${image}" | tr '=' '\t') - )" - - cat <<EOF -<?xml version="1.0" encoding="UTF-8"?> -<!-- Generated for ${board}:${image} --> -<cdtprojectproperties> - <section name="org.eclipse.cdt.internal.ui.wizards.settingswizards.IncludePaths"> - <!-- Start Normal CDT --> - <language name="holder for library settings"></language> - - <language name="Assembly"> - ${includes} - </language> - - <language name="GNU C++"> - ${includes} - </language> - - <language name="GNU C"> - ${includes} - </language> - <!-- End Normal CDT --> - - <!-- Start CDT Cross/Embedded --> - <language name="C Source File"> - ${includes} - </language> - - <language name="Object File"> - </language> - - <language name="Assembly Source File"> - ${includes} - </language> - <!-- End CDT Cross/Embedded --> - </section> - - <section name="org.eclipse.cdt.internal.ui.wizards.settingswizards.Macros"> - <!-- Start Normal CDT --> - <language name="holder for library settings"></language> - - <language name="Assembly"> -${macros} - </language> - - <language name="GNU C++"> -${macros} - </language> - - <language name="GNU C"> -${macros} - </language> - <!-- End Normal CDT --> - - <!-- Start CDT Cross/Embedded --> - <language name="C Source File"> -${macros} - </language> - - <language name="Object File"> - </language> - - <language name="Assembly Source File"> -${macros} - </language> - <!-- End CDT Cross/Embedded --> - </section> -</cdtprojectproperties> -EOF -} - -# Usage: main <ide> [cfgs...] -main() { - # Disaply help if no args - if [[ $# -lt 1 ]]; then - usage - exit 1 - fi - # Search for help flag - for flag; do - case ${flag} in - help|--help|-h) - usage - exit 0 - ;; - esac - done - - local ide=$1 - shift - - # Expand possible "all" cfgs - local board image - local -a cfgs=( ) - for cfg; do - # We parse both board and image to pre-sanatize the input - if ! board=$(parse-cfg-board "${cfg}"); then - echo "Failed to parse board from cfg '${cfg}'" >&2 - exit 1 - fi - if ! image=$(parse-cfg-image "${cfg}"); then - echo "Failed to parse image from cfg '${cfg}'" >&2 - exit 1 - fi - # Note "all:*" could be specified multiple times for RO and RW - # Note "all:*" could be specified with other specific board:images - if [[ "${board}" == all ]]; then - local -a allboards=( ) - mapfile -t allboards < <(make-boards) - cfgs+=( "${allboards[@]/%/:${image}}" ) - else - cfgs+=( "${cfg}" ) - fi - done - - # Technically, we have not sanitized the cfgs generated from - # "all" expression. - - # Make configs unique (and sorted) - mapfile -t cfgs < <(echo "${cfgs[@]}" | tr ' ' '\n' | sort -u) - echo "# Generating a config for the following board:images: " >&2 - echo "${cfgs[@]}" | tr ' ' '\n' | sort -u | column >&2 - - # Prefill the make cache in parallel - # This is important because each make request take about 700ms. - # When running on all boards, this could result in (127*2)*700ms = 3mins. - if [[ "${PARALLEL_CACHE_FILL}" == true ]]; then - echo "# Fetching make defines and includes. Please wait." >&2 - - # We run into process limits if we launch all processes at the - # same time, so we must split them in half. - # This need some jobserver management. - - # Run make for RWs and ROs - local -i jobs=0 - for cfg in "${cfgs[@]}"; do - if ! board="$(parse-cfg-board "${cfg}")"; then - echo "Failed to parse board from cfg '${cfg}'" >&2 - exit 1 - fi - if ! image="$(parse-cfg-image "${cfg}")"; then - echo "Failed to parse image from cfg '${cfg}'" >&2 - exit 1 - fi - make-defines "${board}" "${image}" >/dev/null & - ((++jobs % JOB_BATCH_SIZE == 0)) && wait - make-includes "${board}" "${image}" >/dev/null & - ((++jobs % JOB_BATCH_SIZE == 0)) && wait - done - wait - fi - - # Run the IDE's generator - case "${ide}" in - vscode) - vscode "${cfgs[@]}" || exit $? - ;; - eclipse) - eclipse-cdt-import "${cfgs[@]}" || exit $? - ;; - *) - echo "Error - IDE '${ide}' is an unsupported." >&2 - exit 1 - ;; - esac -} - -init - -# Only start if not being sourced -if [[ "$0" == "${BASH_SOURCE[0]}" ]]; then - main "$@" -fi diff --git a/util/inject-keys.py b/util/inject-keys.py deleted file mode 100755 index bd10b693ad..0000000000 --- a/util/inject-keys.py +++ /dev/null @@ -1,130 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -# 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. - -# Note: This is a py2/3 compatible file. - -from __future__ import print_function -import string -import subprocess -import sys - - -KEYMATRIX = {'`': (3, 1), '1': (6, 1), '2': (6, 4), '3': (6, 2), '4': (6, 3), - '5': (3, 3), '6': (3, 6), '7': (6, 6), '8': (6, 5), '9': (6, 9), - '0': (6, 8), '-': (3, 8), '=': (0, 8), 'q': (7, 1), 'w': (7, 4), - 'e': (7, 2), 'r': (7, 3), 't': (2, 3), 'y': (2, 6), 'u': (7, 6), - 'i': (7, 5), 'o': (7, 9), 'p': (7, 8), '[': (2, 8), ']': (2, 5), - '\\': (3, 11), 'a': (4, 1), 's': (4, 4), 'd': (4, 2), 'f': (4, 3), - 'g': (1, 3), 'h': (1, 6), 'j': (4, 6), 'k': (4, 5), 'l': (4, 9), - ';': (4, 8), '\'': (1, 8), 'z': (5, 1), 'x': (5, 4), 'c': (5, 2), - 'v': (5, 3), 'b': (0, 3), 'n': (0, 6), 'm': (5, 6), ',': (5, 5), - '.': (5, 9), '/': (5, 8), ' ': (5, 11), '<right>': (6, 12), - '<alt_r>': (0, 10), '<down>': (6, 11), '<tab>': (2, 1), - '<f10>': (0, 4), '<shift_r>': (7, 7), '<ctrl_r>': (4, 0), - '<esc>': (1, 1), '<backspace>': (1, 11), '<f2>': (3, 2), - '<alt_l>': (6, 10), '<ctrl_l>': (2, 0), '<f1>': (0, 2), - '<search>': (0, 1), '<f3>': (2, 2), '<f4>': (1, 2), '<f5>': (3, 4), - '<f6>': (2, 4), '<f7>': (1, 4), '<f8>': (2, 9), '<f9>': (1, 9), - '<up>': (7, 11), '<shift_l>': (5, 7), '<enter>': (4, 11), - '<left>': (7, 12)} - - -UNSHIFT_TABLE = { '~': '`', '!': '1', '@': '2', '#': '3', '$': '4', - '%': '5', '^': '6', '&': '7', '*': '8', '(': '9', - ')': '0', '_': '-', '+': '=', '{': '[', '}': ']', - '|': '\\', - ':': ';', '"': "'", '<': ',', '>': '.', '?': '/'} - -for c in string.ascii_lowercase: - UNSHIFT_TABLE[c.upper()] = c - - -def inject_event(key, press): - if len(key) >= 2 and key[0] != '<': - key = '<' + key + '>' - if key not in KEYMATRIX: - print("%s: invalid key: %s" % (this_script, key)) - sys.exit(1) - (row, col) = KEYMATRIX[key] - subprocess.call(["ectool", "kbpress", str(row), str(col), - "1" if press else "0"]) - - -def inject_key(key): - inject_event(key, True) - inject_event(key, False) - - -def inject_string(string): - for c in string: - if c in KEYMATRIX: - inject_key(c) - elif c in UNSHIFT_TABLE: - inject_event("<shift_l>", True) - inject_key(UNSHIFT_TABLE[c]) - inject_event("<shift_l>", False) - else: - print("unimplemented character:", c) - sys.exit(1) - - -def usage(): - print("Usage: %s [-s <string>] [-k <key>]" % this_script, - "[-p <pressed-key>] [-r <released-key>] ...") - print("Examples:") - print("%s -s MyPassw0rd -k enter" % this_script) - print("%s -p ctrl_l -p alt_l -k f3 -r alt_l -r ctrl_l" % this_script) - - -def help(): - usage() - print("Valid keys are:") - i = 0 - for key in KEYMATRIX: - print("%12s" % key, end='') - i += 1 - if i % 4 == 0: - print() - print() - print("angle brackets may be omitted") - - -def usage_check(asserted_condition, message): - if asserted_condition: - return - print("%s:" % this_script, message) - usage() - sys.exit(1) - - -# -- main - -this_script = sys.argv[0] -arg_len = len(sys.argv) - -if arg_len > 1 and sys.argv[1] == "--help": - help() - sys.exit(0) - -usage_check(arg_len > 1, "not enough arguments") -usage_check(arg_len % 2 == 1, "mismatched arguments") - -for i in range(1, arg_len, 2): - usage_check(sys.argv[i] in ("-s", "-k", "-p", "-r"), - "unknown flag: %s" % sys.argv[i]) - -for i in range(1, arg_len, 2): - flag = sys.argv[i] - arg = sys.argv[i+1] - if flag == "-s": - inject_string(arg) - elif flag == "-k": - inject_key(arg) - elif flag == "-p": - inject_event(arg, True) - elif flag == "-r": - inject_event(arg, False) diff --git a/util/iteflash.c b/util/iteflash.c deleted file mode 100644 index a4a166d3d8..0000000000 --- a/util/iteflash.c +++ /dev/null @@ -1,2445 +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. - * - * ITE83xx SoC in-system programming tool - */ - -/* remove when ftdi_usb_purge_buffers has been replaced to follow libftdi */ -#define _FTDI_DISABLE_DEPRECATED - -#include <errno.h> -#include <fcntl.h> -#include <ftdi.h> -#include <getopt.h> -#include <linux/i2c-dev.h> -#include <linux/i2c.h> -#include <signal.h> -#include <stdbool.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/ioctl.h> -#include <time.h> -#include <unistd.h> -#include <sys/wait.h> - -#include "compile_time_macros.h" -#include "usb_if.h" - -/* Default FTDI device : Servo v2. */ -#define SERVO_USB_VID 0x18d1 -#define SERVO_USB_PID 0x5002 -#define SERVO_INTERFACE INTERFACE_B - -/* Default CCD device: Cr50. */ -#define CR50_USB_VID 0x18d1 -#define CR50_USB_PID 0x5014 - -/* Cr50 exposed properties of the USB I2C endpoint. */ -#define CR50_I2C_SUBCLASS 82 -#define CR50_I2C_PROTOCOL 1 - -#define CROS_CMD_ADDR 0x78 /* USB_I2C_CMD_ADDR 0xF0 >> 1 */ -#define CROS_CMD_ITE_SYNC 0 - -/* DBGR I2C addresses */ -#define I2C_CMD_ADDR 0x5A -#define I2C_DATA_ADDR 0x35 -#define I2C_BLOCK_ADDR 0x79 - -#define FTDI_I2C_FREQ 400000 - -/* I2C pins on the FTDI interface */ -#define SCL_BIT BIT(0) -#define SDA_BIT BIT(1) - -/* Chip ID register value */ -#define CHIP_ID 0x8380 - -/* Embedded flash page size */ -#define PAGE_SIZE (1<<8) - -/* Embedded flash block write size for different programming modes. */ -#define FTDI_BLOCK_WRITE_SIZE (1<<16) - -/* JEDEC SPI Flash commands */ -#define SPI_CMD_PAGE_PROGRAM 0x02 -#define SPI_CMD_WRITE_DISABLE 0x04 -#define SPI_CMD_READ_STATUS 0x05 -#define SPI_CMD_WRITE_ENABLE 0x06 -#define SPI_CMD_FAST_READ 0x0B -#define SPI_CMD_CHIP_ERASE 0x60 -#define SPI_CMD_SECTOR_ERASE_1K 0xD7 -#define SPI_CMD_SECTOR_ERASE_4K 0x20 -#define SPI_CMD_WORD_PROGRAM 0xAD -#define SPI_CMD_EWSR 0x50 /* Enable Write Status Register */ -#define SPI_CMD_WRSR 0x01 /* Write Status Register */ -#define SPI_CMD_RDID 0x9F /* Read Flash ID */ - -/* Size for FTDI outgoing buffer */ -#define FTDI_CMD_BUF_SIZE (1<<12) - -/* Reset Status */ -#define RSTS_VCCDO_PW_ON 0x40 -#define RSTS_VFSPIPG 0x20 -#define RSTS_HGRST 0x08 -#define RSTS_GRST 0x04 - -/* I2C MUX Configuration: TCA9543 or PCA9546 */ -#define I2C_MUX_CMD_ADDR 0x70 -#define I2C_MUX_CMD_NONE 0x00 -#define I2C_MUX_CMD_INAS 0x01 -#define I2C_MUX_CMD_EC 0x02 - -/* Eflash Type*/ -#define EFLASH_TYPE_8315 0x01 -#define EFLASH_TYPE_KGD 0x02 -#define EFLASH_TYPE_NONE 0xFF - -uint8_t eflash_type; -uint8_t spi_cmd_sector_erase; - -/* Embedded flash number of pages in a sector erase */ -uint8_t sector_erase_pages; - - -static volatile sig_atomic_t exit_requested; - -struct i2c_interface; - -/* Config mostly comes from the command line. Defaults are set in main(). */ -struct iteflash_config { - char *input_filename; - char *output_filename; - int send_waveform; /* boolean */ - int erase; /* boolean */ - int i2c_mux; /* boolean */ - int debug; /* boolean */ - int disable_watchdog; /* boolean */ - int disable_protect_path; /* boolean */ - int block_write_size; - int usb_interface; - int usb_vid; - int usb_pid; - int verify; /* boolean */ - char *usb_serial; - char *i2c_dev_path; - const struct i2c_interface *i2c_if; - size_t range_base; - size_t range_size; -}; - -struct common_hnd { - struct iteflash_config conf; - int flash_size; - int flash_cmd_v2; /* boolean */ - int dbgr_addr_3bytes; /* boolean */ - union { - int i2c_dev_fd; - struct usb_endpoint uep; - struct ftdi_context *ftdi_hnd; - }; -}; - -struct cmds { - uint8_t addr; - uint8_t cmd; -}; - -/* For all callback return values, zero indicates success, non-zero failure. */ -struct i2c_interface { - /* Optional, may be NULL. */ - int (*interface_init)(struct common_hnd *chnd); - /* Always called if non-NULL, even if special waveform is skipped! */ - /* Optional, may be NULL. */ - int (*interface_post_waveform)(struct common_hnd *chnd); - /* Called exactly once if and only if interface_init() succeeded. */ - /* Optional, may be NULL. */ - int (*interface_shutdown)(struct common_hnd *chnd); - /* Optional, may be NULL (unsupported for this I2C interface type). */ - int (*send_special_waveform)(struct common_hnd *chnd); - /* Required, must not be NULL. */ - int (*byte_transfer)(struct common_hnd *chnd, uint8_t addr, - uint8_t *data, int write, int numbytes); - /* Required, must be positive. */ - int default_block_write_size; -}; - -static int spi_flash_command_short(struct common_hnd *chnd, - uint8_t cmd, char *desc); - -static void null_and_free(void **ptr) -{ - void *holder; - - if (*ptr) { - holder = *ptr; - *ptr = NULL; - free(holder); - } -} - -/* This releases any memory owned by *conf. This does NOT free conf itself! */ -/* Not all pointers in conf necessarily point to memory owned by it. */ -static void config_release(struct iteflash_config *conf) -{ - null_and_free((void **)&conf->input_filename); - null_and_free((void **)&conf->output_filename); - null_and_free((void **)&conf->usb_serial); - null_and_free((void **)&conf->i2c_dev_path); -} - -/* number of bytes to send consecutively before checking for ACKs */ -#define FTDI_TX_BUFFER_LIMIT 32 - -static inline int i2c_byte_transfer(struct common_hnd *chnd, uint8_t addr, - uint8_t *data, int write, int numbytes) -{ - /* If we got a termination signal, stop sending data */ - if (exit_requested) - return -1; - - return chnd->conf.i2c_if->byte_transfer(chnd, addr, data, write, - numbytes); -} - -static int linux_i2c_byte_transfer(struct common_hnd *chnd, uint8_t addr, - uint8_t *data, int write, int numbytes) -{ - static const int nmsgs = 1; - int ret, extra_int; - struct i2c_msg i2cmsg = {}; - struct i2c_rdwr_ioctl_data msgset = {}; - - i2cmsg.addr = addr; - if (!write) - i2cmsg.flags |= I2C_M_RD; - i2cmsg.buf = data; - i2cmsg.len = numbytes; - - msgset.msgs = &i2cmsg; - msgset.nmsgs = nmsgs; - - ret = ioctl(chnd->i2c_dev_fd, I2C_RDWR, &msgset); - if (ret < 0) { - extra_int = errno; - fprintf(stderr, "%s: ioctl() failed with return value %d and " - "errno %d\n", __func__, ret, extra_int); - if (ret == -1 && extra_int) - ret = -abs(extra_int); - } else if (ret < nmsgs) { - fprintf(stderr, "%s: failed to send %d of %d I2C messages\n", - __func__, (nmsgs - ret), nmsgs); - ret = -1; - } else { - ret = 0; - } - return ret; -} - -static int i2c_add_send_byte(struct ftdi_context *ftdi, uint8_t *buf, - uint8_t *ptr, uint8_t *tbuf, int tcnt, int debug) -{ - int ret, i, j, remaining_data, ack_idx; - int tx_buffered = 0; - static uint8_t ack[FTDI_TX_BUFFER_LIMIT]; - uint8_t *b = ptr; - uint8_t failed_ack = 0; - - for (i = 0; i < tcnt; i++) { - /* WORKAROUND: force SDA before sending the next byte */ - *b++ = SET_BITS_LOW; *b++ = SDA_BIT; *b++ = SCL_BIT | SDA_BIT; - /* write byte */ - *b++ = MPSSE_DO_WRITE | MPSSE_BITMODE | MPSSE_WRITE_NEG; - *b++ = 0x07; *b++ = *tbuf++; - /* prepare for ACK */ - *b++ = SET_BITS_LOW; *b++ = 0; *b++ = SCL_BIT; - /* read ACK */ - *b++ = MPSSE_DO_READ | MPSSE_BITMODE | MPSSE_LSB; - *b++ = 0; - *b++ = SEND_IMMEDIATE; - - tx_buffered++; - - /* - * On the last byte, or every FTDI_TX_BUFFER_LIMIT bytes, read - * the ACK bits. - */ - if (i == tcnt-1 || (tx_buffered == FTDI_TX_BUFFER_LIMIT)) { - /* write data */ - ret = ftdi_write_data(ftdi, buf, b - buf); - if (ret < 0) { - fprintf(stderr, "failed to write byte\n"); - return ret; - } - - /* read ACK bits */ - remaining_data = tx_buffered; - ack_idx = 0; - do { - ret = ftdi_read_data(ftdi, &ack[ack_idx], - remaining_data); - if (ret < 0) { - fprintf(stderr, "read ACK failed\n"); - return ret; - } - remaining_data -= ret; - ack_idx += ret; - } while (remaining_data); - for (j = 0; j < tx_buffered; j++) { - if ((ack[j] & 0x80) != 0) - failed_ack = ack[j]; - } - - /* check ACK bits */ - if (ret < 0 || failed_ack) { - if (debug) - fprintf(stderr, - "write ACK fail: %d, 0x%02x\n", - ret, failed_ack); - return -ENXIO; - } - - /* reset for next set of transactions */ - b = ptr; - tx_buffered = 0; - } - } - return 0; -} - -static int i2c_add_recv_bytes(struct ftdi_context *ftdi, uint8_t *buf, - uint8_t *ptr, uint8_t *rbuf, int rcnt) -{ - int ret, i, rbuf_idx; - uint8_t *b = ptr; - - for (i = 0; i < rcnt; i++) { - /* set SCL low */ - *b++ = SET_BITS_LOW; *b++ = 0; *b++ = SCL_BIT; - /* read the byte on the wire */ - *b++ = MPSSE_DO_READ; *b++ = 0; *b++ = 0; - - if (i == rcnt - 1) { - /* NACK last byte */ - *b++ = SET_BITS_LOW; *b++ = 0; *b++ = SCL_BIT; - *b++ = MPSSE_DO_WRITE | MPSSE_BITMODE | MPSSE_WRITE_NEG; - *b++ = 0; *b++ = 0xff; *b++ = SEND_IMMEDIATE; - } else { - /* ACK all other bytes */ - *b++ = SET_BITS_LOW; *b++ = 0; *b++ = SCL_BIT | SDA_BIT; - *b++ = MPSSE_DO_WRITE | MPSSE_BITMODE | MPSSE_WRITE_NEG; - *b++ = 0; *b++ = 0; *b++ = SEND_IMMEDIATE; - } - } - - ret = ftdi_write_data(ftdi, buf, b - buf); - if (ret < 0) { - fprintf(stderr, "failed to prepare read\n"); - return ret; - } - - rbuf_idx = 0; - do { - ret = ftdi_read_data(ftdi, &rbuf[rbuf_idx], rcnt); - if (ret < 0) { - fprintf(stderr, "read byte failed\n"); - break; - } - rcnt -= ret; - rbuf_idx += ret; - } while (rcnt); - - return ret; -} - -#define USB_I2C_HEADER_SIZE 4 -static int ccd_i2c_byte_transfer(struct common_hnd *chnd, uint8_t addr, - uint8_t *data, int write, int numbytes) -{ - uint8_t usb_buffer[USB_I2C_HEADER_SIZE + numbytes + - (((!write * numbytes) > 0x7f) ? 2 : 0)]; - size_t response_size; - size_t extra = 0; - - /* - * Build a message following format described in ./include/usb_i2c.h. - * - * Hardcode port, the lowest 4 bits of the first byte, to 0; may need - * to make this a command line option. - */ - usb_buffer[0] = 0; - - usb_buffer[1] = addr; - if (write) { - /* - * Write count might spill over into the top 4 bits of the - * first byte. We trust the caller not to pass numbytes - * exceeding (2^12 - 1). - */ - if (numbytes > 255) - usb_buffer[0] |= (numbytes >> 4) & 0xf0; - usb_buffer[2] = numbytes & 0xff; - usb_buffer[3] = 0; - memcpy(usb_buffer + USB_I2C_HEADER_SIZE, data, numbytes); - } else { - usb_buffer[2] = 0; - if (numbytes < 0x80) { - usb_buffer[3] = numbytes; - } else { - usb_buffer[3] = (numbytes & 0x7f) | 0x80; - usb_buffer[4] = numbytes >> 7; - usb_buffer[5] = 0; - extra = 2; - } - } - - response_size = 0; - usb_trx(&chnd->uep, usb_buffer, - write ? sizeof(usb_buffer) : USB_I2C_HEADER_SIZE + extra, - usb_buffer, sizeof(usb_buffer), 1, &response_size); - - if (response_size < (USB_I2C_HEADER_SIZE + (write ? 0 : numbytes))) { - fprintf(stderr, "%s: got too few bytes (%zd) in response\n", - __func__, response_size); - return -1; - } - - if (usb_buffer[0]) { - uint32_t rv; - - /* - * Error is reported as a 16 bit value in little endian byte - * order. - */ - rv = usb_buffer[1]; - rv = (rv << 8) + usb_buffer[0]; - - fprintf(stderr, "%s: usb i2c error %d\n", - __func__, - (((uint16_t)usb_buffer[1]) << 8) + usb_buffer[0]); - - return -rv; - } - - if (!write) - memcpy(data, usb_buffer + USB_I2C_HEADER_SIZE, numbytes); - - return 0; -} - -static int ftdi_i2c_byte_transfer(struct common_hnd *chnd, uint8_t addr, - uint8_t *data, int write, int numbytes) -{ - int ret, rets; - static uint8_t buf[FTDI_CMD_BUF_SIZE]; - uint8_t *b; - uint8_t slave_addr; - struct ftdi_context *ftdi; - - ret = 0; - b = buf; - ftdi = chnd->ftdi_hnd; - - /* START condition */ - /* SCL & SDA high */ - *b++ = SET_BITS_LOW; *b++ = 0; *b++ = 0; - *b++ = SET_BITS_LOW; *b++ = 0; *b++ = 0; - /* SCL high, SDA low */ - *b++ = SET_BITS_LOW; *b++ = 0; *b++ = SDA_BIT; - *b++ = SET_BITS_LOW; *b++ = 0; *b++ = SDA_BIT; - /* SCL low, SDA low */ - *b++ = SET_BITS_LOW; *b++ = 0; *b++ = SCL_BIT | SDA_BIT; - *b++ = SET_BITS_LOW; *b++ = 0; *b++ = SCL_BIT | SDA_BIT; - - /* send address */ - slave_addr = (addr << 1) | (write ? 0 : 1); - ret = i2c_add_send_byte(ftdi, buf, b, &slave_addr, 1, chnd->conf.debug); - if (ret < 0) { - if (chnd->conf.debug) - fprintf(stderr, "address %02x failed\n", addr); - ret = -ENXIO; - goto exit_xfer; - } - - b = buf; - if (write) /* write data */ - ret = i2c_add_send_byte(ftdi, buf, b, data, numbytes, - chnd->conf.debug); - else /* read data */ - ret = i2c_add_recv_bytes(ftdi, buf, b, data, numbytes); - -exit_xfer: - b = buf; - /* STOP condition */ - /* SCL high, SDA low */ - *b++ = SET_BITS_LOW; *b++ = 0; *b++ = SDA_BIT; - *b++ = SET_BITS_LOW; *b++ = 0; *b++ = SDA_BIT; - /* SCL high, SDA high */ - *b++ = SET_BITS_LOW; *b++ = 0; *b++ = 0; - *b++ = SET_BITS_LOW; *b++ = 0; *b++ = 0; - - rets = ftdi_write_data(ftdi, buf, b - buf); - if (rets < 0) - fprintf(stderr, "failed to send STOP\n"); - return ret; -} - -static int i2c_write_byte(struct common_hnd *chnd, uint8_t cmd, uint8_t data) -{ - int ret; - - ret = i2c_byte_transfer(chnd, I2C_CMD_ADDR, &cmd, 1, 1); - if (ret < 0) - return -EIO; - ret = i2c_byte_transfer(chnd, I2C_DATA_ADDR, &data, 1, 1); - if (ret < 0) - return -EIO; - - return 0; -} - -static int i2c_read_byte(struct common_hnd *chnd, uint8_t cmd, uint8_t *data) -{ - int ret; - - ret = i2c_byte_transfer(chnd, I2C_CMD_ADDR, &cmd, 1, 1); - if (ret < 0) - return -EIO; - ret = i2c_byte_transfer(chnd, I2C_DATA_ADDR, data, 0, 1); - if (ret < 0) - return -EIO; - - return 0; -} - -/* Configure I2C MUX to choose EC Prog channel */ -static int config_i2c_mux(struct common_hnd *chnd, uint8_t cmd) -{ - int ret; - - ret = i2c_byte_transfer(chnd, I2C_MUX_CMD_ADDR, &cmd, 1, 1); - if (ret < 0) { - fprintf(stderr, "Failed to configure I2C MUX."); - return -EIO; - } - - return 0; -} - -/* Get 3rd Byte Chip ID */ -static int get_3rd_chip_id_byte(struct common_hnd *chnd, uint8_t *chip_id) -{ - int ret = 0; - - ret = i2c_write_byte(chnd, 0x80, 0xf0); - ret |= i2c_write_byte(chnd, 0x2f, 0x20); - ret |= i2c_write_byte(chnd, 0x2e, 0x85); - ret |= i2c_read_byte(chnd, 0x30, chip_id); - - if (ret < 0) - fprintf(stderr, "Failed to get id of 3rd byte."); - - return ret; -} - -static int check_flashid(struct common_hnd *chnd) -{ - int ret = 0; - uint8_t id[16], i; - struct cmds commands[] = { - {0x07, 0x7f}, - {0x06, 0xff}, - {0x04, 0x00}, - {0x05, 0xfe}, - {0x08, 0x00}, - {0x05, 0xfd}, - {0x08, 0x9f} - }; - - for (i = 0; i < ARRAY_SIZE(commands); i++) { - ret = i2c_write_byte(chnd, commands[i].addr, commands[i].cmd); - if (ret) { - fprintf(stderr, "Flash ID Failed : cmd %x ,data %x\n", - commands[i].addr, commands[i].cmd); - return ret; - } - } - - ret = i2c_byte_transfer(chnd, I2C_DATA_ADDR, id, 0, 16); - - if (ret < 0) - fprintf(stderr, "Check Flash ID FAILED\n"); - - if ((id[0] == 0xFF) && (id[1] == 0xFF) && (id[2] == 0xFE)) { - printf("EFLASH TYPE = 8315\n\r"); - eflash_type = EFLASH_TYPE_8315; - } else if ((id[0] == 0xC8) || (id[0] == 0xEF)) { - printf("EFLASH TYPE = KGD\n\r"); - eflash_type = EFLASH_TYPE_KGD; - } else { - printf("Invalid EFLASH TYPE : "); - printf("FLASH ID = %02x %02x %02x\n\r", id[0], id[1], id[2]); - eflash_type = EFLASH_TYPE_NONE; - ret = -EINVAL; - } - - return ret; -} - -/* Fills in chnd->flash_size */ -static int check_chipid(struct common_hnd *chnd) -{ - int ret; - uint8_t ver = 0xff; - uint32_t id = 0xffff; - uint16_t v2[7] = {128, 192, 256, 384, 512, 0, 1024}; - /* - * Chip Version is mapping from bit 3-0 - * Flash size is mapping from bit 7-4 - * - * Chip Version (bit 3-0) - * 0: AX - * 1: BX - * 2: CX - * 3: DX - * - * CX before flash size (bit 7-4) - * 0:128KB - * 4:192KB - * 8:256KB - * - * DX flash size(bit 7-4) - * 0:128KB - * 2:192KB - * 4:256KB - * 6:384KB - * 8:512KB - * - * flash size(bit 7-4) of it8xxx1 or it8xxx2 series - * 0:128KB - * 4:256KB - * 8:512KB - * C:1024KB - */ - - ret = i2c_read_byte(chnd, 0x00, (uint8_t *)&id + 1); - if (ret < 0) - return ret; - ret = i2c_read_byte(chnd, 0x01, (uint8_t *)&id); - if (ret < 0) - return ret; - ret = i2c_read_byte(chnd, 0x02, &ver); - if (ret < 0) - return ret; - - if ((id & 0xff00) != (CHIP_ID & 0xff00)) { - id |= 0xff0000; - ret = get_3rd_chip_id_byte(chnd, (uint8_t *)&id+2); - if (ret < 0) - return ret; - - if ((id & 0xf000f) == 0x80001 || (id & 0xf000f) == 0x80002) { - chnd->flash_cmd_v2 = 1; - chnd->dbgr_addr_3bytes = 1; - } else { - fprintf(stderr, "Invalid chip id: %05x\n", id); - return -EINVAL; - } - } else { - chnd->dbgr_addr_3bytes = 0; - if ((ver & 0x0f) >= 0x03) - chnd->flash_cmd_v2 = 1; - else - chnd->flash_cmd_v2 = 0; - } - /* compute embedded flash size from CHIPVER field */ - if (chnd->flash_cmd_v2) - chnd->flash_size = v2[(ver & 0xF0)>>5] * 1024; - else - chnd->flash_size = (128 + (ver & 0xF0)) * 1024; - - if (chnd->flash_size == 0) { - fprintf(stderr, "Invalid Flash Size"); - return -EINVAL; - } - - printf("CHIPID %05x, CHIPVER %02x, Flash size %d kB\n", id, ver, - chnd->flash_size / 1024); - - return 0; -} - -/* DBGR Reset */ -static int dbgr_reset(struct common_hnd *chnd, unsigned char val) -{ - int ret = 0; - - /* Reset CPU only, and we keep power state until flashing is done. */ - if (chnd->dbgr_addr_3bytes) - ret |= i2c_write_byte(chnd, 0x80, 0xf0); - - ret |= i2c_write_byte(chnd, 0x2f, 0x20); - ret |= i2c_write_byte(chnd, 0x2e, 0x06); - - /* Enable the Reset Status by val */ - ret |= i2c_write_byte(chnd, 0x30, val); - - ret |= i2c_write_byte(chnd, 0x27, 0x80); - if (ret < 0) - fprintf(stderr, "DBGR RESET FAILED\n"); - - return 0; -} - -/* Exit DBGR mode */ -static int exit_dbgr_mode(struct common_hnd *chnd) -{ - int ret = 0; - - printf("Exit DBGR mode...\n"); - if (chnd->dbgr_addr_3bytes) - ret |= i2c_write_byte(chnd, 0x80, 0xf0); - ret |= i2c_write_byte(chnd, 0x2f, 0x1c); - ret |= i2c_write_byte(chnd, 0x2e, 0x08); - ret |= i2c_write_byte(chnd, 0x30, BIT(4)); - - if (ret < 0) - fprintf(stderr, "EXIT DBGR MODE FAILED\n"); - - return 0; -} - -/* DBGR reset GPIOs to default */ -static int dbgr_reset_gpio(struct common_hnd *chnd) -{ - int ret = 0; - - printf("Reset GPIOs to default.\n"); - if (chnd->dbgr_addr_3bytes) - ret |= i2c_write_byte(chnd, 0x80, 0xf0); - ret |= i2c_write_byte(chnd, 0x2f, 0x20); - ret |= i2c_write_byte(chnd, 0x2e, 0x07); - ret |= i2c_write_byte(chnd, 0x30, BIT(1)); - - if (ret < 0) - fprintf(stderr, "DBGR RESET GPIO FAILED\n"); - - return 0; -} - -/* disable watchdog */ -static int dbgr_disable_watchdog(struct common_hnd *chnd) -{ - int ret = 0; - - printf("Disabling watchdog...\n"); - if (chnd->dbgr_addr_3bytes) - ret |= i2c_write_byte(chnd, 0x80, 0xf0); - - ret |= i2c_write_byte(chnd, 0x2f, 0x1f); - ret |= i2c_write_byte(chnd, 0x2e, 0x05); - ret |= i2c_write_byte(chnd, 0x30, 0x30); - - if (ret < 0) - fprintf(stderr, "DBGR DISABLE WATCHDOG FAILED!\n"); - - return ret; -} - -/* disable protect path from DBGR */ -static int dbgr_disable_protect_path(struct common_hnd *chnd) -{ - int ret = 0, i; - - printf("Disabling protect path...\n"); - - if (chnd->dbgr_addr_3bytes) - ret |= i2c_write_byte(chnd, 0x80, 0xf0); - - ret |= i2c_write_byte(chnd, 0x2f, 0x20); - for (i = 0; i < 32; i++) { - ret |= i2c_write_byte(chnd, 0x2e, 0xa0+i); - ret |= i2c_write_byte(chnd, 0x30, 0); - } - - if (ret < 0) - fprintf(stderr, "DISABLE PROTECT PATH FROM DBGR FAILED!\n"); - - return ret; -} - -/* Enter follow mode and FSCE# high level */ -static int spi_flash_follow_mode(struct common_hnd *chnd, char *desc) -{ - int ret = 0; - - ret |= i2c_write_byte(chnd, 0x07, 0x7f); - ret |= i2c_write_byte(chnd, 0x06, 0xff); - ret |= i2c_write_byte(chnd, 0x05, 0xfe); - ret |= i2c_write_byte(chnd, 0x04, 0x00); - ret |= i2c_write_byte(chnd, 0x08, 0x00); - - ret = (ret ? -EIO : 0); - if (ret < 0) - fprintf(stderr, "Flash %s enter follow mode FAILED (%d)\n", - desc, ret); - - return ret; -} - -/* Exit follow mode */ -static int spi_flash_follow_mode_exit(struct common_hnd *chnd, char *desc) -{ - int ret = 0; - - ret |= i2c_write_byte(chnd, 0x07, 0x00); - ret |= i2c_write_byte(chnd, 0x06, 0x00); - - ret = (ret ? -EIO : 0); - if (ret < 0) - fprintf(stderr, "Flash %s exit follow mode FAILED (%d)\n", - desc, ret); - - return ret; -} - -/* Stop EC by sending follow mode command */ -static int dbgr_stop_ec(struct common_hnd *chnd) -{ - int ret = 0; - - ret |= spi_flash_follow_mode(chnd, "enter follow mode"); - ret |= spi_flash_follow_mode_exit(chnd, "exit follow mode"); - - if (ret < 0) - fprintf(stderr, "DBGR STOP EC FAILED!\n"); - - return ret; -} - -/* SPI Flash generic command, short version */ -static int spi_flash_command_short(struct common_hnd *chnd, - uint8_t cmd, char *desc) -{ - int ret = 0; - - ret |= i2c_write_byte(chnd, 0x05, 0xfe); - ret |= i2c_write_byte(chnd, 0x08, 0x00); - ret |= i2c_write_byte(chnd, 0x05, 0xfd); - ret |= i2c_write_byte(chnd, 0x08, cmd); - - ret = (ret ? -EIO : 0); - if (ret < 0) - fprintf(stderr, "Flash CMD %s FAILED (%d)\n", desc, ret); - - return ret; -} - -/* SPI Flash set erase page */ -static int spi_flash_set_erase_page(struct common_hnd *chnd, - int page, char *desc) -{ - int ret = 0; - - ret |= i2c_write_byte(chnd, 0x08, page >> 8); - ret |= i2c_write_byte(chnd, 0x08, page & 0xff); - ret |= i2c_write_byte(chnd, 0x08, 0); - - ret = (ret ? -EIO : 0); - if (ret < 0) - fprintf(stderr, "Flash %s set page FAILED (%d)\n", desc, ret); - - return ret; -} - -/* Poll SPI Flash Read Status register until BUSY is reset */ -static int spi_poll_busy(struct common_hnd *chnd, char *desc) -{ - uint8_t reg = 0xff; - int ret = -EIO; - - if (spi_flash_command_short(chnd, SPI_CMD_READ_STATUS, - "read status for busy bit") < 0) { - fprintf(stderr, "Flash %s wait busy cleared FAILED\n", desc); - goto failed_read_status; - } - - while (1) { - if (i2c_byte_transfer(chnd, I2C_DATA_ADDR, ®, 0, 1) < 0) { - fprintf(stderr, "Flash polling busy cleared FAILED\n"); - break; - } - - if ((reg & 0x01) == 0) { - /* busy bit cleared */ - ret = 0; - break; - } - } -failed_read_status: - return ret; -} - -static int spi_check_write_enable(struct common_hnd *chnd, char *desc) -{ - uint8_t reg = 0xff; - int ret = -EIO; - - if (spi_flash_command_short(chnd, SPI_CMD_READ_STATUS, - "read status for write enable bit") < 0) { - fprintf(stderr, "Flash %s wait WE FAILED\n", desc); - goto failed_read_status; - } - - while (1) { - if (i2c_byte_transfer(chnd, I2C_DATA_ADDR, ®, 0, 1) < 0) { - fprintf(stderr, "Flash polling WE FAILED\n"); - break; - } - - if ((reg & 0x03) == 2) { - /* busy bit cleared and WE bit set */ - ret = 0; - break; - } - } -failed_read_status: - return ret; -} - -static int ftdi_config_i2c(struct ftdi_context *ftdi) -{ - int ret; - static const uint16_t divisor = - 60000000 / (2 * FTDI_I2C_FREQ * 3 / 2 /* 3-phase CLK */) - 1; - uint8_t clock_buf[] = { - EN_3_PHASE, - DIS_DIV_5, - TCK_DIVISOR, - divisor & 0xff, - divisor >> 8}; - - ret = ftdi_set_latency_timer(ftdi, 16 /* ms */); - if (ret < 0) - fprintf(stderr, "Cannot set latency\n"); - - ret = ftdi_set_bitmode(ftdi, 0, BITMODE_RESET); - if (ret < 0) { - fprintf(stderr, "Cannot reset MPSSE\n"); - return -EIO; - } - ret = ftdi_set_bitmode(ftdi, 0, BITMODE_MPSSE); - if (ret < 0) { - fprintf(stderr, "Cannot enable MPSSE\n"); - return -EIO; - } - - ret = ftdi_usb_purge_buffers(ftdi); - if (ret < 0) - fprintf(stderr, "Cannot purge buffers\n"); - - /* configure the clock */ - ret = ftdi_write_data(ftdi, clock_buf, sizeof(clock_buf)); - if (ret < 0) - return ret; - - return 0; -} - -/* Special waveform definition */ -#define SPECIAL_LEN_USEC 50000ULL /* us */ -#define SPECIAL_FREQ 400000ULL - -#define SPECIAL_PATTERN 0x0000020301010302ULL -#define SPECIAL_PATTERN_SDA_L_SCL_L 0x0000000000000000ULL -#define SPECIAL_PATTERN_SDA_H_SCL_L 0x0202020202020202ULL -#define SPECIAL_PATTERN_SDA_L_SCL_H 0x0101010101010101ULL -#define SPECIAL_PATTERN_SDA_H_SCL_H 0x0303030303030303ULL -#define TICK_COUNT 24 - -#define MSEC 1000 -#define USEC 1000000 - -#define SPECIAL_BUFFER_SIZE \ - (((SPECIAL_LEN_USEC * SPECIAL_FREQ * 2 / USEC) + 7) & ~7) - -static int connect_to_ccd_i2c_bridge(struct common_hnd *chnd) -{ - int rv; - - rv = usb_findit(chnd->conf.usb_serial, chnd->conf.usb_vid, - chnd->conf.usb_pid, CR50_I2C_SUBCLASS, - CR50_I2C_PROTOCOL, &chnd->uep); - - if (rv) { - fprintf(stderr, "%s: usb_findit returned error %d\n", - __func__, rv); - } - - return rv; -} - -static int ccd_trigger_special_waveform(struct common_hnd *chnd) -{ - uint8_t response[20]; - size_t rsize; - uint8_t req[] = { - 0, /* Port 0. Might be necessary to modify. */ - CROS_CMD_ADDR, /* Chrome OS dedicated address. */ - 1, /* Will send a single byte command. */ - 0, /* No need to read back anything. */ - CROS_CMD_ITE_SYNC - }; - - usb_trx(&chnd->uep, req, sizeof(req), response, sizeof(response), 1, - &rsize); - - if (rsize < USB_I2C_HEADER_SIZE) - return -1; - - if (response[0]) - return -response[0]; - /* - * The target is about to get reset, let's shut down the USB - * connection. - */ - usb_shut_down(&chnd->uep); - - sleep(3); - - return connect_to_ccd_i2c_bridge(chnd); -} - -static int ftdi_send_special_waveform(struct common_hnd *chnd) -{ - int ret; - int i; - uint64_t *wave; - struct ftdi_context *ftdi = chnd->ftdi_hnd; - uint8_t release_lines[] = {SET_BITS_LOW, 0, 0}; - - wave = malloc(SPECIAL_BUFFER_SIZE); - if (!wave) { - fprintf(stderr, "malloc(%zu) failed\n", - (size_t)SPECIAL_BUFFER_SIZE); - return -1; - } - - /* Reset the FTDI into a known state */ - ret = ftdi_set_bitmode(ftdi, 0xFF, BITMODE_RESET); - if (ret) { - fprintf(stderr, "failed to reset FTDI\n"); - goto free_and_return; - } - - /* - * set the clock divider, so we output a new bitbang value every - * 2.5us. - */ - ret = ftdi_set_baudrate(ftdi, 160000); - if (ret) { - fprintf(stderr, "failed to set bitbang clock\n"); - goto free_and_return; - } - - /* Enable asynchronous bit-bang mode */ - ret = ftdi_set_bitmode(ftdi, 0xFF, BITMODE_BITBANG); - if (ret) { - fprintf(stderr, "failed to set bitbang mode\n"); - goto free_and_return; - } - - /* do usb special waveform */ - wave[0] = 0x0; - ftdi_write_data(ftdi, (uint8_t *)wave, 1); - usleep(5000); - - /* program each special tick */ - for (i = 0; i < TICK_COUNT; ) { - wave[i++] = SPECIAL_PATTERN_SDA_L_SCL_L; - wave[i++] = SPECIAL_PATTERN_SDA_H_SCL_L; - wave[i++] = SPECIAL_PATTERN_SDA_L_SCL_L; - } - wave[19] = SPECIAL_PATTERN_SDA_H_SCL_H; - - /* fill the buffer with the waveform pattern */ - for (i = TICK_COUNT; i < SPECIAL_BUFFER_SIZE / sizeof(uint64_t); i++) - wave[i] = SPECIAL_PATTERN; - - ret = ftdi_write_data(ftdi, (uint8_t *)wave, SPECIAL_BUFFER_SIZE); - if (ret < 0) - fprintf(stderr, "Cannot output special waveform\n"); - else - /* no error */ - ret = 0; - - /* clean everything to go back to regular I2C communication */ - ftdi_usb_purge_buffers(ftdi); - ftdi_set_bitmode(ftdi, 0xff, BITMODE_RESET); - ftdi_config_i2c(ftdi); - ftdi_write_data(ftdi, release_lines, sizeof(release_lines)); - - free_and_return: - free(wave); - return ret; -} - -static int send_special_waveform(struct common_hnd *chnd) -{ - const int max_iterations = 10; - int ret; - int iterations; - - if (!chnd->conf.i2c_if->send_special_waveform) { - fprintf(stderr, "This binary does not support sending the ITE " - "special waveform with the chosen I2C interface.\n"); - return -1; - } - - iterations = 0; - - do { - ret = chnd->conf.i2c_if->send_special_waveform(chnd); - if (ret) - break; - - /* wait for PLL stable for 5ms (plus remaining USB transfers) */ - usleep(10 * MSEC); - - /* Stop EC ASAP after sending special waveform. */ - if (dbgr_stop_ec(chnd) >= 0) { - /* - * If we can talk to chip, then we can break the retry - * loop. - */ - ret = check_chipid(chnd); - } else { - ret = -1; - if (!(iterations % max_iterations)) - fprintf(stderr, "!please reset EC if flashing" - " sequence is not starting!\n"); - } - } while (ret && (iterations++ < max_iterations)); - - if (ret) - fprintf(stderr, "Failed to send special waveform!\n"); - else - printf("Done with sending special waveform.\n"); - - return ret; -} - -static int windex; -static const char wheel[] = {'|', '/', '-', '\\' }; -static void draw_spinner(uint32_t remaining, uint32_t size) -{ - int percent = (size - remaining)*100/size; - fprintf(stderr, "\r%c%3d%%", wheel[windex++], percent); - windex %= sizeof(wheel); -} - -/* Note: this function must be called in follow mode */ -static int spi_send_cmd_fast_read(struct common_hnd *chnd, uint32_t addr) -{ - int ret = 0; - uint8_t cmd = 0x9; - - /* Fast Read command */ - ret = spi_flash_command_short(chnd, SPI_CMD_FAST_READ, "fast read"); - /* Send address */ - ret |= i2c_write_byte(chnd, 0x08, ((addr >> 16) & 0xff)); /* addr_h */ - ret |= i2c_write_byte(chnd, 0x08, ((addr >> 8) & 0xff)); /* addr_m */ - ret |= i2c_write_byte(chnd, 0x08, (addr & 0xff)); /* addr_l */ - /* fake byte */ - ret |= i2c_write_byte(chnd, 0x08, 0x00); - /* use i2c block read command */ - ret |= i2c_byte_transfer(chnd, I2C_CMD_ADDR, &cmd, 1, 1); - if (ret < 0) - fprintf(stderr, "Send fast read command failed\n"); - - return ret; -} - -static int command_read_pages(struct common_hnd *chnd, uint32_t address, - uint32_t size, uint8_t *buffer) -{ - int res = -EIO; - uint32_t remaining = size; - int cnt; - - if (address & 0xFF) { - fprintf(stderr, "page read requested at non-page boundary: " - "0x%X\n", address); - return -EINVAL; - } - - if (spi_flash_follow_mode(chnd, "fast read") < 0) - goto failed_read; - - if (spi_send_cmd_fast_read(chnd, address) < 0) - goto failed_read; - - while (remaining) { - cnt = (remaining > PAGE_SIZE) ? PAGE_SIZE : remaining; - draw_spinner(remaining, size); - - /* read page data */ - res = i2c_byte_transfer(chnd, I2C_BLOCK_ADDR, buffer, 0, cnt); - if (res < 0) { - fprintf(stderr, "page data read failed\n"); - goto failed_read; - } - - address += cnt; - remaining -= cnt; - buffer += cnt; - - /* We need to resend fast read command at 256KB boundary. */ - if (!(address % 0x40000) && remaining) { - if (spi_send_cmd_fast_read(chnd, address) < 0) - goto failed_read; - } - } - /* No error so far */ - res = size; -failed_read: - if (spi_flash_follow_mode_exit(chnd, "fast read") < 0) - res = -EIO; - - return res; -} - -static bool is_empty_page(uint8_t *buffer, int size) -{ - int i; - - for (i = 0; i < size; i++) { - if (buffer[i] != 0xFF) - return false; - } - - return true; -} - -static int command_write_pages(struct common_hnd *chnd, uint32_t address, - uint32_t size, uint8_t *buffer) -{ - int res = -EIO; - int block_write_size = chnd->conf.block_write_size; - uint32_t remaining = size; - int cnt; - uint8_t addr_H, addr_M, addr_L; - uint8_t data; - - if (spi_flash_follow_mode(chnd, "AAI write") < 0) - goto failed_write; - - while (remaining) { - cnt = (remaining > block_write_size) ? - block_write_size : remaining; - addr_H = (address >> 16) & 0xFF; - addr_M = (address >> 8) & 0xFF; - addr_L = address & 0xFF; - - draw_spinner(remaining, size); - - /* Write enable */ - if (spi_flash_command_short(chnd, SPI_CMD_WRITE_ENABLE, - "write enable for AAI write") < 0) - goto failed_write; - - /* Check write enable bit */ - if (spi_check_write_enable(chnd, "AAI write") < 0) - goto failed_write; - - /* Setup write */ - if (spi_flash_command_short(chnd, SPI_CMD_WORD_PROGRAM, - "AAI write") < 0) - goto failed_write; - - /* Set eflash page address */ - res = i2c_byte_transfer(chnd, I2C_DATA_ADDR, &addr_H, 1, 1); - res |= i2c_byte_transfer(chnd, I2C_DATA_ADDR, &addr_M, 1, 1); - res |= i2c_byte_transfer(chnd, I2C_DATA_ADDR, &addr_L, 1, 1); - if (res < 0) { - fprintf(stderr, "Flash write set page FAILED (%d)\n", - res); - goto failed_write; - } - - /* Wait until not busy */ - if (spi_poll_busy(chnd, "AAI write") < 0) - goto failed_write; - - /* Write up to block_write_size data */ - res = i2c_write_byte(chnd, 0x10, 0x20); - res = i2c_byte_transfer(chnd, I2C_BLOCK_ADDR, buffer, 1, cnt); - buffer += cnt; - - if (res < 0) { - fprintf(stderr, "Flash data write failed\n"); - goto failed_write; - } - - data = 0xFF; - res = i2c_byte_transfer(chnd, I2C_DATA_ADDR, &data, 1, 1); - res |= i2c_write_byte(chnd, 0x10, 0x00); - if (res < 0) { - fprintf(stderr, "Flash end data write FAILED (%d)\n", - res); - goto failed_write; - } - - /* Write disable */ - if (spi_flash_command_short(chnd, SPI_CMD_WRITE_DISABLE, - "write disable for AAI write") < 0) - goto failed_write; - - /* Wait until available */ - if (spi_poll_busy(chnd, "write disable for AAI write") < 0) - goto failed_write; - - address += cnt; - remaining -= cnt; - } - draw_spinner(remaining, size); - /* No error so far */ - res = size; -failed_write: - if (spi_flash_command_short(chnd, SPI_CMD_WRITE_DISABLE, - "write disable exit AAI write") < 0) - res = -EIO; - - if (spi_flash_follow_mode_exit(chnd, "AAI write") < 0) - res = -EIO; - - return res; -} - -/* - * Test for spi page program command - */ -static int command_write_pages3(struct common_hnd *chnd, uint32_t address, - uint32_t size, uint8_t *buffer) -{ - int ret = 0; - uint8_t addr_H, addr_M, addr_L; - - /* SMB_SPI_Flash_Write_Enable */ - if (spi_flash_command_short(chnd, SPI_CMD_WRITE_ENABLE, - "SPI Command Write Enable") < 0) { - ret = -EIO; - goto failed_write; - } - - if (spi_flash_command_short(chnd, SPI_CMD_PAGE_PROGRAM, - "SPI_CMD_PAGE_PROGRAM") < 0) { - ret = -EIO; - goto failed_write; - } - - addr_H = (address >> 16) & 0xFF; - addr_M = (address >> 8) & 0xFF; - addr_L = address & 0xFF; - - ret = i2c_byte_transfer(chnd, I2C_DATA_ADDR, &addr_H, 1, 1); - ret |= i2c_byte_transfer(chnd, I2C_DATA_ADDR, &addr_M, 1, 1); - ret |= i2c_byte_transfer(chnd, I2C_DATA_ADDR, &addr_L, 1, 1); - ret |= i2c_byte_transfer(chnd, I2C_BLOCK_ADDR, buffer, 1, size); - if (ret < 0) - goto failed_write; - - /* Wait until not busy */ - if (spi_poll_busy(chnd, "Page Program") < 0) - ret = -EIO; - - /* No error so far */ -failed_write: - return ret; -} - - - -static int command_erase(struct common_hnd *chnd, uint32_t len, uint32_t off) -{ - int res = -EIO; - int page = 0; - uint32_t remaining = len; - - printf("Erasing chip...\n"); - - if (off != 0 || len != chnd->flash_size) { - fprintf(stderr, "Only full chip erase is supported\n"); - return -EINVAL; - } - - if (spi_flash_follow_mode(chnd, "erase") < 0) - goto failed_erase; - - while (remaining) { - draw_spinner(remaining, len); - - if (spi_flash_command_short(chnd, SPI_CMD_WRITE_ENABLE, - "write enable for erase") < 0) - goto failed_erase; - - if (spi_check_write_enable(chnd, "erase") < 0) - goto failed_erase; - - /* do chip erase */ - if (remaining == chnd->flash_size) { - if (spi_flash_command_short(chnd, SPI_CMD_CHIP_ERASE, - "chip erase") < 0) - goto failed_erase; - goto wait_busy_cleared; - } - - /* do sector erase */ - if (spi_flash_command_short(chnd, spi_cmd_sector_erase, - "sector erase") < 0) - goto failed_erase; - - if (spi_flash_set_erase_page(chnd, page, "sector erase") < 0) - goto failed_erase; - -wait_busy_cleared: - if (spi_poll_busy(chnd, "erase") < 0) - goto failed_erase; - - if (spi_flash_command_short(chnd, SPI_CMD_WRITE_DISABLE, - "write disable for erase") < 0) - goto failed_erase; - - if (remaining == chnd->flash_size) { - remaining = 0; - draw_spinner(remaining, len); - } else { - page += sector_erase_pages; - remaining -= sector_erase_pages * PAGE_SIZE; - } - } - - /* No error so far */ - printf("\n\rErasing Done.\n"); - res = 0; - -failed_erase: - if (spi_flash_command_short(chnd, SPI_CMD_WRITE_DISABLE, - "write disable exit erase") < 0) - res = -EIO; - - if (spi_flash_follow_mode_exit(chnd, "erase") < 0) - res = -EIO; - - return res; -} - -/* - * This function can Erase First Sector or Erase All Sector by reset value - * Some F/W will produce the H/W watchdog reset and it will happen - * reset issue while flash. - * Add such function to prevent the reset issue. - */ -static int command_erase2(struct common_hnd *chnd, uint32_t len, - uint32_t off, uint32_t reset) -{ - int res = -EIO; - int page = 0; - uint32_t remaining = len; - - /* - * TODOD(b/<>): - * Using sector erase instead of chip erase - * For some new chip , the chip erase may not work - * well on the original flow - */ - - printf("Erasing flash...erase size=%d\n", len); - - if (off != 0 || len != chnd->flash_size) { - fprintf(stderr, "Only full chip erase is supported\n"); - return -EINVAL; - } - - if (spi_flash_follow_mode(chnd, "erase") < 0) - goto failed_erase; - - while (remaining) { - - draw_spinner(remaining, len); - - if (spi_flash_command_short(chnd, SPI_CMD_WRITE_ENABLE, - "write enable for erase") < 0) - goto failed_erase; - - if (spi_check_write_enable(chnd, "erase") < 0) - goto failed_erase; - - /* do sector erase */ - if (spi_flash_command_short(chnd, spi_cmd_sector_erase, - "sector erase") < 0) - goto failed_erase; - - if (spi_flash_set_erase_page(chnd, page, "sector erase") < 0) - goto failed_erase; - - if (spi_poll_busy(chnd, "erase") < 0) - goto failed_erase; - - if (spi_flash_command_short(chnd, SPI_CMD_WRITE_DISABLE, - "write disable for erase") < 0) - goto failed_erase; - - if (reset) { - printf("\n\rreset to prevent the watchdog reset...\n"); - break; - } - - page += sector_erase_pages; - remaining -= sector_erase_pages * PAGE_SIZE; - draw_spinner(remaining, len); - - } - - /* No error so far */ - printf("\n\rErasing Done.\n"); - res = 0; - -failed_erase: - if (spi_flash_command_short(chnd, SPI_CMD_WRITE_DISABLE, - "write disable exit erase") < 0) - res = -EIO; - - if (spi_flash_follow_mode_exit(chnd, "erase") < 0) - res = -EIO; - - return res; -} - -/* Return zero on success, a negative error value on failures. */ -static int read_flash(struct common_hnd *chnd) -{ - int res; - FILE *hnd; - uint8_t *buffer; - const char *filename = chnd->conf.input_filename; - size_t offset = chnd->conf.range_base; - size_t size; - - if (!offset && !chnd->conf.range_size) { - size = chnd->flash_size; - } else { - /* - * Zero conf.range_size means the user did not enter range - * size in the command line. - */ - if (chnd->conf.range_size) - size = chnd->conf.range_size; - else - size = chnd->flash_size - offset; - - if (!size) { - fprintf(stderr, - "Error: not reading a zero sized range!\n"); - return -EINVAL; - } - - if ((size + offset) > chnd->flash_size) { - fprintf(stderr, - "Error: Read range exceeds flash size!\n"); - return -EINVAL; - } - } - - buffer = malloc(size); - if (!buffer) { - fprintf(stderr, "Cannot allocate %zd bytes\n", size); - return -ENOMEM; - } - - hnd = fopen(filename, "w"); - if (!hnd) { - fprintf(stderr, "Cannot open file %s for writing\n", filename); - free(buffer); - return -EIO; - } - - printf("Reading %zd bytes at %#08zx\n", size, offset); - res = command_read_pages(chnd, offset, size, buffer); - if (res > 0) { - if (fwrite(buffer, res, 1, hnd) != 1) - fprintf(stderr, "Cannot write %s\n", filename); - } - printf("\r %d bytes read.\n", res); - - fclose(hnd); - free(buffer); - return (res < 0) ? res : 0; -} - -/* Return zero on success, a negative error value on failures. */ -static int write_flash(struct common_hnd *chnd, const char *filename, - uint32_t offset) -{ - int res, written; - FILE *hnd; - int size = chnd->flash_size; - uint8_t *buffer = malloc(size); - - if (!buffer) { - fprintf(stderr, "%s: Cannot allocate %d bytes\n", __func__, - size); - return -ENOMEM; - } - - hnd = fopen(filename, "r"); - if (!hnd) { - fprintf(stderr, "%s: Cannot open file %s for reading\n", - __func__, filename); - free(buffer); - return -EIO; - } - res = fread(buffer, 1, size, hnd); - if (res <= 0) { - fprintf(stderr, "%s: Failed to read %d bytes from %s with " - "ferror() %d\n", __func__, size, filename, ferror(hnd)); - free(buffer); - fclose(hnd); - return -EIO; - } - fclose(hnd); - - printf("Writing %d bytes at 0x%08x\n", res, offset); - written = command_write_pages(chnd, offset, res, buffer); - if (written != res) { - fprintf(stderr, "%s: Error writing to flash\n", __func__); - free(buffer); - return -EIO; - } - printf("\n\rWriting Done.\n"); - - free(buffer); - return 0; -} - -/* - * Return zero on success, a negative error value on failures. - * - * Change the program command to match the ITE Download - * The original flow may not work on the DX chip. - * - */ -static int write_flash2(struct common_hnd *chnd, const char *filename, - uint32_t offset) -{ - int res; - int block_write_size = chnd->conf.block_write_size; - FILE *hnd; - int size = chnd->flash_size; - int cnt, two_bytes_sent, ret; - uint8_t addr_h, addr_m, addr_l, data_ff = 0xff; - uint8_t *buffer = malloc(size); - - if (!buffer) { - fprintf(stderr, "%s: Cannot allocate %d bytes\n", __func__, - size); - return -ENOMEM; - } - - hnd = fopen(filename, "r"); - if (!hnd) { - fprintf(stderr, "%s: Cannot open file %s for reading\n", - __func__, filename); - free(buffer); - return -EIO; - } - res = fread(buffer, 1, size, hnd); - if (res <= 0) { - fprintf(stderr, "%s: Failed to read %d bytes from %s with " - "ferror() %d\n", __func__, size, filename, ferror(hnd)); - fclose(hnd); - free(buffer); - return -EIO; - } - fclose(hnd); - - /* Enter follow mode */ - if (spi_flash_follow_mode(chnd, "AAI write") < 0) { - ret = -EIO; - goto failed_enter_mode; - } - - printf("Writing %d bytes at 0x%08x.......\n", res, offset); - -__send_aai_cmd: - addr_h = (offset >> 16) & 0xff; - addr_m = (offset >> 8) & 0xff; - addr_l = offset & 0xff; - - /* write enable command */ - ret = spi_flash_command_short(chnd, SPI_CMD_WRITE_ENABLE, "SPI WE"); - /* AAI command */ - ret |= spi_flash_command_short(chnd, SPI_CMD_WORD_PROGRAM, "SPI AAI"); - /* address of AAI command */ - ret |= i2c_byte_transfer(chnd, I2C_DATA_ADDR, &addr_h, 1, 1); - ret |= i2c_byte_transfer(chnd, I2C_DATA_ADDR, &addr_m, 1, 1); - ret |= i2c_byte_transfer(chnd, I2C_DATA_ADDR, &addr_l, 1, 1); - /* Send first two bytes of buffe */ - ret |= i2c_byte_transfer(chnd, I2C_DATA_ADDR, &buffer[offset], 1, 1); - ret |= i2c_byte_transfer(chnd, I2C_DATA_ADDR, &buffer[offset+1], 1, 1); - /* we had sent two bytes */ - offset += 2; - res -= 2; - two_bytes_sent = 1; - /* Wait until not busy */ - if (spi_poll_busy(chnd, "wait busy bit cleared at AAI write ") < 0) { - ret = -EIO; - goto failed_write; - } - /* enable quick AAI mode */ - ret |= i2c_write_byte(chnd, 0x10, 0x20); - if (ret < 0) - goto failed_write; - - while (res) { - cnt = (res > block_write_size) ? block_write_size : res; - /* we had sent two bytes */ - if (two_bytes_sent) { - two_bytes_sent = 0; - cnt -= 2; - } - if (i2c_byte_transfer(chnd, I2C_BLOCK_ADDR, &buffer[offset], - 1, cnt) < 0) { - ret = -EIO; - goto failed_write; - } - - res -= cnt; - offset += cnt; - draw_spinner(res, res + offset); - - /* We need to resend aai write command at 256KB boundary. */ - if (!(offset % 0x40000) && res) { - /* disable quick AAI mode */ - i2c_byte_transfer(chnd, I2C_DATA_ADDR, &data_ff, 1, 1); - i2c_write_byte(chnd, 0x10, 0x00); - /* write disable command */ - spi_flash_command_short(chnd, SPI_CMD_WRITE_DISABLE, - "SPI write disable"); - goto __send_aai_cmd; - } - } - -failed_write: - /* disable quick AAI mode */ - i2c_byte_transfer(chnd, I2C_DATA_ADDR, &data_ff, 1, 1); - i2c_write_byte(chnd, 0x10, 0x00); - /* write disable command */ - spi_flash_command_short(chnd, SPI_CMD_WRITE_DISABLE, - "SPI write disable"); -failed_enter_mode: - /* exit follow mode */ - spi_flash_follow_mode_exit(chnd, "AAI write"); - - if (ret < 0) - printf("\n\rWriting Failed.\n"); - else - printf("\n\rWriting Done.\n"); - - free(buffer); - - return ret; -} - -/* - * Return zero on success, a negative error value on failures. - * - * Change the program command to match the ITE Download - * The original flow may not work on the DX chip. - * - */ -static int write_flash3(struct common_hnd *chnd, const char *filename, - uint32_t offset) -{ - int res, ret = 0; - int block_write_size = chnd->conf.block_write_size; - FILE *hnd; - int size = chnd->flash_size; - int cnt; - uint8_t *buf = malloc(size); - - if (!buf) { - fprintf(stderr, "%s: Cannot allocate %d bytes\n", __func__, - size); - return -ENOMEM; - } - - hnd = fopen(filename, "r"); - if (!hnd) { - fprintf(stderr, "%s: Cannot open file %s for reading\n", - __func__, filename); - free(buf); - return -EIO; - } - res = fread(buf, 1, size, hnd); - if (res <= 0) { - fprintf(stderr, "%s: Failed to read %d bytes from %s with " - "ferror() %d\n", __func__, size, filename, ferror(hnd)); - fclose(hnd); - free(buf); - return -EIO; - } - fclose(hnd); - - printf("Writing %d bytes at 0x%08x.......\n", res, offset); - - /* Enter follow mode */ - ret = spi_flash_follow_mode(chnd, "Page program"); - if (ret < 0) - goto failed_write; - - /* Page program instruction allows up to 256 bytes */ - if (block_write_size > 256) - block_write_size = 256; - - while (res) { - cnt = (res > block_write_size) ? block_write_size : res; - if (chnd->conf.erase && is_empty_page(&buf[offset], cnt)) { - /* do nothing */ - } else if (command_write_pages3(chnd, offset, cnt, &buf[offset]) - < 0) { - ret = -EIO; - goto failed_write; - } - - res -= cnt; - offset += cnt; - draw_spinner(res, res + offset); - } - -failed_write: - free(buf); - spi_flash_command_short(chnd, SPI_CMD_WRITE_DISABLE, - "SPI write disable"); - spi_flash_follow_mode_exit(chnd, "Page program"); - if (ret < 0) - fprintf(stderr, "%s: Error writing to flash\n", __func__); - else - printf("\n\rWriting Done.\n"); - - return ret; -} - - - -/* Return zero on success, a non-zero value on failures. */ -static int verify_flash(struct common_hnd *chnd, const char *filename, - uint32_t offset) -{ - int res; - int file_size; - FILE *hnd; - uint8_t *buffer = malloc(chnd->flash_size); - uint8_t *buffer2 = malloc(chnd->flash_size); - - if (!buffer || !buffer2) { - fprintf(stderr, "%s: Cannot allocate %d bytes\n", __func__, - chnd->flash_size); - free(buffer); - free(buffer2); - return -ENOMEM; - } - - hnd = fopen(filename, "r"); - if (!hnd) { - fprintf(stderr, "%s: Cannot open file %s for reading\n", - __func__, filename); - res = -EIO; - goto exit; - } - - file_size = fread(buffer, 1, chnd->flash_size, hnd); - if (file_size <= 0) { - fprintf(stderr, "%s: Failed to read %d bytes from %s with " - "ferror() %d\n", __func__, chnd->flash_size, filename, - ferror(hnd)); - fclose(hnd); - res = -EIO; - goto exit; - } - fclose(hnd); - - printf("Verify %d bytes at 0x%08x\n", file_size, offset); - res = command_read_pages(chnd, offset, chnd->flash_size, buffer2); - if (res > 0) - res = memcmp(buffer, buffer2, file_size); - - printf("\n\rVerify %s\n", res ? "Failed!" : "Done."); - -exit: - free(buffer); - free(buffer2); - return res; -} - -static struct ftdi_context *open_ftdi_device(int vid, int pid, - int interface, const char *serial) -{ - struct ftdi_context *ftdi; - int ret; - - ftdi = ftdi_new(); - if (!ftdi) { - fprintf(stderr, "Cannot allocate context memory\n"); - return NULL; - } - - ret = ftdi_set_interface(ftdi, interface); - if (ret < 0) { - fprintf(stderr, "cannot set ftdi interface %d: %s(%d)\n", - interface, ftdi_get_error_string(ftdi), ret); - goto open_failed; - } - ret = ftdi_usb_open_desc(ftdi, vid, pid, NULL, serial); - if (ret < 0) { - fprintf(stderr, "unable to open ftdi device: %s(%d)\n", - ftdi_get_error_string(ftdi), ret); - goto open_failed; - } - return ftdi; - -open_failed: - ftdi_free(ftdi); - return NULL; -} - -static int linux_i2c_interface_init(struct common_hnd *chnd) -{ - int err; - - if (!chnd->conf.i2c_dev_path) { - fprintf(stderr, "Must set --i2c_dev_path when using " - "Linux i2c-dev interface.\n"); - return -1; - } - printf("Attempting to open Linux i2c-dev path %s\n", - chnd->conf.i2c_dev_path); - chnd->i2c_dev_fd = open(chnd->conf.i2c_dev_path, O_RDWR); - if (chnd->i2c_dev_fd < 0) { - err = errno; - perror("Failed to open Linux i2c-dev file path with error"); - fprintf(stderr, "Linux i2c-dev file path from --i2c_dev_path " - "is: %s\n", chnd->conf.i2c_dev_path); - return err ? err : -1; - } - printf("Successfully opened Linux i2c-dev path %s\n", - chnd->conf.i2c_dev_path); - return 0; -} - -static int linux_i2c_interface_shutdown(struct common_hnd *chnd) -{ - int err; - - printf("Attempting to close Linux i2c-dev file descriptor %d\n", - chnd->i2c_dev_fd); - if (close(chnd->i2c_dev_fd)) { - err = errno; - perror("Failed to close Linux i2c-dev file descriptor with " - "error"); - return err ? err : -1; - } - printf("Successfully closed Linux i2c-dev file descriptor %d\n", - chnd->i2c_dev_fd); - return 0; -} - -static int ccd_i2c_interface_init(struct common_hnd *chnd) -{ - chnd->conf.usb_vid = CR50_USB_VID; - chnd->conf.usb_pid = CR50_USB_PID; - return connect_to_ccd_i2c_bridge(chnd); -} - -static int ccd_i2c_interface_shutdown(struct common_hnd *chnd) -{ - usb_shut_down(&chnd->uep); - return 0; -} - -static int ftdi_i2c_interface_init(struct common_hnd *chnd) -{ - chnd->ftdi_hnd = open_ftdi_device(chnd->conf.usb_vid, - chnd->conf.usb_pid, chnd->conf.usb_interface, - chnd->conf.usb_serial); - if (chnd->ftdi_hnd == NULL) - return -1; - return 0; -} - -static int ftdi_i2c_interface_post_waveform(struct common_hnd *chnd) -{ - return chnd->conf.send_waveform ? 0 : ftdi_config_i2c(chnd->ftdi_hnd); -} - -/* Close the FTDI USB handle */ -static int ftdi_i2c_interface_shutdown(struct common_hnd *chnd) -{ - ftdi_usb_close(chnd->ftdi_hnd); - ftdi_free(chnd->ftdi_hnd); - return 0; -} - -static const struct i2c_interface linux_i2c_interface = { - .interface_init = linux_i2c_interface_init, - .interface_shutdown = linux_i2c_interface_shutdown, - .byte_transfer = linux_i2c_byte_transfer, - /* - * 254 bytes is the largest size that works with Servo Micro as of - * 2018-11-30. Odd numbers up to 255 result in corruption, and 256 or - * greater fails with a timeout from the I2C bus. Fixing that so this - * can be increased to match FTDI_BLOCK_WRITE_SIZE would be a useful - * speedup. - * - * 254 byte block sizes cause corruption with Ampton (using any kind of - * servo). 128 bytes is the largest block_write_size compatible with - * both Ampton and Servo Micro. - * - * See https://issuetracker.google.com/79684405 for background. - */ - .default_block_write_size = 128, -}; - -static const struct i2c_interface ccd_i2c_interface = { - .interface_init = ccd_i2c_interface_init, - .interface_shutdown = ccd_i2c_interface_shutdown, - .send_special_waveform = ccd_trigger_special_waveform, - .byte_transfer = ccd_i2c_byte_transfer, - .default_block_write_size = PAGE_SIZE, -}; - -static const struct i2c_interface ftdi_i2c_interface = { - .interface_init = ftdi_i2c_interface_init, - .interface_post_waveform = ftdi_i2c_interface_post_waveform, - .interface_shutdown = ftdi_i2c_interface_shutdown, - .send_special_waveform = ftdi_send_special_waveform, - .byte_transfer = ftdi_i2c_byte_transfer, - .default_block_write_size = FTDI_BLOCK_WRITE_SIZE, -}; - -static int post_waveform_work(struct common_hnd *chnd) -{ - int ret; - - if (chnd->conf.i2c_if->interface_post_waveform) { - ret = chnd->conf.i2c_if->interface_post_waveform(chnd); - if (ret) - return ret; - } - - if (chnd->conf.disable_watchdog) { - ret = dbgr_disable_watchdog(chnd); - if (ret) - return ret; - } - - if (chnd->conf.disable_protect_path) { - ret = dbgr_disable_protect_path(chnd); - if (ret) - return ret; - } - - return 0; -} - -static int strdup_with_errmsg(const char *source, char **dest, const char *name) -{ - int ret = 0; - *dest = strdup(source); - if (!(*dest)) { - ret = errno ? errno : -1; - fprintf(stderr, "strdup() of %zu size string from %s failed.\n", - strlen(source), name); - } - return ret; -} - -static const struct option longopts[] = { - {"block-write-size", 1, 0, 'b'}, - {"debug", 0, 0, 'd'}, - {"erase", 0, 0, 'e'}, - {"help", 0, 0, 'h'}, - {"i2c-dev-path", 1, 0, 'D'}, - {"i2c-interface", 1, 0, 'c'}, - {"i2c-mux", 0, 0, 'm'}, - {"interface", 1, 0, 'i'}, - {"nodisable-protect-path", 0, 0, 'Z'}, - {"nodisable-watchdog", 0, 0, 'z'}, - {"noverify", 0, 0, 'n'}, - {"product", 1, 0, 'p'}, - {"range", 1, 0, 'R'}, - {"read", 1, 0, 'r'}, - {"send-waveform", 1, 0, 'W'}, - {"serial", 1, 0, 's'}, - {"vendor", 1, 0, 'v'}, - {"write", 1, 0, 'w'}, - {NULL, 0, 0, 0} -}; - -static void display_usage(const char *program) -{ - fprintf(stderr, "Usage: %s [-d] [-v <VID>] [-p <PID>] \\\n" - "\t[-c <linux|ccd|ftdi>] [-D /dev/i2c-<N>] [-i <1|2>] [-S] \\\n" - "\t[-s <serial>] [-e] [-r <file>] [-W <0|1|false|true>] \\\n" - "\t[-w <file>] [-R base[:size]] [-m] [-b <size>]\n", - program); - fprintf(stderr, "-d, --debug : Output debug traces.\n"); - fprintf(stderr, "-e, --erase : Erase all the flash content.\n"); - fprintf(stderr, "-c, --i2c-interface <linux|ccd|ftdi> : I2C interface " - "to use\n"); - fprintf(stderr, "-D, --i2c-dev-path /dev/i2c-<N> : Path to " - "Linux i2c-dev file e.g. /dev/i2c-5;\n" - "\tonly applicable with --i2c-interface=linux\n"); - fprintf(stderr, "-i, --interface <1> : FTDI interface: A=1, B=2," - " ...\n"); - fprintf(stderr, "-m, --i2c-mux : Enable i2c-mux (to EC).\n" - "\tSpecify this flag only if the board has an I2C MUX and\n" - "\tyou are not using servod.\n"); - fprintf(stderr, "-n, --noverify : Don't auto verify.\n"); - fprintf(stderr, "-b, --block-write-size <size> : Perform writes in\n" - "\tblocks of this many bytes.\n"); - fprintf(stderr, "-p, --product <0x1234> : USB product ID\n"); - fprintf(stderr, "-R, --range base[:size] : Allow to read or write" - " just a slice\n" - "\tof the file, starting at <base>:<size> bytes, or til\n" - "\tthe end of the file if <size> is not specified, expressed\n" - "\tin hex.\n"); - fprintf(stderr, "-r, --read <file> : Read the flash content and" - " write it into <file>.\n"); - fprintf(stderr, "-s, --serial <serialname> : USB serial string\n"); - fprintf(stderr, "-v, --vendor <0x1234> : USB vendor ID\n"); - fprintf(stderr, "-W, --send-waveform <0|1|false|true> : Send the" - " special waveform.\n" - "\tDefault is true. Set to false if ITE direct firmware\n" - "\tupdate mode has already been enabled.\n"); - fprintf(stderr, "-w, --write <file> : Write <file> to flash.\n"); - fprintf(stderr, "-z, --nodisable-watchdog : Do *not* disable EC " - "watchdog.\n"); - fprintf(stderr, "-Z, --nodisable-protect-path : Do *not* disable EC " - "protect path.\n"); -} - -/* - * Parses -R command line option parameter, returns zero on success and - * -1 on errors (non hex values, missing values, etc.). - */ -static int parse_range_options(char *str, struct iteflash_config *conf) -{ - char *size; - - if (!str) { - fprintf(stderr, "missing range base address specification\n"); - return -1; - } - - conf->range_base = strtoull(str, &size, 16); - if (!size || !*size) - return 0; - - if (*size++ != ':') { - fprintf(stderr, "wrong range base address specification\n"); - return -1; - } - - if (!*size) { - fprintf(stderr, "missing range size specification\n"); - return -1; - } - - conf->range_size = strtoull(size, &size, 16); - if ((size && *size) || !conf->range_size) { - fprintf(stderr, "wrong range size specification\n"); - return -1; - } - - return 0; -} - -static int parse_parameters(int argc, char **argv, struct iteflash_config *conf) -{ - int opt, idx, ret = 0; - - while (!ret && - (opt = getopt_long(argc, argv, "?b:c:D:dehi:mp:R:r:s:uv:W:w:Zz", - longopts, &idx)) != -1) { - switch (opt) { - case 'b': - conf->block_write_size = strtol(optarg, NULL, 10); - break; - case 'c': - if (!strcasecmp(optarg, "linux")) { - conf->i2c_if = &linux_i2c_interface; - } else if (!strcasecmp(optarg, "ccd")) { - conf->i2c_if = &ccd_i2c_interface; - } else if (!strcasecmp(optarg, "ftdi")) { - conf->i2c_if = &ftdi_i2c_interface; - } else { - fprintf(stderr, "Unexpected -c / " - "--i2c-interface value: %s\n", optarg); - ret = -1; - } - break; - case 'D': - ret = strdup_with_errmsg(optarg, &conf->i2c_dev_path, - "-D / --i2c-dev-path"); - break; - case 'd': - conf->debug = 1; - break; - case 'e': - conf->erase = 1; - break; - case 'h': - case '?': - display_usage(argv[0]); - ret = 2; - break; - case 'i': - conf->usb_interface = strtol(optarg, NULL, 10); - break; - case 'm': - conf->i2c_mux = 1; - break; - case 'n': - conf->verify = 0; - break; - case 'p': - conf->usb_pid = strtol(optarg, NULL, 16); - break; - case 'R': - ret = parse_range_options(optarg, conf); - break; - case 'r': - ret = strdup_with_errmsg(optarg, &conf->input_filename, - "-r / --read"); - break; - case 's': - ret = strdup_with_errmsg(optarg, &conf->usb_serial, - "-s / --serial"); - break; - case 'v': - conf->usb_vid = strtol(optarg, NULL, 16); - break; - case 'W': - if (!strcmp(optarg, "0") || - !strcasecmp(optarg, "false")) { - conf->send_waveform = 0; - break; - } - if (!strcmp(optarg, "1") || - !strcasecmp(optarg, "true")) { - conf->send_waveform = 1; - break; - } - fprintf(stderr, "Unexpected -W / --special-waveform " - "value: %s\n", optarg); - ret = -1; - break; - case 'w': - ret = strdup_with_errmsg(optarg, &conf->output_filename, - "-w / --write"); - break; - case 'z': - conf->disable_watchdog = 0; - break; - case 'Z': - conf->disable_protect_path = 0; - break; - } - } - - if (ret) - config_release(conf); - return ret; -} - -static void sighandler(int signum) -{ - int status; - printf("\nCaught signal %d: %s\nExiting...\n", - signum, strsignal(signum)); - wait(&status); - exit_requested = status; -} - -static void register_sigaction(void) -{ - struct sigaction sigact; - - memset(&sigact, 0, sizeof(sigact)); - sigact.sa_handler = sighandler; - sigemptyset(&sigact.sa_mask); - sigact.sa_flags = 0; - sigaction(SIGINT, &sigact, NULL); - sigaction(SIGTERM, &sigact, NULL); - sigaction(SIGQUIT, &sigact, NULL); -} - -int main(int argc, char **argv) -{ - int ret = 1, other_ret; - struct common_hnd chnd = { - /* Default flag settings. */ - .conf = { - .send_waveform = 1, - .disable_watchdog = 1, - .disable_protect_path = 1, - .usb_interface = SERVO_INTERFACE, - .usb_vid = SERVO_USB_VID, - .usb_pid = SERVO_USB_PID, - .verify = 1, - .i2c_if = &ftdi_i2c_interface, - }, - }; - - /* Parse command line options */ - other_ret = parse_parameters(argc, argv, &chnd.conf); - if (other_ret) - return other_ret; - - /* Fill in block_write_size if not set from command line. */ - if (!chnd.conf.block_write_size) - chnd.conf.block_write_size = - chnd.conf.i2c_if->default_block_write_size; - - /* Open the communications channel. */ - if (chnd.conf.i2c_if->interface_init && - chnd.conf.i2c_if->interface_init(&chnd)) - goto return_after_parse; - - /* Register signal handler after opening the communications channel. */ - register_sigaction(); - - if (chnd.conf.i2c_mux) { - printf("configuring I2C MUX to EC.\n"); - - if (config_i2c_mux(&chnd, I2C_MUX_CMD_EC)) - goto return_after_init; - } - - /* Trigger embedded monitor detection */ - if (chnd.conf.send_waveform) { - if (send_special_waveform(&chnd)) - goto return_after_init; - } else { - /* Stop EC ASAP after sending special waveform. */ - dbgr_stop_ec(&chnd); - - ret = check_chipid(&chnd); - if (ret) { - fprintf(stderr, "Failed to get ITE chip ID. This " - "could be because the ITE direct firmware " - "update (DFU) mode is not enabled.\n"); - goto return_after_init; - } - } - - /* Turn off power rails by reset GPIOs to default (input). */ - dbgr_reset_gpio(&chnd); - - check_flashid(&chnd); - - ret = post_waveform_work(&chnd); - if (ret) - goto return_after_init; - - if (chnd.conf.input_filename) { - ret = read_flash(&chnd); - if (ret) - goto return_after_init; - } - - switch (eflash_type) { - case EFLASH_TYPE_8315: - sector_erase_pages = 4; - spi_cmd_sector_erase = SPI_CMD_SECTOR_ERASE_1K; - break; - case EFLASH_TYPE_KGD: - sector_erase_pages = 16; - spi_cmd_sector_erase = SPI_CMD_SECTOR_ERASE_4K; - break; - default: - printf("Invalid EFLASH TYPE!"); - ret = -EINVAL; - break; - } - - if (ret) - goto return_after_init; - - if (chnd.conf.erase) { - if (chnd.flash_cmd_v2) - /* Do Normal Erase Function */ - command_erase2(&chnd, chnd.flash_size, 0, 0); - else - command_erase(&chnd, chnd.flash_size, 0); - /* Call DBGR Rest to clear the EC lock status after erasing */ - dbgr_reset(&chnd, RSTS_VCCDO_PW_ON|RSTS_HGRST|RSTS_GRST); - } - - if (chnd.conf.output_filename) { - if (chnd.flash_cmd_v2) - switch (eflash_type) { - case EFLASH_TYPE_8315: - ret = write_flash2(&chnd, - chnd.conf.output_filename, 0); - break; - case EFLASH_TYPE_KGD: - ret = write_flash3(&chnd, - chnd.conf.output_filename, 0); - break; - default: - printf("Invalid EFLASH TYPE!"); - ret = -EINVAL; - break; - } - else - ret = write_flash(&chnd, chnd.conf.output_filename, 0); - if (ret) - goto return_after_init; - if (chnd.conf.verify) { - ret = verify_flash(&chnd, chnd.conf.output_filename, 0); - if (ret) - goto return_after_init; - } - } - - /* Normal exit */ - ret = 0; - - return_after_init: - /* - * Exit DBGR mode. This ensures EC won't hold clock/data pins of I2C. - * Avoid resetting EC here because flash_ec will after iteflash exits. - * This avoids double reset after flash sequence. - */ - exit_dbgr_mode(&chnd); - - if (chnd.conf.i2c_mux) { - printf("configuring I2C MUX to none.\n"); - config_i2c_mux(&chnd, I2C_MUX_CMD_NONE); - } - - if (chnd.conf.i2c_if->interface_shutdown) { - other_ret = chnd.conf.i2c_if->interface_shutdown(&chnd); - if (!ret && other_ret) - ret = other_ret; - } - - return_after_parse: - config_release(&chnd.conf); - return ret; -} diff --git a/util/iteflash.md b/util/iteflash.md deleted file mode 100644 index 4d0db0fcc6..0000000000 --- a/util/iteflash.md +++ /dev/null @@ -1,167 +0,0 @@ -# Reflashing an ITE EC - -This doc: [http://go/cros-ite-ec-reflash](https://goto.google.com/cros-ite-ec-reflash) -<br> -First written: 2019-04-02 -<br> -Last updated: 2019-04-03 - -Familiarity with [Chromium OS](https://www.chromium.org/chromium-os) -[Embedded Controller (EC) development](../README.md) is assumed. - -[TOC] - -## Background - -### Terminology - -**ITE EC** refers to the [ITE](http://www.ite.com.tw/) -[IT8320](http://www.ite.com.tw/en/product/view?mid=96) -[Embedded Controller (EC)](https://en.wikipedia.org/wiki/Embedded_controller) -microcontroller when used as a Chromium OS / Chrome OS EC. - -**CrOS** refers to Chromium OS, Chrome OS, or both, depending on the context. -The distinction between Chromium OS and Chrome OS is largely immaterial to this -document. - -**Servo** refers to a debug board providing direct debug access to various -circuits on a Chrome OS device motherboard. As of this writing, the most common -[servos](https://www.chromium.org/chromium-os/servo) used by CrOS developers are -[CR50 (CCD)](https://www.chromium.org/chromium-os/ccd), -[Servo Micro](https://www.chromium.org/chromium-os/servo/servomicro), and -[Servo v2](https://www.chromium.org/chromium-os/servo/servo-v2). (Note that -[Servo v4](https://www.chromium.org/chromium-os/servo/servov4) is **not** a -Servo in this sense. It is a USB hub with a microcontroller that proxies Servo -functionality from either CR50 or Servo Micro.) See also -[Case-Closed Debug in Chromebooks and Servo Micro](https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/board/servo_micro/ccd.md). - -### How ITE EC reflashing works - -An ITE EC is reflashed using a Servo by: - -1. Sending special non-I2C waveforms over its I2C clock and data lines, to - enable a debug mode / direct firmware update (DFU) mode. - -1. Communicating with it using I2C, including transferring the actual EC image - over I2C.  The ITE EC will only respond over I2C after receiving the special - waveforms. - -### Further reading - -Googlers, and Partners involved in ITE EC projects, see -[The State of ITE CrOS EC Reflashing](https://docs.google.com/document/d/1fs29eBvwKrOWYozLZXTg7ObwAO5dyM4Js2Vq301EwAU/preview). -That document is not public, do not request access if you lack it. - -## How to reflash - -### Prerequisites for CR50 CCD - -This section applies whether using CR50 CCD via -[Servo v4](https://www.chromium.org/chromium-os/servo/servov4) or -[SuzyQ aka SuzyQable](https://www.sparkfun.com/products/14746). - -CR50 MP minimum firmware version: `0.3.15` -<br> -CR50 pre-PVT minimum firmware version: `0.4.15` - -Googlers, to upgrade CR50 firmware if needed see -[How to use CCD on CR50](https://docs.google.com/document/d/1MqDAoBsmGTmrFi-WNOoC5R-UFeuQK37_9kaEdCFU8QE/preview). -That document is not public, do not request access if you lack it. - -The CR50 CCD capabilities must be set to `always`. To achieve this: - -1. Open CCD. - * root shell: `$ gsctool -o` - * CR50 console: `ccd open` -1. Reset CCD to `factory` mode. - * CR50 console: `ccd reset factory` - -Reflashing with CR50 also requires the [i2c-pseudo kernel module](#i2c-pseudo), -unless using the [CR50 CCD sans servod](#ccd-sans-servod) alternative method. - -### Prerequisites for Servo Micro - -This section applies whether the -[Servo Micro](https://www.chromium.org/chromium-os/servo/servomicro) is -connected directly to your development host, or through a -[Servo v4](https://www.chromium.org/chromium-os/servo/servov4). - -Servo Micro minimum firmware version: `servo_micro_v2.3.5` - -To upgrade Servo Micro firmware if needed: - -1. Enter the chroot. - * `$ cros_sdk` -1. Run servo_updater. - * `$ sudo servo_updater --board=servo_micro` - -If that still results in too old of a firmware version, use `repo sync` and -`update_chroot` to update your CrOS development environment, then try again. - -Reflashing with Servo Micro also requires the -[i2c-pseudo kernel module](#i2c-pseudo). - -### Installing i2c-pseudo {#i2c-pseudo} - -1. Install the `i2c-pseudo` Linux kernel module. (Do this **outside** of the - chroot!) - * `$ cd src/platform/ec/extra/i2c_pseudo` - * `$ ./install` - -If the above fails, your system may be missing packages necessary for building -kernel modules. Consult your Linux distribution's documentation and support -forums. After installing any packages that might be missing, simply try the -install script again. - -You will need to reinstall `i2c-pseudo` after each kernel upgrade. - -There is an intention to -[upstream i2c-pseudo](https://issuetracker.google.com/129565355), though even if -accepted upstream, it may or may not become included with common Linux -distribution kernels. - -### Common reflash instructions - -These instructions apply when using any kind of Servo, including those with no -special prerequisites (such as -[Servo v2](https://www.chromium.org/chromium-os/servo/servo-v2) with its Yoshi -flex cable connected to the DUT). - -1. Enter the chroot (for servod). - * `$ cros_sdk --no-ns-pid` -1. Start servod. - * `$ sudo servod --board=<servod_board_name>` - * For some boards the servod board name is different than the EC codebase - board name used below! -1. Enter the chroot (for flash_ec). - * `$ cros_sdk` -1. Build the EC image for your board. - * `$ cd ~/trunk/src/platform/ec` - * `$ board=<board_name>` - * `$ make -j BOARD="$board"` -1. Run flash_ec from the util directory. - * `$ util/flash_ec --board="$board" --image=build/"$board"/ec.bin` - -## CR50 CCD sans servod alternative {#ccd-sans-servod} - -This section applies whether using CR50 CCD via -[Servo v4](https://www.chromium.org/chromium-os/servo/servov4) or -[SuzyQ aka SuzyQable](https://www.sparkfun.com/products/14746). - -When using CR50 CCD, it is possible to reflash without servod, which _must not_ -be running when using this method. - -1. Enter the chroot. - * `$ cros_sdk` -1. Build the EC image for your board. - * `$ cd ~/trunk/src/platform/ec` - * `$ board=<board_name>` - * `$ make -j BOARD="$board"` -1. Run iteflash from the build/\<board\>/util directory. - * `$ build/"$board"/util/iteflash --i2c-interface=ccd --i2c-mux - --send-waveform=1 --erase --write=build/"$board"/ec.bin` - -WARNING: The `--i2c-mux` flag is only required for some ITE EC boards. For -boards without an I2C mux between CR50 and the EC, that flag _must not_ be -specified. (This is handled for you when using `flash_ec` + `servod` because the -latter has knowledge of which boards are expected to have the I2C mux.) diff --git a/util/kconfig_check.py b/util/kconfig_check.py deleted file mode 100755 index b6b9fda8de..0000000000 --- a/util/kconfig_check.py +++ /dev/null @@ -1,209 +0,0 @@ -#!/usr/bin/env python3 -# Copyright 2021 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. -"""Kconfig checker - -Checks that the .config file provided does not introduce any new ad-hoc CONFIG -options -""" - -import argparse -import os -import re -import sys - - -def parse_args(argv): - """Parse the program arguments - - Args: - argv: List of arguments to parse, excluding the program name - - Returns: - argparse.Namespace object containing the results - """ - epilog = """Checks that new ad-hoc CONFIG options are not introduced without -a corresponding Kconfig option for Zephyr""" - - parser = argparse.ArgumentParser(epilog=epilog) - parser.add_argument('-a', '--allowed', type=str, - default='util/config_allowed.txt', - help='File containing list of allowed ad-hoc CONFIGs') - parser.add_argument('-c', '--configs', type=str, default='.config', - help='File containing CONFIG options to check') - parser.add_argument( - '-D', '--debug', action='store_true', - help='Enabling debugging (provides a full traceback on error)') - parser.add_argument('-p', '--prefix', type=str, default='PLATFORM_EC_', - help='Prefix to string from Kconfig options') - parser.add_argument('-s', '--srctree', type=str, default='.', - help='Path to source tree to look for Kconfigs') - - subparsers = parser.add_subparsers(dest='cmd', required=True) - subparsers.add_parser('check', help='Check for new ad-hoc CONFIGs') - - return parser.parse_args(argv) - - -class KconfigCheck: - """Class for handling checking of CONFIG options against Kconfig options - - The goal is to make sure that CONFIG_xxx options used by a build have an - equivalent Kconfig option defined as well. - - For example if a Kconfig file has: - - config PREFIX_MY_CONFIG - ... - - and the CONFIG files has - - CONFIG_MY_CONFIG - - then we consider these equivalent (with the prefix 'PREFIX_') and thus - CONFIG_MY_CONFIG is allowed to be used. - - If any CONFIG option is found that does not have an equivalent in the Kconfig, - the user is exhorted to add a new Kconfig. This helps avoid adding new ad-hoc - CONFIG options, eventually returning the number to zero. - """ - @classmethod - def find_new_adhoc(cls, configs, kconfigs, allowed): - """Get a list of new ad-hoc CONFIG options - - Arguments and return value should omit the 'CONFIG_' prefix, so - CONFIG_LTO should be provided as 'LTO'. - - Args: - configs: List of existing CONFIG options - kconfigs: List of existing Kconfig options - allowed: List of allowed CONFIG options - - Returns: - List of new CONFIG options, with the CONFIG_ prefix removed - """ - return sorted(list(set(configs) - set(kconfigs) - set(allowed))) - - @classmethod - def read_configs(cls, configs_file): - """Read CONFIG options from a file - - Args: - configs_file: Filename to read from - - Returns: - List of CONFIG_xxx options found in the file, with the 'CONFIG_' - prefixremoved - """ - with open(configs_file, 'r') as inf: - configs = re.findall('CONFIG_([A-Za-z0-9_]*)', inf.read()) - return configs - - @classmethod - def find_kconfigs(cls, srcdir): - """Find all the Kconfig files in a source directory, recursively - - Any subdirectory called 'Kconfig' is ignored, since Zephyr generates - this in its build directory. - - Args: - srcdir: Directory to scan - - Returns: - List of pathnames found - """ - kconfig_files = [] - for root, dirs, files in os.walk(srcdir): - kconfig_files += [os.path.join(root, fname) - for fname in files if fname.startswith('Kconfig')] - if 'Kconfig' in dirs: - dirs.remove('Kconfig') - return kconfig_files - - def scan_kconfigs(self, srcdir, prefix=''): - """Scan a source tree for Kconfig options - - Args: - srcdir: Directory to scan - prefix: Prefix to strip from the name (e.g. 'PLATFORM_EC_') - - Returns: - List of config and menuconfig options found, - """ - kconfigs = [] - - # Remove the prefix if present - expr = re.compile(r'(config|menuconfig) (%s)?([A-Za-z0-9_]*)\n' % - prefix) - for fname in self.find_kconfigs(srcdir): - with open(fname) as inf: - found = re.findall(expr, inf.read()) - kconfigs += [name for kctype, _, name in found] - return kconfigs - - def find_new_adhoc_configs(self, configs_file, srcdir, allowed_file, - prefix=''): - """Find new ad-hoc configs in the configs_file - - Args: - configs_file: Filename containing CONFIG options to check - srcdir: Source directory to scan for Kconfig files - allowed_file: File containing allowed CONFIG options - prefix: Prefix to strip from the start of each Kconfig - (e.g. 'PLATFORM_EC_') - """ - configs = self.read_configs(configs_file) - kconfigs = self.scan_kconfigs(srcdir, prefix) - allowed = self.read_configs(allowed_file) - new_adhoc = self.find_new_adhoc(configs, kconfigs, allowed) - return new_adhoc - - def do_check(self, configs_file, srcdir, allowed_file, prefix): - """Find new ad-hoc configs in the configs_file - - Args: - configs_file: Filename containing CONFIG options to check - srcdir: Source directory to scan for Kconfig files - allowed_file: File containing allowed CONFIG options - prefix: Prefix to strip from the start of each Kconfig - (e.g. 'PLATFORM_EC_') - - Returns: - Exit code: 0 if OK, 1 if a problem was found - """ - new_adhoc = self.find_new_adhoc_configs(configs_file, srcdir, - allowed_file, prefix) - if new_adhoc: - print("""Error:\tThe EC is in the process of migrating to Zephyr. -\tZephyr uses Kconfig for configuration rather than ad-hoc #defines. -\tAny new EC CONFIG options must ALSO be added to Zephyr so that new -\tfunctionality is available in Zephyr also. The following new ad-hoc -\tCONFIG options were detected: - -%s - -Please add these via Kconfig instead. Find a suitable Kconfig -file in zephyr/ and add a 'config' or 'menuconfig' option. -Also see details in http://issuetracker.google.com/181253613 - -To temporarily disable this, use: ALLOW_CONFIG=1 make ... -""" % '\n'.join(['CONFIG_%s' % name for name in new_adhoc]), file=sys.stderr) - return 1 - return 0 - - -def main(argv): - """Main function""" - args = parse_args(argv) - if not args.debug: - sys.tracebacklimit = 0 - checker = KconfigCheck() - if args.cmd == 'check': - return checker.do_check(args.configs, args.srctree, args.allowed, - args.prefix) - return 2 - - -if __name__ == '__main__': - sys.exit(main(sys.argv[1:])) diff --git a/util/keeby-relevant-paths.txt b/util/keeby-relevant-paths.txt deleted file mode 120000 index 9b63ef59c7..0000000000 --- a/util/keeby-relevant-paths.txt +++ /dev/null @@ -1 +0,0 @@ -dedede-relevant-paths.txt
\ No newline at end of file diff --git a/util/lbcc.c b/util/lbcc.c deleted file mode 100644 index 4a3633153e..0000000000 --- a/util/lbcc.c +++ /dev/null @@ -1,691 +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 <errno.h> -#include <stdarg.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#include "compile_time_macros.h" -#include "ec_commands.h" -#include "lb_common.h" -#include "lightbar.h" - -static const char usage[] = - "\n" - "Usage: %s [OPTIONS] [INFILE [OUTFILE]]\n" - "\n" - "This compiles or decompiles the lightbar programmable bytecode.\n" - "\n" - "Options:\n" - " -d Decode binary to ascii\n" - " -v Decode output should be verbose\n" - "\n"; - -/* globals */ -static int hit_errors; -static int opt_verbose; -static int is_jump_target[EC_LB_PROG_LEN]; /* does program jump here? */ -static int is_instruction[EC_LB_PROG_LEN]; /* instruction or operand? */ -static char *label[EC_LB_PROG_LEN]; /* labels we've seen */ -static char *reloc_label[EC_LB_PROG_LEN]; /* put label target here */ - -static void Error(const char *format, ...) -{ - va_list ap; - va_start(ap, format); - fprintf(stderr, "ERROR: "); - vfprintf(stderr, format, ap); - va_end(ap); - hit_errors++; -} - -static void Warning(const char *format, ...) -{ - va_list ap; - va_start(ap, format); - fprintf(stderr, "Warning: "); - vfprintf(stderr, format, ap); - va_end(ap); -} - -/* The longest line should have a label, an opcode, and the max operands */ -#define LB_PROG_MAX_OPERANDS 4 -#define MAX_WORDS (2 + LB_PROG_MAX_OPERANDS) - -struct safe_lightbar_program { - struct lightbar_program p; - uint8_t zeros[LB_PROG_MAX_OPERANDS]; -} __packed; - -#define OP(NAME, BYTES, MNEMONIC) NAME, -#include "lightbar_opcode_list.h" -enum lightbyte_opcode { - LIGHTBAR_OPCODE_TABLE - MAX_OPCODE -}; -#undef OP - -#define OP(NAME, BYTES, MNEMONIC) BYTES, -#include "lightbar_opcode_list.h" -static const int num_operands[] = { - LIGHTBAR_OPCODE_TABLE -}; -#undef OP - -#define OP(NAME, BYTES, MNEMONIC) MNEMONIC, -#include "lightbar_opcode_list.h" -static const char * const opcode_sym[] = { - LIGHTBAR_OPCODE_TABLE -}; -#undef OP - -static const char * const control_sym[] = { - "beg", "end", "phase", "<invalid>" -}; -static const char * const color_sym[] = { - "r", "g", "b", "<invalid>" -}; - -static void read_binary(FILE *fp, struct safe_lightbar_program *prog) -{ - int got; - - memset(prog, 0, sizeof(*prog)); - - /* Read up to one more byte than we need, so we know if it's too big */ - got = fread(prog->p.data, 1, EC_LB_PROG_LEN + 1, fp); - if (got < 1) { - Error("Unable to read any input: "); - if (feof(fp)) - fprintf(stderr, "EOF\n"); - else if (ferror(fp)) - fprintf(stderr, "%s\n", strerror(errno)); - else - fprintf(stderr, "no idea why.\n"); - } else if (got > EC_LB_PROG_LEN) { - Warning("Truncating input at %d bytes\n", EC_LB_PROG_LEN); - prog->zeros[0] = 0; - got = EC_LB_PROG_LEN; - } else { - prog->p.size = got; - } -} - -static uint32_t val32(uint8_t *ptr) -{ - uint32_t val; - val = (ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | ptr[3]; - return val; -} - -static int is_jump(uint8_t op) -{ - /* TODO: probably should be a field in the opcode list */ - return op >= JUMP && op <= JUMP_IF_CHARGING; -} - -static void print_led_set(FILE *fp, uint8_t led) -{ - int i, first = 1; - - fprintf(fp, "{"); - for (i = 0; i < NUM_LEDS; i++) - if (led & BIT(i)) { - if (!first) - fprintf(fp, ","); - fprintf(fp, "%d", i); - first = 0; - } - fprintf(fp, "}"); -} - -/* returns number of operands consumed */ -static int print_op(FILE *fp, uint8_t addr, uint8_t cmd, uint8_t *arg) -{ - uint8_t led, color, control; - int i, operands; - - operands = num_operands[cmd]; - - /* assume valid instruction for now */ - is_instruction[addr] = 1; - - if (opt_verbose) { - fprintf(fp, "%02x: %02x", addr, cmd); - for (i = 0; i < LB_PROG_MAX_OPERANDS; i++) - if (i < operands) - fprintf(fp, " %02x", arg[i]); - else - fprintf(fp, " "); - fprintf(fp, "\t"); - } - if (is_jump_target[addr]) - fprintf(fp, "L00%02x:", addr); - fprintf(fp, "\t"); - - if (cmd < MAX_OPCODE) - fprintf(fp, "%s", opcode_sym[cmd]); - - switch (cmd) { - case JUMP: - case JUMP_IF_CHARGING: - fprintf(fp, "\tL00%02x\n", arg[0]); - break; - case JUMP_BATTERY: - fprintf(fp, "\tL00%02x L00%02x\n", arg[0], arg[1]); - break; - case SET_WAIT_DELAY: - case SET_RAMP_DELAY: - fprintf(fp, "\t%d\n", val32(arg)); - break; - case SET_BRIGHTNESS: - fprintf(fp, "\t%d\n", arg[0]); - break; - case SET_COLOR_SINGLE: - led = arg[0] >> 4; - control = (arg[0] >> 2) & 0x03; - color = arg[0] & 0x03; - fprintf(fp, "\t"); - - print_led_set(fp, led); - fprintf(fp, ".%s", control_sym[control]); - fprintf(fp, ".%s", color_sym[color]); - fprintf(fp, "\t0x%02x\n", arg[1]); - break; - case SET_COLOR_RGB: - led = arg[0] >> 4; - control = (arg[0] >> 2) & 0x03; - fprintf(fp, "\t"); - - print_led_set(fp, led); - fprintf(fp, ".%s", control_sym[control]); - fprintf(fp, "\t0x%02x 0x%02x 0x%02x\n", arg[1], arg[2], arg[3]); - break; - case ON: - case OFF: - case WAIT: - case GET_COLORS: - case SWAP_COLORS: - case RAMP_ONCE: - case CYCLE_ONCE: - case CYCLE: - case HALT: - fprintf(fp, "\n"); - break; - default: - fprintf(fp, "-- invalid opcode 0x%02x --\n", cmd); - is_instruction[addr] = 0; - hit_errors++; - } - - return operands; -} - -static void set_jump_target(uint8_t targ) -{ - if (targ >= EC_LB_PROG_LEN) { - Warning("program jumps to 0x%02x, " - "which out of bounds\n", targ); - return; - } - is_jump_target[targ] = 1; -} - -static void disassemble_prog(FILE *fp, struct safe_lightbar_program *prog) -{ - int i; - uint8_t *ptr, op; - - /* Scan the program once to identify all the jump targets, - * so we can print the labels when we encounter them. */ - for (i = 0; i < prog->p.size; i++) { - ptr = &prog->p.data[i]; - op = *ptr; - if (is_jump(op)) - set_jump_target(ptr[1]); - if (op == JUMP_BATTERY) - set_jump_target(ptr[2]); - i += num_operands[op]; - } - - /* Now disassemble */ - for (i = 0; i < prog->p.size; i++) { - ptr = &prog->p.data[i]; - i += print_op(fp, i, *ptr, ptr + 1); - } - - /* Finally, make sure the program doesn't jump to any location other - * than a valid instruction */ - for (i = 0; i < EC_LB_PROG_LEN; i++) - if (is_jump_target[i] && !is_instruction[i]) { - Warning("program jumps to 0x%02x, " - "which is not a valid instruction\n", i); - } -} - -/* We'll split each line into an array of these. */ -struct parse_s { - char *word; - int is_num; - uint32_t val; -}; - -/* Fills in struct, returns number of words found. Note that pointers are only - * copied. The strings they point to are not duplicated. */ -static int split_line(char *buf, const char *delim, struct parse_s *elt, - int max) -{ - char *w, *ptr, *buf_savetok; - int i; - char *e = 0; - - memset(elt, 0, max * sizeof(*elt)); - - for (ptr = buf, i = 0; - i < max && (w = strtok_r(ptr, delim, &buf_savetok)) != 0; - ptr = 0, i++) { - elt[i].word = w; - elt[i].val = (uint32_t)strtoull(w, &e, 0); - if (!e || !*e) - elt[i].is_num = 1; - - } - - return i; -} - -/* Decode led set. Return 0 if bogus, 1 if okay. */ -static int is_led_set(char *buf, uint8_t *valp) -{ - uint8_t led = 0; - unsigned long int next_led; - char *ptr; - - if (!buf) - return 0; - - if (*buf != '{') - return 0; - - buf++; - for (;;) { - next_led = strtoull(buf, &ptr, 0); - if (buf == ptr) { - if (buf[0] == '}' && buf[1] == 0) { - *valp = led; - return 1; - } else - return 0; - } - - if (next_led >= NUM_LEDS) - return 0; - - led |= 1 << next_led; - - buf = ptr; - if (*buf == ',') - buf++; - } -} - -/* Decode color arg based on expected control param sections. - * Return 0 if bogus, 1 if okay. - */ -static int is_color_arg(char *buf, int expected, uint32_t *valp) -{ - struct parse_s token[MAX_WORDS]; - uint8_t led, control, color; - int i; - - if (!buf) - return 0; - - /* There should be three terms, separated with '.' */ - i = split_line(buf, ".", token, MAX_WORDS); - if (i != expected) - return 0; - - if (!is_led_set(token[0].word, &led)) { - Error("Invalid LED set \"%s\"\n", token[0].word); - return 0; - } - - for (i = 0; i < LB_CONT_MAX; i++) - if (!strcmp(token[1].word, control_sym[i])) { - control = i; - break; - } - if (i >= LB_CONT_MAX) - return 0; - - if (expected == 3) { - for (i = 0; i < ARRAY_SIZE(color_sym); i++) - if (!strcmp(token[2].word, color_sym[i])) { - color = i; - break; - } - if (i >= ARRAY_SIZE(color_sym)) - return 0; - } else - color = 0; - - - *valp = ((led & 0xF) << 4) | ((control & 0x3) << 2) | (color & 0x3); - return 1; -} - -static void fixup_symbols(struct safe_lightbar_program *prog) -{ - int i, j; - - for (i = 0; i < EC_LB_PROG_LEN; i++) { - if (reloc_label[i]) { - /* Looking for reloc label */ - for (j = 0; j < EC_LB_PROG_LEN; j++) { - if (label[j] && !strcmp(label[j], - reloc_label[i])) { - prog->p.data[i] = j; - break; - } - } - if (j >= EC_LB_PROG_LEN) - Error("Can't find label %s\n", reloc_label[i]); - } - } -} - - -static void compile(FILE *fp, struct safe_lightbar_program *prog) -{ - char buf[128]; - struct parse_s token[MAX_WORDS]; - char *s; - int line = 0, chopping = 0; - uint8_t addr = 0; - int opcode; - int wnum, wordcnt; - int i; - - while (fgets(buf, sizeof(buf), fp)) { - - /* We truncate lines that are too long */ - s = strchr(buf, '\n'); - if (chopping) { - if (s) - chopping = 0; - continue; - } - - /* Got something to look at */ - line++; - if (!s) { - chopping = 1; - Warning("truncating line %d\n", line); - } - - /* Ignore comments */ - s = strchr(buf, '#'); - if (s) - *s = '\0'; - - wordcnt = split_line(buf, " \t\n", token, MAX_WORDS); - if (!wordcnt) - continue; - - wnum = 0; - - /* A label must be the first word, ends with a ':' (no spaces - * before it), and doesn't start with a ':' */ - s = strchr(token[0].word, ':'); - if (s && s[1] == '\0' && s != token[0].word) { - *s = '\0'; - label[addr] = strdup(token[0].word); - wnum++; - } - - /* How about an opcode? */ - for (opcode = 0; opcode < MAX_OPCODE; opcode++) - if (!strcasecmp(token[wnum].word, opcode_sym[opcode])) - break; - - if (opcode >= MAX_OPCODE) { - Error("Unrecognized opcode \"%s\"" - " at line %d\n", token[wnum].word, line); - continue; - } - - /* Do we even have a place to write this opcode? */ - if (addr >= EC_LB_PROG_LEN) { - Error("out of program space at line %d\n", line); - break; - } - - /* Got an opcode. Save it! */ - prog->p.data[addr++] = opcode; - wnum++; - - /* Now we need operands. */ - switch (opcode) { - case JUMP: - case JUMP_IF_CHARGING: - /* a label */ - if (token[wnum].word) - reloc_label[addr++] = strdup(token[wnum].word); - else - Error("Missing jump target at line %d\n", line); - break; - case JUMP_BATTERY: - /* two labels*/ - if (token[wnum].word) - reloc_label[addr++] = strdup(token[wnum].word); - else { - Error("Missing first jump target " - "at line %d\n", line); - break; - } - wnum++; - if (token[wnum].word) - reloc_label[addr++] = strdup(token[wnum].word); - else - Error("Missing second jump target " - "at line %d\n", line); - break; - - case SET_BRIGHTNESS: - /* one 8-bit arg */ - if (token[wnum].is_num) - prog->p.data[addr++] = token[wnum].val; - else - Error("Missing/invalid arg at line %d\n", line); - break; - - case SET_WAIT_DELAY: - case SET_RAMP_DELAY: - /* one 32-bit arg */ - if (token[wnum].is_num) { - prog->p.data[addr++] = - (token[wnum].val >> 24) & 0xff; - prog->p.data[addr++] = - (token[wnum].val >> 16) & 0xff; - prog->p.data[addr++] = - (token[wnum].val >> 8) & 0xff; - prog->p.data[addr++] = - token[wnum].val & 0xff; - } else { - Error("Missing/invalid arg at line %d\n", line); - } - break; - - case SET_COLOR_SINGLE: - /* one magic word, then one more 8-bit arg */ - i = is_color_arg(token[wnum].word, 3, &token[wnum].val); - if (!i) { - Error("Missing/invalid arg at line %d\n", line); - break; - } - /* save the magic number */ - prog->p.data[addr++] = token[wnum++].val; - /* and the color immediate */ - if (token[wnum].is_num) { - prog->p.data[addr++] = - token[wnum++].val; - } else { - Error("Missing/Invalid arg " - "at line %d\n", line); - break; - } - break; - case SET_COLOR_RGB: - /* one magic word, then three more 8-bit args */ - i = is_color_arg(token[wnum].word, 2, &token[wnum].val); - if (!i) { - Error("Missing/invalid arg at line %d\n", line); - break; - } - /* save the magic number */ - prog->p.data[addr++] = token[wnum++].val; - /* and the color immediates */ - for (i = 0; i < 3; i++) { - if (token[wnum].is_num) { - prog->p.data[addr++] = - token[wnum++].val; - } else { - Error("Missing/Invalid arg " - "at line %d\n", line); - break; - } - } - break; - - default: - /* No args needed */ - break; - } - - /* Did we run past the end? */ - if (addr > EC_LB_PROG_LEN) { - Error("out of program space at line %d\n", line); - break; - } - } - if (ferror(fp)) - Error("problem while reading input: %s\n", strerror(errno)); - - if (!hit_errors) - fixup_symbols(prog); - - if (!hit_errors) - prog->p.size = addr; - - if (!prog->p.size) - Error("input file produced no output bytes\n"); -} - -int main(int argc, char *argv[]) -{ - struct safe_lightbar_program safe_prog; - int opt_decode = 0; - int c; - int errorcnt = 0; - const char *infile, *outfile; - FILE *ifp, *ofp; - - char *progname = strrchr(argv[0], '/'); - if (progname) - progname++; - else - progname = argv[0]; - - opterr = 0; /* quiet, you */ - while ((c = getopt(argc, argv, ":dv")) != -1) { - switch (c) { - case 'd': - opt_decode = 1; - break; - case 'v': - opt_verbose = 1; - break; - - case '?': - fprintf(stderr, "%s: unrecognized switch: -%c\n", - progname, optopt); - errorcnt++; - break; - case ':': - fprintf(stderr, "%s: missing argument to -%c\n", - progname, optopt); - errorcnt++; - break; - default: - errorcnt++; - break; - } - } - - if (errorcnt) { - fprintf(stderr, usage, progname); - exit(1); - } - - if (argc - optind > 0) { - infile = argv[optind]; - ifp = fopen(infile, "rb"); - if (!ifp) { - fprintf(stderr, - "%s: Unable to open %s for reading: %s\n", - progname, infile, strerror(errno)); - exit(1); - } - } else { - infile = "stdin"; - ifp = stdin; - } - - if (argc - optind > 1) { - outfile = argv[optind + 1]; - ofp = fopen(outfile, "wb"); - if (!ofp) { - fprintf(stderr, - "%s: Unable to open %s for writing: %s\n", - progname, outfile, strerror(errno)); - exit(1); - } - } else { - outfile = "stdout"; - ofp = stdout; - } - - if (opt_decode) { - read_binary(ifp, &safe_prog); - fclose(ifp); - if (hit_errors) - return 1; - fprintf(ofp, "# %s\n", infile); - disassemble_prog(ofp, &safe_prog); - fclose(ofp); - } else { - memset(&safe_prog, 0, sizeof(safe_prog)); - compile(ifp, &safe_prog); - fclose(ifp); - if (!hit_errors) { - if (1 != fwrite(safe_prog.p.data, - safe_prog.p.size, 1, ofp)) - Error("%s: Unable to write to %s: %s\n", - progname, outfile, strerror(errno)); - else - fprintf(stderr, "0x%02x bytes written to %s\n", - safe_prog.p.size, outfile); - } - fclose(ofp); - } - - return hit_errors; -} diff --git a/util/lbplay.c b/util/lbplay.c deleted file mode 100644 index 9ab0564b74..0000000000 --- a/util/lbplay.c +++ /dev/null @@ -1,165 +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 <errno.h> -#include <fcntl.h> -#include <stdint.h> -#include <stdio.h> -#include <string.h> -#include <strings.h> -#include <sys/file.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <unistd.h> - -#define LIGHTBAR "/sys/devices/virtual/chromeos/cros_ec/lightbar" - -int main(int argc, char **argv) -{ - int major, minor, fd_v; - int i, tries, fd_s, fd_l; - char buf[80]; - int ret = 1; - - /* Check version */ - fd_v = open(LIGHTBAR "/version", O_RDONLY); - if (fd_v < 0) { - perror("can't open version file"); - goto out; - } - ret = read(fd_v, buf, sizeof(buf) - 1); - if (ret <= 0) { - perror("can't read version"); - close(fd_v); - goto out; - } - buf[ret] = '\0'; - close(fd_v); - - errno = 0; - /* Expect "MAJOR MINOR" */ - if (2 != sscanf(buf, "%d %d", &major, &minor)) { - if (errno) - perror("can't parse version string"); - else - fprintf(stderr, "can't parse version string\n"); - goto out; - } - /* Pixel is "0 0". Minor change will be compatible, Major may not */ - if (major != 0) { - fprintf(stderr, "Don't know how to handle version %d.%d\n", - major, minor); - goto out; - } - - /* Take over lightbar sequencing. */ - fd_s = open(LIGHTBAR "/sequence", O_RDWR | O_SYNC); - if (fd_s < 0) { - perror("can't open sequence control"); - goto out; - } - - /* NOTE: Cooperative locking only. Rude programs may not play nice. */ - if (flock(fd_s, LOCK_EX | LOCK_NB) < 0) { - perror("can't lock sequence control"); - goto out_close; - } - - /* - * If power events are changing the sequence our request to stop may - * be missed, so try a few times before giving up. - * - * Note that every write to a control file should be prefaced with an - * lseek() to the beginning. sysfs files don't work quite like normal - * files. - */ - tries = 3; - while (1) { - lseek(fd_s, 0, SEEK_SET); - if (read(fd_s, buf, sizeof(buf)) <= 0) { - perror("can't read sequence control"); - goto out_unlock; - } - - if (!strncasecmp(buf, "stop", 4)) - break; - - if (!tries--) { - fprintf(stderr, "couldn't get EC to stop\n"); - goto out_unlock; - } - - lseek(fd_s, 0, SEEK_SET); - strcpy(buf, "stop"); - if (write(fd_s, buf, strlen(buf) + 1) <= 0) { - perror("can't write sequence control"); - goto out_unlock; - } - } - - /* Turn the brightness all the way up */ - fd_l = open(LIGHTBAR "/brightness", O_WRONLY | O_SYNC); - if (fd_l < 0) { - perror("can't open brightness control"); - goto out_run; - } - strcpy(buf, "255"); - if (write(fd_l, buf, strlen(buf) + 1) < 0) { - perror("can't write brightness control"); - goto out_led; - } - close(fd_l); - - /* Now let's drive the colors. */ - fd_l = open(LIGHTBAR "/led_rgb", O_WRONLY | O_SYNC); - if (fd_l < 0) { - perror("can't open led control"); - goto out_run; - } - - /* Cycle through some colors. We can update multiple LEDs at once, - * but there's a limit on how often we can send commands to the - * lightbar. Going too fast will block, although buffering combined - * with lseek() may just cause data to be lost. Read "/interval_msec" - * to see what the limit is. The default is 50msec (20Hz). - */ - for (i = 0; i < 256; i += 4) { - sprintf(buf, "0 %d %d %d 1 %d %d %d 2 %d %d %d 3 %d %d %d", - i, 0, 0, - 0, 0, i, - 255-i, 255, 0, - 0, 255, 255-i); - lseek(fd_l, 0, SEEK_SET); - if (write(fd_l, buf, strlen(buf) + 1) < 0) - perror("write to led control"); - - usleep(100000); - } - - /* all white */ - strcpy(buf, "4 255 255 255"); - lseek(fd_l, 0, SEEK_SET); - if (write(fd_l, buf, strlen(buf) + 1) < 0) - perror("write to led control"); - - usleep(400000); - - /* Done. */ - ret = 0; -out_led: - close(fd_l); -out_run: - /* Let EC drive lightbar again */ - strcpy(buf, "run"); - lseek(fd_s, 0, SEEK_SET); - if (write(fd_s, buf, strlen(buf) + 1) < 0) - perror("write to sequence control"); -out_unlock: - flock(fd_s, LOCK_UN); -out_close: - close(fd_s); -out: - return ret; -} diff --git a/util/linux_ec_commands_h_check.sh b/util/linux_ec_commands_h_check.sh deleted file mode 100755 index 4c55faca0a..0000000000 --- a/util/linux_ec_commands_h_check.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/bash -# -# 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. - -set -e - -ec_commands_file_in="include/ec_commands.h" -ec_commands_file_out="build/kernel/include/linux/mfd/cros_ec_commands.h" - -# Check if ec_commands.h has changed. -echo ${PRESUBMIT_FILES} | grep -q "${ec_commands_file_in}" || exit 0 - -if [ ! -f "${ec_commands_file_out}" ]; then - echo "A new cros_ec_commands.h must be generated." - echo 'Please run "make buildall" or "make build_cros_ec_commands"'. - exit 1 -fi - -if [ "${ec_commands_file_out}" -ot "${ec_commands_file_in}" ]; then - echo "cros_ec_commands.h is out of date." - echo 'Please run "make buildall" or "make build_cros_ec_commands"'. - exit 1 -fi diff --git a/util/llvm-gcov.sh b/util/llvm-gcov.sh deleted file mode 100755 index 7c1c97a7d5..0000000000 --- a/util/llvm-gcov.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash -# -# Copyright 2021 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. - -exec llvm-cov gcov "$@" diff --git a/util/lock/android.c b/util/lock/android.c deleted file mode 100644 index 8472b6db68..0000000000 --- a/util/lock/android.c +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - */ - -#include <stdlib.h> - -#include "android.h" - -int in_android(void) -{ - if (getenv("ANDROID_ROOT")) - return 1; - - return 0; -} - -char *android_tmpdir_path(void) -{ - return getenv("TMPDIR"); -} diff --git a/util/lock/android.h b/util/lock/android.h deleted file mode 100644 index bb08486919..0000000000 --- a/util/lock/android.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - */ - -#ifndef ANDROID_H__ -#define ANDROID_H__ - -/* - * in_android - Test to see if the underlying OS is Android - * - * returns boolean 1 to indicate true, 0 otherwise - */ -extern int in_android(void); - -/** - * Determine where temporary files go. - * - * @return A pointer to value of directory containing temporary files if - * successful, or NULL otherwise - */ -extern char *android_tmpdir_path(void); - -#endif diff --git a/util/lock/build.mk b/util/lock/build.mk deleted file mode 100644 index 65a63ab9db..0000000000 --- a/util/lock/build.mk +++ /dev/null @@ -1,10 +0,0 @@ -# -*- makefile -*- -# 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. -# -# Lock library -# - -util-lock-objs=file_lock.o gec_lock.o -util-lock-objs+=android.o diff --git a/util/lock/file_lock.c b/util/lock/file_lock.c deleted file mode 100644 index 36b420d287..0000000000 --- a/util/lock/file_lock.c +++ /dev/null @@ -1,262 +0,0 @@ -/* Copyright 2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * file_lock.c: Implementation for a binary semaphore using a file lock. - * - * Warning: This relies on flock() which is known to be broken on NFS. - * - * The file will remain persistent once the lock has been used. Unfortunately, - * unlinking the file can introduce a race condition so we leave the file - * in place. - * - * The current process's PID will be written to the file for debug purposes. - */ - -#include <errno.h> -#include <fcntl.h> -#include <inttypes.h> -#include <limits.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> -#include <unistd.h> -#include <sys/file.h> -#include <sys/types.h> -#include <sys/stat.h> - -#include "android.h" -#include "ipc_lock.h" -#include "locks.h" - -#define SLEEP_INTERVAL_MS 50 - -static void msecs_to_timespec(int msecs, struct timespec *tmspec) -{ - tmspec->tv_sec = msecs / 1000; - tmspec->tv_nsec = (msecs % 1000) * 1000 * 1000; -} - -static int lock_is_held(struct ipc_lock *lock) -{ - return lock->is_held; -} - -static int test_dir(const char *path) -{ - struct stat s; - - if (lstat(path, &s) < 0) { - fprintf(stderr, "Cannot stat %s.\n", path); - return -1; - } - - if (!S_ISDIR(s.st_mode)) { - fprintf(stderr, "%s is not a directory.\n", path); - return -1; - } - - return 0; -} - -static int file_lock_open_or_create(struct ipc_lock *lock) -{ - char path[PATH_MAX]; - - if (in_android()) { - char *tmpdir; - - tmpdir = android_tmpdir_path(); - if (!tmpdir) - return -1; - - if (snprintf(path, sizeof(path), "%s/%s", - tmpdir, lock->filename) < 0) { - return -1; - } - } else { - const char *dir = SYSTEM_LOCKFILE_DIR; - const char fallback[] = "/tmp"; - - if (test_dir(dir)) { - dir = fallback; - fprintf(stderr, "Trying fallback directory: %s\n", dir); - if (test_dir(dir)) - return -1; - } - - if (snprintf(path, sizeof(path), - "%s/%s", dir, lock->filename) < 0) - return -1; - - } - - lock->fd = open(path, O_RDWR | O_CREAT, 0600); - if (lock->fd < 0) { - fprintf(stderr, "Cannot open lockfile %s", path); - return -1; - } - - return 0; -} - -static int file_lock_get(struct ipc_lock *lock, int timeout_msecs) -{ - int msecs_remaining = timeout_msecs; - struct timespec sleep_interval, rem; - int ret = -1; - - if (timeout_msecs == 0) - return flock(lock->fd, LOCK_EX | LOCK_NB); - - msecs_to_timespec(SLEEP_INTERVAL_MS, &sleep_interval); - - while ((ret = flock(lock->fd, LOCK_EX | LOCK_NB)) != 0) { - if (errno != EWOULDBLOCK) { - fprintf(stderr, "Error obtaining lock"); - return -1; - } - - if (msecs_remaining < SLEEP_INTERVAL_MS) - msecs_to_timespec(msecs_remaining, &sleep_interval); - - while (nanosleep(&sleep_interval, &rem) != 0) { - if (errno == EINTR) { - sleep_interval = rem; - continue; - } else { - fprintf(stderr, "nanosleep() failed"); - return ret; - } - } - - if (timeout_msecs < 0) - continue; - - msecs_remaining -= SLEEP_INTERVAL_MS; - if (msecs_remaining < 0) - break; - } - - if (ret != 0) { - fprintf(stderr, "Timed out waiting for file lock.\n"); - return -1; - } - - return 0; -} - -static int file_lock_write_pid(struct ipc_lock *lock) -{ - ssize_t len; - /* - * PIDs are usually 5 digits, but we'll reserve enough room for - * a value of 2^32 (10 digits) out of paranoia. - */ - char pid_str[11]; - - if (ftruncate(lock->fd, 0) < 0) { - fprintf(stderr, "Cannot truncate lockfile"); - return -1; - } - - snprintf(pid_str, sizeof(pid_str), "%lu", (unsigned long)getpid()); - len = write(lock->fd, pid_str, strlen(pid_str)); - if (len < 0) { - fprintf(stderr, "Cannot write PID to lockfile"); - return -1; - } - - return 0; -} - -static void file_lock_release(struct ipc_lock *lock) -{ - if (flock(lock->fd, LOCK_UN) < 0) - fprintf(stderr, "Cannot release lock"); - - if (close(lock->fd) < 0) - fprintf(stderr, "Cannot close lockfile"); -} - -/* - * timeout <0 = no timeout (try forever) - * timeout 0 = do not wait (return immediately) - * timeout >0 = wait up to $timeout milliseconds - * - * returns 0 to indicate lock acquired - * returns >0 to indicate lock was already held - * returns <0 to indicate failed to acquire lock - */ -int acquire_lock(struct ipc_lock *lock, int timeout_msecs) -{ - /* check if it is already held */ - if (lock_is_held(lock)) - return 1; - - if (file_lock_open_or_create(lock)) - return -1; - - if (file_lock_get(lock, timeout_msecs)) { - lock->is_held = 0; - close(lock->fd); - return -1; - } else { - lock->is_held = 1; - } - - /* - * Write PID to lockfile for debug purposes. Failure to write to - * the file should not be considered fatal. There might be something - * bad happening with the filesystem, but the lock has already been - * obtained and we may need our tools for diagnostics and repairs - * so we should continue anyway. - */ - file_lock_write_pid(lock); - return 0; -} - -/* - * returns 0 if lock was released successfully - * returns -1 if lock had not been held before the call - */ -int release_lock(struct ipc_lock *lock) -{ - if (lock_is_held(lock)) { - file_lock_release(lock); - lock->is_held = 0; - return 0; - } - - return -1; -} diff --git a/util/lock/gec_lock.c b/util/lock/gec_lock.c deleted file mode 100644 index d354ea08f3..0000000000 --- a/util/lock/gec_lock.c +++ /dev/null @@ -1,45 +0,0 @@ -/* Copyright 2012, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "gec_lock.h" -#include "ipc_lock.h" -#include "locks.h" - -static struct ipc_lock gec_lock = LOCKFILE_INIT(CROS_EC_LOCKFILE_NAME); - -int acquire_gec_lock(int timeout_secs) -{ - return acquire_lock(&gec_lock, timeout_secs * 1000); -} - -int release_gec_lock(void) -{ - return release_lock(&gec_lock); -} diff --git a/util/lock/gec_lock.h b/util/lock/gec_lock.h deleted file mode 100644 index 8480700ddd..0000000000 --- a/util/lock/gec_lock.h +++ /dev/null @@ -1,51 +0,0 @@ -/* Copyright 2012, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __UTIL_GEC_LOCK_H -#define __UTIL_GEC_LOCK_H - -/* - * acquire_gec_lock - acquire global lock - * - * returns 0 to indicate lock acquired - * returns >0 to indicate lock was already held - * returns <0 to indicate failed to acquire lock - */ -extern int acquire_gec_lock(int timeout_secs); - -/* - * release_gec_lock - release global lock - * - * returns 0 if lock was released successfully - * returns -1 if lock had not been held before the call - */ -extern int release_gec_lock(void); - -#endif /* __UTIL_GEC_LOCK_H */ diff --git a/util/lock/ipc_lock.h b/util/lock/ipc_lock.h deleted file mode 100644 index 5d0d321af4..0000000000 --- a/util/lock/ipc_lock.h +++ /dev/null @@ -1,69 +0,0 @@ -/* Copyright 2012, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __UTIL_IPC_LOCK_H -#define __UTIL_IPC_LOCK_H - -struct ipc_lock { - int is_held; /* internal */ - const char *filename; /* provided by the developer */ - int fd; /* internal */ -}; - -/* don't use C99 initializers here, so this can be used in C++ code */ -#define LOCKFILE_INIT(lockfile) \ - { \ - 0, /* is_held */ \ - lockfile, /* filename */ \ - -1, /* fd */ \ - } - -/* - * acquire_lock: acquire a lock - * - * timeout <0 = no timeout (try forever) - * timeout 0 = do not wait (return immediately) - * timeout >0 = wait up to $timeout milliseconds (subject to kernel scheduling) - * - * return 0 = lock acquired - * return >0 = lock was already held - * return <0 = failed to acquire lock - */ -extern int acquire_lock(struct ipc_lock *lock, int timeout_msecs); - -/* - * release_lock: release a lock - * - * returns 0 if lock was released successfully - * returns -1 if lock had not been held before the call - */ -extern int release_lock(struct ipc_lock *lock); - -#endif /* __UTIL_IPC_LOCK_H */ diff --git a/util/lock/locks.h b/util/lock/locks.h deleted file mode 100644 index 6875d91454..0000000000 --- a/util/lock/locks.h +++ /dev/null @@ -1,38 +0,0 @@ -/* Copyright 2012, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __UTIL_LOCKS_H -#define __UTIL_LOCKS_H - -#define SYSTEM_LOCKFILE_DIR "/run/lock" -#define LOCKFILE_NAME "firmware_utility_lock" -#define CROS_EC_LOCKFILE_NAME "cros_ec_lock" - -#endif /* __UTIL_LOCKS_H */ diff --git a/util/make_linux_ec_commands_h.sh b/util/make_linux_ec_commands_h.sh deleted file mode 100755 index 4deeaeef32..0000000000 --- a/util/make_linux_ec_commands_h.sh +++ /dev/null @@ -1,81 +0,0 @@ -#!/bin/bash -# -# 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. - -# Generate a kernel include file from ec_commands.h. - -usage() { - cat << EOF -Generate an ec_commands.h file suitable for upstreaming to kernel.org. -Syntax: -$0 source_ec_commands.h target_cros_ec_commands.h - -source_ec_commands.h: source file, usually include/ec_commands.h -target_cros_ec_commands.h: target file that will be upstreamed. -EOF -} - -set -e - -in="$1" -out="$2" - -if [ $# -ne 2 ]; then - usage - exit 1 -fi - -if [ ! -d "${CROS_WORKON_SRCROOT}" ]; then - printf "Not in Chrome OS chroot!\n\n" - usage - exit 0 -fi - -out_dir="$(dirname "${out}")" -mkdir -p "${out_dir}" -tmp="$(mktemp -p "${out_dir}" cros_ec_XXX.h)" -cp "${in}" "${tmp}" - -cleanup() { - rm -f "${tmp}"* -} - -trap cleanup EXIT - -# Replace license -patch "${tmp}" << EOF -@@ -1,6 +1,11 @@ --/* 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. -+/* SPDX-License-Identifier: GPL-2.0-only */ -+/* -+ * Host communication command constants for ChromeOS EC -+ * -+ * Copyright (C) 2012 Google, Inc -+ * -+ * NOTE: This file is auto-generated from ChromeOS EC Open Source code from -+ * https://chromium.googlesource.com/chromiumos/platform/ec/+/master/include/ec_commands.h - */ - - /* Host communication command constants for Chrome EC */ -EOF - -# Change header guards -sed -i "s/__CROS_EC_EC_COMMANDS_H/__CROS_EC_COMMANDS_H/" "${tmp}" - -# Convert UINT32_MAX into U32_MAX (and friends). -sed -i "s/UINT\([0-9]\{1,2\}\)_MAX/U\1_MAX/" "${tmp}" -sed -i "s/INT\([0-9]\{1,2\}\)_MAX/S\1_MAX/" "${tmp}" -sed -i "s/INT\([0-9]\{1,2\}\)_MIN/S\1_MIN/" "${tmp}" - -# Remove non kernel code to prevent checkpatch warnings and simplify the .h. -unifdef -x2 -m -UCONFIG_HOSTCMD_ALIGNED -U__ACPI__ -D__KERNEL__ -U__cplusplus \ - -UCHROMIUM_EC "${tmp}" - -# Check kernel checkpatch passes. -"${CROS_WORKON_SRCROOT}/src/repohooks/checkpatch.pl" -f "${tmp}" - -cp "${tmp}" "${out}" diff --git a/util/misc_util.c b/util/misc_util.c deleted file mode 100644 index 9813dc72b4..0000000000 --- a/util/misc_util.c +++ /dev/null @@ -1,175 +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 <ctype.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/utsname.h> - -#include "comm-host.h" -#include "misc_util.h" - -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; -} - -char *read_file(const char *filename, int *size) -{ - FILE *f = fopen(filename, "rb"); - char *buf; - int i; - - if (!f) { - perror("Error opening input file"); - return NULL; - } - - fseek(f, 0, SEEK_END); - *size = ftell(f); - rewind(f); - if ((*size > 0x100000) || (*size < 0)) { - if (*size < 0) - perror("ftell failed"); - else - fprintf(stderr, "File seems unreasonably large\n"); - fclose(f); - return NULL; - } - - buf = (char *)malloc(*size); - if (!buf) { - fprintf(stderr, "Unable to allocate buffer.\n"); - fclose(f); - return NULL; - } - - printf("Reading %d bytes from %s...\n", *size, filename); - i = fread(buf, 1, *size, f); - fclose(f); - if (i != *size) { - perror("Error reading file"); - free(buf); - return NULL; - } - - return buf; -} - -int is_string_printable(const char *buf) -{ - while (*buf) { - if (!isprint(*buf)) - return 0; - buf++; - } - - return 1; -} - -/** - * Get the versions of the command supported by the EC. - * - * @param cmd Command - * @param pmask Destination for version mask; will be set to 0 on - * error. - * @return 0 if success, <0 if error - */ -int ec_get_cmd_versions(int cmd, uint32_t *pmask) -{ - struct ec_params_get_cmd_versions_v1 pver_v1; - struct ec_params_get_cmd_versions pver; - struct ec_response_get_cmd_versions rver; - int rv; - - *pmask = 0; - - pver_v1.cmd = cmd; - rv = ec_command(EC_CMD_GET_CMD_VERSIONS, 1, &pver_v1, sizeof(pver_v1), - &rver, sizeof(rver)); - - if (rv < 0) { - pver.cmd = cmd; - rv = ec_command(EC_CMD_GET_CMD_VERSIONS, 0, &pver, sizeof(pver), - &rver, sizeof(rver)); - } - - if (rv < 0) - return rv; - - *pmask = rver.version_mask; - return 0; -} - -/** - * Return non-zero if the EC supports the command and version - * - * @param cmd Command to check - * @param ver Version to check - * @return non-zero if command version supported; 0 if not. - */ -int ec_cmd_version_supported(int cmd, int ver) -{ - uint32_t mask = 0; - - if (ec_get_cmd_versions(cmd, &mask)) - return 0; - - return (mask & EC_VER_MASK(ver)) ? 1 : 0; -} - -/** - * Return 1 is the current kernel version is greater or equal to - * <major>.<minor>.<sublevel> - */ -int kernel_version_ge(int major, int minor, int sublevel) -{ - struct utsname uts; - int atoms, kmajor, kminor, ksublevel; - - if (uname(&uts) < 0) - return -1; - atoms = sscanf(uts.release, "%d.%d.%d", &kmajor, &kminor, &ksublevel); - if (atoms < 1) - return -1; - - if (kmajor > major) - return 1; - if (kmajor < major) - return 0; - - /* kmajor == major */ - if (atoms < 2) - return 0 == minor && 0 == sublevel; - if (kminor > minor) - return 1; - if (kminor < minor) - return 0; - - /* kminor == minor */ - if (atoms < 3) - return 0 == sublevel; - - return ksublevel >= sublevel; -} - diff --git a/util/misc_util.h b/util/misc_util.h deleted file mode 100644 index 240d735556..0000000000 --- a/util/misc_util.h +++ /dev/null @@ -1,65 +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_MISC_UTIL_H -#define __UTIL_MISC_UTIL_H - -/* Don't use a macro where an inline will do... */ -static inline int MIN(int a, int b) { return a < b ? a : b; } -static inline int MAX(int a, int b) { return a > b ? a : b; } - -/** - * Write a buffer to the file. - * - * @param filename Target filename - * @param buf Buffer to write - * @param size Size of buffer in bytes - * @return non-zero if error - */ -int write_file(const char *filename, const char *buf, int size); - -/** - * Read a file into a newly-allocated buffer. - * - * @param filename Source filename - * @param size Size of data in bytes will be stored here on success. - * @return A newly allocated buffer with the data, which must be freed with - * free() by the caller, or NULL if error. - */ -char *read_file(const char *filename, int *size); - -/** - * Check if a string contains only printable characters. - * - * @param buf Null-terminated string to check - * @return non-zero if buf contains only printable characters; zero if not. - */ -int is_string_printable(const char *buf); - -/** - * Get the versions of the command supported by the EC. - * - * @param cmd Command - * @param pmask Destination for version mask; will be set to 0 on - * error. - * @return 0 if success, <0 if error - */ -int ec_get_cmd_versions(int cmd, uint32_t *pmask); - -/** - * Return non-zero if the EC supports the command and version - * - * @param cmd Command to check - * @param ver Version to check - * @return non-zero if command version supported; 0 if not. - */ -int ec_cmd_version_supported(int cmd, int ver); - -/** - * Return 1 is the current kernel version is greater or equal to - * <major>.<minor>.<sublevel> - */ -int kernel_version_ge(int major, int minor, int sublevel); -#endif diff --git a/util/openocd/lm4_chip.cfg b/util/openocd/lm4_chip.cfg deleted file mode 100644 index 3dffa2dc66..0000000000 --- a/util/openocd/lm4_chip.cfg +++ /dev/null @@ -1,11 +0,0 @@ - -ftdi_layout_init 0x0018 0x009b - -# open collector oe only -ftdi_layout_signal nSRST -oe 0x0020 - -reset_config trst_only - -source [find target/stellaris.cfg] -source [find lm4x_cmds.tcl] - diff --git a/util/openocd/lm4x_cmds.tcl b/util/openocd/lm4x_cmds.tcl deleted file mode 100644 index 59c2dbdeb6..0000000000 --- a/util/openocd/lm4x_cmds.tcl +++ /dev/null @@ -1,51 +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. -# -# Command automation for Blizzard LM4F chip - -# Program internal flash - -proc flash_lm4 {path offset} { - reset halt; - flash write_image erase $path $offset; - reset -} - -proc flash_lm4_board {board} { - flash_lm4 ../../build/$board/ec.bin 0 -} - -proc flash_lm4_ro {board} { - flash_lm4 ../../build/$board/RO/ec.RO.flat 0 -} - -proc flash_lm4_rw {board} { - flash_lm4 ../../build/$board/RW/ec.RW.bin 131072 -} - -# Boards with CONFIG_FLASH_PSTATE_BANK have pstate following RO -proc unprotect_pstate { } { - reset halt - flash erase_sector 0 126 127 - reset -} - -# Boot a software using internal RAM only - -proc ramboot_lm4 {path} { - reset halt - load_image $path 0x20000000 bin - reg 15 0x20000400 - resume -} - -proc ramboot_lm4_board {board} { - ramboot_lm4 ../../../build/$board/ec.RO.flat -} - -proc flash_emerged_board {board} { - set firmware_image ../../../../../../chroot/build/$board/firmware/ec.bin - - flash_lm4 $firmware_image 0 -} diff --git a/util/openocd/npcx.cfg b/util/openocd/npcx.cfg deleted file mode 100644 index 0ab2b42888..0000000000 --- a/util/openocd/npcx.cfg +++ /dev/null @@ -1,61 +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. -# -# nuvoton-m4 devices support both JTAG and SWD transports. -# - -source [find target/swj-dp.tcl] - -if { [info exists CHIPNAME] } { - set _CHIPNAME $CHIPNAME -} else { - set _CHIPNAME npcx_ec -} - -if { [info exists ENDIAN] } { - set _ENDIAN $ENDIAN -} else { - set _ENDIAN little -} - -# Work-area is a space in RAM used for flash programming -# By default use 16kB -if { [info exists WORKAREASIZE] } { - set _WORKAREASIZE $WORKAREASIZE -} else { - set _WORKAREASIZE 0x8000 -} - -#jtag scan chain -if { [info exists CPUTAPID ] } { - set _CPUTAPID $CPUTAPID -} else { - set _CPUTAPID 0x4BA00477 -} - -#jtag newtap $_CHIPNAME cpu -irlen 4 -expected-id $_CPUTAPID -swj_newdap $_CHIPNAME cpu -irlen 4 -expected-id $_CPUTAPID - -set _TARGETNAME $_CHIPNAME.cpu -target create $_TARGETNAME cortex_m -endian $_ENDIAN -chain-position \ - $_CHIPNAME.cpu -work-area-phys 0x200C0000 \ - -work-area-size $_WORKAREASIZE - -# JTAG speed -adapter_khz 100 - -adapter_nsrst_delay 100 -jtag_ntrst_delay 100 - -# use sysresetreq to perform a system reset -cortex_m reset_config sysresetreq - -#reset configuration -reset_config trst_and_srst - -$_TARGETNAME configure -event reset-start { - echo "NPCX Reset..." - halt - adapter_khz 1000 -} diff --git a/util/openocd/npcx_chip.cfg b/util/openocd/npcx_chip.cfg deleted file mode 100644 index ddd01df5a4..0000000000 --- a/util/openocd/npcx_chip.cfg +++ /dev/null @@ -1,11 +0,0 @@ - -source [find npcx.cfg] -source [find npcx_cmds.tcl] - -ftdi_layout_init 0x0018 0x009b - -# open collector oe only -ftdi_layout_signal nSRST -oe 0x0020 - -reset_config trst_only - diff --git a/util/openocd/npcx_cmds.tcl b/util/openocd/npcx_cmds.tcl deleted file mode 100644 index 759e897131..0000000000 --- a/util/openocd/npcx_cmds.tcl +++ /dev/null @@ -1,184 +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. -# -# Command automation for NPCX5M5G chip - -# Program spi flash -source [find mem_helper.tcl] - -proc flash_npcx {image_path cram_addr image_offset image_size spifw_image} { - set UPLOAD_FLAG 0x200C4000; - set UUT_TAG 0x200C3000; - - echo "*** NPCX Reset and halt CPU first ***" - reset halt - - # Clear whole Code RAM - mwb $cram_addr 0xFF $image_size - # Upload binary image to Code RAM - load_image $image_path $cram_addr - - # Upload program spi image FW to lower 16KB Data RAM - load_image $spifw_image 0x200C3020 - - # Set sp to upper 16KB Data RAM - reg sp 0x200C8000 - # Set spi offset address of uploaded image - reg r0 $image_offset - # Set spi program size of uploaded image - reg r1 $image_size - # Set pc to start of spi program function - reg pc 0x200C3021 - # Clear upload flag - mww $UPLOAD_FLAG 0x0 - - # Clear UUT Tag - mww $UUT_TAG 0x0 - - echo "*** Program ... ***" - # Start to program spi flash - resume - - # Wait for any pending flash operations to complete - while {[expr [mrw $UPLOAD_FLAG] & 0x01] == 0} { sleep 1000 } - - if {[expr [mrw $UPLOAD_FLAG] & 0x02] == 0} { - echo "*** Program Fail ***" - } else { - echo "*** Program Done ***" - } - - # Halt CPU - halt -} - -proc flash_npcx5m5g {image_path image_offset spifw_image} { - # 96 KB for RO & RW regions - set fw_size 0x18000 - # Code RAM start address - set cram_addr 0x100A8000 - - echo "*** Start to program npcx5m5g with $image_path ***" - flash_npcx $image_path $cram_addr $image_offset $fw_size $spifw_image - echo "*** Finish program npcx5m5g ***\r\n" -} - -proc flash_npcx5m6g {image_path image_offset spifw_image} { - # 224 KB for RO & RW regions - set fw_size 0x38000 - # Code RAM start address - set cram_addr 0x10088000 - - echo "*** Start to program npcx5m6g with $image_path ***" - flash_npcx $image_path $cram_addr $image_offset $fw_size $spifw_image - echo "*** Finish program npcx5m6g ***\r\n" -} - -proc flash_npcx7m6x {image_path image_offset spifw_image} { - # 192 KB for RO & RW regions - set fw_size 0x30000 - # Code RAM start address - set cram_addr 0x10090000 - - echo "*** Start to program npcx7m6f/g/w with $image_path ***" - flash_npcx $image_path $cram_addr $image_offset $fw_size $spifw_image - echo "*** Finish program npcx7m6f/g/w ***\r\n" -} - -proc flash_npcx7m7x {image_path image_offset spifw_image} { - # 320 KB for RO & RW regions - set fw_size 0x50000 - # Code RAM start address - set cram_addr 0x10070000 - - echo "*** Start to program npcx7m7f/g/w with $image_path ***" - flash_npcx $image_path $cram_addr $image_offset $fw_size $spifw_image - echo "*** Finish program npcx7m7f/g/w ***\r\n" -} - -proc flash_npcx_ro {chip_name image_dir image_offset} { - set MPU_RNR 0xE000ED98; - set MPU_RASR 0xE000EDA0; - - # images path - set ro_image_path $image_dir/RO/ec.RO.flat - set spifw_image $image_dir/chip/npcx/spiflashfw/npcx_monitor.bin - - # Halt CPU first - halt - - # disable MPU for Data RAM - mww $MPU_RNR 0x1 - mww $MPU_RASR 0x0 - - if {$chip_name == "npcx_5m5g_jtag"} { - # program RO region - flash_npcx5m5g $ro_image_path $image_offset $spifw_image - } elseif {$chip_name == "npcx_5m6g_jtag"} { - # program RO region - flash_npcx5m6g $ro_image_path $image_offset $spifw_image - } elseif {$chip_name == "npcx_7m6x_jtag"} { - # program RO region - flash_npcx7m6x $ro_image_path $image_offset $spifw_image - } elseif {$chip_name == "npcx_7m7x_jtag"} { - # program RO region - flash_npcx7m7x $ro_image_path $image_offset $spifw_image - } else { - echo $chip_name "no supported." - } -} - -proc flash_npcx_all {chip_name image_dir image_offset} { - set MPU_RNR 0xE000ED98; - set MPU_RASR 0xE000EDA0; - - # images path - set ro_image_path $image_dir/RO/ec.RO.flat - set rw_image_path $image_dir/RW/ec.RW.bin - set spifw_image $image_dir/chip/npcx/spiflashfw/npcx_monitor.bin - - # Halt CPU first - halt - - # disable MPU for Data RAM - mww $MPU_RNR 0x1 - mww $MPU_RASR 0x0 - - if {$chip_name == "npcx_5m5g_jtag"} { - # RW images offset - 128 KB - set rw_image_offset [expr ($image_offset + 0x20000)] - # program RO region - flash_npcx5m5g $ro_image_path $image_offset $spifw_image - # program RW region - flash_npcx5m5g $rw_image_path $rw_image_offset $spifw_image - } elseif {$chip_name == "npcx_5m6g_jtag"} { - # RW images offset - 256 KB - set rw_image_offset [expr ($image_offset + 0x40000)] - # program RO region - flash_npcx5m6g $ro_image_path $image_offset $spifw_image - # program RW region - flash_npcx5m6g $rw_image_path $rw_image_offset $spifw_image - } elseif {$chip_name == "npcx_7m6x_jtag"} { - # RW images offset - 256 KB - set rw_image_offset [expr ($image_offset + 0x40000)] - # program RO region - flash_npcx7m6x $ro_image_path $image_offset $spifw_image - # program RW region - flash_npcx7m6x $rw_image_path $rw_image_offset $spifw_image - } elseif {$chip_name == "npcx_7m7x_jtag"} { - # RW images offset - 512 KB - set rw_image_offset [expr ($image_offset + 0x80000)] - # program RO region - flash_npcx7m7x $ro_image_path $image_offset $spifw_image - # program RW region - flash_npcx7m7x $rw_image_path $rw_image_offset $spifw_image - } else { - echo $chip_name "no supported." - } -} - -proc reset_halt_cpu { } { - echo "*** NPCX Reset and halt CPU first ***" - reset halt -} diff --git a/util/openocd/nrf51_chip.cfg b/util/openocd/nrf51_chip.cfg deleted file mode 100644 index f0e78897d6..0000000000 --- a/util/openocd/nrf51_chip.cfg +++ /dev/null @@ -1,14 +0,0 @@ - -#nRF51 uses SWD -transport select swd -# Since nTRST is repurposed, we need a different layout_init setting -ftdi_layout_init 0x0008 0x009b - -ftdi_layout_signal SWDIO_OE -nalias nTRST -ftdi_layout_signal SWD_EN -alias TMS - -#Disable fast flashing, it only works with ST-Link and CMSIS-DAP -set WORKAREASIZE 0 -source [find target/nrf51.cfg] -source [find nrf51_cmds.tcl] - diff --git a/util/openocd/nrf51_cmds.tcl b/util/openocd/nrf51_cmds.tcl deleted file mode 100644 index 711b27574d..0000000000 --- a/util/openocd/nrf51_cmds.tcl +++ /dev/null @@ -1,22 +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. -# -# Command automation for Nordic nRF51 chip - -proc flash_nrf51 {path offset} { - reset halt; - program $path $offset; -} - -proc unprotect_nrf51 { } { - reset halt; - nrf51 mass_erase; -} - -# enable reset by writing 1 to the RESET register -# This will disconnect the debugger with the following message: -# Polling target nrf51.cpu failed, trying to reexamine -proc exit_debug_mode_nrf51 { } { - mww 0x40000544 1; -} diff --git a/util/openocd/servo.cfg b/util/openocd/servo.cfg deleted file mode 100644 index 8331a9bc08..0000000000 --- a/util/openocd/servo.cfg +++ /dev/null @@ -1,14 +0,0 @@ -telnet_port 4444 -gdb_port 3333 -gdb_memory_map enable -gdb_flash_program enable - -interface ftdi -# VID/PID for servo v2, servo v3 -ftdi_vid_pid 0x18d1 0x5002 0x18d1 0x5004 0x18d1 0x500d -# Only initialize Port A -ftdi_channel 0 - -# unbuffered connection data == oe -ftdi_layout_signal nTRST -data 0x0010 -oe 0x0010 - diff --git a/util/powerd_lock.c b/util/powerd_lock.c deleted file mode 100644 index df34d03c6c..0000000000 --- a/util/powerd_lock.c +++ /dev/null @@ -1,63 +0,0 @@ -/* - * This file is ported from the flashrom project. - * - * 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 program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * powerd_lock.c: power management routines - */ - -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/types.h> -#include <unistd.h> - -#include "powerd_lock.h" - -/* - * Path to a file containing flashrom's PID. While present, powerd avoids - * suspending or shutting down the system. - */ -static const char lock_file_path[] = - "/run/lock/power_override/battery_tool.lock"; - -int disable_power_management() -{ - FILE *lock_file; - int rc = 0; - lock_file = fopen(lock_file_path, "w"); - if (!lock_file) - return POWERD_CREATE_LOCK_FILE_ERROR; - - if (fprintf(lock_file, "%ld", (long)getpid()) < 0) - rc = POWERD_WRITE_LOCK_FILE_ERROR; - - if (fclose(lock_file) != 0) - rc |= POWERD_CLOSE_LOCK_FILE_ERROR; - return rc; -} - -int restore_power_management() -{ - int result = 0; - result = unlink(lock_file_path); - if (result != 0 && errno != ENOENT) - return POWERD_DELETE_LOCK_FILE_ERROR; - return 0; -} diff --git a/util/powerd_lock.h b/util/powerd_lock.h deleted file mode 100644 index 86be184a19..0000000000 --- a/util/powerd_lock.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * This file is ported from the flashrom project. - * - * 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 program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * powerd_lock.h: header file for power management routines - */ - -#ifndef __UTIL_POWERD_LOCK_H -#define __UTIL_POWERD_LOCK_H 1 - -enum POWERD_ERROR_CODE { - POWERD_OK = 0, - POWERD_CREATE_LOCK_FILE_ERROR = 0x1, - POWERD_WRITE_LOCK_FILE_ERROR = 0x2, - POWERD_CLOSE_LOCK_FILE_ERROR = 0x4, - POWERD_DELETE_LOCK_FILE_ERROR = 0x8 -}; - -/* Disable power management. */ -int disable_power_management(void); - -/* Re-enable power management. */ -int restore_power_management(void); - -#endif /* __UTIL_POWERD_LOCK_H */ diff --git a/util/presubmit_check.sh b/util/presubmit_check.sh deleted file mode 100755 index 7d46f38a0f..0000000000 --- a/util/presubmit_check.sh +++ /dev/null @@ -1,44 +0,0 @@ -#!/bin/bash -# -# 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. - -# Verify there is no CPRINTS("....\n", ...) statements added to the code. -upstream_branch="$(git rev-parse --abbrev-ref --symbolic-full-name @{u} \ - 2>/dev/null)" -if [[ -z ${upstream_branch} ]]; then - echo "Current branch does not have an upstream branch" >&2 - exit 1 -fi -# This will print the offending CPRINTS invocations, if any, and the names of -# the files they are in. -if git diff --no-ext-diff "${upstream_branch}" HEAD | - grep -e '^+\(.*CPRINTS(.*\\n"\|++\)' | - grep CPRINTS -B1 >&2 ; then - echo "error: CPRINTS strings should not include newline characters" >&2 - exit 1 -fi - -# Directories that need to be tested by separate unit tests. -unittest_dirs="util/ec3po/ extra/stack_analyzer/" - -for dir in $unittest_dirs; do - dir_files=$(echo "${PRESUBMIT_FILES}" | grep "${dir}") - if [[ -z "${dir_files}" ]]; then - continue - fi - - if [[ ! -e "${dir}/.tests-passed" ]]; then - echo "Unit tests have not passed. Please run \"${dir}run_tests.sh\"." - exit 1 - fi - - changed_files=$(find ${dir_files} -newer "${dir}/.tests-passed") - if [[ -n "${changed_files}" ]] && [[ -n "${dir_files}" ]]; then - echo "Files have changed since last time unit tests passed:" - echo "${changed_files}" | sed -e 's/^/ /' - echo "Please run \"${dir}run_tests.sh\"." - exit 1 - fi -done diff --git a/util/run_ects.py b/util/run_ects.py deleted file mode 100644 index 9178328e5f..0000000000 --- a/util/run_ects.py +++ /dev/null @@ -1,96 +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. -# -# Ignore indention messages, since legacy scripts use 2 spaces instead of 4. -# pylint: disable=bad-indentation,docstring-section-indent -# pylint: disable=docstring-trailing-quotes - -"""Run all eCTS tests and publish results.""" - - -import argparse -import logging -import os -import subprocess -import sys - -# List of tests to run. -TESTS = ['meta', 'gpio', 'hook', 'i2c', 'interrupt', 'mutex', 'task', 'timer'] - - -class CtsRunner(object): - """Class running eCTS tests.""" - - def __init__(self, ec_dir, dryrun): - self.ec_dir = ec_dir - self.cts_py = [] - if dryrun: - self.cts_py += ['echo'] - self.cts_py += [os.path.join(ec_dir, 'cts/cts.py')] - - def run_cmd(self, cmd): - try: - rc = subprocess.call(cmd) - if rc != 0: - return False - except OSError: - return False - return True - - def run_test(self, test): - cmd = self.cts_py + ['-m', test] - self.run_cmd(cmd) - - def run(self, tests): - for test in tests: - logging.info('Running', test, 'test.') - self.run_test(test) - - def sync(self): - logging.info('Syncing tree...') - os.chdir(self.ec_dir) - cmd = ['repo', 'sync', '.'] - return self.run_cmd(cmd) - - def upload(self): - logging.info('Uploading results...') - - -def main(): - if not os.path.exists('/etc/cros_chroot_version'): - logging.error('This script has to run inside chroot.') - sys.exit(-1) - - ec_dir = os.path.realpath(os.path.dirname(__file__) + '/..') - - parser = argparse.ArgumentParser(description='Run eCTS and report results.') - parser.add_argument('-d', - '--dryrun', - action='store_true', - help='Echo commands to be executed without running them.') - parser.add_argument('-s', - '--sync', - action='store_true', - help='Sync tree before running tests.') - parser.add_argument('-u', - '--upload', - action='store_true', - help='Upload test results.') - args = parser.parse_args() - - runner = CtsRunner(ec_dir, args.dryrun) - - if args.sync: - if not runner.sync(): - logging.error('Failed to sync.') - sys.exit(-1) - - runner.run(TESTS) - - if args.upload: - runner.upload() - - -if __name__ == '__main__': - main() diff --git a/util/run_host_test b/util/run_host_test deleted file mode 100755 index 15013d91b6..0000000000 --- a/util/run_host_test +++ /dev/null @@ -1,129 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# Copyright 2020 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. - -"""Wrapper that runs a host test. Handles timeout and stopping the emulator.""" - -import argparse -import enum -import io -import os -import pathlib -import select -import subprocess -import sys -import time - - -class TestResult(enum.Enum): - """An Enum representing the result of running a test.""" - SUCCESS = 0 - FAIL = 1 - TIMEOUT = 2 - UNEXPECTED_TERMINATION = 3 - - @property - def reason(self): - return { - TestResult.SUCCESS: 'passed', - TestResult.FAIL: 'failed', - TestResult.TIMEOUT: 'timed out', - TestResult.UNEXPECTED_TERMINATION: 'terminated unexpectedly', - }[self] - - -def run_test(path, timeout=10): - start_time = time.monotonic() - env = dict(os.environ) - env['ASAN_OPTIONS'] = 'log_path=stderr' - - proc = subprocess.Popen( - [path], - bufsize=0, - stdin=subprocess.PIPE, - stdout=subprocess.PIPE, - env=env, - encoding='utf-8', - errors='replace', - ) - - # Put the output pipe in non-blocking mode. We will then select(2) - # on the pipe to know when we have bytes to process. - os.set_blocking(proc.stdout.fileno(), False) - - try: - output_buffer = io.StringIO() - while True: - select_timeout = timeout - (time.monotonic() - start_time) - if select_timeout <= 0: - return TestResult.TIMEOUT, output_buffer.getvalue() - - readable, _, _ = select.select([proc.stdout], [], [], select_timeout) - - if not readable: - # Indicates that select(2) timed out. - return TestResult.TIMEOUT, output_buffer.getvalue() - - output_buffer.write(proc.stdout.read()) - output_log = output_buffer.getvalue() - - if 'Pass!' in output_log: - return TestResult.SUCCESS, output_log - if 'Fail!' in output_log: - return TestResult.FAIL, output_log - if proc.poll(): - return TestResult.UNEXPECTED_TERMINATION, output_log - finally: - # Check if the process has exited. If not, send it a SIGTERM, wait for it - # to exit, and if it times out, kill the process directly. - if not proc.poll(): - try: - proc.terminate() - proc.wait(timeout) - except subprocess.TimeoutExpired: - proc.kill() - - -def parse_options(argv): - parser = argparse.ArgumentParser() - parser.add_argument('-t', '--timeout', type=float, default=60, - help='Timeout to kill test after.') - parser.add_argument('--coverage', action='store_const', const='coverage', - default='host', dest='test_target', - help='Flag if this is a code coverage test.') - parser.add_argument('--verbose', '-v', action='store_true', - help='Dump emulator output always, even if successful.') - parser.add_argument('test_name', type=str) - return parser.parse_args(argv) - - -def main(argv): - opts = parse_options(argv) - - # Tests will be located in build/host, unless the --coverage flag was - # provided, in which case they will be in build/coverage. - exec_path = pathlib.Path('build', opts.test_target, opts.test_name, - f'{opts.test_name}.exe') - if not exec_path.is_file(): - print(f'No test named {opts.test_name} exists!') - return 1 - - start_time = time.monotonic() - result, output = run_test(exec_path, timeout=opts.timeout) - elapsed_time = time.monotonic() - start_time - - print('{} {}! ({:.3f} seconds)'.format( - opts.test_name, result.reason, elapsed_time), - file=sys.stderr) - - if result is not TestResult.SUCCESS or opts.verbose: - print('====== Emulator output ======', file=sys.stderr) - print(output, file=sys.stderr) - print('=============================', file=sys.stderr) - return result.value - - -if __name__ == '__main__': - sys.exit(main(sys.argv[1:])) diff --git a/util/stm32mon.c b/util/stm32mon.c deleted file mode 100644 index 7be802b1ed..0000000000 --- a/util/stm32mon.c +++ /dev/null @@ -1,1758 +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. - * - * STM32 SoC system monitor interface tool - * For Serial, implement protocol v2.0 as defined in: - * http://www.st.com/st-web-ui/static/active/en/resource/technical/\ - * document/application_note/CD00264342.pdf - * - * For i2C, implement protocol v1.0 as defined in: - * http://www.st.com/st-web-ui/static/active/en/resource/technical/\ - * document/application_note/DM00072315.pdf - * - * For SPI, implement protocol v1.1 as defined in: - * https://www.st.com/resource/en/application_note/dm00081379.pdf - */ - -/* use cfmakeraw() */ -#define _DEFAULT_SOURCE /* Newer glibc */ -#define _BSD_SOURCE /* Older glibc */ - -#include <arpa/inet.h> -#include <compile_time_macros.h> -#include <errno.h> -#include <fcntl.h> -#include <getopt.h> -#include <inttypes.h> -#include <stdio.h> -#include <stdint.h> -#include <stdlib.h> -#include <string.h> -#include <sys/ioctl.h> -#include <sys/stat.h> -#include <linux/i2c-dev.h> -#include <linux/spi/spidev.h> -#include <termios.h> -#include <time.h> -#include <unistd.h> - -#include "ec_version.h" - -#define KBYTES_TO_BYTES 1024 - -/* - * Some Ubuntu versions do not export SPI_IOC_WR_MODE32 even though - * the kernel shipped on those supports it. - */ -#ifndef SPI_IOC_WR_MODE32 -#define SPI_IOC_WR_MODE32 _IOW(SPI_IOC_MAGIC, 5, __u32) -#endif - -/* Monitor command set */ -#define CMD_INIT 0x7f /* Starts the monitor */ - -#define CMD_GETCMD 0x00 /* Gets the allowed commands */ -#define CMD_GETVER 0x01 /* Gets the bootloader version */ -#define CMD_GETID 0x02 /* Gets the Chip ID */ -#define CMD_READMEM 0x11 /* Reads memory */ -#define CMD_GO 0x21 /* Jumps to user code */ -#define CMD_WRITEMEM 0x31 /* Writes memory (SRAM or Flash) */ -#define CMD_ERASE 0x43 /* Erases n pages of Flash memory */ -#define CMD_EXTERASE 0x44 /* Erases n pages of Flash memory */ -#define CMD_NO_STRETCH_ERASE 0x45 /* Erases while sending busy frame */ -#define CMD_WP 0x63 /* Enables write protect */ -#define CMD_WU 0x73 /* Disables write protect */ -#define CMD_RP 0x82 /* Enables the read protection */ -#define CMD_RU 0x92 /* Disables the read protection */ - -#define CMD_LOOKUP_ENTRY(COMMAND) {CMD_##COMMAND, #COMMAND} -const struct { - const uint8_t cmd; - const char *name; -} cmd_lookup_table[] = { - CMD_LOOKUP_ENTRY(INIT), - CMD_LOOKUP_ENTRY(GETCMD), - CMD_LOOKUP_ENTRY(GETVER), - CMD_LOOKUP_ENTRY(GETID), - CMD_LOOKUP_ENTRY(READMEM), - CMD_LOOKUP_ENTRY(GO), - CMD_LOOKUP_ENTRY(WRITEMEM), - CMD_LOOKUP_ENTRY(ERASE), - CMD_LOOKUP_ENTRY(EXTERASE), - CMD_LOOKUP_ENTRY(NO_STRETCH_ERASE), - CMD_LOOKUP_ENTRY(WP), - CMD_LOOKUP_ENTRY(WU), - CMD_LOOKUP_ENTRY(RP), - CMD_LOOKUP_ENTRY(RU), -}; - -const char *cmd_lookup_name(uint8_t cmd) -{ - int i; - for (i = 0; i < ARRAY_SIZE(cmd_lookup_table); i++) { - if (cmd_lookup_table[i].cmd == cmd) - return cmd_lookup_table[i].name; - } - - return NULL; -} - -#define RESP_NACK 0x1f -#define RESP_ACK 0x79 /* 0b 0111 1001 */ -#define RESP_BUSY 0x76 -#define RESP_DAMAGED_ACK 0xBC /* 0b 1011 1100, 1 bit shifted REST_ACK */ - -/* SPI Start of Frame */ -#define SOF 0x5A - -/* Extended erase special parameters */ -#define ERASE_ALL 0xffff -#define ERASE_BANK1 0xfffe -#define ERASE_BANK2 0xfffd - -/* Upper bound of rebooting the monitor */ -#define MAX_DELAY_REBOOT 100000 /* us */ - -/* Standard addresses common across various ST chips */ -#define STM32_MAIN_MEMORY_ADDR 0x08000000 -#define STM32_SYSTEM_MEMORY_ADDR 0x1FFF0000 - -#define STM32_UNIQUE_ID_SIZE_BYTES 12 - -/* - * Device electronic signature contains factory-programmed identification - * and calibration data to automatically match the characteristics of the - * microcontroller. - */ -struct stm32_device_signature { - /* - * Address of the Unique Device ID register. This register contains a - * 96-bit value that is unique across all chips. - * Zero means ignore/unknown. - */ - uint32_t unique_device_id_addr; - /* - * Address of the Flash Size register. This 16-bit register contains the - * flash size in KB. - * Zero means ignore/unknown. - */ - uint32_t flash_size_addr; - /* - * Address of the Package Data register. This 16-bit register contains a - * value that differentiates between package types of a given chip. - * Zero means ignore/unknown. - */ - uint32_t package_data_addr; -}; - -struct memory_info { - /* Zero means ignore/unknown/not-applicable */ - uint32_t addr; - /* If addr is non-zero - * - zero here means value is dynamic and will be read from bootloader. - * If addr is zero, - * - zero here means ignore/unknown/not-applicable. - */ - uint32_t size_bytes; -}; - -struct memory_layout { - struct memory_info main_memory; - struct memory_info system_memory; - struct memory_info otp_area; - struct memory_info option_bytes; -}; - -/* known STM32 SoC parameters */ -struct stm32_def { - uint16_t id; - const char *name; - uint32_t flash_size; - uint32_t page_size; - uint32_t cmds_len[2]; - const struct memory_layout memory_layout; - const struct stm32_device_signature device_signature; -} chip_defs[] = { - {0x416, "STM32L15xxB", 0x20000, 256, {13, 13}, { { 0 } }, { 0 } }, - {0x429, "STM32L15xxB-A", 0x20000, 256, {13, 13}, { { 0 } }, { 0 } }, - {0x427, "STM32L15xxC", 0x40000, 256, {13, 13}, { { 0 } }, { 0 } }, - {0x435, "STM32L44xx", 0x40000, 2048, {13, 13}, { { 0 } }, { 0 } }, - {0x420, "STM32F100xx", 0x20000, 1024, {13, 13}, { { 0 } }, { 0 } }, - {0x410, "STM32F102R8", 0x10000, 1024, {13, 13}, { { 0 } }, { 0 } }, - {0x440, "STM32F05x", 0x10000, 1024, {13, 13}, { { 0 } }, { 0 } }, - {0x444, "STM32F03x", 0x08000, 1024, {13, 13}, { { 0 } }, { 0 } }, - {0x448, "STM32F07xB", 0x20000, 2048, {13, 13}, { { 0 } }, { 0 } }, - {0x432, "STM32F37xx", 0x40000, 2048, {13, 13}, { { 0 } }, { 0 } }, - {0x442, "STM32F09x", 0x40000, 2048, {13, 13}, { { 0 } }, { 0 } }, - {0x431, "STM32F411", 0x80000, 16384, {13, 19}, { { 0 } }, { 0 } }, - { - .id = 0x441, - .name = "STM32F412", - .flash_size = 0x100000, - .page_size = 16384, - .cmds_len = {13, 19}, - /* - * STM32F412: - * See https://www.st.com/resource/en/reference_manual/dm00180369.pdf - * Section 3.3 Table 5 Flash module organization - */ - .memory_layout = { - .main_memory = { - .addr = STM32_MAIN_MEMORY_ADDR, - .size_bytes = 0, /* set by flash reg read */ - }, - .system_memory = { - .addr = STM32_SYSTEM_MEMORY_ADDR, - .size_bytes = 30 * KBYTES_TO_BYTES, - }, - .otp_area = { - .addr = 0x1FFF7800, - .size_bytes = 528, - }, - .option_bytes = { - .addr = 0x1FFFC000, - .size_bytes = 16, - } - }, - /* - * STM32F412: - * See https://www.st.com/resource/en/reference_manual/dm00180369.pdf - * Section 31 Device electronic signature - */ - .device_signature = { - .unique_device_id_addr = 0x1FFF7A10, - .flash_size_addr = 0x1FFF7A22, - /* - * Out of range for bootloader on this chip, so we don't - * attempt to read. - */ - .package_data_addr = 0, /* 0x1FFF7BF0 */ - } - }, - {0x450, "STM32H74x", 0x200000, 131768, {13, 19}, { { 0 } }, { 0 } }, - {0x451, "STM32F76x", 0x200000, 32768, {13, 19}, { { 0 } }, { 0 } }, - { - .id = 0x460, - .name = "STM32G071xx", - .flash_size = 0x20000, - .page_size = 2048, - .cmds_len = {13, 13}, - /* - * STM32G0x1: - * See https://www.st.com/resource/en/reference_manual/dm00371828.pdf - * Section 3.3.1 Table 6 Flash module organization - */ - .memory_layout = { - .main_memory = { - .addr = STM32_MAIN_MEMORY_ADDR, - .size_bytes = 0, /* set by flash reg read */ - }, - .system_memory = { - .addr = STM32_SYSTEM_MEMORY_ADDR, - .size_bytes = 28 * KBYTES_TO_BYTES, - }, - .otp_area = { - .addr = 0x1FFF7000, - .size_bytes = 1024, - }, - .option_bytes = { - .addr = 0x1FFF7800, - .size_bytes = 128, - } - }, - /* - * STM32G0x1: - * See https://www.st.com/resource/en/reference_manual/dm00371828.pdf - * Section 38 Device electronic signature - */ - .device_signature = { - .unique_device_id_addr = 0x1FFF7590, - .flash_size_addr = 0x1FFF75E0, - /* - * Datasheet litst as same address as e.g. STM32F412, - * hence declaring as zero as for that other chip. - */ - .package_data_addr = 0, /* 0x1FFF7500 */ - } - }, - { 0 } -}; - -#define DEFAULT_CONNECT_RETRIES 5 -#define DEFAULT_TIMEOUT 4 /* seconds */ -#define EXT_ERASE_TIMEOUT 20 /* seconds */ -#define DEFAULT_BAUDRATE B38400 -#define PAGE_SIZE 256 -#define INVALID_I2C_ADAPTER -1 -#define MAX_ACK_RETRY_COUNT (EXT_ERASE_TIMEOUT / DEFAULT_TIMEOUT) -#define MAX_RETRY_COUNT 3 - -enum interface_mode { - MODE_SERIAL, - MODE_I2C, - MODE_SPI, -} mode = MODE_SERIAL; - -/* I2c address the EC is listening depends on the device: - * stm32f07xxx: 0x76 - * stm32f411xx: 0x72 - */ -#define DEFAULT_I2C_SLAVE_ADDRESS 0x76 - -/* store custom parameters */ -speed_t baudrate = DEFAULT_BAUDRATE; -int connect_retries = DEFAULT_CONNECT_RETRIES; -int i2c_adapter = INVALID_I2C_ADAPTER; -const char *spi_adapter; -int i2c_slave_address = DEFAULT_I2C_SLAVE_ADDRESS; -uint8_t boot_loader_version; -const char *serial_port = "/dev/ttyUSB1"; -const char *input_filename; -const char *output_filename; -uint32_t offset = 0x08000000, length = 0; -int retry_on_damaged_ack; - -/* STM32MON function return values */ -enum { - STM32_SUCCESS = 0, - STM32_EIO = -1, /* IO error */ - STM32_EINVAL = -2, /* Got a faulty response from device */ - STM32_ETIMEDOUT = -3, /* Device didn't respond in a time window. */ - STM32_ENOMEM = -4, /* Failed to allocate memory. */ - STM32_ENACK = -5, /* Got NACK. */ - STM32_EDACK = -6, /* Got a damanged ACK. */ -}; -BUILD_ASSERT(STM32_SUCCESS == 0); -#define IS_STM32_ERROR(res) ((res) < STM32_SUCCESS) - -/* optional command flags */ -enum { - FLAG_UNPROTECT = 0x01, - FLAG_ERASE = 0x02, - FLAG_GO = 0x04, - FLAG_READ_UNPROTECT = 0x08, - FLAG_CR50_MODE = 0x10, -}; - -typedef struct { - int size; - uint8_t *data; -} payload_t; - -/* List all possible flash erase functions */ -typedef int command_erase_t(int fd, uint16_t count, uint16_t start); -command_erase_t command_erase; -command_erase_t command_ext_erase; -command_erase_t command_erase_i2c; - -command_erase_t *erase; - -static void discard_input(int); - -#define MIN(a, b) ((a) < (b) ? (a) : (b)) - -/* On user request save all data exchange with the target in this log file. */ -static FILE *log_file; - -/* Statistic data structure for response kind. */ -struct { - const char * const event_name; - uint32_t event_count; -} stat_resp[] = { - { "RESP_ACK", 0 }, - { "RESP_NACK", 0 }, - { "RESP_BUSY", 0 }, - { "RESP_DAMAGED_ACK", 0 }, - { "JUNK", 0 }, -}; - -enum { - RESP_ACK_IDX = 0, - RESP_NACK_IDX, - RESP_BUSY_IDX, - RESP_DAMAGED_ACK_IDX, - JUNK_IDX, - MAX_EVENT_IDX -}; - -BUILD_ASSERT(ARRAY_SIZE(stat_resp) == MAX_EVENT_IDX); - -/* - * Print data into the log file, in hex, 16 bytes per line, prefix the first - * line with the value supplied by the caller (usually 'r' or 'w' for - * read/write). - */ -static void dump_log(const char *prefix, const void *data, size_t count) -{ - size_t i; - - fprintf(log_file, "%s: ", prefix); - for (i = 0; i < count; i++) { - if (i && !(i % 16)) - fprintf(log_file, "\n "); - fprintf(log_file, " %02x", ((uint8_t *)data)[i]); - } - - if (count % 16) - fprintf(log_file, "\n"); - - /* Make sure all data is there even in case of aborts/crashes. */ - fflush(log_file); -} - -/* - * Wrappers for standard library read() and write() functions. Add transferred - * data to the log if log file is opened. - */ -static ssize_t read_wrapper(int fd, void *buf, size_t count) -{ - ssize_t rv = read(fd, buf, count); - - if (log_file && (rv > 0)) - dump_log("r", buf, rv); - - return rv; -} - -static ssize_t write_wrapper(int fd, const void *buf, size_t count) -{ - ssize_t rv; - - rv = write(fd, buf, count); - - if (log_file && (rv > 0)) - dump_log("w", buf, rv); - - return rv; -} - -int open_serial(const char *port, int cr50_mode) -{ - int fd, res; - struct termios cfg, cfg_copy; - - fd = open(port, O_RDWR | O_NOCTTY); - if (fd == -1) { - perror("Unable to open serial port"); - return -1; - } - - /* put the tty in "raw" mode at the defined baudrate */ - res = tcgetattr(fd, &cfg); - if (res == -1) { - perror("Cannot read tty attributes"); - close(fd); - return -1; - } - cfmakeraw(&cfg); - - /* Don't bother setting speed and parity when programming over Cr50. */ - if (!cr50_mode) { - cfsetspeed(&cfg, baudrate); - /* serial mode should be 8e1 */ - cfg.c_cflag |= PARENB; - } - - /* 200 ms timeout */ - cfg.c_cc[VTIME] = 2; - cfg.c_cc[VMIN] = 0; - memcpy(&cfg_copy, &cfg, sizeof(cfg_copy)); - - /* - * tcsetattr() returns success if any of the modifications succeed, so - * its return value of zero is not an indication of success, one needs - * to check the result explicitly. - */ - tcsetattr(fd, TCSANOW, &cfg); - if (tcgetattr(fd, &cfg)) { - perror("Failed to re-read tty attributes"); - close(fd); - return -1; - } - - if (memcmp(&cfg, &cfg_copy, sizeof(cfg))) { - /* - * On some systems the setting which does not come through is - * the parity. We can try continuing without it when using - * certain interfaces, let's try. - */ - cfg_copy.c_cflag &= ~PARENB; - if (memcmp(&cfg, &cfg_copy, sizeof(cfg))) { - /* - * Something other than parity failed to get set, this - * is an error. - */ - perror("Cannot set tty attributes"); - close(fd); - return -1; - } else { - fprintf(stderr, "Failed to enable parity\n"); - } - } - - discard_input(fd); /* in case were were invoked soon after reset */ - return fd; -} - -int open_i2c(const int port) -{ - int fd; - char filename[20]; - - snprintf(filename, 19, "/dev/i2c-%d", port); - fd = open(filename, O_RDWR); - if (fd < 0) { - perror("Unable to open i2c adapter"); - return -1; - } - if (ioctl(fd, I2C_SLAVE, i2c_slave_address >> 1) < 0) { - perror("Unable to select proper address"); - close(fd); - return -1; - } - - return fd; -} - -int open_spi(const char *port) -{ - int fd; - int res; - uint32_t mode = SPI_MODE_0; - uint8_t bits = 8; - - fd = open(port, O_RDWR); - if (fd == -1) { - perror("Unable to open SPI controller"); - return -1; - } - - res = ioctl(fd, SPI_IOC_WR_MODE32, &mode); - if (res == -1) { - perror("Cannot set SPI mode"); - close(fd); - return -1; - } - - res = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits); - if (res == -1) { - perror("Cannot set SPI bits per word"); - close(fd); - return -1; - } - - return fd; -} - -static void discard_input(int fd) -{ - uint8_t buffer[64]; - int res, i; - int count_of_zeros; - - /* Skip in i2c and spi modes */ - if (mode != MODE_SERIAL) - return; - - /* eat trailing garbage */ - count_of_zeros = 0; - do { - res = read_wrapper(fd, buffer, sizeof(buffer)); - if (res > 0) { - - /* Discard zeros in the beginning of the buffer. */ - for (i = 0; i < res; i++) - if (buffer[i]) - break; - - count_of_zeros += i; - if (i == res) { - /* Only zeros, nothing to print out. */ - continue; - } - - /* Discard zeros in the end of the buffer. */ - while (!buffer[res - 1]) { - count_of_zeros++; - res--; - } - - printf("Recv[%d]:", res - i); - for (; i < res; i++) - printf("%02x ", buffer[i]); - printf("\n"); - } - } while (res > 0); - - if (count_of_zeros) - printf("%d zeros ignored\n", count_of_zeros); -} - -int wait_for_ack(int fd) -{ - uint8_t resp; - int res; - time_t deadline = time(NULL) + DEFAULT_TIMEOUT; - const uint8_t ack = RESP_ACK; - - while (time(NULL) < deadline) { - res = read_wrapper(fd, &resp, 1); - if ((res < 0) && (errno != EAGAIN)) { - perror("Failed to read answer"); - return STM32_EIO; - } - - if (res != 1) - continue; - - switch (resp) { - case RESP_ACK: - stat_resp[RESP_ACK_IDX].event_count++; - if (mode == MODE_SPI) /* Ack the ACK */ - if (write_wrapper(fd, &ack, 1) != 1) - return STM32_EIO; - return STM32_SUCCESS; - - case RESP_NACK: - stat_resp[RESP_NACK_IDX].event_count++; - fprintf(stderr, "NACK\n"); - if (mode == MODE_SPI) /* Ack the NACK */ - if (write_wrapper(fd, &ack, 1) != 1) - return STM32_EIO; - discard_input(fd); - return STM32_ENACK; - - case RESP_BUSY: - stat_resp[RESP_BUSY_IDX].event_count++; - /* I2C Boot protocol 1.1 */ - deadline = time(NULL) + DEFAULT_TIMEOUT; - break; - - case RESP_DAMAGED_ACK: - if (retry_on_damaged_ack) { - /* It is a damaged ACK. However, device is - * likely to believe it sent ACK, so let's not - * treat it as junk. - */ - stat_resp[RESP_DAMAGED_ACK_IDX].event_count++; - fprintf(stderr, "DAMAGED_ACK\n"); - return STM32_EDACK; - } - - /* Do not break so that it can be handled as junk */ - default: - stat_resp[JUNK_IDX].event_count++; - if (mode == MODE_SERIAL) - fprintf(stderr, "Receive junk: %02x\n", resp); - break; - } - } - fprintf(stderr, "Timeout\n"); - return STM32_ETIMEDOUT; -} - -int send_command(int fd, uint8_t cmd, payload_t *loads, int cnt, - uint8_t *resp, int resp_size, int ack_requested) -{ - int res, i, c; - payload_t *p; - int readcnt = 0; - - uint8_t cmd_frame[] = { SOF, cmd, - /* XOR checksum */ - (uint8_t)(0xff ^ cmd) }; - /* only the SPI mode needs the Start Of Frame byte */ - int cmd_off = mode == MODE_SPI ? 0 : 1; - int count_damaged_ack = 0; - - /* Send the command index */ - res = write_wrapper(fd, cmd_frame + cmd_off, - sizeof(cmd_frame) - cmd_off); - if (res <= 0) { - perror("Failed to write command frame"); - return STM32_EIO; - } - - /* Wait for the ACK */ - res = wait_for_ack(fd); - if (res == STM32_EDACK) { - ++count_damaged_ack; - } else if (IS_STM32_ERROR(res)) { - const char *name = cmd_lookup_name(cmd); - char hex[sizeof("0xFF")]; - snprintf(hex, sizeof(hex), "0x%02x", cmd); - fprintf(stderr, "Failed to get command %s ACK\n", - name ? name : hex); - return res; - } - - /* Send the command payloads */ - for (p = loads, c = 0; c < cnt; c++, p++) { - uint8_t crc = 0; - int size = p->size; - uint8_t *data = (uint8_t *)(malloc(size + 1)), *data_ptr; - - if (data == NULL) { - fprintf(stderr, - "Failed to allocate memory for load %d\n", c); - return STM32_ENOMEM; - } - memcpy(data, p->data, size); - for (i = 0; i < size; i++) - crc ^= data[i]; - if (size == 1) - crc = 0xff ^ crc; - data[size] = crc; - size++; - data_ptr = data; - while (size) { - res = write_wrapper(fd, data_ptr, size); - if (res < 0) { - perror("Failed to write command payload"); - free(data); - return STM32_EIO; - } - size -= res; - data_ptr += res; - } - free(data); - - /* Wait for the ACK */ - res = wait_for_ack(fd); - if (res == STM32_EDACK) { - ++count_damaged_ack; - } else if (IS_STM32_ERROR(res)) { - if (res != STM32_ETIMEDOUT) - fprintf(stderr, - "payload %d ACK failed for CMD%02x\n", - c, cmd); - return res; - } - } - - /* Read the answer payload */ - if (resp) { - if (mode == MODE_SPI) /* ignore extra byte */ - if (read_wrapper(fd, resp, 1) < 0) - return STM32_EIO; - while ((resp_size > 0) && - (res = read_wrapper(fd, resp, resp_size))) { - if (res < 0) { - perror("Failed to read payload"); - return STM32_EIO; - } - readcnt += res; - resp += res; - resp_size -= res; - } - - /* Wait for the ACK */ - if (ack_requested) { - res = wait_for_ack(fd); - if (res == STM32_EDACK) { - ++count_damaged_ack; - } else if (IS_STM32_ERROR(res)) { - fprintf(stderr, - "Failed to get response to command" - " 0x%02x ACK\n", cmd); - return res; - } - } - } - - if (count_damaged_ack) - return STM32_EDACK; - - return readcnt; -} - -int send_command_retry(int fd, uint8_t cmd, payload_t *loads, - int cnt, uint8_t *resp, int resp_size, int ack_requested) -{ - int res; - int retries = MAX_RETRY_COUNT; - - do { - int ack_tries = MAX_ACK_RETRY_COUNT; - - res = send_command(fd, cmd, loads, cnt, resp, resp_size, - ack_requested); - - while (res == STM32_ETIMEDOUT && ack_tries--) { - if (cmd == CMD_WRITEMEM) { - /* send garbage byte */ - res = write_wrapper(fd, loads->data, 1); - /* Don't care much since it is a garbage - * transfer to let the device not wait for - * any missing data, if any. - */ - if (res < 0) - fprintf(stderr, "warn: write failed\n"); - } - res = wait_for_ack(fd); - } - } while ((res == STM32_ENACK || res == STM32_EDACK) && retries--); - - return res; -} - -struct stm32_def *command_get_id(int fd) -{ - int res; - uint8_t id[3]; - uint16_t chipid; - struct stm32_def *def; - - res = send_command(fd, CMD_GETID, NULL, 0, id, sizeof(id), 1); - if (res > 0) { - if (id[0] != 1) { - fprintf(stderr, "unknown ID : %02x %02x %02x\n", - id[0], id[1], id[2]); - return NULL; - } - chipid = (id[1] << 8) | id[2]; - for (def = chip_defs; def->id; def++) - if (def->id == chipid) - break; - if (def->id == 0) - def = NULL; - printf("ChipID 0x%03x : %s\n", chipid, def ? def->name : "???"); - return def; - } - - return NULL; -} - -int init_monitor(int fd) -{ - int res = 0; - int attempts = connect_retries + 1; - uint8_t init = mode == MODE_SPI ? SOF : CMD_INIT; - - /* Skip in i2c mode */ - if (mode == MODE_I2C) - return STM32_SUCCESS; - - printf("Waiting for the monitor startup ..."); - fflush(stdout); - - while (connect_retries < 0 || attempts--) { - /* Send the command index */ - res = write_wrapper(fd, &init, 1); - if (res <= 0) { - perror("Failed to write command"); - return STM32_EIO; - } - /* Wait for the ACK */ - res = wait_for_ack(fd); - if (res == STM32_SUCCESS) - break; - if (res == STM32_ENACK) { - /* we got NACK'ed, the loader might be already started - * let's ping it to check - */ - if (command_get_id(fd)) { - printf("Monitor already started.\n"); - return STM32_SUCCESS; - } - } - if (IS_STM32_ERROR(res) && res != STM32_ETIMEDOUT) - return res; - fflush(stdout); - } - - if (IS_STM32_ERROR(res)) { - printf("Giving up after %d attempts.\n", connect_retries + 1); - return res; - } - - printf("Done.\n"); - - /* read trailing chars */ - discard_input(fd); - - return STM32_SUCCESS; -} - -int command_get_commands(int fd, struct stm32_def *chip) -{ - int res, i; - uint8_t cmds[64]; - - /* - * For i2c, we have to request the exact amount of bytes we expect. - */ - res = send_command(fd, CMD_GETCMD, NULL, 0, cmds, - chip->cmds_len[(mode == MODE_I2C ? 1 : 0)], 1); - if (res > 0) { - if (cmds[0] > sizeof(cmds) - 2) { - fprintf(stderr, "invalid GET answer (%02x...)\n", - cmds[0]); - return STM32_EINVAL; - } - printf("Bootloader v%d.%d, commands : ", - cmds[1] >> 4, cmds[1] & 0xf); - boot_loader_version = cmds[1]; - - erase = command_erase; - for (i = 2; i < 2 + cmds[0]; i++) { - const char *name; - if (cmds[i] == CMD_EXTERASE) - erase = command_ext_erase; - name = cmd_lookup_name(cmds[i]); - if (name) - printf("%s ", name); - else - printf("0x%02x ", cmds[i]); - } - - if (mode == MODE_I2C) - erase = command_erase_i2c; - printf("\n"); - - return STM32_SUCCESS; - } - - fprintf(stderr, "Cannot get bootloader command list.\n"); - return STM32_EINVAL; -} - -static int use_progressbar; -static int windex; -static const char wheel[] = {'|', '/', '-', '\\' }; -static void draw_spinner(uint32_t remaining, uint32_t size) -{ - int percent = (size - remaining)*100/size; - if (use_progressbar) { - int dots = percent / 4; - - while (dots > windex) { - putchar('#'); - windex++; - } - } else { - printf("\r%c%3d%%", wheel[windex++], percent); - windex %= sizeof(wheel); - } - fflush(stdout); -} - -int command_read_mem(int fd, uint32_t address, uint32_t size, uint8_t *buffer) -{ - int res; - uint32_t remaining = size; - uint32_t addr_be; - uint8_t cnt; - payload_t loads[2] = { - {4, (uint8_t *)&addr_be}, - {1, &cnt} - }; - - while (remaining) { - uint32_t bytes = MIN(remaining, PAGE_SIZE); - - cnt = (uint8_t) (bytes - 1); - addr_be = htonl(address); - - draw_spinner(remaining, size); - - res = send_command_retry(fd, CMD_READMEM, loads, 2, buffer, - bytes, 0); - if (IS_STM32_ERROR(res)) - return STM32_EIO; - - buffer += bytes; - address += bytes; - remaining -= bytes; - } - - return size; -} - -int command_write_mem(int fd, uint32_t address, uint32_t size, uint8_t *buffer) -{ - int res = 0; - int i; - uint32_t remaining = size; - uint32_t addr_be; - uint32_t cnt; - uint8_t outbuf[257]; - payload_t loads[2] = { - {4, (uint8_t *)&addr_be}, - {sizeof(outbuf), outbuf} - }; - - while (remaining) { - cnt = MIN(remaining, PAGE_SIZE); - /* skip empty blocks to save time */ - for (i = 0; i < cnt && buffer[i] == 0xff; i++) - ; - if (i != cnt) { - addr_be = htonl(address); - outbuf[0] = cnt - 1; - loads[1].size = cnt + 1; - memcpy(outbuf + 1, buffer, cnt); - - draw_spinner(remaining, size); - - res = send_command_retry(fd, CMD_WRITEMEM, loads, 2, - NULL, 0, 1); - if (IS_STM32_ERROR(res)) - return STM32_EIO; - } - buffer += cnt; - address += cnt; - remaining -= cnt; - } - - return size; -} - -int command_ext_erase(int fd, uint16_t count, uint16_t start) -{ - int res; - uint16_t count_be = htons(count); - payload_t load = { 2, (uint8_t *)&count_be }; - uint16_t *pages = NULL; - - if (count < 0xfff0) { - int i; - /* not a special value : build a list of pages */ - load.size = 2 * (count + 1); - pages = (uint16_t *)(malloc(load.size)); - if (!pages) - return STM32_ENOMEM; - load.data = (uint8_t *)pages; - pages[0] = htons(count - 1); - for (i = 0; i < count; i++) - pages[i+1] = htons(start + i); - } - - printf("Erasing...\n"); - res = send_command_retry(fd, CMD_EXTERASE, &load, 1, NULL, 0, 1); - if (!IS_STM32_ERROR(res)) - printf("Flash erased.\n"); - - if (pages) - free(pages); - return res; -} - -int command_erase_i2c(int fd, uint16_t count, uint16_t start) -{ - int res; - uint8_t erase_cmd; - uint16_t count_be = htons(count); - payload_t load[2] = { - { 2, (uint8_t *)&count_be}, - { 0, NULL}, - }; - int load_cnt = 1; - uint16_t *pages = NULL; - - if (count < 0xfff) { - int i; - /* not a special value : build a list of pages */ - /* - * I2c protocol requires 2 messages, the count has to be acked - * before the addresses can be sent. - * TODO(gwendal): Still broken on i2c. - */ - load_cnt = 2; - load[1].size = 2 * count; - pages = (uint16_t *)(malloc(load[1].size)); - if (!pages) - return STM32_ENOMEM; - load[1].data = (uint8_t *)pages; - count_be = htons(count - 1); - for (i = 0; i < count; i++) - pages[i] = htons(start + i); - } - - erase_cmd = (boot_loader_version == 0x10) ? CMD_EXTERASE : - CMD_NO_STRETCH_ERASE; - - printf("Erasing...\n"); - res = send_command(fd, erase_cmd, load, load_cnt, NULL, 0, 1); - if (!IS_STM32_ERROR(res)) - printf("Flash erased.\n"); - - if (pages) - free(pages); - return res; -} - - -int command_erase(int fd, uint16_t count, uint16_t start) -{ - int res; - uint8_t count_8bit = count; - payload_t load = { 1, &count_8bit }; - uint8_t *pages = NULL; - - if (count < 0xff) { - int i; - /* not a special value : build a list of pages */ - load.size = count + 1; - pages = (uint8_t *)(malloc(load.size)); - if (!pages) - return STM32_ENOMEM; - load.data = (uint8_t *)pages; - pages[0] = count - 1; - for (i = 0; i < count; i++) - pages[i+1] = start + i; - } - - printf("Erasing...\n"); - res = send_command(fd, CMD_ERASE, &load, 1, NULL, 0, 1); - if (!IS_STM32_ERROR(res)) - printf("Flash erased.\n"); - - if (pages) - free(pages); - return res; -} - -int command_read_unprotect(int fd) -{ - int res; - int retries = MAX_ACK_RETRY_COUNT; - - printf("Unprotecting flash read...\n"); - - res = send_command(fd, CMD_RU, NULL, 0, NULL, 0, 1); - /* - * Read unprotect can trigger a mass erase, which can take long time - * (e.g. 13s+ on STM32H7) - */ - do { - res = wait_for_ack(fd); - } while ((res == STM32_ETIMEDOUT) && --retries); - - if (IS_STM32_ERROR(res)) { - fprintf(stderr, "Failed to get read-protect ACK\n"); - return res; - } - printf("Flash read unprotected.\n"); - - /* - * This command triggers a reset. - * - * Wait at least the reboot delay, else we could reconnect - * before the actual reset depending on the bootloader. - */ - usleep(MAX_DELAY_REBOOT); - if (IS_STM32_ERROR(init_monitor(fd))) { - fprintf(stderr, "Cannot recover after RU reset\n"); - return STM32_EIO; - } - - return STM32_SUCCESS; -} - -int command_write_unprotect(int fd) -{ - int res; - - res = send_command(fd, CMD_WU, NULL, 0, NULL, 0, 1); - if (IS_STM32_ERROR(res)) - return STM32_EIO; - - /* Wait for the ACK */ - if (wait_for_ack(fd) < 0) { - fprintf(stderr, "Failed to get write-protect ACK\n"); - return STM32_EINVAL; - } - printf("Flash write unprotected.\n"); - - /* - * This command triggers a reset. - * - * Wait at least the reboot delay, else we could reconnect - * before the actual reset depending on the bootloader. - */ - usleep(MAX_DELAY_REBOOT); - if (IS_STM32_ERROR(init_monitor(fd))) { - fprintf(stderr, "Cannot recover after WP reset\n"); - return STM32_EIO; - } - - return STM32_SUCCESS; -} - -int command_go(int fd, uint32_t address) -{ - int res; - uint32_t addr_be = htonl(address); - payload_t load = { 4, (uint8_t *)&addr_be }; - - res = send_command(fd, CMD_GO, &load, 1, NULL, 0, 1); - if (IS_STM32_ERROR(res)) - return STM32_EIO; - -#if 0 /* this ACK should exist according to the documentation ... */ - /* Wait for the ACK */ - if (wait_for_ack(fd) < 0) { - fprintf(stderr, "Failed to get GO ACK\n"); - return -EINVAL; - } -#endif - - printf("Program started at 0x%08x.\n", address); - return STM32_SUCCESS; -} - -/* - * The bootloader does not allow reading directly from the "device signature" - * registers. However, it does allow reading the OTP region, so this function - * starts a read from the last byte in that region and reads an additional - * number of bytes to read the requested register. - * - * Example: - * - * Given a chip with OTP region starting at address 0x1FFF7800 with a size of - * 528 bytes and a register that we want to read at address 0x1FFF7A10 with a - * size of 12 bytes: - * - * We start the read at the last byte in the OTP region: - * - * 0x1FFF7800 + 528 - 1 = 0x1FFF7A0F - * - * From 0x1FFF7A0F we perform a read of (12 + 1) = 13 bytes in order to read the - * 12 bytes starting at 0x1FFF7A10 (the actual register we care about). - * - * Returns zero on success, negative on failure. - */ -int read_device_signature_register(int fd, const struct stm32_def *chip, - uint32_t addr, uint32_t size_bytes, - uint8_t *out_buffer) -{ - int res; - uint8_t *buffer; - struct memory_info otp = chip->memory_layout.otp_area; - uint32_t otp_end_addr = otp.addr + otp.size_bytes - 1; - uint32_t offset = addr - otp_end_addr; - uint32_t read_size_bytes = offset + size_bytes; - - if (!otp.addr) { - fprintf(stderr, "No otp_area.addr specified for given chip.\n"); - return STM32_EINVAL; - } - - if (addr <= otp_end_addr) { - fprintf(stderr, "Attempting to read from invalid address: " - "%08X\n", addr); - return STM32_EINVAL; - } - - /* - * The USART/SPI/I2C bootloader can only read at most 256 bytes in a - * single read command (see AN4286 section 2.5 or AN3155 section 3.4). - * - * command_read_mem will correctly chunk larger requests, but the - * subsequent reads will fail because the bootloader won't allow reads - * from a starting address that is beyond the OTP region. - */ - if (read_size_bytes > PAGE_SIZE) { - fprintf(stderr, - "Requested register 0x%08X is outside read range.\n", - addr); - return STM32_EINVAL; - } - - buffer = (uint8_t *)(malloc(read_size_bytes)); - if (!buffer) { - fprintf(stderr, "Cannot allocate %" PRIu32 " bytes\n", - read_size_bytes); - return STM32_ENOMEM; - } - - res = command_read_mem(fd, otp_end_addr, read_size_bytes, buffer); - if (res == read_size_bytes) - memcpy(out_buffer, buffer + offset, size_bytes); - else - fprintf(stderr, - "Cannot read %" PRIu32 " bytes from address 0x%08X", - read_size_bytes, otp_end_addr); - - free(buffer); - return IS_STM32_ERROR(res) ? res : STM32_SUCCESS; -} - -/* Return zero on success, a negative error value on failures. */ -int read_flash_size_register(int fd, struct stm32_def *chip, - uint16_t *flash_size_kbytes) -{ - int res; - uint32_t flash_size_addr = chip->device_signature.flash_size_addr; - - if (!flash_size_addr) - return STM32_EINVAL; - - res = read_device_signature_register(fd, chip, - flash_size_addr, sizeof(*flash_size_kbytes), - (uint8_t *)flash_size_kbytes); - - if (!IS_STM32_ERROR(res)) - printf("Flash size: %" PRIu16 " KB\n", *flash_size_kbytes); - else - fprintf(stderr, - "Unable to read flash size register (0x%08X).\n", - flash_size_addr); - - return res; -} - -/* Return zero on success, a negative error value on failures. */ -int read_unique_device_id_register(int fd, struct stm32_def *chip, - uint8_t device_id[STM32_UNIQUE_ID_SIZE_BYTES]) -{ - int i; - int res; - uint32_t unique_device_id_addr = - chip->device_signature.unique_device_id_addr; - - if (!unique_device_id_addr) - return STM32_EINVAL; - - res = read_device_signature_register(fd, chip, unique_device_id_addr, - STM32_UNIQUE_ID_SIZE_BYTES, device_id); - - if (!IS_STM32_ERROR(res)) { - printf("Unique Device ID: 0x"); - for (i = STM32_UNIQUE_ID_SIZE_BYTES - 1; i >= 0; i--) - printf("%02X", device_id[i]); - printf("\n"); - } else { - fprintf(stderr, - "Unable to read unique device ID register (0x%08X). " - "Ignoring non-critical failure.\n", - unique_device_id_addr); - } - - return res; -} - -/* Return zero on success, a negative error value on failures. */ -int read_package_data_register(int fd, struct stm32_def *chip, - uint16_t *package_data) -{ - int res; - uint32_t package_data_addr = chip->device_signature.package_data_addr; - - if (!package_data_addr) - return STM32_EINVAL; - - res = read_device_signature_register(fd, chip, package_data_addr, - sizeof(*package_data), - (uint8_t *)package_data); - - if (!IS_STM32_ERROR(res)) - printf("Package data register: %04X\n", *package_data); - else - fprintf(stderr, - "Failed to read package data register (0x%08X). " - "Ignoring non-critical failure.\n", package_data_addr); - - return res; -} - -/* Return zero on success, a negative error value on failures. */ -int read_flash(int fd, struct stm32_def *chip, const char *filename, - uint32_t offset, uint32_t size) -{ - int res; - FILE *hnd; - uint8_t *buffer; - - if (!size) - size = chip->flash_size; - buffer = (uint8_t *)(malloc(size)); - if (!buffer) { - fprintf(stderr, "Cannot allocate %d bytes\n", size); - return STM32_ENOMEM; - } - - hnd = fopen(filename, "w"); - if (!hnd) { - fprintf(stderr, "Cannot open file %s for writing\n", filename); - free(buffer); - return STM32_EIO; - } - - printf("Reading %d bytes at 0x%08x\n", size, offset); - res = command_read_mem(fd, offset, size, buffer); - if (res > 0) { - if (fwrite(buffer, res, 1, hnd) != 1) - fprintf(stderr, "Cannot write %s\n", filename); - } - printf("\r %d bytes read.\n", res); - - fclose(hnd); - free(buffer); - return IS_STM32_ERROR(res) ? res : STM32_SUCCESS; -} - -/* Return zero on success, a negative error value on failures. */ -int write_flash(int fd, struct stm32_def *chip, const char *filename, - uint32_t offset) -{ - int res, written; - FILE *hnd; - int size = chip->flash_size; - uint8_t *buffer = (uint8_t *)(malloc(size)); - - if (!buffer) { - fprintf(stderr, "Cannot allocate %d bytes\n", size); - return STM32_ENOMEM; - } - - if (!strncmp(filename, "-", sizeof("-"))) - hnd = fdopen(STDIN_FILENO, "r"); - else - hnd = fopen(filename, "r"); - if (!hnd) { - fprintf(stderr, "Cannot open file %s for reading\n", filename); - free(buffer); - return STM32_EIO; - } - res = fread(buffer, 1, size, hnd); - fclose(hnd); - if (res <= 0) { - fprintf(stderr, "Cannot read %s\n", filename); - free(buffer); - return STM32_EIO; - } - - /* faster write: skip empty trailing space */ - while (res && buffer[res - 1] == 0xff) - res--; - /* ensure 'res' is multiple of 4 given 'size' is and res <= size */ - res = (res + 3) & ~3; - - printf("Writing %d bytes at 0x%08x\n", res, offset); - written = command_write_mem(fd, offset, res, buffer); - if (written != res) { - fprintf(stderr, "Error writing to flash\n"); - free(buffer); - return STM32_EIO; - } - printf("\r %d bytes written.\n", written); - - free(buffer); - return STM32_SUCCESS; -} - -static const struct option longopts[] = { - {"adapter", 1, 0, 'a'}, - {"baudrate", 1, 0, 'b'}, - {"cr50", 0, 0, 'c'}, - {"device", 1, 0, 'd'}, - {"erase", 0, 0, 'e'}, - {"go", 0, 0, 'g'}, - {"help", 0, 0, 'h'}, - {"length", 1, 0, 'n'}, - {"location", 1, 0, 'l'}, - {"logfile", 1, 0, 'L'}, - {"offset", 1, 0, 'o'}, - {"progressbar", 0, 0, 'p'}, - {"read", 1, 0, 'r'}, - {"retries", 1, 0, 'R'}, - {"spi", 1, 0, 's'}, - {"unprotect", 0, 0, 'u'}, - {"version", 0, 0, 'v'}, - {"write", 1, 0, 'w'}, - {NULL, 0, 0, 0} -}; - -void display_usage(char *program) -{ - fprintf(stderr, - "Usage: %s [-a <i2c_adapter> [-l address ]] | [-s]" - " [-d <tty>] [-b <baudrate>]] [-u] [-e] [-U]" - " [-r <file>] [-w <file>] [-o offset] [-n length] [-g] [-p]" - " [-L <log_file>] [-c] [-v]\n", - program); - fprintf(stderr, "Can access the controller via serial port or i2c\n"); - fprintf(stderr, "Serial port mode:\n"); - fprintf(stderr, "--d[evice] <tty> : use <tty> as the serial port\n"); - fprintf(stderr, "--b[audrate] <baudrate> : set serial port speed " - "to <baudrate> bauds\n"); - fprintf(stderr, "i2c mode:\n"); - fprintf(stderr, "--a[dapter] <id> : use i2c adapter <id>.\n"); - fprintf(stderr, "--l[ocation] <address> : use address <address>.\n"); - fprintf(stderr, "--s[pi]: use spi mode.\n"); - fprintf(stderr, "--u[nprotect] : remove flash write protect\n"); - fprintf(stderr, "--U[nprotect] : remove flash read protect\n"); - fprintf(stderr, "--e[rase] : erase all the flash content\n"); - fprintf(stderr, "--r[ead] <file> : read the flash content and " - "write it into <file>\n"); - fprintf(stderr, "--s[pi] </dev/spi> : use SPI adapter on </dev>.\n"); - fprintf(stderr, "--w[rite] <file|-> : read <file> or\n\t" - "standard input and write it to flash\n"); - fprintf(stderr, "--o[ffset] : offset to read/write/start from/to\n"); - fprintf(stderr, "--n[length] : amount to read/write\n"); - fprintf(stderr, "--g[o] : jump to execute flash entrypoint\n"); - fprintf(stderr, "--p[rogressbar] : use a progress bar instead of " - "the spinner\n"); - fprintf(stderr, "--R[etries] <num> : limit connect retries to num\n"); - fprintf(stderr, "-L[ogfile] <file> : save all communications exchange " - "in a log file\n"); - fprintf(stderr, "-c[r50_mode] : consider device to be a Cr50 interface," - " no need to set UART port attributes\n"); - fprintf(stderr, "--v[ersion] : print version and exit\n"); - - exit(2); -} - -void display_version(const char *exe_name) -{ - printf("%s version: %s %s %s\n", exe_name, CROS_STM32MON_VERSION, DATE, - BUILDER); -} - -speed_t parse_baudrate(const char *value) -{ - int rate = atoi(value); - - switch (rate) { - case 9600: - return B9600; - case 19200: - return B19200; - case 38400: - return B38400; - case 57600: - return B57600; - case 115200: - return B115200; - default: - fprintf(stderr, "Invalid baudrate %s, using %d\n", - value, DEFAULT_BAUDRATE); - return DEFAULT_BAUDRATE; - } -} - -int parse_parameters(int argc, char **argv) -{ - int opt, idx; - int flags = 0; - const char *log_file_name = NULL; - - while ((opt = getopt_long(argc, argv, "a:l:b:cd:eghL:n:o:pr:R:s:w:uUv?", - longopts, &idx)) != -1) { - switch (opt) { - case 'a': - i2c_adapter = atoi(optarg); - mode = MODE_I2C; - break; - case 'l': - i2c_slave_address = strtol(optarg, NULL, 0); - break; - case 'b': - baudrate = parse_baudrate(optarg); - break; - case 'c': - flags |= FLAG_CR50_MODE; - break; - case 'd': - serial_port = optarg; - mode = MODE_SERIAL; - break; - case 'e': - flags |= FLAG_ERASE; - break; - case 'g': - flags |= FLAG_GO; - break; - case 'h': - case '?': - display_usage(argv[0]); - break; - case 'L': - log_file_name = optarg; - break; - case 'n': - length = strtol(optarg, NULL, 0); - break; - case 'o': - offset = strtol(optarg, NULL, 0); - break; - case 'p': - use_progressbar = 1; - break; - case 'r': - input_filename = optarg; - break; - case 'R': - connect_retries = atoi(optarg); - break; - case 's': - spi_adapter = optarg; - mode = MODE_SPI; - break; - case 'w': - output_filename = optarg; - break; - case 'u': - flags |= FLAG_UNPROTECT; - break; - case 'U': - flags |= FLAG_READ_UNPROTECT; - break; - case 'v': - display_version(argv[0]); - exit(0); - } - } - - if (log_file_name) { - log_file = fopen(log_file_name, "w"); - if (!log_file) { - fprintf(stderr, "failed to open %s for writing\n", - log_file_name); - exit(2); - } - } - return flags; -} - -static void display_stat_response(void) -{ - uint32_t total_events = MAX_EVENT_IDX; - uint32_t idx; - - printf("--\n"); - for (idx = 0; idx < total_events; ++idx) { - printf("%-18s %d\n", stat_resp[idx].event_name, - stat_resp[idx].event_count); - } - printf("--\n"); -} - -int main(int argc, char **argv) -{ - int ser; - struct stm32_def *chip; - int ret = STM32_EIO; - int res; - int flags; - uint16_t flash_size_kbytes = 0; - uint8_t unique_device_id[STM32_UNIQUE_ID_SIZE_BYTES] = { 0 }; - uint16_t package_data_reg = 0; - - /* Parse command line options */ - flags = parse_parameters(argc, argv); - - display_version(argv[0]); - - retry_on_damaged_ack = !!(flags & FLAG_CR50_MODE); - - switch (mode) { - case MODE_SPI: - ser = open_spi(spi_adapter); - break; - case MODE_I2C: - ser = open_i2c(i2c_adapter); - break; - case MODE_SERIAL: - default: - /* Open the serial port tty */ - ser = open_serial(serial_port, !!(flags & FLAG_CR50_MODE)); - } - if (ser < 0) - return 1; - /* Trigger embedded monitor detection */ - res = init_monitor(ser); - if (IS_STM32_ERROR(res)) - goto terminate; - - chip = command_get_id(ser); - if (!chip) - goto terminate; - - if (command_get_commands(ser, chip) < 0) - goto terminate; - - if (flags & FLAG_READ_UNPROTECT) - command_read_unprotect(ser); - - /* - * Use the actual size if we were able to read it since some chips - * have the same chip ID, but different flash sizes based on the - * package. - */ - res = read_flash_size_register(ser, chip, &flash_size_kbytes); - if (!IS_STM32_ERROR(res)) - chip->flash_size = flash_size_kbytes * KBYTES_TO_BYTES; - - /* - * This is simply informative at the moment, so we don't care about the - * return value. - */ - (void)read_unique_device_id_register(ser, chip, unique_device_id); - - /* - * This is simply informative at the moment, so we don't care about the - * return value. - */ - (void)read_package_data_register(ser, chip, &package_data_reg); - - if (flags & FLAG_UNPROTECT) - command_write_unprotect(ser); - - if (flags & FLAG_ERASE || output_filename) { - if ((!strncmp("STM32L15", chip->name, 8)) || - (!strncmp("STM32F411", chip->name, 9))) { - /* Mass erase is not supported on these chips*/ - int i, page_count = chip->flash_size / chip->page_size; - for (i = 0; i < page_count; i += 128) { - int count = MIN(128, page_count - i); - ret = erase(ser, count, i); - if (IS_STM32_ERROR(ret)) - goto terminate; - } - } else { - ret = erase(ser, 0xFFFF, 0); - if (IS_STM32_ERROR(ret)) - goto terminate; - } - } - - if (input_filename) { - ret = read_flash(ser, chip, input_filename, offset, length); - if (IS_STM32_ERROR(ret)) - goto terminate; - } - - if (output_filename) { - ret = write_flash(ser, chip, output_filename, offset); - if (IS_STM32_ERROR(ret)) - goto terminate; - } - - /* Run the program from flash */ - if (flags & FLAG_GO) - command_go(ser, offset); - - /* Normal exit */ - ret = STM32_SUCCESS; -terminate: - if (log_file) - fclose(log_file); - - /* Close serial port */ - close(ser); - - if (retry_on_damaged_ack) - display_stat_response(); - - if (IS_STM32_ERROR(ret)) { - fprintf(stderr, "Failed: %d\n", ret); - return 1; - } - - printf("Done.\n"); - return 0; -} diff --git a/util/tagbranch.sh b/util/tagbranch.sh deleted file mode 100755 index 3e196b6f25..0000000000 --- a/util/tagbranch.sh +++ /dev/null @@ -1,84 +0,0 @@ -#!/bin/bash -# -# 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. -# -# Generate git strings for tagging EC branches. -# -# This script builds up on ideas put by vpalatin@ into util/getversion.sh -# -# Git allows to count number of patches between the current state of the tree -# and any directly preceding tag in the tree. That is if we tag the first -# patch in the current branch, we can tell how many patches are in the branch -# above that tag. And if we tag the branch such that the tag string includes -# the branch name, we can also say what branch we are in looking at the -# closest tag in the tree. -# -# This admittedly brittle script automates the process of tagging for the EC -# git tree in Chrome OS repo, but it could be used for any other Chrome OS -# repo git tree just as well. -# -# The script is brittle because it relies on the following assumptions which -# are true for Chrome OS repo at the time of writing: -# -# - the upstream branch alias name shows up in the 'git branch -a' output -# separated by -> -# - the upstream branch alias name has the format of -# cros/<branch name> -# - the remote git server name shows up in 'git config -l' output in the -# line starting with "remote.cros.url=" -# - firmware branch names have format of firmware-<board>-XXXXXX -# - the current branch was cut off of <remote name>/master -# -# The tag name generated by this script would be the XXXXX string with dots, -# if any, replaced by underscores. - -# Retrieve the upstream branch alias name -UPSTREAM="$(git branch -a | awk '/->/ {print $3}')" -if [[ -z "${UPSTREAM}" ]]; then - echo "Failed to determine upstream branch alias" >&2 - exit 1 -fi - -export ORIGIN_NAME="cros" -ORIGIN="$(git config "remote.${ORIGIN_NAME}.url")" - -# The last common patch between this branch and the master. -BRANCH_POINT="$(git merge-base "${UPSTREAM}" "${ORIGIN_NAME}/master")" -if [[ -z "${BRANCH_POINT}" ]]; then - echo "Failed to determine cros/master branch point" >&2 - exit 1 -fi - -# Derive tag base string from the upstream branch name as described above. -TAG_BASE="$(sed 's/.*-// # drop everything up to including the last - - s/\./_/g # replace dots and dashes with underscores - ' <<< "${UPSTREAM}" )" - -if [[ "${TAG_BASE}" == "master" ]]; then - echo "Nothing to tag in master branch" >&2 - exit 1 -fi - -TAG="v1.${TAG_BASE}.0" - -#SHA1 of the first patch of this branch -BASE_SHA="$(git rev-list --ancestry-path "${BRANCH_POINT}".."${UPSTREAM}" | - tail -1)" - -echo "Will run git tag -a -m \"firmware branch ${TAG}\" ${TAG} ${BASE_SHA}" -if git tag -a -m "firmware branch ${TAG}" "${TAG}" "${BASE_SHA}"; then - cat <<EOF - -A new tag '$TAG' has been set. Use the following command -to push it to the server - -git push --tags ${ORIGIN} ${TAG} - -Or if you want to delete it: - -git tag -d $TAG - -EOF -fi diff --git a/util/temp_metrics.conf b/util/temp_metrics.conf deleted file mode 100644 index ccd3254beb..0000000000 --- a/util/temp_metrics.conf +++ /dev/null @@ -1,396 +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. - -description "Temporary, quick-hack metrics collection & thermal daemon" -author "chromium-os-dev@chromium.org" - -# This is for quickly adding UMA stats that we may need for -# short-term experiments, when we don't have the time to add -# stuff to metrics_daemon. That's where it should go in the -# long term. -# -# This is also currently doing a userland thermal loop to allow -# for quick experimentation. This thermal loop will eventually -# move to the BIOS once the data from experiments help prove its -# efficacy. - -start on started system-services -stop on stopping system-services -respawn - -script - TEMP_OFFSET=273 # difference between K (reported by EC) and C (used in UMA) - - # Thermal loop fields - CPU_MAX_FREQ_FIELD=1 - CPU_MIN_FREQ_FIELD=2 - GPU_MAX_FREQ_FIELD=3 - CPU_DUTY_CYCLE_FIELD=4 - PKG_POWER_LIMIT_FIELD=5 - - # Thermal loop steps - all_steps=" - 1801000 800000 1150 0 0x180aa00dd8088 # no throttling - 1801000 800000 1150 0 0x180aa00dd8080 # cap pkg to 16W - 1801000 800000 1150 0 0x180aa00dd8078 # cap pkg to 15W - 1801000 800000 1150 0 0x180aa00dd8070 # cap pkg to 14W - 1801000 800000 1150 0 0x180aa00dd8068 # cap pkg to 13W - 1800000 800000 900 0 0x180aa00dd8068 # disable turbo - 1600000 800000 800 0 0x180aa00dd8068 # cap CPU & GPU frequency - 1400000 800000 700 0 0x180aa00dd8068 # cap CPU & GPU frequency - 1200000 800000 600 0 0x180aa00dd8068 # cap CPU & GPU frequency - 1000000 800000 500 0 0x180aa00dd8068 # cap CPU & GPU frequency - 800000 800000 400 0 0x180aa00dd8068 # cap CPU & GPU frequency - 800000 800000 350 0 0x180aa00dd8068 # cap CPU & GPU frequency - 800000 800000 350 0x1c 0x180aa00dd8068 # duty cycle CPU - 800000 800000 350 0x18 0x180aa00dd8068 # duty cycle CPU - " - max_steps=$(($(echo "$all_steps" | wc -l) - 3)) - - get_step() { - row=$(($1 + 2)) - out=$(echo "$all_steps" | awk "{if (NR==$row) print}") - echo "$out" - } - - get_field() { - out=$(echo "$2" | awk "{print \$$1}") - echo $out - } - - get_peci_temp() { - tempk=$(ectool temps 9 | sed 's/[^0-9]//g') - tempc=$((tempk - $TEMP_OFFSET)) - echo $tempc - } - - get_sensor_temp() { - s=$1 - tempc=0 - if out=$(ectool temps $s); then - tempk=$(echo $out | sed 's/[^0-9]//g') - tempc=$((tempk - $TEMP_OFFSET)) - fi - echo $tempc - } - - get_sensor_list() { - # USB C-Object: 1 or 13 - # PCH D-Object: 3 - # Hinge C-Object: 5 or 15 - # Charger D-Object: 7 - if ectool tempsinfo 1 | grep -q "USB C-Object"; then - usb_c_object=1 - else - usb_c_object=13 - fi - charger_d_object=7 - echo $usb_c_object $charger_d_object - } - - set_calibration_data() { - B0='-2.94e-5' - B1='-5.7e-7' - B2='4.63e-9' - - USB_C_S0='2.712e-14' - PCH_D_S0='9.301e-14' - HINGE_C_S0='-11.000e-14' - CHARGER_D_S0='5.141e-14' - - # Note that the sensor numbering is different between the ectool tmp006 - # and temps/tempsinfo commands. - USB_C="0 $USB_C_S0 $B0 $B1 $B2" - PCH_D="1 $PCH_D_S0 $B0 $B1 $B2" - HINGE_C="2 $HINGE_C_S0 $B0 $B1 $B2" - CHARGER_D="3 $CHARGER_D_S0 $B0 $B1 $B2" - - for i in "$USB_C" "$PCH_D" "$HINGE_C" "$CHARGER_D"; do - # Add "--" otherwise ectool will barf when trying to parse negative - # coefficients. - ectool tmp006cal -- $i - done - } - - max_skin_temp=0 - sensor_temperatures= - - get_max_skin_temp() { - sensor_temperatures= - max_skin_temp=0 - for i in $*; do - t=$(get_sensor_temp $i) - sensor_temperatures=$sensor_temperatures$i:$t: - if [ $t -gt $max_skin_temp ]; then - max_skin_temp=$t - fi - done - - # Record the PECI CPU temperature also. - i=9 - t=$(get_sensor_temp $i) - sensor_temperatures=$sensor_temperatures$i:$t: - } - - set_cpu_freq() { - max_freq=$1 - min_freq=$2 - for cpu in /sys/devices/system/cpu/cpu?/cpufreq; do - echo 800000 > $cpu/scaling_min_freq - echo 800000 > $cpu/scaling_max_freq - echo $max_freq > $cpu/scaling_max_freq - echo $min_freq > $cpu/scaling_min_freq - done - } - - set_gpu_min_freq() { - GPU_MIN_FREQ=450 - echo $GPU_MIN_FREQ > /sys/kernel/debug/dri/0/i915_min_freq - } - - set_gpu_max_freq() { - gpu_max_freq=$1 - if [ $GPU_MIN_FREQ -gt $gpu_max_freq ]; then - gpu_max_freq=$GPU_MIN_FREQ - fi - echo $gpu_max_freq > /sys/kernel/debug/dri/0/i915_max_freq - } - - set_duty_cycle() { - duty_cycle=$1 - for i in 0 1 2 3; do - iotools wrmsr $i 0x19a $duty_cycle - done - } - - set_pkg_power_limit() { - pwr_limit=$1 - iotools wrmsr 0 0x610 $pwr_limit - } - - log_message() { - logger -t temp_metrics "$*" - } - - TEMP_THRESHOLD_1=38 - TEMP_THRESHOLD_1_WM=40 - TEMP_THRESHOLD_2=45 - TEMP_THRESHOLD_2_WM=47 - TEMP_THRESHOLD_3=50 - TEMP_THRESHOLD_3_WM=50 - - TEMP_THRESHOLD_0_MIN_STEP=0 - TEMP_THRESHOLD_0_MAX_STEP=0 - TEMP_THRESHOLD_1_MIN_STEP=1 - TEMP_THRESHOLD_1_MAX_STEP=5 - TEMP_THRESHOLD_2_MIN_STEP=6 - TEMP_THRESHOLD_2_MAX_STEP=9 - TEMP_THRESHOLD_3_MIN_STEP=10 - TEMP_THRESHOLD_3_MAX_STEP=13 - - current_step=1 - new_step=0 - - thermal_loop() { - # Hack to reset turbo activation threshold since BIOS can change it - # underneath us. - iotools wrmsr 0 0x64c 0x12 - - skin_temp=$1 - if [ $skin_temp -gt $TEMP_THRESHOLD_3 ]; then - temp_watermark=$TEMP_THRESHOLD_3_WM - min_step=$TEMP_THRESHOLD_3_MIN_STEP - max_step=$TEMP_THRESHOLD_3_MAX_STEP - elif [ $skin_temp -gt $TEMP_THRESHOLD_2 ]; then - temp_watermark=$TEMP_THRESHOLD_2_WM - min_step=$TEMP_THRESHOLD_2_MIN_STEP - max_step=$TEMP_THRESHOLD_2_MAX_STEP - elif [ $skin_temp -gt $TEMP_THRESHOLD_1 ]; then - temp_watermark=$TEMP_THRESHOLD_1_WM - min_step=$TEMP_THRESHOLD_1_MIN_STEP - max_step=$TEMP_THRESHOLD_1_MAX_STEP - else - temp_watermark=0 - min_step=$TEMP_THRESHOLD_0_MIN_STEP - max_step=$TEMP_THRESHOLD_0_MAX_STEP - fi - - if [ $skin_temp -gt $temp_watermark ]; then - if [ $current_step -ne $max_step ]; then - new_step=$(($current_step + 1)) - fi - elif [ $skin_temp -lt $temp_watermark ]; then - if [ $current_step -gt $min_step ]; then - new_step=$(($current_step - 1)) - fi - else - new_step=$current_step - fi - - if [ $new_step -gt $max_step ]; then - new_step=$max_step - elif [ $new_step -lt $min_step ]; then - new_step=$min_step - fi - - if [ $new_step -eq $current_step ]; then - return - fi - - current_step=$new_step - step=$(get_step $new_step) - - log_message "Throttling (temps: $sensor_temperatures):" $step - - cpu_max_freq=$(get_field $CPU_MAX_FREQ_FIELD "$step") - cpu_min_freq=$(get_field $CPU_MIN_FREQ_FIELD "$step") - gpu_max_freq=$(get_field $GPU_MAX_FREQ_FIELD "$step") - cpu_duty_cycle=$(get_field $CPU_DUTY_CYCLE_FIELD "$step") - pkg_power_limit=$(get_field $PKG_POWER_LIMIT_FIELD "$step") - - set_cpu_freq $cpu_max_freq $cpu_min_freq - set_gpu_max_freq $gpu_max_freq - set_duty_cycle $cpu_duty_cycle - set_pkg_power_limit $pkg_power_limit - } - - get_fan_rpm() { - echo $(ectool pwmgetfanrpm | sed 's/[^0-9]//g') - } - - set_fan_rpm() { - ectool pwmsetfanrpm $1 - } - - reset_fan_thresholds() { - temp_low1=105 - temp_low2=105 - temp_low3=105 - temp_low4=105 - temp_low5=105 - temp_low6=105 - } - - last_rpm=10 - temp_low1=105 - temp_low2=105 - temp_low3=105 - temp_low4=105 - temp_low5=105 - temp_low6=105 - - fan_loop() { - skin_temp=$1 - - if [ $skin_temp -gt 48 ] || [ $skin_temp -gt $temp_low1 ]; then - rpm=9300 - reset_fan_thresholds - temp_low1=46 - elif [ $skin_temp -gt 44 ] || [ $skin_temp -gt $temp_low2 ]; then - rpm=8000 - reset_fan_thresholds - temp_low2=43 - elif [ $skin_temp -gt 42 ] || [ $skin_temp -gt $temp_low3 ]; then - rpm=7000 - reset_fan_thresholds - temp_low3=41 - elif [ $skin_temp -gt 40 ] || [ $skin_temp -gt $temp_low4 ]; then - rpm=5500 - reset_fan_thresholds - temp_low4=39 - elif [ $skin_temp -gt 38 ] || [ $skin_temp -gt $temp_low5 ]; then - rpm=4000 - reset_fan_thresholds - temp_low5=34 - elif [ $skin_temp -gt 33 ] || [ $skin_temp -gt $temp_low6 ]; then - rpm=3000 - reset_fan_thresholds - temp_low6=30 - else - rpm=0 - reset_fan_thresholds - fi - - # During S0->S3->S0 transitions, the EC sets the fan RPM to 0. This script - # isn't aware of such transitions. Read the current fan RPM again to see - # if it got set to 0. Note that comparing the current fan RPM against last - # requested RPM won't suffice since the actual fan RPM may not be exactly - # what was requested. - cur_rpm=$(get_fan_rpm) - if ([ $cur_rpm -ne 0 ] && [ $last_rpm -eq $rpm ]) || \ - ([ $cur_rpm -eq 0 ] && [ $rpm -eq 0 ]); then - last_rpm=$rpm - return - fi - - log_message "Setting fan RPM (temps: $sensor_temperatures): $last_rpm -> $rpm" - - last_rpm=$rpm - set_fan_rpm $rpm - } - - # Thermal zone 1 is for operating systems where a userland thermal loop - # doesn't exist. Disable it. - if [ -e /sys/class/thermal/thermal_zone1/mode ]; then - echo -n 'disabled' > /sys/class/thermal/thermal_zone1/mode - fi - - # Enable the fan in case no other code has enabled it. - ectool fanduty 0 - - # Get list of sensors to monitor. - sensor_list=$(get_sensor_list) - - # Set sensor calibration data. - set_calibration_data - - # Set minimum GPU frequency. - set_gpu_min_freq - - loop_count=0 - ec_fan_loop=0 - - while true; do - sleep 10 - loop_count=$(($loop_count + 1)) - - # Read the max skin temperature. - get_max_skin_temp $sensor_list - - if [ $max_skin_temp -eq 0 ]; then - if [ $ec_fan_loop -eq 0 ]; then - log_message "Invalid max skin temp. Switching to EC fan loop." - ectool autofanctrl - ec_fan_loop=1 - last_rpm=10 - fi - else - # Run the fan loop. - fan_loop $max_skin_temp - ec_fan_loop=0 - - # Run the thermal loop. - thermal_loop $max_skin_temp - fi - - # Report the metrics once every 30 seconds. - if [ $loop_count -lt 3 ]; then - continue - fi - loop_count=0 - - ectool temps all | while read line; do - index=$(printf "%02d" "${line%%:*}") - tempk="${line##* }" - tempc=$(($tempk - $TEMP_OFFSET)) - # ignore values below freezing - if [ $tempc -lt 0 ]; then - tempc=0 - fi - # Use a linear histogram with 1 C buckets starting at 0. - N_SLOTS=180 - metrics_client -e Platform.Temperature.Sensor$index $tempc $N_SLOTS - done - done -end script diff --git a/util/test-inject-keys.sh b/util/test-inject-keys.sh deleted file mode 100755 index 031452150e..0000000000 --- a/util/test-inject-keys.sh +++ /dev/null @@ -1,111 +0,0 @@ -#!/bin/bash -# -# 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. - -# Regression test for inject-keys.py. Works by creating a "fake" ectool -# and comparing expected ectool commands with expected ones. - -TMPX=/tmp/inject-key-test$$_x -TMPY=/tmp/inject-key-test$$_y - -cleanup() { - rm -f ./ectool $TMPX $TMPY -} - -fail() { - echo $* - exit 1 -} - -trap cleanup SIGINT - -PATH=.:$PATH - -if [ -e ectool ]; then - if [ "$(echo $(cat ectool))" != '#! /bin/bash echo $*' ]; then - echo "./ectool exists, please remove it to run this script" - exit 1 - fi -fi - -echo "#! /bin/bash" > ectool -echo 'echo $*' >> ectool -chmod a+x ectool - -# tests that should fail - -# bad args -./inject-keys.py >& /dev/null && fail "undetected zero args" -./inject-keys.py -k >& /dev/null && fail "undetected mismatched args (1)" -./inject-keys.py -k a b >& /dev/null && fail "undetected mismatched args (2)" -./inject-keys.py -z a >& /dev/null && fail "undetected bad flag" - -# bad key -./inject-keys.py -p foobar >& /dev/null && fail "undetected bad key" - -# tests that should succeed with the expected output - -# simple string -./inject-keys.py -s abcd > $TMPX - -cat > $TMPY <<EOF -kbpress 4 1 1 -kbpress 4 1 0 -kbpress 0 3 1 -kbpress 0 3 0 -kbpress 5 2 1 -kbpress 5 2 0 -kbpress 4 2 1 -kbpress 4 2 0 -EOF - -cmp $TMPX $TMPY || fail $TMPX and $TMPY differ - -# string with shifted characters -./inject-keys.py -s A@%Bx > $TMPX - -cat > $TMPY <<EOF -kbpress 5 7 1 -kbpress 4 1 1 -kbpress 4 1 0 -kbpress 5 7 0 -kbpress 5 7 1 -kbpress 6 4 1 -kbpress 6 4 0 -kbpress 5 7 0 -kbpress 5 7 1 -kbpress 3 3 1 -kbpress 3 3 0 -kbpress 5 7 0 -kbpress 5 7 1 -kbpress 0 3 1 -kbpress 0 3 0 -kbpress 5 7 0 -kbpress 5 4 1 -kbpress 5 4 0 -EOF - -cmp $TMPX $TMPY || fail $TMPX and $TMPY differ - -# keystroke injection -./inject-keys.py -k enter > $TMPX - -cat > $TMPY <<EOF -kbpress 4 11 1 -kbpress 4 11 0 -EOF - -cmp $TMPX $TMPY || fail $TMPX and $TMPY differ - -# key event injection -./inject-keys.py -p enter > $TMPX - -cat > $TMPY <<EOF -kbpress 4 11 1 -EOF - -cmp $TMPX $TMPY || fail $TMPX and $TMPY differ - -cleanup diff --git a/util/test_kconfig_check.py b/util/test_kconfig_check.py deleted file mode 100644 index 0426dc3e6f..0000000000 --- a/util/test_kconfig_check.py +++ /dev/null @@ -1,154 +0,0 @@ -# Copyright 2021 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. -"""Test for Kconfig checker""" - -import contextlib -import io -import os -import re -import sys -import tempfile -import unittest - -import kconfig_check - -# Prefix that we strip from each Kconfig option, when considering whether it is -# equivalent to a CONFIG option with the same name -PREFIX = 'PLATFORM_EC_' - -@contextlib.contextmanager -def capture_sys_output(): - """Capture output for testing purposes - - Use this to suppress stdout/stderr output: - with capture_sys_output() as (stdout, stderr) - ...do something... - """ - capture_out, capture_err = io.StringIO(), io.StringIO() - old_out, old_err = sys.stdout, sys.stderr - try: - sys.stdout, sys.stderr = capture_out, capture_err - yield capture_out, capture_err - finally: - sys.stdout, sys.stderr = old_out, old_err - - -# Use unittest since it produced less verbose output than pytest and can be run -# directly from Python. You can still run this test with 'pytest' if you like. -class KconfigCheck(unittest.TestCase): - """Tests for the KconfigCheck class""" - def test_simple_check(self): - """Check it detected a new ad-hoc CONFIG""" - checker = kconfig_check.KconfigCheck() - self.assertEqual(['NEW_ONE'], checker.find_new_adhoc( - configs=['NEW_ONE', 'OLD_ONE', 'IN_KCONFIG'], - kconfigs=['IN_KCONFIG'], - allowed=['OLD_ONE'])) - - def test_sorted_check(self): - """Check it sorts the results in order""" - checker = kconfig_check.KconfigCheck() - self.assertSequenceEqual( - ['ANOTHER_NEW_ONE', 'NEW_ONE'], - checker.find_new_adhoc( - configs=['NEW_ONE', 'ANOTHER_NEW_ONE', 'OLD_ONE', 'IN_KCONFIG'], - kconfigs=['IN_KCONFIG'], - allowed=['OLD_ONE'])) - - def test_read_configs(self): - """Test KconfigCheck.read_configs()""" - checker = kconfig_check.KconfigCheck() - with tempfile.NamedTemporaryFile() as configs: - with open(configs.name, 'w') as out: - out.write("""CONFIG_OLD_ONE=y -NOT_A_CONFIG -CONFIG_STRING="something" -CONFIG_INT=123 -CONFIG_HEX=45ab -""") - self.assertEqual(['OLD_ONE', 'STRING', 'INT', 'HEX'], - checker.read_configs(configs.name)) - - @classmethod - def setup_srctree(cls, srctree): - """Set up some Kconfig files in a directory and subdirs - - Args: - srctree: Directory to write to - """ - with open(os.path.join(srctree, 'Kconfig'), 'w') as out: - out.write('config PLATFORM_EC_MY_KCONFIG\n') - subdir = os.path.join(srctree, 'subdir') - os.mkdir(subdir) - with open(os.path.join(subdir, 'Kconfig.wibble'), 'w') as out: - out.write('menuconfig PLATFORM_EC_MENU_KCONFIG\n') - - # Add a directory which should be ignored - bad_subdir = os.path.join(subdir, 'Kconfig') - os.mkdir(bad_subdir) - with open(os.path.join(bad_subdir, 'Kconfig.bad'), 'w') as out: - out.write('menuconfig PLATFORM_EC_BAD_KCONFIG') - - def test_find_kconfigs(self): - """Test KconfigCheck.find_kconfigs()""" - checker = kconfig_check.KconfigCheck() - with tempfile.TemporaryDirectory() as srctree: - self.setup_srctree(srctree) - files = checker.find_kconfigs(srctree) - fnames = [fname[len(srctree):] for fname in files] - self.assertEqual(['/Kconfig', '/subdir/Kconfig.wibble'], fnames) - - def test_scan_kconfigs(self): - """Test KconfigCheck.scan_configs()""" - checker = kconfig_check.KconfigCheck() - with tempfile.TemporaryDirectory() as srctree: - self.setup_srctree(srctree) - self.assertEqual(['MY_KCONFIG', 'MENU_KCONFIG'], - checker.scan_kconfigs(srctree, PREFIX)) - - @classmethod - def setup_allowed_and_configs(cls, allowed_fname, configs_fname): - """Set up the 'allowed' and 'configs' files for tests - - Args: - allowed_fname: Filename to write allowed CONFIGs to - configs_fname: Filename to which CONFIGs to check should be written - """ - with open(allowed_fname, 'w') as out: - out.write('CONFIG_OLD_ONE') - with open(configs_fname, 'w') as out: - out.write('\n'.join(['CONFIG_OLD_ONE', 'CONFIG_NEW_ONE', - 'CONFIG_MY_KCONFIG'])) - - def test_find_new_adhoc_configs(self): - """Test KconfigCheck.find_new_adhoc_configs()""" - checker = kconfig_check.KconfigCheck() - with tempfile.TemporaryDirectory() as srctree: - self.setup_srctree(srctree) - with tempfile.NamedTemporaryFile() as allowed: - with tempfile.NamedTemporaryFile() as configs: - self.setup_allowed_and_configs(allowed.name, configs.name) - result = checker.find_new_adhoc_configs( - configs.name, srctree, allowed.name, PREFIX) - self.assertEqual(['NEW_ONE'], result) - - def test_check(self): - """Test running the 'check' subcommand""" - with capture_sys_output() as (stdout, stderr): - with tempfile.TemporaryDirectory() as srctree: - self.setup_srctree(srctree) - with tempfile.NamedTemporaryFile() as allowed: - with tempfile.NamedTemporaryFile() as configs: - self.setup_allowed_and_configs(allowed.name, configs.name) - ret_code = kconfig_check.main( - ['-c', configs.name, '-s', srctree, - '-a', allowed.name, '-p', PREFIX, 'check']) - self.assertEqual(1, ret_code) - self.assertEqual('', stdout.getvalue()) - found = re.findall('(CONFIG_.*)', stderr.getvalue()) - self.assertEqual(['CONFIG_NEW_ONE'], found) - - -if __name__ == '__main__': - unittest.main() diff --git a/util/uart_stress_tester.py b/util/uart_stress_tester.py deleted file mode 100755 index b3db60060e..0000000000 --- a/util/uart_stress_tester.py +++ /dev/null @@ -1,562 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# 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. -# -# Ignore indention messages, since legacy scripts use 2 spaces instead of 4. -# pylint: disable=bad-indentation,docstring-section-indent -# pylint: disable=docstring-trailing-quotes - -"""ChromeOS Uart Stress Test - -This tester runs the command 'chargen' on EC and/or AP, captures the -output, and compares it against the expected output to check any characters -lost. - -Prerequisite: - (1) This test needs PySerial. Please check if it is available before test. - Can be installed by 'pip install pyserial' - (2) If servod is running, turn uart_timestamp off before running this test. - e.g. dut-control cr50_uart_timestamp:off -""" - -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function - -import argparse -import atexit -import logging -import os -import stat -import sys -import threading -import time - -import serial - -BAUDRATE = 115200 # Default baudrate setting for UART port -CROS_USERNAME = 'root' # Account name to login to ChromeOS -CROS_PASSWORD = 'test0000' # Password to login to ChromeOS -CHARGEN_TXT = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' - # The result of 'chargen 62 62' -CHARGEN_TXT_LEN = len(CHARGEN_TXT) -CR = '\r' # Carriage Return -LF = '\n' # Line Feed -CRLF = CR + LF -FLAG_FILENAME = '/tmp/chargen_testing' -TPM_CMD = ('trunks_client --key_create --rsa=2048 --usage=sign' - ' --key_blob=/tmp/blob &> /dev/null') - # A ChromeOS TPM command for the cr50 stress - # purpose. -CR50_LOAD_GEN_CMD = ('while [[ -f %s ]]; do %s; done &' - % (FLAG_FILENAME, TPM_CMD)) - # A command line to run TPM_CMD in background - # infinitely. - - -class ChargenTestError(Exception): - """Exception for Uart Stress Test Error""" - pass - - -class UartSerial(object): - """Test Object for a single UART serial device - - Attributes: - UART_DEV_PROFILES - char_loss_occurrences: Number that character loss happens - cleanup_cli: Command list to perform before the test exits - cr50_workload: True if cr50 should be stressed, or False otherwise - usb_output: True if output should be generated to USB channel - dev_prof: Dictionary of device profile - duration: Time to keep chargen running - eol: Characters to add at the end of input - logger: object that store the log - num_ch_exp: Expected number of characters in output - num_ch_cap: Number of captured characters in output - test_cli: Command list to run for chargen test - test_thread: Thread object that captures the UART output - serial: serial.Serial object - """ - UART_DEV_PROFILES = ( - # Kernel - { - 'prompt':'localhost login:', - 'device_type':'AP', - 'prepare_cmd':[ - CROS_USERNAME, # Login - CROS_PASSWORD, # Password - 'dmesg -D', # Disable console message - 'touch ' + FLAG_FILENAME, # Create a temp file - ], - 'cleanup_cmd':[ - 'rm -f ' + FLAG_FILENAME, # Remove the temp file - 'dmesg -E', # Enable console message - 'logout', # Logout - ], - 'end_of_input':LF, - }, - # EC - { - 'prompt':'> ', - 'device_type':'EC', - 'prepare_cmd':[ - 'chan save', - 'chan 0' # Disable console message - ], - 'cleanup_cmd':['', 'chan restore'], - 'end_of_input':CRLF, - }, - ) - - def __init__(self, port, duration, timeout=1, - baudrate=BAUDRATE, cr50_workload=False, - usb_output=False): - """Initialize UartSerial - - Args: - port: UART device path. e.g. /dev/ttyUSB0 - duration: Time to test, in seconds - timeout: Read timeout value. - baudrate: Baud rate such as 9600 or 115200. - cr50_workload: True if a workload should be generated on cr50 - usb_output: True if a workload should be generated to USB channel - """ - - # Initialize serial object - self.serial = serial.Serial() - self.serial.port = port - self.serial.timeout = timeout - self.serial.baudrate = baudrate - - self.duration = duration - self.cr50_workload = cr50_workload - self.usb_output = usb_output - - self.logger = logging.getLogger(type(self).__name__ + '| ' + port) - self.test_thread = threading.Thread(target=self.stress_test_thread) - - self.dev_prof = {} - self.cleanup_cli = [] - self.test_cli = [] - self.eol = CRLF - self.num_ch_exp = 0 - self.num_ch_cap = 0 - self.char_loss_occurrences = 0 - atexit.register(self.cleanup) - - def run_command(self, command_lines, delay=0): - """Run command(s) at UART prompt - - Args: - command_lines: list of commands to run. - delay: delay after a command in second - """ - for cli in command_lines: - self.logger.debug('run %r', cli) - - self.serial.write((cli + self.eol).encode()) - self.serial.flush() - if delay: - time.sleep(delay) - - def cleanup(self): - """Before termination, clean up the UART device.""" - self.logger.debug('Closing...') - - self.serial.open() - self.run_command(self.cleanup_cli) # Run cleanup commands - self.serial.close() - - self.logger.debug('Cleanup done') - - def get_output(self): - """Capture the UART output - - Args: - stop_char: Read output buffer until it reads stop_char. - - Returns: - text from UART output. - """ - if self.serial.inWaiting() == 0: - time.sleep(1) - - return self.serial.read(self.serial.inWaiting()).decode() - - def prepare(self): - """Prepare the test: - - Identify the type of UART device (EC or Kernel?), then - decide what kind of commands to use to generate stress loads. - - Raises: - ChargenTestError if UART source can't be identified. - """ - try: - self.logger.info('Preparing...') - - self.serial.open() - - # Prepare the device for test - self.serial.flushInput() - self.serial.flushOutput() - - self.get_output() # drain data - - # Give a couple of line feeds, and capture the prompt text - self.run_command(['', '']) - prompt_txt = self.get_output() - - # Detect the device source: EC or AP? - # Detect if the device is AP or EC console based on the captured. - for dev_prof in self.UART_DEV_PROFILES: - if dev_prof['prompt'] in prompt_txt: - self.dev_prof = dev_prof - break - else: - # No prompt patterns were found. UART seems not responding or in - # an undesirable status. - if prompt_txt: - raise ChargenTestError('%s: Got an unknown prompt text: %s\n' - 'Check manually whether %s is available.' % - (self.serial.port, prompt_txt, - self.serial.port)) - else: - raise ChargenTestError('%s: Got no input. Close any other connections' - ' to this port, and try it again.' % - self.serial.port) - - self.logger.info('Detected as %s UART', self.dev_prof['device_type']) - # Log displays the UART type (AP|EC) instead of device filename. - self.logger = logging.getLogger(type(self).__name__ + '| ' + - self.dev_prof['device_type']) - - # Either login to AP or run some commands to prepare the device - # for test - self.eol = self.dev_prof['end_of_input'] - self.run_command(self.dev_prof['prepare_cmd'], delay=2) - self.cleanup_cli += self.dev_prof['cleanup_cmd'] - - # 'chargen' of AP does not have option for USB output. - # Force it work on UART. - if self.dev_prof['device_type'] == 'AP': - self.usb_output = False - - # Check whether the command 'chargen' is available in the device. - # 'chargen 1 4' is supposed to print '0000' - self.get_output() # drain data - - chargen_cmd = 'chargen 1 4' - if self.usb_output: - chargen_cmd += ' usb' - self.run_command([chargen_cmd]) - tmp_txt = self.get_output() - - # Check whether chargen command is available. - if '0000' not in tmp_txt: - raise ChargenTestError('%s: Chargen got an unexpected result: %s' % - (self.dev_prof['device_type'], tmp_txt)) - - self.num_ch_exp = int(self.serial.baudrate * self.duration / 10) - chargen_cmd = 'chargen ' + str(CHARGEN_TXT_LEN) + ' ' + \ - str(self.num_ch_exp) - if self.usb_output: - chargen_cmd += ' usb' - self.test_cli = [chargen_cmd] - - self.logger.info('Ready to test') - finally: - self.serial.close() - - def stress_test_thread(self): - """Test thread - - Raises: - ChargenTestError: if broken character is found. - """ - try: - self.serial.open() - self.serial.flushInput() - self.serial.flushOutput() - - # Run TPM command in background to burden cr50. - if self.dev_prof['device_type'] == 'AP' and self.cr50_workload: - self.run_command([CR50_LOAD_GEN_CMD]) - self.logger.debug('run TPM job while %s exists', FLAG_FILENAME) - - # Run the command 'chargen', one time - self.run_command(['']) # Give a line feed - self.get_output() # Drain the output - self.run_command(self.test_cli) - self.serial.readline() # Drain the echoed command line. - - err_msg = '%s: Expected %r but got %s after %d char received' - - # Keep capturing the output until the test timer is expired. - self.num_ch_cap = 0 - self.char_loss_occurrences = 0 - data_starve_count = 0 - - total_num_ch = self.num_ch_exp # Expected number of characters in total - ch_exp = CHARGEN_TXT[0] - ch_cap = 'z' # any character value is ok for loop initial condition. - while self.num_ch_cap < total_num_ch: - captured = self.get_output() - - if captured: - # There is some output data. Reset the data starvation count. - data_starve_count = 0 - else: - data_starve_count += 1 - if data_starve_count > 1: - # If nothing was captured more than once, then terminate the test. - self.logger.debug('No more output') - break - - for ch_cap in captured: - if ch_cap not in CHARGEN_TXT: - # If it is not alpha-numeric, terminate the test. - if ch_cap not in CRLF: - # If it is neither a CR nor LF, then it is an error case. - self.logger.error('Whole captured characters: %r', captured) - raise ChargenTestError(err_msg % ('Broken char captured', ch_exp, - hex(ord(ch_cap)), - self.num_ch_cap)) - - # Set the loop termination condition true. - total_num_ch = self.num_ch_cap - - if self.num_ch_cap >= total_num_ch: - break - - if ch_exp != ch_cap: - # If it is alpha-numeric but not continuous, then some characters - # are lost. - self.logger.error(err_msg, 'Char loss detected', - ch_exp, repr(ch_cap), self.num_ch_cap) - self.char_loss_occurrences += 1 - - # Recalculate the expected number of characters to adjust - # termination condition. The loss might be bigger than this - # adjustment, but it is okay since it will terminates by either - # CR/LF detection or by data starvation. - idx_ch_exp = CHARGEN_TXT.find(ch_exp) - idx_ch_cap = CHARGEN_TXT.find(ch_cap) - if idx_ch_cap < idx_ch_exp: - idx_ch_cap += len(CHARGEN_TXT) - total_num_ch -= (idx_ch_cap - idx_ch_exp) - - self.num_ch_cap += 1 - - # Determine What character is expected next? - ch_exp = CHARGEN_TXT[(CHARGEN_TXT.find(ch_cap) + 1) % CHARGEN_TXT_LEN] - - finally: - self.serial.close() - - def start_test(self): - """Start the test thread""" - self.logger.info('Test thread starts') - self.test_thread.start() - - def wait_test_done(self): - """Wait until the test thread get done and join""" - self.test_thread.join() - self.logger.info('Test thread is done') - - def get_result(self): - """Display the result - - Returns: - Integer = the number of lost character - - Raises: - ChargenTestError: if the capture is corrupted. - """ - # If more characters than expected are captured, it means some messages - # from other than chargen are mixed. Stop processing further. - if self.num_ch_exp < self.num_ch_cap: - raise ChargenTestError('%s: UART output is corrupted.' % - self.dev_prof['device_type']) - - # Get the count difference between the expected to the captured - # as the number of lost character. - char_lost = self.num_ch_exp - self.num_ch_cap - self.logger.info('%8d char lost / %10d (%.1f %%)', - char_lost, self.num_ch_exp, - char_lost * 100.0 / self.num_ch_exp) - - return char_lost, self.num_ch_exp, self.char_loss_occurrences - - -class ChargenTest(object): - """UART stress tester - - Attributes: - logger: logging object - serials: Dictionary where key is filename of UART device, and the value is - UartSerial object - """ - - def __init__(self, ports, duration, cr50_workload=False, - usb_output=False): - """Initialize UART stress tester - - Args: - ports: List of UART ports to test. - duration: Time to keep testing in seconds. - cr50_workload: True if a workload should be generated on cr50 - usb_output: True if a workload should be generated to USB channel - - Raises: - ChargenTestError: if any of ports is not a valid character device. - """ - - # Save the arguments - for port in ports: - try: - mode = os.stat(port).st_mode - except OSError as e: - raise ChargenTestError(e) - if not stat.S_ISCHR(mode): - raise ChargenTestError('%s is not a character device.' % port) - - if duration <= 0: - raise ChargenTestError('Input error: duration is not positive.') - - # Initialize logging object - self.logger = logging.getLogger(type(self).__name__) - - # Create an UartSerial object per UART port - self.serials = {} # UartSerial objects - for port in ports: - self.serials[port] = UartSerial(port=port, duration=duration, - cr50_workload=cr50_workload, - usb_output=usb_output) - - def prepare(self): - """Prepare the test for each UART port""" - self.logger.info('Prepare ports for test') - for _, ser in self.serials.items(): - ser.prepare() - self.logger.info('Ports are ready to test') - - def print_result(self): - """Display the test result for each UART port - - Returns: - char_lost: Total number of characters lost - """ - char_lost = 0 - for _, ser in self.serials.items(): - (tmp_lost, _, _) = ser.get_result() - char_lost += tmp_lost - - # If any characters are lost, then test fails. - msg = 'lost %d character(s) from the test' % char_lost - if char_lost > 0: - self.logger.error('FAIL: %s', msg) - else: - self.logger.info('PASS: %s', msg) - - return char_lost - - def run(self): - """Run the stress test on UART port(s) - - Raises: - ChargenTestError: If any characters are lost. - """ - - # Detect UART source type, and decide which command to test. - self.prepare() - - # Run the test on each UART port in thread. - self.logger.info('Test starts') - for _, ser in self.serials.items(): - ser.start_test() - - # Wait all tests to finish. - for _, ser in self.serials.items(): - ser.wait_test_done() - - # Print the result. - char_lost = self.print_result() - if char_lost: - raise ChargenTestError('Test failed: lost %d character(s)' % - char_lost) - - self.logger.info('Test is done') - -def parse_args(cmdline): - """Parse command line arguments. - - Args: - cmdline: list to be parsed - - Returns: - tuple (options, args) where args is a list of cmdline arguments that the - parser was unable to match i.e. they're servod controls, not options. - """ - description = """%(prog)s repeats sending a uart console command -to each UART device for a given time, and check if output -has any missing characters. - -Examples: - %(prog)s /dev/ttyUSB2 --time 3600 - %(prog)s /dev/ttyUSB1 /dev/ttyUSB2 --debug - %(prog)s /dev/ttyUSB1 /dev/ttyUSB2 --cr50 -""" - - parser = argparse.ArgumentParser(description=description, - formatter_class=argparse.RawTextHelpFormatter - ) - parser.add_argument('port', type=str, nargs='*', - help='UART device path to test') - parser.add_argument('-c', '--cr50', action='store_true', default=False, - help='generate TPM workload on cr50') - parser.add_argument('-d', '--debug', action='store_true', default=False, - help='enable debug messages') - parser.add_argument('-t', '--time', type=int, - help='Test duration in second', default=300) - parser.add_argument('-u', '--usb', action='store_true', default=False, - help='Generate output to USB channel instead') - return parser.parse_known_args(cmdline) - - -def main(): - """Main function wrapper""" - try: - (options, _) = parse_args(sys.argv[1:]) - - # Set Log format - log_format = '%(asctime)s %(levelname)-6s | %(name)-25s' - date_format = '%Y-%m-%d %H:%M:%S' - if options.debug: - log_format += ' | %(filename)s:%(lineno)4d:%(funcName)-18s' - loglevel = logging.DEBUG - else: - loglevel = logging.INFO - log_format += ' | %(message)s' - - logging.basicConfig(level=loglevel, format=log_format, - datefmt=date_format) - - # Create a ChargenTest object - utest = ChargenTest(options.port, options.time, - cr50_workload=options.cr50, - usb_output=options.usb) - utest.run() # Run - - except KeyboardInterrupt: - sys.exit(0) - - except ChargenTestError as e: - logging.error(str(e)) - sys.exit(1) - -if __name__ == '__main__': - main() diff --git a/util/unpack_ftb.py b/util/unpack_ftb.py deleted file mode 100755 index 03127a7089..0000000000 --- a/util/unpack_ftb.py +++ /dev/null @@ -1,122 +0,0 @@ -#!/usr/bin/env python -# 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. -# -# Ignore indention messages, since legacy scripts use 2 spaces instead of 4. -# pylint: disable=bad-indentation,docstring-section-indent -# pylint: disable=docstring-trailing-quotes - -# Note: This is a py2/3 compatible file. - -from __future__ import print_function -import argparse -import ctypes -import os - - -class Header(ctypes.Structure): - _pack_ = 1 - _fields_ = [ - ('signature', ctypes.c_uint32), - ('ftb_ver', ctypes.c_uint32), - ('chip_id', ctypes.c_uint32), - ('svn_ver', ctypes.c_uint32), - ('fw_ver', ctypes.c_uint32), - ('config_id', ctypes.c_uint32), - ('config_ver', ctypes.c_uint32), - ('reserved', ctypes.c_uint8 * 8), - ('release_info', ctypes.c_ulonglong), - ('sec_size', ctypes.c_uint32 * 4), - ('crc', ctypes.c_uint32), - ] - -FW_HEADER_SIZE = 64 -FW_HEADER_SIGNATURE = 0xAA55AA55 -FW_FTB_VER = 0x00000001 -FW_CHIP_ID = 0x3936 -FW_BYTES_ALIGN = 4 -FW_BIN_VER_OFFSET = 16 -FW_BIN_CONFIG_ID_OFFSET = 20 - -# Starting address in flash for each section -FLASH_SEC_ADDR = [ - 0x0000 * 4, # CODE - 0x7C00 * 4, # CONFIG - 0x7000 * 4, # CX - None # This section shouldn't exist -] - -UPDATE_PDU_SIZE = 4096 - -# Bin file format: -# FTB header (padded to `UPDATE_PDU_SIZE`) -# Flash sections -# CODE -# CX -# CONFIG -OUTPUT_FILE_SIZE = UPDATE_PDU_SIZE + 128 * 1024 - - -def main(): - parser = argparse.ArgumentParser() - parser.add_argument('--input', '-i', required=True) - parser.add_argument('--output', '-o', required=True) - args = parser.parse_args() - - with open(args.input, 'rb') as f: - bs = f.read() - - size = len(bs) - if size < FW_HEADER_SIZE + FW_BYTES_ALIGN: - raise Exception('FW size too small') - - print('FTB file size:', size) - - header = Header() - assert ctypes.sizeof(header) == FW_HEADER_SIZE - - ctypes.memmove(ctypes.addressof(header), bs, ctypes.sizeof(header)) - if (header.signature != FW_HEADER_SIGNATURE or - header.ftb_ver != FW_FTB_VER or - header.chip_id != FW_CHIP_ID): - raise Exception('Invalid header') - - for key, _ in header._fields_: - v = getattr(header, key) - if isinstance(v, ctypes.Array): - print(key, list(map(hex, v))) - else: - print(key, hex(v)) - - dimension = sum(header.sec_size) - - assert dimension + FW_HEADER_SIZE + FW_BYTES_ALIGN == size - data = bs[FW_HEADER_SIZE:FW_HEADER_SIZE + dimension] - - with open(args.output, 'wb') as f: - # ensure the file size - f.seek(OUTPUT_FILE_SIZE - 1, os.SEEK_SET) - f.write(b'\x00') - - f.seek(0, os.SEEK_SET) - f.write(bs[0 : ctypes.sizeof(header)]) - - offset = 0 - # write each sections - for i, addr in enumerate(FLASH_SEC_ADDR): - size = header.sec_size[i] - assert addr is not None or size == 0 - - if size == 0: - continue - - f.seek(UPDATE_PDU_SIZE + addr, os.SEEK_SET) - f.write(data[offset : offset + size]) - offset += size - - f.flush() - - -if __name__ == '__main__': - main() diff --git a/util/update_release_branch.py b/util/update_release_branch.py deleted file mode 100755 index 222c7b01ba..0000000000 --- a/util/update_release_branch.py +++ /dev/null @@ -1,260 +0,0 @@ -#!/usr/bin/env python3 -# Copyright 2021 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. -"""Release branch updater tool. - -This is a tool to merge from the main branch into a release branch. - -Inspired by the fingerprint release process: -http://go/cros-fingerprint-firmware-branching-and-signing and now used by other -boards. -""" -from __future__ import print_function -import argparse -import os -import re -import subprocess -import sys -import textwrap - -BUG_NONE_PATTERN = re.compile('none', flags=re.IGNORECASE) - - -def git_commit_msg(branch, head, merge_head, rel_paths): - """Generates a merge commit message based off of relevant changes. - - This function obtains the relevant commits from the given relative paths in - order to extract the bug numbers. It constructs the git commit message - showing the command used to find the relevant commits. - - Args: - branch: String indicating the release branch name - head: String indicating the HEAD refspec - merge_head: String indicating the merge branch refspec. - rel_paths: String containing all the relevant paths for this particular - baseboard or board. - - Returns: - A String containing the git commit message with the exception of the - Signed-Off-By field and Change-ID field. - """ - relevant_commits_cmd, relevant_commits = get_relevant_commits(head, - merge_head, - '--oneline', - rel_paths) - - _, relevant_bugs = get_relevant_commits(head, merge_head, '', rel_paths) - relevant_bugs = set(re.findall('BUG=(.*)', relevant_bugs)) - # Filter out "none" from set of bugs - filtered = [] - for bug_line in relevant_bugs: - bug_line = bug_line.replace(',', ' ') - bugs = bug_line.split(' ') - for bug in bugs: - if bug and not BUG_NONE_PATTERN.match(bug): - filtered.append(bug) - relevant_bugs = filtered - - # TODO(b/179509333): remove Cq-Include-Trybots line when regular CQ and - # firmware CQ do not behave differently. - COMMIT_MSG_TEMPLATE = """ -Merge remote-tracking branch cros/main into {BRANCH} - -Relevant changes: - -{RELEVANT_COMMITS_CMD} - -{RELEVANT_COMMITS} - -BRANCH=None -{BUG_FIELD} -TEST=`make -j buildall` - -Cq-Include-Trybots: chromeos/cq:cq-orchestrator -""" - # Wrap the relevant commits command and bug field such that we don't exceed - # 72 cols. - relevant_commits_cmd = textwrap.fill(relevant_commits_cmd, width=72) - # Wrap at 68 cols to save room for 'BUG=' - bugs = textwrap.wrap(' '.join(relevant_bugs), width=68) - bug_field = '' - for line in bugs: - bug_field += 'BUG=' + line + '\n' - # Remove the final newline since the template adds it for us. - bug_field = bug_field[:-1] - - return COMMIT_MSG_TEMPLATE.format(BRANCH=branch, - RELEVANT_COMMITS_CMD=relevant_commits_cmd, - RELEVANT_COMMITS=relevant_commits, - BUG_FIELD=bug_field) - - -def get_relevant_boards(baseboard): - """Searches through the EC repo looking for boards that use the given - baseboard. - - Args: - baseboard: String containing the baseboard to consider - - Returns: - A list of strings containing the boards based off of the baseboard. - """ - proc = subprocess.run(['git', 'grep', 'BASEBOARD:=' + baseboard, '--', - 'board/'], - stdout=subprocess.PIPE, - encoding='utf-8', - check=True) - boards = [] - res = proc.stdout.splitlines() - for line in res: - boards.append(line.split('/')[1]) - return boards - - -def get_relevant_commits(head, merge_head, fmt, relevant_paths): - """Searches git history to find changes since the last merge which modify - files present in relevant_paths. - - Args: - head: String indicating the HEAD refspec - merge_head: String indicating the merge branch refspec. - fmt: An optional string containing the format option for `git log` - relevant_paths: String containing all the relevant paths for this - particular baseboard or board. - - Returns: - A tuple containing the arguments passed to the git log command and - stdout. - """ - if fmt: - cmd = ['git', 'log', fmt, head + '..' + merge_head, '--', - relevant_paths] - else: - cmd = ['git', 'log', head + '..' + merge_head, '--', relevant_paths] - - # Pass cmd as a string to subprocess.run() since we need to run with shell - # equal to True. The reason we are using shell equal to True is to take - # advantage of the glob expansion for the relevant paths. - cmd = ' '.join(cmd) - proc = subprocess.run(cmd, - stdout=subprocess.PIPE, - encoding='utf-8', - check=True, - shell=True) - return ''.join(proc.args), proc.stdout - - -def main(argv): - """Generates a merge commit from ToT to a desired release branch. - - For the commit message, it finds all the commits that have modified a - relevant path. By default this is the baseboard or board directory. The - user may optionally specify a path to a text file which contains a longer - list of relevant files. The format should be in the glob syntax that git - log expects. - - Args: - argv: A list of the command line arguments passed to this script. - """ - # Set up argument parser. - parser = argparse.ArgumentParser(description=("A script that generates a " - "merge commit from cros/main" - " to a desired release " - "branch. By default, the " - "'recursive' merge strategy " - "with the 'theirs' strategy " - "option is used.")) - parser.add_argument('--baseboard') - parser.add_argument('--board') - parser.add_argument('release_branch', help=('The name of the target release' - ' branch')) - parser.add_argument('--relevant_paths_file', - help=('A path to a text file which includes other ' - 'relevant paths of interest for this board ' - 'or baseboard')) - parser.add_argument('--merge_strategy', '-s', default='recursive', - help='The merge strategy to pass to `git merge -s`') - parser.add_argument('--strategy_option', '-X', - help=('The strategy option for the chosen merge ' - 'strategy')) - - opts = parser.parse_args(argv) - - baseboard_dir = '' - board_dir = '' - - if opts.baseboard: - # Dereference symlinks so "git log" works as expected. - baseboard_dir = os.path.relpath('baseboard/' + opts.baseboard) - baseboard_dir = os.path.relpath(os.path.realpath(baseboard_dir)) - - boards = get_relevant_boards(opts.baseboard) - elif opts.board: - board_dir = os.path.relpath('board/' + opts.board) - board_dir = os.path.relpath(os.path.realpath(board_dir)) - boards = [opts.board] - else: - parser.error('You must specify a board OR a baseboard') - - print("Gathering relevant paths...") - relevant_paths = [] - if opts.baseboard: - relevant_paths.append(baseboard_dir) - else: - relevant_paths.append(board_dir) - - for board in boards: - relevant_paths.append('board/' + board) - - # Check for the existence of a file that has other paths of interest. - if opts.relevant_paths_file and os.path.exists(opts.relevant_paths_file): - with open(opts.relevant_paths_file, 'r') as relevant_paths_file: - for line in relevant_paths_file: - if not line.startswith('#'): - relevant_paths.append(line.rstrip()) - relevant_paths.append('util/getversion.sh') - relevant_paths = ' '.join(relevant_paths) - - # Now that we have the paths of interest, let's perform the merge. - print("Updating remote...") - subprocess.run(['git', 'remote', 'update'], check=True) - subprocess.run(['git', 'checkout', '-B', opts.release_branch, 'cros/' + - opts.release_branch], check=True) - print("Attempting git merge...") - if opts.merge_strategy == 'recursive' and not opts.strategy_option: - opts.strategy_option = 'theirs' - print("Using '%s' merge strategy" % opts.merge_strategy, - ("with strategy option '%s'" % opts.strategy_option - if opts.strategy_option else '')) - arglist = ['git', 'merge', '--no-ff', '--no-commit', 'cros/main', '-s', - opts.merge_strategy] - if opts.strategy_option: - arglist.append('-X' + opts.strategy_option) - subprocess.run(arglist, check=True) - - print("Generating commit message...") - branch = subprocess.run(['git', 'rev-parse', '--abbrev-ref', 'HEAD'], - stdout=subprocess.PIPE, - encoding='utf-8', - check=True).stdout.rstrip() - head = subprocess.run(['git', 'rev-parse', '--short', 'HEAD'], - stdout=subprocess.PIPE, - encoding='utf-8', - check=True).stdout.rstrip() - merge_head = subprocess.run(['git', 'rev-parse', '--short', - 'MERGE_HEAD'], - stdout=subprocess.PIPE, - encoding='utf-8', - check=True).stdout.rstrip() - - print("Typing as fast as I can...") - commit_msg = git_commit_msg(branch, head, merge_head, relevant_paths) - subprocess.run(['git', 'commit', '--signoff', '-m', commit_msg], check=True) - subprocess.run(['git', 'commit', '--amend'], check=True) - print(("Finished! **Please review the commit to see if it's to your " - "liking.**")) - - -if __name__ == '__main__': - main(sys.argv[1:])
\ No newline at end of file diff --git a/util/usb_if.c b/util/usb_if.c deleted file mode 100644 index f8aa6bfd7e..0000000000 --- a/util/usb_if.c +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "usb_if.h" - -/* Return 0 on error, since it's never gonna be EP 0 */ -static int find_endpoint(const struct libusb_interface_descriptor *iface, - uint16_t subclass, - uint16_t protocol, - 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(uint16_t subclass, - uint16_t protocol, - 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, subclass, protocol, uep)) { - iface_num = i; - goto out; - } - } - } - -out: - libusb_free_config_descriptor(conf); - return iface_num; -} - -static libusb_device_handle *check_device(libusb_device *dev, - uint16_t vid, uint16_t pid, const char *serial) -{ - struct libusb_device_descriptor desc; - libusb_device_handle *handle = NULL; - char sn[256]; - size_t sn_size = 0; - - if (libusb_get_device_descriptor(dev, &desc) < 0) - return NULL; - - if (libusb_open(dev, &handle) != LIBUSB_SUCCESS) - return NULL; - - if (desc.iSerialNumber && serial) { - sn_size = libusb_get_string_descriptor_ascii(handle, - desc.iSerialNumber, (unsigned char *)sn, - sizeof(sn)); - } - /* - * If the VID, PID, and serial number don't match, then it's not the - * correct device. Close the handle and return NULL. - */ - if ((vid && vid != desc.idVendor) || - (pid && pid != desc.idProduct) || - (serial && ((sn_size != strlen(serial)) || - memcmp(sn, serial, sn_size)))) { - libusb_close(handle); - return NULL; - } - return handle; -} - -int usb_findit(const char *serial, uint16_t vid, uint16_t pid, - uint16_t subclass, uint16_t protocol, 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)); - - /* Must supply either serial or vendor and product ids. */ - if (!serial && !(vid && pid)) - goto terminate_usb_findit; - - r = libusb_init(NULL); - if (r < 0) { - USB_ERROR("libusb_init", r); - goto terminate_usb_findit; - } - - printf("finding_device "); - if (vid) - printf("%04x:%04x ", vid, pid); - if (serial) - printf("%s", serial); - printf("\n"); - - count = libusb_get_device_list(NULL, &devs); - if (count < 0) - goto terminate_usb_findit; - - for (i = 0; i < count; i++) { - devh = check_device(devs[i], vid, pid, serial); - if (devh) { - printf("Found device.\n"); - break; - } - } - - libusb_free_device_list(devs, 1); - - if (!devh) { - fprintf(stderr, "Can't find device\n"); - goto terminate_usb_findit; - } - uep->devh = devh; - - iface_num = find_interface(subclass, protocol, uep); - if (iface_num < 0) { - fprintf(stderr, "USB interface %d is not found\n", uep->ep_num); - goto terminate_usb_findit; - } - if (!uep->chunk_len) { - fprintf(stderr, "wMaxPacketSize isn't valid\n"); - goto terminate_usb_findit; - } - - 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); - goto terminate_usb_findit; - } - - printf("READY\n-------\n"); - return 0; - -terminate_usb_findit: - if (uep->devh) - usb_shut_down(uep); - return -1; -} - -int usb_trx(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, 1000); - if (r < 0) { - USB_ERROR("libusb_bulk_transfer", r); - return -1; - } - if (actual != outlen) { - fprintf(stderr, "%s:%d, only sent %d/%d bytes\n", - __FILE__, __LINE__, actual, outlen); - usb_shut_down(uep); - } - } - - /* Read reply back */ - if (inbuf && inlen) { - - actual = 0; - r = libusb_bulk_transfer(uep->devh, uep->ep_num | 0x80, - inbuf, inlen, - &actual, 1000); - if (r < 0) { - USB_ERROR("libusb_bulk_transfer", r); - return -1; - } - if ((actual != inlen) && !allow_less) { - fprintf(stderr, "%s:%d, only received %d/%d bytes\n", - __FILE__, __LINE__, actual, inlen); - usb_shut_down(uep); - } - - if (rxed_count) - *rxed_count = actual; - } - - return 0; -} - -void usb_shut_down(struct usb_endpoint *uep) -{ - libusb_close(uep->devh); - libusb_exit(NULL); -} diff --git a/util/usb_if.h b/util/usb_if.h deleted file mode 100644 index 8cc1088c6e..0000000000 --- a/util/usb_if.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef __EC_EXTRA_USB_UPDATER_USB_IF_H -#define __EC_EXTRA_USB_UPDATER_USB_IF_H - -#include <libusb.h> - -/* This describes USB endpoint used to communicate with Cr50. */ -struct usb_endpoint { - struct libusb_device_handle *devh; - uint8_t ep_num; - int chunk_len; -}; - -/* - * Find the requested USB endpoint. This finds the device using the device - * serial number, vendor id, and product id. The subclass and protocol are used - * to find the correct endpoint. If a matching endpoint is found, fill up the - * uep structure. If succeeded, usb_shut_down() must be invoked before program - * exits. - * - * Return 0 on success, -1 on failure. - */ -int usb_findit(const char *serialno, uint16_t vid, uint16_t pid, - uint16_t subclass, uint16_t protocol, struct usb_endpoint *uep); - -/* - * Actual USB transfer function, the 'allow_less' flag indicates that the - * valid response could be shorter than allotted memory, the 'rxed_count' - * pointer, if provided along with 'allow_less', lets the caller know how many - * bytes were received. - */ -int usb_trx(struct usb_endpoint *uep, void *outbuf, int outlen, - void *inbuf, int inlen, int allow_less, - size_t *rxed_count); - -/* - * This function should be called for graceful tear down of the USB interface - * when the program exits, either normally or due to error. This is required - * only after USB connection was established, i.e. after successful invocation - * of usb_findit(). - */ -void usb_shut_down(struct usb_endpoint *uep); - -#define USB_ERROR(m, r) \ - fprintf(stderr, "%s:%d, %s returned %d (%s)\n", __FILE__, __LINE__, \ - m, r, libusb_strerror(r)) - -#endif /* ! __EC_EXTRA_USB_UPDATER_USB_IF_H */ diff --git a/util/uut/cmd.c b/util/uut/cmd.c deleted file mode 100644 index 57cf75a29e..0000000000 --- a/util/uut/cmd.c +++ /dev/null @@ -1,482 +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 file creates the UART Program Protocol API commands. */ - -#include <stdint.h> -#include <stdio.h> -#include <string.h> - -#include "cmd.h" -#include "lib_crc.h" -#include "main.h" - - /* Extracting Byte - 8 bit: MSB, LSB */ -#define MSB(u16) ((uint8_t)((uint16_t)(u16) >> 8)) -#define LSB(u16) ((uint8_t)(u16)) - -/*---------------------------------------------------------------------------- - * SPI Flash commands - *--------------------------------------------------------------------------- - */ - -#define SPI_READ_JEDEC_ID_CMD 0x9F -#define SPI_WRITE_ENABLE_CMD 0x06 -#define SPI_WRITE_DISABLE_CMD 0x04 -#define SPI_READ_STATUS_REG_CMD 0x05 -#define SPI_WRITE_STATUS_REG_CMD 0x01 -#define SPI_READ_DATA_CMD 0x03 -#define SPI_PAGE_PRGM_CMD 0x02 -#define SPI_SECTOR_ERASE_CMD 0xD8 -#define SPI_BULK_ERASE_CMD 0xC7 -#define SPI_READ_PID_CMD 0x90 - -union cmd_addr { - uint8_t c_adr[4]; - uint32_t h_adr; -}; - -/*---------------------------------------------------------------------------- - * Function implementation - *--------------------------------------------------------------------------- - */ - -/*---------------------------------------------------------------------------- - * Function: cmd_create_sync - * - * Parameters: cmd_info - Pointer to a command buffer. - * cmd_len - Pointer to command length. - * Returns: none. - * Side effects: - * Description: - * Create a Host to Device SYNC protocol command. - * The total command length is written to 'cmd_len'. - *--------------------------------------------------------------------------- - */ -void cmd_create_sync(uint8_t *cmd_info, uint32_t *cmd_len) -{ - uint32_t len = 0; - - /* Build the command buffer */ - cmd_info[len++] = UFPP_H2D_SYNC_CMD; - - /* Return total command length */ - *cmd_len = len; -} - -/*--------------------------------------------------------------------------- - * Function: cmd_create_write - * - * Parameters: addr - Memory address to write to. - * size - Size of daya (in bytes) to write to memory. - * data_buf - Pointer to data buffer containing raw data to write. - * cmd_info - Pointer to a command buffer. - * cmd_len - Pointer to command length. - * Returns: none. - * Side effects: - * Description: - * Create a WRITE protocol command. - * The command buffer is enclosed by CRC, calculated on command - * information and raw data. - * The total command length is written to 'cmd_len'. - *--------------------------------------------------------------------------- - */ -void cmd_create_write(uint32_t addr, uint32_t size, uint8_t *data_buf, - uint8_t *cmd_info, uint32_t *cmd_len) -{ - uint32_t i; - union cmd_addr adr_tr; - uint16_t crc = 0; - uint32_t len = 0; - - /* Build the command buffer */ - cmd_info[len++] = UFPP_WRITE_CMD; - cmd_info[len++] = (uint8_t)(size - 1); - - /* Insert Address */ - adr_tr.h_adr = addr; - cmd_info[len++] = adr_tr.c_adr[3]; - cmd_info[len++] = adr_tr.c_adr[2]; - cmd_info[len++] = adr_tr.c_adr[1]; - cmd_info[len++] = adr_tr.c_adr[0]; - - /* Insert data */ - memcpy(&cmd_info[len], data_buf, size); - len += size; - - /* Calculate CRC */ - for (i = 0; i < len; i++) - crc = update_crc(crc, (char)cmd_info[i]); - - /* Insert CRC */ - cmd_info[len++] = MSB(crc); - cmd_info[len++] = LSB(crc); - - /* Return total command length */ - *cmd_len = len; -} - -/*---------------------------------------------------------------------------- - * Function: cmd_create_read - * - * Parameters: addr - Memory address to read from. - * size - Size of daya (in bytes) to read from memory. - * cmd_info - Pointer to a command buffer. - * cmd_len - Pointer to command length. - * Returns: none. - * Side effects: - * Description: - * Create a READ protocol command. - * The command buffer is enclosed by CRC, calculated on command - * information and raw data. - * The total command length is written to 'cmd_len'. - *--------------------------------------------------------------------------- - */ -void cmd_create_read(uint32_t addr, uint8_t size, uint8_t *cmd_info, - uint32_t *cmd_len) -{ - uint32_t i; - union cmd_addr adr_tr; - uint16_t crc = 0; - uint32_t len = 0; - - /* Build the command buffer */ - cmd_info[len++] = UFPP_READ_CMD; - cmd_info[len++] = (uint8_t)size; - - /* Insert Address */ - adr_tr.h_adr = addr; - cmd_info[len++] = adr_tr.c_adr[3]; - cmd_info[len++] = adr_tr.c_adr[2]; - cmd_info[len++] = adr_tr.c_adr[1]; - cmd_info[len++] = adr_tr.c_adr[0]; - - /* Calculate CRC */ - for (i = 0; i < len; i++) - crc = update_crc(crc, (char)cmd_info[i]); - - /* Insert CRC */ - cmd_info[len++] = MSB(crc); - cmd_info[len++] = LSB(crc); - - /* Return total command length */ - *cmd_len = len; -} - -/*---------------------------------------------------------------------------- - * Function: cmd_create_exec - * - * Parameters: addr - Memory address to execute from. - * cmd_info - Pointer to a command buffer. - * cmd_len - Pointer to command length. - * Returns: none. - * Side effects: - * Description: - * Create an FCALL protocol command. - * The command buffer is enclosed by CRC, calculated on command - * information and raw data. - * The total command length is written to 'cmd_len'. - *--------------------------------------------------------------------------- - */ -void cmd_create_exec(uint32_t addr, uint8_t *cmd_info, uint32_t *cmd_len) -{ - uint32_t i; - union cmd_addr adr_tr; - uint16_t crc = 0; - uint32_t len = 0; - - /* Build the command buffer */ - cmd_info[len++] = UFPP_FCALL_CMD; - cmd_info[len++] = 0; - - /* Insert Address */ - adr_tr.h_adr = addr; - cmd_info[len++] = adr_tr.c_adr[3]; - cmd_info[len++] = adr_tr.c_adr[2]; - cmd_info[len++] = adr_tr.c_adr[1]; - cmd_info[len++] = adr_tr.c_adr[0]; - - /* Calculate CRC */ - for (i = 0; i < len; i++) - crc = update_crc(crc, (char)cmd_info[i]); - - /* Insert CRC */ - cmd_info[len++] = MSB(crc); - cmd_info[len++] = LSB(crc); - - /* Return total command length */ - *cmd_len = len; -} - -/*--------------------------------------------------------------------------- - * Function: cmd_build_sync - * - * Parameters: cmd_buf - Pointer to a command buffer. - * cmd_num - Pointer to command number. - * Returns: none. - * Description: - * Build a synchronization command buffer. - * The total command number is written to 'cmd_num'. - *--------------------------------------------------------------------------- - */ -void cmd_build_sync(struct command_node *cmd_buf, uint32_t *cmd_num) -{ - uint32_t cmd = 0; - - cmd_create_sync(cmd_buf[cmd].cmd, &cmd_buf[cmd].cmd_size); - cmd_buf[cmd].resp_size = 1; - cmd++; - - *cmd_num = cmd; -} - -/*---------------------------------------------------------------------------- - * Function: cmd_build_exec_exit - * - * Parameters: addr - Memory address to execute from. - * cmd_buf - Pointer to a command buffer. - * cmd_num - Pointer to command number. - * Returns: none. - * Side effects: - * Description: - * Build an Excute command buffer. - * Command does not expect the executed code to return, that is, - * only FCALL protocol - * command code is expected. - * Determine the expected response size per each command. - * The total command number is written to 'cmd_num'. - *--------------------------------------------------------------------------- - */ -void cmd_build_exec_exit(uint32_t addr, struct command_node *cmd_buf, - uint32_t *cmd_num) -{ - uint32_t cmd = 0; - - cmd_create_exec(addr, cmd_buf[cmd].cmd, &cmd_buf[cmd].cmd_size); - cmd_buf[cmd].resp_size = 1; - cmd++; - - *cmd_num = cmd; -} - -/*---------------------------------------------------------------------------- - * Function: cmd_build_exec_ret - * - * Parameters: addr - Memory address to execute from. - * cmd_buf - Pointer to a command buffer. - * cmd_num - Pointer to command number. - * Returns: none. - * Side effects: - * Description: - * Build an Excute command buffer. - * Command expects the executed code to return, that is, - * FCALL_RSLT protocol command - * code is expected, together with the execution result. - * Determine the expected response size per each command. - * The total command number is written to 'cmd_num'. - *--------------------------------------------------------------------------- - */ -void cmd_build_exec_ret(uint32_t addr, struct command_node *cmd_buf, - uint32_t *cmd_num) -{ - uint32_t cmd = 0; - - cmd_create_exec(addr, cmd_buf[cmd].cmd, &cmd_buf[cmd].cmd_size); - cmd_buf[cmd].resp_size = 3; - cmd++; - - *cmd_num = cmd; -} - -/*---------------------------------------------------------------------------- - * Function: cmd_disp_sync - * - * Parameters: resp_buf - Pointer to a response buffer. - * Returns: TRUE if successful, FALSE in the case of an error. - * Side effects: - * Description: - * Display SYNC command response information. - *--------------------------------------------------------------------------- - */ -bool cmd_disp_sync(uint8_t *resp_buf) -{ - if (resp_buf[0] == (uint8_t)(UFPP_D2H_SYNC_CMD)) { - display_color_msg(SUCCESS, "Host/Device are synchronized\n"); - return true; - } - - display_color_msg(FAIL, "Host/Device synchronization failed!!!\n"); - return false; -} - -/*---------------------------------------------------------------------------- - * Function: cmd_disp_write - * - * Parameters: resp_buf - Pointer to a response buffer. - * resp_size - Response size. - * resp_num - Response packet number. - * Returns: TRUE if successful, FALSE in the case of an error. - * Side effects: - * Description: - * Display WRITE command response information. - *--------------------------------------------------------------------------- - */ -bool cmd_disp_write(uint8_t *resp_buf, uint32_t resp_size, uint32_t resp_num, - uint32_t total_size) -{ - if (resp_buf[0] == (uint8_t)(UFPP_WRITE_CMD)) { - display_color_msg(SUCCESS, - "\rTransmitted packet of size %u bytes, packet " - "[%u]out of [%u]", - resp_size, resp_num, total_size); - return true; - } - - display_color_msg(FAIL, "\nWrite packet [%lu] Failed\n", resp_num); - return false; -} - -/*----------------------------------------------------------------------------- - * Function: cmd_disp_read - * - * Parameters: resp_buf - Pointer to a response buffer. - * resp_size - Response size. - * resp_num - Response packet number. - * Returns: TRUE if successful, FALSE in the case of an error. - * Side effects: - * Description: - * Display READ command response information. - *--------------------------------------------------------------------------- - */ -bool cmd_disp_read(uint8_t *resp_buf, uint32_t resp_size, uint32_t resp_num, - uint32_t total_size) -{ - if (resp_buf[0] == (uint8_t)(UFPP_READ_CMD)) { - display_color_msg(SUCCESS, - "\rReceived packet of size %u bytes, packet [%u] out " - "of [%u]", - resp_size, resp_num, total_size); - return true; - } - - display_color_msg(FAIL, "\nRead packet [%u] Failed\n", resp_num); - return false; -} - -/*---------------------------------------------------------------------------- - * Function: cmd_disp_data - * - * Parameters: resp_buf - Pointer to a response buffer. - * resp_size - Response size. - * Returns: none. - * Side effects: - * Description: - * Display raw data, read from memory. - *--------------------------------------------------------------------------- - */ -void cmd_disp_data(uint8_t *resp_buf, uint32_t resp_size) -{ - uint32_t idx; - uint32_t i; - - for (idx = 0; idx < resp_size; idx += 4) { - if ((idx % 16) == 0) - printf("\n"); - - printf("0x"); - for (i = 4; i > 0; i--) - printf("%02x", resp_buf[idx + i - 1]); - - if ((idx % 4) == 0) - printf(" "); - } - - printf("\n"); -} - -/*---------------------------------------------------------------------------- - * Function: cmd_disp_flash_erase_dev - * - * Parameters: resp_buf - Pointer to a response buffer. - * dev_num - Flash Device Number. - * Returns: none. - * Side effects: - * Description: - * Display BULK_ERASE command response information. - *--------------------------------------------------------------------------- - */ -void cmd_disp_flash_erase_dev(uint8_t *resp_buf, uint32_t dev_num) -{ - if (resp_buf[0] == (uint8_t)(UFPP_WRITE_CMD)) { - display_color_msg(SUCCESS, - "Flash Erase of device [%u] Passed\n", dev_num); - } else { - display_color_msg( - FAIL, "Flash Erase of device [%u] Failed\n", dev_num); - } -} - -/*--------------------------------------------------------------------------- - * Function: cmd_disp_flash_erase_sect - * - * Parameters: resp_buf - Pointer to a response buffer. - * Returns: none. - * Side effects: - * Description: - * Display BULK_ERASE command response information. - *--------------------------------------------------------------------------- - */ -void cmd_disp_flash_erase_sect(uint8_t *resp_buf, uint32_t dev_num) -{ - if (resp_buf[0] == (uint8_t)(UFPP_WRITE_CMD)) { - display_color_msg(SUCCESS, - "Sector Erase of device [%lu] Passed\n", dev_num); - } else { - display_color_msg( - FAIL, "Sector Erase of device [%lu] Failed\n", dev_num); - } -} - -/*--------------------------------------------------------------------------- - * Function: cmd_disp_exec_exit - * - * Parameters: resp_buf - Pointer to a response buffer. - * Returns: none. - * Side effects: - * Description: - * Display Execute command response information. - *--------------------------------------------------------------------------- - */ -void cmd_disp_exec_exit(uint8_t *resp_buf) -{ - if (resp_buf[0] == (uint8_t)(UFPP_FCALL_CMD)) - display_color_msg(SUCCESS, "Execute Command Passed\n"); - else - display_color_msg(FAIL, "Execute Command Failed\n"); -} - -/*--------------------------------------------------------------------------- - * Function: cmd_disp_exec_ret - * - * Parameters: resp_buf - Pointer to a response buffer. - * Returns: none. - * Side effects: - * Description: - * Display Execute Result command response information. - *--------------------------------------------------------------------------- - */ -void cmd_disp_exec_ret(uint8_t *resp_buf) -{ - if (resp_buf[1] == (uint8_t)(UFPP_FCALL_RSLT_CMD)) { - display_color_msg(SUCCESS, - "Execute Command Passed, execution result is [0x%X]\n", - resp_buf[2]); - } else { - display_color_msg(FAIL, - "Execute Command Failed [0x%X] [0x%X], rslt=[0x%X]\n", - resp_buf[0], resp_buf[1], resp_buf[2]); - } -} diff --git a/util/uut/cmd.h b/util/uut/cmd.h deleted file mode 100644 index 44cebbe989..0000000000 --- a/util/uut/cmd.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef __UTIL_UUT_CMD_H -#define __UTIL_UUT_CMD_H - -#include <stdbool.h> - -/*--------------------------------------------------------------------------- - * Constant definitions - *--------------------------------------------------------------------------- - */ - -#define MAX_CMD_BUF_SIZE 10 -#define MAX_RESP_BUF_SIZE 512 - -enum uart_protocol_cmd { - UFPP_H2D_SYNC_CMD = 0x55, /* Single-Byte Host to Device */ - /* synchronization command */ - UFPP_D2H_SYNC_CMD = 0x5A, /* Single-Byte Device to Host */ - /* synchronization response */ - UFPP_WRITE_CMD = 0x07, /* Write command and response */ - UFPP_READ_CMD = 0x1C, /* Read command and response */ - UFPP_READ_CRC_CMD = 0x89, /* Read CRC command and response */ - UFPP_FCALL_CMD = 0x70, /* Call function command */ - UFPP_FCALL_RSLT_CMD = 0x73, /* Call function response */ - UFPP_SPI_CMD = 0x92, /* SPI specific command */ - UFPP_ERROR_CMD = 0xFF /* Error response */ -}; - -struct command_node { - uint8_t cmd[512]; - uint32_t cmd_size; - uint32_t resp_size; -}; - -/*--------------------------------------------------------------------------- - * Functions prototypes - *--------------------------------------------------------------------------- - */ - -void cmd_create_sync(uint8_t *cmd_info, uint32_t *cmd_len); -void cmd_create_write(uint32_t addr, uint32_t size, uint8_t *data_buf, - uint8_t *cmd_info, uint32_t *cmd_len); -void cmd_create_read(uint32_t addr, uint8_t size, uint8_t *cmd_info, - uint32_t *cmd_len); -void cmd_create_exec(uint32_t addr, uint8_t *cmd_info, uint32_t *cmd_len); - -void cmd_build_sync(struct command_node *cmd_buf, uint32_t *cmd_num); -void cmd_build_exec_exit(uint32_t addr, struct command_node *cmd_buf, - uint32_t *cmd_num); -void cmd_build_exec_ret(uint32_t addr, struct command_node *cmd_buf, - uint32_t *cmd_num); - -bool cmd_disp_sync(uint8_t *resp_buf); -bool cmd_disp_write(uint8_t *resp_buf, uint32_t resp_size, uint32_t resp_num, - uint32_t total_size); -bool cmd_disp_read(uint8_t *resp_buf, uint32_t resp_size, uint32_t resp_num, - uint32_t total_size); -void cmd_disp_data(uint8_t *resp_buf, uint32_t resp_size); -void cmd_disp_flash_erase_dev(uint8_t *resp_buf, uint32_t dev_num); -void cmd_disp_flash_erase_sect(uint8_t *resp_buf, uint32_t dev_num); -void cmd_disp_exec_exit(uint8_t *resp_buf); -void cmd_disp_exec_ret(uint8_t *resp_buf); - -#endif /* __UTIL_UUT_CMD_H */ diff --git a/util/uut/com_port.h b/util/uut/com_port.h deleted file mode 100644 index 36331f2fb6..0000000000 --- a/util/uut/com_port.h +++ /dev/null @@ -1,149 +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 file defines the ComPort interface header file. */ - -#ifndef __UTIL_UUT_COM_PORT_H -#define __UTIL_UUT_COM_PORT_H - -#include <stdbool.h> -#include <termios.h> - -#ifdef __cplusplus -extern "C" { -#endif -/*--------------------------------------------------------------------------- - * ComPort INTERFACE - *--------------------------------------------------------------------------- - */ - -/*--------------------------------------------------------------------------- - * Constant definitions - *--------------------------------------------------------------------------- - */ -#define INVALID_HANDLE_VALUE -1 - -/*--------------------------------------------------------------------------- - * Type definitions - *--------------------------------------------------------------------------- - */ -#define COMP_PORT_PREFIX_1 "ttyS" -#define COMP_PORT_PREFIX_2 "ttyUSB" -#define COMP_PORT_PREFIX_3 "pts" - -struct comport_fields { - uint32_t baudrate; /* Baudrate at which running */ - tcflag_t byte_size; /* Number of bits/byte, 4-8 */ - tcflag_t parity; /* 0-4=None,Odd,Even,Mark,Space */ - uint8_t stop_bits; /* 0,1,2 = 1, 1.5, 2 */ - uint8_t flow_control; /* 0-none, 1-SwFlowControl,2-HwFlowControl */ -}; - -/*--------------------------------------------------------------------------- - * Function: int com_port_open() - * - * Purpose: Open the specified ComPort device. - * - * Params: com_port_dev_name - The name of the device to open - * com_port_fields - a struct filled with Comport settings, see - * definition above. - * - * Returns: INVALID_HANDLE_VALUE (-1) - invalid handle. - * Other value - Handle to be used in other Comport APIs - * - * Comments: The returned handle can be used for other Win32 API communication - * function by casting it to HANDLE. - * - *--------------------------------------------------------------------------- - */ -int com_port_open(const char *com_port_dev_name, - struct comport_fields com_port_fields); - -/*--------------------------------------------------------------------------- - * Function: int com_config_uart() - * - * Purpose: Configures the Uart port properties. - * - * Params: h_dev_drv - the opened handle returned by com_port_open() - * com_port_fields - a struct filled with Comport settings, see - * definition above. - * - * Returns: 1 if successful - * 0 in the case of an error. - * - *--------------------------------------------------------------------------- - */ -bool com_config_uart(int h_dev_drv, struct comport_fields com_port_fields); - -/*--------------------------------------------------------------------------- - * Function: bool ComPortClose() - * - * Purpose: Close the ComPort device specified by Handle - * - * Params: device_id - the opened handle returned by com_port_open() - * - * Returns: 1 if successful - * 0 in the case of an error. - * - *--------------------------------------------------------------------------- - */ -bool com_port_close(int device_id); - -/*--------------------------------------------------------------------------- - * Function: bool com_port_write_bin() - * - * Purpose: Send binary data through Comport - * - * Params: device_id - the opened handle returned by com_port_open() - * buffer - contains the binary data to send - * buf_size - the size of data to send - * - * Returns: 1 if successful - * 0 in the case of an error. - * - * Comments: The caller must ensure that buf_size is not bigger than - * Buffer size. - * - *--------------------------------------------------------------------------- - */ -bool com_port_write_bin(int device_id, const uint8_t *buffer, - uint32_t buf_size); - -/*--------------------------------------------------------------------------- - * Function: uint32_t com_port_read_bin() - * - * Purpose: Read a binary data from Comport - * - * Params: device_id - the opened handle returned by com_port_open() - * buffer - this buffer will contain the arrived data - * buf_size - maximum data size to read - * - * Returns: The number of bytes read. - * - * Comments: The caller must ensure that Size is not bigger than Buffer size. - * - *--------------------------------------------------------------------------- - */ -uint32_t com_port_read_bin(int device_id, uint8_t *buffer, uint32_t buf_size); - -/*--------------------------------------------------------------------------- - * Function: uint32_t com_port_wait_read() - * - * Purpose: Wait until a byte is received for read - * - * Params: device_id - the opened handle returned by com_port_open() - * - * Returns: The number of bytes that are waiting in RX queue. - * - *--------------------------------------------------------------------------- - */ -uint32_t com_port_wait_read(int device_id); - -#ifdef __cplusplus -} -#endif - -#endif /* __UTIL_UUT_COM_PORT_H */ diff --git a/util/uut/l_com_port.c b/util/uut/l_com_port.c deleted file mode 100644 index 018dec9950..0000000000 --- a/util/uut/l_com_port.c +++ /dev/null @@ -1,446 +0,0 @@ -/* - * Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include <errno.h> -#include <fcntl.h> -#include <poll.h> -#include <stdint.h> -#include <stdio.h> -#include <string.h> -#include <sys/ioctl.h> -#include <termios.h> -#include <unistd.h> - -#include "com_port.h" -#include "main.h" - -/*--------------------------------------------------------------------------- - * Constant definitions - *--------------------------------------------------------------------------- - */ - -#define INBUFSIZE 2048 -#define OUTBUFSIZE 2048 -#define LOWER_THRESHOLD 16 -#define UPPER_THRESHOLD 512 -#define XOFF_CHAR 0x13 -#define XON_CHAR 0x11 - -#define UART_FIFO_SIZE 16 - -#define COMMAND_TIMEOUT 10000 /* 10 seconds */ - -/*--------------------------------------------------------------------------- - * Global variables - *--------------------------------------------------------------------------- - */ -static struct termios savetty; - -/*--------------------------------------------------------------------------- - * Functions prototypes - *--------------------------------------------------------------------------- - */ - -/*-------------------------------------------------------------------------- - * Local Function implementation - *-------------------------------------------------------------------------- - */ - -/*-------------------------------------------------------------------------- - * Function: convert_baudrate_to_baudrate_mask - * - * Parameters: - * baudrate - Bauderate value. - * - * Returns: Baudrate mask. - * Side effects: - * Description: - * This routine convert from baudrate mode to paudrate mask. - *-------------------------------------------------------------------------- - */ -static speed_t convert_baudrate_to_baudrate_mask(uint32_t baudrate) -{ - switch (baudrate) { - case 9600: - return B9600; - case 19200: - return B19200; - case 38400: - return B38400; - case 57600: - return B57600; - case 115200: - return B115200; - default: - return B0; - } -} - -/*------------------------------------------------------------------------- - * Function: set_read_blocking - * - * Parameters: - * dev_drv - The opened handle returned by com_port_open() - * block - TRUE means read in blocking mode - * FALSE means read in non-blocking mode. - * - * Returns: none - * Side effects: - * Description: - * This routine set/unset read blocking mode. - *-------------------------------------------------------------------------- - */ -void set_read_blocking(int dev_drv, bool block) -{ - struct termios tty; - - memset(&tty, 0, sizeof(tty)); - - if (tcgetattr(dev_drv, &tty) != 0) { - display_color_msg(FAIL, - "set_read_blocking Error: %d Fail to get attribute " - "from Device number %d.\n", - errno, dev_drv); - return; - } - - tty.c_cc[VMIN] = block; - tty.c_cc[VTIME] = 5; /* 0.5 seconds read timeout */ - - if (tcsetattr(dev_drv, TCSANOW, &tty) != 0) { - display_color_msg(FAIL, - "set_read_blocking Error: %d Fail to set attribute to " - "Device number %d.\n", - errno, dev_drv); - } -} - -/*-------------------------------------------------------------------------- - * Global Function implementation - *-------------------------------------------------------------------------- - */ - -/****************************************************************************** - * Function: int com_config_uart() - * - * Purpose: Configures the Uart port properties. - * - * Params: h_dev_drv - the opened handle returned by com_port_open() - * com_port_fields - a struct filled with Comport settings, see - * definition above. - * - * Returns: 1 if successful - * 0 in the case of an error. - * - ***************************************************************************** - */ -bool com_config_uart(int h_dev_drv, struct comport_fields com_port_fields) -{ - struct termios tty; - speed_t baudrate; - - memset(&tty, 0, sizeof(tty)); - - if (tcgetattr(h_dev_drv, &tty) != 0) { - display_color_msg(FAIL, - "com_config_uart Error: Fail to get attribute from " - "Device number %d.\n", - h_dev_drv); - return false; - } - - baudrate = convert_baudrate_to_baudrate_mask(com_port_fields.baudrate); - cfsetospeed(&tty, baudrate); - cfsetispeed(&tty, baudrate); - - tty.c_cflag |= baudrate; - - tty.c_cflag |= com_port_fields.byte_size; - - /* - * disable IGNBRK for mismatched speed tests; otherwise receive break - * as \000 chars - */ - - /* Set port to be in a "raw" mode. */ - tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | - ICRNL | IXON); - tty.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); - - tty.c_oflag = ~OPOST; - tty.c_cc[VMIN] = 0; /* read doesn't block */ - tty.c_cc[VTIME] = 5; /* 0.5 seconds read timeout */ - - tty.c_iflag |= (com_port_fields.flow_control == 0x01) - ? (IXON | IXOFF) - : 0x00; /* xon/xoff ctrl */ - - tty.c_cflag |= (CLOCAL | CREAD); /* ignore modem controls */ - /* enable reading */ - tty.c_cflag &= ~(PARENB | PARODD); /* shut off parity */ - tty.c_cflag |= com_port_fields.parity; - /* Stop bits */ - tty.c_cflag |= (com_port_fields.stop_bits == 0x02) ? CSTOPB : 0x00; - /* HW flow control */ - tty.c_cflag |= (com_port_fields.flow_control == 0x02) ? CRTSCTS : 0x00; - - /* Flush Port, then applies attributes */ - tcflush(h_dev_drv, TCIFLUSH); - - if (tcsetattr(h_dev_drv, TCSANOW, &tty) != 0) { - display_color_msg(FAIL, - "com_config_uart Error: %d setting port handle %d: %s.\n", - errno, h_dev_drv, strerror(errno)); - return false; - } - - return true; -} - -/** - * Drain the console RX buffer before programming. The device should be in - * programming mode and shouldn't be printing anything. Anything that's - * currently in the buffer could interfere with programming. discard_input - * will discard everything currently in the buffer. It prints any non zero - * characters and returns when the console is empty and ready for programming. - * - * This is the same as discard_input in stm32mon. - * TODO: create common library for initializing serial consoles. - */ -static void discard_input(int fd) -{ - uint8_t buffer[64]; - int res, i; - int count_of_zeros; - - /* Keep track of discarded zeros */ - count_of_zeros = 0; - do { - res = read(fd, buffer, sizeof(buffer)); - if (res > 0) { - - /* Discard zeros in the beginning of the buffer. */ - for (i = 0; i < res; i++) - if (buffer[i]) - break; - - count_of_zeros += i; - if (i == res) { - /* Only zeros, nothing to print out. */ - continue; - } - - /* Discard zeros in the end of the buffer. */ - while (!buffer[res - 1]) { - count_of_zeros++; - res--; - } - - printf("Recv[%d]:", res - i); - for (; i < res; i++) - printf("%02x ", buffer[i]); - printf("\n"); - } - } while (res > 0); - - if (count_of_zeros) - printf("%d zeros ignored\n", count_of_zeros); -} - - -/****************************************************************************** - * Function: int com_port_open() - * - * Purpose: Open the specified ComPort device and return its handle. - * - * Params: com_port_dev_name - The name of the device to open - * com_port_fields - a struct filled with Comport settings - * - * Returns: INVALID_HANDLE_VALUE (-1) - invalid handle. - * Other value - Handle to be used in other Comport APIs - * - * Comments: The returned handle can be used for other Win32 API communication - * function. - * - ***************************************************************************** - */ -int com_port_open(const char *com_port_dev_name, - struct comport_fields com_port_fields) -{ - int port_handler; - - port_handler = open(com_port_dev_name, O_RDWR | O_NOCTTY); - - if (port_handler < 0) { - display_color_msg(FAIL, - "com_port_open Error %d opening %s: %s\n", - errno, com_port_dev_name, strerror(errno)); - return INVALID_HANDLE_VALUE; - } - - tcgetattr(port_handler, &savetty); - - if (!com_config_uart(port_handler, com_port_fields)) { - display_color_msg(FAIL, - "com_port_open() Error %d, Failed on com_config_uart() %s, " - "%s\n", - errno, com_port_dev_name, strerror(errno)); - close(port_handler); - return INVALID_HANDLE_VALUE; - } - - /* - * Drain the console, so what ever is already in the EC console wont - * interfere with programming. - */ - discard_input(port_handler); - - return port_handler; -} - -/****************************************************************************** - * Function: com_port_close() - * - * Purpose: Close the ComPort device specified by Handle - * - * Params: device_id - the opened handle returned by com_port_open() - * - * Returns: 1 if successful - * 0 in the case of an error. - * - ***************************************************************************** - */ -bool com_port_close(int device_id) -{ - tcsetattr(device_id, TCSANOW, &savetty); - - if (close(device_id) == INVALID_HANDLE_VALUE) { - display_color_msg(FAIL, - "com_port_close() Error: %d Device com%u was not opened, " - "%s.\n", - errno, (uint32_t)device_id, strerror(errno)); - return false; - } - - return true; -} - -/****************************************************************************** - * Function: com_port_write_bin() - * - * Purpose: Send binary data through Comport - * - * Params: device_id - the opened handle returned by com_port_open() - * buffer - contains the binary data to send - * buf_size - the size of data to send - * - * Returns: 1 if successful - * 0 in the case of an error. - * - * Comments: The caller must ensure that buf_size is not bigger than - * buffer size. - * - ***************************************************************************** - */ -bool com_port_write_bin(int device_id, const uint8_t *buffer, - uint32_t buf_size) -{ - uint32_t bytes_written; - - bytes_written = write(device_id, buffer, buf_size); - if (bytes_written != buf_size) { - display_color_msg(FAIL, - "com_port_write_bin() Error: %d Failed to write data to " - "Uart Port %d, %s.\n", - errno, (uint32_t)device_id, strerror(errno)); - - return false; - } - - return true; -} - -/****************************************************************************** - * Function: uint32_t com_port_read_bin() - * - * Purpose: Read a binary data from Comport - * - * Params: device_id - the opened handle returned by com_port_open() - * buffer - this buffer will contain the arrived data - * buf_size - maximum data size to read - * - * Returns: The number of bytes read. - * - * Comments: The caller must ensure that Size is not bigger than buffer size. - * - ***************************************************************************** - */ -uint32_t com_port_read_bin(int device_id, uint8_t *buffer, uint32_t buf_size) -{ - int32_t read_bytes; - - /* Reset read blocking mode */ - set_read_blocking(device_id, false); - - read_bytes = read(device_id, buffer, buf_size); - - if (read_bytes == -1) { - display_color_msg(FAIL, - "%s() Error: %d Device number %u was not " - "opened, %s.\n", - __func__, errno, (uint32_t)device_id, strerror(errno)); - } - - return read_bytes; -} - -/****************************************************************************** - * Function: uint32_t com_port_wait_read() - * - * Purpose: Wait until a byte is received for read - * - * Params: device_id - the opened handle returned by com_port_open() - * - * Returns: The number of bytes that are waiting in RX queue. - * - ***************************************************************************** - */ -uint32_t com_port_wait_read(int device_id) -{ - int32_t bytes; - int32_t ret_val; - struct pollfd fds; - - /* Set read blocking mode */ - set_read_blocking(device_id, true); - - /* Wait up to 10 sec until byte is received for read. */ - fds.fd = device_id; - fds.events = POLLIN; - ret_val = poll(&fds, 1, COMMAND_TIMEOUT); - if (ret_val < 0) { - display_color_msg(FAIL, - "%s() Error: %d Device number %u %s\n", - __func__, errno, (uint32_t)device_id, strerror(errno)); - return 0; - } - - bytes = 0; - - /* If data is ready for read. */ - if (ret_val > 0) { - /* Get number of bytes that are ready to be read. */ - if (ioctl(device_id, FIONREAD, &bytes) < 0) { - display_color_msg(FAIL, - "com_port_wait_for_read() Error: %d Device number " - "%u %s\n", - errno, (uint32_t)device_id, strerror(errno)); - return 0; - } - } - - return bytes; -} diff --git a/util/uut/lib_crc.c b/util/uut/lib_crc.c deleted file mode 100644 index 176e91327c..0000000000 --- a/util/uut/lib_crc.c +++ /dev/null @@ -1,109 +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. - */ - -/* - * The file lib_crc.c contains the functions used for the calculation of - * CRC-16 cyclic redundancy values. - */ - -#include "lib_crc.h" - -/********************************************************************* - * * - * Library : lib_crc * - * File : lib_crc.c * - * Author : Lammert Bies 1999-2005 * - * E-mail : info@lammertbies.nl * - * Language : ANSI C * - * * - * * - * Description * - * =========== * - * * - * The file lib_crc.c contains the private and public func- * - * tions used for the calculation of CRC-16, CRC-CCITT and * - * CRC-32 cyclic redundancy values. * - * * - * * - * Dependencies * - * ============ * - * * - * lib_crc.h CRC definitions and prototypes * - * * - * * - * Modification history * - * ==================== * - * * - * Date Version Comment * - * * - * 2005-05-14 1.12 Added CRC-CCITT with start value 0 * - * * - * 2005-02-05 1.11 Fixed bug in CRC-DNP routine * - * * - * 2005-02-04 1.10 Added CRC-DNP routines * - * * - * 1999-02-21 1.01 Added FALSE and TRUE mnemonics * - * * - * 1999-01-22 1.00 Initial source * - * * - ********************************************************************* - */ - -/* CRC16 lookup table for polynom 0xA001 */ -static const unsigned short crc16_tab[256] = { - 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, - 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440, - 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, - 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841, - 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, - 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, - 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, - 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, - 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240, - 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, - 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, - 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, - 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, - 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, - 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, - 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, - 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, - 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441, - 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, - 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, - 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41, - 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, - 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640, - 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, - 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241, - 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, - 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, - 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841, - 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, - 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41, - 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, - 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040 -}; - -/********************************************************************* - * * - * unsigned short update_crc( unsigned long crc, unsigned char c ) * - * * - * The function update_crc calculates a new CRC-16 value * - * based on the previous value of the CRC and the next byte * - * of the data to be checked. * - * * - ********************************************************************* - */ -unsigned short update_crc(unsigned short crc, unsigned char c) -{ - unsigned short tmp; - - tmp = crc ^ (0x00ff & (unsigned short)c); - crc = (crc >> 8) ^ crc16_tab[tmp & 0xff]; - - return crc; -} diff --git a/util/uut/lib_crc.h b/util/uut/lib_crc.h deleted file mode 100644 index 58db81c4e5..0000000000 --- a/util/uut/lib_crc.h +++ /dev/null @@ -1,68 +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 file contains public definitions and prototypes for the CRC functions. - */ - -#ifndef __UTIL_UUT_LIB_CRC_H -#define __UTIL_UUT_LIB_CRC_H - -/*-------------------------------------------------------------------*\ - * * - * Library : lib_crc * - * File : lib_crc.h * - * Author : Lammert Bies 1999-2005 * - * E-mail : info@lammertbies.nl * - * Language : ANSI C * - * * - * * - * Description * - * =========== * - * * - * The file lib_crc.h contains public definitions and proto- * - * types for the CRC functions present in lib_crc.c. * - * * - * * - * Dependencies * - * ============ * - * * - * none * - * * - * * - * Modification history * - * ==================== * - * * - * Date Version Comment * - * * - * 2005-02-14 1.12 Added CRC-CCITT with initial value 0 * - * * - * 2005-02-05 1.11 Fixed bug in CRC-DNP routine * - * * - * 2005-02-04 1.10 Added CRC-DNP routines * - * * - * 2005-01-07 1.02 Changes in tst_crc.c * - * * - * 1999-02-21 1.01 Added FALSE and TRUE mnemonics * - * * - * 1999-01-22 1.00 Initial source * - * * - *-------------------------------------------------------------------* - */ - -/*--------------------------------------------------------------------------- - * CRC library constant definitions - *--------------------------------------------------------------------------- - */ -#define CRC_VERSION "1.12" - -/*--------------------------------------------------------------------------- - * CRC library API - *--------------------------------------------------------------------------- - */ -unsigned short update_crc(unsigned short crc, unsigned char c); - -#endif /* __UTIL_UUT_LIB_CRC_H */ diff --git a/util/uut/main.c b/util/uut/main.c deleted file mode 100644 index 146ddc0275..0000000000 --- a/util/uut/main.c +++ /dev/null @@ -1,770 +0,0 @@ -/* - * Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include <errno.h> -#include <getopt.h> -#include <stdarg.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/stat.h> - -#include "com_port.h" -#include "compile_time_macros.h" -#include "main.h" -#include "misc_util.h" -#include "opr.h" - -/*---------------------------------------------------------------------------- - * Constant definitions - *--------------------------------------------------------------------------- - */ - -#define MAX_FILE_NAME_SIZE 512 -#define MAX_PARAM_SIZE 32 -#define MAX_MSG_SIZE 128 -#define MAX_SYNC_RETRIES 3 - -/* Default values */ -#define DEFAULT_BAUD_RATE 115200 -#define DEFAULT_PORT_NAME "ttyS0" -#define DEFAULT_DEV_NUM 0 -#define DEFAULT_FLASH_OFFSET 0 - -/* The magic number in monitor header */ -#define MONITOR_HDR_TAG 0xA5075001 -/* The location of monitor header */ -#define MONITOR_HDR_ADDR 0x200C3000 -/* The start address of the monitor little firmware to execute */ -#define MONITOR_ADDR 0x200C3020 -/* The start address to store the firmware segment to be programmed */ -#define FIRMWARE_START_ADDR 0x10090000 -/* Divide the ec firmware image into 4K byte */ -#define FIRMWARE_SEGMENT 0x1000 -/* Register address for chip ID */ -#define NPCX_SRID_CR 0x400C101C -/* Register address for device ID */ -#define NPCX_DEVICE_ID_CR 0x400C1022 -#define NPCX_FLASH_BASE_ADDR 0x64000000 - -/*--------------------------------------------------------------------------- - * Global variables - *--------------------------------------------------------------------------- - */ -bool verbose; -bool console; -struct comport_fields port_cfg; - -/*--------------------------------------------------------------------------- - * Local variables - *--------------------------------------------------------------------------- - */ - -static const char tool_name[] = {"LINUX UART Update Tool"}; -static const char tool_version[] = {"2.0.1"}; - -static char port_name[MAX_PARAM_SIZE]; -static char opr_name[MAX_PARAM_SIZE]; -static char file_name[MAX_FILE_NAME_SIZE]; -static char addr_str[MAX_PARAM_SIZE]; -static char size_str[MAX_PARAM_SIZE]; -static uint32_t baudrate; -static uint32_t dev_num; -static uint32_t flash_offset; -static bool auto_mode; -static bool read_flash_flag; - -struct npcx_chip_info { - uint8_t device_id; - uint8_t chip_id; - uint32_t flash_size; -}; - -const static struct npcx_chip_info chip_info[] = { - { - /* NPCX796FA */ - .device_id = 0x21, - .chip_id = 0x06, - .flash_size = 1024 * 1024, - }, - - { - /* NPCX796FB */ - .device_id = 0x21, - .chip_id = 0x07, - .flash_size = 1024 * 1024, - }, - - { - /* NPCX796FC */ - .device_id = 0x29, - .chip_id = 0x07, - .flash_size = 512 * 1024, - }, - - { - /* NPCX797FC */ - .device_id = 0x20, - .chip_id = 0x07, - .flash_size = 512 * 1024, - }, - - { - /* NPCX797WB */ - .device_id = 0x24, - .chip_id = 0x07, - .flash_size = 1024 * 1024, - }, - - { - /* NPCX797WC */ - .device_id = 0x2C, - .chip_id = 0x07, - .flash_size = 512 * 1024, - }, - - { - /* NPCX993F */ - .device_id = 0x25, - .chip_id = 0x09, - .flash_size = 512 * 1024, - }, - - { - /* NPCX996F */ - .device_id = 0x21, - .chip_id = 0x09, - .flash_size = 512 * 1024, - }, -}; -/*--------------------------------------------------------------------------- - * Functions prototypes - *--------------------------------------------------------------------------- - */ - -static void param_parse_cmd_line(int argc, char *argv[]); -static void param_check_opr_num(const char *opr); -static uint32_t param_get_file_size(const char *file_name); -static uint32_t param_get_str_size(char *string); -static void main_print_version(void); -static void tool_usage(void); -static void exit_uart_app(int32_t exit_status); - -enum EXIT_CODE { - EC_OK = 0x00, - EC_PORT_ERR = 0x01, - EC_BAUDRATE_ERR = 0x02, - EC_SYNC_ERR = 0x03, - EC_DEV_NUM_ERR = 0x04, - EC_OPR_MUM_ERR = 0x05, - EC_ALIGN_ERR = 0x06, - EC_FILE_ERR = 0x07, - EC_UNSUPPORTED_CMD_ERR = 0x08 -}; - -/*--------------------------------------------------------------------------- - * Function implementation - *--------------------------------------------------------------------------- - */ - -/*--------------------------------------------------------------------------- - * Function: image_auto_write - * - * Parameters: offset - The start address of the flash to write the firmware - * to. - * buffer - The buffer holds data of the firmware. - * file_size - the size to be programmed. - * Returns: 1 for a successful operation, 0 otherwise. - * Side effects: - * Description: - * Divide the firmware to segments and program them one by one. - *--------------------------------------------------------------------------- - */ -static bool image_auto_write(uint32_t offset, uint8_t *buffer, - uint32_t file_size) -{ - uint32_t data_buf[4]; - uint32_t addr, chunk_remain, file_seg, flash_index, seg; - uint32_t count, percent, total; - uint32_t i; - - flash_index = offset; - /* Monitor tag */ - data_buf[0] = MONITOR_HDR_TAG; - - file_seg = file_size; - total = 0; - while (file_seg) { - seg = (file_seg > FIRMWARE_SEGMENT) ? - FIRMWARE_SEGMENT : file_seg; - /* - * Check if the content of the segment is all 0xff. - * If yes, there is no need to write. - * Call the monitor to erase the segment only for - * time efficiency. - */ - for (i = 0; i < seg && buffer[i] == 0xFF; i++) - ; - if (i == seg) { - data_buf[1] = seg; - /* - * Set src_addr = 0 as a flag. When the monitor read 0 - * from this field, it will do sector erase only. - */ - data_buf[2] = 0; - data_buf[3] = flash_index; - opr_write_chunk((uint8_t *)data_buf, MONITOR_HDR_ADDR, - sizeof(data_buf)); - if (opr_execute_return(MONITOR_ADDR) != true) - return false; - file_seg -= seg; - flash_index += seg; - buffer += seg; - total += seg; - percent = total * 100 / file_size; - printf("\r[%d%%] %d/%d", percent, total, file_size); - fflush(stdout); - continue; - } - chunk_remain = seg; - addr = FIRMWARE_START_ADDR; - /* the size to be programmed */ - data_buf[1] = seg; - /* The source(RAM) address where the firmware is stored. */ - data_buf[2] = FIRMWARE_START_ADDR; - /* - * The offset of the flash where the segment to be programmed. - */ - data_buf[3] = flash_index; - /* Write the monitor header to RAM */ - opr_write_chunk((uint8_t *)data_buf, MONITOR_HDR_ADDR, - sizeof(data_buf)); - while (chunk_remain) { - count = (chunk_remain > MAX_RW_DATA_SIZE) ? - MAX_RW_DATA_SIZE : chunk_remain; - if (opr_write_chunk(buffer, addr, count) != true) - return false; - - addr += count; - buffer += count; - chunk_remain -= count; - total += count; - percent = total * 100 / file_size; - printf("\r[%d%%] %d/%d", percent, total, file_size); - } - fflush(stdout); - if (opr_execute_return(MONITOR_ADDR) != true) - return false; - file_seg -= seg; - flash_index += seg; - } - printf("\n"); - /* Clear the UUT header tag */ - data_buf[0] = 0; - opr_write_chunk((uint8_t *)data_buf, MONITOR_HDR_ADDR, 4); - return true; -} - -static bool get_flash_size(uint32_t *flash_size) -{ - uint8_t dev_id, chip_id, i; - - if (opr_read_chunk(&dev_id, NPCX_DEVICE_ID_CR, 1) != true) - return false; - - if (opr_read_chunk(&chip_id, NPCX_SRID_CR, 1) != true) - return false; - - for (i = 0; i < ARRAY_SIZE(chip_info); i++) { - if (chip_info[i].device_id == dev_id && - chip_info[i].chip_id == chip_id) { - *flash_size = chip_info[i].flash_size; - return true; - } - } - printf("Unknown NPCX device ID:0x%02x chip ID:0x%02x\n", - dev_id, chip_id); - - return false; -} - -/*--------------------------------------------------------------------------- - * Function: read_input_file - * - * Parameters: size - The size of input file. - * file_name - The name if input file. - * Returns: The address of the buffer allocated to stroe file content. - * Side effects: - * Description: - * Read the file content into an allocated buffer. - *--------------------------------------------------------------------------- - */ -static uint8_t *read_input_file(uint32_t size, const char *file_name) -{ - uint8_t *buffer; - FILE *input_fp; - - buffer = (uint8_t *)(malloc(size)); - if (!buffer) { - fprintf(stderr, "Cannot allocate %d bytes\n", size); - return NULL; - } - input_fp = fopen(file_name, "r"); - if (!input_fp) { - display_color_msg(FAIL, - "ERROR: cannot open file %s\n", file_name); - free(buffer); - return NULL; - } - if (fread(buffer, size, 1, input_fp) != 1) { - fprintf(stderr, "Cannot read %s\n", file_name); - fclose(input_fp); - free(buffer); - return NULL; - } - fclose(input_fp); - return buffer; -} - -/*--------------------------------------------------------------------------- - * Function: main - * - * Parameters: argc - Argument Count. - * argv - Argument Vector. - * Returns: 1 for a successful operation, 0 otherwise. - * Side effects: - * Description: - * Console application main operation. - *--------------------------------------------------------------------------- - */ -int main(int argc, char *argv[]) -{ - char *stop_str; - char aux_buf[MAX_FILE_NAME_SIZE]; - uint32_t size = 0; - uint32_t addr = 0; - enum sync_result sr; - uint8_t *buffer; - int sync_cnt; - - if (argc <= 1) - exit(EC_UNSUPPORTED_CMD_ERR); - - /* Setup defaults */ - strncpy(port_name, DEFAULT_PORT_NAME, sizeof(port_name)); - baudrate = DEFAULT_BAUD_RATE; - dev_num = DEFAULT_DEV_NUM; - flash_offset = DEFAULT_FLASH_OFFSET; - opr_name[0] = '\0'; - verbose = true; - console = false; - auto_mode = false; - read_flash_flag = false; - - param_parse_cmd_line(argc, argv); - - /* Configure COM Port parameters */ - port_cfg.baudrate = MAX(baudrate, BR_LOW_LIMIT); - port_cfg.byte_size = CS8; - port_cfg.flow_control = 0; - port_cfg.parity = 0; - port_cfg.stop_bits = 0; - - /* - * Open a ComPort device. If user haven't specified such, use ComPort 1 - */ - if (opr_open_port(port_name, port_cfg) != true) - exit(EC_PORT_ERR); - - if (baudrate == 0) { /* Scan baud rate range */ - opr_scan_baudrate(); - exit_uart_app(EC_OK); - } - - /* Verify Host and Device are synchronized */ - DISPLAY_MSG(("Performing a Host/Device synchronization check...\n")); - for (sync_cnt = 1; sync_cnt <= MAX_SYNC_RETRIES; sync_cnt++) { - sr = opr_check_sync(baudrate); - if (sr == SR_OK) - break; - /* - * If it fails, try it again up to three times. - * It might fail for garbage data drainage from H1, or - * for timeout due to unstable data transfer yet. - */ - display_color_msg(FAIL, - "Host/Device synchronization failed, error = %d," - " fail count = %d\n", sr, sync_cnt); - } - if (sync_cnt > MAX_SYNC_RETRIES) - exit_uart_app(EC_SYNC_ERR); - - if (auto_mode) { - size = param_get_file_size(file_name); - if (size == 0) - exit_uart_app(EC_FILE_ERR); - - buffer = read_input_file(size, file_name); - if (!buffer) - exit_uart_app(EC_FILE_ERR); - - printf("Write file %s at %d with %d bytes\n", - file_name, flash_offset, size); - if (image_auto_write(flash_offset, buffer, size)) { - printf("Flash Done.\n"); - free(buffer); - exit_uart_app(EC_OK); - } - free(buffer); - exit_uart_app(-1); - } - - if (read_flash_flag) { - uint32_t flash_size; - - if (get_flash_size(&flash_size)) { - printf("Read %d bytes from flash...\n", flash_size); - opr_read_mem(file_name, NPCX_FLASH_BASE_ADDR, - flash_size); - exit_uart_app(EC_OK); - } - - printf("Fail to read the flash size\n"); - exit_uart_app(-1); - } - - param_check_opr_num(opr_name); - - /* Write buffer data to chosen address */ - if (strcmp(opr_name, OPR_WRITE_MEM) == 0) { - addr = strtoull(addr_str, &stop_str, 0); - - if (console) { - /* - * Copy the input string to an auxiliary buffer, since - * string is altered by param_get_str_size - */ - memcpy(aux_buf, file_name, sizeof(file_name)); - /* Retrieve input size */ - size = param_get_str_size(file_name); - /* Ensure non-zero size */ - if (size == 0) - exit_uart_app(EC_FILE_ERR); - opr_write_mem((uint8_t *)(aux_buf), addr, size); - } else { - size = param_get_file_size(file_name); - if (size == 0) - exit_uart_app(EC_FILE_ERR); - buffer = read_input_file(size, file_name); - if (!buffer) - exit_uart_app(EC_FILE_ERR); - opr_write_mem(buffer, addr, size); - free(buffer); - } - } else if (strcmp(opr_name, OPR_READ_MEM) == 0) { - /* Read data to chosen address */ - - addr = strtoull(addr_str, &stop_str, 0); - size = strtoull(size_str, &stop_str, 0); - - opr_read_mem(file_name, addr, size); - } else if (strcmp(opr_name, OPR_EXECUTE_EXIT) == 0) { - /* Execute From Address a non-return code */ - - addr = strtoull(addr_str, &stop_str, 0); - - opr_execute_exit(addr); - exit_uart_app(EC_OK); - } else if (strcmp(opr_name, OPR_EXECUTE_CONT) == 0) { - /* Execute From Address a returnable code */ - - addr = strtoull(addr_str, &stop_str, 0); - - opr_execute_return(addr); - } else { - exit_uart_app(EC_UNSUPPORTED_CMD_ERR); - } - - exit_uart_app(EC_OK); - return 0; -} - -/*--------------------------------------------------------------------------- - * Function: param_parse_cmd_line - * - * Parameters: argc - Argument Count. - * argv - Argument Vector. - * Returns: None. - * Side effects: - * Description: - * Parse command line parameters. - *--------------------------------------------------------------------------- - */ - -static const struct option long_opts[] = { - {"version", 0, 0, 'v'}, - {"help", 0, 0, 'h'}, - {"quiet", 0, 0, 'q'}, - {"console", 0, 0, 'c'}, - {"auto", 0, 0, 'A'}, - {"read-flash", 0, 0, 'r'}, - {"baudrate", 1, 0, 'b'}, - {"opr", 1, 0, 'o'}, - {"port", 1, 0, 'p'}, - {"file", 1, 0, 'f'}, - {"addr", 1, 0, 'a'}, - {"size", 1, 0, 's'}, - {"offset", 1, 0, 'O'}, - {NULL, 0, 0, 0} -}; - -static const char *short_opts = "vhqcArb:o:p:f:a:s:O:?"; - -static void param_parse_cmd_line(int argc, char *argv[]) -{ - int opt, idx; - - while ((opt = getopt_long(argc, argv, short_opts, - long_opts, &idx)) != -1) { - - switch (opt) { - case 'v': - main_print_version(); - exit(EC_OK); - case 'h': - case '?': - tool_usage(); - opr_usage(); - exit(EC_OK); - case 'q': - verbose = false; - break; - case 'c': - console = true; - break; - case 'A': - auto_mode = true; - break; - case 'r': - read_flash_flag = true; - break; - case 'b': - if (sscanf(optarg, "%du", &baudrate) == 0) - exit(EC_BAUDRATE_ERR); - break; - case 'o': - strncpy(opr_name, optarg, sizeof(opr_name)); - opr_name[sizeof(opr_name)-1] = '\0'; - break; - case 'p': - strncpy(port_name, optarg, sizeof(port_name)); - port_name[sizeof(port_name)-1] = '\0'; - break; - case 'f': - strncpy(file_name, optarg, sizeof(file_name)); - file_name[sizeof(file_name)-1] = '\0'; - break; - case 'a': - strncpy(addr_str, optarg, sizeof(addr_str)); - addr_str[sizeof(addr_str)-1] = '\0'; - break; - case 's': - strncpy(size_str, optarg, sizeof(size_str)); - size_str[sizeof(size_str)-1] = '\0'; - break; - case 'O': - flash_offset = strtol(optarg, NULL, 0); - break; - } - } -} - -/*--------------------------------------------------------------------------- - * Function: param_check_opr_num - * - * Parameters: opr - Operation Number. - * Returns: none. - * Side effects: - * Description: - * Verify the validity of operation Number. - *--------------------------------------------------------------------------- - */ -static void param_check_opr_num(const char *opr) -{ - - if ((strcasecmp(opr, OPR_WRITE_MEM) != 0) && - (strcasecmp(opr, OPR_READ_MEM) != 0) && - (strcasecmp(opr, OPR_EXECUTE_EXIT) != 0) && - (strcasecmp(opr, OPR_EXECUTE_CONT) != 0)) { - display_color_msg(FAIL, - "ERROR: Operation %s not supported, Supported " - "operations are %s, %s, %s & %s\n", - opr, OPR_WRITE_MEM, OPR_READ_MEM, OPR_EXECUTE_EXIT, - OPR_EXECUTE_CONT); - exit_uart_app(EC_OPR_MUM_ERR); - } -} - -/*--------------------------------------------------------------------------- - * Function: param_get_file_size - * - * Parameters: file_name - input file name. - * Returns: size of file (in bytes). - * Side effects: - * Description: - * Retrieve the size (in bytes) of a given file. - *-------------------------------------------------------------------------- - */ -static uint32_t param_get_file_size(const char *file_name) -{ - struct stat fst; - - if (stat(file_name, &fst)) { - display_color_msg(FAIL, - "ERROR: Could not stat file [%s]\n", file_name); - return 0; - } - return fst.st_size; - -} - -/*--------------------------------------------------------------------------- - * Function: param_get_str_size - * - * Parameters: string - input string. - * Returns: size of double-words (in bytes). - * Side effects: - * Description: - * Retrieve the size (in bytes) of double-word values in a given string. - * E.g., given the string "1234 AB5678 FF", return 12 (for three - * double-words). - *--------------------------------------------------------------------------- - */ -static uint32_t param_get_str_size(char *string) -{ - uint32_t str_size = 0; - char seps[] = " "; - char *token = NULL; - - /* Verify string is non-NULL */ - if ((string == NULL) || (strlen(string) == 0)) { - display_color_msg(FAIL, - "ERROR: Zero length input string provided\n"); - return 0; - } - - /* Read first token from string */ - token = strtok(string, seps); - - /* Loop while there are tokens in "string" */ - while (token != NULL) { - str_size++; - token = strtok(NULL, seps); - } - - /* Refer to each token as a double-word */ - str_size *= sizeof(uint32_t); - return str_size; -} - -/*-------------------------------------------------------------------------- - * Function: tool_usage - * - * Parameters: none. - * Returns: none. - * Side effects: - * Description: - * Prints the console application help menu. - *-------------------------------------------------------------------------- - */ -static void tool_usage(void) -{ - printf("%s version %s\n\n", tool_name, tool_version); - printf("General switches:\n"); - printf(" -v, --version - Print version\n"); - printf(" -h, --help - Help menu\n"); - printf(" -q, --quiet - Suppress verbose mode (default is " - "verbose ON)\n"); - printf(" -c, --console - Print data to console (default is " - "print to file)\n"); - printf(" -p, --port <name> - Serial port name (default is %s)\n", - DEFAULT_PORT_NAME); - printf(" -b, --baudrate <num> - COM Port baud-rate (default is %d)\n", - DEFAULT_BAUD_RATE); - printf(" -A, --auto - Enable auto mode. (default is off)\n"); - printf(" -O, --offset <num> - With --auto, assign the offset of"); - printf(" flash where the image to be written.\n"); - printf(" -r, --read-flash - With --file=<file>, Read the whole" - " flash content and write it to <file>.\n"); - printf("\n"); - printf("Operation specific switches:\n"); - printf(" -o, --opr <name> - Operation number (see list below)\n"); - printf(" -f, --file <name> - Input/output file name\n"); - printf(" -a, --addr <num> - Start memory address\n"); - printf(" -s, --size <num> - Size of data to read\n"); - printf("\n"); -} - -/*-------------------------------------------------------------------------- - * Function: main_print_version - * - * Parameters: none - * Returns: none - * Side effects: - * Description: - * This routine prints the tool version - *-------------------------------------------------------------------------- - */ -static void main_print_version(void) -{ - printf("%s version %s\n\n", tool_name, tool_version); -} - -/*--------------------------------------------------------------------------- - * Function: exit_uart_app - * - * Parameters: none. - * Returns: none. - * Side effects: - * Description: - * Exit "nicely" the application. - *--------------------------------------------------------------------------- - */ -static void exit_uart_app(int32_t exit_status) -{ - if (opr_close_port() != true) - display_color_msg(FAIL, "ERROR: Port close failed.\n"); - - exit(exit_status); -} - -/*--------------------------------------------------------------------------- - * Function: display_color_msg - * - * Parameters: - * success - SUCCESS for successful message, FAIL for erroneous - * massage. - * fmt - Massage to dispaly (format and arguments). - * - * Returns: none - * Side effects: Using DISPLAY_MSG macro. - * Description: - * This routine displays a message using color attributes: - * In case of a successful message, use green foreground text on - * black background. - * In case of an erroneous message, use red foreground text on - * black background. - *--------------------------------------------------------------------------- - */ -void display_color_msg(bool success, const char *fmt, ...) -{ - va_list argptr; - - va_start(argptr, fmt); - vprintf(fmt, argptr); - va_end(argptr); -} diff --git a/util/uut/main.h b/util/uut/main.h deleted file mode 100644 index 2885e7368a..0000000000 --- a/util/uut/main.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef __UTIL_UUT_MAIN_H -#define __UTIL_UUT_MAIN_H - -#include <stdbool.h> - -/*--------------------------------------------------------------------------- - * Constant definitions - *--------------------------------------------------------------------------- - */ -/* Maximum Read/Write data size per packet */ -#define MAX_RW_DATA_SIZE 256 - -/* Base for string conversion */ -#define BASE_DECIMAL 10 -#define BASE_HEXADECIMAL 16 - -/* Verbose control messages display */ -#define DISPLAY_MSG(msg) \ -{ \ - if (verbose) \ - printf msg; \ -} - -#define SUCCESS true -#define FAIL false - -#ifdef __cplusplus -extern "C" { -#endif - -/*-------------------------------------------------------------------------- - * Global variables - *-------------------------------------------------------------------------- - */ - -extern bool verbose; -extern bool console; - -/*-------------------------------------------------------------------------- - * Global functions - *-------------------------------------------------------------------------- - */ - -/*--------------------------------------------------------------------------- - * Function: display_color_msg - * - * Parameters: - * success - SUCCESS for successful message, FAIL for erroneous - * massage. - * fmt - Massage to dispaly (format and arguments). - * - * Returns: none - * Side effects: Using DISPLAY_MSG macro. - * Description: - * This routine displays a message using color attributes: - * In case of a successful message, use green foreground text on - * black background. - * In case of an erroneous message, use red foreground text on - * black background. - *-------------------------------------------------------------------------- - */ -void display_color_msg(bool success, const char *fmt, ...); - -#ifdef __cplusplus -} -#endif - -#endif /* __UTIL_UUT_MAIN_H */ diff --git a/util/uut/opr.c b/util/uut/opr.c deleted file mode 100644 index 2105a199a1..0000000000 --- a/util/uut/opr.c +++ /dev/null @@ -1,553 +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 file implements the UART console application operations. */ - -#ifndef _GNU_SOURCE -#define _GNU_SOURCE /* for asprintf */ -#endif - -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> -#include <unistd.h> - -#include "com_port.h" -#include "cmd.h" -#include "main.h" -#include "misc_util.h" -#include "opr.h" - -/*---------------------------------------------------------------------------- - * Global Variables - *--------------------------------------------------------------------------- - */ -int port_handle = INVALID_HANDLE_VALUE; - -/*---------------------------------------------------------------------------- - * Constant definitions - *--------------------------------------------------------------------------- - */ -#define MAX_PORT_NAME_SIZE 32 -#define OPR_TIMEOUT 10L /* 10 seconds */ -#define FLASH_ERASE_TIMEOUT 120L /* 120 seconds */ - -#define STS_MSG_MIN_SIZE 8 -#define STS_MSG_APP_END 0x09 - -#define MAX_SYNC_TRIALS 3 - -/*---------------------------------------------------------------------------- - * Global variables - *--------------------------------------------------------------------------- - */ -struct command_node cmd_buf[MAX_CMD_BUF_SIZE]; -uint8_t resp_buf[MAX_RESP_BUF_SIZE]; - -/*--------------------------------------------------------------------------- - * Functions prototypes - *--------------------------------------------------------------------------- - */ -static bool opr_send_cmds(struct command_node *cmd_buf, uint32_t cmd_num); - -/*---------------------------------------------------------------------------- - * Function implementation - *---------------------------------------------------------------------------- - */ - -/*---------------------------------------------------------------------------- - * Function: opr_usage - * - * Parameters: none. - * Returns: none. - * Side effects: - * Description: - * Prints the console application operation menu. - *--------------------------------------------------------------------------- - */ -void opr_usage(void) -{ - printf("Operations:\n"); - printf(" %s\t\t- Write To Memory/Flash\n", OPR_WRITE_MEM); - printf(" %s\t\t- Read From Memory/Flash\n", OPR_READ_MEM); - printf(" %s\t\t- Execute a non-return code\n", OPR_EXECUTE_EXIT); - printf(" %s\t\t- Execute a returnable code\n", OPR_EXECUTE_CONT); -} - -/*---------------------------------------------------------------------------- - * Function: opr_close_port - * - * Parameters: none - * Returns: - * Side effects: - * Description: - * This routine closes the opened COM port by the application - *--------------------------------------------------------------------------- - */ -bool opr_close_port(void) -{ - return com_port_close(port_handle); -} - -/*---------------------------------------------------------------------------- - * Function: opr_open_port - * - * Parameters: port_name - COM Port name. - * port_cfg - COM Port configuration structure. - * Returns: 1 if successful, 0 in the case of an error. - * Side effects: - * Description: - * Open a specified ComPort device. - *--------------------------------------------------------------------------- - */ -bool opr_open_port(const char *port_name, struct comport_fields port_cfg) -{ - char *full_port_name; - - if (asprintf(&full_port_name, "/dev/%s", port_name) == -1) - return false; - - if (port_handle > 0) - com_port_close(port_handle); - - port_handle = com_port_open((const char *)full_port_name, port_cfg); - - if (port_handle <= 0) { - display_color_msg(FAIL, "\nERROR: COM Port failed to open.\n"); - DISPLAY_MSG( - ("Please select the right serial port or check if " - "other serial\n")); - DISPLAY_MSG(("communication applications are opened.\n")); - return false; - } - - display_color_msg(SUCCESS, "Port %s Opened\n", full_port_name); - - return true; -} - -/*---------------------------------------------------------------------------- - * Function: opr_write_chunk - * - * Parameters: - * buffer - Input data buffer. - * addr - Memory address to write to. - * size - Data size to write. - * Returns: true if successful, false in the case of an error. - * Side effects: - * Description: - * Write data to RAM, starting from the given address (addr). - * Data size is limited to the max chunk size (256 bytes). - *--------------------------------------------------------------------------- - */ -bool opr_write_chunk(uint8_t *buffer, uint32_t addr, uint32_t size) -{ - struct command_node wr_cmd_buf; - - if (size > MAX_RW_DATA_SIZE) { - display_color_msg(FAIL, - "ERROR: Block cannot exceed %d\n", MAX_RW_DATA_SIZE); - } - /* Initialize response size */ - wr_cmd_buf.resp_size = 1; - cmd_create_write(addr, size, buffer, - wr_cmd_buf.cmd, &wr_cmd_buf.cmd_size); - return opr_send_cmds(&wr_cmd_buf, 1); -} - -/*---------------------------------------------------------------------------- - * Function: opr_read_chunk - * - * Parameters: - * buffer - Data read buffer. - * addr - Memory address to read from. - * size - Data size to read. - * Returns: true if successful, false in the case of an error. - * Side effects: - * Description: - * Read data from RAM, starting from the given address (addr). - * Data size is limited to the max chunk size (256 bytes). - *--------------------------------------------------------------------------- - */ -bool opr_read_chunk(uint8_t *buffer, uint32_t addr, uint32_t size) -{ - struct command_node rd_cmd_buf; - - if (size > MAX_RW_DATA_SIZE) { - display_color_msg(FAIL, - "ERROR: Block cannot exceed %d\n", MAX_RW_DATA_SIZE); - return false; - } - - cmd_create_read(addr, ((uint8_t)size - 1), - rd_cmd_buf.cmd, &rd_cmd_buf.cmd_size); - rd_cmd_buf.resp_size = size + 3; - if (opr_send_cmds(&rd_cmd_buf, 1)) { - if (resp_buf[0] == (uint8_t)(UFPP_READ_CMD)) { - memcpy(buffer, &resp_buf[1], size); - return true; - } - } - return false; -} -/*---------------------------------------------------------------------------- - * Function: opr_write_mem - * - * Parameters: input - Input (file-name/console), containing data to write. - * addr - Memory address to write to. - * size - Data size to write. - * Returns: none. - * Side effects: - * Description: - * Write data to memory, starting from a given address. - * Memory may be Flash (SPI), DRAM (DDR) or SRAM. - * The data is retrieved either from an input file or from a console. - * Data size is not limited. - * Data is sent in 256 bytes chunks (file mode) or 4 bytes chunks - * (console mode). - *--------------------------------------------------------------------------- - */ -void opr_write_mem(uint8_t *buffer, uint32_t addr, uint32_t size) -{ - uint32_t cur_addr = addr; - uint8_t data_buf[256]; - uint32_t write_size, size_remain; - uint32_t cmd_idx = 1; - char seps[] = " "; - char *token = NULL; - char *stop_str; - uint32_t block_size = (console) ? sizeof(uint32_t) : MAX_RW_DATA_SIZE; - struct command_node wr_cmd_buf; - - /* Initialize response size */ - wr_cmd_buf.resp_size = 1; - - DISPLAY_MSG(("Writing [%d] bytes in [%d] packets\n", size, - ((size + (block_size - 1)) / block_size))); - - /* Read first token from string */ - if (console) - token = strtok((char *)(buffer), seps); - - size_remain = size; - /* Main write loop */ - while (true) { - if (console) { - /* - * Invert token to double-word and insert the value to - * data buffer - */ - (*(uint32_t *)data_buf) = - strtoull(token, &stop_str, BASE_HEXADECIMAL); - - /* Prepare the next iteration */ - token = strtok(NULL, seps); - } - write_size = (size_remain > block_size) ? - block_size : size_remain; - if (console) { - cmd_create_write(cur_addr, write_size, data_buf, - wr_cmd_buf.cmd, &wr_cmd_buf.cmd_size); - } else { - cmd_create_write(cur_addr, write_size, buffer, - wr_cmd_buf.cmd, &wr_cmd_buf.cmd_size); - buffer += write_size; - } - if (opr_send_cmds(&wr_cmd_buf, 1) != true) - break; - - cmd_disp_write(resp_buf, write_size, cmd_idx, - ((size + (block_size - 1)) / block_size)); - cur_addr += write_size; - size_remain -= write_size; - cmd_idx++; - if (size_remain == 0) - break; - } - - DISPLAY_MSG(("\n")); -} - -/*---------------------------------------------------------------------------- - * Function: opr_read_mem - * - * Parameters: output - Output file name, containing data that was read. - * addr - Memory address to read from. - * size - Data size to read. - * Returns: none. - * Side effects: - * Description: - * Read data from memory, starting from a given address. - * Memory may be Flash (SPI), DRAM (DDR) or SRAM. - * The data is written into an output file, data size is limited - * as specified. - * Data is received in 256 bytes chunks. - *--------------------------------------------------------------------------- - */ -void opr_read_mem(char *output, uint32_t addr, uint32_t size) -{ - FILE *output_file_id = NULL; - uint32_t cur_addr; - uint32_t bytes_left; - uint32_t read_size; - uint32_t cmd_idx = 1; - struct command_node rd_cmd_buf; - - if (!console) { - output_file_id = fopen(output, "w+b"); - - if (output_file_id == NULL) { - display_color_msg(FAIL, - "ERROR: could not open output file [%s]\n", - output); - return; - } - } - - DISPLAY_MSG(("Reading [%d] bytes in [%d] packets\n", size, - ((size + (MAX_RW_DATA_SIZE - 1)) / MAX_RW_DATA_SIZE))); - - for (cur_addr = addr; cur_addr < (addr + size); - cur_addr += MAX_RW_DATA_SIZE) { - bytes_left = (uint32_t)(addr + size - cur_addr); - read_size = MIN(bytes_left, MAX_RW_DATA_SIZE); - - cmd_create_read(cur_addr, ((uint8_t)read_size - 1), - rd_cmd_buf.cmd, &rd_cmd_buf.cmd_size); - rd_cmd_buf.resp_size = read_size + 3; - - if (opr_send_cmds(&rd_cmd_buf, 1) != true) - break; - - cmd_disp_read(resp_buf, read_size, cmd_idx, - ((size + (MAX_RW_DATA_SIZE - 1)) / MAX_RW_DATA_SIZE)); - - if (console) - cmd_disp_data((resp_buf + 1), read_size); - else - fwrite((resp_buf + 1), 1, read_size, output_file_id); - - cmd_idx++; - } - - DISPLAY_MSG(("\n")); - if (!console) - fclose(output_file_id); -} - -/*---------------------------------------------------------------------------- - * Function: opr_execute_exit - * - * Parameters: addr - Start address to execute from. - * Returns: none. - * Side effects: ROM-Code is not in UART command mode anymore. - * Description: - * Execute code starting from a given address. - * Memory address may be in Flash (SPI), DRAM (DDR) or SRAM. - * No further communication with thr ROM-Code is expected at this point. - *--------------------------------------------------------------------------- - */ -void opr_execute_exit(uint32_t addr) -{ - uint32_t cmd_num; - - cmd_build_exec_exit(addr, cmd_buf, &cmd_num); - if (opr_send_cmds(cmd_buf, cmd_num) != true) - return; - - cmd_disp_exec_exit(resp_buf); -} - -/*---------------------------------------------------------------------------- - * Function: opr_execute_return - * - * Parameters: addr - Start address to execute from. - * Returns: true if successful, false in the case of an error. - * Side effects: - * Description: - * Execute code starting from the given address and then check the result. - * The executed code should return with the execution result. - *--------------------------------------------------------------------------- - */ -bool opr_execute_return(uint32_t addr) -{ - uint32_t cmd_num; - - cmd_build_exec_ret(addr, cmd_buf, &cmd_num); - if (opr_send_cmds(cmd_buf, cmd_num) != true) - return false; - - /* - * Check the response command code is UFPP_FCALL_RSLT_CMD and - * the return value from monitor is 0x03. (program finish and verify ok) - */ - if (resp_buf[1] != (uint8_t)(UFPP_FCALL_RSLT_CMD) - || resp_buf[2] != 0x03) - return false; - return true; -} - -/*---------------------------------------------------------------------------- - * Function: opr_check_sync - * - * Parameters: - * baudrate - baud rate to check - * - * Returns: - * Side effects: - * Description: - * Checks whether the Host and the Core are synchoronized in the - * specified baud rate - *--------------------------------------------------------------------------- - */ -enum sync_result opr_check_sync(uint32_t baudrate) -{ - uint32_t cmd_num; - struct command_node *cur_cmd = cmd_buf; - uint32_t bytes_read = 0; - uint32_t i; - - port_cfg.baudrate = baudrate; - if (!com_config_uart(port_handle, port_cfg)) - return SR_ERROR; - - cmd_build_sync(cmd_buf, &cmd_num); - - if (!com_port_write_bin(port_handle, cur_cmd->cmd, cur_cmd->cmd_size)) - return SR_ERROR; - - /* Allow several SYNC trials */ - for (i = 0; i < MAX_SYNC_TRIALS; i++) { - bytes_read = com_port_read_bin(port_handle, resp_buf, 1); - - /* Quit if succeeded to read a response */ - if (bytes_read == 1) - break; - /* Otherwise give the ROM-Code time to answer */ - sleep(1); - } - - if (bytes_read == 0) - /* - * Unable to read a response from ROM-Code in a reasonable - * time - */ - return SR_TIMEOUT; - - if (resp_buf[0] != (uint8_t)(UFPP_D2H_SYNC_CMD)) - /* ROM-Code response is not as expected */ - return SR_WRONG_DATA; - - /* Good response */ - return SR_OK; -} - -/*---------------------------------------------------------------------------- - * Function: opr_scan_baudrate - * - * Parameters: none - * Returns: - * Side effects: - * Description: - * Scans the baud rate range by sending sync request to the core - * and prints the response - *--------------------------------------------------------------------------- - */ -bool opr_scan_baudrate(void) -{ - uint32_t baud = 0; - uint32_t step; - enum sync_result sr; - bool synched = false; - bool data_received = false; - - /* Scan with HUGE STEPS */ - /* BR_BIG_STEP is percents */ - step = (BR_LOW_LIMIT * BR_BIG_STEP) / 100; - for (baud = BR_LOW_LIMIT; baud < BR_HIGH_LIMIT; baud += step) { - sr = opr_check_sync(baud); - step = (baud * BR_BIG_STEP) / 100; - if (sr == SR_OK) { - printf("SR_OK: Baud rate - %d, resp_buf - 0x%x\n", - baud, resp_buf[0]); - synched = true; - step = (baud * BR_SMALL_STEP) / 100; - } else if (sr == SR_WRONG_DATA) { - printf("SR_WRONG_DATA: Baud rate - %d, resp_buf - " - "0x%x\n", baud, resp_buf[0]); - data_received = true; - step = (baud * BR_MEDIUM_STEP) / 100; - } else if (sr == SR_TIMEOUT) { - printf("SR_TIMEOUT: Baud rate - %d, resp_buf - 0x%x\n", - baud, resp_buf[0]); - - if (synched || data_received) - break; - } else if (sr == SR_ERROR) { - printf("SR_ERROR: Baud rate - %d, resp_buf - 0x%x\n", - baud, resp_buf[0]); - if (synched || data_received) - break; - } else - printf("Unknown error code: Baud rate - %d, resp_buf - " - "0x%x\n", baud, resp_buf[0]); - } - - return true; -} - -/*---------------------------------------------------------------------------- - * Function: opr_send_cmds - * - * Parameters: cmd_buf - Pointer to a Command Buffer. - * cmd_num - Number of commands to send. - * Returns: 1 if successful, 0 in the case of an error. - * Side effects: - * Description: - * Send a group of commands through COM port. - * A command is sent only after a valid response for the previous command - * was received. - *--------------------------------------------------------------------------- - */ -static bool opr_send_cmds(struct command_node *cmd_buf, uint32_t cmd_num) -{ - struct command_node *cur_cmd = cmd_buf; - uint32_t cmd; - uint32_t read; - time_t start; - double elapsed_time; - - for (cmd = 0; cmd < cmd_num; cmd++, cur_cmd++) { - if (com_port_write_bin(port_handle, cur_cmd->cmd, - cur_cmd->cmd_size) == true) { - time(&start); - - do { - read = com_port_wait_read(port_handle); - elapsed_time = difftime(time(NULL), start); - } while ((read < cur_cmd->resp_size) && - (elapsed_time <= OPR_TIMEOUT)); - com_port_read_bin(port_handle, resp_buf, - cur_cmd->resp_size); - - if (elapsed_time > OPR_TIMEOUT) - display_color_msg(FAIL, - "ERROR: [%d] bytes received for read, " - "[%d] bytes are expected\n", - read, cur_cmd->resp_size); - } else { - display_color_msg(FAIL, - "ERROR: Failed to send Command number %d\n", - cmd); - return false; - } - } - - return true; -} - diff --git a/util/uut/opr.h b/util/uut/opr.h deleted file mode 100644 index 3b166f0c7e..0000000000 --- a/util/uut/opr.h +++ /dev/null @@ -1,59 +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 file defines the UART console application operations. */ - -#ifndef __UTIL_UUT_OPR_H -#define __UTIL_UUT_OPR_H - -/*--------------------------------------------------------------------------- - * Constant definitions - *--------------------------------------------------------------------------- - */ - -/* Baud rate scan steps: */ -#define BR_BIG_STEP 20 /* in percents from current baud rate */ -#define BR_MEDIUM_STEP 10 /* in percents from current baud rate */ -#define BR_SMALL_STEP 1 /* in percents from current baud rate */ -#define BR_MIN_STEP 5 /* in absolute baud rate units */ -#define BR_LOW_LIMIT 400 /* Automatic BR detection starts at this value */ -#define BR_HIGH_LIMIT 150000 /* Automatic BR detection ends at this value */ - -#define OPR_WRITE_MEM "wr" /* Write To Memory/Flash */ -#define OPR_READ_MEM "rd" /* Read From Memory/Flash */ -#define OPR_EXECUTE_EXIT "go" /* Execute a non-return code */ -#define OPR_EXECUTE_CONT "call" /* Execute returnable code */ - -enum sync_result { - SR_OK = 0x00, - SR_WRONG_DATA = 0x01, - SR_TIMEOUT = 0x02, - SR_ERROR = 0x03 -}; - -/*---------------------------------------------------------------------------- - * External Variables - *--------------------------------------------------------------------------- - */ -extern struct comport_fields port_cfg; - -/*--------------------------------------------------------------------------- - * Functions prototypes - *--------------------------------------------------------------------------- - */ - -void opr_usage(void); -bool opr_close_port(void); -bool opr_open_port(const char *port_name, struct comport_fields port_cfg); -bool opr_write_chunk(uint8_t *buffer, uint32_t addr, uint32_t size); -bool opr_read_chunk(uint8_t *buffer, uint32_t addr, uint32_t size); -void opr_write_mem(uint8_t *buffer, uint32_t addr, uint32_t size); -void opr_read_mem(char *output, uint32_t addr, uint32_t size); -void opr_execute_exit(uint32_t addr); -bool opr_execute_return(uint32_t addr); -bool opr_scan_baudrate(void); -enum sync_result opr_check_sync(uint32_t baudrate); -#endif /* __UTIL_UUT_OPR_H */ diff --git a/util/volteer-relevant-paths.txt b/util/volteer-relevant-paths.txt deleted file mode 100644 index a45c44dcf6..0000000000 --- a/util/volteer-relevant-paths.txt +++ /dev/null @@ -1,15 +0,0 @@ -# Here you can place files of interest to be included in the commit message for -# merge commits to firmware-volteer-13672.B-main -chip/npcx/*npcx7* -driver/accel_bma2x2.* -driver/accelgyro_bmi260.* -driver/als_tcs3400.* -driver/bc12/piusb9201.* -driver/charger/isl9241.* -driver/ppc/sn5s330.* -driver/ppc/syv682x.* -driver/retimer/bb_retimer.* -driver/retimer/kb800x.* -driver/tcpm/ps8xxx.* -driver/tcpm/rt1715.* -driver/usb_mux/virtual.* |