| #!/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. |
| |
| readonly PREFIX="${HOME}/.local/hdctools" |
| readonly BRANCH='master' |
| readonly REPO=https://chromium.googlesource.com/chromiumos/third_party/hdctools |
| readonly PYUSBDIR="${PREFIX}/util/usb" |
| readonly PYUSB='v1.0.2' |
| readonly SERVOD_PYTHONPATH="${PREFIX}/lib/python2.7/site-packages" |
| readonly DEPS=(python-pexpect python-numpy python-setuptools |
| python-serial python-pytest tidy libftdi-dev curl gcc make |
| pkg-config) |
| FORCE='' |
| |
| |
| # Prints out a log message with the wrapper prefix. |
| info() { |
| echo "servod-wrapper: $*" >&2 |
| } |
| |
| |
| # Prints usage tips. |
| usage() { |
| info 'Installs and runs servod (or dut-control) from hdctools. |
| Wrapper usage: |
| servod [parameters] # Runs servod, first preparing it if necessary. |
| servod dut [parameters] # Runs dut-control, first preparing it if necessary. |
| dut-control [parameters] # Same as "servod dut" (via symlink). |
| servod install [-f] # Just prepares (or updates) servod. |
| servod uninstall # Removes the prepared servod install. |
| ' |
| } |
| |
| |
| # Downloads gitiles src file and decodes to stdout. |
| curl_src() { |
| curl -#f "$1?format=TEXT" | base64 -d |
| } |
| |
| |
| # Determine and install prereqs. |
| install_dependencies() { |
| local pkg needed=() |
| for pkg in "${DEPS[@]}"; do |
| if [[ ! -f "/usr/share/doc/${pkg}/copyright" ]]; then |
| needed+=("${pkg}") |
| fi |
| done |
| if [[ "${#needed[@]}" -gt 0 ]]; then |
| info "Installing prerequisite packages: ${needed[*]}" |
| sudo apt-get install "${needed[@]}" |
| fi |
| } |
| |
| |
| # Fetches the latest version of hdctools. |
| fetch_hdctools_version() { |
| local commit |
| info "Checking hdctools version (branch ${BRANCH})..." |
| commit="$(curl_src "${REPO}/+/${BRANCH}" \ |
| | grep -m 1 '^tree' \ |
| | cut -d' ' -f 2)" |
| printf "%s" "${BRANCH}-${commit:-unknown}" |
| } |
| |
| |
| # Downloads and patches hdctools. |
| download_hdctools() { |
| info "Downloading hdctools..." |
| curl -#f "${REPO}/+archive/${BRANCH}.tar.gz" | tar -xzm || return |
| # don't need warnings |
| echo 'HOSTOS_CWARN=' >> 'defs/c-Linux.mk' |
| # FIXME: improve EC Makefile so we don't need to hack out toad |
| sed -i 's/toad//' 'src/Makefile' |
| # Avoid servo_updater dependency by implementing a dummy servo_updater. |
| sed -i "s|import servo_updater|class servo_updater:\n FIRMWARE_PATH = '/='|g" \ |
| 'servo/drv/ec3po_servo.py' |
| # Use /tmp as default log directory rather than /var/log since we're not root. |
| sed -i "/^DEFAULT_LOG_DIR *=/s|'[^']*'|'/tmp'|" 'servo/servod.py' |
| } |
| |
| |
| # Grabs the latest EC3PO from the EC repo without cloning the whole thing. |
| download_ec3po() { |
| info "Downloading ec3po..." |
| local ec3po="${PREFIX}/util/ec3po" |
| mkdir -p "${ec3po}" |
| curl -#f 'https://chromium.googlesource.com/chromiumos/platform/ec/+archive/master/util/ec3po.tar.gz' \ |
| | tar -xz -C "${ec3po}" || return |
| # Extract just the ec3po section of setup.py |
| # FIXME: improve the setup.py so we can call only the chunk we want |
| curl_src 'https://chromium.googlesource.com/chromiumos/platform/ec/+/master/setup.py' \ |
| | awk ' |
| /^setup\(/ && x==0 { print; x=1 } |
| /name=.ec3po./ { x=2 } |
| x==2; |
| /^\)/ && x==2 { exit } |
| ' >> setup.py |
| if [[ ! -s 'setup.py' ]]; then |
| return 1 |
| fi |
| } |
| |
| |
| # Grabs a pyusb that matches the chroot. |
| download_pyusb() { |
| info "Downloading pyusb ${PYUSB}..." |
| mkdir -p "${PYUSBDIR}" |
| curl -#f "https://codeload.github.com/walac/pyusb/tar.gz/${PYUSB}" \ |
| | tar -xz -C "${PYUSBDIR}" |
| } |
| |
| |
| # Builds pyusb. |
| build_pyusb() { |
| mkdir -p "${SERVOD_PYTHONPATH}" |
| ( |
| cd "${PYUSBDIR}"/* || return |
| python setup.py build || return |
| python setup.py install --prefix="${PREFIX}" || return |
| ) |
| } |
| |
| |
| # Downloads, extracts, and compiles servod and prereqs. |
| prepare() { |
| install_dependencies || return |
| |
| # Store the commit hash in VCSID so that servod --version reports something. |
| VCSID="$(fetch_hdctools_version)" |
| export VCSID |
| |
| # Check version |
| if [[ "${VCSID%-unknown}" != "${VCSID}" ]]; then |
| info "Failed to determine hdctools version" |
| elif grep -qF "${VCSID}" "${PREFIX}/.version" 2>/dev/null; then |
| info "Same version already installed (${VCSID})." |
| if [[ -z "${FORCE}" ]]; then |
| info "Specify -f to reinstall." |
| return 0 |
| fi |
| else |
| info "Latest hdctools is ${VCSID}" |
| fi |
| |
| # Reset the prefix each time to ensure a clean slate. |
| rm -rf "${PREFIX}" |
| mkdir -p "${PREFIX}" |
| |
| # Download and build. |
| ( |
| cd "${PREFIX}" |
| |
| download_hdctools || return |
| download_ec3po || return |
| download_pyusb || return |
| |
| # Build and install into our own prefix. |
| info "Building and installing..." |
| build_pyusb || return |
| make DESTDIR="${PREFIX}" || return |
| python setup.py build || return |
| make DESTDIR="${PREFIX}" install || return |
| python setup.py install --prefix="${PREFIX}" || return |
| |
| # For some reason, the python eggs aren't properly populated with metadata |
| for pkg in servo usbkm232; do |
| cp -vft lib/python*/site-packages/"$pkg"-*/EGG-INFO "build/$pkg.egg-info/"* |
| done |
| ) || return |
| |
| # Store the VCSID on success. |
| echo "${VCSID}" > "${PREFIX}/.version" |
| |
| # Done; output usage. |
| info 'Finished preparing servod.' |
| usage |
| } |
| |
| |
| main() { |
| export LD_LIBRARY_PATH="${PREFIX}/usr/lib${LD_LIBRARY_PATH+:${LD_LIBRARY_PATH}}" |
| export PYTHONPATH="${SERVOD_PYTHONPATH}${PYTHONPATH+:${PYTHONPATH}}" |
| |
| local cmd="${1-}" |
| if [[ "${cmd}" == 'uninstall' ]]; then |
| rm -rvf "${PREFIX}" |
| return |
| elif [[ "${cmd}" != 'install' ]]; then |
| if [[ -d "${SERVOD_PYTHONPATH}" ]]; then |
| # Also support dut-control. |
| local servod="servo.servod" |
| local base="${0##*/}" |
| if [[ "${base#dut}" != "${base}" || "${cmd#dut}" != "${cmd}" ]]; then |
| servod="servo.dut_control" |
| if [[ "${base#dut}" == "${base}" ]]; then |
| shift |
| fi |
| elif [[ "${base#servodutil}" != "${base}" || "${cmd#servodutil}" != "${cmd}" ]]; then |
| servod="servo.servodutil" |
| if [[ "${base#servodutil}" == "${base}" ]]; then |
| shift |
| fi |
| elif [[ "${cmd}" == '-h' || "${cmd}" == '--help' ]]; then |
| usage |
| else |
| info "Note: you can update servod to ToT by running $0 install" |
| fi |
| python -m "${servod}" "$@" |
| return |
| fi |
| elif [[ "${cmd}" == 'install' ]]; then |
| if [[ "${2-}" == '-f' ]]; then |
| FORCE=y |
| fi |
| fi |
| |
| # Either an explicit or implicit install. |
| prepare || return |
| |
| # Relaunch if this wasn't an explicit install. |
| if [[ "${cmd}" != 'install' ]]; then |
| main "$@" |
| fi |
| } |
| set -eu |
| main "$@" |