Drive Backplane Development Guide
更新时间: 2025/12/04
在Gitcode上查看源码

This document describes how to adapt a drive backplane on openUBMC.

Drive Backplane Introduction

The server drive backplane is a hardware device that is usually installed in the server chassis. It is used to install and connect drives. Its design and functions are as follows:
Drive installation: The server drive backplane provides interfaces and slots for installing drives. By tightening the screws on the drive backplane, the drive can be securely installed in the server chassis and connected to the interfaces on the backplane.
Data transmission: Interfaces on the server drive backplane usually use standards such as Serial ATA (SATA), Serial Attached SCSI (SAS), and Non-Volatile Memory Express (NVMe). These interfaces are used to transmit data and signals, connecting drives with the server mainboard or RAID controller. Through the drive backplane, drives can transmit data and communicate with other hardware devices.
Power supply: The server drive backplane usually provides power interfaces for drives to supply power. These interfaces ensure that drives have the power supply required for normal operation and connect to the power source on the server mainboard.
Heat dissipation and securing: The server drive backplane also dissipates heat and secures drives. It is designed for the heat dissipation requirements of drives, providing effective heat dissipation and temperature control through heat dissipation structures and ventilation holes. Meanwhile, securing devices on the drive backplane ensure that drives remain stable and secure during operation.
In summary, the server drive backplane is a hardware device used to install and connect drives. It provides interfaces, transmits data, supplies power, dissipates heat, and secures drives. Through the drive backplane, server drives can operate normally and communicate and interact with other hardware devices.

Drive Backplane Adaptation Process

Like other components, every drive backplane has a component self-description record (CSR) file. The CSR file tells openUBMC how to identify the drive backplane, manage backplane information, monitor backplane status, and manage drive information.

CSR Information to Include When Adapting a New Drive Backplane

  • Fixed information such as the UID, name, type, vendor, slot number, start slot for drives, and silkscreen of the drive backplane
  • Drive types and quantity supported by the drive backplane
  • Status of the drive backplane to be monitored, such as the backplane temperature, drive temperature, and drive status
  • Required sensors for the drive backplane and how to obtain their readings
  • Alarms or events to be reported and alarm conditions, such as temperature, drive hot-swap events, drive localization failure, array alarms, drive pre-failure, foreign drive status, drive write-through, drive rebuild start, drive rebuild end, drive failure, and drive replacement records
  • Sources for obtaining drive status and alarm information
  • Whether the drive backplane requires a separate cooling policy

Drive Backplane Identification

  • Configure the self-description record (SR) file name using the format Bom + Id + AuxId. In the SR of the upstream component (such as the carrier board) connected to the drive backplane, configure the connector for the drive backplane, and then load the drive backplane SR file based on the presence signal feedback from the hardware.
  • You are advised to prioritize 3 for the IdentifyMode mode of SR loading. If the drive backplane does not meet the identification protocol of Tianchi, you can configure it as 1 or 2 and set a fixed ID.
json
{
    "Connector_SEU_1": {
      "Bom": "14100665",
      "Slot": 1,
      "Position": 2,
      "Presence": "<=/Scanner_SEU_1.Value",  // Presence signal scanning information. 0 indicates presence and 1 indicates absence. If it is fixed as present, no detection is required. Set the parameter to 1.
      "Buses": [
        "I2c_2",
        "I2c_5",
        "JtagOverLocalBus_1"
      ],
      "SystemId": "${SystemId}",
      "ManagerId": "${ManagerId}",
      "ChassisId": "${ChassisId}",
      "SilkText": "SEU",
      "IdentifyMode": 3,  // Downstream component identification mode. 3 corresponds to Tianchi standard components, 2 corresponds to components with unreadable (reported) BoardId, and 1 corresponds to components with readable BoardId.
      "Container": "Component_ComExpander",
      "Type": "DiskBackplane"
    },
    "Scanner_SEU_1": {
      "Chip": "#/Smc_ExpBoardSMC",
      "Offset": 134234368,  // SMC command word
      "Size": 2,  // Number of data bytes
      "Mask": 1,  // Data mask
      "Type": 0,
      "Period": 2000,  // Scanning period, in milliseconds
      "Value": 0
    }
}

Management Topology Objects

  • Configure all bus information for the drive backplane.
  • Configure all channel information.
  • Configure all chip information.
