tools: Extend pldm_fwup_pkg_creator
Extend the pldm_fwup_pkg_creator script to handle multiple record
descriptors in the firmware device ID record. The metadata json also
handles vendor defined descriptors.
Tested: Verified this change by using the updated json in the patch
and sample images to create a package. The fields of the package
header were verified for accuracy.
Signed-off-by: Tom Joseph <rushtotom@gmail.com>
Change-Id: I9efde5689e551170b46a4e6ee4ea1e5624173420
diff --git a/tools/fw-update/README.md b/tools/fw-update/README.md
index d231a1f..7dff704 100644
--- a/tools/fw-update/README.md
+++ b/tools/fw-update/README.md
@@ -83,17 +83,32 @@
- ComponentImageSetVersionString: Supported, must be specified in metadata
file
- RecordDescriptors:
- - Initial Descriptor: Supported, must be specified in metadata file.
- Metatdata file must have key called "InitialDescriptor", which is of
- type Object:
- - InitialDescriptorType: Supported, must be specified in metadata
- file. The supported types are 0x0000(PCI Vendor ID), 0x0001(IANA
- Enterprise ID), 0x0002 (UUID), 0x0003(PnP Vendor ID), 0x0004( ACPI
- Vendor ID)
- - InitialDescriptorLength: Supported, generated by the script
- - InitialDescriptorData: Supported, must be specified in metadata
- file as a hex string
- - Optional Additional Descriptors: Not supported at the moment
+ Metadata JSON must have a key called "Descriptors", which is of type List.
+ Each List entry corresponds to a descriptor. The first entry is considered
+ as the initial descriptor and the type shall be one of the following
+ 0x0000(PCI Vendor ID), 0x0001(IANA Enterprise ID), 0x0002(UUID),
+ 0x0003(PnP Vendor ID), 0x0004(ACPI Vendor ID). The additional
+ descriptors support initial descriptor types and additionally
+ 0x0100(PCI Device ID), 0x0101(PCI Subsystem Vendor ID),
+ 0x0102(PCI Subsystem ID), 0x0103(PCI Revision ID),
+ 0x0104(PnP Product Identifier), 0x0105(ACPI Product Identifier),
+ 0xFFFF(Vendor defined). For descriptor types other than vendor defined the
+ properties expected are DescriptorType and DescriptorData. If the descriptor
+ type is vendor defined, the properties expected are DescriptorType,
+ VendorDefinedDescriptorTitleString and VendorDefinedDescriptorData.
+ See below for details on properties:
+ - DescriptorType: Supported, must be specified in metadata file
+ - DescriptorLength: Supported, generated by the script
+ - DescriptorData: Supported, must be specified in metadata
+ file as a hex string
+ - VendorDefinedDescriptorTitleStringType: Supported - only ASCII at the
+ moment.
+ - VendorDefinedDescriptorTitleStringLength: Supported, generated by the
+ script
+ - VendorDefinedDescriptorTitleString: Supported, must be specified in
+ metadata file
+ - VendorDefinedDescriptorData: Supported, must be specified in metadata
+ file as a hex string
- FirmwareDevicePackageData: Not supported at the moment
## Downstream Device Identification Area
diff --git a/tools/fw-update/metadata-example.json b/tools/fw-update/metadata-example.json
index 70751ad..6584ed9 100644
--- a/tools/fw-update/metadata-example.json
+++ b/tools/fw-update/metadata-example.json
@@ -1,7 +1,7 @@
{
"PackageHeaderInformation": {
- "PackageHeaderIdentifier": "1244D2648D7D4718A030FC8A56587D5A",
- "PackageHeaderFormatVersion": 2,
+ "PackageHeaderIdentifier": "F018878CCB7D49439800A02F059ACA02",
+ "PackageHeaderFormatVersion": 1,
"PackageReleaseDateTime": "25/12/2021 00:00:00",
"PackageVersionString": "VersionString1"
},
@@ -15,10 +15,21 @@
100,
200
],
- "InitialDescriptor": {
- "InitialDescriptorType": 2,
- "InitialDescriptorData": "1244D2648D7D4718A030FC8A56587D5B"
- }
+ "Descriptors": [
+ {
+ "DescriptorType": 2,
+ "DescriptorData": "1244D2648D7D4718A030FC8A56587D5B"
+ },
+ {
+ "DescriptorType": 1,
+ "DescriptorData": "47160000"
+ },
+ {
+ "DescriptorType": 65535,
+ "VendorDefinedDescriptorTitleString": "OpenBMC",
+ "VendorDefinedDescriptorData": "1234"
+ }
+ ]
},
{
"DeviceUpdateOptionFlags": [
@@ -29,10 +40,12 @@
200,
300
],
- "InitialDescriptor": {
- "InitialDescriptorType": 2,
- "InitialDescriptorData": "1244D2648D7D4718A030FC8A56587D5C"
- }
+ "Descriptors": [
+ {
+ "DescriptorType": 2,
+ "DescriptorData": "1244D2648D7D4718A030FC8A56587D5C"
+ }
+ ]
},
{
"DeviceUpdateOptionFlags": [
@@ -41,10 +54,12 @@
"ApplicableComponents": [
100
],
- "InitialDescriptor": {
- "InitialDescriptorType": 2,
- "InitialDescriptorData": "1244D2648D7D4718A030FC8A56587D5D"
- }
+ "Descriptors": [
+ {
+ "DescriptorType": 2,
+ "DescriptorData": "1244D2648D7D4718A030FC8A56587D5D"
+ }
+ ]
}
],
"ComponentImageInformationArea": [
diff --git a/tools/fw-update/pldm_fwup_pkg_creator.py b/tools/fw-update/pldm_fwup_pkg_creator.py
index 1273296..5d603b8 100755
--- a/tools/fw-update/pldm_fwup_pkg_creator.py
+++ b/tools/fw-update/pldm_fwup_pkg_creator.py
@@ -22,13 +22,26 @@
("UTF16LE", 4),
("UTF16BE", 5)])
-descriptor_type_name_length = {
+initial_descriptor_type_name_length = {
0x0000: ["PCI Vendor ID", 2],
0x0001: ["IANA Enterprise ID", 4],
0x0002: ["UUID", 16],
0x0003: ["PnP Vendor ID", 3],
0x0004: ["ACPI Vendor ID", 4]}
+descriptor_type_name_length = {
+ 0x0000: ["PCI Vendor ID", 2],
+ 0x0001: ["IANA Enterprise ID", 4],
+ 0x0002: ["UUID", 16],
+ 0x0003: ["PnP Vendor ID", 3],
+ 0x0004: ["ACPI Vendor ID", 4],
+ 0x0100: ["PCI Device ID", 2],
+ 0x0101: ["PCI Subsystem Vendor ID", 2],
+ 0x0102: ["PCI Subsystem ID", 2],
+ 0x0103: ["PCI Revision ID", 1],
+ 0x0104: ["PnP Product Identifier", 4],
+ 0x0105: ["ACPI Product Identifier", 4]}
+
def check_string_length(string):
"""Check if the length of the string is not greater than 255."""
@@ -185,6 +198,74 @@
return applicable_components
+def prepare_record_descriptors(descriptors):
+ '''
+ This function processes the Descriptors and prepares the RecordDescriptors
+ section of the the firmware device ID record.
+
+ Parameters:
+ descriptors: Descriptors entry
+
+ Returns:
+ RecordDescriptors, DescriptorCount
+ '''
+ record_descriptors = bytearray()
+ vendor_defined_desc_type = 65535
+ vendor_desc_title_str_type_len = 1
+ vendor_desc_title_str_len_len = 1
+ descriptor_count = 0
+
+ for descriptor in descriptors:
+
+ descriptor_type = descriptor["DescriptorType"]
+ if descriptor_count == 0:
+ if initial_descriptor_type_name_length.get(descriptor_type) \
+ is None:
+ sys.exit("ERROR: Initial descriptor type not supported")
+ else:
+ if descriptor_type_name_length.get(descriptor_type) is None and \
+ descriptor_type != vendor_defined_desc_type:
+ sys.exit("ERROR: Descriptor type not supported")
+
+ if descriptor_type == vendor_defined_desc_type:
+ vendor_desc_title_str = \
+ descriptor["VendorDefinedDescriptorTitleString"]
+ vendor_desc_data = descriptor["VendorDefinedDescriptorData"]
+ check_string_length(vendor_desc_title_str)
+ vendor_desc_title_str_type = string_types["ASCII"]
+ descriptor_length = vendor_desc_title_str_type_len + \
+ vendor_desc_title_str_len_len + len(vendor_desc_title_str) + \
+ len(bytearray.fromhex(vendor_desc_data))
+ format_string = '<HHBB' + str(len(vendor_desc_title_str)) + 's'
+ record_descriptors.extend(struct.pack(
+ format_string,
+ descriptor_type,
+ descriptor_length,
+ vendor_desc_title_str_type,
+ len(vendor_desc_title_str),
+ vendor_desc_title_str.encode('ascii')))
+ record_descriptors.extend(bytearray.fromhex(vendor_desc_data))
+ descriptor_count += 1
+ else:
+ descriptor_type = descriptor["DescriptorType"]
+ descriptor_data = descriptor["DescriptorData"]
+ descriptor_length = len(bytearray.fromhex(descriptor_data))
+ if descriptor_length != \
+ descriptor_type_name_length.get(descriptor_type)[1]:
+ err_string = "ERROR: Descriptor type - " + \
+ descriptor_type_name_length.get(descriptor_type)[0] + \
+ " length is incorrect"
+ sys.exit(err_string)
+ format_string = '<HH'
+ record_descriptors.extend(struct.pack(
+ format_string,
+ descriptor_type,
+ descriptor_length))
+ record_descriptors.extend(bytearray.fromhex(descriptor_data))
+ descriptor_count += 1
+ return record_descriptors, descriptor_count
+
+
def write_fw_device_identification_area(pldm_fw_up_pkg, metadata,
component_bitmap_bit_length):
'''
@@ -193,7 +274,7 @@
This function writes the DeviceIDRecordCount and the
FirmwareDeviceIDRecords into the firmware update package by processing the
metadata JSON. Currently there is no support for optional
- FirmwareDevicePackageData and for Additional descriptors.
+ FirmwareDevicePackageData.
Parameters:
pldm_fw_up_pkg: PLDM FW update package
@@ -216,8 +297,7 @@
# RecordLength size
record_length = 2
- # Only initial descriptor type supported now
- descriptor_count = 1
+ # DescriptorCount
record_length += 1
# DeviceUpdateOptionFlags
@@ -257,32 +337,15 @@
round(len(applicable_components)/8)
record_length += applicable_components_bitfield_length
- initial_descriptor = device["InitialDescriptor"]
- initial_descriptor_type = initial_descriptor["InitialDescriptorType"]
- initial_descriptor_data = initial_descriptor["InitialDescriptorData"]
-
- # InitialDescriptorType
- if descriptor_type_name_length.get(initial_descriptor_type) is None:
- sys.exit("ERROR: Initial descriptor type not supported")
- record_length += 2
-
- # InitialDescriptorLength
- initial_descriptor_length = \
- len(bytearray.fromhex(initial_descriptor_data))
- if initial_descriptor_length != \
- descriptor_type_name_length.get(initial_descriptor_type)[1]:
- err_string = "ERROR: Initial descriptor type - " + \
- descriptor_type_name_length.get(initial_descriptor_type)[0] + \
- " length is incorrect"
- sys.exit(err_string)
- record_length += 2
-
- # InitialDescriptorData, the byte order in the JSON is retained.
- record_length += initial_descriptor_length
+ # RecordDescriptors
+ descriptors = device["Descriptors"]
+ record_descriptors, descriptor_count = \
+ prepare_record_descriptors(descriptors)
+ record_length += len(record_descriptors)
format_string = '<HBIBBH' + \
str(applicable_components_bitfield_length) + 's' + \
- str(len(component_image_set_version_string)) + 'sHH'
+ str(len(component_image_set_version_string)) + 's'
pldm_fw_up_pkg.write(
struct.pack(
format_string,
@@ -293,10 +356,8 @@
len(component_image_set_version_string),
fw_device_pkg_data_length,
applicable_components.tobytes(),
- component_image_set_version_string.encode('ascii'),
- initial_descriptor_type,
- initial_descriptor_length))
- pldm_fw_up_pkg.write(bytearray.fromhex(initial_descriptor_data))
+ component_image_set_version_string.encode('ascii')))
+ pldm_fw_up_pkg.write(record_descriptors)
def write_component_image_info_area(pldm_fw_up_pkg, metadata, image_files):