• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 *)&paramSet->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(&paramSet->params[paramSet->paramsCnt++], sizeof(struct CmParam), &params[i],
269             sizeof(struct CmParam));
270     }
271     return CM_SUCCESS;
272 }
273