1# Copyright (C) 2019-2022 Intel Corporation.
2#
3# SPDX-License-Identifier: BSD-3-Clause
4#
5
6import os
7from inspectorlib import external_tools
8
9BIOS_INFO_KEY = ['BIOS Information', 'Vendor:', 'Version:', 'Release Date:', 'BIOS Revision:']
10
11BASE_BOARD_KEY = ['Base Board Information', 'Manufacturer:', 'Product Name:', 'Version:']
12
13
14def check_dmi():
15    """Check if this tool run on native os"""
16    return os.path.exists("/sys/firmware/dmi")
17
18
19def print_yel(msg, warn=False, end=True):
20    """Output the message with the color of yellow
21    :param msg: the stings which will be output to STDOUT
22    :param warn: the condition if needs to be output the color of yellow with 'Warning'
23    :param end: The flag of it needs to combine with the next line for stdout
24    """
25    if warn:
26        if end:
27            print("\033[1;33mWarning\033[0m: "+msg)
28        else:
29            print("\033[1;33mWarning\033[0m: "+msg, end="")
30    else:
31        if end:
32            print("\033[1;33m{}\033[0m".format(msg))
33        else:
34            print("\033[1;33m{}\033[0m".format(msg), end="")
35
36
37def print_red(msg, err=False):
38    """Output the messag with the color of red
39    :param msg: the stings which will be output to STDOUT
40    :param err: the condition if needs to be output the color of red with 'Error'
41    """
42    if err:
43        print("\033[1;31mError\033[0m: "+msg)
44    else:
45        print("\033[1;31m{0}\033[0m".format(msg))
46
47
48def handle_hw_info(line, hw_info):
49    """Handle the hardware information
50    :param line: one line of information which had decoded to 'ASCII'
51    :param hw_info: the list which contains key strings what can describe bios/board
52    """
53    for board_line in hw_info:
54        if board_line == " ".join(line.split()[0:1]) or \
55                board_line == " ".join(line.split()[0:2]) or \
56                board_line == " ".join(line.split()[0:3]):
57            return True
58    return False
59
60
61def handle_pci_dev(line):
62    """Handle if it match PCI device information pattern
63    :param line: one line of information which had decoded to 'ASCII'
64    """
65    if "Region" in line and "Memory at" in line:
66        return True
67
68    if line != '\n':
69        if line.split()[0][2:3] == ':' and line.split()[0][5:6] == '.':
70            return True
71
72    return False
73
74
75def handle_block_dev(line):
76    """Handle if it match root device information pattern
77    :param line: one line of information which had decoded to 'ASCII'
78    """
79    block_format = ''
80    for root_type in line.split():
81        if "ext4" in root_type or "ext3" in root_type:
82            block_type = ''
83            block_dev = line.split()[0]
84            for type_str in line.split():
85                if "TYPE=" in type_str:
86                    block_type = type_str
87
88            block_format = block_dev + " " + block_type
89            return block_format
90
91    return block_format
92
93
94def dump_execute(cmd, desc, config):
95    """Execute cmd and get information
96    :param cmd: command what can be executed in shell
97    :param desc: the string indicated what class information store to board.xml
98    :param config: file pointer that opened for writing board information
99    """
100    val_dmi = check_dmi()
101    print("\t<{0}>".format(desc), file=config)
102
103    if not val_dmi and "dmidecode" in cmd:
104        print("\t\t</{0}>".format(desc), file=config)
105        return
106
107    res = external_tools.run(cmd)
108    while True:
109        line = res.stdout.readline().decode('ascii')
110        line = line.replace("&", "&amp;").replace('"', "&quot;") \
111            .replace("'", "&apos;").replace("<", "&lt;").replace(">", "&gt;")
112
113        if not line:
114            break
115
116        if desc == "PCI_DEVICE":
117            if "prog-if" in line:
118                line = line.rsplit('(', 1)[0] + '\n'
119            ret = handle_pci_dev(line)
120            if not ret:
121                continue
122
123        if desc == "BIOS_INFO":
124            ret = handle_hw_info(line, BIOS_INFO_KEY)
125            if not ret:
126                continue
127
128        if desc == "BASE_BOARD_INFO":
129            ret = handle_hw_info(line, BASE_BOARD_KEY)
130            if not ret:
131                continue
132
133        if desc == "BLOCK_DEVICE_INFO":
134            line = handle_block_dev(line)
135            if not line:
136                continue
137
138        print("\t{}".format(line.strip()), file=config)
139
140    print("\t</{0}>".format(desc), file=config)
141
142
143def get_output_lines(cmd):
144    res_lines = []
145    res = external_tools.run(cmd)
146    while True:
147        line = res.stdout.readline().decode('ascii')
148        if not line:
149            break
150        res_lines.append(line.strip())
151
152    return res_lines
153