Changes in ipmi/test_ipmi_fru_device.robot

Added Following Test Case

	- Read Fru Device configuration
	- Verify Get FRU Inventory Area Info
	- Verify Get FRU Inventory Area Info For Invalid Device Data
	- Verify Get FRU Inventory Area Info For Invalid Data Request
	- Verify IPMI Write FRU Data
	- Verify IPMI Write FRU Data With BMC Reboot

Functions required are defined under lib/bmc_dbus.robot, lib/ipmi_client.robot and lib/utils.py

Request data for fru data present in data/ipmi_raw_cmd_table.py.

Read Fru Device configuration - Validates each ipmi fru device data with corresponding dbus data.

Verify Get FRU Inventory Area Info - Validates fru inventory byte size with ipmi read fru count returned.

Verify Get FRU Inventory Area Info For Invalid Device Data - Validates the response of inventory fru area info command with invalid device id.

Verify Get FRU Inventory Area Info For Invalid Data Request - Validates the response of inventory fru area info command with invalid request data by giving extra bytes.

Verify IPMI Write FRU Data - Verify write fru data with the response returned with read fru data after data is written.

Verify IPMI Write FRU Data With BMC Reboot -  Verify the response of read fru data after the bmc is rebooted once the data is written to the fru device.

Signed-off-by: ganesanb <ganesanb@ami.com>
Change-Id: I2ea51ad51512ecbcc4036e2d2593cafaa40a2d3c
diff --git a/data/ipmi_raw_cmd_table.py b/data/ipmi_raw_cmd_table.py
index e4395c4..b9e057c 100644
--- a/data/ipmi_raw_cmd_table.py
+++ b/data/ipmi_raw_cmd_table.py
@@ -665,4 +665,24 @@
             "0x0a 0x25"
         ]
     },
+    'FRU':
+    {
+        'Inventory_Area_Info':
+        [
+            # raw command, expected output(s), comment
+            "0x0a 0x10",
+            "Invalid data field in request",
+            "Request data length invalid"
+        ],
+        'Read':
+        [
+            # raw command
+            "0x0a 0x11",
+        ],
+        'Write':
+        [
+            # raw command
+            "0x0a 0x12",
+        ],
+    },
 }
diff --git a/ipmi/test_ipmi_fru_device.robot b/ipmi/test_ipmi_fru_device.robot
index 53347e9..5ed37b7 100644
--- a/ipmi/test_ipmi_fru_device.robot
+++ b/ipmi/test_ipmi_fru_device.robot
@@ -2,16 +2,392 @@
 Documentation  Test IPMI FRU data.
 
 Resource               ../lib/ipmi_client.robot
+Resource               ../lib/bmc_dbus.robot
+Variables              ../data/ipmi_raw_cmd_table.py
+Library                ../lib/ipmi_utils.py
 
 *** Variables ***
-
 ${FRU_NAME}       dimm01 dimm02 cpu0 cpu1  motherboard
+${BUSCTL_FRU}                xyz.openbmc_project.FruDevice
+${FRU_DBUS_URL}              /xyz/openbmc_project/FruDevice
+${fru_device_id}             0x00
+${fru_device_id_invalid}     0xff
+${read_write_offset}         0x00 0x00
+&{dbus_dict}
+&{ipmi_dbus_name_mapping}    Chassis Part Number=.CHASSIS_PART_NUMBER
+...  Board Mfg Date=.BOARD_MANUFACTURE_DATE  Board Mfg=.BOARD_MANUFACTURER
+...  Board Product=.BOARD_PRODUCT_NAME  Board Serial=.BOARD_SERIAL_NUMBER
+...  Board Part Number=.BOARD_PART_NUMBER  Product Manufacturer=.PRODUCT_MANUFACTURER
+...  Product Name=.PRODUCT_PRODUCT_NAME  Product Part Number=.PRODUCT_PART_NUMBER
+...  Product Version=.PRODUCT_VERSION  Product Serial=.PRODUCT_SERIAL_NUMBER
 
 *** Test Cases ***
-
 Test FRU Device Name
     [Documentation]  Search FRU for device name
     [Tags]  Test_FRU_Device_Name
 
     ${output}=  Run External IPMI Standard Command  fru
     Should Contain  ${output}  ${FRU_NAME}  msg=Fail: Given FRU device ${FRU_NAME} not found
