#!/usr/bin/python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2021 MIT License

# DXCC = Discretix CryptoCell

import logging, os
import hashlib
from struct import pack
from Crypto.Util.number import bytes_to_long
from Crypto.Cipher import AES
from Crypto.Util import Counter
from mtkclient.Library.utils import LogBase, logsetup

oem_pubk = "DACD8B5FDA8A766FB7BCAA43F0B16915" + \
           "CE7B47714F1395FDEBCF12A2D41155B0" + \
           "FB587A51FECCCB4DDA1C8E5EB9EB69B8" + \
           "6DAF2C620F6C2735215A5F22C0B6CE37" + \
           "7AA0D07EB38ED340B5629FC2890494B0" + \
           "78A63D6D07FDEACDBE3E7F27FDE4B143" + \
           "F49DB4971437E6D00D9E18B56F02DABE" + \
           "B0000B6E79516D0C8074B5A42569FD0D" + \
           "9196655D2A4030D42DFE05E9F64883E6" + \
           "D5F79A5BFA3E7014C9A62853DC1F21D5" + \
           "D626F4D0846DB16452187DD776E8886B" + \
           "48C210C9E208059E7CAFC997FD2CA210" + \
           "775C1A5D9AA261252FB975268D970C62" + \
           "733871D57814098A453DF92BC6CA1902" + \
           "5CD9D430F02EE46F80DE6C63EA802BEF" + \
           "90673AAC4C6667F2883FB4501FA77455"

mtk_oem_key = hashlib.sha256(bytes.fromhex(oem_pubk)).digest()

regval = {
    "DXCC_CON": 0x0000,
}

INT32_MAX = 0x7FFFFFFF

SB_AXI_ID = 0
AXI_SECURE = 0

HASH_MD5_DIGEST_SIZE_IN_BYTES = 16
HASH_SHA1_DIGEST_SIZE_IN_BYTES = 20
HASH_SHA224_DIGEST_SIZE_IN_BYTES = 28
HASH_SHA256_DIGEST_SIZE_IN_BYTES = 32
HASH_SHA384_DIGEST_SIZE_IN_BYTES = 48
HASH_SHA512_DIGEST_SIZE_IN_BYTES = 64

HASH_MD5_BLOCK_SIZE_IN_BYTES = 64
HASH_SHA1_BLOCK_SIZE_IN_BYTES = 64
HASH_SHA224_BLOCK_SIZE_IN_BYTES = 64
HASH_SHA256_BLOCK_SIZE_IN_BYTES = 64
HASH_SHA384_BLOCK_SIZE_IN_BYTES = 128
HASH_SHA512_BLOCK_SIZE_IN_BYTES = 128

AES_BLOCK_SIZE_IN_BYTES = 16

AES_IV_SIZE_IN_BYTES = AES_BLOCK_SIZE_IN_BYTES

AES_CCM_NONCE_LENGTH_MIN = 7
AES_CCM_NONCE_LENGTH_MAX = 13

AES_CCM_TAG_LENGTH_MIN = 4
AES_CCM_TAG_LENGTH_MAX = 16
DES_IV_SIZE_IN_BYTES = 8

# Use constant counter ID and AXI ID
SB_COUNTER_ID = 0

# The AES block size in words and in bytes
AES_BLOCK_SIZE_IN_WORDS = 4

# The size of the IV or counter buffer
AES_IV_COUNTER_SIZE_IN_WORDS = AES_BLOCK_SIZE_IN_WORDS
AES_IV_COUNTER_SIZE_IN_BYTES = (AES_IV_COUNTER_SIZE_IN_WORDS * 4)

# The size of the AES KEY in words and bytes
AES_KEY_SIZE_IN_WORDS = AES_BLOCK_SIZE_IN_WORDS
AES_KEY_SIZE_IN_BYTES = (AES_KEY_SIZE_IN_WORDS * 4)

AES_Key128Bits_SIZE_IN_WORDS = AES_BLOCK_SIZE_IN_WORDS
AES_Key128Bits_SIZE_IN_BYTES = AES_BLOCK_SIZE_IN_BYTES
AES_Key256Bits_SIZE_IN_WORDS = 8
AES_Key256Bits_SIZE_IN_BYTES = (AES_Key256Bits_SIZE_IN_WORDS * 4)

# Hash IV+Length
HASH_DIGEST_SIZE_IN_WORDS = 8
HASH_DIGEST_SIZE_IN_BYTES = (HASH_DIGEST_SIZE_IN_WORDS * 4)
HASH_LENGTH_SIZE_IN_WORDS = 4
HASH_LENGTH_SIZE_IN_BYTES = (HASH_LENGTH_SIZE_IN_WORDS * 4)

# Offset, shift, size
AES = {
    "KEY_0_0": [0x400, 0x0, 0x20],
    "KEY_0_1": [0x404, 0x0, 0x20],
    "KEY_0_2": [0x408, 0x0, 0x20],
    "KEY_0_3": [0x40C, 0x0, 0x20],
    "KEY_0_4": [0x410, 0x0, 0x20],
    "KEY_0_5": [0x414, 0x0, 0x20],
    "KEY_0_6": [0x418, 0x0, 0x20],
    "KEY_0_7": [0x41C, 0x0, 0x20],
    "IV_0_0": [0x440, 0x0, 0x20],
    "IV_0_1": [0x444, 0x0, 0x20],
    "IV_0_2": [0x448, 0x0, 0x20],
    "IV_0_3": [0x44C, 0x0, 0x20],
    "CTR_0_0": [0x460, 0x0, 0x20],
    "CTR_0_1": [0x464, 0x0, 0x20],
    "CTR_0_2": [0x468, 0x0, 0x20],
    "CTR_0_3": [0x46C, 0x0, 0x20],
    "BUSY": [0x470, 0x0, 0x1],
    "SK": [0x478, 0x0, 0x1],
    "CMAC_INIT": [0x47C, 0x0, 0x1],
    "PREV_IV_0_0": [0x490, 0x0, 0x20],
    "PREV_IV_0_1": [0x494, 0x0, 0x20],
    "PREV_IV_0_2": [0x498, 0x0, 0x20],
    "PREV_IV_0_3": [0x49C, 0x0, 0x20],
    "REMAINING_BYTES": [0x4BC, 0x0, 0x20],
    "CONTROL": [0x4C0,
                {"DEC_KEY0": [0x0, 0x1],
                 "MODE0_IS_CBC_CTS": [0x1, 0x1],
                 "MODE_KEY0": [0x2, 0x3],
                 "MODE_KEY1": [0x5, 0x3],
                 "AES_TUNNEL_IS_ON": [0xa, 0x1],
                 "NK_KEY0": [0xc, 0x2],
                 "NK_KEY1": [0xe, 0x2],
                 "AES_TUNNEL1_DECRYPT": [0x16, 0x1],
                 "AES_TUN_B1_USES_PADDED_DATA_IN": [0x17, 0x1],
                 "AES_TUNNEL0_ENCRYPT": [0x18, 0x1],
                 "AES_OUTPUT_MID_TUNNEL_DATA": [0x19, 0x1],
                 "AES_TUNNEL_B1_PAD_EN": [0x1a, 0x1],
                 "AES_OUT_MID_TUN_TO_HASH": [0x1c, 0x1],
                 "AES_XOR_CRYPTOKEY": [0x1d, 0x1],
                 "DIRECT_ACCESS": [0x1f, 0x1]}
                ],
    "HW_FLAGS": [0x4C8,
                 {"SUPPORT_256_192_KEY": [0x0, 0x1],
                  "AES_LARGE_RKEK": [0x1, 0x1],
                  "DPA_CNTRMSR_EXIST": [0x2, 0x1],
                  "CTR_EXIST": [0x3, 0x1],
                  "ONLY_ENCRYPT": [0x4, 0x1],
                  "USE_SBOX_TABLE": [0x5, 0x1],
                  "USE_5_SBOXES": [0x8, 0x1],
                  "AES_SUPPORT_PREV_IV": [0x9, 0x1],
                  "AES_TUNNEL_EXISTS": [0xa, 0x1],
                  "SECOND_REGS_SET_EXIST": [0xb, 0x1],
                  "DFA_CNTRMSR_EXIST": [0xc, 0x1]}
                 ],
    "XEX_HW_T_CALC_KICK": [0x4cc, 0x0, 0x1],
    "XEX_HW_T_CALC_IS_ON": [0x4d4, 0x0, 0x2],
    "CTR_NO_INCREMENT": [0x4d8, 0x0, 0x1],
    "SW_RESET": [0x4f4, 0x0, 0x1],
    "XEX_HW_T_CALC_KEY_0": [0x500, 0x0, 0x20],
    "XEX_HW_T_CALC_KEY_1": [0x504, 0x0, 0x20],
    "XEX_HW_T_CALC_KEY_2": [0x508, 0x0, 0x20],
    "XEX_HW_T_CALC_KEY_3": [0x50c, 0x0, 0x20],
    "XEX_HW_T_CALC_KEY_4": [0x510, 0x0, 0x20],
    "XEX_HW_T_CALC_KEY_5": [0x514, 0x0, 0x20],
    "XEX_HW_T_CALC_KEY_6": [0x518, 0x0, 0x20],
    "XEX_HW_T_CALC_KEY_7": [0x51c, 0x0, 0x20],
    "DATA_UNIT": [0x520, 0x0, 0x20],
    "AES_CMAC_SIZE0_KICK": [0x524, 0x0, 0x1],
}