json
{
    "ManagementTopology": {
        "Anchor": {
        "Buses": ["I2c_2",
            "I2c_5",
            "JtagOverLocalBus_1"]
        },
        "I2c_5": {
            "Chips": ["Smc_EnclSMC",
            "Eeprom_SEU"],
            "Connectors": ["Connector_SEU_Inner_1",
            "Connector_SEU_Inner_2"]
        },
        "I2c_2": {
            "Chips": ["Smc_ExpBoardSMC"]
        },
        "JtagOverLocalBus_1": {
            "Chips": ["Cpld_1"]
        }
    }
}

Component Objects

  • Configure FruId for the drive backplane and drives.
  • Configure the types of the drive backplane and drives.
  • Configure location information for the drive backplane and drives.
  • Configure serial number (SN) sources for the drive backplane and drives.
json
{
    "Component_HddBackplane": {
        "FruId": "<=/Fru_SEU.FruId",  // The default value is 255 if there is no FRU. Otherwise, FruId of the FRU object is referenced.
        "Instance": "${Slot}",
        "Type": 5,  // Component type, corresponding to COMPONENT_TYPE* in the code
        "Location": "<=/HddBackplane_1.Position",  // Location information
        "Name": "<=/HddBackplane_1.DeviceName",  // Name
        "Presence": 1,  // Presence information
        "Health": 0,  // Health status
        "PowerState": 1,  // Power status
        "GroupId": 1,  // Group ID
        "UniqueId": "00000001030302023934",  // Unique ID
        "ReplaceFlag": 0,  // Replacement flag
        "PreviousSN": "",  // Previous SN
        "SerialNumber": "<=/HddBackplane_1.SerialNumber",  // SN
        "NodeId": "<=/HddBackplane_1.Position;<=/HddBackplane_1.DeviceName |> string.format('%s%s',$1,$2)",  // Node ID
        "BoardId": "<=/HddBackplane_1.BoardID"  // Board ID
    },
    "Component_Drive0": {  // A corresponding Component object must be configured for each drive.
        "FruId": 255,
        "Instance": 255,
        "Type": 2,
        "Name": "Disk0",
        "Presence": 1,
        "Health": 0,
        "PowerState": 1,
        "NodeId": "Disk0",
        "ReplaceFlag": 0,
        "PreviousSN": "",
        "SerialNumber": "<=/Drive_1.SerialNumber"
        },
    "Component_Cable": {  // Drive backplanes usually include cable detection. Configure the corresponding Component object.
        "FruId": 255,
        "Instance": 255,
        "Type": 40,
        "Name": "cable",
        "Presence": 1,
        "Health": 0,
        "PowerState": 1,
        "GroupId": 1
    }
}

Entity Objects

If sensors need to be configured, an Entity object must be configured for each hardware component, including the drive backplane and drives.

json
{
    "Entity_HddCard": {
    "Id": 11,
    "Name": "HddCard${Slot}",
    "PowerState": "<=/Scanner_PowerGood.Value",
    "Presence": 1,
    "Instance": 112
    },
    "Entity_Disk0": {
    "Id": 4,
    "Instance": 96,
    "Name": "Disk0",
    "PowerState": 1,
    "Presence": 1
    }
}

Drive Objects

Define basic information and attributes for drives:

  • Name
  • ID
  • Location
  • Location indicator scanning information
  • Fault scanning information
  • Type
