| #!/usr/bin/python -u |
| # -*- coding: utf-8 -*- |
| # |
| # Copyright (c) 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. |
| |
| """Implementation of HWID v3 encoder.""" |
| |
| import factory_common # pylint: disable=W0611 |
| |
| from cros.factory.hwid import common |
| from cros.factory.hwid.base32 import Base32 |
| |
| |
| def BOMToBinaryString(database, bom): |
| """Encodes the given BOM object to a binary string. |
| |
| Args: |
| database: A Database object that is used to provide device-specific |
| information for encoding. |
| |
| Returns: |
| A binary string. |
| """ |
| database.VerifyBOM(bom) |
| bit_length = database.pattern.GetTotalBitLength() |
| size = ((bit_length + Base32.BASE32_BIT_WIDTH - 1) / |
| Base32.BASE32_BIT_WIDTH * Base32.BASE32_BIT_WIDTH) |
| binary_list = size * [0] |
| |
| # Fill in header. |
| binary_list[0] = bom.encoding_pattern_index |
| for i in xrange(1, 5): |
| binary_list[i] = (bom.image_id >> (4 - i)) & 1 |
| # Fill in each bit. |
| bit_mapping = database.pattern.GetBitMapping() |
| for index, (field, bit_offset) in bit_mapping.iteritems(): |
| binary_list[index] = (bom.encoded_fields[field] >> bit_offset) & 1 |
| # Set stop bit. |
| binary_list[bit_length - 1] = 1 |
| return ''.join(['%d' % bit for bit in binary_list]) |
| |
| |
| def BinaryStringToEncodedString(database, binary_string): |
| """Encodes the given binary string to a encoded string. |
| |
| Args: |
| database: A Database object that is used to provide device-specific |
| information for encoding. |
| binary_string: A string of '0's and '1's. |
| |
| Returns: |
| An encoded string with board name, base32-encoded HWID, and checksum. |
| """ |
| database.VerifyBinaryString(binary_string) |
| b32_string = Base32.Encode(binary_string) |
| # Make board name part of the checksum. |
| b32_string += Base32.Checksum(database.board.upper() + ' ' + b32_string) |
| # Insert dashes to increase readibility. |
| b32_string = ( |
| '-'.join([b32_string[i:i + 4] for i in xrange(0, len(b32_string), 4)])) |
| return database.board.upper() + ' ' + b32_string |
| |
| |
| def Encode(database, bom, skip_check=False, rma_mode=False): |
| """Encodes all the given BOM object. |
| |
| Args: |
| database: A Database object that is used to provide device-specific |
| information for encoding. |
| bom: A BOM object. |
| skip_check: A bool value to skip the verification when constructing the HWID |
| object. Needed when creating a HWID skelton to be further processed. |
| rma_mode: If set to True, deprecated components will be allowed. |
| |
| Returns: |
| A HWID object which contains the BOM, the binary string, and the encoded |
| string derived from the given BOM object. |
| """ |
| # Convert all encoded fields with None value to the default index 0. |
| components_to_update = {} |
| for field, index in bom.encoded_fields.iteritems(): |
| if index is None: |
| for comp_cls, comp_name in database.encoded_fields[field][0].iteritems(): |
| # Check every component classes that this encoded field consists of. |
| for probed_comp in bom.components[comp_cls]: |
| if probed_comp.component_name is not None: |
| continue |
| if comp_cls not in database.components.probeable: |
| # Only convert unprobeable components. |
| components_to_update[comp_cls] = comp_name |
| else: |
| raise common.HWIDException(probed_comp.error) |
| updated_bom = database.UpdateComponentsOfBOM(bom, components_to_update) |
| |
| for field, index in updated_bom.encoded_fields.iteritems(): |
| if index is None: |
| err_msg = ('Unable to determine index for encoded field %r. Probed ' |
| 'components are:\n') % field |
| for comp_cls in database.encoded_fields[field][0].iterkeys(): |
| for probed_comp in bom.components[comp_cls]: |
| err_msg += ' %r: %r\n' % (comp_cls, probed_comp.component_name) |
| raise common.HWIDException(err_msg) |
| |
| binary_string = BOMToBinaryString(database, updated_bom) |
| encoded_string = BinaryStringToEncodedString(database, binary_string) |
| hwid = common.HWID(database, binary_string, encoded_string, updated_bom, |
| skip_check=skip_check) |
| hwid.VerifyComponentStatus(rma_mode) |
| return hwid |