MISC = {
    "AES_CLK_ENABLE": [0x810, 0x0, 0x1],
    "DES_CLK_ENABLE": [0x814, 0x0, 0x1],
    "HASH_CLK_ENABLE": [0x818, 0x0, 0x1],
    "PKA_CLK_ENABLE": [0x81c, 0x0, 0x1],
    "DMA_CLK_ENABLE": [0x820, 0x0, 0x1],
    "CLK_STATUS": [0x824,
                   {"AES_CLK_STATUS": [0x0, 0x1],
                    "DES_CLK_STATUS": [0x1, 0x1],
                    "HASH_CLK_STATUS": [0x2, 0x1],
                    "PKA_CLK_STATUS": [0x3, 0x1],
                    "RC4_CLK_STATUS": [0x4, 0x1],
                    "C2_CLK_STATUS": [0x7, 0x1],
                    "DMA_CLK_STATUS": [0x8, 0x1]}
                   ],
    "RC4_CLK_ENABLE": [0x854, 0x0, 0x1],
    "MTI2_CLK_ENABLE": [0x858, 0x0, 0x1],
}

CC_CTL = {
    "CRYPTO_CTL": [0x900, 0x0, 0x5],
    "CRYPTO_BUSY": [0x910, 0x0, 0x1],
    "HASH_BUSY": [0x91c, 0x0, 0x1],
    "VERSION": [0x928, 0x0, 0x20],
    "CONTEXT_ID": [0x930, 0x0, 0x8],
    "HASH_COMPARE_ERR_ID_FIFO0": [0x940, 0x0, 0x1a],
    "HASH_COMPARE_ERR_ID_FIFO1": [0x944, 0x0, 0x1a],
    "HASH_COMPARE_ERR_ID_FIFO2": [0x948, 0x0, 0x1a],
    "HASH_COMPARE_ERR_ID_FIFO3": [0x94c, 0x0, 0x1a]
}

DIN = {
    "DIN_BUFFER": [0xc00, 0x0, 0x20],
    "DIN_MEM_DMA_BUSY": [0xc20, 0x0, 0x1],
    "SRC_LLI_SRAM_ADDR": [0xc24, 0x0, 0xf],
    "SRC_LLI_WORD0": [0xc28, 0x0, 0x20],
    "SRC_LLI_WORD1": [0xC2C,
                      {"BYTES_NUM": [0x0, 0x1e],
                       "FIRST": [0x1e, 0x1],
                       "LAST": [0x1f, 0x1]}
                      ],
    "SRAM_SRC_ADDR": [0xc30, 0x0, 0x20],
    "DIN_SRAM_BYTES_LEN": [0xc34, 0x0, 0x20],
    "DIN_SRAM_DMA_BUSY": [0xc38, 0x0, 0x1],
    "DIN_SRAM_ENDIANNESS": [0xc3c, 0x0, 0x1],
    "AXI_CPU_DIN_PARAMS": [0xC40,
                           {"RDID": [0x0, 0x4],
                            "PROT": [0x8, 0x2]}
                           ],
    "DIN_SW_RESET": [0xc44, 0x0, 0x1],
    "DIN_CPU_DATA_SIZE": [0xc48, 0x0, 0x10],
    "WRITE_ALIGN_LAST": [0xc4c, 0x0, 0x1],
    "FIFO_IN_EMPTY": [0xc50, 0x0, 0x1],
    "DISABLE_OUTSTD_REQ": [0xc54, 0x0, 0x1],
    "DIN_FIFO_RST_PNTR": [0xc58, 0x0, 0x1],
}

DOUT = {
    "DOUT_BUFFER": [0xd00, 0x0, 0x20],
    "DOUT_MEM_DMA_BUSY": [0xd20, 0x0, 0x1],
    "DST_LLI_SRAM_ADDR": [0xd24, 0x0, 0xf],
    "DST_LLI_WORD0": [0xd28, 0x0, 0x20],
    "DST_LLI_WORD1": [0xD2C,
                      {"BYTES_NUM": [0x0, 0x1e],
                       "FIRST": [0x1e, 0x1],
                       "LAST": [0x1f, 0x1]}
                      ],
    "DOUT_SRAM_BYTES_LEN": [0xd34, 0x0, 0x20],
    "DOUT_SRAM_DMA_BUSY": [0xd38, 0x0, 0x1],
    "DOUT_SRAM_ENDIANNESS": [0xd3c, 0x0, 0x1],
    "READ_ALIGN_LAST": [0xd44, 0x0, 0x1],
    "FIFO_MODE": [0xd48, 0x0, 0x1],
    "DOUT_FIFO_EMPTY": [0xd50, 0x0, 0x1],
    "AXI_CPU_DOUT_PARAMS": [0xD54,
                            {"CACHE_TYPE": [0x0, 0x4],
                             "WRID": [0xc, 0x4],
                             "PROT": [0x10, 0x2],
                             "FORCE_CPU_PARAMS": [0x12, 0x1]}
                            ],
    "DOUT_SW_RESET": [0xd58, 0x0, 0x1]
}

DES = {
    "SRAM_DEST_ADDR": [0xd30, 0x0, 0x20],
    "DES_KEY_0": [0x208, 0x0, 0x20],
    "DES_KEY_1": [0x20c, 0x0, 0x20],
    "DES_KEY_2": [0x210, 0x0, 0x20],
    "DES_KEY_3": [0x214, 0x0, 0x20],
    "DES_KEY_4": [0x218, 0x0, 0x20],
    "DES_KEY_5": [0x21c, 0x0, 0x20],
    "DES_CONTROL_0": [0x220,
                      {"ENC": [0x0, 0x1],
                       "KEY_NUM": [0x1, 0x2],
                       "MODE": [0x3, 0x2]}
                      ],
    "DES_CONTROL_1": [0x224, 0x0, 0x20],
    "DES_IV_0": [0x228, 0x0, 0x20],
    "DES_IV_1": [0x22c, 0x0, 0x20],
    "DES_VERSION": [0x230,
                    {"FIXES": [0x0, 0x8],
                     "MINOR": [0x8, 0x4],
                     "MAJOR": [0xc, 0x4]}
                    ],
    "DES_RBG_INIT_VAL": [0x248, 0x0, 0x8],
    "DES_RBG_READY": [0x24c, 0x0, 0x1],
    "DES_BUSY": [0x270, 0x0, 0x1],
    "DES_SW_RESET": [0x280, 0x0, 0x1]
}