json
{
    "Drive_1": {
        "Id": 0,  // Drive ID, which is the primary key of the drive object, must be unique. Calculation method: HddBackplaneStartSlot + RelativeSlot.
        "Name": "Disk0",  // Drive name
        "PhysicalLocation": "HDD Plane",  // Location information
        "NodeId": "HDDPlaneDisk0",  // Unique ID of the resource
        "Presence": "<=/Scanner_Drive0PresentAccessor.Status;<=/Scanner_Drive0PresentAccessor.Value |> expr($1 != 0 ? 255 : $2)",  // Drive presence state. 0 indicates absence, 1 indicates presence, and 255 indicates an invalid value.
        "LocateLed": "<=/Scanner_Drive0LocateAccessor.Value",  // Localization indicator status: 0 for off, 1 for blinking, and 2 for steady on
        "FaultLed": "<=/Scanner_Drive0FalutAccessor.Value",  // Drive fault indicator status: 0 for off, 1 for steady on, and 2 for blinking
        "ActivationLed": "<=/Scanner_Drive0ActivationAccessor.Value",  // Drive activity indicator status: 0 for off and 1 for on
        "SetLocateLed": "#/Accessor_Drive0LocateAccessor.Value",  // Sets the drive location indicator: 0 for off and 1 for on (blinking)
        "SetFaultLed": "#/Accessor_Drive0FaultAccessor.Value",  // Sets the drive fault indicator: 0 for off and 1 for on (steady on)
        "TemperatureCelsius": 255,  // Drive temperature in Celsius degrees (255 is invalid)
        "Missing": 0,  // Missing status of the drive
        "Health": "<=/Component_Drive0.Health",  // Drive health status: 0 for OK, 1 for Minor, 2 for Major, and 3 for Critical
        "RebuildState": 0,  // Specified drive data rebuild state
        "FirmwareStatus": 255,  // Drive firmware status from BMA or RAID (255 is invalid)
        "PredictiveFailure": 0,  // Pre-failure detection from RAID: 0 for normal and 1 for failure
        "InAFailedArray": 0,  // Whether the drive belongs to a failed array from RAID: 0 for no and 1 for yes
        "FirmwareStatusError": false,  // Associated drive FaultLed state: true for faulty and false for normal
        "PredictedMediaLifeLeftPercent": 255,  // Static wear rate of the drive
        "SerialNumber": "",  // Drive SN from BMA, RAID, or VPD
        "Type": "SATA/SAS",  // Silkscreen type, used by the PcieAddressInfo object
        "IODeteriorationHealthCode": 0,  // Drive I/O performance health code
        "HddBackplaneStartSlot": "<=/HddBackplane_1.StartSlot",  // Start slot number of the drive backplane
        "RelativeSlot": 0  // Relative offset from the start slot of the backplane, usually the same as ID
    }
}

Alarm and Event Configuration

For configuration, refer to Sensor Customization and Development. The following example focuses solely on the drive backplane and related sensors.

  • Set temperature monitoring thresholds for alarms or cooling.

Threshold Sensor Objects (ThresholdSensor)

  • Six thresholds
  • Alarm deassertion hysteresis
  • Reading data source
  • Reasonable M and RBExp values to keep calculated sensor readings within the valid one-byte range
json
{
    "ThresholdSensor_HddBpTemp": {
        "OwnerId": 32,
        "OwnerLun": 0,
        "EntityId": "<=/Entity_HddCard.Id",
        "EntityInstance": "<=/Entity_HddCard.Instance",
        "Initialization": 127,
        "Capabilities": 232,  // Sensor activation conditions
        "SensorType": 1,  // Sensor type. For details, see chapter 42 in the IPMI Specification.
        "ReadingType": 1,
        "SensorName": "Disk BP${Slot} Temp",
        "Unit": 128,
        "BaseUnit": 1,
        "ModifierUnit": 0,
        "Analog": 1,
        "NominalReading": 25,
        "NormalMaximum": 0,
        "NormalMinimum": 0,
        "MaximumReading": 127,
        "MinimumReading": 128,
        "Reading": "<=/Scanner_HddBPTemp.TemperatureCelsius",
        "ReadingStatus": "<=/Scanner_HddBPTemp.Status",
        "AssertMask": 128,  // Alarm capability mask. For details, see Assertion Event Mask in the IPMI Specification.
        "DeassertMask": 28800,  // For details, see Deassertion Event Mask in the IPMI Specification.
        "ReadingMask": 2056,
        "Linearization": 0,
        "M": 100,
        "RBExp": 224,
        "UpperNoncritical": 105,
        "PositiveHysteresis": 2,
        "NegativeHysteresis": 2
    }
}

Discrete Sensor Objects (DiscreteSensor)

