diff mbox series

[V6,17/21] core/pldm: Update "bmc-firmware-version" device-tree field

Message ID 20220913102705.65506-18-clombard@linux.vnet.ibm.com
State Superseded
Headers show
Series Implement MCTP and PLDM features | expand

Commit Message

Christophe Lombard Sept. 13, 2022, 10:27 a.m. UTC
Use the GetFruRecordByOptionReq command to retrieve the bmc information
with: "FRU Field Type": Version
      "FRU Record Set Identifier": 1,
      "FRU Record Type": "General(1)"
and update the "bmc-firmware-version" device-tree field.

Signed-off-by: Christophe Lombard <clombard@linux.vnet.ibm.com>
---
 core/pldm/pldm-fru-requests.c | 60 +++++++++++++++++++++++++++++++++++
 core/pldm/pldm.h              |  1 +
 include/pldm.h                |  5 +++
 3 files changed, 66 insertions(+)

Comments

Abhishek Singh Tomar Sept. 29, 2022, 5:12 p.m. UTC | #1
On Tue, Sep 13, 2022 at 12:27:01PM +0200, Christophe Lombard wrote:
> Use the GetFruRecordByOptionReq command to retrieve the bmc information
> with: "FRU Field Type": Version
>       "FRU Record Set Identifier": 1,
>       "FRU Record Type": "General(1)"
> and update the "bmc-firmware-version" device-tree field.
> 
> Signed-off-by: Christophe Lombard <clombard@linux.vnet.ibm.com>
Reviewed-by: Abhishek Singh Tomar <abhishek@linux.ibm.com>
> ---
>  core/pldm/pldm-fru-requests.c | 60 +++++++++++++++++++++++++++++++++++
>  core/pldm/pldm.h              |  1 +
>  include/pldm.h                |  5 +++
>  3 files changed, 66 insertions(+)
> 
> diff --git a/core/pldm/pldm-fru-requests.c b/core/pldm/pldm-fru-requests.c
> index 02c9b968..b07a7b1a 100644
> --- a/core/pldm/pldm-fru-requests.c
> +++ b/core/pldm/pldm-fru-requests.c
> @@ -15,6 +15,7 @@ static void *fru_record_table;
>  static size_t fru_record_length;
> 
>  static bool fru_ready;
> +static char *bmc_version = NULL;
> 
>  static void fru_init_complete(bool success)
>  {
> @@ -33,6 +34,16 @@ static void fru_init_complete(bool success)
>  	fru_ready = true;
>  }
> 
> +int pldm_fru_get_bmc_version(void *bv)
> +{
> +	if (bmc_version == NULL)
> +		return OPAL_HARDWARE;
> +
> +	memcpy(bv, bmc_version, strlen(bmc_version) + 1);
> +
> +	return OPAL_SUCCESS;
> +}
> +
>  static int get_fru_record_table_req(void **record_table_data,
>  				    size_t *record_table_length)
>  {
> @@ -115,6 +126,55 @@ static int get_fru_record_table_req(void **record_table_data,
>  	return OPAL_SUCCESS;
>  }
> 
> +int pldm_fru_dt_add_bmc_version(void)
> +{
> +	struct pldm_fru_record_data_format *data;
> +	struct pldm_fru_record_tlv *tlv;
> +	struct dt_node *dt_fw_version;
> +	uint8_t *record_table;
> +	size_t record_size;
> +
> +	dt_fw_version = dt_find_by_name(dt_root, "ibm,firmware-versions");
> +	if (!dt_fw_version)
> +		return OPAL_SUCCESS;
> +
> +	/* retrieve the bmc information with
> +	 * "FRU Record Set Identifier": 1,
> +	 * "FRU Record Type": "General(1)"
> +	 * "FRU Field Type": Version
> +	 *
> +	 * we can not know size of the record table got by options
> +	 * in advance, but it must be less than the source table. So
> +	 * it's safe to use sizeof the source table.
> +	 */
> +	record_table = zalloc(fru_record_length);
> +	record_size = fru_record_length;
> +	get_fru_record_by_option(
> +			fru_record_table,
> +			fru_record_length - PLDM_GET_FRU_RECORD_TABLE_MIN_RESP_BYTES,
> +			record_table,
> +			&record_size,
> +			1,
> +			PLDM_FRU_RECORD_TYPE_GENERAL,
> +			PLDM_FRU_FIELD_TYPE_VERSION);
> +
> +	/* get tlv value */
> +	data = (struct pldm_fru_record_data_format *)record_table;
> +	tlv = (struct pldm_fru_record_tlv *)data->tlvs;
> +	prlog(PR_DEBUG, "%s - value: %s\n", __func__, tlv->value);
> +
> +	dt_add_property_string(dt_fw_version, "bmc-firmware-version",
> +			       tlv->value);
> +
> +	/* store the bmc version */
> +	bmc_version = zalloc(tlv->length + 1);
> +	memcpy(bmc_version, tlv->value, tlv->length);
> +
> +	free(record_table);
> +
> +	return OPAL_SUCCESS;
> +}
> +
>  int pldm_fru_init(void)
>  {
>  	int rc;
> diff --git a/core/pldm/pldm.h b/core/pldm/pldm.h
> index f9e9db40..5ee53cb9 100644
> --- a/core/pldm/pldm.h
> +++ b/core/pldm/pldm.h
> @@ -47,6 +47,7 @@ int pldm_responder_handle_request(struct pldm_rx_data *rx);
>  int pldm_responder_init(void);
> 
>  /* Requester support */
> +int pldm_fru_get_bmc_version(void *bv);
>  int pldm_fru_init(void);
> 
>  int pldm_bios_find_lid_by_attr_name(const char *name, char **lid);
> diff --git a/include/pldm.h b/include/pldm.h
> index 3e653aa3..693c1ae5 100644
> --- a/include/pldm.h
> +++ b/include/pldm.h
> @@ -25,4 +25,9 @@ int pldm_platform_power_off(void);
>   */
>  int pldm_platform_restart(void);
> 
> +/**
> + * Update the firmware version device-tree field
> + */
> +int pldm_fru_dt_add_bmc_version(void);
> +
>  #endif /* __PLDM_H__ */
> -- 
> 2.37.3
> 
> _______________________________________________
> Skiboot mailing list
> Skiboot@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/skiboot
Frederic Barrat April 12, 2023, 3:41 p.m. UTC | #2
On 13/09/2022 12:27, Christophe Lombard wrote:
> Use the GetFruRecordByOptionReq command to retrieve the bmc information
> with: "FRU Field Type": Version
>        "FRU Record Set Identifier": 1,
>        "FRU Record Type": "General(1)"
> and update the "bmc-firmware-version" device-tree field.
> 
> Signed-off-by: Christophe Lombard <clombard@linux.vnet.ibm.com>
> ---
>   core/pldm/pldm-fru-requests.c | 60 +++++++++++++++++++++++++++++++++++
>   core/pldm/pldm.h              |  1 +
>   include/pldm.h                |  5 +++
>   3 files changed, 66 insertions(+)
> 
> diff --git a/core/pldm/pldm-fru-requests.c b/core/pldm/pldm-fru-requests.c
> index 02c9b968..b07a7b1a 100644
> --- a/core/pldm/pldm-fru-requests.c
> +++ b/core/pldm/pldm-fru-requests.c
> @@ -15,6 +15,7 @@ static void *fru_record_table;
>   static size_t fru_record_length;
>   
>   static bool fru_ready;
> +static char *bmc_version = NULL;
>   
>   static void fru_init_complete(bool success)
>   {
> @@ -33,6 +34,16 @@ static void fru_init_complete(bool success)
>   	fru_ready = true;
>   }
>   
> +int pldm_fru_get_bmc_version(void *bv)


That's a dangerous API as we don't know what has been allocated and 
we're going to write over it an unknown size. Should at the minimum take 
an extra parameter specifying the buffer size.


> +{
> +	if (bmc_version == NULL)
> +		return OPAL_HARDWARE;
> +
> +	memcpy(bv, bmc_version, strlen(bmc_version) + 1); > +
> +	return OPAL_SUCCESS;
> +}
> +
>   static int get_fru_record_table_req(void **record_table_data,
>   				    size_t *record_table_length)
>   {
> @@ -115,6 +126,55 @@ static int get_fru_record_table_req(void **record_table_data,
>   	return OPAL_SUCCESS;
>   }
>   
> +int pldm_fru_dt_add_bmc_version(void)
> +{
> +	struct pldm_fru_record_data_format *data;
> +	struct pldm_fru_record_tlv *tlv;
> +	struct dt_node *dt_fw_version;
> +	uint8_t *record_table;
> +	size_t record_size;
> +
> +	dt_fw_version = dt_find_by_name(dt_root, "ibm,firmware-versions");
> +	if (!dt_fw_version)
> +		return OPAL_SUCCESS;
> +
> +	/* retrieve the bmc information with
> +	 * "FRU Record Set Identifier": 1,
> +	 * "FRU Record Type": "General(1)"
> +	 * "FRU Field Type": Version
> +	 *
> +	 * we can not know size of the record table got by options
> +	 * in advance, but it must be less than the source table. So
> +	 * it's safe to use sizeof the source table.
> +	 */
> +	record_table = zalloc(fru_record_length);


We need to verify that the init went fine and 
fru_record_table/fru_record_length are defined. It's a general pattern 
in all those functions with static data. It's the only time I've seen 
where you don't verify it first, but it's probably worth double-checking 
all of them.


> +	record_size = fru_record_length;
> +	get_fru_record_by_option(
> +			fru_record_table,
> +			fru_record_length - PLDM_GET_FRU_RECORD_TABLE_MIN_RESP_BYTES,


PLDM_GET_FRU_RECORD_TABLE_MIN_RESP_BYTES was already deducted in 
decode_get_fru_record_table_resp(), so fru_record_length should be the 
correct length. At least, that's what I understand :)


> +			record_table,
> +			&record_size,
> +			1,
> +			PLDM_FRU_RECORD_TYPE_GENERAL,
> +			PLDM_FRU_FIELD_TYPE_VERSION);
> +
> +	/* get tlv value */


We need to check 'record_size' and make sure we have (at least) one 
entry in the record table.

   Fred
Christophe Lombard April 13, 2023, 3:57 p.m. UTC | #3
Le 12/04/2023 à 17:41, Frederic Barrat a écrit :
>
>
> On 13/09/2022 12:27, Christophe Lombard wrote:
>> Use the GetFruRecordByOptionReq command to retrieve the bmc information
>> with: "FRU Field Type": Version
>>        "FRU Record Set Identifier": 1,
>>        "FRU Record Type": "General(1)"
>> and update the "bmc-firmware-version" device-tree field.
>>
>> Signed-off-by: Christophe Lombard <clombard@linux.vnet.ibm.com>
>> ---
>>   core/pldm/pldm-fru-requests.c | 60 +++++++++++++++++++++++++++++++++++
>>   core/pldm/pldm.h              |  1 +
>>   include/pldm.h                |  5 +++
>>   3 files changed, 66 insertions(+)
>>
>> diff --git a/core/pldm/pldm-fru-requests.c 
>> b/core/pldm/pldm-fru-requests.c
>> index 02c9b968..b07a7b1a 100644
>> --- a/core/pldm/pldm-fru-requests.c
>> +++ b/core/pldm/pldm-fru-requests.c
>> @@ -15,6 +15,7 @@ static void *fru_record_table;
>>   static size_t fru_record_length;
>>     static bool fru_ready;
>> +static char *bmc_version = NULL;
>>     static void fru_init_complete(bool success)
>>   {
>> @@ -33,6 +34,16 @@ static void fru_init_complete(bool success)
>>       fru_ready = true;
>>   }
>>   +int pldm_fru_get_bmc_version(void *bv)
>
>
> That's a dangerous API as we don't know what has been allocated and 
> we're going to write over it an unknown size. Should at the minimum 
> take an extra parameter specifying the buffer size.
>

You are right. We have to new parameters to control the memcpy 
operation. Thanks

>
>> +{
>> +    if (bmc_version == NULL)
>> +        return OPAL_HARDWARE;
>> +
>> +    memcpy(bv, bmc_version, strlen(bmc_version) + 1); > +
>> +    return OPAL_SUCCESS;
>> +}
>> +
>>   static int get_fru_record_table_req(void **record_table_data,
>>                       size_t *record_table_length)
>>   {
>> @@ -115,6 +126,55 @@ static int get_fru_record_table_req(void 
>> **record_table_data,
>>       return OPAL_SUCCESS;
>>   }
>>   +int pldm_fru_dt_add_bmc_version(void)
>> +{
>> +    struct pldm_fru_record_data_format *data;
>> +    struct pldm_fru_record_tlv *tlv;
>> +    struct dt_node *dt_fw_version;
>> +    uint8_t *record_table;
>> +    size_t record_size;
>> +
>> +    dt_fw_version = dt_find_by_name(dt_root, "ibm,firmware-versions");
>> +    if (!dt_fw_version)
>> +        return OPAL_SUCCESS;
>> +
>> +    /* retrieve the bmc information with
>> +     * "FRU Record Set Identifier": 1,
>> +     * "FRU Record Type": "General(1)"
>> +     * "FRU Field Type": Version
>> +     *
>> +     * we can not know size of the record table got by options
>> +     * in advance, but it must be less than the source table. So
>> +     * it's safe to use sizeof the source table.
>> +     */
>> +    record_table = zalloc(fru_record_length);
>
>
> We need to verify that the init went fine and 
> fru_record_table/fru_record_length are defined. It's a general pattern 
> in all those functions with static data. It's the only time I've seen 
> where you don't verify it first, but it's probably worth 
> double-checking all of them.
>
>

That's true. We need to check that we got successfully the pldm fru data 
using fru_ready. thanks

>> +    record_size = fru_record_length;
>> +    get_fru_record_by_option(
>> +            fru_record_table,
>> +            fru_record_length - 
>> PLDM_GET_FRU_RECORD_TABLE_MIN_RESP_BYTES,
>
>
> PLDM_GET_FRU_RECORD_TABLE_MIN_RESP_BYTES was already deducted in 
> decode_get_fru_record_table_resp(), so fru_record_length should be the 
> correct length. At least, that's what I understand :)
>

Really, I don't remember. You should certainly right, but I need to 
dobble check it. Thanks

>
>> +            record_table,
>> +            &record_size,
>> +            1,
>> +            PLDM_FRU_RECORD_TYPE_GENERAL,
>> +            PLDM_FRU_FIELD_TYPE_VERSION);
>> +
>> +    /* get tlv value */
>
>
> We need to check 'record_size' and make sure we have (at least) one 
> entry in the record table.
>

will do. thanks

> Fred
diff mbox series

Patch

diff --git a/core/pldm/pldm-fru-requests.c b/core/pldm/pldm-fru-requests.c
index 02c9b968..b07a7b1a 100644
--- a/core/pldm/pldm-fru-requests.c
+++ b/core/pldm/pldm-fru-requests.c
@@ -15,6 +15,7 @@  static void *fru_record_table;
 static size_t fru_record_length;
 
 static bool fru_ready;
+static char *bmc_version = NULL;
 
 static void fru_init_complete(bool success)
 {
@@ -33,6 +34,16 @@  static void fru_init_complete(bool success)
 	fru_ready = true;
 }
 
+int pldm_fru_get_bmc_version(void *bv)
+{
+	if (bmc_version == NULL)
+		return OPAL_HARDWARE;
+
+	memcpy(bv, bmc_version, strlen(bmc_version) + 1);
+
+	return OPAL_SUCCESS;
+}
+
 static int get_fru_record_table_req(void **record_table_data,
 				    size_t *record_table_length)
 {
@@ -115,6 +126,55 @@  static int get_fru_record_table_req(void **record_table_data,
 	return OPAL_SUCCESS;
 }
 
+int pldm_fru_dt_add_bmc_version(void)
+{
+	struct pldm_fru_record_data_format *data;
+	struct pldm_fru_record_tlv *tlv;
+	struct dt_node *dt_fw_version;
+	uint8_t *record_table;
+	size_t record_size;
+
+	dt_fw_version = dt_find_by_name(dt_root, "ibm,firmware-versions");
+	if (!dt_fw_version)
+		return OPAL_SUCCESS;
+
+	/* retrieve the bmc information with
+	 * "FRU Record Set Identifier": 1,
+	 * "FRU Record Type": "General(1)"
+	 * "FRU Field Type": Version
+	 *
+	 * we can not know size of the record table got by options
+	 * in advance, but it must be less than the source table. So
+	 * it's safe to use sizeof the source table.
+	 */
+	record_table = zalloc(fru_record_length);
+	record_size = fru_record_length;
+	get_fru_record_by_option(
+			fru_record_table,
+			fru_record_length - PLDM_GET_FRU_RECORD_TABLE_MIN_RESP_BYTES,
+			record_table,
+			&record_size,
+			1,
+			PLDM_FRU_RECORD_TYPE_GENERAL,
+			PLDM_FRU_FIELD_TYPE_VERSION);
+
+	/* get tlv value */
+	data = (struct pldm_fru_record_data_format *)record_table;
+	tlv = (struct pldm_fru_record_tlv *)data->tlvs;
+	prlog(PR_DEBUG, "%s - value: %s\n", __func__, tlv->value);
+
+	dt_add_property_string(dt_fw_version, "bmc-firmware-version",
+			       tlv->value);
+
+	/* store the bmc version */
+	bmc_version = zalloc(tlv->length + 1);
+	memcpy(bmc_version, tlv->value, tlv->length);
+
+	free(record_table);
+
+	return OPAL_SUCCESS;
+}
+
 int pldm_fru_init(void)
 {
 	int rc;
diff --git a/core/pldm/pldm.h b/core/pldm/pldm.h
index f9e9db40..5ee53cb9 100644
--- a/core/pldm/pldm.h
+++ b/core/pldm/pldm.h
@@ -47,6 +47,7 @@  int pldm_responder_handle_request(struct pldm_rx_data *rx);
 int pldm_responder_init(void);
 
 /* Requester support */
+int pldm_fru_get_bmc_version(void *bv);
 int pldm_fru_init(void);
 
 int pldm_bios_find_lid_by_attr_name(const char *name, char **lid);
diff --git a/include/pldm.h b/include/pldm.h
index 3e653aa3..693c1ae5 100644
--- a/include/pldm.h
+++ b/include/pldm.h
@@ -25,4 +25,9 @@  int pldm_platform_power_off(void);
  */
 int pldm_platform_restart(void);
 
+/**
+ * Update the firmware version device-tree field
+ */
+int pldm_fru_dt_add_bmc_version(void);
+
 #endif /* __PLDM_H__ */