Add encoders for state sensor/effecter PDRs and sensor event data

Change-Id: I736d1b7b1c124faf8fbf86bb3b760cc9b48c1e2b
Signed-off-by: Zach Clark <zach@ibm.com>
diff --git a/libpldm/base.h b/libpldm/base.h
index dd63f1c..5109c34 100644
--- a/libpldm/base.h
+++ b/libpldm/base.h
@@ -110,6 +110,10 @@
 	uint8_t command; //!< PLDM command code
 } __attribute__((packed));
 
+// Macros for byte-swapping variables in-place
+#define HTOLE32(X) (X = htole32(X))
+#define HTOLE16(X) (X = htole16(X))
+
 /** @struct pldm_msg
  *
  * Structure representing PLDM message
diff --git a/libpldm/platform.c b/libpldm/platform.c
index 9b0403f..401e1ca 100644
--- a/libpldm/platform.c
+++ b/libpldm/platform.c
@@ -3,6 +3,140 @@
 
 #include "platform.h"
 
+int encode_state_effecter_pdr(
+    struct pldm_state_effecter_pdr *const effecter,
+    const size_t allocation_size,
+    const struct state_effecter_possible_states *const possible_states,
+    const size_t possible_states_size, size_t *const actual_size)
+{
+	// Encode possible states
+
+	size_t calculated_possible_states_size = 0;
+
+	{
+		char *states_ptr = (char *)possible_states;
+		char *const begin_states_ptr = states_ptr;
+
+		for (int i = 0; i < effecter->composite_effecter_count; ++i) {
+			struct state_effecter_possible_states *states =
+			    (struct state_effecter_possible_states *)states_ptr;
+
+			HTOLE16(states->state_set_id);
+
+			states_ptr +=
+			    (sizeof(*states) - sizeof(states->states) +
+			     states->possible_states_size);
+		}
+
+		calculated_possible_states_size = states_ptr - begin_states_ptr;
+	}
+
+	// Check lengths
+
+	if (possible_states_size != calculated_possible_states_size) {
+		*actual_size = 0;
+		return PLDM_ERROR;
+	}
+
+	*actual_size =
+	    (sizeof(struct pldm_state_effecter_pdr) + possible_states_size -
+	     sizeof(effecter->possible_states));
+
+	if (allocation_size < *actual_size) {
+		*actual_size = 0;
+		return PLDM_ERROR_INVALID_LENGTH;
+	}
+
+	// Encode rest of PDR
+
+	effecter->hdr.version = 1;
+	effecter->hdr.type = PLDM_STATE_EFFECTER_PDR;
+	effecter->hdr.length = *actual_size - sizeof(struct pldm_pdr_hdr);
+
+	memcpy(effecter->possible_states, possible_states,
+	       possible_states_size);
+
+	// Convert effecter PDR body
+	HTOLE16(effecter->terminus_handle);
+	HTOLE16(effecter->effecter_id);
+	HTOLE16(effecter->entity_type);
+	HTOLE16(effecter->entity_instance);
+	HTOLE16(effecter->container_id);
+	HTOLE16(effecter->effecter_semantic_id);
+
+	// Convert header
+	HTOLE32(effecter->hdr.record_handle);
+	HTOLE16(effecter->hdr.record_change_num);
+	HTOLE16(effecter->hdr.length);
+
+	return PLDM_SUCCESS;
+}
+
+int encode_state_sensor_pdr(
+    struct pldm_state_sensor_pdr *const sensor, const size_t allocation_size,
+    const struct state_sensor_possible_states *const possible_states,
+    const size_t possible_states_size, size_t *const actual_size)
+{
+	// Encode possible states
+
+	size_t calculated_possible_states_size = 0;
+
+	{
+		char *states_ptr = (char *)possible_states,
+		     *const begin_states_ptr = states_ptr;
+
+		for (int i = 0; i < sensor->composite_sensor_count; ++i) {
+			struct state_sensor_possible_states *states =
+			    (struct state_sensor_possible_states *)states_ptr;
+
+			HTOLE16(states->state_set_id);
+
+			states_ptr +=
+			    (sizeof(*states) - sizeof(states->states) +
+			     states->possible_states_size);
+		}
+
+		calculated_possible_states_size = states_ptr - begin_states_ptr;
+	}
+
+	// Check lengths
+
+	if (possible_states_size != calculated_possible_states_size) {
+		*actual_size = 0;
+		return PLDM_ERROR;
+	}
+
+	*actual_size = (sizeof(struct pldm_state_sensor_pdr) +
+			possible_states_size - sizeof(sensor->possible_states));
+
+	if (allocation_size < *actual_size) {
+		*actual_size = 0;
+		return PLDM_ERROR_INVALID_LENGTH;
+	}
+
+	// Encode rest of PDR
+
+	sensor->hdr.version = 1;
+	sensor->hdr.type = PLDM_STATE_SENSOR_PDR;
+	sensor->hdr.length = *actual_size - sizeof(struct pldm_pdr_hdr);
+
+	memcpy(sensor->possible_states, possible_states, possible_states_size);
+
+	// Convert sensor PDR body
+	HTOLE16(sensor->terminus_handle);
+	HTOLE16(sensor->sensor_id);
+	HTOLE16(sensor->entity_type);
+	HTOLE16(sensor->entity_instance);
+	HTOLE16(sensor->container_id);
+
+	// Convert header
+	HTOLE32(sensor->hdr.record_handle);
+	HTOLE16(sensor->hdr.record_change_num);
+	HTOLE16(sensor->hdr.length);
+
+	return PLDM_SUCCESS;
+}
+
 int encode_set_state_effecter_states_resp(uint8_t instance_id,
 					  uint8_t completion_code,
 					  struct pldm_msg *msg)
@@ -562,6 +696,40 @@
 	return PLDM_SUCCESS;
 }
 
+int encode_sensor_event_data(
+    struct pldm_sensor_event_data *const event_data,
+    const size_t event_data_size, const uint16_t sensor_id,
+    const enum sensor_event_class_states sensor_event_class,
+    const uint8_t sensor_offset, const uint8_t event_state,
+    const uint8_t previous_event_state, size_t *const actual_event_data_size)
+{
+	*actual_event_data_size =
+	    (sizeof(*event_data) - sizeof(event_data->event_class) +
+	     sizeof(struct pldm_sensor_event_state_sensor_state));
+
+	if (!event_data) {
+		return PLDM_SUCCESS;
+	}
+
+	if (event_data_size < *actual_event_data_size) {
+		*actual_event_data_size = 0;
+		return PLDM_ERROR_INVALID_LENGTH;
+	}
+
+	event_data->sensor_id = htole32(sensor_id);
+	event_data->sensor_event_class_type = sensor_event_class;
+
+	struct pldm_sensor_event_state_sensor_state *const state_data =
+	    (struct pldm_sensor_event_state_sensor_state *)
+		event_data->event_class;
+
+	state_data->sensor_offset = sensor_offset;
+	state_data->event_state = event_state;
+	state_data->previous_event_state = previous_event_state;
+
+	return PLDM_SUCCESS;
+}
+
 int decode_platform_event_message_req(const struct pldm_msg *msg,
 				      size_t payload_length,
 				      uint8_t *format_version, uint8_t *tid,
diff --git a/libpldm/platform.h b/libpldm/platform.h
index 5d80511..be55d4f 100644
--- a/libpldm/platform.h
+++ b/libpldm/platform.h
@@ -316,6 +316,29 @@
 	uint8_t possible_states[1];
 } __attribute__((packed));
 
+/** @brief Encode PLDM state sensor PDR
+ *
+ * @param[in/out] sensor                 Structure to encode. All members of
+ * sensor, except those mentioned in the @note below, should be initialized by
+ * the caller.
+ * @param[in]     allocation_size        Size of sensor allocation in bytes
+ * @param[in]     possible_states        Possible sensor states
+ * @param[in]     possible_states_size   Size of possible sensor states in bytes
+ * @param[out]    actual_size            Size of sensor PDR. Set to 0 on error.
+ * @return int    pldm_completion_codes
+ *                PLDM_SUCCESS/PLDM_ERROR/PLDM_ERROR_INVALID_LENGTH
+ *
+ * @note The sensor parameter will be encoded in place.
+ * @note Caller is responsible for allocation of the sensor parameter. Caller
+ *       must allocate enough space for the base structure and the
+ *       sensor->possible_states array, otherwise the function will fail.
+ * @note sensor->hdr.length, .type, and .version will be set appropriately.
+ */
+int encode_state_sensor_pdr(
+    struct pldm_state_sensor_pdr *sensor, size_t allocation_size,
+    const struct state_sensor_possible_states *possible_states,
+    size_t possible_states_size, size_t *actual_size);
+
 /** @union union_effecter_data_size
  *
  *  The bit width and format of reading and threshold values that the effecter
@@ -399,6 +422,32 @@
 	bitfield8_t states[1];
 } __attribute__((packed));
 
+/** @brief Encode PLDM state effecter PDR
+ *
+ * @param[in/out] effecter               Structure to encode. All members of
+ *                                       effecter, except those mentioned in
+ *                                       the @note below, should be initialized
+ *                                       by the caller.
+ * @param[in]     allocation_size        Size of effecter allocation in bytes
+ * @param[in]     possible_states        Possible effecter states
+ * @param[in]     possible_states_size   Size of possible effecter states in
+ *                                       bytes
+ * @param[out]    actual_size            Size of effecter PDR. Set to 0 on
+ *                                       error.
+ * @return int    pldm_completion_codes
+ *                PLDM_SUCCESS/PLDM_ERROR/PLDM_ERROR_INVALID_LENGTH
+ *
+ * @note The effecter parameter will be encoded in place.
+ * @note Caller is responsible for allocation of the effecter parameter. Caller
+ *       must allocate enough space for the base structure and the
+ *       effecter->possible_states array, otherwise the function will fail.
+ * @note effecter->hdr.length, .type, and .version will be set appropriately.
+ */
+int encode_state_effecter_pdr(
+    struct pldm_state_effecter_pdr *effecter, size_t allocation_size,
+    const struct state_effecter_possible_states *possible_states,
+    size_t possible_states_size, size_t *actual_size);
+
 /** @struct set_effecter_state_field
  *
  *  Structure representing a stateField in SetStateEffecterStates command */
