1 /* Copyright (c) 2021, The Linux Foundataion. All rights reserved. 2 * 3 * Redistribution and use in source and binary forms, with or without 4 * modification, are permitted provided that the following conditions are 5 * met: 6 * * Redistributions of source code must retain the above copyright 7 * notice, this list of conditions and the following disclaimer. 8 * * Redistributions in binary form must reproduce the above 9 * copyright notice, this list of conditions and the following 10 * disclaimer in the documentation and/or other materials provided 11 * with the distribution. 12 * * Neither the name of The Linux Foundation nor the names of its 13 * contributors may be used to endorse or promote products derived 14 * from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 */ 29 30 #ifndef __GENERIC_PAYLOAD_H__ 31 #define __GENERIC_PAYLOAD_H__ 32 33 #include <errno.h> 34 #include <debug_handler.h> 35 #include <assert.h> 36 #include <functional> 37 #include <cstring> 38 39 // Do not define __CLASS__ for logging in shared utility header like this one 40 41 namespace sdm { 42 43 struct GenericPayload { 44 public: GenericPayloadGenericPayload45 GenericPayload(): 46 type_size(0), payload(nullptr), array_size(0) {} 47 GenericPayloadGenericPayload48 GenericPayload(const GenericPayload &in) { 49 type_size = 0; 50 payload = nullptr; 51 array_size = 0; 52 if (in.payload) { 53 display::DebugHandler::Get()->Error("GenericPayload::%s:New GenericPayload will not copy" 54 "payload data! Use CopyPayload on a new GenericPayload instance.", __FUNCTION__); 55 } 56 copy_constructed = true; 57 } 58 59 GenericPayload& operator=(const GenericPayload &) = delete; 60 CopyPayloadGenericPayload61 template<typename A> int CopyPayload(const GenericPayload &in) { 62 if (sizeof(A) != in.type_size) { 63 return -EINVAL; 64 } 65 A* p = reinterpret_cast<A *>(in.payload); 66 type_size = sizeof(A); 67 array_size = in.array_size; 68 69 if (payload != nullptr) { 70 release(); 71 } 72 A* p2 = nullptr; 73 if (array_size > 1) { 74 p2 = new A[array_size]; 75 } else { 76 p2 = new A(); 77 } 78 if (p2 == nullptr) { 79 return -ENOMEM; 80 } 81 *p2 = *p; 82 payload = reinterpret_cast<uint8_t *>(p2); 83 if (array_size > 1) { 84 release = std::function<void(void)>([p2]() -> void {delete [] p2;}); 85 } else { 86 release = std::function<void(void)>([p2]() -> void {delete p2;}); 87 } 88 return 0; 89 } 90 CreatePayloadGenericPayload91 template<typename A> int CreatePayload(A *&p) { 92 if (payload) { 93 p = nullptr; 94 return -EALREADY; 95 } 96 97 p = new A(); 98 if (p == nullptr) { 99 return -ENOMEM; 100 } 101 102 type_size = sizeof(A); 103 array_size = 1; 104 payload = reinterpret_cast<uint8_t *>(p); 105 release = std::function<void(void)>([p]() -> void {delete p;}); 106 107 return 0; 108 } 109 CreatePayloadGenericPayload110 template<typename A> int CreatePayload(A *&p, uint32_t sz) { 111 if (payload) { 112 p = nullptr; 113 return -EALREADY; 114 } 115 116 if (!sz) { 117 return -EINVAL; 118 } 119 120 p = new A[sz]; 121 if (p == nullptr) { 122 return -ENOMEM; 123 } 124 125 type_size = sizeof(A); 126 array_size = sz; 127 payload = reinterpret_cast<uint8_t *>(p); 128 release = std::function<void(void)>([p]() -> void {delete [] p;}); 129 130 return 0; 131 } 132 GetPayloadGenericPayload133 template<typename A> int GetPayload(A *&p, uint32_t *sz) const { 134 if ((sz == nullptr) || (sizeof(A) != type_size)) { 135 p = nullptr; 136 return -EINVAL; 137 } 138 139 p = reinterpret_cast<A *>(payload); 140 *sz = 0; 141 if (p == nullptr && copy_constructed) { 142 display::DebugHandler::Get()->Error("GenericPayload::%s:Payload was not properly" 143 "copied via CopyPayload", __FUNCTION__); 144 return -ENOMEM; 145 } else if (p == nullptr) { 146 display::DebugHandler::Get()->Error("GenericPayload::%s:Payload was not properly" 147 "created via CreatePayload", __FUNCTION__); 148 return -ENOMEM; 149 } 150 *sz = array_size; 151 152 return 0; 153 } 154 DeletePayloadGenericPayload155 void DeletePayload() { 156 if (payload != nullptr) { 157 release(); 158 } 159 160 type_size = 0; 161 payload = nullptr; 162 array_size = 0; 163 } 164 ~GenericPayloadGenericPayload165 ~GenericPayload() { 166 DeletePayload(); 167 } 168 169 private: 170 uint32_t type_size; 171 uint8_t *payload; 172 uint32_t array_size; 173 std::function<void(void)> release; 174 bool copy_constructed = false; 175 }; 176 177 } // namespace sdm 178 179 #endif // __GENERIC_PAYLOAD_H__ 180 181