DSCRPTR = {
    "DSCRPTR_COMPLETION_COUNTER0": [0xE00,
                                    {"COMPLETION_COUNTER": [0x0, 0x6],
                                     "OVERFLOW_COUNTER": [0x6, 0x1]}
                                    ],
    "DSCRPTR_COMPLETION_COUNTER1": [0xE04,
                                    {"COMPLETION_COUNTER": [0x0, 0x6],
                                     "OVERFLOW_COUNTER": [0x6, 0x1]}
                                    ],
    "DSCRPTR_COMPLETION_STATUS": [0xe3c, 0x0, 0x2],
    "DSCRPTR_SW_RESET": [0xe40, 0x0, 0x1],
    "DSCRPTR_CNTX_SWITCH_COUNTER_VAL": [0xe44, 0x0, 0x20],
    "DSCRPTR_DISABLE_CNTX_SWITCH": [0xe48, 0x0, 0x1],
    "DSCRPTR_DEBUG_MODE": [0xe4c, 0x0, 0x1],
    "DSCRPTR_FILTER_DROPPED_CNT": [0xe50, 0x0, 0x20],
    "DSCRPTR_FILTER_DROPPED_MEM_CNT": [0xe54, 0x0, 0x20],
    "DSCRPTR_FILTER_DEBUG": [0xe58, 0x0, 0x8],
    "DSCRPTR_FILTER_DROPPED_ADDRESS": [0xe5c, 0x0, 0x20],
    "DSCRPTR_QUEUE_SRAM_SIZE": [0xe60, 0x0, 0xa],
    "DSCRPTR_SINGLE_ADDR_EN": [0xe64, 0x0, 0x1],
    "DSCRPTR_MEASURE_CNTR": [0xe68, 0x0, 0x20],
    "DSCRPTR_FILTER_DROPPED_ADDRESS_HIGH": [0xe6c, 0x0, 0x10],
    "DSCRPTR_QUEUE0_WORD0": [0xe80, 0x0, 0x20],
    "DSCRPTR_QUEUE0_WORD1": [0xE84,
                             {"DIN_DMA_MODE": [0x0, 0x2],
                              "DIN_SIZE": [0x2, 0x18],
                              "NS_BIT": [0x1a, 0x1],
                              "DIN_CONST_VALUE": [0x1b, 0x1],
                              "NOT_LAST": [0x1c, 0x1],
                              "LOCK_QUEUE": [0x1d, 0x1],
                              "DIN_VIRTUAL_HOST": [0x1e, 0x2]}
                             ],
    "DSCRPTR_QUEUE0_WORD2": [0xe88, 0x0, 0x20],
    "DSCRPTR_QUEUE0_WORD3": [0xE8C,
                             {"DOUT_DMA_MODE": [0x0, 0x2],
                              "DOUT_SIZE": [0x2, 0x18],
                              "NS_BIT": [0x1a, 0x1],
                              "DOUT_LAST_IND": [0x1b, 0x1],
                              "HASH_XOR_BIT": [0x1d, 0x1],
                              "DOUT_VIRTUAL_HOST": [0x1e, 0x2]}
                             ],
    "DSCRPTR_QUEUE0_WORD4": [0xE90,
                             {"DATA_FLOW_MODE": [0x0, 0x6],
                              "AES_SEL_N_HASH": [0x6, 0x1],
                              "AES_XOR_CRYPTO_KEY": [0x7, 0x1],
                              "ACK_NEEDED": [0x8, 0x2],
                              "CIPHER_MODE": [0xa, 0x4],
                              "CMAC_SIZE0": [0xe, 0x1],
                              "CIPHER_DO": [0xf, 0x2],
                              "CIPHER_CONF0": [0x11, 0x2],
                              "CIPHER_CONF1": [0x13, 0x1],
                              "CIPHER_CONF2": [0x14, 0x2],
                              "KEY_SIZE": [0x16, 0x2],
                              "SETUP_OPERATION": [0x18, 0x4],
                              "DIN_SRAM_ENDIANNESS": [0x1c, 0x1],
                              "DOUT_SRAM_ENDIANNESS": [0x1d, 0x1],
                              "WORD_SWAP": [0x1e, 0x1],
                              "BYTES_SWAP": [0x1f, 0x1]}
                             ],
    "DSCRPTR_QUEUE0_WORD5": [0xE94,
                             {"DIN_ADDR_HIGH": [0x0, 0x10],
                              "DOUT_ADDR_HIGH": [0x10, 0x10]}
                             ],
    "DSCRPTR_QUEUE0_WATERMARK": [0xe98, 0x0, 0xa],
    "DSCRPTR_QUEUE0_CONTENT": [0xe9c, 0x0, 0xa],
    "DSCRPTR_QUEUE1_WORD0": [0xea0, 0x0, 0x20],
    "DSCRPTR_QUEUE1_WORD1": [0xEA4,
                             {"DIN_DMA_MODE": [0x0, 0x2],
                              "DIN_SIZE": [0x2, 0x18],
                              "NS_BIT": [0x1a, 0x1],
                              "DIN_CONST": [0x1b, 0x1],
                              "NOT_LAST": [0x1c, 0x1],
                              "LOCK_QUEUE": [0x1d, 0x1],
                              "DIN_VIRTUAL_HOST": [0x1e, 0x2]}
                             ],
    "DSCRPTR_QUEUE1_WORD2": [0xea8, 0x0, 0x20],
    "DSCRPTR_QUEUE1_WORD3": [0xEAC,
                             {"DOUT_DMA_MODE": [0x0, 0x2],
                              "DOUT_SIZE": [0x2, 0x18],
                              "NS_BIT": [0x1a, 0x1],
                              "DOUT_LAST_IND": [0x1b, 0x1],
                              "HASH_XOR_BIT": [0x1d, 0x1],
                              "DOUT_VIRTUAL_HOST": [0x1e, 0x2]}
                             ],
    "DSCRPTR_QUEUE1_WORD4": [0xEB0,
                             {"DATA_FLOW_MODE": [0x0, 0x6],
                              "AES_SEL_N_HASH": [0x6, 0x1],
                              "AES_XOR_CRYPTO_KEY": [0x7, 0x1],
                              "ACK_NEEDED": [0x8, 0x2],
                              "CIPHER_MODE": [0xa, 0x4],
                              "CMAC_SIZE0": [0xe, 0x1],
                              "CIPHER_DO": [0xf, 0x2],
                              "CIPHER_CONF0": [0x11, 0x2],
                              "CIPHER_CONF1": [0x13, 0x1],
                              "CIPHER_CONF2": [0x14, 0x2],
                              "KEY_SIZE": [0x16, 0x2],
                              "SETUP_OPERATION": [0x18, 0x4],
                              "DIN_SRAM_ENDIANNESS": [0x1c, 0x1],
                              "DOUT_SRAM_ENDIANNESS": [0x1d, 0x1],
                              "WORD_SWAP": [0x1e, 0x1],
                              "BYTES_SWAP": [0x1f, 0x1]}
                             ],
    "DSCRPTR_QUEUE1_WORD5": [0xEB4,
                             {"DIN_ADDR_HIGH": [0x0, 0x10],
                              "DOUT_ADDR_HIGH": [0x10, 0x10]}
                             ],
    "DSCRPTR_QUEUE1_WATERMARK": [0xeb8, 0x0, 0xa],
    "DSCRPTR_QUEUE1_CONTENT": [0xebc, 0x0, 0xa]
}

HASH = {
    "HASH_H0": [0x640, 0x0, 0x20],
    "HASH_H1": [0x644, 0x0, 0x20],
    "HASH_H2": [0x648, 0x0, 0x20],
    "HASH_H3": [0x64c, 0x0, 0x20],
    "HASH_H4": [0x650, 0x0, 0x20],
    "HASH_H5": [0x654, 0x0, 0x20],
    "HASH_H6": [0x658, 0x0, 0x20],
    "HASH_H7": [0x65c, 0x0, 0x20],
    "HASH_H8": [0x660, 0x0, 0x20],
    "FLUSH_AES_MAC_BUF": [0x680, 0x0, 0x1],
    "AUTO_HW_PADDING": [0x684, 0x0, 0x1],
    "LOAD_INIT_STATE": [0x694, 0x0, 0x1],
    "TRUNC_OUTPUT": [0x698, 0x0, 0x2],
    "DUMP_COMPARE_REST": [0x69c, 0x0, 0x1],
    "DUMP_TO_DOUT": [0x6a0, 0x0, 0x1],
    "HASH_SEL_AES_MAC": [0x6a4, 0x0, 0x1],
    "HASH_H0_SAVED": [0x740, 0x0, 0x20],
    "HASH_H1_SAVED": [0x744, 0x0, 0x20],
    "HASH_H2_SAVED": [0x748, 0x0, 0x20],
    "HASH_H3_SAVED": [0x74c, 0x0, 0x20],
    "HASH_H4_SAVED": [0x750, 0x0, 0x20],
    "HASH_H5_SAVED": [0x754, 0x0, 0x20],
    "HASH_H6_SAVED": [0x758, 0x0, 0x20],
    "HASH_H7_SAVED": [0x75c, 0x0, 0x20],
    "HASH_H8_SAVED": [0x760, 0x0, 0x20],
    "HASH_VERSION": [0x7B0,
                     {"FIXES": [0x0, 0x8],
                      "MINOR_VERSION_NUMBER": [0x8, 0x4],
                      "MAJOR_VERSION_NUMBER": [0xc, 0x4]}
                     ],
    "HASH_CONTROL": [0x7C0,
                     {"MODE_0_1": [0x0, 0x2],
                      "MODE_3": [0x3, 0x1]}
                     ],
    "HASH_PAD_EN": [0x7c4, 0x0, 0x1],
    "HASH_PAD_CFG": [0x7c8, 0x2, 0x1],
    "HASH_CUR_LEN_0": [0x7cc, 0x0, 0x20],
    "HASH_CUR_LEN_1": [0x7d0, 0x0, 0x20],
    "HASH_PARAM": [0x7DC,
                   {"CW": [0x0, 0x4],
                    "CH": [0x4, 0x4],
                    "DW": [0x8, 0x4],
                    "SHA_512_EXISTS": [0xc, 0x1],
                    "PAD_EXISTS": [0xd, 0x1],
                    "MD5_EXISTS": [0xe, 0x1],
                    "HMAC_EXISTS": [0xf, 0x1],
                    "SHA_256_EXISTS": [0x10, 0x1],
                    "HASH_COMPARE_EXISTS": [0x11, 0x1],
                    "DUMP_HASH_TO_DOUT_EXISTS": [0x12, 0x1]}
                   ],
    "HASH_AES_SW_RESET": [0x7e4, 0x0, 0x1],
    "HASH_ENDIANESS": [0x7e8, 0x0, 0x1],
    "HASH_LOAD_DIGEST": [0x7fc, 0x0, 0x1]
}