@@ -1273,6 +1322,29 @@
     struct pldm_pdr_repository_chg_event_data *event_data,
     size_t *actual_change_records_size, size_t max_change_records_size);
 
+/** @brief Encode event data for a PLDM Sensor Event
+ *
+ *  @param[out] event_data              The object to store the encoded event in
+ *  @param[in] event_data_size          Size of the allocation for event_data
+ *  @param[in] sensor_id                Sensor ID
+ *  @param[in] sensor_event_class       Sensor event class
+ *  @param[in] sensor_offset            Offset
+ *  @param[in] event_state              Event state
+ *  @param[in] previous_event_state     Previous event state
+ *  @param[out] actual_event_data_size  The real size in bytes of the event_data
+ *  @return int pldm_completion_codes   PLDM_SUCCESS/PLDM_ERROR_INVALID_LENGTH
+ *  @note If event_data is NULL, then *actual_event_data_size will be set to
+ *        reflect the size of the event data, and PLDM_SUCCESS will be returned.
+ *  @note The caller is responsible for allocating and deallocating the
+ *        event_data
+ */
+int encode_sensor_event_data(struct pldm_sensor_event_data *event_data,
+			     size_t event_data_size, uint16_t sensor_id,
+			     enum sensor_event_class_states sensor_event_class,
+			     uint8_t sensor_offset, uint8_t event_state,
+			     uint8_t previous_event_state,
+			     size_t *actual_event_data_size);
+
 /** @brief Decode PldmPDRRepositoryChangeRecord response data
  *
  *  @param[in] change_record_data - changeRecordData for
diff --git a/libpldm/state_set.h b/libpldm/state_set.h
index 90a128e..7bc364c 100644
--- a/libpldm/state_set.h
+++ b/libpldm/state_set.h
@@ -127,8 +127,31 @@
 	PLDM_STATE_SET_SLOT_STATE = 353,

 };

 

+/* @brief List of states for the Boot Restart Cause state set (ID 192).

+ */