json
{
    "DiscreteSensor_Disk0": {
        "EntityId": "<=/Entity_Disk0.Id",
        "EntityInstance": "<=/Entity_Disk0.Instance",
        "Initialization": 99,
        "Capabilities": 192,
        "SensorType": 13,
        "ReadingType": 111,
        "SensorName": "DISK0",
        "AssertMask": 199,
        "DeassertMask": 199,
        "DiscreteMask": 199,
        "DiscreteType": 0,
        "Unit": 192,
        "BaseUnit": 0,
        "ModifierUnit": 0,
        "RecordSharing": 1,
        "Reading": 0
    },
    "DiscreteEvent_Disk0Presence": {  // Add DiscreteEvent as required. Refer to other drive backplane SR files.
        "Property": "<=/Drive_1.Presence",
        "ListenType": 1,
        "EventData1": 0,
        "EventData2": 255,
        "EventData3": 255,
        "EventDir": "<=/Drive_1.Presence",
        "Conversion": 0,
        "InvalidReadingIgnore": 1,
        "InvalidReading": 255,
        "SensorObject": "#/DiscreteSensor_Disk0"
    },
    "Scanner_Drive0PresentAccessor": {
        "Chip": "#/Smc_EnclSMC",
        "Offset": 335545601,
        "Size": 2,
        "Mask": 1,
        "Type": 0,
        "Period": 2000,
        "Debounce": "None",
        "Value": 255
    },
    "Event_Disk0Missing": {  // Add Event as required. Refer to other drive backplane SR files.
        "EventKeyId": "Disk.DiskMissing",
        "Reading": "<=/Drive_1.Missing",
        "Condition": 2,
        "OperatorId": 5,
        "Enabled": true,
        "DescArg2": "Disk0",
        "Component": "#/Component_Drive0",
        "ComponentHealth": "#/Component_Drive0.Health"
    },
    "Event_SEU3_UBNotPresent": {  // Add the cable detection event as required. Refer to other drive backplane SR files.
        "EventKeyId": "Cable.UBNotPresent",  // Event ID, which is the unique alarm ID
        "InvalidReadingIgnore": 1,  // Whether to ignore invalid values. 1: enabled; 0: disabled. If 1 is set, readings that equal to InvalidReading are ignored.
        "InvalidReading": 255,  // Invalid value to be ignored
        "Reading": "<=/Scanner_SEU_Inner_1.Value;<=/Scanner_Inner_1_CablePresent.Value;<=/Scanner_Inner_2_CablePresent.Value |> expr($1 == 1 ? (($2 == 0 && $3 == 0) ? 1 : 0) : 0)",  // Compares Reading and Condition based on the OperatorId rule. If the result is true, an alarm is triggered. The precision is up to four decimal places.
        "@Default": {  // Default value
            "Reading": 0
        },
        "ComponentId": 40,
        "Condition": 1,
        "OperatorId": 5,  // Operators: 1 (<), 2 (<=), 3 (>), 4 (>=), 5 (=), 6 (!=), 7 (rising edge, asserted on 0 to 1 and deasserted on 1 to 0), 8 (falling edge, asserted on 1 to 0 and deasserted on 0 to 1)
        "Enabled": true,  // Whether the alarm is enabled
        "DescArg1": "#/Accessor_Id_1.Value |> expr($1 == 51 ? 1030302023930 : 1030302023928) |> string.format('%020d(SEUSlot3)',$1)",  // Event description/suggestion parameters used to format parameters. The value can contain up to 10 strings.
        "AdditionalInfo": "1",  // Additional information, used to distinguish alarm objects during reporting to upper-layer NMS
        "Component": "#/Component_Cable",  // Associated Component object
        "ComponentHealth": "#/Component_Cable.Health"
    }
}

Heat Dissipation Control Objects

  • Target temperature
  • Maximum allowed temperature
