// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
// Copyright 2022 IBM Corp.

#define pr_fmt(fmt) "PLDM: " fmt

#include <cpu.h>
#include <opal.h>
#include <stdio.h>
#include <string.h>
#include <timebase.h>
#include <inttypes.h>
#include <libpldm/entity.h>
#include <libpldm/pdr.h>
#include <libpldm/state_set.h>
#include <libpldm/platform.h>
#include "pldm.h"

#define NO_MORE_PDR_HANDLES 0

static pldm_pdr *pdrs_repo;
static bool pdr_ready;

struct pldm_pdrs {
	struct pldm_tx_data *tx;
	uint32_t record_hndl;
	bool done;
	int rc;
};

struct pldm_pdrs *pdrs;

static void pdr_init_complete(bool success)
{
	/* Read not successful, error out and free the buffer */
	if (!success) {
		pdr_ready = false;

		if (pdrs_repo)
			pldm_pdr_destroy(pdrs_repo);
		return;
	}

	/* Mark ready */
	pdr_ready = true;
}

struct get_pdr_response {
	uint8_t completion_code;
	uint32_t next_record_hndl;
	uint32_t next_data_transfer_hndl;
	uint8_t transfer_flag;
	uint16_t resp_cnt;
	uint8_t *record_data;
	size_t record_data_length;
	uint8_t transfer_crc;
};

static int encode_and_queue_get_pdr_req(struct pldm_pdrs *pdrs);

static void get_pdr_req_complete(struct pldm_rx_data *rx,
				 void *data)
{
	struct pldm_pdrs *pdrs = (struct pldm_pdrs *)data;
	uint32_t record_hndl = pdrs->record_hndl;
	struct get_pdr_response response;
	size_t payload_len;
	int rc, i;

	prlog(PR_DEBUG, "%s - record_hndl: %d\n", __func__, record_hndl);

	if (rx == NULL) {
		pdrs->rc = OPAL_PARAMETER;
		pdrs->done = true;
	}

	/* Decode the message twice; the first time, the payload buffer
	 * will be null so that the decoder will simply tell us how big
	 * the buffer should be. Then we create a suitable payload
	 * buffer and call the decoder again, this time with the real
	 * buffer so that it can fill it with data from the message.
	 *
	 * transfer_crc is not used in case of PLDM_START_AND_END.
	 */
	payload_len = rx->msg_len - sizeof(struct pldm_msg_hdr);
	response.record_data_length = 0;
	response.record_data = NULL;

	for (i = 0; i < 2; i++) {
		rc = decode_get_pdr_resp(
				rx->msg, payload_len,
				&response.completion_code,
				&response.next_record_hndl,
				&response.next_data_transfer_hndl,
				&response.transfer_flag,
				&response.resp_cnt,
				response.record_data,
				response.record_data_length,
				&response.transfer_crc);

		if (rc != PLDM_SUCCESS || response.completion_code != PLDM_SUCCESS) {
			/* Message decoding failed */
			prlog(PR_ERR, "Decode GetPDRResp Error (rc: %d, cc: %d)\n",
				      rc, response.completion_code);

			/* BMC is not ready, try again. This behavior can be
			 * encountered when the BMC reboots and the host is
			 * still operational.
			 * The host receives a GET VERSION request indicating
			 * that we must rehcrage the pdrs.
			 */
			if (response.completion_code == PLDM_ERROR_NOT_READY) {
				time_wait_ms(500);
				encode_and_queue_get_pdr_req(pdrs);
				return;
			}

			pdrs->rc = OPAL_PARAMETER;
			pdrs->done = true;
			return;
		}

		if (response.record_data == NULL) {
			response.record_data_length = response.resp_cnt;
			response.record_data = zalloc(response.resp_cnt);
			if (!response.record_data) {
				prlog(PR_ERR, "failed to allocate record data (size: 0x%lx)\n", response.record_data_length);
				pdrs->rc = OPAL_NO_MEM;
				pdrs->done = true;
				return;
			}
		}
	}

	/* we do not support multipart transfer */
	if (response.transfer_flag != PLDM_START_AND_END)
		prlog(PR_ERR, "Transfert GetPDRResp not complete, transfer_flag: %d\n",
			      response.transfer_flag);

	prlog(PR_DEBUG, "%s - record_hndl: %d, next_record_hndl: %d, resp_cnt: %d\n",
			__func__, record_hndl,
			response.next_record_hndl,
			response.resp_cnt);

	/* Add a PDR record to a PDR repository.
	 * Use HOST_TID as terminus handle
	 */
	pldm_pdr_add(pdrs_repo,
		     response.record_data,
		     response.resp_cnt,
		     record_hndl,
		     false,
		     HOST_TID);

	free(response.record_data);

	if (response.next_record_hndl != NO_MORE_PDR_HANDLES) {
		pdrs->record_hndl = response.next_record_hndl;
		encode_and_queue_get_pdr_req(pdrs);
	} else {
		/* We have to indicate the end of the initialization when we
		 * reload the pdrs in background
		 */
		pdr_init_complete(true);
		pdrs->done = true;
		pdrs->rc = OPAL_SUCCESS;
		prlog(PR_DEBUG, "%s - done\n", __func__);
	}
}

