-
Notifications
You must be signed in to change notification settings - Fork 666
/
decode-syseeprom
executable file
·270 lines (212 loc) · 8.95 KB
/
decode-syseeprom
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
#!/usr/bin/env python3
"""
Command-line utility for obtaining system EEPROM data
It can either read the information directly from the EEPROM
or read information cached in State DB via syseerpomd
"""
#############################################################################
#
# This is the main script that handles eeprom encoding and decoding
#
import optparse
import os
import re
import sys
import sonic_platform
from sonic_platform_base.sonic_eeprom.eeprom_tlvinfo import TlvInfoDecoder
from sonic_py_common import device_info, logger
from swsscommon.swsscommon import SonicV2Connector
from tabulate import tabulate
EEPROM_INFO_TABLE = 'EEPROM_INFO'
SYSLOG_IDENTIFIER = 'decode-syseeprom'
log = logger.Logger(SYSLOG_IDENTIFIER)
def instantiate_eeprom_object():
eeprom = None
try:
eeprom = sonic_platform.platform.Platform().get_chassis().get_eeprom()
except Exception as e:
log.log_error('Failed to obtain EEPROM object due to {}'.format(repr(e)))
eeprom = None
return eeprom
def read_and_print_eeprom():
eeprom = instantiate_eeprom_object()
if not eeprom:
return False
sys_eeprom_data = eeprom.read_eeprom()
eeprom.decode_eeprom(sys_eeprom_data)
def print_eeprom_dict(tlv_dict):
'''
Pretty print EEPROM contents from a dictionary
'''
if not tlv_dict:
print('Unable to retrieve system EEPROM info')
return
print('TlvInfo Header:')
print(' Id String: {}'.format(tlv_dict['header']['id']))
print(' Version: {}'.format(tlv_dict['header']['version']))
print(' Total Length: {}'.format(tlv_dict['header']['length']))
tlv_table_header = ['TLV Name', 'Code', 'Len', 'Value']
tlv_table_body = []
for tlv in tlv_dict['tlv_list']:
tlv_table_body.append([tlv['name'], tlv['code'], tlv['length'], tlv['value']])
print(tabulate(tlv_table_body, tlv_table_header, tablefmt='simple'))
print('')
if tlv_dict['checksum_valid']:
print('(checksum valid)')
else:
print('(*** checksum invalid)')
def read_eeprom_from_db():
tlv_dict = {}
db = SonicV2Connector(host="127.0.0.1")
db.connect(db.STATE_DB)
initialized = db.get(db.STATE_DB, '{}|{}'.format(EEPROM_INFO_TABLE, 'State'), 'Initialized')
if initialized != '1':
return None
tlv_header = db.get_all(db.STATE_DB, '{}|{}'.format(EEPROM_INFO_TABLE, 'TlvHeader'))
tlv_dict['header'] = {}
tlv_dict['header']['id'] = tlv_header.get('Id String', 'N/A')
tlv_dict['header']['version'] = tlv_header.get('Version', 'N/A')
tlv_dict['header']['length'] = tlv_header.get('Total Length', 'N/A')
tlv_dict['tlv_list'] = []
concerned_tlvs = []
concerned_tlvs.extend(range(TlvInfoDecoder._TLV_CODE_PRODUCT_NAME, TlvInfoDecoder._TLV_CODE_SERVICE_TAG + 1))
concerned_tlvs.append(TlvInfoDecoder._TLV_CODE_VENDOR_EXT)
concerned_tlvs.append(TlvInfoDecoder._TLV_CODE_CRC_32)
for tlv_code in concerned_tlvs:
tlv_code_string = '0x{:02X}'.format(tlv_code)
tlv_data = db.get_all(db.STATE_DB, '{}|{}'.format(EEPROM_INFO_TABLE, tlv_code_string.lower()))
if not tlv_data:
continue
if tlv_code == TlvInfoDecoder._TLV_CODE_VENDOR_EXT:
num_vendor_ext = int(tlv_data.get('Num_vendor_ext', '0'))
for i in range(num_vendor_ext):
tlv = {}
tlv['code'] = tlv_code_string
tlv['name'] = tlv_data.get('Name_{}'.format(i), 'N/A')
tlv['length'] = tlv_data.get('Len_{}'.format(i), 'N/A')
tlv['value'] = tlv_data.get('Value_{}'.format(i), 'N/A')
tlv_dict['tlv_list'].append(tlv)
else:
tlv = {}
tlv['code'] = tlv_code_string
tlv['name'] = tlv_data.get('Name', 'N/A')
tlv['length'] = tlv_data.get('Len', 'N/A')
tlv['value'] = tlv_data.get('Value', 'N/A')
tlv_dict['tlv_list'].append(tlv)
checksum_valid = db.get(db.STATE_DB, '{}|{}'.format(EEPROM_INFO_TABLE, 'Checksum'), 'Valid')
tlv_dict['checksum_valid'] = (checksum_valid == '1')
return tlv_dict
def get_tlv_value_from_db(tlv_code):
db = SonicV2Connector(host="127.0.0.1")
db.connect(db.STATE_DB)
initialized = db.get(db.STATE_DB, '{}|{}'.format(EEPROM_INFO_TABLE, 'State'), 'Initialized')
if initialized != '1':
print('Failed to read system EEPROM info from DB')
return None
tlv_code_string = '0x{:02x}'.format(tlv_code)
return db.get(db.STATE_DB, '{}|{}'.format(EEPROM_INFO_TABLE, tlv_code_string), 'Value')
def print_mgmt_mac(use_db=False):
base_mac_addr = None
if use_db:
base_mac_addr = get_tlv_value_from_db(TlvInfoDecoder._TLV_CODE_MAC_BASE)
else:
eeprom = instantiate_eeprom_object()
if not eeprom:
print('Failed to read system EEPROM info')
return
# TODO: Some vendors override eeprom.base_mac_addr() such that it doesn't take EEPROM data
# as a parameter. Refactor sonic_eeprom such that the function reads the EEPROM data itself
# and doesn't require the parameter (this will also require modifying some vendor's implementations.
try:
base_mac_addr = eeprom.base_mac_addr()
except TypeError:
base_mac_addr = eeprom.base_mac_addr(eeprom.read_eeprom())
if base_mac_addr:
print(base_mac_addr)
def print_serial(use_db=False):
serial = None
if use_db:
serial = get_tlv_value_from_db(TlvInfoDecoder._TLV_CODE_SERIAL_NUMBER)
else:
eeprom = instantiate_eeprom_object()
if not eeprom:
print('Failed to read system EEPROM info')
return
# TODO: Some vendors override eeprom.serial_number_str() such that it doesn't take EEPROM data
# as a parameter. Refactor sonic_eeprom such that the function reads the EEPROM data itself
# and doesn't require the parameter (this will also require modifying some vendor's implementations.
try:
serial = eeprom.serial_number_str()
except TypeError:
serial = eeprom.serial_number_str(eeprom.read_eeprom())
print(serial)
def print_model(use_db=False):
model = None
if use_db:
model = get_tlv_value_from_db(TlvInfoDecoder._TLV_CODE_PRODUCT_NAME)
else:
eeprom = instantiate_eeprom_object()
if not eeprom:
print('Failed to read system EEPROM info')
return
# TODO: Some vendors override eeprom.modelstr() such that it doesn't take EEPROM data
# as a parameter. Refactor sonic_eeprom such that the function reads the EEPROM data itself
# and doesn't require the parameter (this will also require modifying some vendor's implementations.
try:
model = eeprom.modelstr()
except TypeError:
model = eeprom.modelstr(eeprom.read_eeprom())
print(model)
#-------------------------------------------------------------------------------
#
# sets global variable "optcfg"
#
def get_cmdline_opts():
optcfg = optparse.OptionParser(usage='usage: {} [-s][-m]'.format(sys.argv[0]))
optcfg.add_option('-d', dest='db', action='store_true',
default=False, help='print eeprom from database')
optcfg.add_option('-s', dest='serial', action='store_true',
default=False, help='print device serial number/service tag')
optcfg.add_option('-p', dest='modelstr', action='store_true', default=False,
help='print the device product name')
optcfg.add_option('-m', dest='mgmtmac', action='store_true', default=False,
help='print the base mac address for management interfaces')
return optcfg.parse_args()
def main():
support_eeprom_db = True
if not os.geteuid() == 0:
print('Root privileges are required for this operation')
return 1
(opts, args) = get_cmdline_opts()
# Get platform name
platform = device_info.get_platform()
# Currently, don't support eeprom db on Arista platform
platforms_without_eeprom_db = ['.*arista.*', '.*kvm.*']
if any(re.match(p, platform) for p in platforms_without_eeprom_db):
support_eeprom_db = False
use_db = opts.db and support_eeprom_db
if opts.mgmtmac:
print_mgmt_mac(use_db)
elif opts.serial:
print_serial(use_db)
elif opts.modelstr:
print_model(use_db)
else:
if use_db:
tlv_dict = read_eeprom_from_db()
if not tlv_dict:
print('Failed to read system EEPROM info from DB')
return 2
print_eeprom_dict(tlv_dict)
else:
read_and_print_eeprom()
return 0
if __name__ == '__main__':
try:
sys.exit(main())
except KeyboardInterrupt:
print('\nInterrupted\n', file=sys.stderr)
sys.exit(3)
except (RuntimeError, OSError, IOError) as errstr:
print('{}: ERROR : {}\n'.format(sys.argv[0], str(errstr)), file=sys.stderr)
sys.exit(4)