AXI = {
    "AXIM_MON_INFLIGHT0": [0xb00, 0x0, 0x8],
    "AXIM_MON_INFLIGHT1": [0xb04, 0x0, 0x8],
    "AXIM_MON_INFLIGHT2": [0xb08, 0x0, 0x8],
    "AXIM_MON_INFLIGHT3": [0xb0c, 0x0, 0x8],
    "AXIM_MON_INFLIGHT4": [0xb10, 0x0, 0x8],
    "AXIM_MON_INFLIGHT5": [0xb14, 0x0, 0x8],
    "AXIM_MON_INFLIGHT8": [0xb20, 0x0, 0x8],
    "AXIM_MON_INFLIGHT9": [0xb24, 0x0, 0x8],
    "AXIM_MON_INFLIGHT10": [0xb28, 0x0, 0x8],
    "AXIM_MON_INFLIGHT11": [0xb2c, 0x0, 0x8],
    "AXIM_MON_INFLIGHTLAST0": [0xb40, 0x0, 0x8],
    "AXIM_MON_INFLIGHTLAST1": [0xb44, 0x0, 0x8],
    "AXIM_MON_INFLIGHTLAST2": [0xb48, 0x0, 0x8],
    "AXIM_MON_INFLIGHTLAST3": [0xb4c, 0x0, 0x8],
    "AXIM_MON_INFLIGHTLAST4": [0xb50, 0x0, 0x8],
    "AXIM_MON_INFLIGHTLAST5": [0xb54, 0x0, 0x8],
    "AXIM_MON_INFLIGHTLAST8": [0xb60, 0x0, 0x8],
    "AXIM_MON_INFLIGHTLAST9": [0xb64, 0x0, 0x8],
    "AXIM_MON_INFLIGHTLAST10": [0xb68, 0x0, 0x8],
    "AXIM_MON_INFLIGHTLAST11": [0xb6c, 0x0, 0x8],
    "AXIM_PIDTABLE0": [0xB70,
                       {"PID_BROKEN1": [0x0, 0x1],
                        "PID_BROKEN2": [0x1, 0x1],
                        "PID_OSCNTR": [0x2, 0x8],
                        "PID_ID": [0xa, 0x5]}
                       ],
    "AXIM_PIDTABLE1": [0xB74,
                       {"PID_BROKEN1": [0x0, 0x1],
                        "PID_BROKEN2": [0x1, 0x1],
                        "PID_OSCNTR": [0x2, 0x8],
                        "PID_ID": [0xa, 0x5]}
                       ],
    "AXIM_PIDTABLE2": [0xB78,
                       {"PID_BROKEN1": [0x0, 0x1],
                        "PID_BROKEN2": [0x1, 0x1],
                        "PID_OSCNTR": [0x2, 0x8],
                        "PID_ID": [0xa, 0x5]}
                       ],
    "AXIM_PIDTABLE3": [0xB7C,
                       {"PID_BROKEN1": [0x0, 0x1],
                        "PID_BROKEN2": [0x1, 0x1],
                        "PID_OSCNTR": [0x2, 0x8],
                        "PID_ID": [0xa, 0x5]}
                       ],
    "AXIM_MON_COMP0": [0xb80, 0x0, 0x10],
    "AXIM_MON_COMP1": [0xb84, 0x0, 0x10],
    "AXIM_MON_COMP2": [0xb88, 0x0, 0x10],
    "AXIM_MON_COMP3": [0xb8c, 0x0, 0x10],
    "AXIM_MON_COMP4": [0xb90, 0x0, 0x10],
    "AXIM_MON_COMP5": [0xb94, 0x0, 0x10],
    "AXIM_MON_COMP8": [0xba0, 0x0, 0x10],
    "AXIM_MON_COMP9": [0xba4, 0x0, 0x10],
    "AXIM_MON_COMP10": [0xba8, 0x0, 0x10],
    "AXIM_MON_COMP11": [0xbac, 0x0, 0x10],
    "AXIM_MON_RMAX": [0xbb4, 0x0, 0x20],
    "AXIM_MON_RMIN": [0xbb8, 0x0, 0x20],
    "AXIM_MON_WMAX": [0xbbc, 0x0, 0x20],
    "AXIM_MON_WMIN": [0xbc0, 0x0, 0x20],
    "AXIM_MON_ERR": [0xBC4,
                     {"BRESP": [0x0, 0x2],
                      "BID": [0x2, 0x4],
                      "RRESP": [0x10, 0x2],
                      "RID": [0x12, 0x4]}
                     ],
    "AXIM_RDSTAT": [0xbc8, 0x0, 0x4],
    "AXIM_RLATENCY": [0xbd0, 0x0, 0x20],
    "AXIM_RBURST": [0xbd4, 0x0, 0x20],
    "AXIM_WLATENCY": [0xbd8, 0x0, 0x20],
    "AXIM_WBURST": [0xbdc, 0x0, 0x20],
    "AXIM_CACHETYPE_CFG": [0xBE0,
                           {"ICACHE_ARCACHE": [0x0, 0x4],
                            "DCACHE_ARCACHE": [0x4, 0x4],
                            "DD_ARCACHE": [0x8, 0x4],
                            "NOT_USED0": [0xc, 0x4],
                            "ICACHE_AWCACHE": [0x10, 0x4],
                            "DCACHE_AWCACHE": [0x14, 0x4],
                            "DD_AWCACHE": [0x18, 0x4],
                            "NOT_USED1": [0x1c, 0x4]}
                           ],
    "AXIM_PROT_CFG": [0xBE4,
                      {"ICACHE_ARPROT": [0x0, 0x2],
                       "DCACHE_ARPROT": [0x2, 0x2],
                       "DD_ARPROT": [0x4, 0x1],
                       "NOT_USED0": [0x5, 0x3],
                       "ICACHE_AWPROT": [0x8, 0x2],
                       "DCACHE_AWPROT": [0xa, 0x2],
                       "DD_AWPROT": [0xc, 0x1],
                       "NOT_USED1": [0xd, 0x3]}
                      ],
    "AXIM_CFG1": [0xBE8,
                  {"RD_AFTER_WR_STALL": [0x0, 0x4],
                   "BRESPMASK": [0x4, 0x1],
                   "RRESPMASK": [0x5, 0x1],
                   "INFLTMASK": [0x6, 0x1],
                   "COMPMASK": [0x7, 0x1],
                   "ACCUM_LIMIT": [0x10, 0x5]}
                  ],
    "AXIM_ACE_CONST": [0xBEC,
                       {"ARDOMAIN": [0x0, 0x2],
                        "AWDOMAIN": [0x2, 0x2],
                        "ARBAR": [0x4, 0x2],
                        "AWBAR": [0x6, 0x2],
                        "ARSNOOP": [0x8, 0x4],
                        "AWSNOOP_NOT_ALIGNED": [0xc, 0x3],
                        "AWSNOOP_ALIGNED": [0xf, 0x3],
                        "AWADDR_NOT_MASKED": [0x12, 0x7],
                        "AWLEN_VAL": [0x19, 0x4]}
                       ],
    "AXIM_CACHE_PARAMS": [0xBF0,
                          {"AWCACHE_LAST": [0x0, 0x4],
                           "AWCACHE": [0x4, 0x4],
                           "ARCACHE": [0x8, 0x4]}
                          ]
}


class DescDirection:
    DESC_DIRECTION_ILLEGAL = 0xFFFFFFFF
    DESC_DIRECTION_ENCRYPT_ENCRYPT = 0
    DESC_DIRECTION_DECRYPT_DECRYPT = 1
    DESC_DIRECTION_DECRYPT_ENCRYPT = 3
    DESC_DIRECTION_END = INT32_MAX


class sep_engine_type:
    SEP_ENGINE_NULL = 0
    SEP_ENGINE_AES = 1
    SEP_ENGINE_DES = 2
    SEP_ENGINE_HASH = 3
    SEP_ENGINE_RC4 = 4
    SEP_ENGINE_DOUT = 5


class sep_crypto_alg:
    SEP_CRYPTO_ALG_NULL = 0xFFFFFFFF
    SEP_CRYPTO_ALG_AES = 0
    SEP_CRYPTO_ALG_DES = 1
    SEP_CRYPTO_ALG_HASH = 2
    SEP_CRYPTO_ALG_RC4 = 3
    SEP_CRYPTO_ALG_C2 = 4
    SEP_CRYPTO_ALG_HMAC = 5
    SEP_CRYPTO_ALG_AEAD = 6
    SEP_CRYPTO_ALG_BYPASS = 7
    SEP_CRYPTO_ALG_COMBINED = 8
    SEP_CRYPTO_ALG_NUM = 9
    SEP_CRYPTO_ALG_RESERVE32B = INT32_MAX


class sep_crypto_direction:
    SEP_CRYPTO_DIRECTION_NULL = 0xFFFFFFFF
    SEP_CRYPTO_DIRECTION_ENCRYPT = 0
    SEP_CRYPTO_DIRECTION_DECRYPT = 1
    SEP_CRYPTO_DIRECTION_DECRYPT_ENCRYPT = 3
    SEP_CRYPTO_DIRECTION_RESERVE32B = INT32_MAX


class sep_cipher_mode:
    SEP_CIPHER_NULL_MODE = 0xFFFFFFFF
    SEP_CIPHER_ECB = 0
    SEP_CIPHER_CBC = 1
    SEP_CIPHER_CTR = 2
    SEP_CIPHER_CBC_MAC = 3
    SEP_CIPHER_XTS = 4
    SEP_CIPHER_XCBC_MAC = 5
    SEP_CIPHER_OFB = 6
    SEP_CIPHER_CMAC = 7
    SEP_CIPHER_CCM = 8
    SEP_CIPHER_CBC_CTS = 11
    SEP_CIPHER_GCTR = 12
    SEP_CIPHER_RESERVE32B = INT32_MAX


class sep_hash_mode:
    SEP_HASH_NULL = 0xFFFFFFFF
    SEP_HASH_SHA1 = 0
    SEP_HASH_SHA256 = 1
    SEP_HASH_SHA224 = 2
    SEP_HASH_SHA512 = 3
    SEP_HASH_SHA384 = 4
    SEP_HASH_MD5 = 5
    SEP_HASH_CBC_MAC = 6
    SEP_HASH_XCBC_MAC = 7
    SEP_HASH_CMAC = 8
    SEP_HASH_MODE_NUM = 9
    SEP_HASH_RESERVE32B = INT32_MAX


class sep_hash_hw_mode:
    SEP_HASH_HW_MD5 = 0
    SEP_HASH_HW_SHA1 = 1
    SEP_HASH_HW_SHA256 = 2
    SEP_HASH_HW_SHA224 = 10
    SEP_HASH_HW_SHA512 = 4
    SEP_HASH_HW_SHA384 = 12
    SEP_HASH_HW_GHASH = 6
    SEP_HASH_HW_RESERVE32B = INT32_MAX


class sep_c2_mode:
    SEP_C2_NULL = 0xFFFFFFFF
    SEP_C2_ECB = 0
    SEP_C2_CBC = 1
    SEP_C2_RESERVE32B = INT32_MAX


