1# Copyright 2017 The Chromium OS Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5"""A collection of classes representing TCPC firmware blobs. 6""" 7 8import logging 9import os 10import subprocess 11 12 13class ChipUtilsError(Exception): 14 """Error in the chip_utils module.""" 15 16 17 18class generic_chip(object): 19 20 """A chip we don't actually support.""" 21 22 chip_name = 'unknown' 23 fw_name = None 24 25 def __init__(self): 26 self.fw_ver = None 27 self.fw_file_name = None 28 29 def set_fw_ver_from_string(self, version): 30 """Sets version property from string.""" 31 self.fw_ver = int(version, 0) 32 33 def set_from_file(self, file_name): 34 """Sets chip params from file name. 35 36 The typical firmware blob file name format is: <chip>_0x00.bin 37 38 Args: 39 file_name: Firmware blob file name. 40 41 Raises: 42 ValueError: Failed to decompose firmware file name. 43 """ 44 45 basename = os.path.basename(file_name) 46 if not basename.startswith(self.chip_name): 47 raise ValueError('filename did not start with %s' % self.chip_name) 48 fname = basename.split('.')[0] 49 if '_' in fname: 50 rev = fname.split('_')[-1] 51 self.set_fw_ver_from_string(rev) 52 else: 53 logging.info('No fw ver found in filename %s', basename) 54 self.fw_file_name = file_name 55 56 57class ps8751(generic_chip): 58 59 """The PS8751 TCPC chip.""" 60 61 chip_name = 'ps8751' 62 fw_name = 'ps8751_a3' 63 cbfs_bin_name = fw_name + '.bin' 64 cbfs_hash_name = fw_name + '.hash' 65 66 def fw_ver_from_hash(self, blob): 67 """Return the firmware version encoded in the firmware hash.""" 68 69 return blob[1] 70 71 def compute_hash_bytes(self): 72 """Generates the firmware blob hash.""" 73 74 if self.fw_ver is None: 75 raise ChipUtilsError('fw_ver not initialized') 76 77 h = bytearray(2) 78 h[0] = 0xa3 79 h[1] = self.fw_ver 80 return h 81 82 83class anx3429(generic_chip): 84 85 """The ANX3429 TCPC chip.""" 86 87 chip_name = 'anx3429' 88 fw_name = 'anx3429_ocm' 89 cbfs_bin_name = fw_name + '.bin' 90 cbfs_hash_name = fw_name + '.hash' 91 92 def fw_ver_from_hash(self, blob): 93 """Return the firmware version encoded in the firmware hash.""" 94 95 return blob[0] 96 97 def compute_hash_bytes(self): 98 """Generates the firmware blob hash.""" 99 100 if self.fw_ver is None: 101 raise ChipUtilsError('fw_ver not initialized') 102 103 h = bytearray(1) 104 h[0] = self.fw_ver 105 return h 106 107 108class ecrw(generic_chip): 109 110 """Chrome EC RW portion.""" 111 112 chip_name = 'ecrw' 113 fw_name = 'ecrw' 114 cbfs_bin_name = fw_name 115 cbfs_hash_name = fw_name + '.hash' 116 117 def compute_hash_bytes(self): 118 """Generates the firmware blob hash.""" 119 120 if self.fw_file_name is None: 121 raise ChipUtilsError('fw_file_name not initialized') 122 123 if not os.path.exists(self.fw_file_name): 124 raise ChipUtilsError('%s does not exist' % self.fw_file_name) 125 126 # openssl outputs the result to stdout 127 cmd = 'openssl dgst -sha256 -binary %s' % self.fw_file_name 128 return subprocess.check_output(cmd, shell=True) 129 130 131chip_id_map = { 132 '0x8751': ps8751, 133 '0x3429': anx3429, 134} 135