1# 2# Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. 3# 4# SPDX-License-Identifier: BSD-3-Clause 5# 6 7import sys 8from os import path, walk, mkdir 9import subprocess 10from pydevicetree import Devicetree 11 12class bcolors: 13 HEADER = '\033[95m' 14 OKBLUE = '\033[94m' 15 OKCYAN = '\033[96m' 16 OKGREEN = '\033[92m' 17 WARNING = '\033[93m' 18 FAIL = '\033[91m' 19 ENDC = '\033[0m' 20 BOLD = '\033[1m' 21 UNDERLINE = '\033[4m' 22 23class DTTree: 24 def __init__(self, input): 25 self.input = input 26 self.test_dir = "./tmp" 27 self.logging_file = self.test_dir + "/result.log" 28 29 def dtValidate(self): 30 subprocess.run(["rm", "-rf", self.test_dir]) 31 32 if not path.exists(self.test_dir): 33 mkdir(self.test_dir) 34 35 if path.isfile(self.input): 36 self.dtValidateFile(self.input, printInfo=True) 37 return 38 39 if path.isdir(self.input): 40 self.dtValidateFiles() 41 return 42 43 def dtValidateFile(self, input, printInfo=False): 44 valid, tree = self.dtParseFile(input, printInfo) 45 46 if not valid: 47 return False 48 49 if input.rfind("/") != -1: 50 filename = self.test_dir + input[input.rfind("/"):] 51 else: 52 filename = self.test_dir + "/" + input 53 54 f = open(filename, "w+") 55 if "/dts-v1/;" not in str(tree): 56 f.write("/dts-v1/;\n\n") 57 f.write(str(tree)) 58 f.close() 59 60 if str(tree) == "": 61 return valid 62 63 return valid 64 65 def dtParseFile(self, input, printInfo=False): 66 with open(input, 'r') as f: 67 contents = f.read() 68 69 pos = contents.find("/ {") 70 if pos != -1: 71 contents = contents[pos:] 72 73 try: 74 tree = Devicetree.parseStr(contents) 75 if printInfo: 76 print(bcolors.OKGREEN + "{} parse tree successfully".format(input) + bcolors.ENDC) 77 except Exception as e: 78 if printInfo: 79 print(bcolors.FAIL + "{} parse tree failed:\t{}".format(input, str(e)) + bcolors.ENDC) 80 else: 81 f = open(self.logging_file, "a") 82 f.write("=====================================================================================\n") 83 f.write("{} result:\n".format(input)) 84 f.write("{} INVALID:\t{}\n".format(input, str(e))) 85 f.close() 86 return False, None 87 88 return True, tree 89 90 def dtValidateFiles(self): 91 f = [] 92 for (dirpath, dirnames, filenames) in walk(self.input): 93 f.extend(filenames) 94 95 allFile = len(f) 96 dtsiFile = 0 97 validFile = 0 98 invalidFile = 0 99 100 for i in f: 101 if (".dtsi" in i or ".dts" in i) and "cot" not in i and "fw-config" not in i: 102 dtsiFile += 1 103 valid = True 104 105 if self.input[-1] == "/": 106 valid = self.dtValidateFile(self.input + i) 107 else: 108 valid = self.dtValidateFile(self.input + "/" + i) 109 110 if valid: 111 validFile += 1 112 else: 113 invalidFile += 1 114 115 print("=====================================================") 116 print("Total File: " + str(allFile)) 117 print("Total DT File: " + str(dtsiFile)) 118 print("Total Valid File: " + str(validFile)) 119 print("Total Invalid File: " + str(invalidFile)) 120 121def dtValidatorMain(input): 122 dt = DTTree(input) 123 dt.dtValidate() 124 125if __name__=="__main__": 126 if (len(sys.argv) < 2): 127 print("usage: python3 " + sys.argv[0] + " [dtsi file path] or [dtsi folder path]") 128 exit() 129 if len(sys.argv) == 2: 130 dtValidatorMain(sys.argv[1]) 131