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 extension = '.bin' 64 hash_extension = '.hash' 65 cbfs_bin_name = fw_name + extension 66 cbfs_hash_name = fw_name + hash_extension 67 68 def fw_ver_from_hash(self, blob): 69 """Return the firmware version encoded in the firmware hash.""" 70 71 return blob[1] 72 73 def compute_hash_bytes(self): 74 """Generates the firmware blob hash.""" 75 76 if self.fw_ver is None: 77 raise ChipUtilsError('fw_ver not initialized') 78 79 h = bytearray(2) 80 h[0] = 0xa3 81 h[1] = self.fw_ver 82 return h 83 84 85class anx3429(generic_chip): 86 87 """The ANX3429 TCPC chip.""" 88 89 chip_name = 'anx3429' 90 fw_name = 'anx3429_ocm' 91 extension = '.bin' 92 hash_extension = '.hash' 93 cbfs_bin_name = fw_name + extension 94 cbfs_hash_name = fw_name + hash_extension 95 96 def fw_ver_from_hash(self, blob): 97 """Return the firmware version encoded in the passed-in hash content.""" 98 return blob[0] 99 100 def compute_hash_bytes(self): 101 """Generates the firmware blob hash.""" 102 103 if self.fw_ver is None: 104 raise ChipUtilsError('fw_ver not initialized') 105 106 h = bytearray(1) 107 h[0] = self.fw_ver 108 return h 109 110 111class ecrw(generic_chip): 112 113 """Chrome EC RW portion.""" 114 115 chip_name = 'ecrw' 116 fw_name = 'ecrw' 117 extension = '' 118 hash_extension = '.hash' 119 cbfs_bin_name = fw_name 120 cbfs_hash_name = fw_name + hash_extension 121 122 def compute_hash_bytes(self): 123 """Generates the firmware blob hash.""" 124 125 if self.fw_file_name is None: 126 raise ChipUtilsError('fw_file_name not initialized') 127 128 if not os.path.exists(self.fw_file_name): 129 raise ChipUtilsError('%s does not exist' % self.fw_file_name) 130 131 # openssl outputs the result to stdout 132 cmd = 'openssl dgst -sha256 -binary %s' % self.fw_file_name 133 result = subprocess.check_output(cmd, shell=True) 134 return bytearray(result) 135 136 137chip_id_map = { 138 'ecrw': ecrw, 139 '0x8751': ps8751, 140 '0x3429': anx3429, 141} 142