1b8265621SJacob Keller /* SPDX-License-Identifier: GPL-2.0 */ 2b8265621SJacob Keller /* Copyright (C) 2018-2019, Intel Corporation. */ 3b8265621SJacob Keller 4b8265621SJacob Keller #ifndef _PLDMFW_H_ 5b8265621SJacob Keller #define _PLDMFW_H_ 6b8265621SJacob Keller 7b8265621SJacob Keller #include <linux/list.h> 8b8265621SJacob Keller #include <linux/firmware.h> 9b8265621SJacob Keller 10b8265621SJacob Keller #define PLDM_DEVICE_UPDATE_CONTINUE_AFTER_FAIL BIT(0) 11b8265621SJacob Keller 12b8265621SJacob Keller #define PLDM_STRING_TYPE_UNKNOWN 0 13b8265621SJacob Keller #define PLDM_STRING_TYPE_ASCII 1 14b8265621SJacob Keller #define PLDM_STRING_TYPE_UTF8 2 15b8265621SJacob Keller #define PLDM_STRING_TYPE_UTF16 3 16b8265621SJacob Keller #define PLDM_STRING_TYPE_UTF16LE 4 17b8265621SJacob Keller #define PLDM_STRING_TYPE_UTF16BE 5 18b8265621SJacob Keller 19b8265621SJacob Keller struct pldmfw_record { 20b8265621SJacob Keller struct list_head entry; 21b8265621SJacob Keller 22b8265621SJacob Keller /* List of descriptor TLVs */ 23b8265621SJacob Keller struct list_head descs; 24b8265621SJacob Keller 25b8265621SJacob Keller /* Component Set version string*/ 26b8265621SJacob Keller const u8 *version_string; 27b8265621SJacob Keller u8 version_type; 28b8265621SJacob Keller u8 version_len; 29b8265621SJacob Keller 30b8265621SJacob Keller /* Package Data length */ 31b8265621SJacob Keller u16 package_data_len; 32b8265621SJacob Keller 33b8265621SJacob Keller /* Bitfield of Device Update Flags */ 34b8265621SJacob Keller u32 device_update_flags; 35b8265621SJacob Keller 36b8265621SJacob Keller /* Package Data block */ 37b8265621SJacob Keller const u8 *package_data; 38b8265621SJacob Keller 39b8265621SJacob Keller /* Bitmap of components applicable to this record */ 40b8265621SJacob Keller unsigned long *component_bitmap; 41b8265621SJacob Keller u16 component_bitmap_len; 42b8265621SJacob Keller }; 43b8265621SJacob Keller 44b8265621SJacob Keller /* Standard descriptor TLV identifiers */ 45b8265621SJacob Keller #define PLDM_DESC_ID_PCI_VENDOR_ID 0x0000 46b8265621SJacob Keller #define PLDM_DESC_ID_IANA_ENTERPRISE_ID 0x0001 47b8265621SJacob Keller #define PLDM_DESC_ID_UUID 0x0002 48b8265621SJacob Keller #define PLDM_DESC_ID_PNP_VENDOR_ID 0x0003 49b8265621SJacob Keller #define PLDM_DESC_ID_ACPI_VENDOR_ID 0x0004 50b8265621SJacob Keller #define PLDM_DESC_ID_PCI_DEVICE_ID 0x0100 51b8265621SJacob Keller #define PLDM_DESC_ID_PCI_SUBVENDOR_ID 0x0101 52b8265621SJacob Keller #define PLDM_DESC_ID_PCI_SUBDEV_ID 0x0102 53b8265621SJacob Keller #define PLDM_DESC_ID_PCI_REVISION_ID 0x0103 54b8265621SJacob Keller #define PLDM_DESC_ID_PNP_PRODUCT_ID 0x0104 55b8265621SJacob Keller #define PLDM_DESC_ID_ACPI_PRODUCT_ID 0x0105 56b8265621SJacob Keller #define PLDM_DESC_ID_VENDOR_DEFINED 0xFFFF 57b8265621SJacob Keller 58b8265621SJacob Keller struct pldmfw_desc_tlv { 59b8265621SJacob Keller struct list_head entry; 60b8265621SJacob Keller 61b8265621SJacob Keller const u8 *data; 62b8265621SJacob Keller u16 type; 63b8265621SJacob Keller u16 size; 64b8265621SJacob Keller }; 65b8265621SJacob Keller 66b8265621SJacob Keller #define PLDM_CLASSIFICATION_UNKNOWN 0x0000 67b8265621SJacob Keller #define PLDM_CLASSIFICATION_OTHER 0x0001 68b8265621SJacob Keller #define PLDM_CLASSIFICATION_DRIVER 0x0002 69b8265621SJacob Keller #define PLDM_CLASSIFICATION_CONFIG_SW 0x0003 70b8265621SJacob Keller #define PLDM_CLASSIFICATION_APP_SW 0x0004 71b8265621SJacob Keller #define PLDM_CLASSIFICATION_INSTRUMENTATION 0x0005 72b8265621SJacob Keller #define PLDM_CLASSIFICATION_BIOS 0x0006 73b8265621SJacob Keller #define PLDM_CLASSIFICATION_DIAGNOSTIC_SW 0x0007 74b8265621SJacob Keller #define PLDM_CLASSIFICATION_OS 0x0008 75b8265621SJacob Keller #define PLDM_CLASSIFICATION_MIDDLEWARE 0x0009 76b8265621SJacob Keller #define PLDM_CLASSIFICATION_FIRMWARE 0x000A 77b8265621SJacob Keller #define PLDM_CLASSIFICATION_CODE 0x000B 78b8265621SJacob Keller #define PLDM_CLASSIFICATION_SERVICE_PACK 0x000C 79b8265621SJacob Keller #define PLDM_CLASSIFICATION_SOFTWARE_BUNDLE 0x000D 80b8265621SJacob Keller 81b8265621SJacob Keller #define PLDM_ACTIVATION_METHOD_AUTO BIT(0) 82b8265621SJacob Keller #define PLDM_ACTIVATION_METHOD_SELF_CONTAINED BIT(1) 83b8265621SJacob Keller #define PLDM_ACTIVATION_METHOD_MEDIUM_SPECIFIC BIT(2) 84b8265621SJacob Keller #define PLDM_ACTIVATION_METHOD_REBOOT BIT(3) 85b8265621SJacob Keller #define PLDM_ACTIVATION_METHOD_DC_CYCLE BIT(4) 86b8265621SJacob Keller #define PLDM_ACTIVATION_METHOD_AC_CYCLE BIT(5) 87b8265621SJacob Keller 88b8265621SJacob Keller #define PLDMFW_COMPONENT_OPTION_FORCE_UPDATE BIT(0) 89b8265621SJacob Keller #define PLDMFW_COMPONENT_OPTION_USE_COMPARISON_STAMP BIT(1) 90b8265621SJacob Keller 91b8265621SJacob Keller struct pldmfw_component { 92b8265621SJacob Keller struct list_head entry; 93b8265621SJacob Keller 94b8265621SJacob Keller /* component identifier */ 95b8265621SJacob Keller u16 classification; 96b8265621SJacob Keller u16 identifier; 97b8265621SJacob Keller 98b8265621SJacob Keller u16 options; 99b8265621SJacob Keller u16 activation_method; 100b8265621SJacob Keller 101b8265621SJacob Keller u32 comparison_stamp; 102b8265621SJacob Keller 103b8265621SJacob Keller u32 component_size; 104b8265621SJacob Keller const u8 *component_data; 105b8265621SJacob Keller 106b8265621SJacob Keller /* Component version string */ 107b8265621SJacob Keller const u8 *version_string; 108b8265621SJacob Keller u8 version_type; 109b8265621SJacob Keller u8 version_len; 110b8265621SJacob Keller 111b8265621SJacob Keller /* component index */ 112b8265621SJacob Keller u8 index; 113b8265621SJacob Keller 114b8265621SJacob Keller }; 115b8265621SJacob Keller 116b8265621SJacob Keller /* Transfer flag used for sending components to the firmware */ 117b8265621SJacob Keller #define PLDM_TRANSFER_FLAG_START BIT(0) 118b8265621SJacob Keller #define PLDM_TRANSFER_FLAG_MIDDLE BIT(1) 119b8265621SJacob Keller #define PLDM_TRANSFER_FLAG_END BIT(2) 120b8265621SJacob Keller 121b8265621SJacob Keller struct pldmfw_ops; 122b8265621SJacob Keller 123b8265621SJacob Keller /* Main entry point to the PLDM firmware update engine. Device drivers 124b8265621SJacob Keller * should embed this in a private structure and use container_of to obtain 125b8265621SJacob Keller * a pointer to their own data, used to implement the device specific 126b8265621SJacob Keller * operations. 127b8265621SJacob Keller */ 128*d4679b79SKonrad Knitter 129*d4679b79SKonrad Knitter enum pldmfw_update_mode { 130*d4679b79SKonrad Knitter PLDMFW_UPDATE_MODE_FULL, 131*d4679b79SKonrad Knitter PLDMFW_UPDATE_MODE_SINGLE_COMPONENT, 132*d4679b79SKonrad Knitter }; 133*d4679b79SKonrad Knitter 134b8265621SJacob Keller struct pldmfw { 135b8265621SJacob Keller const struct pldmfw_ops *ops; 136b8265621SJacob Keller struct device *dev; 137*d4679b79SKonrad Knitter u16 component_identifier; 138*d4679b79SKonrad Knitter enum pldmfw_update_mode mode; 139b8265621SJacob Keller }; 140b8265621SJacob Keller 141b8265621SJacob Keller bool pldmfw_op_pci_match_record(struct pldmfw *context, struct pldmfw_record *record); 142b8265621SJacob Keller 143b8265621SJacob Keller /* Operations invoked by the generic PLDM firmware update engine. Used to 144b8265621SJacob Keller * implement device specific logic. 145b8265621SJacob Keller * 146b8265621SJacob Keller * @match_record: check if the device matches the given record. For 147b8265621SJacob Keller * convenience, a standard implementation is provided for PCI devices. 148b8265621SJacob Keller * 149b8265621SJacob Keller * @send_package_data: send the package data associated with the matching 150b8265621SJacob Keller * record to firmware. 151b8265621SJacob Keller * 152b8265621SJacob Keller * @send_component_table: send the component data associated with a given 153b8265621SJacob Keller * component to firmware. Called once for each applicable component. 154b8265621SJacob Keller * 155b8265621SJacob Keller * @flash_component: Flash the data for a given component to the device. 156b8265621SJacob Keller * Called once for each applicable component, after all component tables have 157b8265621SJacob Keller * been sent. 158b8265621SJacob Keller * 159b8265621SJacob Keller * @finalize_update: (optional) Finish the update. Called after all components 160b8265621SJacob Keller * have been flashed. 161b8265621SJacob Keller */ 162b8265621SJacob Keller struct pldmfw_ops { 163b8265621SJacob Keller bool (*match_record)(struct pldmfw *context, struct pldmfw_record *record); 164b8265621SJacob Keller int (*send_package_data)(struct pldmfw *context, const u8 *data, u16 length); 165b8265621SJacob Keller int (*send_component_table)(struct pldmfw *context, struct pldmfw_component *component, 166b8265621SJacob Keller u8 transfer_flag); 167b8265621SJacob Keller int (*flash_component)(struct pldmfw *context, struct pldmfw_component *component); 168b8265621SJacob Keller int (*finalize_update)(struct pldmfw *context); 169b8265621SJacob Keller }; 170b8265621SJacob Keller 171b8265621SJacob Keller int pldmfw_flash_image(struct pldmfw *context, const struct firmware *fw); 172b8265621SJacob Keller 173b8265621SJacob Keller #endif 174