/*
 * Send/receive a PLDM GetPDR stateEffecter request message
 * Get platform descriptor records.
 *
 * pldmtool platform GetPDR -t stateEffecter
 * ...
 * {
 * "nextRecordHandle": 138,
 * "responseCount": 30,
 * "recordHandle": 137,
 * "PDRHeaderVersion": 1,
 * "PDRType": "State Effecter PDR",
 * "recordChangeNumber": 0,
 * "dataLength": 20,
 * "PLDMTerminusHandle": 1,
 * "effecterID": 43,
 * "entityType": "[Physical] System chassis (main enclosure)",
 * ...
 * "Off-Soft Graceful(9)"
 * }
 * ...
 */
static int encode_and_queue_get_pdr_req(struct pldm_pdrs *pdrs)
{
	uint32_t record_hndl = pdrs->record_hndl;
	int rc;

	struct pldm_get_pdr_req pdr_req = {
		.record_handle = record_hndl, /* record change number (0 for first request) */
		.data_transfer_handle = 0, /* (0 if transfer op is FIRSTPART) */
		.transfer_op_flag = PLDM_GET_FIRSTPART, /* transfer op flag */
		.request_count = SHRT_MAX, /* Don't limit the size of the PDR */
		.record_change_number = 0 /* record change number (0 for first request) */
	};

	prlog(PR_DEBUG, "%s - record_hndl: %d\n", __func__, record_hndl);

	/* Encode the get_PDR request */
	rc = encode_get_pdr_req(DEFAULT_INSTANCE_ID,
				pdr_req.record_handle,
				pdr_req.data_transfer_handle,
				pdr_req.transfer_op_flag,
				pdr_req.request_count,
				pdr_req.record_change_number,
				(struct pldm_msg *)pdrs->tx->data,
				PLDM_GET_PDR_REQ_BYTES);
	if (rc != PLDM_SUCCESS) {
		prlog(PR_ERR, "Encode GetPDRReq Error, rc: %d\n", rc);
		pdrs->done = true;
		pdrs->rc = OPAL_PARAMETER;
		return OPAL_PARAMETER;
	}

	/* Queue the first getpdr request */
	rc = pldm_requester_queue(pdrs->tx, get_pdr_req_complete, pdrs);
	if (rc) {
		prlog(PR_ERR, "Communication Error, req: GetPDRReq, rc: %d\n", rc);
		pdrs->done = true;
		pdrs->rc = OPAL_PARAMETER;
	}

	return rc;
}

static int pldm_platform_load_pdrs(void)
{
	/* destroy current repo and mark repo not ready */
	pdr_init_complete(false);

	/* make a new PDR repository */
	pdrs_repo = pldm_pdr_init();

	/* collect all PDrs into a PDR Repository */
	pdrs->record_hndl = 0;
	pdrs->done = false;
	return encode_and_queue_get_pdr_req(pdrs);
}

static int pdrs_init(void)
{
	int rc;

	rc = pldm_platform_load_pdrs();
	if (rc)
		return rc;

	/* wait for the end of pdrs received */
	for (;;) {
		if (pdrs->done)
			break;

		time_wait_ms(5);
	}
	return pdrs->rc;
}

int pldm_platform_init(void)
{
	size_t data_size = PLDM_MSG_SIZE(struct pldm_get_pdr_req);
	int rc;

	pdrs = zalloc(sizeof(struct pldm_pdrs));
	if (!pdrs) {
		prlog(PR_ERR, "failed to allocate pdrs\n");
		return OPAL_NO_MEM;
	}

	pdrs->tx = zalloc(sizeof(struct pldm_tx_data) + data_size);
	if (!pdrs->tx)
		return OPAL_NO_MEM;
	pdrs->tx->data_size = data_size;

	/* retrieve all PDRs */
	rc = pdrs_init();
	if (rc)
		goto err;

	pdr_init_complete(true);
	prlog(PR_DEBUG, "%s - done\n", __func__);

	return OPAL_SUCCESS;

err:
	prlog(PR_ERR, "%s - failed to initialize pdrs, rc: %d\n", __func__, rc);
	pdr_init_complete(false);
	free(pdrs->tx);
	free(pdrs);
	return rc;
}

void pldm_platform_exit(void)
{
	if (pdr_ready)
		pldm_pdr_destroy(pdrs_repo);

	if (pdrs) {
		free(pdrs->tx);
		free(pdrs);
	}
}