json
{
    "CoolingConfig_Basic": {  // CoolingConfig is usually not configured in the board configuration file.
        "SmartCoolingState": "Enabled",  // Whether smart cooling is enabled. The value can be Enabled or Disabled
        "SmartCoolingMode": "EnergySaving",  // Smart cooling mode. The value can be EnergySaving, HighPerformance, LowNoise, Custom, or LiquidCooling.
        "LevelPercentRange": [20, 100],  // Smart cooling speed range (20 to 100 in the example)
        "InitLevelInStartup": 100,  // Default speed level at startup. The value range is LevelPercentRange.
        "DiskRowTemperatureAvailable": false,  // Whether the drive temperature is available
        "SysHDDsMaxTemperature": 80.0,  // Max temperature threshold for HDDs
        "SysSSDsMaxTemperature": 80.0,  // Max temperature threshold for SSDs
        "SensorLocationSupported": false  // Whether the temperature ocean interface is supported
    },
    "CoolingPolicy_EnergySaving": {
        "PolicyIdx": 6,  // ID for the linear cooling policy, which must be globally unique
        "ExpCondVal": "EnergySaving",  // Expected condition. CoolingPolicy takes effect only when the actual condition matches the expected condition. The value can be EnergySaving, HighPerformance, LowNoise, Custom, or LiquidCooling.
        "ActualCondVal": "<=/CoolingConfig_1.SmartCoolingMode",  // Actual condition. The value can be EnergySaving, HighPerformance, LowNoise, Custom, or LiquidCooling.
        "TemperatureRangeLow": [-127, 20, 30, 40, 50],  // Lower thresholds for temperature intervals in the linear cooling policy
        "TemperatureRangeHigh": [20, 30, 40, 50, 127],  // Upper thresholds for temperature intervals in the linear cooling policy
        "SpeedRangeLow": [20, 32, 70, 100],  // Lower thresholds for speed intervals in the linear cooling policy
        "SpeedRangeHigh": [20, 32, 70, 100],  // Upper thresholds for speed intervals in the linear cooling policy
        "FanType": ["02314BLG 8038+"]  // List of fan types. The fan condition is met if any fan type in this list exists.
    },
    "CoolingRequirement_1_7": {
        "RequirementId": 7,  // Target cooling policy ID. The ID must be globally unique. Currently, the ID supports 16 valid bits, where the first 8 bits are the base ID and the last 8 bits are the slot ID.
        "TemperatureType": 11,  // Type of the target cooling temperature point. The value can be 1 for Cpu, 2 for Outlet, 3 for Disk, 4 for Memory, 5 for PCH, 6 for VRD, 7 for VDDQ, 8 for NPUHbm, 9 for NPUAiCore, 10 for NPUBoard, 11 for Inlet, 12 for SoCBoardOutlet, or 13 for SoCBoardInlet,.
        "MonitoringStatus": "<=/Scanner_Lm75_Inlet.Status",  // Temperature sensor status: 0 for normal and 1 for abnormal
        "MonitoringValue": "<=/Scanner_Lm75_Inlet.Value;<=/Scanner_Lm75_Inlet.Value |> expr((($1 + 5) > ($2 - 10)) ? ($1 + 5) : ($2 - 10))",  // Temperature value involved in cooling
        "FailedValue": 80,  // Fan speed when the temperature status is abnormal. If this field is not set, abnormal cooling is not triggered. If it is set, the set fan speed is issued during abnormal cooling when the temperature point fails to be read.
        "TargetTemperatureCelsius": 50,  // Current cooling target value
        "MaxAllowedTemperatureCelsius": 60,
        "TargetTemperatureRangeCelsius": [  // Allowed range for the custom target temperature, which is used for validity check of custom target values
            40,
            60
        ],
        "SmartCoolingTargetTemperature": [  // Target temperature values for EnergySaving, HighPerformance, and LowNoise modes. This field is optional.
            50,
            47,
            53
        ],
        "CustomSupported": true,  // Whether custom target values are supported. The value can be true or false.
        "CustomTargetTemperatureCelsius": 50,  // Custom temperature. The value 255 is invalid.
        "SensorName": "#/ThresholdSensor_InletTemp.SensorName"  // Sensor name
    },
    "CoolingArea_1_25": {
        "AreaId": 25,
        "RequirementIdx": 25,
        "PolicyIdxGroup": [],
        "FanIdxGroup": [
            1,
            2,
            3,
            4
        ]
    }
}

FRU Objects

json
{
    "Eeprom_NetCard": {
        "OffsetWidth": 2,
        "AddrWidth": 1,
        "Address": 172,
        "WriteTmout": 100,
        "ReadTmout": 100,
        "RwBlockSize": 32,
        "WriteInterval": 20,
        "HealthStatus": 0
    },
    "Fru_SEU": {
        "PcbId": "#/Accessor_PcbID.Value",
        "FruId": 1,
        "FruName": "DiskBP${Slot}",
        "PowerState": 1,
        "Health": 0,
        "EepStatus": 1,
        "Type": 5,
        "FruDataId": "#/FruData_SEU"
    },
    "FruData_SEU": {
      "FruId": 1,
      "FruDev": "#/Eeprom_SEU",
      "EepromWp": "#/Accessor_WP.Value",
      "StorageType": "TianChi"  // Common electronic label formats include TianChi, EepromV2, File, MCU, and Power.
    }
}

