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_generate_tree.h"
10 #include "hcs_blob_if.h"
11 #include "hdf_log.h"
12 #include "osal_mem.h"
13
14 #define HDF_LOG_TAG hcs_generate_tree
15
GetParentNode(int32_t offset,const struct TreeStack * treeStack,int32_t * treeLayer,int32_t configOffset)16 static struct DeviceResourceNode *GetParentNode(int32_t offset, const struct TreeStack *treeStack,
17 int32_t *treeLayer, int32_t configOffset)
18 {
19 int32_t parentLayer = *treeLayer;
20 while ((parentLayer > 0) && (configOffset + offset > 0)) {
21 if (treeStack[parentLayer].offset >= (uint32_t)(configOffset + offset)) {
22 *treeLayer = parentLayer;
23 return treeStack[parentLayer].node;
24 }
25 parentLayer--;
26 }
27 return NULL;
28 }
29
CreateTreeNode(const char * start,int32_t offset,struct DeviceResourceNode * parentNode,char ** treeMem)30 static struct DeviceResourceNode *CreateTreeNode(const char *start, int32_t offset,
31 struct DeviceResourceNode *parentNode, char **treeMem)
32 {
33 struct DeviceResourceNode *newNode = (struct DeviceResourceNode *)(*treeMem);
34 struct DeviceResourceNode *curNode = NULL;
35 *treeMem += sizeof(struct DeviceResourceNode);
36 newNode->name = start + offset + HCS_PREFIX_LENGTH;
37 newNode->hashValue = (uint32_t)offset + sizeof(struct HbcHeader);
38 if (parentNode != NULL) {
39 newNode->parent = parentNode;
40 curNode = parentNode->child;
41 while ((curNode != NULL) && (curNode->sibling != NULL)) {
42 curNode = curNode->sibling;
43 }
44 if (curNode == NULL) {
45 parentNode->child = newNode;
46 } else {
47 curNode->sibling = newNode;
48 }
49 }
50 return newNode;
51 }
52
UpdateTreeStack(struct TreeStack ** treeStack,int32_t * treeLayer,struct DeviceResourceNode * newNode,uint32_t offset)53 static bool UpdateTreeStack(struct TreeStack **treeStack, int32_t *treeLayer, struct DeviceResourceNode *newNode,
54 uint32_t offset)
55 {
56 if (*treeLayer >= (TREE_STACK_MAX - 1)) {
57 HDF_LOGE("%s failed, the treeLayer error, treeLayer: %d", __func__, *treeLayer);
58 return false;
59 }
60 (*treeLayer)++;
61 (*treeStack)[*treeLayer].node = newNode;
62 (*treeStack)[*treeLayer].offset = offset;
63 return true;
64 }
65
AddAttrInNode(const char * start,struct DeviceResourceNode * parentNode,char ** treeMem)66 static bool AddAttrInNode(const char *start, struct DeviceResourceNode *parentNode, char **treeMem)
67 {
68 struct DeviceResourceAttr *newAttr = NULL;
69 struct DeviceResourceAttr *curAttr = NULL;
70 if (parentNode == NULL) {
71 HDF_LOGE("%s failed, the parentNode is NULL", __func__);
72 return false;
73 }
74 newAttr = (struct DeviceResourceAttr *)(*treeMem);
75 *treeMem += sizeof(struct DeviceResourceAttr);
76 newAttr->name = start + HCS_PREFIX_LENGTH;
77 newAttr->value = start + HCS_PREFIX_LENGTH + HCS_STRING_LENGTH(newAttr->name);
78 curAttr = parentNode->attrData;
79 parentNode->attrData = newAttr;
80 newAttr->next = curAttr;
81 return true;
82 }
83
ParseByteCode(const char * treeStart,int32_t offset,char ** treeMem,struct TreeStack ** treeStack,int32_t * treeLayerOrMemLen)84 static int32_t ParseByteCode(const char *treeStart, int32_t offset, char **treeMem,
85 struct TreeStack **treeStack, int32_t *treeLayerOrMemLen)
86 {
87 if (treeMem == NULL) {
88 HDF_LOGE("params invalid treeMem");
89 return HDF_ERR_INVALID_PARAM;
90 }
91 int32_t termOffset = HcsGetNodeOrAttrLength(treeStart + offset);
92 struct DeviceResourceNode *parentOrCurNode = NULL;
93 struct DeviceResourceNode *newNode = NULL;
94 uint32_t newNodeOffset;
95 if (termOffset <= 0) {
96 HDF_LOGE("%s failed, HcsGetNodeOrAttrLength error, errno: %d", __func__, termOffset);
97 return HDF_FAILURE;
98 }
99
100 switch (HcsGetPrefix(treeStart + offset)) {
101 case CONFIG_NODE:
102 if (*treeMem == NULL) {
103 *treeLayerOrMemLen += sizeof(struct DeviceResourceNode);
104 break;
105 }
106 parentOrCurNode = GetParentNode(offset, *treeStack, treeLayerOrMemLen, termOffset);
107 newNode = CreateTreeNode(treeStart, offset, parentOrCurNode, treeMem);
108 (void)HcsSwapToUint32(&newNodeOffset, treeStart + offset + HCS_STRING_LENGTH(newNode->name) +
109 HCS_PREFIX_LENGTH, CONFIG_DWORD);
110 newNodeOffset += (uint32_t)(offset + termOffset);
111 if (!UpdateTreeStack(treeStack, treeLayerOrMemLen, newNode, newNodeOffset)) {
112 return HDF_FAILURE;
113 }
114 break;
115 case CONFIG_ATTR:
116 if (*treeMem == NULL) {
117 *treeLayerOrMemLen += sizeof(struct DeviceResourceAttr);
118 break;
119 }
120 parentOrCurNode = GetParentNode(offset, *treeStack, treeLayerOrMemLen, termOffset);
121 if (!AddAttrInNode(treeStart + offset, parentOrCurNode, treeMem)) {
122 HDF_LOGE("%s failed, AddAttrInNode error", __func__);
123 return HDF_FAILURE;
124 }
125 break;
126 default:
127 termOffset = HDF_FAILURE;
128 break;
129 }
130 return termOffset;
131 }
132
GenerateCfgTree(const char * treeStart,int32_t length,char * treeMem,struct DeviceResourceNode ** root)133 int32_t GenerateCfgTree(const char *treeStart, int32_t length, char *treeMem, struct DeviceResourceNode **root)
134 {
135 int32_t offset = 0;
136 int32_t treeLayerOrMemLen = 0;
137
138 struct TreeStack *treeStack = (struct TreeStack *)OsalMemCalloc(sizeof(struct TreeStack) * TREE_STACK_MAX);
139 if (treeStack == NULL) {
140 HDF_LOGE("%s failed, treeStack malloc error", __func__);
141 return HDF_FAILURE;
142 }
143
144 while ((offset < length) && (offset >= 0)) {
145 int32_t eachOffset = ParseByteCode(treeStart, offset, &treeMem, &treeStack, &treeLayerOrMemLen);
146 if (eachOffset <= 0) {
147 HDF_LOGE("%s failed, ParseByteCode error", __func__);
148 treeLayerOrMemLen = eachOffset;
149 break;
150 }
151 offset += eachOffset;
152 }
153 if ((treeMem != NULL) && (root != NULL) && (treeLayerOrMemLen > 0)) {
154 // The treeStack[1] is root
155 *root = treeStack[1].node;
156 }
157 OsalMemFree(treeStack);
158 return treeLayerOrMemLen;
159 }
160