+enum pldm_state_set_boot_restart_cause_values {

+	PLDM_STATE_SET_BOOT_RESTART_CAUSE_POWERED_UP = 1,

+	PLDM_STATE_SET_BOOT_RESTART_CAUSE_HARD_RESET = 2,

+	PLDM_STATE_SET_BOOT_RESTART_CAUSE_WARM_RESET = 3,

+	PLDM_STATE_SET_BOOT_RESTART_CAUSE_MANUAL_HARD_RESET = 4,

+	PLDM_STATE_SET_BOOT_RESTART_CAUSE_MANUAL_WARM_RESET = 5,

+	PLDM_STATE_SET_BOOT_RESTART_CAUSE_SYSTEM_RESTART = 6,

+	PLDM_STATE_SET_BOOT_RESTART_CAUSE_WATCHDOG_TIMEOUT = 7

+};

+

+/* @brief List of states for the Operational Running Status state set (ID 11).

+ */

+enum pldm_state_set_operational_running_status_values {

+	PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_STARTING = 1,

+	PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_STOPPING = 2,

+	PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_STOPPED = 3,

+	PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_IN_SERVICE = 4,

+	PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_ABORTED = 5,

+	PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_DORMANT = 6

+};

+

 #ifdef __cplusplus

 }

 #endif

 

-#endif /* STATE_SET_H */
\ No newline at end of file
+#endif /* STATE_SET_H */