#!/usr/bin/env python3 """Script to create PLDM FW update package""" import argparse import binascii import enum import json import math import os import struct import sys from datetime import datetime from bitarray import bitarray from bitarray.util import ba2int string_types = dict( [ ("Unknown", 0), ("ASCII", 1), ("UTF8", 2), ("UTF16", 3), ("UTF16LE", 4), ("UTF16BE", 5), ] ) 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], } class ComponentOptions(enum.IntEnum): """ Enum to represent ComponentOptions """ ForceUpdate = 0 UseComponentCompStamp = 1 def check_string_length(string): """Check if the length of the string is not greater than 255.""" if len(string) > 255: sys.exit("ERROR: Max permitted string length is 255") def write_pkg_release_date_time(pldm_fw_up_pkg, release_date_time): """ Write the timestamp into the package header. The timestamp is formatted as series of 13 bytes defined in DSP0240 specification. Parameters: pldm_fw_up_pkg: PLDM FW update package release_date_time: Package Release Date Time """ time = release_date_time.time() date = release_date_time.date() us_bytes = time.microsecond.to_bytes(3, byteorder="little") pldm_fw_up_pkg.write( struct.pack( " max_components: sys.exit("ERROR: only upto 32 components supported now") component_bitmap_bit_length = bitmap_multiple * math.ceil( num_components / bitmap_multiple ) pldm_fw_up_pkg.write(struct.pack(" max_device_id_record_count: sys.exit( "ERROR: there can be only upto 255 entries in the " " FirmwareDeviceIdentificationArea section" ) # DeviceIDRecordCount pldm_fw_up_pkg.write(struct.pack(" 0xFFFF: sys.exit( "ERROR: ComponentClassification should be [0x0000 - 0xFFFF]" ) # ComponentIdentifier component_identifier = component["ComponentIdentifier"] if component_identifier < 0 or component_identifier > 0xFFFF: sys.exit("ERROR: ComponentIdentifier should be [0x0000 - 0xFFFF]") # ComponentComparisonStamp component_comparison_stamp = get_component_comparison_stamp(component) # ComponentOptions component_options = bitarray(16, endian="little") component_options.setall(0) supported_component_options = [0, 1, 2] for option in component["ComponentOptions"]: if option not in supported_component_options: sys.exit( "ERROR: unsupported ComponentOption in " " ComponentImageInformationArea section" ) component_options[option] = 1 # RequestedComponentActivationMethod requested_component_activation_method = bitarray(16, endian="little") requested_component_activation_method.setall(0) supported_requested_component_activation_method = [0, 1, 2, 3, 4, 5] for option in component["RequestedComponentActivationMethod"]: if option not in supported_requested_component_activation_method: sys.exit( "ERROR: unsupported RequestedComponent " " ActivationMethod entry" ) requested_component_activation_method[option] = 1 # ComponentLocationOffset component_location_offset = 0 # ComponentSize component_size = 0 # ComponentVersionStringType component_version_string_type = string_types["ASCII"] # ComponentVersionStringlength # ComponentVersionString component_version_string = component["ComponentVersionString"] check_string_length(component_version_string) format_string = "