66#
77#############################################################################
88import os
9+ import struct
10+ import binascii
911
1012from sonic_py_common .logger import Logger
1113from platform_ndk import nokia_common
1719
1820logger = Logger ()
1921
22+ # ONIE TlvInfo constants
23+ TLV_INFO_HEADER = b"TlvInfo"
24+ TLV_INFO_VERSION = 0x01
25+ TLV_CRC32_TYPE = 0xFE
26+
2027#
2128# CACHE_XXX stuffs are supposted to be moved to the base classes
2229# since they are common for all vendors
@@ -38,7 +45,8 @@ def __init__(self):
3845 # use /tmp to instead
3946 cache_file = os .path .join ("/tmp" , CACHE_FILE )
4047 pass
41- if not os .path .exists (cache_file ):
48+
49+ if not os .path .exists (cache_file ) or not self .validate_eeprom_cache (cache_file ):
4250 channel , stub = nokia_common .channel_setup (nokia_common .NOKIA_GRPC_EEPROM_SERVICE )
4351 if not channel or not stub :
4452 raise RuntimeError (str (e ) + "Unable to fetch eeprom info from platform-ndk" )
@@ -95,6 +103,76 @@ def __init__(self):
95103
96104 tlv_index += eeprom [tlv_index + 1 ] + 2
97105
106+ def validate_eeprom_cache (self , file_path ):
107+ if not os .path .exists (file_path ):
108+ return False
109+ try :
110+ with open (file_path , "rb" ) as f :
111+ data = f .read ()
112+ except IOError as e :
113+ logger .log_error ("Unable to read file {}" .format (file_path ))
114+ return False
115+
116+ # Minimum size check: header (8) + version (1) + length (2) + CRC TLV (6)
117+ if len (data ) < 17 :
118+ logger .log_warning ("File {} too short to be a valid ONIE EEPROM" .format (file_path ))
119+ return False
120+
121+ # Check magic header
122+ if data [0 :7 ] != TLV_INFO_HEADER :
123+ logger .log_warning ("Missing 'TlvInfo' header" )
124+ return False
125+
126+ # Check version
127+ version = data [8 ]
128+ if version != TLV_INFO_VERSION :
129+ logger .log_warning ("Unsupported TLV version {}. Expected {}" .format (version , TLV_INFO_VERSION ))
130+ return False
131+
132+ # Read total length (big-endian)
133+ total_len = struct .unpack (">H" , data [9 :11 ])[0 ]
134+ if total_len + 11 != len (data ):
135+ logger .log_warning ("Length mismatch!" )
136+ return False
137+
138+ # Parse TLVs
139+ offset = 11
140+ crc_expected = None
141+ tlv_count = 0
142+
143+ while offset < len (data ):
144+ if offset + 2 > len (data ):
145+ logger .log_warning ("TLV entry truncated." )
146+ return False
147+
148+ tlv_type = data [offset ]
149+ tlv_len = data [offset + 1 ]
150+ offset += 2
151+
152+ if offset + tlv_len > len (data ):
153+ logger .log_warning ("TLV value exceeds file size." )
154+ return False
155+
156+ tlv_value = data [offset :offset + tlv_len ]
157+ offset += tlv_len
158+ tlv_count += 1
159+ if tlv_type == TLV_CRC32_TYPE :
160+ if tlv_len != 4 :
161+ logger .log_warning ("CRC32 TLV length must be 4." )
162+ return False
163+ crc_expected = struct .unpack (">I" , tlv_value )[0 ]
164+
165+ # CRC check
166+ if crc_expected is None :
167+ logger .log_warning ("Missing CRC32 TLV." )
168+ return False
169+
170+ crc_calc = binascii .crc32 (data [0 :- 4 ]) & 0xFFFFFFFF
171+ if crc_calc != crc_expected :
172+ logger .log_warning ("CRC32 mismatch: expected 0x{}, got 0x{}" .format (hex (crc_expected ), hex (crc_calc )))
173+ return False
174+ return True
175+
98176 def get_base_mac (self ):
99177 """
100178 Retrieves the base MAC address for the chassis
0 commit comments