class sep_multi2_mode:
    SEP_MULTI2_NULL = 0xFFFFFFFF
    SEP_MULTI2_ECB = 0
    SEP_MULTI2_CBC = 1
    SEP_MULTI2_OFB = 2
    SEP_MULTI2_RESERVE32B = INT32_MAX


class sep_crypto_key_type:
    SEP_USER_KEY = 0
    SEP_ROOT_KEY = 1
    SEP_PROVISIONING_KEY = 2
    SEP_SESSION_KEY = 3
    SEP_APPLET_KEY = 4
    SEP_END_OF_KEYS = INT32_MAX


class DmaMode:
    DMA_MODE_NULL = 0xFFFFFFFF
    NO_DMA = 0
    DMA_SRAM = 1
    DMA_DLLI = 2
    DMA_MLLI = 3


class FlowMode:
    FLOW_MODE_NULL = -1
    BYPASS = 0
    DIN_AES_DOUT = 1
    AES_to_HASH = 2
    AES_and_HASH = 3
    DIN_DES_DOUT = 4
    DES_to_HASH = 5
    DES_and_HASH = 6
    DIN_HASH = 7
    DIN_HASH_and_BYPASS = 8
    AESMAC_and_BYPASS = 9
    AES_to_HASH_and_DOUT = 10
    DIN_RC4_DOUT = 11
    DES_to_HASH_and_DOUT = 12
    AES_to_AES_to_HASH_and_DOUT = 13
    AES_to_AES_to_HASH = 14
    AES_to_HASH_and_AES = 15
    DIN_MULTI2_DOUT = 16
    DIN_AES_AESMAC = 17
    HASH_to_DOUT = 18
    S_DIN_to_AES = 32
    S_DIN_to_AES2 = 33
    S_DIN_to_DES = 34
    S_DIN_to_RC4 = 35
    S_DIN_to_MULTI2 = 36
    S_DIN_to_HASH = 37
    S_AES_to_DOUT = 38
    S_AES2_to_DOUT = 39
    S_RC4_to_DOUT = 41
    S_DES_to_DOUT = 42
    S_HASH_to_DOUT = 43
    SET_FLOW_ID = 44


class SetupOp:
    SETUP_LOAD_NOP = 0
    SETUP_LOAD_STATE0 = 1
    SETUP_LOAD_STATE1 = 2
    SETUP_LOAD_STATE2 = 3
    SETUP_LOAD_KEY0 = 4
    SETUP_LOAD_XEX_KEY = 5
    SETUP_WRITE_STATE0 = 8
    SETUP_WRITE_STATE1 = 9
    SETUP_WRITE_STATE2 = 10
    SETUP_WRITE_STATE3 = 11


class AesMacSelector:
    AES_SK = 1
    AES_CMAC_INIT = 2
    AES_CMAC_SIZE0 = 3


class HwCryptoKey:
    USER_KEY = 0
    ROOT_KEY = 1
    PROVISIONING_KEY = 2
    SESSION_KEY = 3
    RESERVED_KEY = 4
    PLATFORM_KEY = 5
    CUSTOMER_KEY = 6
    KFDE0_KEY = 7
    KFDE1_KEY = 9
    KFDE2_KEY = 10
    KFDE3_KEY = 11


class HwAesKeySize:
    AES_128_KEY = 0
    AES_192_KEY = 1
    AES_256_KEY = 2


class HwDesKeySize:
    DES_ONE_KEY = 0
    DES_TWO_KEYS = 1
    DES_THREE_KEYS = 2


"""

/* SeP context size */
#ifndef SEP_CTX_SIZE_LOG2
#if (SEP_SUPPORT_SHA > 256)
SEP_CTX_SIZE_LOG2 8
#else
SEP_CTX_SIZE_LOG2 7
#endif
#endif
SEP_CTX_SIZE (1<<SEP_CTX_SIZE_LOG2)
SEP_CTX_SIZE_WORDS (SEP_CTX_SIZE >> 2)

SEP_DES_IV_SIZE 8
SEP_DES_BLOCK_SIZE 8

SEP_DES_ONE_KEY_SIZE 8
SEP_DES_DOUBLE_KEY_SIZE 16
SEP_DES_TRIPLE_KEY_SIZE 24
SEP_DES_KEY_SIZE_MAX SEP_DES_TRIPLE_KEY_SIZE

SEP_AES_IV_SIZE 16
SEP_AES_IV_SIZE_WORDS (SEP_AES_IV_SIZE >> 2)

SEP_AES_BLOCK_SIZE 16
SEP_AES_BLOCK_SIZE_WORDS 4

SEP_AES_128_BIT_KEY_SIZE 16
SEP_AES_128_BIT_KEY_SIZE_WORDS	(SEP_AES_128_BIT_KEY_SIZE >> 2)
SEP_AES_192_BIT_KEY_SIZE 24
SEP_AES_192_BIT_KEY_SIZE_WORDS	(SEP_AES_192_BIT_KEY_SIZE >> 2)
SEP_AES_256_BIT_KEY_SIZE 32
SEP_AES_256_BIT_KEY_SIZE_WORDS	(SEP_AES_256_BIT_KEY_SIZE >> 2)
SEP_AES_KEY_SIZE_MAX			SEP_AES_256_BIT_KEY_SIZE
SEP_AES_KEY_SIZE_WORDS_MAX		(SEP_AES_KEY_SIZE_MAX >> 2)

SEP_MD5_DIGEST_SIZE 16
SEP_SHA1_DIGEST_SIZE 20
SEP_SHA224_DIGEST_SIZE 28
SEP_SHA256_DIGEST_SIZE 32
SEP_SHA256_DIGEST_SIZE_IN_WORDS 8
SEP_SHA384_DIGEST_SIZE 48
SEP_SHA512_DIGEST_SIZE 64

SEP_SHA1_BLOCK_SIZE 64
SEP_SHA1_BLOCK_SIZE_IN_WORDS 16
SEP_MD5_BLOCK_SIZE 64
SEP_MD5_BLOCK_SIZE_IN_WORDS 16
SEP_SHA224_BLOCK_SIZE 64
SEP_SHA256_BLOCK_SIZE 64
SEP_SHA256_BLOCK_SIZE_IN_WORDS 16
SEP_SHA1_224_256_BLOCK_SIZE 64
SEP_SHA384_BLOCK_SIZE 128
SEP_SHA512_BLOCK_SIZE 128

#if (SEP_SUPPORT_SHA > 256)
SEP_DIGEST_SIZE_MAX SEP_SHA512_DIGEST_SIZE
SEP_HASH_BLOCK_SIZE_MAX SEP_SHA512_BLOCK_SIZE /*1024b*/
#else /* Only up to SHA256 */
SEP_DIGEST_SIZE_MAX SEP_SHA256_DIGEST_SIZE
SEP_HASH_BLOCK_SIZE_MAX SEP_SHA256_BLOCK_SIZE /*512b*/
#endif

SEP_HMAC_BLOCK_SIZE_MAX SEP_HASH_BLOCK_SIZE_MAX

SEP_RC4_KEY_SIZE_MIN 1
SEP_RC4_KEY_SIZE_MAX 20
SEP_RC4_STATE_SIZE 264

SEP_C2_KEY_SIZE_MAX 16
SEP_C2_BLOCK_SIZE 8

SEP_MULTI2_SYSTEM_KEY_SIZE 		32
SEP_MULTI2_DATA_KEY_SIZE 		8
SEP_MULTI2_SYSTEM_N_DATA_KEY_SIZE 	(SEP_MULTI2_SYSTEM_KEY_SIZE + SEP_MULTI2_DATA_KEY_SIZE)
#define	SEP_MULTI2_BLOCK_SIZE					8
#define	SEP_MULTI2_IV_SIZE					8
#define	SEP_MULTI2_MIN_NUM_ROUNDS				8
#define	SEP_MULTI2_MAX_NUM_ROUNDS				128


SEP_ALG_MAX_BLOCK_SIZE SEP_HASH_BLOCK_SIZE_MAX

SEP_MAX_COMBINED_ENGINES 4

SEP_MAX_CTX_SIZE (max(sizeof(struct sep_ctx_rc4), \
				sizeof(struct sep_ctx_cache_entry)))
"""


def hw_desc_init():
    res = [0, 0, 0, 0, 0, 0]
    return res


def bitmask(mask_size):
    if mask_size < 32:
        return (1 << mask_size) - 1
    else:
        return 0xFFFFFFFF


def tovalue(value, bitsize, shift):
    v = value & (1 << bitsize) - 1
    return v << shift


def hw_desc_set_cipher_mode(pDesc, cipherMode):
    shift, bitsize = DSCRPTR["DSCRPTR_QUEUE0_WORD4"][1]["CIPHER_MODE"]
    pDesc[4] |= tovalue(cipherMode, bitsize, shift)
    return pDesc


def hw_desc_set_cipher_config0(pDesc, cipherConfig):
    shift, bitsize = DSCRPTR["DSCRPTR_QUEUE0_WORD4"][1]["CIPHER_CONF0"]
    pDesc[4] |= tovalue(cipherConfig, bitsize, shift)
    return pDesc


def hw_desc_set_cipher_config1(pDesc, cipherConfig):
    shift, bitsize = DSCRPTR["DSCRPTR_QUEUE0_WORD4"][1]["CIPHER_CONF1"]
    pDesc[4] |= tovalue(cipherConfig, bitsize, shift)
    return pDesc


def hw_desc_set_setup_mode(pDesc, setupMode):
    shift, bitsize = DSCRPTR["DSCRPTR_QUEUE0_WORD4"][1]["SETUP_OPERATION"]
    pDesc[4] |= tovalue(setupMode, bitsize, shift)
    return pDesc


