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