user_layer: Add get/set user payload access.

IPMI Spec reference: Section 24.6, 24.7.
Support is added to get/set user access details for the
unreserved, supported payload types defined by Spec.
SOL is the only unreserved, supported payload currently.
If support is needed for unreserved std/oem payload
types in future, they can be enabled with minor source code
changes to this implementation.

All payload types are packed in a JSON object
"payload_enabled" in ipmi_user.json file.

Tested-by:
1. For user 8 in channel 3, Enable SOL payload.

   // Command - (channel 3 is of LAN channel type)
   ipmitool  -I lanplus...raw 0x06 0x4C 3 0x8 0x02 0 0 0
   // Verify it with Get User Payload Access Command
   ipmitool  -I lanplus...raw 0x06 0x4D 3 8
   02 00 00 00 // Response

2. Disable SOL payload.

   // Command
   ipmitool  -I lanplus...raw 0x06 0x4C 3 0x48 0x02 0 0x00 0
   // Verify it with Get User Payload Access Command
   ipmitool  -I lanplus...raw 0x06 0x4D 3 8
   00 00 00 00 // Response

3. Enable unsupported payload stdPayload7.

   // Command
   ipmitool  -I lanplus...raw 0x06 0x4C 3 0x8 0x80 0 0 0
   Error: Invalid data field in request // Response

Change-Id: Idc57b04a747e55666407d928d8b2169223501e5b
Signed-off-by: Saravanan Palanisamy <saravanan.palanisamy@linux.intel.com>
diff --git a/user_channel/user_layer.hpp b/user_channel/user_layer.hpp
index 7926c59..450d878 100644
--- a/user_channel/user_layer.hpp
+++ b/user_channel/user_layer.hpp
@@ -16,6 +16,7 @@
 #pragma once
 #include <ipmid/api.h>
 
+#include <bitset>
 #include <string>
 
 namespace ipmi
@@ -37,6 +38,7 @@
 static constexpr uint8_t ipmiMaxChannels = 16;
 static constexpr uint8_t maxIpmi20PasswordSize = 20;
 static constexpr uint8_t maxIpmi15PasswordSize = 16;
+static constexpr uint8_t payloadsPerByte = 8;
 
 /** @struct PrivAccess
  *
@@ -61,6 +63,19 @@
 #endif
 } __attribute__((packed));
 
+/** @struct UserPayloadAccess
+ *
+ *  Structure to denote payload access restrictions applicable for a
+ *  given user and channel. (refer spec sec 24.6)
+ */
+struct PayloadAccess
+{
+    std::bitset<payloadsPerByte> stdPayloadEnables1;
+    std::bitset<payloadsPerByte> stdPayloadEnables2Reserved;
+    std::bitset<payloadsPerByte> oemPayloadEnables1;
+    std::bitset<payloadsPerByte> oemPayloadEnables2Reserved;
+};
+
 /** @brief initializes user management
  *
  *  @return IPMI_CC_OK for success, others for failure.
@@ -221,4 +236,30 @@
 bool ipmiUserPamAuthenticate(std::string_view userName,
                              std::string_view userPassword);
 
+/** @brief sets user payload access data
+ *
+ *  @param[in] chNum - channel number
+ *  @param[in] operation - ENABLE / DISABLE operation
+ *  @param[in] userId - user id
+ *  @param[in] payloadAccess - payload access data
+ *
+ *  @return IPMI_CC_OK for success, others for failure.
+ */
+ipmi_ret_t ipmiUserSetUserPayloadAccess(const uint8_t chNum,
+                                        const uint8_t operation,
+                                        const uint8_t userId,
+                                        const PayloadAccess& payloadAccess);
+
+/** @brief provides user payload access data
+ *
+ *  @param[in] chNum - channel number
+ *  @param[in] userId - user id
+ *  @param[out] payloadAccess - payload access data
+ *
+ *  @return IPMI_CC_OK for success, others for failure.
+ */
+ipmi_ret_t ipmiUserGetUserPayloadAccess(const uint8_t chNum,
+                                        const uint8_t userId,
+                                        PayloadAccess& payloadAccess);
+
 } // namespace ipmi