1 /*
2  * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
3  *
4  * HDF is dual licensed: you can use it either under the terms of
5  * the GPL, or the BSD license, at your option.
6  * See the LICENSE file in the root of this repository for complete details.
7  */
8 
9 #include "hcs_tree_if.h"
10 #include "hcs_blob_if.h"
11 #include "hdf_log.h"
12 
13 #define HDF_LOG_TAG hcs_tree_if
14 
GetAttrInNode(const struct DeviceResourceNode * node,const char * attrName)15 static struct DeviceResourceAttr *GetAttrInNode(const struct DeviceResourceNode *node, const char *attrName)
16 {
17     struct DeviceResourceAttr *attr = NULL;
18     if ((node == NULL) || (attrName == NULL)) {
19         return NULL;
20     }
21     for (attr = node->attrData; attr != NULL; attr = attr->next) {
22         if ((attr->name != NULL) && (strcmp(attr->name, attrName) == 0)) {
23             break;
24         }
25     }
26     return attr;
27 }
28 
HcsGetBool(const struct DeviceResourceNode * node,const char * attrName)29 bool HcsGetBool(const struct DeviceResourceNode *node, const char *attrName)
30 {
31     uint8_t value;
32     struct DeviceResourceAttr *attr = GetAttrInNode(node, attrName);
33     if ((attr == NULL) || (attr->value == NULL)) {
34         HDF_LOGE("%s failed, the node or attrName is NULL", __func__);
35         return false;
36     }
37 
38     if (!HcsSwapToUint8(&value, attr->value + HCS_PREFIX_LENGTH, HcsGetPrefix(attr->value))) {
39         HDF_LOGE("%s failed, incorrect prefix", __func__);
40         return false;
41     }
42     return value ? true : false;
43 }
44 
45 #define RETURN_DEFAULT_VALUE(attr, attrName, value, def) do {                                              \
46     if (((attr) == NULL) || ((attr)->value == NULL) || ((value) == NULL)) {                                \
47         HDF_LOGE("%s failed, the attr of %s is NULL, or the value is NULL, the value is default value",    \
48                 __func__, ((attrName) == NULL) ? "error attrName" : (attrName));                           \
49         if ((value) != NULL) {                                                                             \
50             *(value) = (def);                                                                              \
51         }                                                                                                  \
52         return HDF_FAILURE;                                                                                \
53     }                                                                                                      \
54 } while (0)
55 
HcsGetUint8(const struct DeviceResourceNode * node,const char * attrName,uint8_t * value,uint8_t def)56 int32_t HcsGetUint8(const struct DeviceResourceNode *node, const char *attrName, uint8_t *value, uint8_t def)
57 {
58     struct DeviceResourceAttr *attr = GetAttrInNode(node, attrName);
59     RETURN_DEFAULT_VALUE(attr, attrName, value, def);
60 
61     if (!HcsSwapToUint8(value, attr->value + HCS_PREFIX_LENGTH, HcsGetPrefix(attr->value))) {
62         *value = def;
63         HDF_LOGE("%s failed, incorrect prefix", __func__);
64         return HDF_FAILURE;
65     }
66     return HDF_SUCCESS;
67 }
68 
HcsGetUint16(const struct DeviceResourceNode * node,const char * attrName,uint16_t * value,uint16_t def)69 int32_t HcsGetUint16(const struct DeviceResourceNode *node, const char *attrName, uint16_t *value, uint16_t def)
70 {
71     struct DeviceResourceAttr *attr = GetAttrInNode(node, attrName);
72     RETURN_DEFAULT_VALUE(attr, attrName, value, def);
73 
74     if (!HcsSwapToUint16(value, attr->value + HCS_PREFIX_LENGTH, HcsGetPrefix(attr->value))) {
75         *value = def;
76         HDF_LOGE("%s failed, incorrect prefix", __func__);
77         return HDF_FAILURE;
78     }
79     return HDF_SUCCESS;
80 }
81 
HcsGetUint32(const struct DeviceResourceNode * node,const char * attrName,uint32_t * value,uint32_t def)82 int32_t HcsGetUint32(const struct DeviceResourceNode *node, const char *attrName, uint32_t *value, uint32_t def)
83 {
84     struct DeviceResourceAttr *attr = GetAttrInNode(node, attrName);
85     RETURN_DEFAULT_VALUE(attr, attrName, value, def);
86 
87     if (!HcsSwapToUint32(value, attr->value + HCS_PREFIX_LENGTH, HcsGetPrefix(attr->value))) {
88         *value = def;
89         HDF_LOGE("%s failed, incorrect prefix", __func__);
90         return HDF_FAILURE;
91     }
92     return HDF_SUCCESS;
93 }
94 
HcsGetUint64(const struct DeviceResourceNode * node,const char * attrName,uint64_t * value,uint64_t def)95 int32_t HcsGetUint64(const struct DeviceResourceNode *node, const char *attrName, uint64_t *value, uint64_t def)
96 {
97     struct DeviceResourceAttr *attr = GetAttrInNode(node, attrName);
98     RETURN_DEFAULT_VALUE(attr, attrName, value, def);
99 
100     if (!HcsSwapToUint64(value, attr->value + HCS_PREFIX_LENGTH, HcsGetPrefix(attr->value))) {
101         *value = def;
102         HDF_LOGE("%s failed, incorrect prefix", __func__);
103         return HDF_FAILURE;
104     }
105     return HDF_SUCCESS;
106 }
107 
GetArrayElem(const struct DeviceResourceAttr * attr,uint32_t index)108 static const char *GetArrayElem(const struct DeviceResourceAttr *attr, uint32_t index)
109 {
110     int32_t offset = HCS_WORD_LENGTH + HCS_PREFIX_LENGTH;
111     uint16_t count;
112     uint32_t i;
113     if ((HcsGetPrefix(attr->value) != CONFIG_ARRAY) ||
114         !HcsSwapToUint16(&count, attr->value + HCS_PREFIX_LENGTH, CONFIG_WORD)) {
115         HDF_LOGE("%s failed, the attr of %s is not array", __func__, attr->name);
116         return NULL;
117     }
118     if (index >= count) {
119         HDF_LOGE("%s failed, index: %u >= count: %hu", __func__, index, count);
120         return NULL;
121     }
122     for (i = 0; i < index; i++) {
123         int32_t result = HcsGetDataTypeOffset(attr->value + offset);
124         if (result < 0) {
125             return NULL;
126         }
127         offset += result;
128     }
129     return attr->value + offset;
130 }
131 
HcsGetUint8ArrayElem(const struct DeviceResourceNode * node,const char * attrName,uint32_t index,uint8_t * value,uint8_t def)132 int32_t HcsGetUint8ArrayElem(const struct DeviceResourceNode *node, const char *attrName, uint32_t index,
133     uint8_t *value, uint8_t def)
134 {
135     const char *realValue = NULL;
136     struct DeviceResourceAttr *attr = GetAttrInNode(node, attrName);
137     RETURN_DEFAULT_VALUE(attr, attrName, value, def);
138 
139     realValue = GetArrayElem(attr, index);
140     if (realValue == NULL) {
141         *value = def;
142         HDF_LOGE("%s failed, the realValue is NULL", __func__);
143         return HDF_FAILURE;
144     }
145     if (!HcsSwapToUint8(value, realValue + HCS_PREFIX_LENGTH, HcsGetPrefix(realValue))) {
146         *value = def;
147         HDF_LOGE("%s failed, incorrect prefix", __func__);
148         return HDF_ERR_INVALID_OBJECT;
149     }
150     return HDF_SUCCESS;
151 }
152 
HcsGetUint16ArrayElem(const struct DeviceResourceNode * node,const char * attrName,uint32_t index,uint16_t * value,uint16_t def)153 int32_t HcsGetUint16ArrayElem(const struct DeviceResourceNode *node, const char *attrName, uint32_t index,
154     uint16_t *value, uint16_t def)
155 {
156     const char *realValue = NULL;
157     struct DeviceResourceAttr *attr = GetAttrInNode(node, attrName);
158     RETURN_DEFAULT_VALUE(attr, attrName, value, def);
159 
160     realValue = GetArrayElem(attr, index);
161     if (realValue == NULL) {
162         *value = def;
163         HDF_LOGE("%s failed, the realValue is NULL", __func__);
164         return HDF_FAILURE;
165     }
166     if (!HcsSwapToUint16(value, realValue + HCS_PREFIX_LENGTH, HcsGetPrefix(realValue))) {
167         *value = def;
168         HDF_LOGE("%s failed, incorrect prefix", __func__);
169         return HDF_ERR_INVALID_OBJECT;
170     }
171     return HDF_SUCCESS;
172 }
173 
HcsGetUint32ArrayElem(const struct DeviceResourceNode * node,const char * attrName,uint32_t index,uint32_t * value,uint32_t def)174 int32_t HcsGetUint32ArrayElem(const struct DeviceResourceNode *node, const char *attrName, uint32_t index,
175     uint32_t *value, uint32_t def)
176 {
177     const char *realValue = NULL;
178     struct DeviceResourceAttr *attr = GetAttrInNode(node, attrName);
179     RETURN_DEFAULT_VALUE(attr, attrName, value, def);
180 
181     realValue = GetArrayElem(attr, index);
182     if (realValue == NULL) {
183         *value = def;
184         HDF_LOGE("%s failed, the realValue is NULL", __func__);
185         return HDF_FAILURE;
186     }
187     if (!HcsSwapToUint32(value, realValue + HCS_PREFIX_LENGTH, HcsGetPrefix(realValue))) {
188         *value = def;
189         HDF_LOGE("%s failed, incorrect prefix", __func__);
190         return HDF_ERR_INVALID_OBJECT;
191     }
192     return HDF_SUCCESS;
193 }
194 
HcsGetUint64ArrayElem(const struct DeviceResourceNode * node,const char * attrName,uint32_t index,uint64_t * value,uint64_t def)195 int32_t HcsGetUint64ArrayElem(const struct DeviceResourceNode *node, const char *attrName, uint32_t index,
196     uint64_t *value, uint64_t def)
197 {
198     const char *realValue = NULL;
199     struct DeviceResourceAttr *attr = GetAttrInNode(node, attrName);
200     RETURN_DEFAULT_VALUE(attr, attrName, value, def);
201 
202     realValue = GetArrayElem(attr, index);
203     if ((realValue == NULL) || !HcsSwapToUint64(value, realValue + HCS_PREFIX_LENGTH, HcsGetPrefix(realValue))) {
204         *value = def;
205         HDF_LOGE("%s failed, invalid realValue (NULL) or incorrect prefix", __func__);
206         return HDF_FAILURE;
207     }
208     return HDF_SUCCESS;
209 }
210 
211 #define CONTINUE_RETURN_DIFFERENT_ERRNO(ret, result) do {              \
212     if ((result) == HDF_ERR_INVALID_OBJECT) {                          \
213         (ret) = HDF_ERR_INVALID_OBJECT;                                \
214         HDF_LOGE("%s failed, the result is %d", __func__, (result));   \
215         continue;                                                      \
216     } else if ((result) != HDF_SUCCESS) {                              \
217         HDF_LOGE("%s failed, the result is %d", __func__, (result));   \
218         return result;                                                 \
219     }                                                                  \
220 } while (0)
221 
HcsGetUint8Array(const struct DeviceResourceNode * node,const char * attrName,uint8_t * value,uint32_t len,uint8_t def)222 int32_t HcsGetUint8Array(const struct DeviceResourceNode *node, const char *attrName, uint8_t *value, uint32_t len,
223     uint8_t def)
224 {
225     int32_t ret = HDF_SUCCESS;
226     uint32_t i;
227     if ((value == NULL) || (len == 0)) {
228         HDF_LOGE("%s failed, parameter error, len: %u", __func__, len);
229         return HDF_FAILURE;
230     }
231 
232     for (i = 0; i < len; i++) {
233         int32_t result = HcsGetUint8ArrayElem(node, attrName, i, value + i, def);
234         // If the error type is HDF_ERR_INVALID_OBJECT, the error is recorded and returned after the loop exits.
235         CONTINUE_RETURN_DIFFERENT_ERRNO(ret, result);
236     }
237     return ret;
238 }
239 
HcsGetUint16Array(const struct DeviceResourceNode * node,const char * attrName,uint16_t * value,uint32_t len,uint16_t def)240 int32_t HcsGetUint16Array(const struct DeviceResourceNode *node, const char *attrName, uint16_t *value, uint32_t len,
241     uint16_t def)
242 {
243     int32_t ret = HDF_SUCCESS;
244     uint32_t i;
245     if ((value == NULL) || (len == 0)) {
246         HDF_LOGE("%s failed, parameter error, len: %u", __func__, len);
247         return HDF_FAILURE;
248     }
249 
250     for (i = 0; i < len; i++) {
251         int32_t result = HcsGetUint16ArrayElem(node, attrName, i, value + i, def);
252         // If the error type is HDF_ERR_INVALID_OBJECT, the error is recorded and returned after the loop exits.
253         CONTINUE_RETURN_DIFFERENT_ERRNO(ret, result);
254     }
255     return ret;
256 }
257 
HcsGetUint32Array(const struct DeviceResourceNode * node,const char * attrName,uint32_t * value,uint32_t len,uint32_t def)258 int32_t HcsGetUint32Array(const struct DeviceResourceNode *node, const char *attrName, uint32_t *value, uint32_t len,
259     uint32_t def)
260 {
261     int32_t ret = HDF_SUCCESS;
262     uint32_t i;
263     if ((value == NULL) || (len == 0)) {
264         HDF_LOGE("%s failed, parameter error, len: %u", __func__, len);
265         return HDF_FAILURE;
266     }
267 
268     for (i = 0; i < len; i++) {
269         int32_t result = HcsGetUint32ArrayElem(node, attrName, i, value + i, def);
270         // If the error type is HDF_ERR_INVALID_OBJECT, the error is recorded and returned after the loop exits.
271         CONTINUE_RETURN_DIFFERENT_ERRNO(ret, result);
272     }
273     return ret;
274 }
275 
HcsGetUint64Array(const struct DeviceResourceNode * node,const char * attrName,uint64_t * value,uint32_t len,uint64_t def)276 int32_t HcsGetUint64Array(const struct DeviceResourceNode *node, const char *attrName, uint64_t *value, uint32_t len,
277     uint64_t def)
278 {
279     uint32_t i;
280     if ((value == NULL) || (len == 0)) {
281         HDF_LOGE("%s failed, parameter error, len: %u", __func__, len);
282         return HDF_FAILURE;
283     }
284 
285     for (i = 0; i < len; i++) {
286         int32_t result = HcsGetUint64ArrayElem(node, attrName, i, value + i, def);
287         if (result != HDF_SUCCESS) {
288             HDF_LOGE("%s failed, the ret is %d", __func__, result);
289             return result;
290         }
291     }
292     return HDF_SUCCESS;
293 }
294 
HcsGetStringArrayElem(const struct DeviceResourceNode * node,const char * attrName,uint32_t index,const char ** value,const char * def)295 int32_t HcsGetStringArrayElem(const struct DeviceResourceNode *node, const char *attrName, uint32_t index,
296     const char **value, const char *def)
297 {
298     const char *realValue = NULL;
299     struct DeviceResourceAttr *attr = GetAttrInNode(node, attrName);
300     RETURN_DEFAULT_VALUE(attr, attrName, value, def);
301 
302     realValue = GetArrayElem(attr, index);
303     if ((realValue == NULL) || (HcsGetPrefix(realValue) != CONFIG_STRING)) {
304         *value = def;
305         HDF_LOGE("%s failed, %s attr is default value", __func__, attrName);
306         return HDF_FAILURE;
307     }
308     *value = realValue + HCS_PREFIX_LENGTH;
309     return HDF_SUCCESS;
310 }
311 
HcsGetString(const struct DeviceResourceNode * node,const char * attrName,const char ** value,const char * def)312 int32_t HcsGetString(const struct DeviceResourceNode *node, const char *attrName, const char **value, const char *def)
313 {
314     struct DeviceResourceAttr *attr = GetAttrInNode(node, attrName);
315     RETURN_DEFAULT_VALUE(attr, attrName, value, def);
316     if (HcsGetPrefix(attr->value) != CONFIG_STRING) {
317         *value = def;
318         HDF_LOGE("%s failed, incorrect prefix", __func__);
319         return HDF_FAILURE;
320     }
321     *value = attr->value + HCS_PREFIX_LENGTH;
322     return HDF_SUCCESS;
323 }
324 
HcsGetElemNum(const struct DeviceResourceNode * node,const char * attrName)325 int32_t HcsGetElemNum(const struct DeviceResourceNode *node, const char *attrName)
326 {
327     uint16_t num;
328     struct DeviceResourceAttr *attr = GetAttrInNode(node, attrName);
329     if ((attr == NULL) || (attr->value == NULL) || (HcsGetPrefix(attr->value) != CONFIG_ARRAY)) {
330         HDF_LOGE("%s failed, %s attr error", __func__, (attrName == NULL) ? "error attrName" : attrName);
331         return HDF_FAILURE;
332     }
333 
334     (void)HcsSwapToUint16(&num, attr->value + HCS_PREFIX_LENGTH, CONFIG_WORD);
335     return num;
336 }
337 
GetAttrValueInNode(const struct DeviceResourceNode * node,const char * attrValue)338 static struct DeviceResourceAttr *GetAttrValueInNode(const struct DeviceResourceNode *node, const char *attrValue)
339 {
340     struct DeviceResourceAttr *attr = NULL;
341     if ((node == NULL) || (attrValue == NULL)) {
342         return NULL;
343     }
344     for (attr = node->attrData; attr != NULL; attr = attr->next) {
345         if ((attr->value != NULL) && (strcmp(attr->value + HCS_PREFIX_LENGTH, attrValue) == 0) &&
346             (attr->name != NULL) && (strcmp(attr->name, HCS_MATCH_ATTR) == 0)) {
347             break;
348         }
349     }
350     return attr;
351 }
352 
TraverseTreeNode(const struct DeviceResourceNode * curNode)353 static const struct DeviceResourceNode *TraverseTreeNode(const struct DeviceResourceNode *curNode)
354 {
355     const struct DeviceResourceNode *nextNode = curNode;
356     while (nextNode->parent && !nextNode->sibling) {
357         nextNode = nextNode->parent;
358     }
359     nextNode = nextNode->sibling;
360     return nextNode;
361 }
362 
HcsGetNodeByMatchAttr(const struct DeviceResourceNode * node,const char * attrValue)363 const struct DeviceResourceNode *HcsGetNodeByMatchAttr(const struct DeviceResourceNode *node, const char *attrValue)
364 {
365     const struct DeviceResourceNode *curNode = NULL;
366     struct DeviceResourceIface *instance = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
367     if ((attrValue == NULL) || (instance == NULL) || (instance->GetRootNode == NULL)) {
368         HDF_LOGE("%s failed, attrValue or instance error", __func__);
369         return NULL;
370     }
371     curNode = (node != NULL) ? node : instance->GetRootNode();
372     while (curNode != NULL) {
373         if (GetAttrValueInNode(curNode, attrValue) != NULL) {
374             break;
375         }
376         curNode = (curNode->child != NULL) ? curNode->child : TraverseTreeNode(curNode);
377     }
378     return curNode;
379 }
380 
HcsGetChildNode(const struct DeviceResourceNode * node,const char * nodeName)381 const struct DeviceResourceNode *HcsGetChildNode(const struct DeviceResourceNode *node, const char *nodeName)
382 {
383     struct DeviceResourceNode *child = NULL;
384     if ((node == NULL) || (nodeName == NULL)) {
385         HDF_LOGE("%s failed, the node or nodeName is NULL", __func__);
386         return NULL;
387     }
388 
389     for (child = node->child; child != NULL; child = child->sibling) {
390         if ((child->name != NULL) && (strcmp(nodeName, child->name) == 0)) {
391             break;
392         }
393     }
394     return child;
395 }
396 
HcsGetNodeByRefAttr(const struct DeviceResourceNode * node,const char * attrName)397 const struct DeviceResourceNode *HcsGetNodeByRefAttr(const struct DeviceResourceNode *node, const char *attrName)
398 {
399     uint32_t attrValue;
400     struct DeviceResourceIface *instance = NULL;
401     const struct DeviceResourceNode *curNode = NULL;
402     struct DeviceResourceAttr *attr = GetAttrInNode(node, attrName);
403     if ((attr == NULL) || (attr->value == NULL) || (HcsGetPrefix(attr->value) != CONFIG_REFERENCE)) {
404         HDF_LOGE("%s failed, %s attr error", __func__, (attrName == NULL) ? "error attrName" : attrName);
405         return NULL;
406     }
407 
408     (void)HcsSwapToUint32(&attrValue, attr->value + HCS_PREFIX_LENGTH, CONFIG_DWORD);
409     instance = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
410     if ((instance == NULL) || (instance->GetRootNode == NULL)) {
411         HDF_LOGE("%s failed, DeviceResourceGetIfaceInstance error", __func__);
412         return NULL;
413     }
414     curNode = instance->GetRootNode();
415     while (curNode != NULL) {
416         if (curNode->hashValue == attrValue) {
417             break;
418         }
419         curNode = (curNode->child != NULL) ? curNode->child : TraverseTreeNode(curNode);
420     }
421     return curNode;
422 }
423