• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-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 <stdio.h>
17 #include <stdint.h>
18 #include <stdlib.h>
19 #include <errno.h>
20 #include <string.h>
21 #include <limits.h>
22 #include <sys/stat.h>
23 #include "securec.h"
24 #include "cJSON.h"
25 #include "endian_internal.h"
26 #include "create_pcid.h"
27 #include "context_tool.h"
28 
29 #ifdef SYSCAP_DEFINE_EXTERN_ENABLE
30 #include "syscap_define_custom.h"
31 #else
32 #include "syscap_define.h"
33 #endif
34 
35 #define SYSCAP_PREFIX_LEN 17
36 #define SINGLE_FEAT_LEN (SINGLE_SYSCAP_LEN - SYSCAP_PREFIX_LEN)
37 #define PCID_OUT_BUFFER 32
38 #define PRIVATE_SYSCAP_SIZE 1000
39 #define UINT8_BIT 8
40 
41 #define U32_TO_STR_MAX_LEN 11
42 #define FREE_CREATE_PCID_BUFFER_OUT 1
43 
44 #define FREE_DECODE_PCID_CONVERT_OUT 1
45 #define FREE_DECODE_PCID_ROOT_OUT 2
46 #define FREE_DECODE_PCID_SYSCAP_OUT 3
47 #define FREE_DECODE_PCID_CONTEXT_OUT 4
48 
49 #define ENCODE_PCID_OUTPUT 1
50 #define FREE_ENCODE_PCID_OUT 2
51 #define FREE_ENCODE_PCID_PRISYSCAP_FULL_OUT 3
52 #define FREE_ENCODE_PCID_CONTEXT_OUT 4
53 
54 struct FreeEncodePcidInfo {
55     char *output;
56     char *priSyscapFull;
57     char *contextBuffer;
58     char *outDirPathFinal;
59 };
60 
61 
62 struct FreeDecodePcidJsonInfo {
63     char *strJson;
64     char *contextBuffer;
65     cJSON *jsonRootObj;
66     cJSON *sysCapObj;
67     int32_t flag;
68 };
69 
SetOsSyscap(PCIDMain * pcidBuffer,uint32_t osCapSize,const cJSON * jsonOsSyscapObj,const cJSON * allOsSyscapObj)70 int32_t SetOsSyscap(PCIDMain *pcidBuffer, uint32_t osCapSize,
71                     const cJSON *jsonOsSyscapObj, const cJSON *allOsSyscapObj)
72 {
73     int32_t sectorOfBits, posOfBits;
74     cJSON *jsonArrayItem = NULL;
75     cJSON *osCapIndex = NULL;
76 
77     for (uint32_t i = 0; i < osCapSize; i++) {
78         jsonArrayItem = cJSON_GetArrayItem(jsonOsSyscapObj, (int)i);
79         if (jsonArrayItem == NULL || !cJSON_IsString(jsonArrayItem)) {
80             PRINT_ERR("Get jsonArrayItem failed.");
81             return -1;
82         }
83         osCapIndex = cJSON_GetObjectItem(allOsSyscapObj, jsonArrayItem->valuestring);
84         if (osCapIndex == NULL) {
85             PRINT_ERR("can't find the syscap: %s, please add it in syscap_define.h.\n", jsonArrayItem->valuestring);
86             return -1;
87         }
88         if (!cJSON_IsNumber(osCapIndex)) {
89             PRINT_ERR("Get osCapIndex failed.");
90             return -1;
91         }
92         sectorOfBits = (osCapIndex->valueint) / UINT8_BIT;
93         posOfBits = (osCapIndex->valueint) % UINT8_BIT;
94         if (sectorOfBits >= OS_SYSCAP_BYTES) {
95             PRINT_ERR("num of \"os syscap\" is out of 960\n");
96             return -1;
97         }
98         pcidBuffer->osSyscap[sectorOfBits] |= 1 << (posOfBits);
99     }
100 
101     return 0;
102 }
103 
SetPriSyscap(PCIDMain * pcidBuffer,cJSON * jsonPriSyscapObj,uint32_t privateCapSize,uint16_t allPriSyscapStrLen)104 int32_t SetPriSyscap(PCIDMain *pcidBuffer, cJSON *jsonPriSyscapObj,
105                      uint32_t privateCapSize, uint16_t allPriSyscapStrLen)
106 {
107     char *priSyscapHead = (char *)(pcidBuffer + 1);
108     char *priSyscapStr = NULL;
109     for (uint32_t i = 0; i < privateCapSize; i++) {
110         cJSON *jsonArrayItem = cJSON_GetArrayItem(jsonPriSyscapObj, (int)i);
111         if (jsonArrayItem == NULL || !cJSON_IsString(jsonArrayItem)) {
112             PRINT_ERR("get jsonArrayItem failed!");
113             return -1;
114         }
115         priSyscapStr = strchr(jsonArrayItem->valuestring, '.') + 1;
116         errno_t nRet = strcat_s(priSyscapHead, allPriSyscapStrLen + 1, priSyscapStr);
117         nRet += strcat_s(priSyscapHead, allPriSyscapStrLen + 1, ",");
118         if (nRet != EOK) {
119             PRINT_ERR("strcat_s \"pri\" string is failed\n");
120             return -1;
121         }
122     }
123     return 0;
124 }
125 
SetPCIDHeader(PCIDMain * pcidBuffer,const cJSON * jsonRootObj)126 int32_t SetPCIDHeader(PCIDMain *pcidBuffer, const cJSON *jsonRootObj)
127 {
128     cJSON *jsonSyscapObj = cJSON_GetObjectItem(jsonRootObj, "api_version");
129     if (jsonSyscapObj == NULL || !cJSON_IsNumber(jsonSyscapObj)) {
130         PRINT_ERR("get \"api_version\" failed\n");
131         return -1;
132     }
133     pcidBuffer->apiVersion = HtonsInter((uint16_t)jsonSyscapObj->valueint);
134     pcidBuffer->apiVersionType = 0;
135 
136     jsonSyscapObj = cJSON_GetObjectItem(jsonRootObj, "system_type");
137     if (jsonSyscapObj == NULL || !cJSON_IsString(jsonSyscapObj)) {
138         PRINT_ERR("get \"system_type\" failed\n");
139         return -1;
140     }
141     char *systemType = jsonSyscapObj->valuestring;
142     pcidBuffer->systemType = !strcmp(systemType, "mini") ? 0b001 :
143                              (!strcmp(systemType, "small") ? 0b010 :
144                               (!strcmp(systemType, "standard") ? 0b100 : 0));
145     if (pcidBuffer->systemType == 0) {
146         PRINT_ERR("\"system_type\" is invaild, systemType = \"%s\"\n", systemType);
147         return -1;
148     }
149 
150     jsonSyscapObj = cJSON_GetObjectItem(jsonRootObj, "manufacturer_id");
151     if (jsonSyscapObj == NULL || !cJSON_IsNumber(jsonSyscapObj)) {
152         PRINT_ERR("get \"manufacturer_id\" failed\n");
153         return -1;
154     }
155     pcidBuffer->manufacturerID = HtonlInter((uint32_t)jsonSyscapObj->valueint);
156 
157     return 0;
158 }
159 
GetOsAndPriSyscapSize(const cJSON * osSyscap,const cJSON * priSyscap,uint32_t * osCapSize,uint32_t * privateCapSize)160 int32_t GetOsAndPriSyscapSize(const cJSON *osSyscap, const cJSON *priSyscap,
161                               uint32_t *osCapSize, uint32_t *privateCapSize)
162 {
163     *osCapSize = 0;
164     *privateCapSize = 0;
165 
166     // get os syscap size
167     if (osSyscap == NULL || !cJSON_IsArray(osSyscap)) {
168         PRINT_ERR("get \"os\" array failed\n");
169         return -1;
170     }
171     int32_t ret = cJSON_GetArraySize(osSyscap);
172     if (ret < 0) {
173         PRINT_ERR("get \"os\" array size failed\n");
174         return -1;
175     }
176     *osCapSize = (uint32_t)ret;
177 
178     // get private syscap size
179     if (priSyscap != NULL && cJSON_IsArray(priSyscap)) {
180         ret = cJSON_GetArraySize(priSyscap);
181         if (ret < 0) {
182             PRINT_ERR("get \"private syscap\" array size failed\n");
183             return -1;
184         }
185         *privateCapSize = (uint32_t)ret;
186     } else if (priSyscap == NULL) {
187         *privateCapSize = 0;
188     } else {
189         PRINT_ERR("get \"private\" array failed\n");
190         return -1;
191     }
192 
193     return 0;
194 }
195 
GetPriSyscapLen(uint32_t privateCapSize,cJSON * jsonPriSyscapObj,uint16_t * len)196 int32_t GetPriSyscapLen(uint32_t privateCapSize, cJSON *jsonPriSyscapObj, uint16_t *len)
197 {
198     for (uint32_t i = 0; i < privateCapSize; i++) {
199         cJSON *jsonArrayItem = cJSON_GetArrayItem(jsonPriSyscapObj, (int)i);
200         if (jsonArrayItem == NULL || !cJSON_IsString(jsonArrayItem)) {
201             PRINT_ERR("Get jsonArrayItem failed.");
202             return -1;
203         }
204         *len += (uint16_t)strlen(strchr(jsonArrayItem->valuestring, '.') + 1);
205         (*len)++;  // for separator ','
206     }
207     if ((*len + 1) > PRIVATE_SYSCAP_SIZE) {
208         PRINT_ERR("context of \"pri\" array is too many.\n");
209         return -1;
210     }
211     return 0;
212 }
213 
CheckConvertedContextSaveAsFile(char * outDirPath,PCIDMain * pcidBuffer,uint16_t pcidLength,int32_t ret)214 static int32_t CheckConvertedContextSaveAsFile(char *outDirPath, PCIDMain *pcidBuffer, uint16_t pcidLength, int32_t ret)
215 {
216     const char pcidFileName[] = "PCID.sc";
217     ret = ConvertedContextSaveAsFile(outDirPath, pcidFileName, (char *)pcidBuffer, pcidLength);
218     if (ret != 0) {
219         PRINT_ERR("Save as file failed, outDirPath:%s, filename:%s\n", outDirPath, pcidFileName);
220     }
221     return ret;
222 }
223 
FreeAfterCreatePCID(PCIDMain * pcidBuffer,cJSON * allOsSyscapObj,char * contextBuffer,int32_t type,int32_t ret)224 static int32_t FreeAfterCreatePCID(PCIDMain *pcidBuffer, cJSON *allOsSyscapObj, char *contextBuffer,
225         int32_t type, int32_t ret)
226 {
227     if (type == FREE_CREATE_PCID_BUFFER_OUT) {
228         free(pcidBuffer);
229     }
230     cJSON_Delete(allOsSyscapObj);
231     FreeContextBuffer(contextBuffer);
232     return ret;
233 }
234 
CreatePCID(char * inputFile,char * outDirPath)235 int32_t CreatePCID(char *inputFile, char *outDirPath)
236 {
237     uint32_t privateCapSize, osCapSize;
238     uint32_t contextBufLen;
239     char *contextBuffer = NULL;
240     cJSON *allOsSyscapObj = CreateWholeSyscapJsonObj();
241 
242     int32_t ret = GetFileContext(inputFile, &contextBuffer, (uint32_t *)&contextBufLen);
243     if (ret != 0) {
244         PRINT_ERR("GetFileContext failed, input file : %s\n", inputFile);
245         return FreeAfterCreatePCID(NULL, allOsSyscapObj, contextBuffer, 0, -1);
246     }
247 
248     cJSON *jsonRootObj = cJSON_ParseWithLength(contextBuffer, contextBufLen);
249     if (jsonRootObj == NULL) {
250         PRINT_ERR("cJSON_Parse failed, context buffer is:\n%s\n", contextBuffer);
251         return FreeAfterCreatePCID(NULL, allOsSyscapObj, contextBuffer, 0, -1);
252     }
253 
254     cJSON *jsonSyscapObj = cJSON_GetObjectItem(jsonRootObj, "syscap");
255     if (jsonSyscapObj == NULL || !cJSON_IsObject(jsonSyscapObj)) {
256         PRINT_ERR("get \"syscap\" object failed\n");
257         return FreeAfterCreatePCID(NULL, allOsSyscapObj, contextBuffer, 0, -1);
258     }
259 
260     cJSON *jsonOsSyscapObj = cJSON_GetObjectItem(jsonSyscapObj, "os");
261     cJSON *jsonPriSyscapObj = cJSON_GetObjectItem(jsonSyscapObj, "private");
262     ret = GetOsAndPriSyscapSize(jsonOsSyscapObj, jsonPriSyscapObj, &osCapSize, &privateCapSize);
263     if (ret != 0) {
264         return FreeAfterCreatePCID(NULL, allOsSyscapObj, contextBuffer, 0, ret);
265     }
266 
267     uint16_t allPriSyscapStrLen = 0;
268     ret = GetPriSyscapLen(privateCapSize, jsonPriSyscapObj, &allPriSyscapStrLen);
269     if (ret != 0) {
270         return FreeAfterCreatePCID(NULL, allOsSyscapObj, contextBuffer, 0, ret);
271     }
272 
273     uint16_t pcidLength = sizeof(PCIDMain) + allPriSyscapStrLen + 1;
274     PCIDMain *pcidBuffer = (PCIDMain *)malloc(pcidLength);
275     if (pcidBuffer == NULL) {
276         PRINT_ERR("malloc for pcid buffer failed\n");
277         return FreeAfterCreatePCID(NULL, allOsSyscapObj, contextBuffer, 0, -1);
278     }
279     (void)memset_s(pcidBuffer, pcidLength, 0, pcidLength);
280 
281     ret = SetOsSyscap(pcidBuffer, osCapSize, jsonOsSyscapObj, allOsSyscapObj);
282     ret += SetPriSyscap(pcidBuffer, jsonPriSyscapObj, privateCapSize, allPriSyscapStrLen);
283     ret += SetPCIDHeader(pcidBuffer, jsonRootObj);
284     if (ret != 0) {
285         return FreeAfterCreatePCID(pcidBuffer, allOsSyscapObj, contextBuffer, FREE_CREATE_PCID_BUFFER_OUT, ret);
286     }
287 
288     ret = CheckConvertedContextSaveAsFile(outDirPath, pcidBuffer, pcidLength, ret);
289     return FreeAfterCreatePCID(pcidBuffer, allOsSyscapObj, contextBuffer, FREE_CREATE_PCID_BUFFER_OUT, ret);
290 }
291 
GetOsSyscap(PCIDMain * pcidMain,cJSON * sysCapObject)292 int32_t GetOsSyscap(PCIDMain *pcidMain, cJSON *sysCapObject)
293 {
294     uint32_t i, j, countOfSyscap = 0;
295     uint8_t osSyscap[OS_SYSCAP_BYTES] = {0};
296     uint16_t indexOfSyscap[OS_SYSCAP_BYTES * UINT8_BIT] = {0};
297 
298     cJSON *capVectorPtr = cJSON_CreateArray();
299     if (capVectorPtr == NULL) {
300         PRINT_ERR("cJSON_CreateArray failed\n");
301         return -1;
302     }
303 
304     // 8, bytes of pcid header
305     errno_t nRet = memcpy_s(osSyscap, OS_SYSCAP_BYTES, (uint8_t *)pcidMain + 8, OS_SYSCAP_BYTES);
306     if (nRet != EOK) {
307         PRINT_ERR("memcpy_s failed.");
308         return -1;
309     }
310 
311     for (i = 0; i < OS_SYSCAP_BYTES; i++) {
312         for (j = 0; j < UINT8_BIT; j++) {
313             if (osSyscap[i] & (0x01 << j)) {
314                 indexOfSyscap[countOfSyscap++] = i * UINT8_BIT + j;
315             }
316         }
317     }
318     for (i = 0; i < countOfSyscap; i++) {
319         for (j = 0; j < sizeof(g_arraySyscap) / sizeof(SyscapWithNum); j++) {
320             if (g_arraySyscap[j].num != indexOfSyscap[i]) {
321                 continue;
322             }
323             if (!cJSON_AddItemToArray(capVectorPtr, cJSON_CreateString(g_arraySyscap[j].str))) {
324                 printf("cJSON_AddItemToArray or cJSON_CreateString failed\n");
325                 return -1;
326             }
327         }
328     }
329 
330     if (!cJSON_AddItemToObject(sysCapObject, "os", capVectorPtr)) {
331         PRINT_ERR("cJSON_AddItemToObject failed\n");
332         return -1;
333     }
334 
335     return 0;
336 }
337 
GetPriSyscap(PCIDMain * pcidMain,cJSON * sysCapObject,size_t contextBufLen)338 int32_t GetPriSyscap(PCIDMain *pcidMain, cJSON *sysCapObject, size_t contextBufLen)
339 {
340     cJSON *capVectorPtr = cJSON_CreateArray();
341     if (capVectorPtr == NULL) {
342         PRINT_ERR("cJSON_CreateArray failed\n");
343         return -1;
344     }
345 
346     int32_t privateSyscapLen = (int32_t)(contextBufLen - sizeof(PCIDMain) - 1);
347     if (privateSyscapLen < 0) {
348         PRINT_ERR("parse private syscap failed.");
349         return -1;
350     } else if (privateSyscapLen == 0) {
351         return 0;
352     }
353 
354     char fullCapStr[SINGLE_SYSCAP_LEN] = {0};
355     char priSyscapStr[SINGLE_SYSCAP_LEN] = {0};
356     char *tempPriSyscapStr = priSyscapStr;
357     char *ptrPrivateSyscap = (char *)(pcidMain + 1);
358     while (*ptrPrivateSyscap != '\0') {
359         if (*ptrPrivateSyscap == ',') {
360             *tempPriSyscapStr = '\0';
361             int32_t ret = sprintf_s(fullCapStr, SINGLE_SYSCAP_LEN, "SystemCapability.%s", priSyscapStr);
362             if (ret == -1) {
363                 printf("sprintf_s failed\n");
364                 return -1;
365             }
366             if (!cJSON_AddItemToArray(capVectorPtr, cJSON_CreateString(fullCapStr))) {
367                 printf("cJSON_AddItemToArray or cJSON_CreateString failed\n");
368                 return -1;
369             }
370             tempPriSyscapStr = priSyscapStr;
371             ptrPrivateSyscap++;
372             continue;
373         }
374         *tempPriSyscapStr++ = *ptrPrivateSyscap++;
375     }
376     if (!cJSON_AddItemToObject(sysCapObject, "private", capVectorPtr)) {
377         PRINT_ERR("cJSON_AddItemToObject failed\n");
378         return -1;
379     }
380 
381     return 0;
382 }
383 
CheckSysCapObj(struct FreeDecodePcidJsonInfo freePcidJsonInfo,PCIDMain * pcidMain,uint32_t contextBufLen,int32_t ret)384 static int32_t CheckSysCapObj(struct FreeDecodePcidJsonInfo freePcidJsonInfo, PCIDMain *pcidMain,
385         uint32_t contextBufLen, int32_t ret)
386 {
387     if (freePcidJsonInfo.sysCapObj == NULL) {
388         PRINT_ERR("cJSON_CreateObject failed\n");
389         freePcidJsonInfo.flag = -1;
390         return -1;
391     }
392     if (GetOsSyscap(pcidMain, freePcidJsonInfo.sysCapObj) != 0) {
393         freePcidJsonInfo.flag = -1;
394         return ret;
395     }
396     if (GetPriSyscap(pcidMain, freePcidJsonInfo.sysCapObj, contextBufLen) != 0) {
397         freePcidJsonInfo.flag = -1;
398     }
399     return ret;
400 }
401 
CheckJsonRootObj(struct FreeDecodePcidJsonInfo freePcidJsonInfo,PCIDMain * pcidMain,char * systemType)402 static int32_t CheckJsonRootObj(struct FreeDecodePcidJsonInfo freePcidJsonInfo, PCIDMain *pcidMain, char *systemType)
403 {
404     if (!cJSON_AddNumberToObject(freePcidJsonInfo.jsonRootObj, "api_version", NtohsInter(pcidMain->apiVersion))) {
405         PRINT_ERR("cJSON_AddNumberToObject failed\n");
406         return -1;
407     }
408     if (!cJSON_AddNumberToObject(freePcidJsonInfo.jsonRootObj, "manufacturer_id",
409                                  NtohlInter(pcidMain->manufacturerID))) {
410         PRINT_ERR("cJSON_AddNumberToObject failed\n");
411         return -1;
412     }
413     if (!cJSON_AddStringToObject(freePcidJsonInfo.jsonRootObj, "system_type", systemType)) {
414         PRINT_ERR("cJSON_AddStringToObject failed\n");
415         return -1;
416     }
417     if (!cJSON_AddItemToObject(freePcidJsonInfo.jsonRootObj, "syscap", freePcidJsonInfo.sysCapObj)) {
418         PRINT_ERR("cJSON_AddItemToObject failed\n");
419         return -1;
420     }
421     return 0;
422 }
423 
FreeAfterDecodePCID(struct FreeDecodePcidJsonInfo freePcidJsonInfo,int32_t type,int32_t ret)424 static int32_t FreeAfterDecodePCID(struct FreeDecodePcidJsonInfo freePcidJsonInfo, int32_t type, int32_t ret)
425 {
426     switch (type) {
427         case FREE_DECODE_PCID_CONVERT_OUT:
428             free(freePcidJsonInfo.strJson);
429             cJSON_Delete(freePcidJsonInfo.jsonRootObj);
430             cJSON_Delete(freePcidJsonInfo.sysCapObj);
431             FreeContextBuffer(freePcidJsonInfo.contextBuffer);
432             break;
433         case FREE_DECODE_PCID_ROOT_OUT:
434             cJSON_Delete(freePcidJsonInfo.jsonRootObj);
435             cJSON_Delete(freePcidJsonInfo.sysCapObj);
436             FreeContextBuffer(freePcidJsonInfo.contextBuffer);
437             break;
438         case FREE_DECODE_PCID_SYSCAP_OUT:
439             cJSON_Delete(freePcidJsonInfo.sysCapObj);
440             FreeContextBuffer(freePcidJsonInfo.contextBuffer);
441             break;
442         case FREE_DECODE_PCID_CONTEXT_OUT:
443         default:
444             FreeContextBuffer(freePcidJsonInfo.contextBuffer);
445     }
446     return ret;
447 }
448 
DecodePCID(char * inputFile,char * outDirPath)449 int32_t DecodePCID(char *inputFile, char *outDirPath)
450 {
451     int32_t ret = 0;
452     uint32_t contextBufLen;
453     struct FreeDecodePcidJsonInfo freePcidJsonInfo;
454     freePcidJsonInfo.strJson = NULL;
455     freePcidJsonInfo.contextBuffer = NULL;
456     freePcidJsonInfo.jsonRootObj = NULL;
457     freePcidJsonInfo.sysCapObj = NULL;
458     freePcidJsonInfo.flag = 0;
459 
460     ret = GetFileContext(inputFile, &freePcidJsonInfo.contextBuffer, (uint32_t *)&contextBufLen);
461     if (ret != 0) {
462         PRINT_ERR("GetFileContext failed, input file : %s\n", inputFile);
463         return -1;
464     }
465 
466     PCIDMain *pcidMain = (PCIDMain *)freePcidJsonInfo.contextBuffer;
467 
468     /* api version */
469     if (pcidMain->apiVersionType != 0) {
470         PRINT_ERR("Prase file failed, apiVersionType is invaild, input file : %s\n", inputFile);
471         return FreeAfterDecodePCID(freePcidJsonInfo, FREE_DECODE_PCID_CONTEXT_OUT, -1);
472     }
473 
474     /* system type */
475     char *systemType = pcidMain->systemType == 0b001 ? "mini" :
476                        (pcidMain->systemType == 0b010 ? "small" :
477                         (pcidMain->systemType == 0b100 ? "standard" : NULL));
478     if (systemType == NULL) {
479         PRINT_ERR("prase file failed, systemType is invaild, %u\n", pcidMain->systemType);
480         return FreeAfterDecodePCID(freePcidJsonInfo, FREE_DECODE_PCID_CONTEXT_OUT, -1);
481     }
482 
483     /* syscap */
484     freePcidJsonInfo.sysCapObj = cJSON_CreateObject();
485     ret = CheckSysCapObj(freePcidJsonInfo, pcidMain, contextBufLen, ret);
486     if (freePcidJsonInfo.flag == -1) {
487         return FreeAfterDecodePCID(freePcidJsonInfo, FREE_DECODE_PCID_CONTEXT_OUT, ret);
488     }
489 
490     // create json root
491     freePcidJsonInfo.jsonRootObj = cJSON_CreateObject();
492     if (freePcidJsonInfo.jsonRootObj == NULL) {
493         PRINT_ERR("cJSON_CreateObject failed\n");
494         return FreeAfterDecodePCID(freePcidJsonInfo, FREE_DECODE_PCID_SYSCAP_OUT, -1);
495     }
496 
497     ret = CheckJsonRootObj(freePcidJsonInfo, pcidMain, systemType);
498     if (ret == -1) {
499         return FreeAfterDecodePCID(freePcidJsonInfo, FREE_DECODE_PCID_ROOT_OUT, ret);
500     }
501 
502     freePcidJsonInfo.sysCapObj = NULL; // avoid being released repeatedly.
503 
504     char *strJson = cJSON_Print(freePcidJsonInfo.jsonRootObj);
505     const char outputFileName[] = "PCID.json";
506     ret = ConvertedContextSaveAsFile(outDirPath, outputFileName, strJson, strlen(strJson));
507     if (ret != 0) {
508         PRINT_ERR("ConvertedContextSaveAsFile failed, outDirPath:%s, filename:%s\n", outDirPath, outputFileName);
509     }
510     return FreeAfterDecodePCID(freePcidJsonInfo, FREE_DECODE_PCID_CONVERT_OUT, ret);
511 }
512 
513 #define U32_TO_STR_MAX_LEN 11
514 #define OS_SYSCAP_NUM 30
515 #define PCID_HEADER 2
ParseStringSyscap(char * input,uint32_t * osSyscap,uint32_t osSyscapNum,uint32_t * header,uint32_t headerLen)516 static int32_t ParseStringSyscap(char *input, uint32_t *osSyscap, uint32_t osSyscapNum,
517                                  uint32_t *header, uint32_t headerLen)
518 {
519     int32_t ret;
520     uint32_t tempNum;
521     uint32_t i = 0;
522     size_t inputLen = strlen(input);
523 
524     if (osSyscapNum != OS_SYSCAP_NUM || headerLen != PCID_HEADER) {
525         PRINT_ERR("Input osSyscapNum(%u) or headerLen(%u) error.\n", osSyscapNum, headerLen);
526         return -1;
527     }
528 
529     if (sscanf_s(input, "%u,%u,%s", &header[0], &header[1], input, inputLen) != 3) { // 3, return val of "%u,%u,%s"
530         PRINT_ERR("Get pcid header failed.\n");
531         return -1;
532     }
533 
534     while ((ret = sscanf_s(input, "%u,%s", &tempNum, input, inputLen)) > 0) {
535         osSyscap[i++] = tempNum;
536         if (i >= OS_SYSCAP_NUM) {
537             break;
538         }
539     }
540     if (ret == -1) {
541         PRINT_ERR("sscanf_s failed, i = %u.\n", i);
542         return -1;
543     }
544 
545     if (strlen(input) <= 1) {
546         *input = '\0';
547     }
548 
549     return 0;
550 }
551 
AddHeaderToJsonObj(uint32_t * pcidHeader,uint32_t pcidHeaderLen,cJSON * rootObj)552 static int32_t AddHeaderToJsonObj(uint32_t *pcidHeader, uint32_t pcidHeaderLen, cJSON *rootObj)
553 {
554     if (pcidHeaderLen != PCID_HEADER) {
555         PRINT_ERR("input pcidHeader(%u) error.\n", pcidHeaderLen);
556         return -1;
557     }
558 
559     PCIDHeader *header = (PCIDHeader *)pcidHeader;
560     // trans system type to string
561     char *systemType = header->systemType  == 0b001 ? "mini" :
562                        (header->systemType == 0b010 ? "small" :
563                        (header->systemType == 0b100 ? "standard" : NULL));
564     if (systemType == NULL) {
565         PRINT_ERR("prase system type failed.\n");
566         return -1;
567     }
568 
569     // add to json
570     if (!cJSON_AddNumberToObject(rootObj, "api_version", NtohsInter(header->apiVersion))) {
571         PRINT_ERR("add api_version(%u) to json object failed.\n", NtohsInter(header->apiVersion));
572         return -1;
573     }
574     if (!cJSON_AddNumberToObject(rootObj, "manufacturer_id", NtohlInter(header->manufacturerID))) {
575         PRINT_ERR("add manufacturer_id(%u) to json object failed\n", NtohlInter(header->manufacturerID));
576         return -1;
577     }
578     if (!cJSON_AddStringToObject(rootObj, "system_type", systemType)) {
579         PRINT_ERR("add system_type(%s) to json object failed\n", systemType);
580         return -1;
581     }
582     return 0;
583 }
584 
AddOsSyscapToJsonObj(uint32_t * osSyscapArray,uint32_t osSyscapArrayLen,cJSON * sysCapObj)585 static int32_t AddOsSyscapToJsonObj(uint32_t *osSyscapArray, uint32_t osSyscapArrayLen, cJSON *sysCapObj)
586 {
587     cJSON *sysCapArray = cJSON_CreateArray();
588     if (sysCapArray == NULL) {
589         PRINT_ERR("Create cJSON array failed.\n");
590         return -1;
591     }
592 
593     if (osSyscapArrayLen != OS_SYSCAP_NUM) {
594         PRINT_ERR("Input os syscap array len error.\n");
595         free(sysCapArray);
596         return -1;
597     }
598     uint8_t *osSysCapArrayUint8 = (uint8_t *)osSyscapArray;
599 
600     uint32_t i, j;
601     uint32_t osSyscapCount = 0;
602     uint16_t index[OS_SYSCAP_BYTES * UINT8_BIT] = {0};
603     for (i = 0; i < OS_SYSCAP_BYTES; i++) {
604         for (j = 0; j < UINT8_BIT; j++) {
605             if (osSysCapArrayUint8[i] & (0x01 << j)) {
606                 index[osSyscapCount++] = i * UINT8_BIT + j;
607             }
608         }
609     }
610 
611     for (i = 0; i < osSyscapCount; i++) {
612         for (j = 0; j < sizeof(g_arraySyscap) / sizeof(SyscapWithNum); j++) {
613             if (index[i] != g_arraySyscap[j].num) {
614                 continue;
615             }
616             if (!cJSON_AddItemToArray(sysCapArray, cJSON_CreateString(g_arraySyscap[j].str))) {
617                 PRINT_ERR("Add os syscap string to json failed.\n");
618                 free(sysCapArray);
619                 return -1;
620             }
621             break;
622         }
623     }
624 
625     if (!cJSON_AddItemToObject(sysCapObj, "os", sysCapArray)) {
626         PRINT_ERR("Add os syscap item to json object failed.\n");
627         free(sysCapArray);
628         return -1;
629     }
630     return 0;
631 }
632 
AddPriSyscapToJsonObj(char * priSyscapString,uint32_t priSyscapStringLen,cJSON * sysCapObj)633 static int32_t AddPriSyscapToJsonObj(char *priSyscapString, uint32_t priSyscapStringLen, cJSON *sysCapObj)
634 {
635     char *token = NULL;
636 
637     cJSON *sysCapArray = cJSON_CreateArray();
638     if (sysCapArray == NULL) {
639         PRINT_ERR("Create cJSON array failed.\n");
640         free(sysCapArray);
641         return -1;
642     }
643     if (priSyscapStringLen == 0) {
644         if (!cJSON_AddItemToObject(sysCapObj, "private", sysCapArray)) {
645             PRINT_ERR("Add private syscap array to json failed.\n");
646             free(sysCapArray);
647             return -1;
648         }
649         return 0;
650     }
651 
652     token = strtok(priSyscapString, ",");
653     while (token != NULL) {
654         if (!cJSON_AddItemToArray(sysCapArray, cJSON_CreateString(token))) {
655             PRINT_ERR("Add private syscap string to json failed.\n");
656             free(sysCapArray);
657             return -1;
658         }
659         token = strtok(NULL, ",");
660     }
661     if (!cJSON_AddItemToObject(sysCapObj, "private", sysCapArray)) {
662         PRINT_ERR("Add private syscap array to json failed.\n");
663         free(sysCapArray);
664         return -1;
665     }
666     return 0;
667 }
668 
DecodeStringPCIDToJson(char * input,char * outDirPath)669 int32_t DecodeStringPCIDToJson(char *input, char *outDirPath)
670 {
671     int32_t ret = -1;
672     uint32_t osSyscap[OS_SYSCAP_NUM] = {0};
673     uint32_t pcidHeader[PCID_HEADER];
674     uint32_t fileContextLen;
675     char *ctx = NULL;
676     char *priSyscapStr = NULL;
677 
678     if (GetFileContext(input, &ctx, (uint32_t *)&fileContextLen) != 0) {
679         PRINT_ERR("GetFileContext failed, input file : %s\n", input);
680         goto PARSE_FAILED;
681     }
682     if (ParseStringSyscap(ctx, osSyscap, OS_SYSCAP_NUM, pcidHeader, PCID_HEADER) != 0) {
683         PRINT_ERR("Parse string syscap failed.\n");
684         goto PARSE_FAILED;
685     }
686     priSyscapStr = ctx;
687 
688     // add to json object
689     cJSON *sysCapObj = cJSON_CreateObject();
690     cJSON *rootObj = cJSON_CreateObject();
691     if (!cJSON_AddItemToObject(rootObj, "syscap", sysCapObj)) {
692         PRINT_ERR("Add syscap to json failed.\n");
693         goto ADD_JSON_FAILED;
694     }
695     if (AddHeaderToJsonObj(pcidHeader, PCID_HEADER, rootObj) != 0) {
696         PRINT_ERR("Add header to json object failed.\n");
697         goto ADD_JSON_FAILED;
698     }
699     if (AddOsSyscapToJsonObj(osSyscap, OS_SYSCAP_NUM, sysCapObj) != 0) {
700         PRINT_ERR("Add os syscap json object failed.\n");
701         goto ADD_JSON_FAILED;
702     }
703     if (AddPriSyscapToJsonObj(priSyscapStr, (uint32_t)strlen(priSyscapStr), sysCapObj) != 0) {
704         PRINT_ERR("Add private syscap json object failed.\n");
705         goto ADD_JSON_FAILED;
706     }
707     // save as json file
708     char *jsonBuffer = cJSON_Print(rootObj);
709     const char outputFileName[] = "PCID.json";
710     if (ConvertedContextSaveAsFile(outDirPath, outputFileName,
711                                    jsonBuffer, strlen(jsonBuffer)) != 0) {
712         PRINT_ERR("Save as json file failed.\n");
713         goto SAVE_FAILED;
714     }
715     ret = 0;
716 
717     SAVE_FAILED:
718     free(jsonBuffer);
719     ADD_JSON_FAILED:
720     cJSON_Delete(rootObj);
721     PARSE_FAILED:
722     free(ctx);
723     return ret;
724 }
725 
FreeAfterEncodePCID(struct FreeEncodePcidInfo freePcidInfo,int32_t type,int32_t ret)726 static int32_t FreeAfterEncodePCID(struct FreeEncodePcidInfo freePcidInfo, int32_t type, int32_t ret)
727 {
728     switch (type) {
729         case FREE_ENCODE_PCID_OUT:
730             free(freePcidInfo.output);
731             free(freePcidInfo.priSyscapFull);
732             free(freePcidInfo.contextBuffer);
733             break;
734         case FREE_ENCODE_PCID_PRISYSCAP_FULL_OUT:
735             free(freePcidInfo.priSyscapFull);
736             free(freePcidInfo.contextBuffer);
737             break;
738         case FREE_ENCODE_PCID_CONTEXT_OUT:
739         default:
740             free(freePcidInfo.contextBuffer);
741     }
742     return ret;
743 }
744 
GetEncodePCIDOut(uint16_t priSyscapCount,uint32_t privateSyscapLen,uint32_t * mainSyscap,struct FreeEncodePcidInfo freePcidInfo,int32_t ret)745 static int32_t GetEncodePCIDOut(uint16_t priSyscapCount, uint32_t privateSyscapLen, uint32_t *mainSyscap,
746         struct FreeEncodePcidInfo freePcidInfo, int32_t ret)
747 {
748     // 17, size of "SystemCapability."
749     uint32_t outputLen = U32_TO_STR_MAX_LEN * PCID_OUT_BUFFER + 17 * priSyscapCount + privateSyscapLen + 1;
750     char *output = NULL;
751     uint32_t i;
752     output = (char *)malloc(outputLen);
753     if (output == NULL) {
754         PRINT_ERR("malloc failed\n");
755         return FreeAfterEncodePCID(freePcidInfo, FREE_ENCODE_PCID_PRISYSCAP_FULL_OUT, ret);
756     }
757     (void)memset_s(output, outputLen, 0, outputLen);
758     ret = sprintf_s(output, outputLen, "%u", mainSyscap[0]);
759     if (ret == -1) {
760         PRINT_ERR("sprintf_s failed\n");
761         return FreeAfterEncodePCID(freePcidInfo, FREE_ENCODE_PCID_OUT, ret);
762     }
763     for (i = 1; i < PCID_OUT_BUFFER; i++) {
764         ret = sprintf_s(output, outputLen, "%s,%u", output, mainSyscap[i]);
765         if (ret == -1) {
766             PRINT_ERR("sprintf_s failed\n");
767             return FreeAfterEncodePCID(freePcidInfo, FREE_ENCODE_PCID_OUT, ret);
768         }
769     }
770     for (i = 0; i < priSyscapCount; i++) {
771         ret = sprintf_s(output, outputLen, "%s,%s", output, freePcidInfo.priSyscapFull + i * SINGLE_SYSCAP_LEN);
772         if (ret == -1) {
773             PRINT_ERR("sprintf_s failed\n");
774             return FreeAfterEncodePCID(freePcidInfo, FREE_ENCODE_PCID_OUT, ret);
775         }
776     }
777     // save as file
778     const char outputFileName[] = "PCID.txt";
779     ret = ConvertedContextSaveAsFile(freePcidInfo.outDirPathFinal, outputFileName, output, strlen(output));
780     if (ret != 0) {
781         PRINT_ERR("ConvertedContextSaveAsFile failed, outDirPath:%s, filename:%s\n",
782                   freePcidInfo.outDirPathFinal, outputFileName);
783     }
784     return FreeAfterEncodePCID(freePcidInfo, FREE_ENCODE_PCID_OUT, ret);
785 }
786 
CheckPrivateSyCap(struct FreeEncodePcidInfo freePcidInfo,uint32_t privateSyscapLen,char * privateSyscap,int32_t ret)787 static int32_t CheckPrivateSyCap(struct FreeEncodePcidInfo freePcidInfo, uint32_t privateSyscapLen,
788     char *privateSyscap, int32_t ret)
789 {
790     uint32_t i, j;
791     char tempSyscap[SINGLE_SYSCAP_LEN] = {0};
792     char *temp = tempSyscap;
793     for (i = 0, j = 0; i < privateSyscapLen; i++) {
794         if (*privateSyscap == ',') {
795             *temp = '\0';
796             ret = sprintf_s(freePcidInfo.priSyscapFull + j * SINGLE_SYSCAP_LEN, SINGLE_SYSCAP_LEN,
797                             "SystemCapability.%s", tempSyscap);
798             if (ret == -1) {
799                 PRINT_ERR("sprintf_s failed\n");
800                 return ret;
801             }
802             temp = tempSyscap;
803             privateSyscap++;
804             j++;
805             continue;
806         }
807         *temp++ = *privateSyscap++;
808     }
809     return ret;
810 }
811 
EncodePcidscToString(char * inputFile,char * outDirPath)812 int32_t EncodePcidscToString(char *inputFile, char *outDirPath)
813 {
814     int32_t ret = 0;
815     uint32_t bufferLen, privateSyscapLen;
816     uint32_t i;
817     uint32_t *mainSyscap = NULL;
818     uint16_t priSyscapCount = 0;
819 
820     char *privateSyscap = NULL;
821     struct FreeEncodePcidInfo freePcidInfo;
822     freePcidInfo.contextBuffer = NULL;
823     freePcidInfo.priSyscapFull = NULL;
824     freePcidInfo.output = NULL;
825     freePcidInfo.outDirPathFinal = outDirPath;
826     PCIDMain *pcidMain = NULL;
827 
828     ret = GetFileContext(inputFile, &freePcidInfo.contextBuffer, (uint32_t *)&bufferLen);
829     if (ret != 0) {
830         PRINT_ERR("Get pcid file failed, pcid file path: %s\n", inputFile);
831         return -1;
832     }
833 
834     if (bufferLen > 1128) { // 1128, max size of pcid.sc
835         PRINT_ERR("Input pcid file too large, pcid file size: %u\n", bufferLen);
836         return FreeAfterEncodePCID(freePcidInfo, FREE_ENCODE_PCID_CONTEXT_OUT, ret);
837     }
838 
839     pcidMain = (PCIDMain *)freePcidInfo.contextBuffer;
840     privateSyscap = (char *)(pcidMain + 1);
841     privateSyscapLen = strlen(privateSyscap);
842 
843     // process os syscap
844     mainSyscap = (uint32_t *)pcidMain;
845 
846     // process private syscap
847     for (i = 0; i < privateSyscapLen; i++) {
848         if (privateSyscap[i] == ',') {
849             priSyscapCount++;
850         }
851     }
852     if (priSyscapCount == 0) {
853         return GetEncodePCIDOut(priSyscapCount, privateSyscapLen, mainSyscap,  freePcidInfo, ret);
854     }
855     freePcidInfo.priSyscapFull = (char *)malloc(priSyscapCount * SINGLE_SYSCAP_LEN);
856     if (freePcidInfo.priSyscapFull == NULL) {
857         PRINT_ERR("malloc failed\n");
858         return FreeAfterEncodePCID(freePcidInfo, FREE_ENCODE_PCID_PRISYSCAP_FULL_OUT, ret);
859     }
860     (void)memset_s(freePcidInfo.priSyscapFull, priSyscapCount * SINGLE_SYSCAP_LEN,
861                    0, priSyscapCount * SINGLE_SYSCAP_LEN);
862 
863     ret = CheckPrivateSyCap(freePcidInfo, privateSyscapLen, privateSyscap, ret);
864     if (ret == -1) {
865         return FreeAfterEncodePCID(freePcidInfo, FREE_ENCODE_PCID_PRISYSCAP_FULL_OUT, ret);
866     }
867 
868     // output
869     return GetEncodePCIDOut(priSyscapCount, privateSyscapLen, mainSyscap,  freePcidInfo, ret);
870 }