コード例 #1
0
ファイル: pfr.py プロジェクト: saper/spsdk
    def _export_register(self, register_name: str, compute_inverses: bool) -> bytes:
        """Generate binary output for single register."""
        register = BitArray(length=32)
        user_config = self.user_config.get(register_name, dict())
        inverse_present = False
        for field in self._get_bitfields(register_name, exclude_computed=False):
            name = field.attrib["name"]
            offset = parse_int(field.attrib["offset"])
            width = parse_int(field.attrib["width"])
            # chcek whether there's a need to calculate inverse values
            inverse_present |= name == "INVERSE_VALUE"

            # The configuration allows to configure the whole register with single value
            if isinstance(user_config, str):
                temp_value = user_config
            else:
                temp_value = user_config.get(name) or field.attrib["reset_value"]
            value = parse_int(temp_value)
            # due to endianess we fill the bits from the end, therefore there's '-' in position
            # pos = 0 means offset = 0, means end of the BitArray
            register.overwrite(bs=BitArray(f"uint:{width}={value}"), pos=-(offset + width))
        if compute_inverses and inverse_present:
            # NOTE: For now we'll assume the INVERSES are 16b long and inverts bits[15:0]
            # should this change in the future a data model change is necessary
            # NOTE: invert method changes bits in-place, thus we need to call it on separate object
            # calling invert() after slicing doesn't work for BitArray
            b_lower = register[16:]
            b_lower.invert()
            register.overwrite(b_lower, 0)
        # swapping bytes from big endian into little
        register.byteswap()
        return register.bytes
コード例 #2
0
ファイル: pfr.py プロジェクト: saper/spsdk
 def _parse_register(self, register_name: str, data: bytes) -> Union[str, dict]:
     """Parse individual register, returns wither one 32b value or dict of bitfields."""
     register = {}
     bits = BitArray(data)
     # data is stored in little endian, but processed in big endian
     bits.byteswap()
     for field in self._get_bitfields(register_name, exclude_computed=False):
         width = parse_int(field.attrib["width"])
         # exit early if we found a single 32b field
         if width == 32:
             return format_value(bits.uint, width)
         name = field.attrib["name"]
         offset = parse_int(field.attrib["offset"])
         # OK, what the hell is that slicing about?!
         # offset is marked from the end of the bitarray not the begging like in a list
         # e.g.: ba = BitArray('0b00001100'), we want to extract bitfields of width=2 and offset=2 ('11')
         # again offset=2 means 2 bits from the end
         # BitArray supports negative indexing like an regular python list does: last bit has index -1
         # that means we want to extract bits with indecies -4,-3 => [-4:-2]
         # HOWEVER: if we would want to extract 2 bits in the end (offset=0)
         # we would need to use [-offset:] slice or [-offset:None]
         slice_end = None if offset == 0 else -offset
         filed_bits = bits[-(offset + width): slice_end]
         register[name] = format_value(filed_bits.uint, width)
     return register
コード例 #3
0
ファイル: pfr.py プロジェクト: saper/spsdk
    def export(self, add_seal: bool = False, compute_inverses: bool = False) -> bytes:
        """Generate binary output."""
        data = bytearray(self.BINARY_SIZE)
        for reg in self._get_registers(exclude_computed=False):
            name = reg.attrib["name"]
            width = parse_int(reg.attrib["width"])
            offset = parse_int(reg.attrib["offset"])
            assert width == 32, "Don't know how to handle non-32b registers"
            register = self._export_register(name, compute_inverses)
            # rewriting 4B at the time
            data[offset: offset + 4] = register

        # ROTKH may or may not be present, derived class defines its presense
        if self.HAS_ROTKH:
            rotkh_data = self.rotkh or self._calc_rotkh()
            rothk_start = self._get_rotkh_start_address()
            data[rothk_start: rothk_start + self.ROTKH_SIZE] = rotkh_data

        if add_seal:
            seal_start = self._get_seal_start_address()
            seal_cout = self._get_seal_count()
            data[seal_start: seal_start + seal_cout * 4] = self.MARK * seal_cout

        assert len(data) == self.BINARY_SIZE, f'The size of data is {len(data)}, is not equal to {self.BINARY_SIZE}'
        return bytes(data)
コード例 #4
0
ファイル: pfr.py プロジェクト: vhamersky/spsdk
    def export(self,
               add_hash: bool = False,
               compute_inverses: bool = False) -> bytes:
        """Generate binary output."""
        data = bytearray(self.BINARY_SIZE)
        for reg in self._get_registers(exclude_computed=False):
            name = reg.attrib["name"]
            width = parse_int(reg.attrib["width"])
            offset = parse_int(reg.attrib["offset"])
            assert width == 32, "Don't know how to handle non-32b registers"
            register = self._export_register(name, compute_inverses)
            # rewriting 4B at the time
            data[offset:offset + 4] = register

        # ROTKH may or may not be present, derived class defines its presense
        if self.HAS_ROTKH:
            rotkh_data = self.rotkh or self._calc_rotkh()
            rothk_start = self._get_rotkh_start_address()
            data[rothk_start:rothk_start + self.ROTKH_SIZE] = rotkh_data

        if add_hash:
            sha_start = self._get_sha_start_address()
            data[sha_start:sha_start + self.SHA_SIZE] = openssl_backend.hash(
                data[:sha_start])
        return bytes(data)
コード例 #5
0
ファイル: pfr.py プロジェクト: saper/spsdk
 def parse(self, data: bytes, exclude_computed: bool = True) -> dict:
     """Return a user config JSON object based on input data."""
     user_config = {}
     for reg in self._get_registers(exclude_computed=exclude_computed):
         name = reg.attrib["name"]
         width = parse_int(reg.attrib["width"])
         offset = parse_int(reg.attrib["offset"])
         assert width == 32, "Don't know how to handle non-32b registers"
         reg_config = self._parse_register(name, data[offset: offset + 4])
         user_config[name] = reg_config
     return user_config
コード例 #6
0
ファイル: pfr.py プロジェクト: saper/spsdk
 def _get_sha_start_address(self) -> int:
     """Return the offset of the first SHA_DIGEST register."""
     return parse_int(self._get_register(self.SHA_START_REGISTER).attrib["offset"])
コード例 #7
0
ファイル: pfr.py プロジェクト: saper/spsdk
 def _get_rotkh_start_address(self) -> int:
     """Return the offset of the first ROTKHx register defined as ROTKH_START_REGISTER."""
     return parse_int(self._get_register(self.ROTKH_START_REGISTER).attrib["offset"])
コード例 #8
0
def test_parse_int_invalid_input(test_input):
    """ Test invalid inputs for parse_int() """
    with pytest.raises(ValueError):
        parse_int(test_input)
コード例 #9
0
def test_parse_int(test_input, expected):
    assert parse_int(test_input) == expected
コード例 #10
0
ファイル: pfr.py プロジェクト: saper/spsdk
 def _get_seal_start_address(self) -> int:
     start = self.config['devices'][self.device].get('seal_start')
     if start is None:
         start = self.config['seal_start']
     assert start, "Can't find 'seal_start' in database.json"
     return parse_int(self._get_register(start).attrib['offset'])