[Skiboot] [PATCH V2 13/15] core/pldm: Register OPAL_RTC_READ/WRITE calls back
Christophe Lombard
clombard at linux.ibm.com
Wed May 17 00:12:40 AEST 2023
Le 26/04/2023 à 17:20, Frederic Barrat a écrit :
>
>
> On 29/04/2022 11:47, Christophe Lombard wrote:
>> OPAL_RTC_READ/WRITE are used to retrieve and write the time. PLDM stack
>> provides GetBiosDateTimeReq and SetBiosDateTimeReq commands to exercise.
>>
>> Signed-off-by: Christophe Lombard <clombard at linux.vnet.ibm.com>
>> ---
>> core/pldm/Makefile.inc | 2 +-
>> core/pldm/pldm-bios-requests.c | 134 +++++++++++++++++++++++++++++++++
>> core/pldm/pldm-rtc.c | 76 +++++++++++++++++++
>> core/pldm/pldm.h | 3 +
>> include/pldm.h | 5 ++
>> 5 files changed, 219 insertions(+), 1 deletion(-)
>> create mode 100644 core/pldm/pldm-rtc.c
>>
>> diff --git a/core/pldm/Makefile.inc b/core/pldm/Makefile.inc
>> index 01117680..cf174c86 100644
>> --- a/core/pldm/Makefile.inc
>> +++ b/core/pldm/Makefile.inc
>> @@ -16,7 +16,7 @@ PLDM_OBJS = pldm-common.o pldm-responder.o
>> pldm-requester.o
>> PLDM_OBJS += pldm-base-requests.o pldm-platform-requests.o
>> PLDM_OBJS += pldm-bios-requests.o pldm-fru-requests.o
>> PLDM_OBJS += pldm-file-io-requests.o pldm-lid-files.o
>> -PLDM_OBJS += pldm-watchdog.o
>> +PLDM_OBJS += pldm-watchdog.o pldm-rtc.o
>> PLDM = $(PLDM_DIR)/built-in.a
>> $(PLDM): $(PLDM_OBJS:%=$(PLDM_DIR)/%)
>> diff --git a/core/pldm/pldm-bios-requests.c
>> b/core/pldm/pldm-bios-requests.c
>> index 66a46bb8..09a30b2b 100644
>> --- a/core/pldm/pldm-bios-requests.c
>> +++ b/core/pldm/pldm-bios-requests.c
>> @@ -6,9 +6,11 @@
>> #include <opal.h>
>> #include <stdio.h>
>> #include <string.h>
>> +#include <time.h>
>> #include <inttypes.h>
>> #include <pldm/libpldm/bios.h>
>> #include <pldm/libpldm/bios_table.h>
>> +#include <pldm/libpldm/utils.h>
>> #include "pldm.h"
>> /*
>> @@ -84,6 +86,138 @@ static void bios_init_complete(bool success)
>> bios_ready = true;
>> }
>> +struct get_date_time_resp {
>> + uint8_t completion_code;
>> + uint8_t seconds;
>> + uint8_t minutes;
>> + uint8_t hours;
>> + uint8_t day;
>> + uint8_t month;
>> + uint16_t year;
>> +};
>> +
>> +/*
>> + * Send/receive a PLDM GetBiosDateTime request message
>> + */
>> +int pldm_bios_get_date_time_req(struct tm *tm)
>> +{
>> + char request_msg[PKT_SIZE(0)]; /* the command doesn't have a
>> message payload */
>> + size_t response_len, payload_len;
>> + void *response_msg;
>> + int rc;
>> +
>> + struct get_date_time_resp response;
>> +
>> + /* Encode the date time request */
>> + rc = encode_get_date_time_req(
>> + DEFAULT_INSTANCE_ID,
>> + (struct pldm_msg *)request_msg);
>> + if (rc != PLDM_SUCCESS) {
>> + prlog(PR_ERR, "Encode GetBiosDateTimeReq Error, rc: %d\n",
>> + rc);
>> + return OPAL_PARAMETER;
>> + }
>> +
>> + /* Send and get the response message bytes */
>> + rc = pldm_do_request(BMC_EID, request_msg, sizeof(request_msg),
>> + &response_msg, &response_len);
>> + if (rc) {
>> + prlog(PR_ERR, "Communication Error, req: GetBiosDateTimeReq,
>> rc: %d\n", rc);
>> + return rc;
>> + }
>> +
>> + /* Decode the message */
>> + payload_len = response_len - sizeof(struct pldm_msg_hdr);
>> + rc = decode_get_date_time_resp(
>> + response_msg,
>> + payload_len,
>> + &response.completion_code,
>> + &response.seconds,
>> + &response.minutes,
>> + &response.hours,
>> + &response.day,
>> + &response.month,
>> + &response.year);
>> + if (rc != PLDM_SUCCESS || response.completion_code !=
>> PLDM_SUCCESS) {
>> + prlog(PR_ERR, "Decode GetBiosDateTimeReq Error, rc: %d, cc:
>> %d\n",
>> + rc, response.completion_code);
>> + free(response_msg);
>> + return OPAL_PARAMETER;
>> + }
>> +
>> + /* The data arrives from BMC in BCD format. Convert it to
>> + * decimal for processing
>> + */
>> + tm->tm_sec = bcd2dec8(response.seconds);
>> + tm->tm_min = bcd2dec8(response.minutes);
>> + tm->tm_hour = bcd2dec8(response.hours);
>> + tm->tm_mday = bcd2dec8(response.day);
>> + tm->tm_mon = bcd2dec8(response.month);
>> + tm->tm_year = bcd2dec16(response.year);
>> +
>> + if (!is_time_legal(tm->tm_sec, tm->tm_min, tm->tm_hour,
>> + tm->tm_mday, tm->tm_mon, tm->tm_year)) {
>> + prlog(PR_ERR, "Invalid date time value\n");
>> + free(response_msg);
>> + return OPAL_PARAMETER;
>> + }
>> +
>> + free(response_msg);
>> +
>> + return OPAL_SUCCESS;
>> +}
>> +
>> +/*
>> + * Send/receive a PLDM SetBiosDateTime request message
>> + */
>> +int pldm_bios_set_date_time_req(struct tm *tm)
>> +{
>> + char request_msg[PKT_SIZE(struct pldm_set_date_time_req)];
>> + size_t response_len, payload_len;
>> + uint8_t completion_code;
>> + void *response_msg;
>> + int rc;
>> +
>> + /* Encode the date time request */
>> + rc = encode_set_date_time_req(
>> + DEFAULT_INSTANCE_ID,
>> + tm->tm_sec, tm->tm_min, tm->tm_hour,
>> + tm->tm_mday, tm->tm_mon, tm->tm_year,
>> + (struct pldm_msg *)request_msg,
>> + sizeof(struct pldm_set_date_time_req));
>> + if (rc != PLDM_SUCCESS) {
>> + prlog(PR_ERR, "Encode SetBiosDateTimeReq Error, rc: %d\n",
>> + rc);
>> + return OPAL_PARAMETER;
>> + }
>> +
>> + /* Send and get the response message bytes */
>> + rc = pldm_do_request(BMC_EID, request_msg, sizeof(request_msg),
>> + &response_msg, &response_len);
>> + if (rc) {
>> + prlog(PR_ERR, "Communication Error, req: SetBiosDateTimeReq,
>> rc: %d\n", rc);
>> + return rc;
>> + }
>> +
>> + /* Decode the message */
>> + payload_len = response_len - sizeof(struct pldm_msg_hdr);
>> + rc = decode_set_date_time_resp(
>> + response_msg,
>> + payload_len,
>> + &completion_code);
>> + if (rc != PLDM_SUCCESS || (completion_code > PLDM_ERROR)) {
>> + /* FIXME: Time value from OPAL_RTC_WRITE is never correct */
>> + prlog(PR_ERR, "Decode SetBiosDateTimeReq Error, rc: %d, cc:
>> %d\n",
>> + rc, completion_code);
>> + free(response_msg);
>> + return OPAL_PARAMETER;
>> + }
>> +
>> + free(response_msg);
>> +
>> + return OPAL_SUCCESS;
>> +}
>> +
>> /*
>> * parse a string, format:
>> * <ATTR_a>=<lid_id_1>,<ATTR_b>=<lid_id_2>
>> diff --git a/core/pldm/pldm-rtc.c b/core/pldm/pldm-rtc.c
>> new file mode 100644
>> index 00000000..e449b73e
>> --- /dev/null
>> +++ b/core/pldm/pldm-rtc.c
>> @@ -0,0 +1,76 @@
>> +// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
>> +// Copyright 2022 IBM Corp.
>> +
>> +#define pr_fmt(fmt) "PLDM: " fmt
>> +
>> +#include <stdlib.h>
>> +#include <string.h>
>> +#include <time.h>
>> +#include <time-utils.h>
>> +#include <device.h>
>> +#include <opal.h>
>> +#include <rtc.h>
>> +#include "pldm.h"
>> +
>> +static int64_t get_and_cache_date_time(struct tm *tm)
>> +{
>> + int rc;
>> +
>> + rc = pldm_bios_get_date_time_req(tm);
>> + if (!rc)
>> + rtc_cache_update(tm);
>> +
>> + return rc;
>> +}
>> +
>> +static int64_t pldm_opal_rtc_read(__be32 *__ymd, __be64 *__hmsm)
>> +{
>> + struct tm tm;
>> + uint32_t ymd;
>> + uint64_t hmsm;
>> + int rc;
>> +
>> + if (!__ymd || !__hmsm)
>> + return OPAL_PARAMETER;
>> +
>> + rc = get_and_cache_date_time(&tm);
>> + if ((rc) && (rc != OPAL_BUSY))
>> + return OPAL_HARDWARE;
>> +
>> + if (rc == OPAL_BUSY)
>> + return OPAL_BUSY_EVENT;
>> +
>> + rtc_cache_get_datetime(&ymd, &hmsm);
>> + *__ymd = cpu_to_be32(ymd);
>> + *__hmsm = cpu_to_be64(hmsm);
>> +
>> + return OPAL_SUCCESS;
>> +}
>> +
>> +static int64_t pldm_opal_rtc_write(uint32_t year_month_day,
>> + uint64_t hour_minute_second_millisecond)
>> +{
>> + struct tm tm;
>> + int rc;
>> +
>> + datetime_to_tm(year_month_day, hour_minute_second_millisecond,
>> &tm);
>> +
>> + rc = pldm_bios_set_date_time_req(&tm);
>> + if (rc == OPAL_BUSY)
>> + return OPAL_BUSY_EVENT;
>
>
> if set_date_time_req() fails with something different than OPAL_BUSY,
> we return from this function with OPAL_SUCCESS?
>
> Why are we converting from OPAL_BUSY to OPAL_BUSY_EVENT?
>
A bad copy/past. Thanks
> If the OS loops (which will happen on powernv), then we're going to
> send many PLDM requests, while ignoring the response. IPMI doesn't
> bother and ignore the result of the write request.
>
> Fred
>
>
>> +
>> + return OPAL_SUCCESS;
>> +}
>> +
>> +void pldm_rtc_init(void)
>> +{
>> + struct tm tm;
>> + struct dt_node *np = dt_new(opal_node, "rtc");
>> +
>> + dt_add_property_strings(np, "compatible", "ibm,opal-rtc");
>> +
>> + opal_register(OPAL_RTC_READ, pldm_opal_rtc_read, 2);
>> + opal_register(OPAL_RTC_WRITE, pldm_opal_rtc_write, 2);
>> +
>> + get_and_cache_date_time(&tm);
>> +}
>> diff --git a/core/pldm/pldm.h b/core/pldm/pldm.h
>> index ef884995..81df9f8b 100644
>> --- a/core/pldm/pldm.h
>> +++ b/core/pldm/pldm.h
>> @@ -5,6 +5,7 @@
>> #ifndef __COREPLDM_H__
>> #define __COREPLDM_H__
>> +#include <time.h>
>> #include <pldm/libpldm/base.h>
>> #include <pldm/libpldm/utils.h>
>> #include <pldm.h>
>> @@ -94,6 +95,8 @@ void pldm_fru_add_record(uint32_t *fru_table_length,
>> int pldm_fru_get_table(void **fru_record_table_bytes,
>> uint32_t *fru_record_table_size);
>> +int pldm_bios_get_date_time_req(struct tm *tm);
>> +int pldm_bios_set_date_time_req(struct tm *tm);
>> int pldm_bios_find_lid_by_attr_name(const char *name, char **lid);
>> int pldm_bios_get_lids_id(char **lid_ids_string);
>> int pldm_bios_init(void);
>> diff --git a/include/pldm.h b/include/pldm.h
>> index 5acdcbbe..019e811f 100644
>> --- a/include/pldm.h
>> +++ b/include/pldm.h
>> @@ -54,4 +54,9 @@ int pldm_watchdog_init(void);
>> int pldm_platform_send_progress_state_change(
>> enum pldm_state_set_boot_progress_state_values state);
>> +/**
>> + * Configure real-time clock
>> + */
>> +void pldm_rtc_init(void);
>> +
>> #endif /* __PLDM_H__ */
More information about the Skiboot
mailing list