CPLD Upgrade Management Objects

json
{
    "LogicFirmware_SEU_1": {
        "UId": "00000001030302023934",  // Unique identifier for the CPLD component, consisting of the vendor (00000001) + board type (03) + board code (0302023934)
        "Name": "SEU_CPLD",  // Name of the CPLD component
        "Manufacturer": "Huawei",  // Firmware vendor
        "Version": "#/Accessor_LogicVerId.Value",  // Firmware version, which is used to distinguish different CPLD versions
        "Location": 3,  // Position number of the component where the firmware is located. U is added before the number for BMC display.
        "UpgradeChip": "#/Cpld_1",  // Chip to be upgraded via the JTAG link
        "ChipInfo": "#/Cpld_1",  // CPLD vendor and bypass enablement
        "Routes": "#/Accessor_JtagSwitch.Value",  // JTAG route value. The route function and information for the CPLD component upgrade is usually provided by the carrier board CPLD.
        "DefaultRoute": 0,  // Default route value. The route function and information for the CPLD component upgrade is usually provided by the carrier board CPLD. This field points to the carrier board by default.
        "FirmwareRoute": 2,  // Corresponds to SMC associated with Routes. During the upgrade, the corresponding value is set to switch to the corresponding link. The value 0 indicates that the link does not need to be switched.
        "SoftwareId": "CPLD-BC83HBBH"  // CPLD code information. The format is "firmware_type-board_name".
    },
    "Accessor_JtagSwitch": {
        "Chip": "#/Smc_ExpBoardSMC",
        "Offset": 469776896,
        "Size": 1,
        "Mask": 255,
        "Type": 0,
        "Value": 0
    }
}

PcieAddrInfo Object

json
    "PcieAddrInfo_SAS_1": {  // PcieAddrInfo object for drives used to match drive information reported by iBMA
      "Location": "HddBackplane${Slot}",  // PCIe slot location
      "ComponentType": 71,  // Component type, corresponding to COMPONENT_TYPE in the code
      "ContainerSlot": "${Slot}",
      "ContainerUID": "00000001030302023934",  // Container UID
      "ContainerUnitType": "SEU SAS",  // Container board type
      "GroupPosition": "PcieAddrInfo_1_${GroupPosition}",
      "ControllerType": 2,  // PCIe controller type: 0 for PCIeCore, 1 for NIC, 2 for SAS, 3 for SATA, 4 for ZIP, and 5 for SEC
      "Segment": 0,  // Segment index for multi-PCI bridge scenarios. Each segment corresponds to a PCI bus space.
      "GroupID": 0,  // Logical group ID
      "SlotID": 1,  // PCIe device slot number
      "SocketID": 0,  // CPU ID: 0 for CPU 1 and 1 for CPU 2
      "Bus": 0,  // Root port bus number
      "Device": 125,  // Root port device number
      "Function": 0  // Root port function number
    }

Drive Management

Drive loading workflow

Non-pass-through drives: Drive is an abstract drive object configured in the CSR of the drive backplane. Each slot corresponds to a Drive object.
Pass-through drives with special protocols: The Drive object handles common attributes of drives to be added to the tree and obtains the attributes from the protocol.
Standard pass-through drives: The Drive object handles common attributes of the drives to be added to the tree. The attributes have only default values and can be obtained from iBMA.

Non-pass-through drives are typically managed by RAID controllers. Their Drive objects are configured in the SR of the backplane. In storage, they are represented as PD classes not directly exposed externally The PD chain creation workflow is as follows:

Loading pass-through drives with special protocols differs from non-pass-through drives Separate SR files are loaded based on presence and type information:

