普通文本  |  135行  |  3.27 KB

# 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.

"""A collection of classes representing TCPC firmware blobs.
"""

import logging
import os
import subprocess


class ChipUtilsError(Exception):
    """Error in the chip_utils module."""



class generic_chip(object):

    """A chip we don't actually support."""

    chip_name = 'unknown'
    fw_name = None

    def __init__(self):
        self.fw_ver = None
        self.fw_file_name = None

    def set_fw_ver_from_string(self, version):
        """Sets version property from string."""
        self.fw_ver = int(version, 0)

    def set_from_file(self, file_name):
        """Sets chip params from file name.

        The typical firmware blob file name format is: <chip>_0x00.bin

        Args:
            file_name: Firmware blob file name.

        Raises:
            ValueError: Failed to decompose firmware file name.
        """

        basename = os.path.basename(file_name)
        if not basename.startswith(self.chip_name):
            raise ValueError('filename did not start with %s' % self.chip_name)
        fname = basename.split('.')[0]
        if '_' in fname:
            rev = fname.split('_')[-1]
            self.set_fw_ver_from_string(rev)
        else:
            logging.info('No fw ver found in filename %s', basename)
        self.fw_file_name = file_name


class ps8751(generic_chip):

    """The PS8751 TCPC chip."""

    chip_name = 'ps8751'
    fw_name = 'ps8751_a3'
    cbfs_bin_name = fw_name + '.bin'
    cbfs_hash_name = fw_name + '.hash'

    def fw_ver_from_hash(self, blob):
        """Return the firmware version encoded in the firmware hash."""

        return blob[1]

    def compute_hash_bytes(self):
        """Generates the firmware blob hash."""

        if self.fw_ver is None:
            raise ChipUtilsError('fw_ver not initialized')

        h = bytearray(2)
        h[0] = 0xa3
        h[1] = self.fw_ver
        return h


class anx3429(generic_chip):

    """The ANX3429 TCPC chip."""

    chip_name = 'anx3429'
    fw_name = 'anx3429_ocm'
    cbfs_bin_name = fw_name + '.bin'
    cbfs_hash_name = fw_name + '.hash'

    def fw_ver_from_hash(self, blob):
        """Return the firmware version encoded in the firmware hash."""

        return blob[0]

    def compute_hash_bytes(self):
        """Generates the firmware blob hash."""

        if self.fw_ver is None:
            raise ChipUtilsError('fw_ver not initialized')

        h = bytearray(1)
        h[0] = self.fw_ver
        return h


class ecrw(generic_chip):

    """Chrome EC RW portion."""

    chip_name = 'ecrw'
    fw_name = 'ecrw'
    cbfs_bin_name = fw_name
    cbfs_hash_name = fw_name + '.hash'

    def compute_hash_bytes(self):
        """Generates the firmware blob hash."""

        if self.fw_file_name is None:
            raise ChipUtilsError('fw_file_name not initialized')

        if not os.path.exists(self.fw_file_name):
            raise ChipUtilsError('%s does not exist' % self.fw_file_name)

        # openssl outputs the result to stdout
        cmd = 'openssl dgst -sha256 -binary %s' % self.fw_file_name
        return subprocess.check_output(cmd, shell=True)


chip_id_map = {
    '0x8751': ps8751,
    '0x3429': anx3429,
}