1#!/usr/bin/env python3 2# coding=utf-8 3# Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15 16""" 17* Description: NV binary create. 18* Create: 2020-3-10 19""" 20from ctypes import * 21import os 22import re 23import ctypes 24import sys 25import pycparser 26 27from parse_msgdefs import Visitor 28from conf_parser import ParserError 29 30nextIsBitfield = 0 31bitField = 0 32bitLength = 0 33lastByteLength = 0 34totalByteLen = 0 35baseByteSize = 0 36# type define 37class generate_data_stream: 38 def __init__(self): 39 self.v = Visitor() 40 41 def phase_etypes(self, file): 42 code = pycparser.parse_file(file) 43 tmp = Visitor() 44 tmp.visit(code) 45 self.v.typedefs.update(tmp.typedefs) 46 47 def is_dec(self, s): 48 try: 49 int(s) 50 return True 51 except ValueError: 52 pass 53 return False 54 55 def is_hex(self, s): 56 try: 57 int(s, 16) 58 return True 59 except ValueError: 60 pass 61 return False 62 63 def byte_len(self, value): 64 if value < 256: 65 return 1 66 elif value < 65536: 67 return 2 68 elif value < 4294967296: 69 return 4 70 else: 71 return 8 72 73# value 的几种case需要分别考虑 74#1.直接数字 75#2.直接字符串 76#3.枚举 77#4.简单数组 78#5.结构体 79#6.结构体数组 80#7.指针 81#8.指针数组 82 def get_value(self, value_str): 83 if self.is_dec(value_str): 84 value = int(value_str) 85 return value 86 elif self.is_hex(value_str): 87 value = int(value_str, 16) 88 return value 89 return None 90 91 def get_char_value(self, value_str): 92 if type(value_str) is int: 93 return value_str 94 if len(value_str) == 1: 95 return ord(value_str) 96 return None 97 98 def get_value_for_array(self, value_str): 99 if '[' not in value_str or ']' not in value_str: 100 return None 101 value_line_list = list(filter(None, re.split(r'[;,\s\"\[\]]\s*', value_str))) 102 return value_line_list 103 104 def get_value_for_char_array(self, value_str): 105 if '\"' not in value_str: 106 return None 107 value_str = value_str.replace('\"','') 108 value_line_list = [x for x in value_str] 109 return value_line_list 110 111 def get_value_str(self, value): 112 value_line_list = list(filter(None, value.split('\n'))) 113 value_list = [] 114 for i in range(len(value_line_list)): 115 tmp_list = list(filter(None, value_line_list[i].split(' = '))) 116 value_list.append(tmp_list[1]) 117 return value_list 118 119 def get_enum_value(self, enum_fields, enum_str): 120 if 1: 121 enum_value = enum_fields.members.get(enum_str) 122 if enum_value is None: 123 msg = "[error] [%s] not a enum value, please check!!" % enum_str 124 raise ParserError(msg) 125 return enum_value 126 127 for field in enum_fields.members: 128 if enum_str == field: 129 return enum_fields.members[field] 130 131 def get_bitfield_value(self, fields, typename, value): 132 global nextIsBitfield 133 global bitField 134 global bitLength 135 global lastByteLength 136 global totalByteLen 137 global baseByteSize 138 139 bufferData = b'' 140 bitsize = self.get_value(fields.bitsize) 141 bitLength += bitsize 142 143 if value.bit_length() > bitsize: 144 msg = "[error] [%s]'s value exceeds its bit width!!" % typename 145 raise ParserError(msg) 146 if bitLength == bitsize: 147 baseByteSize = sizeof(fields) 148 totalByteLen = 0 149 writeLen = 0 150 # 前后类型相同,不压缩处理 151 if bitLength > bitsize and sizeof(fields) == lastByteLength: 152 if bitLength > baseByteSize * 8: 153 writelen = max(self.byte_len(bitField), lastByteLength) 154 bufferData += bitField.to_bytes(writelen, byteorder="little", signed=True) if bitField < 0 \ 155 else bitField.to_bytes(writelen, byteorder="little", signed=False) 156 totalByteLen += writelen 157 bitField = 0 158 bitLength = bitsize # 记录未写入的bit 159 # 前后类型不同,考虑压缩场景 160 elif bitLength > bitsize and sizeof(fields) != lastByteLength: 161 baseByteSize = sizeof(fields) if sizeof(fields) > lastByteLength else lastByteLength 162 if bitLength > baseByteSize * 8: # 不压缩处理 163 writelen = max(self.byte_len(bitField), lastByteLength) 164 bufferData += bitField.to_bytes(writelen, byteorder="little", signed=True) if bitField < 0 \ 165 else bitField.to_bytes(writelen, byteorder="little", signed=False) 166 totalByteLen += writelen 167 # 对齐处理 168 if totalByteLen % sizeof(fields) != 0: 169 bitField = 0 170 alignByteLen = sizeof(fields) - totalByteLen if sizeof(fields) > totalByteLen \ 171 else totalByteLen - sizeof(fields) 172 bufferData += bitField.to_bytes(alignByteLen, byteorder="little", signed=True) if bitField < 0 \ 173 else bitField.to_bytes(alignByteLen, byteorder="little", signed=False) 174 totalByteLen += alignByteLen 175 bitField = 0 176 bitLength = bitsize 177 if totalByteLen % baseByteSize != 0: # 非对齐场景,不压缩 178 writelen = max(self.byte_len(bitField), lastByteLength) 179 bufferData += bitField.to_bytes(writelen, byteorder="little", signed=True) if bitField < 0 \ 180 else bitField.to_bytes(writelen, byteorder="little", signed=False) 181 totalByteLen += writelen 182 bitField = 0 183 bitLength = bitsize 184 lastByteLength = sizeof(fields) 185 if bitLength > bitsize: 186 bitField = (bitField | (value << (bitLength - bitsize))) 187 else: 188 bitField = value 189 190 # print("bitsize: ",bitsize) 191 # print("value: ",value) 192 # print("lastByteLength: ",lastByteLength) 193 # print("bitLength: ",bitLength) 194 # print("totalByteLen :", totalByteLen) 195 # print("bitField: ",bitField) 196 if bitLength == (sizeof(fields) * 8): 197 writelen = max(self.byte_len(bitField), sizeof(fields)) 198 bufferData += bitField.to_bytes(writelen, byteorder="little", signed=True) if bitField < 0 \ 199 else bitField.to_bytes(writelen, byteorder="little", signed=False) 200 totalByteLen += writelen 201 bitField = 0 202 bitLength = 0 203 return bufferData 204 if nextIsBitfield == 0: 205 # 后面非位域,数据输出。如果后面嵌套结构体,结构体起始仍为位域,仍需要考虑压缩 206 writelen = max(self.byte_len(bitField), sizeof(fields)) 207 bufferData += bitField.to_bytes(writelen, byteorder="little", signed=True) if bitField < 0 \ 208 else bitField.to_bytes(writelen, byteorder="little", signed=False) 209 totalByteLen += writelen 210 bitField = 0 211 bitLength = 0 212 if totalByteLen % baseByteSize != 0: 213 bitField = 0 214 alignByteLen = baseByteSize - (totalByteLen % baseByteSize) 215 bufferData += bitField.to_bytes(alignByteLen, byteorder="little", signed=True) if bitField < 0 \ 216 else bitField.to_bytes(alignByteLen, byteorder="little", signed=False) 217 # print("bufferData: ", bufferData) 218 return bufferData 219 220 def print_type(self, typename, value, isBaseType, isEnum, isSomeKindOfArray, isUnion, isPointer): 221 print("%s, value: %s, isBaseType :" % (typename, value), isBaseType) if isBaseType else None 222 print("%s, value: %s, isEnum :" % (typename, value), isEnum) if isEnum else None 223 print("%s, value: %s, isSomeKindOfArray :" % (typename, value), isSomeKindOfArray) if isSomeKindOfArray else None 224 print("%s, value: %s, isUnion :" % (typename, value), isUnion) if isUnion else None 225 print("%s, value: %s, isPointer :" % (typename, value), isPointer) if isPointer else None 226 227 228 def recursion_parse(self, fields, type_name, value): 229 global nextIsBitfield 230 # print('recurse field: ', fields) 231 # print('recurse type_name: ', type_name) 232 # print('recurse value: ', value) 233 isBitfield = hasattr(fields, "bitsize") 234 isBaseType = not hasattr(fields, "_fields_") 235 isEnum = hasattr(fields, "members") 236 isSomeKindOfArray = issubclass(fields, ctypes.Array) 237 isUnion = isinstance(fields, ctypes.Union) 238 isPointer = hasattr(fields, "contents") 239 #self.print_type(type_name, value, isBaseType, isEnum, isSomeKindOfArray, isUnion, isPointer) 240 241 if ((isBaseType and not isSomeKindOfArray) or isEnum or isPointer) and \ 242 (type(value) is list or type(value) is dict): 243 msg = "[error] [%s] is not a array or a structrue, the value cannot be a list or a dict!!" % type_name 244 raise ParserError(msg) 245 246 if not ((isBaseType and not isSomeKindOfArray) or isEnum or isPointer) and \ 247 not (type(value) is list or type(value) is dict): 248 msg = "[error] [%s] is a array or a structrue, the value must be a list or a dict!!" % type_name 249 raise ParserError(msg) 250 251 if isUnion and not isSomeKindOfArray and type(value) is list: 252 msg = "[error] [%s] is a union, the value must be a hex or int or a dict!!" % type_name 253 raise ParserError(msg) 254 255 buffer = b'' 256 if isEnum: 257 buffer += self.get_enum_value(fields, value).to_bytes(sizeof(fields), byteorder="little") 258 # print("buffer: ", buffer) 259 return buffer 260 261 if isBaseType and not isSomeKindOfArray: 262 # print("base size: ", sizeof(fields)) 263 # print("fileds: ", fields) 264 # print("type: ", type(fields)) 265 if sizeof(fields) == 1 and \ 266 isinstance(value, str) and \ 267 not value.startswith('0x') and not value.startswith('0X'): 268 value = self.get_char_value(value) 269 else: 270 value = self.get_value(value) 271 272 if isBitfield: 273 buffer += self.get_bitfield_value(fields, type_name, value) 274 else: 275 buffer += value.to_bytes(sizeof(fields), byteorder="little", signed=True) if value < 0 \ 276 else value.to_bytes(sizeof(fields), byteorder="little", signed=False) 277 # print("buffer: ", buffer) 278 return buffer 279 280 if isUnion and not isSomeKindOfArray: 281 # print("union size: ", sizeof(fields)) 282 # union要么指定成员赋值,要么直接整体赋值,不能是list,list无法知道对具体哪个成员赋值 283 if type(value) is not dict: 284 buffer += self.get_value(value).to_bytes(sizeof(fields), byteorder="little") 285 else: 286 # 增加枚举结构的解析 287 pass 288 # print("buffer: ", buffer) 289 return buffer 290 291 if isSomeKindOfArray: 292 if type(value) is not list: 293 msg = "[error] [%s] is a array, the value must be a list!!" % type_name 294 raise ParserError(msg) 295 296 # print("array type: ", fields._type_) 297 # print("array length: ", fields._length_) 298 idx = 0 299 for val in value: 300 buffer += self.recursion_parse(fields._type_, '%s[%d]' % (type_name, idx), val) 301 idx += 1 302 # print("sizeof array [%s]: " % type_name, sizeof(fields)) 303 if len(buffer) > sizeof(fields): 304 msg = "[error] the value is oversized the array: [%s]!!" % type_name 305 raise ParserError(msg) 306 buffer += bytearray(sizeof(fields) - len(buffer)) 307 # print("buffer: ", buffer) 308 return buffer 309 310 all_types = fields._fields_ 311 # print('all_types in struct [%s] : ' % type_name, all_types) 312 if type(value) is list: 313 typesLen = len(all_types) 314 typesIdx = 0 315 for (item, item_class) in all_types: 316 if len(value) == 0: 317 buffer += bytearray(sizeof(item_class)) 318 continue 319 if typesIdx + 1 < typesLen: 320 nextField = all_types[typesIdx + 1][1] 321 nextIsBitfield = hasattr(nextField, "bitsize") 322 else: 323 nextIsBitfield = 0 324 buffer += self.recursion_parse(item_class, item, value[0]) 325 del(value[0]) 326 typesIdx += 1 327 if len(value) != 0: 328 msg = "[error] the value is not match the type: [%s]!!" % type_name 329 raise ParserError(msg) 330 return buffer 331 332 if type(value) is dict: 333 typesLen = len(all_types) 334 typesIdx = 0 335 for (item, item_class) in all_types: 336 item_value = value.get(item) 337 if item_value is None: 338 buffer += bytearray(sizeof(item_class)) 339 continue 340 if typesIdx + 1 < typesLen: 341 nextField = all_types[typesIdx + 1][1] 342 nextIsBitfield = hasattr(nextField, "bitsize") 343 else: 344 nextIsBitfield = 0 345 buffer += self.recursion_parse(item_class, item, item_value) 346 typesIdx += 1 347 return buffer 348 349 def generate(self, struct_name, value): 350 fields = self.v.typedefs.get(struct_name) 351 # print("struct: %s, value: " %struct_name, value) 352 # print('types: ', self.v.typedefs) 353 if fields is None: 354 msg = "[error] not found the type [%s]!" % struct_name 355 raise ParserError(msg) 356 buffer = self.recursion_parse(fields, struct_name, value) 357 return buffer, len(buffer) 358 359 360#DEBUG 361 362if __name__=="__main__": 363 class g_env: 364 flash_size = 0x3000 365 protocolKvIndex = 0 366 appKvIndex = 0x1000 367 secureKvindex = 0x2000 368 KV_STORE_DIR = {'security' : 0 ,'protocol' : 1 ,'application' : 2 ,'asset' : 3 } 369 KV_STATUS_DIR = {'alive':0xffff,'reserved':0,'deprecated':1} 370 KV_PAGE_ID = {'security' : 0xcb7e ,'protocol' : 0xda81 ,'application' : 0x254d ,'backup' : 0x34b2} 371 372 g_kv_pairs = { 373 'yml_test_eg' : { 374 'value' : { 375 'num_supported_bands' : 1, 376 'band_ids' :[8, 7, 6] 377 }, 378 'permanence': False 379 }, 380 'yml_test_eg2_mixed' : { 381 'value' : { 382 'param1' : 1, 383 'param2' : [[1,2,], [3,4], [5]] 384 }, 385 'permanence': False 386 }, 387 'yml_test_eg2' : { 388 'value' : [1, [[1,2,], [3,4]]], 389 'permanence': False 390 }, 391 392 'test_nv_type_nest_deep' :{ 393 'value' : [1, "C", 0, 394 [[1, 0, 0x2222, [["TEST_NV_ENUM_1"], ["TEST_NV_ENUM_2"]]], 395 [3, 0, 0x4444, [["TEST_NV_ENUM_3"], ["TEST_NV_ENUM_4"]]]] 396 ], 397 'permanence': False 398 }, 399 400 'test_nv_type_nest_deep____pure_value' :{ 401 'value' : [1, 0, "C", 402 [[1, 0x2222, 0, [[0x1111], [0x2222]]]], 403 [3, 0x4444, 0, [[0x33334444], [0x5555]]] 404 ], 405 'permanence': False 406 }, 407 'test_nv_type_nest_deep___dict' :{ 408 'value' : [1, [[1,2,], [3,4]]], 409 'permanence': False 410 }, 411 'test_nv_type_nest_deep___mixed' :{ 412 'value' : [1, [[1,2,], [3,4]]], 413 'permanence': False 414 } 415 } 416 417 struct_name = sys.argv[1] 418 etypes = sys.argv[2] 419 test = generate_data_stream() 420 test.phase_etypes(etypes) 421 nv_file_Bin = bytearray(g_env.flash_size) 422 for i in range(0, g_env.flash_size): 423 nv_file_Bin[i] = 0xFF 424 # SetKvPageHead(nv_file_Bin) 425 426 for keyValueItem in g_kv_pairs: 427 if keyValueItem != struct_name: 428 continue 429 value,value_len = test.generate(struct_name, g_kv_pairs[struct_name]['value']) 430 print("value: ", value) 431 print("value_len: ", value_len) 432 with open('nv.bin', 'wb') as f: 433 f.write(value) 434 break 435