Skip to content

Commit fbccffa

Browse files
committed
Add function to validate and regenerate ONIE EEPROM cahce file if needed
(cherry picked from commit 6576a40)
1 parent 72bf0c6 commit fbccffa

File tree

1 file changed

+79
-1
lines changed

1 file changed

+79
-1
lines changed

chassis/sonic_platform/eeprom.py

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
#
77
#############################################################################
88
import os
9+
import struct
10+
import binascii
911

1012
from sonic_py_common.logger import Logger
1113
from platform_ndk import nokia_common
@@ -17,6 +19,11 @@
1719

1820
logger = 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

Comments
 (0)