json
{
    "Connector_ComVPDConnect_1": {
        "Bom": "14140224",
        "Slot": 0,
        "Position": 1,
        "Presence": "<=/Scanner_Drive0PresentAccessor.Value;<=/Scanner_Drive1PCIeType.Value|> expr(($1 == 1) && ($2 == 1))",
        "Id": "VPD",
        "AuxId": "0",
        "Buses": ["I2cMux_SMC_1"],
        "SystemId": "${SystemId}",
        "ManagerId": "${ManagerId}",
        "ChassisId": "${ChassisId}",
        "SilkText": "J11",
        "IdentifyMode": 2,
        "Type": "NVMe"
    }
}

NVMe objects create chains with Drive objects through slots, bypassing the non-pass-through workflow. Attributes from the protocol are updated to the Drive object, which adds them to the tree.
Pass-through drives with special protocols require corresponding VPD information. The code identifies the protocol type and loads the appropriate PROTOCOL SR and cooling files.

json
{
    "VirtualVPDConnect": {
        "Slot": "${Slot}",
        "RefVPDChip": "#/Chip_Virtual_SSD",
        "RefConnector": "#/Connector_ComVPD",
        "RefPolicyConnector": "#/Connector_Policy"
        },
    "Chip_Virtual_SSD": {
        "Address": 166,
        "AddrWidth": 1,
        "OffsetWidth": 1,
        "WriteTmout": 100,
        "ReadTmout": 100,
        "HealthStatus": 0
        },
    "Connector_ComVPD": {
        "Bom": "14140224",
        "Slot": "${Slot}",
        "Position": 1,
        "Presence": 0,
        "Id": "PROTOCOL",
        "AuxId": "255",
        "Buses": ["I2cMux_SMC"],
        "SystemId": "${SystemId}",
        "ManagerId": "${ManagerId}",
        "ChassisId": "${ChassisId}",
        "SilkText": "",
        "IdentifyMode": 2,
        "Type": "NVMe"
        },
    "Connector_Policy": {
        "Bom": "14140224",
        "Slot": "${Slot}",
        "Position": 2,
        "Presence": 0,
        "Id": "POLICY",
        "AuxId": "255",
        "Buses": ["I2cMux_SMC"],
        "SystemId": "${SystemId}",
        "ManagerId": "${ManagerId}",
        "ChassisId": "${ChassisId}",
        "SilkText": "",
        "IdentifyMode": 2,
        "Type": "NVMe"
    }
}

Common Issues

  1. SAS/SATA drive information cannot be obtained.
    Description: SAS/SATA drive information is mostly obtained from RAID controllers or iBMA and cannot be directly accessed. If no RAID controller is present, iBMA must be adapted:
    ->During device adaptation, configure the PcieAddrInfo object for SAS/SATA drives in the SR file. Key parameters include Bus, Device, Function, PortID, SlotID, SocketID, ComponentType, ControllerType, and Segment of the PcieAddrInfo_SAS object.
    ->Once iBMA starts, it reports drive information to the BMC.
    ->The BMC matches the reported information based on data like BDF and updates it in the Drive object.

  1. NVMe drive information is missing or incomplete.
    Description: NVMe drive information is mainly retrieved from drive firmware via protocols:
    ->New NVMe drive models may require adaptation for NVMe-MI or SSD-Format protocols.
    ->The protocol version of the drive firmware might be incompatible with the BMC.
    ->Data written in the drive firmware does not meet expectations (common with minor vendors with incomplete protocol understanding).
    ->Data written in the drive firmware is incomplete.
    ->Some attributes, such as drive capacity, are only available in standard protocols like NVMe-MI, whereas the drive may use SSD-Format.
    ->Some vendors add OEM attributes that require BMC code adaptation.

  1. The NVMe drive protocol cannot be identified.
    Description: The protocol of an NVMe drive is parsed based on the VPD data. If the VPD has no data, the data does not comply with the protocol specifications, or the VPD cannot be accessed, the protocol cannot be identified.

Non-pass-through drives cannot be associated with the corresponding RAID controller.
Description: Identification of non-pass-through drives requires indicator-based localization operations. Failure in these operations prevents association.
->Check if the Drive information configuration under the drive backplane meets expectations.
->Check if drive presence and localization information meet expectations.
->Check if the high-speed cable connection between the RAID controller and the drive backplane meets expectations.
->Check if the RAID controller works properly.
->Check if the RAID controller supports out-of-band management.
->Check if the indicator-based localization capability of the CPLD is normal. You can cross-verify the capability by performing in-band indicator-based localization.