blob: dee75953d7ec91039110ff6cda4c98c3f092793b [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
George Keishing87dc4422023-10-20 12:56:30 +05309Force Tags IPMI_FRU_Device
10
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
32 ${output}= Run External IPMI Standard Command fru
33 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.
42 ${ipmi_output}= Run External IPMI Standard Command fru
43
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]}*
81 ... Run IPMI Standard Command raw ${IPMI_RAW_CMD['FRU']['Inventory_Area_Info'][0]} ${fru_device_id_invalid}
82
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]}*
90 ... Run IPMI Standard Command raw ${IPMI_RAW_CMD['FRU']['Inventory_Area_Info'][0]} ${fru_device_id} 0x00
91
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
190 Exit For Loop If '${ipmi_fru_board_serial_status}' == 'True'
191 END
192 ${frudata}= Get From List ${output} ${num}
193 ${serial_no}= Run Keyword If '${ipmi_fru_board_serial_status}' == 'True'
194 ... Get Lines Containing String ${frudata} Board Serial
195 ... ELSE
196 ... Get Lines Containing String ${frudata} Product Serial
197
198 # Get each device and split field as key and value and append to a dictionary.
199 ${serial_nos}= Set Variable ${serial_no.strip()}
200 ${data}= Split String ${serial_nos} :
201 ${serial_number}= Get From List ${data} 1
202 ${num}= Evaluate int(${num}) + 1
203 FOR ${entry} IN @{dev}
204 ${entry}= Split String ${entry} ${SPACE}:${SPACE}
205 ${entry1}= Set Variable ${entry[0].strip()}
206 ${entry2}= Set Variable ${entry[1].strip()}
207 Set To Dictionary ${tmp} ${entry1} ${entry2}
208 END
209 ${serial_number}= Set Variable ${serial_number.strip()}
210 # Assign serial number as key for main dictionary and a each device detail as value.
211 Set To Dictionary ${fru} ${serial_number} ${tmp}
212 END
213
214 [Return] ${fru}
215
216
217Get DBUS Dictionary For FRU Devices
218 [Documentation] Provides the dictionary of DBUS FRU devices from DBUS FRU.
219 [Arguments] ${dbus_fru} ${ipmi_fru}
220
221 # Description of Argument(s):
222 # dbus_fru FRU dbus uri list.
223 # ipmi_fru IPMI FRU details.
224
225 # Execute DBUS Introspect Command for each device,
226 # Appends dictionary with serial number as key and FRU dbus uri as value,
227 # if the IPMI FRU key matches the serial number of each device dbus response.
228 # Example :
229 # ${dbus_output} = { "123456789012345XYZ" : "xyz.openbmc_project.FruDevice/xyz/openbmc_project/FruDevice/Device_0" }
230 FOR ${fru} IN @{dbus_fru}
231 ${cmd}= Catenate ${BUSCTL_FRU} ${fru}
232 ${dbus_output}= Execute DBUS Introspect Command ${cmd}
233 ${dbus_fru_board_serial_status}= Run Keyword And Return Status Should Contain ${dbus_output} .BOARD_SERIAL
234 ${dbus_fru_product_serial_status}= Run Keyword And Return Status Should Contain ${dbus_output} .PRODUCT_SERIAL
235 Run Keyword If '${dbus_fru_board_serial_status}' == 'True' or '${dbus_fru_product_serial_status}' == 'True'
236 ... Create Dictionary For DBUS URI ${dbus_output} ${ipmi_fru} ${dbus_fru_board_serial_status} ${cmd}
237 END
238
239
240Create Dictionary For DBUS URI
241 [Documentation] Create Dictionary For DBUS URI
242 [Arguments] ${dbus_output} ${ipmi_fru} ${dbus_fru_board_serial_status} ${fru_command}
243
244 # Description of Argument(s):
245 # dbus_output Dbus response got from BMC console.
246 # ipmi_fru IPMI FRU details.
247 # dbus_fru_board_serial_status FRU devices may have either BOARD_SERIAL or PRODUCT_SERIAL
248 # ... if status was true value of BOARD_SERIAL will be taken for dictionary as an key
249 # ... otherwise value of PRODUCT_SERIAL will be taken as an key for dictionary.
250 # fru_command FRU command to map into dictionary as value.
251
252 # Validates the IPMI FRU dictionary key with dbus uri response serial number.
253 # If matches then, sets the serial number as key and FRU uri as value.
254 # ${dbus_dict} defined under variable section.
255 FOR ${ipmi_fru_serial_no} IN @{ipmi_fru.keys()}
256 ${serial_no}= Run Keyword If '${dbus_fru_board_serial_status}' == 'True'
257 ... Get Lines Containing String ${dbus_output} .BOARD_SERIAL
258 ... ELSE
259 ... Get Lines Containing String ${dbus_output} .PRODUCT_SERIAL
260 ${serial_no}= Split String ${serial_no} "
261 ${dbus_serial_no}= Set Variable ${serial_no[1].strip()}
262 ${serial_no_status}= Run Keyword And Return Status Should Be Equal As Strings ${ipmi_fru_serial_no} ${dbus_serial_no}
263 Run Keyword If '${serial_no_status}' == 'True'
264 ... Run Keywords Set To Dictionary ${dbus_dict} ${dbus_serial_no} ${fru_command} AND
265 ... Exit For Loop
266 END
267
268
269Compare IPMI FRU with DBUS
270 [Documentation] Compare the IPMI FRU dictionary values with DBUS dictionary values,
271 ... if the serial number is present in both FRU and dbus dictionaries.
272 [Arguments] ${ipmi_fru}
273
274 # Description of Argument(s):
275 # ipmi_fru IPMI FRU device details.
276
277 # With each IPMI FRU key, get the corresponding valid from dbus dictionary,
278 # Execute the value which is dbus uri and,
279 # validate each dbus field value with IPMI FRU field value.
280 # Values are validated for keys present in the ipmi_dbus_name_mapping dictionary.
281 # Example :
282 # IPMI FRU field :
283 # Board Part Number : 111.22222.0000
284 # DBUS FRU field :
285 # .BOARD_PART_NUMBER property s "111.22222.0000" emits-change
286 FOR ${key} ${ipmi_fru_value} IN &{ipmi_fru}
287 ${dbus_resp}= Execute DBUS Introspect Command ${dbus_dict}[${key}]
288 ${ipmi_fru_subkeys}= Get Dictionary Keys ${ipmi_fru_value}
289 FOR ${subkeys} IN @{ipmi_fru_subkeys}
290 ${key_status}= Run Keyword And Return Status Dictionary Should Contain Key
291 ... ${ipmi_dbus_name_mapping} ${subkeys}
292 Continue For Loop If '${key_status}' == 'False'
293 ${property_name}= Get From Dictionary ${ipmi_dbus_name_mapping} ${subkeys}
294 ${dbus_data}= Get Lines Containing String ${dbus_resp} ${property_name}
295 ${dbus_value}= Set Variable ${dbus_data.split('"')[1].strip()}
296 ${ipmi_response}= Get From Dictionary ${ipmi_fru_value} ${subkeys}
297 ${status}= Run Keyword And Return Status Should Contain ${property_name} DATE
298 IF ${status}
299 # If the required IPMI field has date field, the IPMI FRU value is converted to
300 # format = %Y-%m-%d - %H:%M:%S and validated against dbus FRU data.
301 ${ipmi_date}= Convert Date ${ipmi_response} date_format=%a %b %d %H:%M:%S %Y
302 ... result_format=%Y-%m-%d - %H:%M:%S
303 Run Keyword And Continue On Failure Should Be Equal As Strings ${ipmi_date} ${dbus_value}
304 ... message=${property_name} Property value mismatch with IPMI and DBUS
305 ELSE
306 Run Keyword And Continue On Failure Should Be Equal As Strings ${ipmi_response} ${dbus_value}
307 ... message=${property_name} Property value mismatch with IPMI and DBUS
308 END
309 END
310 END
311
312
313Get FRU Inventory Area Info
314 [Documentation] IPMI Get FRU Inventory Area Info and returns FRU Inventory area size in bytes.
315
316 ${resp}= Run IPMI Standard Command raw ${IPMI_RAW_CMD['FRU']['Inventory_Area_Info'][0]} ${fru_device_id}
317 ${resp}= Split String ${resp}
318
319 [Return] ${resp[0]}
320
321
322Read FRU Data Via IPMI
323 [Documentation] Read FRU data using IPMI raw command.
324 [Arguments] ${fru_id} ${offset}
325
326 # Description of Argument(s):
327 # fru_id FRU id.
328 # offset Offset byte for read FRU command.
329
330 # IPMI Read FRU Data Command.
331 # 0xff - Count to read --- count is ‘1’ based
332 ${resp}= Run IPMI Standard Command
333 ... raw ${IPMI_RAW_CMD['FRU']['Read'][0]} ${fru_id} ${offset} 0xff
334
335 [Return] ${resp}
336
337
338Write FRU Data Via IPMI
339 [Documentation] Write FRU data using IPMI raw command.
340 [Arguments] ${fru_id} ${offset} ${data} ${length}
341
342 # Description of Argument(s):
343 # fru_id FRU id.
344 # offset Offset byte for read FRU command.
345 # data Data to write for write FRU command.
346 # length Count of bytes that gets written in write FRU command.
347
348 # IPMI Write FRU Data Command.
349 ${resp}= Run IPMI Standard Command
350 ... raw ${IPMI_RAW_CMD['FRU']['Write'][0]} ${fru_id} ${offset} ${data}
351
352 Should Be Equal As Strings ${resp} ${length}
353
354
355Generate Random Data For FRU
356 [Documentation] Generate random data for write in FRU.
357
358 # Description:
359 # Generates string of bytes and convert to hexadecimal data.
360 # Gets the length of initial FRU data read with IPMI read FRU device command.
361
362 # ${frudata_prefixed} string with bytes prefixed 0x by default
363 # ${fru_data} string with only hexadecimal bytes without prefix
364
365 ${string}= Generate Random String ${initial_fru_length} [LETTERS]
366 ${frudata_prefixed} ${fru_data}= Identify Request Data ${string}
367
368 [Return] ${frudata_prefixed} ${fru_data}
369
370
371Get Default FRU Data
372 [Documentation] Get default data via read FRU data IPMI command.
373
374 # Read the default FRU device data.
375 # split the response and identify length of Requested data.
376 ${initial_fru_data}= Read FRU Data Via IPMI ${fru_device_id} ${read_write_offset}
377 ${initial_fru_list}= Split String ${initial_fru_data}
378 ${initial_fru_list}= Set Variable ${initial_fru_list[1:]}
379 ${initial_fru_length}= Get Length ${initial_fru_list}
380 Set Test Variable ${initial_fru_data}
381 Set Test Variable ${initial_fru_list}
382 Set Test Variable ${initial_fru_length}
383
384
385Restore Default FRU Data
386 [Documentation] Restore default FRU data.
387
388 # Prefix 0x to initial request data.
389 ${fru_list}= Prefix Bytes ${initial_fru_list}
390 ${fru_byte}= Evaluate " ".join(${fru_list})
391 ${initial_frulength_hex}= Convert To Hex ${initial_fru_length} lowercase=yes
392 # Write the initial FRU data to restore.
393 Write FRU Data Via IPMI ${fru_device_id} ${read_write_offset} ${fru_byte} ${initial_frulength_hex}
394 # Verify whether initial FRU data is restored.
395 ${fru_data}= Read FRU Data Via IPMI ${fru_device_id} ${read_write_offset}
George Keishing87dc4422023-10-20 12:56:30 +0530396 Should Be Equal ${fru_data} ${initial_fru_data}