1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "cm_param.h"
17
18 #include <stdlib.h>
19 #include <stdio.h>
20 #include <string.h>
21
22 #include "cm_log.h"
23 #include "cm_mem.h"
24 #include "cm_type_inner.h"
25
GetTagType(enum CmTag tag)26 enum CmTagType GetTagType(enum CmTag tag)
27 {
28 return (enum CmTagType)((uint32_t)tag & CM_TAG_TYPE_MASK);
29 }
30
CmInitParamSet(struct CmParamSet ** paramSet)31 int32_t CmInitParamSet(struct CmParamSet **paramSet)
32 {
33 if (paramSet == NULL) {
34 CM_LOG_E("invalid init params!");
35 return CMR_ERROR_INVALID_ARGUMENT;
36 }
37
38 *paramSet = (struct CmParamSet *)CmMalloc(CM_DEFAULT_PARAM_SET_SIZE);
39 if (*paramSet == NULL) {
40 CM_LOG_E("malloc init param set failed!");
41 return CMR_ERROR_MALLOC_FAIL;
42 }
43 (*paramSet)->paramsCnt = 0;
44 (*paramSet)->paramSetSize = sizeof(struct CmParamSet);
45 return CM_SUCCESS;
46 }
47
CmCheckParamSet(const struct CmParamSet * paramSet,uint32_t size)48 static int32_t CmCheckParamSet(const struct CmParamSet *paramSet, uint32_t size)
49 {
50 if (paramSet == NULL) {
51 return CMR_ERROR_NULL_POINTER;
52 }
53
54 if ((size < sizeof(struct CmParamSet)) || (size > CM_PARAM_SET_MAX_SIZE) ||
55 (paramSet->paramSetSize != size) ||
56 (paramSet->paramsCnt > ((size - sizeof(struct CmParamSet)) / sizeof(struct CmParam)))) {
57 CM_LOG_E("invalid param set!");
58 return CMR_ERROR_INVALID_ARGUMENT;
59 }
60 return CM_SUCCESS;
61 }
62
CmFreshParamSet(struct CmParamSet * paramSet,bool isCopy)63 static int32_t CmFreshParamSet(struct CmParamSet *paramSet, bool isCopy)
64 {
65 if (paramSet == NULL) {
66 CM_LOG_E("invalid NULL paramSet");
67 return CMR_ERROR_NULL_POINTER;
68 }
69 int32_t ret = CmCheckParamSet(paramSet, paramSet->paramSetSize);
70 if (ret != CM_SUCCESS) {
71 CM_LOG_E("invalid fresh paramSet");
72 return ret;
73 }
74
75 uint32_t size = paramSet->paramSetSize;
76 uint32_t offset = sizeof(struct CmParamSet) + sizeof(struct CmParam) * paramSet->paramsCnt;
77
78 for (uint32_t i = 0; i < paramSet->paramsCnt; i++) {
79 if (offset > size) {
80 CM_LOG_E("invalid param set offset!");
81 return CMR_ERROR_INVALID_ARGUMENT;
82 }
83 if (GetTagType(paramSet->params[i].tag) == CM_TAG_TYPE_BYTES) {
84 if (CmIsAdditionOverflow(offset, paramSet->params[i].blob.size)) {
85 CM_LOG_E("blob size overflow!");
86 return CMR_ERROR_INVALID_ARGUMENT;
87 }
88
89 if (isCopy && (memcpy_s((uint8_t *)paramSet + offset, size - offset,
90 paramSet->params[i].blob.data, paramSet->params[i].blob.size) != EOK)) {
91 CM_LOG_E("copy param blob failed!");
92 return CMR_ERROR_INVALID_OPERATION;
93 }
94 paramSet->params[i].blob.data = (uint8_t *)paramSet + offset;
95 offset += paramSet->params[i].blob.size;
96 }
97 }
98
99 if (paramSet->paramSetSize != offset) {
100 CM_LOG_E("invalid param set size!");
101 return CMR_ERROR_INVALID_ARGUMENT;
102 }
103 return CM_SUCCESS;
104 }
105
BuildParamSet(struct CmParamSet ** paramSet)106 static int32_t BuildParamSet(struct CmParamSet **paramSet)
107 {
108 struct CmParamSet *freshParamSet = *paramSet;
109 uint32_t size = freshParamSet->paramSetSize;
110 uint32_t offset = sizeof(struct CmParamSet) + sizeof(struct CmParam) * freshParamSet->paramsCnt;
111
112 if (size > CM_DEFAULT_PARAM_SET_SIZE) {
113 freshParamSet = (struct CmParamSet *)CmMalloc(size);
114 if (freshParamSet == NULL) {
115 CM_LOG_E("malloc params failed!");
116 return CMR_ERROR_MALLOC_FAIL;
117 }
118 if (memcpy_s(freshParamSet, size, *paramSet, offset) != EOK) {
119 CM_FREE_PTR(freshParamSet);
120 CM_LOG_E("copy params failed!");
121 return CMR_ERROR_INVALID_OPERATION;
122 }
123 CM_FREE_PTR(*paramSet);
124 *paramSet = freshParamSet;
125 }
126
127 return CmFreshParamSet(freshParamSet, true);
128 }
129
CmBuildParamSet(struct CmParamSet ** paramSet)130 int32_t CmBuildParamSet(struct CmParamSet **paramSet)
131 {
132 if ((paramSet == NULL) || (*paramSet == NULL)) {
133 return CMR_ERROR_NULL_POINTER;
134 }
135
136 int ret = CmCheckParamSet(*paramSet, (*paramSet)->paramSetSize);
137 if (ret != CM_SUCCESS) {
138 CM_LOG_E("invalid build params!");
139 return ret;
140 }
141
142 return BuildParamSet(paramSet);
143 }
144
CmFreeParamSet(struct CmParamSet ** paramSet)145 void CmFreeParamSet(struct CmParamSet **paramSet)
146 {
147 if (paramSet == NULL) {
148 CM_LOG_E("invalid free paramset!");
149 return;
150 }
151 CM_FREE_PTR(*paramSet);
152 }
153
CmGetParam(const struct CmParamSet * paramSet,uint32_t tag,struct CmParam ** param)154 int32_t CmGetParam(const struct CmParamSet *paramSet, uint32_t tag, struct CmParam **param)
155 {
156 if ((paramSet == NULL) || (param == NULL)) {
157 CM_LOG_E("invalid params!");
158 return CMR_ERROR_INVALID_ARGUMENT;
159 }
160
161 if (CmCheckParamSet(paramSet, paramSet->paramSetSize) != CM_SUCCESS) {
162 CM_LOG_E("invalid paramSet!");
163 return CMR_ERROR_INVALID_ARGUMENT;
164 }
165
166 for (uint32_t i = 0; i < paramSet->paramsCnt; i++) {
167 if (tag == paramSet->params[i].tag) {
168 *param = (struct CmParam *)¶mSet->params[i];
169 return CM_SUCCESS;
170 }
171 }
172
173 return CMR_ERROR_PARAM_NOT_EXIST;
174 }
175
FreshParamSet(struct CmParamSet * paramSet,bool isCopy)176 static int32_t FreshParamSet(struct CmParamSet *paramSet, bool isCopy)
177 {
178 uint32_t size = paramSet->paramSetSize;
179 uint32_t offset = sizeof(struct CmParamSet) + sizeof(struct CmParam) * paramSet->paramsCnt;
180
181 for (uint32_t i = 0; i < paramSet->paramsCnt; i++) {
182 if (offset > size) {
183 CM_LOG_E("FreshParamSet invalid param set offset!");
184 return CMR_ERROR_INVALID_ARGUMENT;
185 }
186 if (GetTagType(paramSet->params[i].tag) == CM_TAG_TYPE_BYTES) {
187 if (CmIsAdditionOverflow(offset, paramSet->params[i].blob.size)) {
188 CM_LOG_E("FreshParamSet blob size overflow!");
189 return CMR_ERROR_INVALID_ARGUMENT;
190 }
191 if (isCopy && memcpy_s((uint8_t *)paramSet + offset, size - offset,
192 paramSet->params[i].blob.data, paramSet->params[i].blob.size) != EOK) {
193 CM_LOG_E("FreshParamSet copy param blob failed!");
194 return CMR_ERROR_INVALID_OPERATION;
195 }
196 paramSet->params[i].blob.data = (uint8_t *)paramSet + offset;
197 offset += paramSet->params[i].blob.size;
198 }
199 }
200
201 if (paramSet->paramSetSize != offset) {
202 CM_LOG_E("FreshParamSet invalid param set size!");
203 return CMR_ERROR_INVALID_ARGUMENT;
204 }
205 return CM_SUCCESS;
206 }
207
CmGetParamSet(const struct CmParamSet * inParamSet,uint32_t inParamSetSize,struct CmParamSet ** outParamSet)208 int32_t CmGetParamSet(const struct CmParamSet *inParamSet, uint32_t inParamSetSize, struct CmParamSet **outParamSet)
209 {
210 int32_t ret = CmCheckParamSet(inParamSet, inParamSetSize);
211 if (ret != CM_SUCCESS) {
212 return ret;
213 }
214
215 uint32_t size = inParamSet->paramSetSize;
216 struct CmParamSet *buf = (struct CmParamSet *)CmMalloc(size);
217 if (buf == NULL) {
218 CM_LOG_E("malloc from param set failed!");
219 return CMR_ERROR_MALLOC_FAIL;
220 }
221 (void)memcpy_s(buf, size, inParamSet, size);
222
223 ret = FreshParamSet(buf, false);
224 if (ret != CM_SUCCESS) {
225 CM_FREE_PTR(buf);
226 return ret;
227 }
228 *outParamSet = buf;
229 return CM_SUCCESS;
230 }
231
CheckBeforeAddParams(const struct CmParamSet * paramSet,const struct CmParam * params,uint32_t paramCnt)232 static int32_t CheckBeforeAddParams(const struct CmParamSet *paramSet, const struct CmParam *params,
233 uint32_t paramCnt)
234 {
235 if ((params == NULL) || (paramSet == NULL) || (paramSet->paramSetSize > CM_PARAM_SET_MAX_SIZE) ||
236 (paramCnt > CM_DEFAULT_PARAM_CNT) || ((paramSet->paramsCnt + paramCnt) > CM_DEFAULT_PARAM_CNT)) {
237 CM_LOG_E("invalid params or paramset!");
238 return CMR_ERROR_INVALID_ARGUMENT;
239 }
240
241 for (uint32_t i = 0; i < paramCnt; i++) {
242 if ((GetTagType(params[i].tag) == CM_TAG_TYPE_BYTES) &&
243 (params[i].blob.data == NULL)) {
244 CM_LOG_E("invalid blob param!");
245 return CMR_ERROR_INVALID_ARGUMENT;
246 }
247 }
248 return CM_SUCCESS;
249 }
250
CmAddParams(struct CmParamSet * paramSet,const struct CmParam * params,uint32_t paramCnt)251 int32_t CmAddParams(struct CmParamSet *paramSet, const struct CmParam *params, uint32_t paramCnt)
252 {
253 int32_t ret = CheckBeforeAddParams(paramSet, params, paramCnt);
254 if (ret != CM_SUCCESS) {
255 return ret;
256 }
257
258 for (uint32_t i = 0; i < paramCnt; i++) {
259 paramSet->paramSetSize += sizeof(struct CmParam);
260 if (GetTagType(params[i].tag) == CM_TAG_TYPE_BYTES) {
261 if (CmIsAdditionOverflow(paramSet->paramSetSize, params[i].blob.size)) {
262 CM_LOG_E("params size overflow!");
263 paramSet->paramSetSize -= sizeof(struct CmParam);
264 return CMR_ERROR_INVALID_ARGUMENT;
265 }
266 paramSet->paramSetSize += params[i].blob.size;
267 }
268 (void)memcpy_s(¶mSet->params[paramSet->paramsCnt++], sizeof(struct CmParam), ¶ms[i],
269 sizeof(struct CmParam));
270 }
271 return CM_SUCCESS;
272 }
273