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