def hw_desc_set_flow_mode(pDesc, flowMode):
    shift, bitsize = DSCRPTR["DSCRPTR_QUEUE0_WORD4"][1]["DATA_FLOW_MODE"]
    pDesc[4] |= tovalue(flowMode, bitsize, shift)
    return pDesc


def hw_desc_set_dout_sram(pDesc, doutAdr, doutSize):
    v = DSCRPTR["DSCRPTR_QUEUE0_WORD2"]
    shift, bitsize = v[1], v[2]
    pDesc[2] |= tovalue((doutAdr & 0xFFFFFFFF), bitsize, shift)
    shift, bitsize = DSCRPTR["DSCRPTR_QUEUE0_WORD3"][1]["DOUT_DMA_MODE"]
    pDesc[3] |= tovalue(DmaMode.DMA_SRAM, bitsize, shift)
    shift, bitsize = DSCRPTR["DSCRPTR_QUEUE0_WORD3"][1]["DOUT_SIZE"]
    pDesc[3] |= tovalue(doutSize, bitsize, shift)
    return pDesc


def hw_desc_set_dout_dlli(pDesc, doutAdr, doutSize, axiNs, lastind):
    v = DSCRPTR["DSCRPTR_QUEUE0_WORD2"]
    shift, bitsize = v[1], v[2]
    pDesc[2] |= tovalue((doutAdr & 0xFFFFFFFF), bitsize, shift)
    shift, bitsize = DSCRPTR["DSCRPTR_QUEUE0_WORD5"][1]["DOUT_ADDR_HIGH"]
    pDesc[5] |= tovalue((doutAdr >> 32 & 0xFFFFFFFF) << 16, bitsize, shift)
    shift, bitsize = DSCRPTR["DSCRPTR_QUEUE0_WORD3"][1]["DOUT_DMA_MODE"]
    pDesc[3] |= tovalue(DmaMode.DMA_DLLI, bitsize, shift)
    shift, bitsize = DSCRPTR["DSCRPTR_QUEUE0_WORD3"][1]["DOUT_SIZE"]
    pDesc[3] |= tovalue(doutSize, bitsize, shift)
    shift, bitsize = DSCRPTR["DSCRPTR_QUEUE0_WORD3"][1]["DOUT_LAST_IND"]
    pDesc[3] |= tovalue(lastind, bitsize, shift)
    shift, bitsize = DSCRPTR["DSCRPTR_QUEUE0_WORD3"][1]["NS_BIT"]
    pDesc[3] |= tovalue(lastind, bitsize, shift)
    return pDesc


def hw_desc_set_key_size_aes(pDesc, keySize):
    shift, bitsize = DSCRPTR["DSCRPTR_QUEUE0_WORD4"][1]["KEY_SIZE"]
    pDesc[4] |= tovalue(((keySize >> 3) - 2), bitsize, shift)
    return pDesc


def hw_desc_set_din_sram(pDesc, dinAdr, dinSize):
    v = DSCRPTR["DSCRPTR_QUEUE0_WORD0"]
    shift, bitsize = v[1], v[2]
    pDesc[0] |= tovalue(dinAdr & 0xFFFFFFFF, bitsize, shift)
    shift, bitsize = DSCRPTR["DSCRPTR_QUEUE0_WORD1"][1]["DIN_DMA_MODE"]
    pDesc[1] |= tovalue(DmaMode.DMA_SRAM, bitsize, shift)
    shift, bitsize = DSCRPTR["DSCRPTR_QUEUE0_WORD1"][1]["DIN_SIZE"]
    pDesc[1] |= tovalue(dinSize, bitsize, shift)
    return pDesc


def hw_desc_set_din_const(pDesc, val, dinSize):
    v = DSCRPTR["DSCRPTR_QUEUE0_WORD0"]
    shift, bitsize = v[1], v[2]
    pDesc[0] |= tovalue(val & 0xFFFFFFFF, bitsize, shift)
    shift, bitsize = DSCRPTR["DSCRPTR_QUEUE0_WORD1"][1]["DIN_CONST_VALUE"]
    pDesc[1] |= tovalue(1, bitsize, shift)
    shift, bitsize = DSCRPTR["DSCRPTR_QUEUE0_WORD1"][1]["DIN_DMA_MODE"]
    pDesc[1] |= tovalue(DmaMode.DMA_SRAM, bitsize, shift)
    shift, bitsize = DSCRPTR["DSCRPTR_QUEUE0_WORD1"][1]["DIN_SIZE"]
    pDesc[1] |= tovalue(dinSize, bitsize, shift)
    return pDesc


def hw_desc_set_cipher_do(pDesc, cipherDo):
    shift, bitsize = DSCRPTR["DSCRPTR_QUEUE0_WORD4"][1]["CIPHER_DO"]
    pDesc[4] |= tovalue(cipherDo, bitsize, shift)
    return pDesc


def hw_desc_set_din_nodma(pDesc, dinAdr, dinSize):
    v = DSCRPTR["DSCRPTR_QUEUE0_WORD0"]
    shift, bitsize = v[1], v[2]
    pDesc[0] |= tovalue(dinAdr & 0xFFFFFFFF, bitsize, shift)
    shift, bitsize = DSCRPTR["DSCRPTR_QUEUE0_WORD1"][1]["DIN_DMA_MODE"]
    pDesc[1] |= tovalue(DmaMode.NO_DMA, bitsize, shift)
    shift, bitsize = DSCRPTR["DSCRPTR_QUEUE0_WORD1"][1]["DIN_SIZE"]
    pDesc[1] |= tovalue(dinSize, bitsize, shift)
    return pDesc


def hw_desc_set_din_type(pDesc, dmaMode, dinAdr, dinSize, axiId, axiNs):
    v = DSCRPTR["DSCRPTR_QUEUE0_WORD0"]
    shift, bitsize = v[1], v[2]
    pDesc[0] |= tovalue(dinAdr & 0xFFFFFFFF, bitsize, shift)
    shift, bitsize = DSCRPTR["DSCRPTR_QUEUE0_WORD5"][1]["DIN_ADDR_HIGH"]
    pDesc[5] |= tovalue(dinAdr >> 32 & 0xFFFF, bitsize, shift)
    shift, bitsize = DSCRPTR["DSCRPTR_QUEUE0_WORD1"][1]["DIN_DMA_MODE"]
    pDesc[1] |= tovalue(dmaMode, bitsize, shift)
    shift, bitsize = DSCRPTR["DSCRPTR_QUEUE0_WORD1"][1]["DIN_SIZE"]
    pDesc[1] |= tovalue(dinSize, bitsize, shift)
    shift, bitsize = DSCRPTR["DSCRPTR_QUEUE0_WORD1"][1]["DIN_VIRTUAL_HOST"]
    pDesc[1] |= tovalue(axiId, bitsize, shift)
    shift, bitsize = DSCRPTR["DSCRPTR_QUEUE0_WORD1"][1]["NS_BIT"]
    pDesc[1] |= tovalue(axiNs, bitsize, shift)
    return pDesc


class dxcc_reg:
    def __init__(self, setup):
        self.dxcc_base = setup.dxcc_base
        self.read32 = setup.read32
        self.write32 = setup.write32

    def __setattr__(self, key, value):
        if key in ("sej_base", "read32", "write32", "regval"):
            return super(dxcc_reg, self).__setattr__(key, value)
        if key in regval:
            addr = regval[key] + self.sej_base
            return self.write32(addr, value)
        else:
            return super(dxcc_reg, self).__setattr__(key, value)

    def __getattribute__(self, item):
        if item in ("sej_base", "read32", "write32", "regval"):
            return super(dxcc_reg, self).__getattribute__(item)
        if item in regval:
            addr = regval[item] + self.sej_base
            return self.read32(addr)
        else:
            return super(dxcc_reg, self).__getattribute__(item)