+
+
+Verify Fru Device Configuration
+    [Documentation]  Read the FRU device configuration of each device
+    ...  and compare with DBUS data.
+    [Tags]  Verify_Fru_Device_Configuration
+
+    # IPMI FRU print.
+    ${ipmi_output}=  Run External IPMI Standard Command  fru
+
+    # Create dictionary with FRU device serial number as key and details as value from IPMI.
+    ${ipmi_fru}=  Get IPMI FRU Devices Data  ${ipmi_output}
+
+    # Returns all the available FRU dbus uri.
+    ${dbus_fru_uri}=  Get DBUS URI List From BMC  ${BUSCTL_FRU}  ${FRU_DBUS_URL}
+
+    # Returns all the FRU device uri with special characters removed.
+    ${dbus_fru_uri_list}=  Fetch DBUS URI List Without Unicode  ${dbus_fru_uri}
+
+    # Creates dictionary with serial number as key, and corresponding FRU device uri as value from dbus.
+    Get DBUS Dictionary For FRU Devices  ${dbus_fru_uri_list}  ${ipmi_fru}
+
+    # Compare dbus dictionary each field, with IPMI FRU device fields for each FRU device.
+    Compare IPMI FRU with DBUS  ${ipmi_fru}
+
+
+Verify Get FRU Inventory Area Info
+    [Documentation]  Verify IPMI get FRU inventory area info command.
+    [Tags]  Verify_Get_FRU_Inventory_Area_Info
+
+    # IPMI read FRU data command.
+    ${resp}=  Read FRU Data Via IPMI  ${fru_device_id}  ${read_write_offset}
+    ${bytes_read}=  Set Variable  ${resp.split()[0]}
+
+    # IPMI get FRU inventory area info command.
+    ${bytes_inventory}=  Get FRU Inventory Area Info
+
+    # Compare read FRU data Count returned -- count is ‘1’ based, with inventory area count.
+    Should Be Equal  ${bytes_inventory}  ${bytes_read}
+
+
+Verify Get FRU Inventory Area Info For Invalid Device Data
+    [Documentation]  Verify IPMI get FRU inventory area info command for Invalid Device Data.
+    [Tags]  Verify_Get_FRU_Inventory_Area_Info_For_Invalid_Device_Data
+
+    # Verify response for invalid FRU device id.
+    Run Keyword and Expect Error  *${IPMI_RAW_CMD['FRU']['Inventory_Area_Info'][1]}*
+    ...  Run IPMI Standard Command  raw ${IPMI_RAW_CMD['FRU']['Inventory_Area_Info'][0]} ${fru_device_id_invalid}
+
+
+Verify Get FRU Inventory Area Info For Invalid Data Request
+    [Documentation]  Verify IPMI get FRU inventory area info command for Invalid Data Request.
+    [Tags]  Verify_Get_FRU_Inventory_Area_Info_For_Invalid_Data_Request
+
+    # Verify response for invalid response data - extra bytes.
+    Run Keyword and Expect Error  *${IPMI_RAW_CMD['FRU']['Inventory_Area_Info'][2]}*
+    ...  Run IPMI Standard Command  raw ${IPMI_RAW_CMD['FRU']['Inventory_Area_Info'][0]} ${fru_device_id} 0x00
+
+
+Verify IPMI Write FRU Data
+    [Documentation]  Verify write data in FRU and compare data from read FRU data command via IPMI.
+    [Tags]  Verify_IPMI_Write_FRU_Data
+    [Setup]  Get Default FRU Data
+    [Teardown]  Restore Default FRU Data
+
+    # Generate random data to write in FRU device.
+    ${write_data_prefixed}  ${write_data}=  Generate Random Data For FRU
+
+    # Get the length of the data generated and convert to hex.
+    ${write_data_length}=  Get Length  ${write_data}
+    ${write_data_length}=  Convert To Hex  ${write_data_length}  lowercase=yes
+
+    # Write the data to FRU device.
+    Write FRU Data Via IPMI  ${fru_device_id}  ${read_write_offset}  ${write_data_prefixed}  ${write_data_length}
+
+    # Read the FRU data.
+    ${resp}=  Read FRU Data Via IPMI  ${fru_device_id}  ${read_write_offset}
+    ${resp_data}=  Set Variable  ${resp.split()[1:]}
+
+    # Verify if the data written and read are same.
+    Should Be Equal  ${write_data}  ${resp_data}
+
+
+Verify IPMI Write FRU Data With BMC Reboot
+    [Documentation]  Verify IPMI write data in FRU and compare data from read FRU data command after BMC reboot.
+    [Tags]  Verify_IPMI_Write_FRU_Data_With_BMC_Reboot
+    [Setup]  Get Default FRU Data
+    [Teardown]  Restore Default FRU Data
+
+    # Generate random data to write in FRU device.
+    ${write_data_prefixed}  ${write_data}=  Generate Random Data For FRU
+
+    # Get the length of the data generated and convert to hex.
+    ${write_data_length}=  Get Length  ${write_data}
+    ${write_data_length}=  Convert To Hex  ${write_data_length}  lowercase=yes
+
+    # Write the data to FRU device.
+    Write FRU Data Via IPMI  ${fru_device_id}  ${read_write_offset}  ${write_data_prefixed}  ${write_data_length}
+
+    # Read the FRU data.
+    ${resp}=  Read FRU Data Via IPMI  ${fru_device_id}  ${read_write_offset}
+    ${resp_data}=  Set Variable  ${resp.split()[1:]}
+
+    # Verify if the data written and read are same.
+    Should Be Equal  ${write_data}  ${resp_data}
+
+    # Reboot BMC and verify if the data written and read are same.
+    IPMI MC Reset Cold (run)
+    ${resp}=  Read FRU Data Via IPMI  ${fru_device_id}  ${read_write_offset}
+    Should Not Be Equal  ${resp}  ${initial_fru_data}
+    Should Be Equal  ${resp[1:]}  ${write_data}
+
+
+*** Keywords ***
+
+Get IPMI FRU Devices Data
+    [Documentation]  Get response from IPMI FRU command and format data
+    ...  with Board or Product serial as key and corresponding data as value.
+    [Arguments]  ${ipmi_output}
+
+    # Description of Argument(s):
+    # ipmi_output        All the FRU devices listed in IPMI FRU command.
+
+    # Get the FRU list and return as a dictionary with serial number as key.
+    # Example:
+    # fru_data = {
+    # "123456789012345XYZ":
+    #  {
+    #     FRU Device Description : Builtin FRU Device (ID 0),
+    #     Chassis Type          : Rack Mount Chassis,
+    #     Chassis Part Number   : xxx-xxxxx-xxxx-xxx,
+    #     Board Mfg Date        : Fri Oct 16 06:34:00 2020 UTC,
+    #     Board Mfg             : XXXXX,
+    #     Board Product         : XXXXX,
+    #     Board Serial          : 123456789012345XYZ,
+    #     Board Part Number     : xxx.xxxxx.xxxx
+    #     Board Extra           : 01
+    #     Product Manufacturer  : XXXXX
+    #     Product Name          : XXXXX
+    #     Product Part Number   : xxx-xxxx-xxxx-xxx
+    #     Product Version       : v1.0
+    #     Product Serial        : 1234567890XYZ
+    #  },....}
+
+    # Gets response from FRU data and split each device.
+    ${output}=  Set Variable  ${ipmi_output.strip("\n")}
+    ${output}=  Split String  ${output}  \n\n
+    &{fru}=  Create Dictionary
+    ${num}=  Set Variable  0
+
+    # For each device, identify either Board Serial/Product Serial (whichever is available).
+    FOR  ${devices}  IN  @{output}
+        &{tmp}=  Create Dictionary
+        ${dev}=  Split String  ${devices}  \n
+        FOR  ${device}  IN  @{dev}
+            ${ipmi_fru_board_serial_status}=  Run Keyword And Return Status  Should Contain  ${device}  Board Serial
+            Exit For Loop If  '${ipmi_fru_board_serial_status}' == 'True'
+        END
+        ${frudata}=  Get From List  ${output}  ${num}
+        ${serial_no}=  Run Keyword If  '${ipmi_fru_board_serial_status}' == 'True'
+        ...    Get Lines Containing String  ${frudata}  Board Serial
+        ...  ELSE
+        ...    Get Lines Containing String  ${frudata}  Product Serial
+
+        # Get each device and split field as key and value and append to a dictionary.
+        ${serial_nos}=  Set Variable  ${serial_no.strip()}
+        ${data}=  Split String  ${serial_nos}  :
+        ${serial_number}=  Get From List  ${data}  1
+        ${num}=  Evaluate  int(${num}) + 1
+        FOR  ${entry}  IN  @{dev}
+            ${entry}=  Split String  ${entry}  ${SPACE}:${SPACE}
+            ${entry1}=  Set Variable  ${entry[0].strip()}
+            ${entry2}=  Set Variable  ${entry[1].strip()}
+            Set To Dictionary  ${tmp}  ${entry1}  ${entry2}
+        END
+        ${serial_number}=  Set Variable  ${serial_number.strip()}
+        # Assign serial number as key for main dictionary and a each device detail as value.
+        Set To Dictionary  ${fru}  ${serial_number}  ${tmp}
+    END
+
+    [Return]  ${fru}
+
+
+Get DBUS Dictionary For FRU Devices
+    [Documentation]  Provides the dictionary of DBUS FRU devices from DBUS FRU.
+    [Arguments]  ${dbus_fru}  ${ipmi_fru}
+
+    # Description of Argument(s):
+    # dbus_fru    FRU dbus uri list.
+    # ipmi_fru    IPMI FRU details.
+
+    # Execute DBUS Introspect Command for each device,
+    # Appends dictionary with serial number as key and FRU dbus uri as value,
+    # if the IPMI FRU key matches the serial number of each device dbus response.
+    # Example :
+    #    ${dbus_output} = { "123456789012345XYZ" : "xyz.openbmc_project.FruDevice/xyz/openbmc_project/FruDevice/Device_0" }
+    FOR  ${fru}  IN  @{dbus_fru}
+        ${cmd}=  Catenate  ${BUSCTL_FRU} ${fru}
+        ${dbus_output}=  Execute DBUS Introspect Command  ${cmd}
+        ${dbus_fru_board_serial_status}=  Run Keyword And Return Status  Should Contain  ${dbus_output}  .BOARD_SERIAL
+        ${dbus_fru_product_serial_status}=  Run Keyword And Return Status  Should Contain  ${dbus_output}  .PRODUCT_SERIAL
+        Run Keyword If  '${dbus_fru_board_serial_status}' == 'True' or '${dbus_fru_product_serial_status}' == 'True'
+        ...    Create Dictionary For DBUS URI  ${dbus_output}  ${ipmi_fru}  ${dbus_fru_board_serial_status}  ${cmd}
+    END
+
+
+Create Dictionary For DBUS URI
+    [Documentation]  Create Dictionary For DBUS URI
+    [Arguments]  ${dbus_output}  ${ipmi_fru}  ${dbus_fru_board_serial_status}  ${fru_command}
+
+    # Description of Argument(s):
+    # dbus_output                             Dbus response got from BMC console.
+    # ipmi_fru                                IPMI FRU details.
+    # dbus_fru_board_serial_status            FRU devices may have either BOARD_SERIAL or PRODUCT_SERIAL
+    # ...                                     if status was true value of BOARD_SERIAL will be taken for dictionary as an key
+    # ...                                     otherwise value of PRODUCT_SERIAL will be taken as an key for dictionary.
+    # fru_command                             FRU command to map into dictionary as value.
+
+    # Validates the IPMI FRU dictionary key with dbus uri response serial number.
+    # If matches then, sets the serial number as key and FRU uri as value.
+    # ${dbus_dict} defined under variable section.
+    FOR  ${ipmi_fru_serial_no}  IN  @{ipmi_fru.keys()}
+        ${serial_no}=  Run Keyword If  '${dbus_fru_board_serial_status}' == 'True'
+        ...    Get Lines Containing String  ${dbus_output}  .BOARD_SERIAL
+        ...  ELSE
+        ...    Get Lines Containing String  ${dbus_output}  .PRODUCT_SERIAL
+        ${serial_no}=  Split String  ${serial_no}  "
+        ${dbus_serial_no}=  Set Variable  ${serial_no[1].strip()}
+        ${serial_no_status}=  Run Keyword And Return Status  Should Be Equal As Strings  ${ipmi_fru_serial_no}  ${dbus_serial_no}
+        Run Keyword If  '${serial_no_status}' == 'True'
+        ...    Run Keywords  Set To Dictionary  ${dbus_dict}  ${dbus_serial_no}  ${fru_command}  AND
+        ...    Exit For Loop
+    END
+
+
+Compare IPMI FRU with DBUS
+    [Documentation]  Compare the IPMI FRU dictionary values with DBUS dictionary values,
+    ...  if the serial number is present in both FRU and dbus dictionaries.
+    [Arguments]  ${ipmi_fru}
+
+   # Description of Argument(s):
+   # ipmi_fru    IPMI FRU device details.
+
+    # With each IPMI FRU key, get the corresponding valid from dbus dictionary,
+    # Execute the value which is dbus uri and,
+    # validate each dbus field value with IPMI FRU field value.
+    # Values are validated for keys present in the ipmi_dbus_name_mapping dictionary.
+    # Example :
+    #    IPMI FRU field :
+    #             Board Part Number     : 111.22222.0000
+    #    DBUS FRU field :
+    #            .BOARD_PART_NUMBER      property  s     "111.22222.0000"        emits-change
+    FOR  ${key}  ${ipmi_fru_value}  IN  &{ipmi_fru}
+        ${dbus_resp}=  Execute DBUS Introspect Command  ${dbus_dict}[${key}]
+        ${ipmi_fru_subkeys}=  Get Dictionary Keys  ${ipmi_fru_value}
+        FOR  ${subkeys}  IN  @{ipmi_fru_subkeys}
+            ${key_status}=  Run Keyword And Return Status  Dictionary Should Contain Key
+            ...  ${ipmi_dbus_name_mapping}  ${subkeys}
+            Continue For Loop If  '${key_status}' == 'False'
+            ${property_name}=  Get From Dictionary  ${ipmi_dbus_name_mapping}  ${subkeys}
+            ${dbus_data}=  Get Lines Containing String  ${dbus_resp}  ${property_name}
+            ${dbus_value}=  Set Variable  ${dbus_data.split('"')[1].strip()}
+            ${ipmi_response}=  Get From Dictionary  ${ipmi_fru_value}  ${subkeys}
+            ${status}=  Run Keyword And Return Status  Should Contain  ${property_name}  DATE
+            IF  ${status}
+                # If the required IPMI field has date field, the IPMI FRU value is converted to
+                # format = %Y-%m-%d - %H:%M:%S and validated against dbus FRU data.
+                ${ipmi_date}=  Convert Date  ${ipmi_response}  date_format=%a %b %d %H:%M:%S %Y
+                ...  result_format=%Y-%m-%d - %H:%M:%S
+                Run Keyword And Continue On Failure  Should Be Equal As Strings  ${ipmi_date}  ${dbus_value}
+                ...  message=${property_name} Property value mismatch with IPMI and DBUS
+            ELSE
+                Run Keyword And Continue On Failure  Should Be Equal As Strings  ${ipmi_response}  ${dbus_value}
+                ...  message=${property_name} Property value mismatch with IPMI and DBUS
+            END
+        END
+    END
+
+
+Get FRU Inventory Area Info
+    [Documentation]  IPMI Get FRU Inventory Area Info and returns FRU Inventory area size in bytes.
+
+    ${resp}=  Run IPMI Standard Command  raw ${IPMI_RAW_CMD['FRU']['Inventory_Area_Info'][0]} ${fru_device_id}
+    ${resp}=  Split String  ${resp}
+
+    [Return]  ${resp[0]}
+
+
+Read FRU Data Via IPMI
+    [Documentation]  Read FRU data using IPMI raw command.
+    [Arguments]  ${fru_id}  ${offset}
+
+   # Description of Argument(s):
+   # fru_id        FRU id.
+   # offset        Offset byte for read FRU command.
+
+    # IPMI Read FRU Data Command.
+    # 0xff - Count to read --- count is ‘1’ based
+    ${resp}=  Run IPMI Standard Command
+    ...  raw ${IPMI_RAW_CMD['FRU']['Read'][0]} ${fru_id} ${offset} 0xff
+
+    [Return]  ${resp}
+
+
+Write FRU Data Via IPMI
+    [Documentation]  Write FRU data using IPMI raw command.
+    [Arguments]  ${fru_id}  ${offset}  ${data}  ${length}
+
+   # Description of Argument(s):
+   # fru_id        FRU id.
+   # offset        Offset byte for read FRU command.
+   # data          Data to write for write FRU command.
+   # length        Count of bytes that gets written in write FRU command.
+
+    # IPMI Write FRU Data Command.
+    ${resp}=  Run IPMI Standard Command
+    ...  raw ${IPMI_RAW_CMD['FRU']['Write'][0]} ${fru_id} ${offset} ${data}
+
+    Should Be Equal As Strings  ${resp}  ${length}
+
+
+Generate Random Data For FRU
+    [Documentation]  Generate random data for write in FRU.
+
+    # Description:
+    #  Generates string of bytes and convert to hexadecimal data.
+    #  Gets the length of initial FRU data read with IPMI read FRU device command.
+
+    # ${frudata_prefixed}    string with bytes prefixed 0x by default
+    # ${fru_data}            string with only hexadecimal bytes without prefix
+
+    ${string}=  Generate Random String  ${initial_fru_length}  [LETTERS]
+    ${frudata_prefixed}  ${fru_data}=  Identify Request Data  ${string}
+
+    [Return]  ${frudata_prefixed}  ${fru_data}
+
+
+Get Default FRU Data
+    [Documentation]  Get default data via read FRU data IPMI command.
+
+    # Read the default FRU device data.
+    # split the response and identify length of Requested data.
+    ${initial_fru_data}=  Read FRU Data Via IPMI  ${fru_device_id}  ${read_write_offset}
+    ${initial_fru_list}=  Split String  ${initial_fru_data}
+    ${initial_fru_list}=  Set Variable  ${initial_fru_list[1:]}
+    ${initial_fru_length}=  Get Length  ${initial_fru_list}
+    Set Test Variable  ${initial_fru_data}
+    Set Test Variable  ${initial_fru_list}
+    Set Test Variable  ${initial_fru_length}
+
+
+Restore Default FRU Data
+    [Documentation]  Restore default FRU data.
+
+    # Prefix 0x to initial request data.
+    ${fru_list}=  Prefix Bytes  ${initial_fru_list}
+    ${fru_byte}=  Evaluate  " ".join(${fru_list})
+    ${initial_frulength_hex}=  Convert To Hex  ${initial_fru_length}  lowercase=yes
+    # Write the initial FRU data to restore.
+    Write FRU Data Via IPMI  ${fru_device_id}  ${read_write_offset}  ${fru_byte}  ${initial_frulength_hex}
+    # Verify whether initial FRU data is restored.
+    ${fru_data}=  Read FRU Data Via IPMI  ${fru_device_id}  ${read_write_offset}
+    Should Be Equal  ${fru_data}  ${initial_fru_data}
\ No newline at end of file
diff --git a/lib/bmc_dbus.robot b/lib/bmc_dbus.robot
new file mode 100644
index 0000000..160fec1
--- /dev/null
+++ b/lib/bmc_dbus.robot
@@ -0,0 +1,83 @@
+*** Settings ***
+Documentation      Implemented keywords to execute DBUS related commands on BMC.
+
+Resource           resource.robot
+Library            OperatingSystem
+Library            Collections
+
+*** Variable ***
+
+${BUSCTL_TREE_COMMAND}                   busctl tree | less
+${BUSCTL_INTROSPECT_COMMAND}             busctl introspect
+@{dbus_uri_list}
+
+*** Keywords ***
+
+Get DBUS URI List From BMC
+    [Documentation]  Get the available DBUS URIs from device tree on BMC.
+    [Arguments]  ${service_name}  ${dbus_url}
+
+    # Return the dbus uris corresponding to the service name provided.
+    # Description of argument(s):
+    #    service_name     Any service uri of the dbus.
+    #                        Eg : xyz.openbmc_project.FruDevice
+    #    dbus_url         Any dbus url of the dbus.
+    #                        Eg : /xyz/openbmc_project/FruDevice
+
+    # Execute dbus tree command
+    ${bmc_response}=  BMC Execute Command  ${BUSCTL_TREE_COMMAND}
+    ${bmc_response}=  Convert To List  ${bmc_response}
+    ${bmc_response_output}=  Get From List  ${bmc_response}  0
+    ${bmc_response_output_list}=  Split String  ${bmc_response_output}  \n\n
+    # Identify the offset of the service name in the response.
+    ${service_name_index_value}=  get_subsequent_value_from_list  ${bmc_response_output_list}  ${service_name}
+    ${service_name_index_value}=  Get From List  ${service_name_index_value}  0
+
+    # Get the service name and its corresponding URI's.
+    ${service_name_with_uri_list}=  Get From List  ${bmc_response_output_list}  ${service_name_index_value}
+    ${service_name_with_uri_list}=  Split String  ${service_name_with_uri_list}  \n
+
+    # Find index of all the uris where the dbus URI matched.
+    ${uri_list_index}=  get_subsequent_value_from_list  ${service_name_with_uri_list}  ${dbus_url}
+    FOR  ${list_index}  IN  @{uri_list_index}
+        # For each index, get the URI and append to list
+        ${dbus_uri}=  Get From List  ${service_name_with_uri_list}  ${list_index}
+        Append To List  ${dbus_uri_list}  ${dbus_uri}
+    END
+
+    [Return]  ${dbus_uri_list[1:]}
+
+
+Fetch DBUS URI List Without Unicode
+    [Documentation]  Gets the list of DBUS URI for the service and returns only sub URIs.
+    [Arguments]  ${dbus_uri_list}
+
+    # Return the dbus uris list without the unicodes.
+    # Description of argument(s):
+    #    dbus_uri_list      List of all the uris for the corresponding service name.
+    #    Example:    Converts "  ├─/xyz/openbmc_project/FruDevice/device_0",
+    #                ...  to '/xyz/openbmc_project/FruDevice/device_0'
+
+    @{dbus_list}=  Create List
+    FOR  ${item}  IN  @{dbus_uri_list}
+        ${item}=  Set Variable  ${item.strip()}
+        ${item}=  return_decoded_string  ${item}
+        Append To List  ${dbus_list}  ${item}
+    END
+
+    [Return]  ${dbus_list}
+
+
+Execute DBUS Introspect Command
+    [Documentation]  Execute the DBUS introspect command and return response.
+    [Arguments]  ${dbus_command}
+
+    # Execute the busctl instrospect command for the service name and dbus uri.
+    # Description of argument(s):
+    #   dbus_command    Command with service name and dbus uri for the fru device.
+    #      Example :    xyz.openbmc_project.FruDevice xyz/openbmc_project/FruDevice/device_0
+
+    ${cmd}=  Catenate  ${BUSCTL_INTROSPECT_COMMAND} ${dbus_command}
+    ${resp}=  BMC Execute Command  ${cmd}
+
+    [Return]  ${resp[0]}
diff --git a/lib/ipmi_client.robot b/lib/ipmi_client.robot
index 5fdd39d..cf2a24a 100755
--- a/lib/ipmi_client.robot
+++ b/lib/ipmi_client.robot
@@ -612,4 +612,35 @@
 
     ${resp}=  Run External IPMI Raw Command  ${ipmi_cmd}  fail_on_err=0
 
