1# This file describes eFuses controller for ESP32-C2 chip 2# 3# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD 4# 5# SPDX-License-Identifier: GPL-2.0-or-later 6 7from bitstring import BitStream 8 9import reedsolo 10 11from .mem_definition import EfuseDefineBlocks, EfuseDefineFields, EfuseDefineRegisters 12from ..emulate_efuse_controller_base import EmulateEfuseControllerBase, FatalError 13 14 15class EmulateEfuseController(EmulateEfuseControllerBase): 16 """The class for virtual efuse operation. Using for HOST_TEST.""" 17 18 CHIP_NAME = "ESP32-C2" 19 mem = None 20 debug = False 21 Blocks = EfuseDefineBlocks 22 Fields = EfuseDefineFields 23 REGS = EfuseDefineRegisters 24 25 def __init__(self, efuse_file=None, debug=False): 26 super(EmulateEfuseController, self).__init__(efuse_file, debug) 27 self.write_reg(self.REGS.EFUSE_STATUS_REG, 1) 28 29 """ esptool method start >>""" 30 31 def get_major_chip_version(self): 32 return 1 33 34 def get_minor_chip_version(self): 35 return 0 36 37 def get_crystal_freq(self): 38 return 40 # MHz 39 40 def get_security_info(self): 41 return { 42 "flags": 0, 43 "flash_crypt_cnt": 0, 44 "key_purposes": 0, 45 "chip_id": 0, 46 "api_version": 0, 47 } 48 49 """ << esptool method end """ 50 51 def handle_writing_event(self, addr, value): 52 if addr == self.REGS.EFUSE_CMD_REG: 53 if value & self.REGS.EFUSE_PGM_CMD: 54 self.copy_blocks_wr_regs_to_rd_regs(updated_block=(value >> 2) & 0xF) 55 self.clean_blocks_wr_regs() 56 self.check_rd_protection_area() 57 self.write_reg(addr, 0) 58 self.write_reg(self.REGS.EFUSE_STATUS_REG, 1) 59 elif value == self.REGS.EFUSE_READ_CMD: 60 self.write_reg(addr, 0) 61 self.write_reg(self.REGS.EFUSE_STATUS_REG, 1) 62 self.save_to_file() 63 64 def get_bitlen_of_block(self, blk, wr=False): 65 if blk.id == 0: 66 if wr: 67 return 32 * 8 68 else: 69 return 32 * blk.len 70 else: 71 if wr: 72 rs_coding = 32 * 3 73 return 32 * 8 + rs_coding 74 else: 75 return 32 * blk.len 76 77 def handle_coding_scheme(self, blk, data): 78 if blk.id != 0: 79 # CODING_SCHEME RS applied only for all blocks except BLK0. 80 coded_bytes = 12 81 data.pos = coded_bytes * 8 82 plain_data = data.readlist("32*uint:8")[::-1] 83 # takes 32 bytes 84 # apply RS encoding 85 rs = reedsolo.RSCodec(coded_bytes) 86 # 32 byte of data + 12 bytes RS 87 calc_encoded_data = list(rs.encode([x for x in plain_data])) 88 data.pos = 0 89 if calc_encoded_data != data.readlist("44*uint:8")[::-1]: 90 raise FatalError("Error in coding scheme data") 91 data = data[coded_bytes * 8 :] 92 if blk.len < 8: 93 data = data[(8 - blk.len) * 32 :] 94 return data 95 96 def check_rd_protection_area(self): 97 # checks fields which have the read protection bits. 98 # if the read protection bit is set then we need to reset this field to 0. 99 100 def get_read_disable_mask(blk): 101 mask = 0 102 if isinstance(blk.read_disable_bit, list): 103 for i in blk.read_disable_bit: 104 mask |= 1 << i 105 else: 106 mask = 1 << blk.read_disable_bit 107 return mask 108 109 read_disable_bit = self.read_field("RD_DIS", bitstring=False) 110 for b in self.Blocks.BLOCKS: 111 blk = self.Blocks.get(b) 112 block = self.read_block(blk.id) 113 if ( 114 blk.read_disable_bit is not None 115 and read_disable_bit & get_read_disable_mask(blk) 116 ): 117 if isinstance(blk.read_disable_bit, list): 118 if read_disable_bit & (1 << blk.read_disable_bit[0]): 119 block.set( 120 0, [i for i in range(blk.len * 32 // 2, blk.len * 32)] 121 ) 122 if read_disable_bit & (1 << blk.read_disable_bit[1]): 123 block.set(0, [i for i in range(0, blk.len * 32 // 2)]) 124 else: 125 block.set(0) 126 else: 127 for e in self.Fields.EFUSES: 128 field = self.Fields.get(e) 129 if ( 130 blk.id == field.block 131 and field.read_disable_bit is not None 132 and read_disable_bit & get_read_disable_mask(field) 133 ): 134 raw_data = self.read_field(field.name) 135 raw_data.set(0) 136 block.pos = block.length - ( 137 field.word * 32 + field.pos + raw_data.length 138 ) 139 block.overwrite(BitStream(raw_data.length)) 140 self.overwrite_mem_from_block(blk, block) 141