class dxcc(metaclass=LogBase):
    DX_HOST_IRR = 0xA00
    DX_HOST_ICR = 0xA08  # DX_CC = (HOST_RGF, HOST_ICR)
    DX_DSCRPTR_QUEUE0_WORD0 = 0xE80
    DX_DSCRPTR_QUEUE0_WORD1 = 0xE84
    DX_DSCRPTR_QUEUE0_WORD2 = 0xE88
    DX_DSCRPTR_QUEUE0_WORD3 = 0xE8C
    DX_DSCRPTR_QUEUE0_WORD4 = 0xE90
    DX_DSCRPTR_QUEUE0_WORD5 = 0xE94
    DX_DSCRPTR_QUEUE0_CONTENT = 0xE9C
    DX_HOST_SEP_HOST_GPR0 = 0xA80  # DX_HOST_SEP_HOST_GPR0_REG_OFFSET
    DX_HOST_SEP_HOST_GPR1 = 0xA88
    DX_HOST_SEP_HOST_GPR2 = 0xA90
    DX_HOST_SEP_HOST_GPR3 = 0xA9C
    DX_HOST_SEP_HOST_GPR4 = 0xAA0

    def SB_HalClearInterruptBit(self):
        self.write32(self.dxcc_base + self.DX_HOST_ICR, [4])

    def SB_CryptoWait(self):
        while True:
            value = self.read32(self.dxcc_base + self.DX_HOST_IRR)
            if value != 0:
                return value

    def sasi_paldmaunmap(self, value1):
        return

    def sasi_paldmamap(self, value1):
        # value2=value1
        return value1

    def sasi_sb_adddescsequence(self, data):
        while True:
            if self.read32(self.dxcc_base + self.DX_DSCRPTR_QUEUE0_CONTENT) << 0x1C != 0:
                break
        self.write32(self.dxcc_base + self.DX_DSCRPTR_QUEUE0_WORD0, data[0])
        self.write32(self.dxcc_base + self.DX_DSCRPTR_QUEUE0_WORD1, data[1])
        self.write32(self.dxcc_base + self.DX_DSCRPTR_QUEUE0_WORD2, data[2])
        self.write32(self.dxcc_base + self.DX_DSCRPTR_QUEUE0_WORD3, data[3])
        self.write32(self.dxcc_base + self.DX_DSCRPTR_QUEUE0_WORD4, data[4])
        self.write32(self.dxcc_base + self.DX_DSCRPTR_QUEUE0_WORD5, data[5])

    def __init__(self, setup, loglevel=logging.INFO):
        self.__logger = logsetup(self, self.__logger, loglevel)
        self.hwcode = setup.hwcode
        self.dxcc_base = setup.dxcc_base
        self.read32 = setup.read32
        self.write32 = setup.write32
        self.writemem = setup.writemem
        self.da_payload_addr = setup.da_payload_addr

        self.__logger = self.__logger
        self.reg = dxcc_reg(setup)

    def tzcc_clk(self, value):
        if value:
            res = self.write32(0x1000108C, 0x18000000)
        else:
            res = self.write32(0x10001088, 0x8000000)
        return res

    def generate_itrustee_fbe(self, key_sz=32):
        fdekey = b""
        dstaddr = self.da_payload_addr - 0x300
        self.tzcc_clk(1)
        for ctr in range(0, key_sz // 16):
            itrustee = b"TrustedCorekeymaster" + b"\x07" * 0x10
            seed = itrustee + pack("<B", ctr)
            paddr = self.SBROM_AesCmac(1, 0x0, seed, 0x0, len(seed), dstaddr)
            for field in self.read32(paddr + 0x108, 4):
                fdekey += pack("<I", field)
        self.tzcc_clk(0)
        return fdekey

    def generate_rpmb(self, level=0):
        rpmb_ikey = bytearray(b"RPMB KEY")
        rpmb_salt = bytearray(b"SASI")
        for i in range(len(rpmb_ikey)):
            rpmb_ikey[i] = rpmb_ikey[i] + level
        for i in range(len(rpmb_salt)):
            rpmb_salt[i] = rpmb_salt[i] + level

        keylength = 0x20
        if level > 0:
            keylength = 0x10
        self.tzcc_clk(1)
        dstaddr = self.da_payload_addr - 0x300
        rpmbkey = self.SBROM_KeyDerivation(1, rpmb_ikey, rpmb_salt, keylength, dstaddr)
        self.tzcc_clk(0)
        return rpmbkey

    def generate_provision_key(self):
        plat_key = b"KEY PLAT"
        prov_key = b"PROVISION KEY"
        self.tzcc_clk(1)
        dstaddr = self.da_payload_addr - 0x300
        platkey = self.SBROM_KeyDerivation(2, plat_key, mtk_oem_key, 0x20, dstaddr)
        provkey = self.SBROM_KeyDerivation(5, prov_key, mtk_oem_key, 0x20, dstaddr)
        self.tzcc_clk(0)
        return platkey, provkey

    def generate_sha256(self, data):
        dstaddr = self.da_payload_addr - 0x300
        self.sbrom_sha256(buffer=data, destaddr=dstaddr)
        result = bytearray()
        for field in self.read32(dstaddr, 8):
            result.extend(pack("<I", field))
        return result

    # SBROM_KeyDerivation(dxcc_base,encmode=1,fde1,8,fde2,4,fdekey,fdekey>>31,fdekeylen
    """
    SBROM_KeyDerivation PC(00230B77) R0:10210000,R1:00000001,R2:001209D8,R3:00000008,R4:00100000,R5:00233760,R6:00000010
    R2:53514e43214c465a
    R5:52504d42204b45595341534953514e43
    key="SQNC!LFZ",8
    salt="SASI",4
    requestedlen=0x10
    """

    def SBROM_KeyDerivation(self, aeskeytype, key, salt, requestedlen, destaddr):
        result = bytearray()
        buffer = bytearray(b"\x00" * 0x43)
        if aeskeytype - 1 > 4 or (1 << (aeskeytype - 1) & 0x17) == 0:
            return 0xF2000002
        if requestedlen > 0xFF or (requestedlen << 28) & 0xFFFFFFFF:
            return 0xF2000003
        if 0x0 >= len(key) > 0x20:
            return 0xF2000003
        bufferlen = len(salt) + 3 + len(key)
        iterlength = (requestedlen + 0xF) >> 4
        if len(key) == 0:
            keyend = 1
        else:
            buffer[1:1 + len(key)] = key
            keyend = len(key) + 1
        saltstart = keyend + 1
        if len(salt) > 0:
            buffer[saltstart:saltstart + len(salt)] = salt
        # ToDo: verify buffer structure
        buffer[saltstart + len(salt):saltstart + len(salt) + 4] = pack("<I", 8 * requestedlen)
        # buffer=0153514e43214c465a005442544a80
        for i in range(0, iterlength):
            buffer[0] = i + 1
            dstaddr = self.SBROM_AesCmac(aeskeytype, 0x0, buffer, 0, bufferlen, destaddr)
            if dstaddr != 0:
                for field in self.read32(dstaddr + 0x108, 4):
                    result.extend(pack("<I", field))
        return result

    def SBROM_AesCmac(self, aesKeyType, pInternalKey, buffer, flag, bufferlen, destaddr):
        dataptr = destaddr + 0x118  # SP - 0xA8 - 0x24 - 0x28 - 0x38 - 0x88 - 0x30 - ((12 * 8) - 16)
        pInternalKeyptr = destaddr + 0x108  # dataptr - 0x10
        destptr = destaddr
        self.writemem(dataptr, buffer[:bufferlen])
        self.writemem(pInternalKeyptr, pack("<Q", pInternalKey))
        if self.SBROM_AesCmacDriver(aesKeyType, pInternalKeyptr, dataptr, DmaMode.DMA_DLLI, bufferlen, destaddr):
            return destptr
        return 0

    def SB_HalInit(self):
        return self.SB_HalClearInterruptBit()

    def SB_HalWaitDescCompletion(self, destptr):
        data = []
        self.SB_HalClearInterruptBit()
        val = self.sasi_paldmamap(0)
        data.append(0x0)  # 0
        data.append(0x8000011)  # 1 #DIN_DMA|DOUT_DMA|DIN_CONST
        data.append(destptr)  # 2
        data.append(0x8000012)  # 3
        data.append(0x100)  # 4
        data.append((destptr >> 32) << 16)  # 5
        self.sasi_sb_adddescsequence(data)
        while True:
            if self.SB_CryptoWait() & 4 != 0:
                break
        while True:
            value = self.read32(self.dxcc_base + 0xBA0)
            if value != 0:
                break
        if value == 1:
            self.SB_HalClearInterruptBit()
            self.sasi_paldmaunmap(val)
            return 0
        else:
            return 0xF6000001

    def SBROM_AesCmacDriver(self, aesKeyType, pInternalKey, pDataIn, dmaMode, blockSize, pCMacResult):
        if aesKeyType == HwCryptoKey.ROOT_KEY:
            if self.read32(self.dxcc_base + self.DX_HOST_SEP_HOST_GPR4) & 2 != 0:
                keySizeInBytes = 0x20  # SEP_AES_256_BIT_KEY_SIZE
            else:
                keySizeInBytes = 0x10  # SEP_AES_128_BIT_KEY_SIZE
        else:
            keySizeInBytes = 0x10  # SEP_AES_128_BIT_KEY_SIZE
        self.SB_HalInit()

        pdesc = hw_desc_init()
        pdesc = hw_desc_set_cipher_mode(pdesc, sep_cipher_mode.SEP_CIPHER_CMAC)  # desc[4]=0x1C00
        pdesc = hw_desc_set_cipher_config0(pdesc, DescDirection.DESC_DIRECTION_ENCRYPT_ENCRYPT)
        pdesc = hw_desc_set_key_size_aes(pdesc, keySizeInBytes)  # desc[4]=0x801C00
        # pdesc = hw_desc_set_din_sram(pdesc, ivSramAddr, AES_IV_COUNTER_SIZE_IN_BYTES)
        pdesc = hw_desc_set_din_const(pdesc, 0, AES_IV_COUNTER_SIZE_IN_BYTES)  # desc[1]=0x8000041
        pdesc = hw_desc_set_flow_mode(pdesc, FlowMode.S_DIN_to_AES)  # desc[4]=0x801C20
        pdesc = hw_desc_set_setup_mode(pdesc, SetupOp.SETUP_LOAD_STATE0)  # desc[4]=0x1801C20
        self.sasi_sb_adddescsequence(pdesc)

        # Load key
        mdesc = hw_desc_init()
        if aesKeyType == HwCryptoKey.USER_KEY:
            mdesc = hw_desc_set_din_sram(mdesc, pInternalKey, AES_Key128Bits_SIZE_IN_BYTES)
        mdesc = hw_desc_set_cipher_do(mdesc, aesKeyType)  # desc[4]=0x8000
        mdesc = hw_desc_set_cipher_mode(mdesc, sep_cipher_mode.SEP_CIPHER_CMAC)  # desc[4]=0x9C00
        mdesc = hw_desc_set_cipher_config0(mdesc, DescDirection.DESC_DIRECTION_ENCRYPT_ENCRYPT)
        mdesc = hw_desc_set_key_size_aes(mdesc, keySizeInBytes)  # desc[4]=0x809C00
        mdesc = hw_desc_set_flow_mode(mdesc, FlowMode.S_DIN_to_AES)  # desc[4]=0x809C20
        mdesc = hw_desc_set_setup_mode(mdesc, SetupOp.SETUP_LOAD_KEY0)  # desc[4]=0x4809C20
        self.sasi_sb_adddescsequence(mdesc)

        # Process input data
        rdesc = hw_desc_init()
        if dmaMode == DmaMode.DMA_SRAM:
            rdesc = hw_desc_set_din_sram(rdesc, pDataIn, blockSize)
        else:
            rdesc = hw_desc_set_din_type(rdesc, DmaMode.DMA_DLLI, pDataIn, blockSize, SB_AXI_ID,
                                         AXI_SECURE)  # desc[1]=0x3E, desc[0]=0x200E18
        rdesc = hw_desc_set_flow_mode(rdesc, FlowMode.DIN_AES_DOUT)  # desc[4]=1
        self.sasi_sb_adddescsequence(rdesc)

        if aesKeyType != HwCryptoKey.PROVISIONING_KEY:
            xdesc = hw_desc_init()
            xdesc = hw_desc_set_cipher_mode(xdesc, sep_cipher_mode.SEP_CIPHER_CMAC)  # desc[4]=0x1C00
            xdesc = hw_desc_set_cipher_config0(xdesc, DescDirection.DESC_DIRECTION_ENCRYPT_ENCRYPT)
            xdesc = hw_desc_set_setup_mode(xdesc, SetupOp.SETUP_WRITE_STATE0)  # desc[4]=0x8001C00
            xdesc = hw_desc_set_flow_mode(xdesc, FlowMode.S_AES_to_DOUT)  # desc[4]=0x8001C26
            if dmaMode == DmaMode.DMA_SRAM:
                xdesc = hw_desc_set_dout_sram(xdesc, pInternalKey, AES_BLOCK_SIZE_IN_BYTES)
            else:
                xdesc = hw_desc_set_dout_dlli(xdesc, pInternalKey, AES_BLOCK_SIZE_IN_BYTES, SB_AXI_ID,
                                              0)  # desc[2]=0x200E08, desc[3]=0x42
            # xdesc = hw_desc_set_din_sram(xdesc, 0, 0)
            xdesc = hw_desc_set_din_nodma(xdesc, 0, 0)
            self.sasi_sb_adddescsequence(xdesc)
        return self.SB_HalWaitDescCompletion(pCMacResult) == 0

    def mtee_decrypt(self, data):
        key = bytes.fromhex("B936C14D95A99585073E5607784A51F7444B60D6BFD6110F76D004CCB7E1950E")
        skey = hashlib.sha256(key).digest()
        return AES.new(key=skey[:16], iv=skey[16:], mode=AES.MODE_CBC).decrypt(data)

    def descramble(self, data):
        key = bytes.fromhex("5C0E349A27DC46034C7B6744A378BD17")
        iv = bytes.fromhex("A0B0924686447109F2D51DCDDC93458A")
        ctr = Counter.new(128, initial_value=bytes_to_long(iv))
        return AES.new(key=key, counter=ctr, mode=AES.MODE_CTR).decrypt(data)

    def sbrom_sha256(self, buffer, destaddr):  # TZCC_SHA256_Init
        dataptr = destaddr + 0x40
        ivptr = destaddr + 0x20
        outptr = destaddr
        self.writemem(0x1000108C, 0x18000000)
        iv = bytes.fromhex("19CDE05BABD9831F8C68059B7F520E513AF54FA572F36E3C85AE67BB67E6096A")
        self.writemem(ivptr, iv)
        self.writemem(dataptr, buffer)
        self.sbrom_cryptoinitdriver(aesivptr=ivptr, cryptodrivermode=0)
        self.sbrom_cryptoupdate(inputptr=dataptr, outputptr=outptr, blockSize=len(buffer), islastblock=1,
                                cryptodrivermode=0, waitforcrypto=3)
        self.sbrom_cryptofinishdriver(outptr)
        self.writemem(0x10001088, 0x8000000)
        return 0

    def sbrom_cryptoinitdriver(self, aesivptr, cryptodrivermode):
        if cryptodrivermode & 0xFFFFFFFD == 0:
            # 0=v9
            # 1=0x820
            # 2=0
            # 3=0
            # 4=0x1000825
            # 5=v9>>32
            pdesc = hw_desc_init()
            pdesc = hw_desc_set_din_type(pdesc, DmaMode.DMA_DLLI, aesivptr, 0x20, SB_AXI_ID, AXI_SECURE)
            pdesc = hw_desc_set_flow_mode(pdesc, FlowMode.S_DIN_to_HASH)
            pdesc = hw_desc_set_cipher_mode(pdesc, sep_hash_hw_mode.SEP_HASH_HW_SHA256)
            pdesc = hw_desc_set_setup_mode(pdesc, SetupOp.SETUP_LOAD_STATE0)
            self.sasi_sb_adddescsequence(pdesc)
            # 0=0
            # 1=0x8000041
            # 2=0
            # 3=0
            # 4=0x4000825
            # 5=0
            tdesc = hw_desc_init()
            tdesc = hw_desc_set_flow_mode(tdesc, FlowMode.S_DIN_to_HASH)
            tdesc = hw_desc_set_cipher_mode(tdesc, sep_hash_hw_mode.SEP_HASH_HW_SHA256)
            tdesc = hw_desc_set_setup_mode(tdesc, SetupOp.SETUP_LOAD_KEY0)
            tdesc = hw_desc_set_din_const(tdesc, 0, 0x10)
            self.sasi_sb_adddescsequence(tdesc)

    def sbrom_cryptoupdate(self, inputptr, outputptr, blockSize, islastblock, cryptodrivermode, waitforcrypto):
        if waitforcrypto != 2 or self.SB_HalWaitDescCompletion(self.dxcc_base) == 0:
            if islastblock == 1 and (cryptodrivermode & 0xFFFFFFFD) == 0:
                # 0=0
                # 1=0
                # 2=outputptr
                # 3=0x42
                # 4=0x908082B
                # 5=outputptr>>32<<16
                ydesc = hw_desc_init()
                ydesc = hw_desc_set_dout_dlli(ydesc, outputptr, 0x10, SB_AXI_ID, 0)
                ydesc = hw_desc_set_flow_mode(ydesc, FlowMode.S_HASH_to_DOUT)
                ydesc = hw_desc_set_cipher_mode(ydesc, sep_hash_hw_mode.SEP_HASH_HW_SHA256)
                ydesc = hw_desc_set_cipher_config1(ydesc, sep_hash_mode.SEP_HASH_SHA256)
                ydesc = hw_desc_set_setup_mode(ydesc, SetupOp.SETUP_WRITE_STATE1)
                self.sasi_sb_adddescsequence(ydesc)
            udesc = hw_desc_init()
            udesc = hw_desc_set_din_type(udesc, DmaMode.DMA_DLLI, inputptr, blockSize, SB_AXI_ID, AXI_SECURE)
            if not cryptodrivermode:
                udesc = hw_desc_set_flow_mode(udesc, FlowMode.DIN_HASH)
            self.sasi_sb_adddescsequence(udesc)
            if (waitforcrypto == 2 and not islastblock) or waitforcrypto == 3:
                self.SB_HalWaitDescCompletion(self.dxcc_base)
            elif waitforcrypto == 0:
                return 0
            else:
                return 0xF2000001

    def sbrom_cryptofinishdriver(self, outputptr):
        fdesc = hw_desc_init()
        fdesc = hw_desc_set_dout_dlli(fdesc, outputptr, 0x10, SB_AXI_ID, 0)
        fdesc = hw_desc_set_flow_mode(fdesc, FlowMode.S_HASH_to_DOUT)
        fdesc = hw_desc_set_cipher_mode(fdesc, sep_hash_hw_mode.SEP_HASH_HW_SHA256)
        fdesc = hw_desc_set_cipher_config0(fdesc, sep_hash_hw_mode.SEP_HASH_HW_SHA256)
        fdesc = hw_desc_set_cipher_config1(fdesc, sep_hash_mode.SEP_HASH_SHA256)
        fdesc = hw_desc_set_setup_mode(fdesc, SetupOp.SETUP_WRITE_STATE0)
        # 0 = 0
        # 1 = 0
        # 2 = outputptr
        # 3 = 0x82
        # 4 = 0x80C082B
        # 5 = outputptr>>32<<16
        self.sasi_sb_adddescsequence(fdesc)
        return self.SB_HalWaitDescCompletion(self.dxcc_base)


if __name__ == "__main__":
    # 0=0
    # 1=0
    # 2=outputptr
    # 3=0x42
    # 4=0x908082B
    # 5=outputptr>>32<<16
    desc = hw_desc_init()
    desc = hw_desc_set_dout_dlli(desc, 0, 0x10, SB_AXI_ID, 0)
    desc = hw_desc_set_flow_mode(desc, FlowMode.S_HASH_to_DOUT)
    desc = hw_desc_set_cipher_mode(desc, sep_hash_hw_mode.SEP_HASH_HW_SHA256)
    desc = hw_desc_set_cipher_config1(desc, sep_hash_mode.SEP_HASH_SHA256)
    desc = hw_desc_set_setup_mode(desc, SetupOp.SETUP_WRITE_STATE1)
    print(desc)