-    Should Contain  ${resp}  rsp=${error_code}
\ No newline at end of file
+    Should Contain  ${resp}  rsp=${error_code}
+
+
+Identify Request Data
+    [Documentation]  Convert text from variable declared to request data.
+    [Arguments]  ${string}
+
+    # Convert string to hexadecimal data for each character.
+    # Return the hex data with prefix of 0x as string and list of hex data.
+    # Description of argument(s):
+    #    string             Any string to be converted to hex.
+
+    # Given a string, convert to hexadecimal and prefix with 0x
+    ${hex1}=  Create List
+    ${hex2}=  Create List
+    ${resp_data}=  Split String With Index  ${string}  1
+    FOR  ${data}  IN  @{resp_data}
+        # prefixes 0x by default
+        ${hex_value}=  Evaluate  hex(ord("${data}"))
+        # prefixes string with bytes prefixed 0x by default
+        Append To List  ${hex1}  ${hex_value}
+        # provides only hexadecimal bytes
+        ${hex}=  Evaluate  hex(ord("${data}"))[2:]
+        # provides string with only hexadecimal bytes
+        Append To List  ${hex2}  ${hex}
+    END
+    ${hex1}=  Evaluate  " ".join(${hex1})
+
+    # ${hex1} will contains the data to write for fru in list.
+    # ${hex2} will contains the data to verify fru after write operation completed.
+
+    [Return]  ${hex1}  ${hex2}
\ No newline at end of file
diff --git a/lib/utils.py b/lib/utils.py
index 40bcf83..901c6e0 100644
--- a/lib/utils.py
+++ b/lib/utils.py
@@ -452,3 +452,22 @@
     """
 
     return data.zfill(int(num))
+
+
+def get_subsequent_value_from_list(list, value):
+    r"""
+    returns first index of the element occurrence.
+    """
+
+    index = [list.index(i) for i in list if value in i]
+    return index
+
+
+def return_decoded_string(input):
+    r"""
+    returns decoded string of encoded byte.
+    """
+
+    encoded_string = input.encode('ascii', 'ignore')
+    decoded_string = encoded_string.decode()
+    return decoded_string