blob: 3c7bc7e5ec83de99aca1441f8603d5d6d24ad6cb [file] [log] [blame]
Vijay Khemkaa787bc22021-04-02 19:51:15 +00001*** Settings ***
2Documentation Test IPMI FRU data.
3
4Resource ../lib/ipmi_client.robot
ganesanbc288aff2022-05-19 19:55:47 +05305Resource ../lib/bmc_dbus.robot
6Variables ../data/ipmi_raw_cmd_table.py
7Library ../lib/ipmi_utils.py
Vijay Khemkaa787bc22021-04-02 19:51:15 +00008
Matt Fischer6fb70d92023-10-24 19:06:33 -06009Test Tags IPMI_FRU_Device
George Keishing87dc4422023-10-20 12:56:30 +053010
Vijay Khemkaa787bc22021-04-02 19:51:15 +000011*** Variables ***
George Keishing87dc4422023-10-20 12:56:30 +053012
Vijay Khemkaa787bc22021-04-02 19:51:15 +000013${FRU_NAME} dimm01 dimm02 cpu0 cpu1 motherboard
ganesanbc288aff2022-05-19 19:55:47 +053014${BUSCTL_FRU} xyz.openbmc_project.FruDevice
15${FRU_DBUS_URL} /xyz/openbmc_project/FruDevice
16${fru_device_id} 0x00
17${fru_device_id_invalid} 0xff
18${read_write_offset} 0x00 0x00
19&{dbus_dict}
20&{ipmi_dbus_name_mapping} Chassis Part Number=.CHASSIS_PART_NUMBER
21... Board Mfg Date=.BOARD_MANUFACTURE_DATE Board Mfg=.BOARD_MANUFACTURER
22... Board Product=.BOARD_PRODUCT_NAME Board Serial=.BOARD_SERIAL_NUMBER
23... Board Part Number=.BOARD_PART_NUMBER Product Manufacturer=.PRODUCT_MANUFACTURER
24... Product Name=.PRODUCT_PRODUCT_NAME Product Part Number=.PRODUCT_PART_NUMBER
25... Product Version=.PRODUCT_VERSION Product Serial=.PRODUCT_SERIAL_NUMBER
Vijay Khemkaa787bc22021-04-02 19:51:15 +000026
27*** Test Cases ***
Vijay Khemkaa787bc22021-04-02 19:51:15 +000028Test FRU Device Name
29 [Documentation] Search FRU for device name
30 [Tags] Test_FRU_Device_Name
31
ishwaryamathim372cd862023-11-14 18:12:23 +000032 ${output}= Run IPMI Standard Command fru
Vijay Khemkaa787bc22021-04-02 19:51:15 +000033 Should Contain ${output} ${FRU_NAME} msg=Fail: Given FRU device ${FRU_NAME} not found
ganesanbc288aff2022-05-19 19:55:47 +053034
35
36Verify Fru Device Configuration
37 [Documentation] Read the FRU device configuration of each device
38 ... and compare with DBUS data.
39 [Tags] Verify_Fru_Device_Configuration
40
41 # IPMI FRU print.
ishwaryamathim372cd862023-11-14 18:12:23 +000042 ${ipmi_output}= Run IPMI Standard Command fru
ganesanbc288aff2022-05-19 19:55:47 +053043
44 # Create dictionary with FRU device serial number as key and details as value from IPMI.
45 ${ipmi_fru}= Get IPMI FRU Devices Data ${ipmi_output}
46
47 # Returns all the available FRU dbus uri.
48 ${dbus_fru_uri}= Get DBUS URI List From BMC ${BUSCTL_FRU} ${FRU_DBUS_URL}
49
50 # Returns all the FRU device uri with special characters removed.
51 ${dbus_fru_uri_list}= Fetch DBUS URI List Without Unicode ${dbus_fru_uri}
52
53 # Creates dictionary with serial number as key, and corresponding FRU device uri as value from dbus.
54 Get DBUS Dictionary For FRU Devices ${dbus_fru_uri_list} ${ipmi_fru}
55
56 # Compare dbus dictionary each field, with IPMI FRU device fields for each FRU device.
57 Compare IPMI FRU with DBUS ${ipmi_fru}
58
59
60Verify Get FRU Inventory Area Info
61 [Documentation] Verify IPMI get FRU inventory area info command.
62 [Tags] Verify_Get_FRU_Inventory_Area_Info
63
64 # IPMI read FRU data command.
65 ${resp}= Read FRU Data Via IPMI ${fru_device_id} ${read_write_offset}
66 ${bytes_read}= Set Variable ${resp.split()[0]}
67
68 # IPMI get FRU inventory area info command.
69 ${bytes_inventory}= Get FRU Inventory Area Info
70
71 # Compare read FRU data Count returned -- count is ‘1’ based, with inventory area count.
72 Should Be Equal ${bytes_inventory} ${bytes_read}
73
74
75Verify Get FRU Inventory Area Info For Invalid Device Data
76 [Documentation] Verify IPMI get FRU inventory area info command for Invalid Device Data.
77 [Tags] Verify_Get_FRU_Inventory_Area_Info_For_Invalid_Device_Data
78
79 # Verify response for invalid FRU device id.
80 Run Keyword and Expect Error *${IPMI_RAW_CMD['FRU']['Inventory_Area_Info'][1]}*
ishwaryamathim372cd862023-11-14 18:12:23 +000081 ... Run IPMI Command ${IPMI_RAW_CMD['FRU']['Inventory_Area_Info'][0]} ${fru_device_id_invalid}
ganesanbc288aff2022-05-19 19:55:47 +053082
83
84Verify Get FRU Inventory Area Info For Invalid Data Request
85 [Documentation] Verify IPMI get FRU inventory area info command for Invalid Data Request.
86 [Tags] Verify_Get_FRU_Inventory_Area_Info_For_Invalid_Data_Request
87
88 # Verify response for invalid response data - extra bytes.
89 Run Keyword and Expect Error *${IPMI_RAW_CMD['FRU']['Inventory_Area_Info'][2]}*
ishwaryamathim372cd862023-11-14 18:12:23 +000090 ... Run IPMI Command ${IPMI_RAW_CMD['FRU']['Inventory_Area_Info'][0]} ${fru_device_id} 0x00
ganesanbc288aff2022-05-19 19:55:47 +053091
92
93Verify IPMI Write FRU Data
94 [Documentation] Verify write data in FRU and compare data from read FRU data command via IPMI.
95 [Tags] Verify_IPMI_Write_FRU_Data
96 [Setup] Get Default FRU Data
97 [Teardown] Restore Default FRU Data
98
99 # Generate random data to write in FRU device.
100 ${write_data_prefixed} ${write_data}= Generate Random Data For FRU
101
102 # Get the length of the data generated and convert to hex.
103 ${write_data_length}= Get Length ${write_data}
104 ${write_data_length}= Convert To Hex ${write_data_length} lowercase=yes
105
106 # Write the data to FRU device.
107 Write FRU Data Via IPMI ${fru_device_id} ${read_write_offset} ${write_data_prefixed} ${write_data_length}
108
109 # Read the FRU data.
110 ${resp}= Read FRU Data Via IPMI ${fru_device_id} ${read_write_offset}
111 ${resp_data}= Set Variable ${resp.split()[1:]}
112
113 # Verify if the data written and read are same.
114 Should Be Equal ${write_data} ${resp_data}
115
116
117Verify IPMI Write FRU Data With BMC Reboot
118 [Documentation] Verify IPMI write data in FRU and compare data from read FRU data command after BMC reboot.
119 [Tags] Verify_IPMI_Write_FRU_Data_With_BMC_Reboot
120 [Setup] Get Default FRU Data
121 [Teardown] Restore Default FRU Data
122
123 # Generate random data to write in FRU device.
124 ${write_data_prefixed} ${write_data}= Generate Random Data For FRU
125
126 # Get the length of the data generated and convert to hex.
127 ${write_data_length}= Get Length ${write_data}
128 ${write_data_length}= Convert To Hex ${write_data_length} lowercase=yes
129
130 # Write the data to FRU device.
131 Write FRU Data Via IPMI ${fru_device_id} ${read_write_offset} ${write_data_prefixed} ${write_data_length}
132
133 # Read the FRU data.
134 ${resp}= Read FRU Data Via IPMI ${fru_device_id} ${read_write_offset}
135 ${resp_data}= Set Variable ${resp.split()[1:]}
136
137 # Verify if the data written and read are same.
138 Should Be Equal ${write_data} ${resp_data}
139
140 # Reboot BMC and verify if the data written and read are same.
141 IPMI MC Reset Cold (run)
142 ${resp}= Read FRU Data Via IPMI ${fru_device_id} ${read_write_offset}
143 Should Not Be Equal ${resp} ${initial_fru_data}
144 Should Be Equal ${resp[1:]} ${write_data}
145
146
147*** Keywords ***
148
149Get IPMI FRU Devices Data
150 [Documentation] Get response from IPMI FRU command and format data
151 ... with Board or Product serial as key and corresponding data as value.
152 [Arguments] ${ipmi_output}
153
154 # Description of Argument(s):
155 # ipmi_output All the FRU devices listed in IPMI FRU command.
156
157 # Get the FRU list and return as a dictionary with serial number as key.
158 # Example:
159 # fru_data = {
160 # "123456789012345XYZ":
161 # {
162 # FRU Device Description : Builtin FRU Device (ID 0),
163 # Chassis Type : Rack Mount Chassis,
164 # Chassis Part Number : xxx-xxxxx-xxxx-xxx,
165 # Board Mfg Date : Fri Oct 16 06:34:00 2020 UTC,
166 # Board Mfg : XXXXX,
167 # Board Product : XXXXX,
168 # Board Serial : 123456789012345XYZ,
169 # Board Part Number : xxx.xxxxx.xxxx
170 # Board Extra : 01
171 # Product Manufacturer : XXXXX
172 # Product Name : XXXXX
173 # Product Part Number : xxx-xxxx-xxxx-xxx
174 # Product Version : v1.0
175 # Product Serial : 1234567890XYZ
176 # },....}
177
178 # Gets response from FRU data and split each device.
179 ${output}= Set Variable ${ipmi_output.strip("\n")}
180 ${output}= Split String ${output} \n\n
181 &{fru}= Create Dictionary
182 ${num}= Set Variable 0
183
184 # For each device, identify either Board Serial/Product Serial (whichever is available).
185 FOR ${devices} IN @{output}
186 &{tmp}= Create Dictionary
187 ${dev}= Split String ${devices} \n
188 FOR ${device} IN @{dev}
189 ${ipmi_fru_board_serial_status}= Run Keyword And Return Status Should Contain ${device} Board Serial
Sridevi Rameshb0a5a6d2025-04-30 07:14:07 -0500190 IF '${ipmi_fru_board_serial_status}' == 'True' BREAK
ganesanbc288aff2022-05-19 19:55:47 +0530191 END
192 ${frudata}= Get From List ${output} ${num}
Sridevi Rameshc6e7f932025-05-07 11:26:54 -0500193
194 ${serial_str}= Set Variable If '${ipmi_fru_board_serial_status}' == 'True'
195 ... Board Serial Product Serial
196
197 ${serial_no}= Get Lines Containing String ${frudata} ${serial_str}
ganesanbc288aff2022-05-19 19:55:47 +0530198
199 # Get each device and split field as key and value and append to a dictionary.
200 ${serial_nos}= Set Variable ${serial_no.strip()}
201 ${data}= Split String ${serial_nos} :
202 ${serial_number}= Get From List ${data} 1
203 ${num}= Evaluate int(${num}) + 1
204 FOR ${entry} IN @{dev}
205 ${entry}= Split String ${entry} ${SPACE}:${SPACE}
206 ${entry1}= Set Variable ${entry[0].strip()}
207 ${entry2}= Set Variable ${entry[1].strip()}
208 Set To Dictionary ${tmp} ${entry1} ${entry2}
209 END
210 ${serial_number}= Set Variable ${serial_number.strip()}
211 # Assign serial number as key for main dictionary and a each device detail as value.
212 Set To Dictionary ${fru} ${serial_number} ${tmp}
213 END
214
George Keishing409df052024-01-17 22:36:14 +0530215 RETURN ${fru}
ganesanbc288aff2022-05-19 19:55:47 +0530216
217
218Get DBUS Dictionary For FRU Devices
219 [Documentation] Provides the dictionary of DBUS FRU devices from DBUS FRU.
220 [Arguments] ${dbus_fru} ${ipmi_fru}
221
222 # Description of Argument(s):
223 # dbus_fru FRU dbus uri list.
224 # ipmi_fru IPMI FRU details.
225
226 # Execute DBUS Introspect Command for each device,
227 # Appends dictionary with serial number as key and FRU dbus uri as value,
228 # if the IPMI FRU key matches the serial number of each device dbus response.
229 # Example :
230 # ${dbus_output} = { "123456789012345XYZ" : "xyz.openbmc_project.FruDevice/xyz/openbmc_project/FruDevice/Device_0" }
231 FOR ${fru} IN @{dbus_fru}
232 ${cmd}= Catenate ${BUSCTL_FRU} ${fru}
233 ${dbus_output}= Execute DBUS Introspect Command ${cmd}
234 ${dbus_fru_board_serial_status}= Run Keyword And Return Status Should Contain ${dbus_output} .BOARD_SERIAL
235 ${dbus_fru_product_serial_status}= Run Keyword And Return Status Should Contain ${dbus_output} .PRODUCT_SERIAL
Sridevi Rameshc6e7f932025-05-07 11:26:54 -0500236 IF '${dbus_fru_board_serial_status}' == 'True' or '${dbus_fru_product_serial_status}' == 'True'
237 Create Dictionary For DBUS URI ${dbus_output} ${ipmi_fru} ${dbus_fru_board_serial_status} ${cmd}
238 END
ganesanbc288aff2022-05-19 19:55:47 +0530239 END
240
241
242Create Dictionary For DBUS URI
243 [Documentation] Create Dictionary For DBUS URI
244 [Arguments] ${dbus_output} ${ipmi_fru} ${dbus_fru_board_serial_status} ${fru_command}
245
246 # Description of Argument(s):
247 # dbus_output Dbus response got from BMC console.
248 # ipmi_fru IPMI FRU details.
249 # dbus_fru_board_serial_status FRU devices may have either BOARD_SERIAL or PRODUCT_SERIAL
250 # ... if status was true value of BOARD_SERIAL will be taken for dictionary as an key
251 # ... otherwise value of PRODUCT_SERIAL will be taken as an key for dictionary.
252 # fru_command FRU command to map into dictionary as value.
253
254 # Validates the IPMI FRU dictionary key with dbus uri response serial number.
255 # If matches then, sets the serial number as key and FRU uri as value.
256 # ${dbus_dict} defined under variable section.
257 FOR ${ipmi_fru_serial_no} IN @{ipmi_fru.keys()}
Sridevi Rameshc6e7f932025-05-07 11:26:54 -0500258 ${serial_str}= Set Variable If '${ipmi_fru_board_serial_status}' == 'True'
259 ... Board Serial Product Serial
260
261 ${serial_no}= Get Lines Containing String ${frudata} ${serial_str}
262
ganesanbc288aff2022-05-19 19:55:47 +0530263 ${serial_no}= Split String ${serial_no} "
264 ${dbus_serial_no}= Set Variable ${serial_no[1].strip()}
Sridevi Rameshc6e7f932025-05-07 11:26:54 -0500265 ${serial_no_status}= Run Keyword And Return Status Should Be Equal As Strings
266 ... ${ipmi_fru_serial_no} ${dbus_serial_no}
267
268 IF '${serial_no_status}' == 'True'
269 Set To Dictionary ${dbus_dict} ${dbus_serial_no} ${fru_command}
270 BREAK
271 END
ganesanbc288aff2022-05-19 19:55:47 +0530272 END
273
274
275Compare IPMI FRU with DBUS
276 [Documentation] Compare the IPMI FRU dictionary values with DBUS dictionary values,
277 ... if the serial number is present in both FRU and dbus dictionaries.
278 [Arguments] ${ipmi_fru}
279
280 # Description of Argument(s):
281 # ipmi_fru IPMI FRU device details.
282
283 # With each IPMI FRU key, get the corresponding valid from dbus dictionary,
284 # Execute the value which is dbus uri and,
285 # validate each dbus field value with IPMI FRU field value.
286 # Values are validated for keys present in the ipmi_dbus_name_mapping dictionary.
287 # Example :
288 # IPMI FRU field :
289 # Board Part Number : 111.22222.0000
290 # DBUS FRU field :
291 # .BOARD_PART_NUMBER property s "111.22222.0000" emits-change
292 FOR ${key} ${ipmi_fru_value} IN &{ipmi_fru}
293 ${dbus_resp}= Execute DBUS Introspect Command ${dbus_dict}[${key}]
294 ${ipmi_fru_subkeys}= Get Dictionary Keys ${ipmi_fru_value}
295 FOR ${subkeys} IN @{ipmi_fru_subkeys}
296 ${key_status}= Run Keyword And Return Status Dictionary Should Contain Key
297 ... ${ipmi_dbus_name_mapping} ${subkeys}
Sridevi Rameshac155722025-05-02 05:09:40 -0500298 IF '${key_status}' == 'False' CONTINUE
ganesanbc288aff2022-05-19 19:55:47 +0530299 ${property_name}= Get From Dictionary ${ipmi_dbus_name_mapping} ${subkeys}
300 ${dbus_data}= Get Lines Containing String ${dbus_resp} ${property_name}
301 ${dbus_value}= Set Variable ${dbus_data.split('"')[1].strip()}
302 ${ipmi_response}= Get From Dictionary ${ipmi_fru_value} ${subkeys}
303 ${status}= Run Keyword And Return Status Should Contain ${property_name} DATE
304 IF ${status}
305 # If the required IPMI field has date field, the IPMI FRU value is converted to
306 # format = %Y-%m-%d - %H:%M:%S and validated against dbus FRU data.
307 ${ipmi_date}= Convert Date ${ipmi_response} date_format=%a %b %d %H:%M:%S %Y
308 ... result_format=%Y-%m-%d - %H:%M:%S
309 Run Keyword And Continue On Failure Should Be Equal As Strings ${ipmi_date} ${dbus_value}
310 ... message=${property_name} Property value mismatch with IPMI and DBUS
311 ELSE
312 Run Keyword And Continue On Failure Should Be Equal As Strings ${ipmi_response} ${dbus_value}
313 ... message=${property_name} Property value mismatch with IPMI and DBUS
314 END
315 END
316 END
317
318
319Get FRU Inventory Area Info
320 [Documentation] IPMI Get FRU Inventory Area Info and returns FRU Inventory area size in bytes.
321
ishwaryamathim372cd862023-11-14 18:12:23 +0000322 ${resp}= Run IPMI Command ${IPMI_RAW_CMD['FRU']['Inventory_Area_Info'][0]} ${fru_device_id}
ganesanbc288aff2022-05-19 19:55:47 +0530323 ${resp}= Split String ${resp}
324
George Keishing409df052024-01-17 22:36:14 +0530325 RETURN ${resp[0]}
ganesanbc288aff2022-05-19 19:55:47 +0530326
327
328Read FRU Data Via IPMI
329 [Documentation] Read FRU data using IPMI raw command.
330 [Arguments] ${fru_id} ${offset}
331
Sridevi Ramesh934d3b02025-04-25 04:59:43 -0500332 # Description of Argument(s):
333 # fru_id FRU id.
334 # offset Offset byte for read FRU command.
ganesanbc288aff2022-05-19 19:55:47 +0530335
336 # IPMI Read FRU Data Command.
337 # 0xff - Count to read --- count is ‘1’ based
ishwaryamathim372cd862023-11-14 18:12:23 +0000338 ${resp}= Run IPMI Command
KManimozhi123b9071cd2024-03-14 11:20:32 +0000339 ... ${IPMI_RAW_CMD['FRU']['Read'][0]} ${fru_id} ${offset} 0xff
ganesanbc288aff2022-05-19 19:55:47 +0530340
George Keishing409df052024-01-17 22:36:14 +0530341 RETURN ${resp}
ganesanbc288aff2022-05-19 19:55:47 +0530342
343
344Write FRU Data Via IPMI
345 [Documentation] Write FRU data using IPMI raw command.
346 [Arguments] ${fru_id} ${offset} ${data} ${length}
347
Sridevi Ramesh934d3b02025-04-25 04:59:43 -0500348 # Description of Argument(s):
349 # fru_id FRU id.
350 # offset Offset byte for read FRU command.
351 # data Data to write for write FRU command.
352 # length Count of bytes that gets written in write FRU command.
ganesanbc288aff2022-05-19 19:55:47 +0530353
354 # IPMI Write FRU Data Command.
ishwaryamathim372cd862023-11-14 18:12:23 +0000355 ${resp}= Run IPMI Command
KManimozhi123b9071cd2024-03-14 11:20:32 +0000356 ... ${IPMI_RAW_CMD['FRU']['Write'][0]} ${fru_id} ${offset} ${data}
ganesanbc288aff2022-05-19 19:55:47 +0530357
358 Should Be Equal As Strings ${resp} ${length}
359
360
361Generate Random Data For FRU
362 [Documentation] Generate random data for write in FRU.
363
364 # Description:
365 # Generates string of bytes and convert to hexadecimal data.
366 # Gets the length of initial FRU data read with IPMI read FRU device command.
367
368 # ${frudata_prefixed} string with bytes prefixed 0x by default
369 # ${fru_data} string with only hexadecimal bytes without prefix
370
371 ${string}= Generate Random String ${initial_fru_length} [LETTERS]
372 ${frudata_prefixed} ${fru_data}= Identify Request Data ${string}
373
George Keishing409df052024-01-17 22:36:14 +0530374 RETURN ${frudata_prefixed} ${fru_data}
ganesanbc288aff2022-05-19 19:55:47 +0530375
376
377Get Default FRU Data
378 [Documentation] Get default data via read FRU data IPMI command.
379
380 # Read the default FRU device data.
381 # split the response and identify length of Requested data.
382 ${initial_fru_data}= Read FRU Data Via IPMI ${fru_device_id} ${read_write_offset}
383 ${initial_fru_list}= Split String ${initial_fru_data}
384 ${initial_fru_list}= Set Variable ${initial_fru_list[1:]}
385 ${initial_fru_length}= Get Length ${initial_fru_list}
386 Set Test Variable ${initial_fru_data}
387 Set Test Variable ${initial_fru_list}
388 Set Test Variable ${initial_fru_length}
389
390
391Restore Default FRU Data
392 [Documentation] Restore default FRU data.
393
394 # Prefix 0x to initial request data.
395 ${fru_list}= Prefix Bytes ${initial_fru_list}
396 ${fru_byte}= Evaluate " ".join(${fru_list})
397 ${initial_frulength_hex}= Convert To Hex ${initial_fru_length} lowercase=yes
398 # Write the initial FRU data to restore.
399 Write FRU Data Via IPMI ${fru_device_id} ${read_write_offset} ${fru_byte} ${initial_frulength_hex}
400 # Verify whether initial FRU data is restored.
401 ${fru_data}= Read FRU Data Via IPMI ${fru_device_id} ${read_write_offset}
George Keishing87dc4422023-10-20 12:56:30 +0530402 Should Be Equal ${fru_data} ${initial_fru_data}