• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     int32_t termOffset = HcsGetNodeOrAttrLength(treeStart + offset);
88     struct DeviceResourceNode *parentOrCurNode = NULL;
89     struct DeviceResourceNode *newNode = NULL;
90     uint32_t newNodeOffset;
91     if (termOffset <= 0) {
92         HDF_LOGE("%s failed, HcsGetNodeOrAttrLength error, errno: %d", __func__, termOffset);
93         return HDF_FAILURE;
94     }
95 
96     switch (HcsGetPrefix(treeStart + offset)) {
97         case CONFIG_NODE:
98             if (*treeMem == NULL) {
99                 *treeLayerOrMemLen += sizeof(struct DeviceResourceNode);
100                 break;
101             }
102             parentOrCurNode = GetParentNode(offset, *treeStack, treeLayerOrMemLen, termOffset);
103             newNode = CreateTreeNode(treeStart, offset, parentOrCurNode, treeMem);
104             (void)HcsSwapToUint32(&newNodeOffset, treeStart + offset + HCS_STRING_LENGTH(newNode->name) +
105                 HCS_PREFIX_LENGTH, CONFIG_DWORD);
106             newNodeOffset += (uint32_t)(offset + termOffset);
107             if (!UpdateTreeStack(treeStack, treeLayerOrMemLen, newNode, newNodeOffset)) {
108                 return HDF_FAILURE;
109             }
110             break;
111         case CONFIG_ATTR:
112             if (*treeMem == NULL) {
113                 *treeLayerOrMemLen += sizeof(struct DeviceResourceAttr);
114                 break;
115             }
116             parentOrCurNode = GetParentNode(offset, *treeStack, treeLayerOrMemLen, termOffset);
117             if (!AddAttrInNode(treeStart + offset, parentOrCurNode, treeMem)) {
118                 HDF_LOGE("%s failed, AddAttrInNode error", __func__);
119                 return HDF_FAILURE;
120             }
121             break;
122         default:
123             termOffset = HDF_FAILURE;
124             break;
125     }
126     return termOffset;
127 }
128 
GenerateCfgTree(const char * treeStart,int32_t length,char * treeMem,struct DeviceResourceNode ** root)129 int32_t GenerateCfgTree(const char *treeStart, int32_t length, char *treeMem, struct DeviceResourceNode **root)
130 {
131     int32_t offset = 0;
132     int32_t treeLayerOrMemLen = 0;
133 
134     struct TreeStack *treeStack = (struct TreeStack *)OsalMemCalloc(sizeof(struct TreeStack) * TREE_STACK_MAX);
135     if (treeStack == NULL) {
136         HDF_LOGE("%s failed, treeStack malloc error", __func__);
137         return HDF_FAILURE;
138     }
139 
140     while ((offset < length) && (offset >= 0)) {
141         int32_t eachOffset = ParseByteCode(treeStart, offset, &treeMem, &treeStack, &treeLayerOrMemLen);
142         if (eachOffset <= 0) {
143             HDF_LOGE("%s failed, ParseByteCode error", __func__);
144             treeLayerOrMemLen = eachOffset;
145             break;
146         }
147         offset += eachOffset;
148     }
149     if ((treeMem != NULL) && (root != NULL) && (treeLayerOrMemLen > 0)) {
150         // The treeStack[1] is root
151         *root = treeStack[1].node;
152     }
153     OsalMemFree(treeStack);
154     return treeLayerOrMemLen;
155 }
156