• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 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 <unistd.h>
21 #include <string.h>
22 #include <limits.h>
23 #include <libgen.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <securec.h>
27 #include "endian_internal.h"
28 #include "cJSON.h"
29 #include "syscap_tool.h"
30 
31 typedef struct ProductCompatibilityIDHead {
32     uint16_t apiVersion : 15;
33     uint16_t apiVersionType : 1;
34     uint16_t systemType : 3;
35     uint16_t reserved : 13;
36     uint32_t manufacturerID;
37 } PCIDHead;
38 
39 typedef struct RequiredProductCompatibilityIDHead {
40     uint16_t apiVersion : 15;
41     uint16_t apiVersionType : 1;
42 } RPCIDHead;
43 
44 #define SINGLE_FEAT_LENGTH  (32 * 8)
45 
46 #define PRINT_ERR(...) \
47     do { \
48         printf("ERROR: in file %s at line %d -> ", __FILE__, __LINE__); \
49         printf(__VA_ARGS__); \
50     } while (0)
51 
FreeContextBuffer(char * contextBuffer)52 static void FreeContextBuffer(char *contextBuffer)
53 {
54     (void)free(contextBuffer);
55 }
56 
GetFileContext(char * inputFile,char ** contextBufPtr,uint32_t * bufferLen)57 static uint32_t GetFileContext(char *inputFile, char **contextBufPtr, uint32_t *bufferLen)
58 {
59     uint32_t ret;
60     FILE *fp = NULL;
61     struct stat statBuf;
62     char *contextBuffer = NULL;
63 
64     ret = stat(inputFile, &statBuf);
65     if (ret != 0) {
66         PRINT_ERR("get file(%s) st_mode failed, errno = %d\n", inputFile, errno);
67         return -1;
68     }
69     if (!(statBuf.st_mode & S_IRUSR)) {
70         PRINT_ERR("don't have permission to read the file(%s)\n", inputFile);
71         return -1;
72     }
73     contextBuffer = (char *)malloc(statBuf.st_size + 1);
74     if (contextBuffer == NULL) {
75         PRINT_ERR("malloc buffer failed, size = %d, errno = %d\n", (int32_t)statBuf.st_size + 1, errno);
76         return -1;
77     }
78     fp = fopen(inputFile, "rb");
79     if (fp == NULL) {
80         PRINT_ERR("open file(%s) failed, errno = %d\n", inputFile, errno);
81         FreeContextBuffer(contextBuffer);
82         return -1;
83     }
84     ret = fread(contextBuffer, statBuf.st_size, 1, fp);
85     if (ret != 1) {
86         PRINT_ERR("read file(%s) failed, errno = %d\n", inputFile, errno);
87         FreeContextBuffer(contextBuffer);
88         (void)fclose(fp);
89         return -1;
90     }
91     contextBuffer[statBuf.st_size] = '\0';
92     (void)fclose(fp);
93 
94     *contextBufPtr = contextBuffer;
95     *bufferLen = statBuf.st_size + 1;
96     return 0;
97 }
98 
ConvertedContextSaveAsFile(char * outDirPath,char * filename,char * convertedBuffer,uint32_t bufferLen)99 static int32_t ConvertedContextSaveAsFile(char *outDirPath, char *filename, char *convertedBuffer, uint32_t bufferLen)
100 {
101     int32_t ret;
102     FILE *fp = NULL;
103     char fileFullPath[PATH_MAX] = {0};
104     int32_t pathLen = strlen(outDirPath);
105 
106     ret = strncpy_s(fileFullPath, PATH_MAX, outDirPath, pathLen + 1);
107     if (ret != 0) {
108         PRINT_ERR("strncpy_s failed, source string:%s, len = %d, errno = %d\n", outDirPath, pathLen + 1, errno);
109         return -1;
110     }
111 
112     if (fileFullPath[pathLen - 1] != '/' && fileFullPath[pathLen - 1] != '\\') {
113         fileFullPath[pathLen] = '/';
114     }
115 
116     ret = strncat_s(fileFullPath, PATH_MAX, filename, strlen(filename) + 1);
117     if (ret != 0) {
118         PRINT_ERR("strncat_s failed, (%s, %d, %s, %d), errno = %d\n",
119                   fileFullPath, PATH_MAX, filename, (int32_t)strlen(filename) + 1, errno);
120         return -1;
121     }
122 
123     fp = fopen(fileFullPath, "wb");
124     if (fp == NULL) {
125         PRINT_ERR("can`t create file(%s), errno = %d\n", fileFullPath, errno);
126         return -1;
127     }
128 
129     ret = fwrite(convertedBuffer, bufferLen, 1, fp);
130     if (ret != 1) {
131         PRINT_ERR("can`t write file(%s),errno = %d\n", fileFullPath, errno);
132         (void)fclose(fp);
133         return -1;
134     }
135 
136     (void)fclose(fp);
137 
138     return 0;
139 }
140 
PCIDEncode(char * inputFile,char * outDirPath)141 int32_t PCIDEncode(char *inputFile, char *outDirPath)
142 {
143     int32_t ret;
144     char productName[NAME_MAX] = {0};
145     char *contextBuffer = NULL;
146     uint32_t bufferLen;
147     char *convertedBuffer = NULL;
148     uint32_t convertedBufLen = sizeof(PCIDHead);
149     char *systemType = NULL;
150     int32_t osCapSize, privateCapSize;
151     PCIDHead *headPtr = NULL;
152     char *fillTmpPtr = NULL;
153     cJSON *cjsonObjectRoot = NULL;
154     cJSON *cjsonObjectPtr = NULL;
155     cJSON *osCapPtr = NULL;
156     cJSON *privateCapPtr = NULL;
157     cJSON *arrayItemPtr = NULL;
158 
159     ret = GetFileContext(inputFile, &contextBuffer, &bufferLen);
160     if (ret != 0) {
161         PRINT_ERR("GetFileContext failed, input file : %s\n", inputFile);
162         return -1;
163     }
164 
165     cjsonObjectRoot = cJSON_ParseWithLength(contextBuffer, bufferLen);
166     if (cjsonObjectRoot == NULL) {
167         PRINT_ERR("cJSON_Parse failed, context buffer is:\n%s\n", contextBuffer);
168         ret = -1;
169         goto FREE_CONTEXT_OUT;
170     }
171 
172     cjsonObjectPtr = cJSON_GetObjectItem(cjsonObjectRoot, "syscap");
173     if (cjsonObjectPtr == NULL || !cJSON_IsObject(cjsonObjectPtr)) {
174         PRINT_ERR("get \"syscap\" object failed, cjsonObjectPtr = %p\n", cjsonObjectPtr);
175         ret = -1;
176         goto FREE_CONTEXT_OUT;
177     }
178 
179     osCapPtr = cJSON_GetObjectItem(cjsonObjectPtr, "os");
180     if (osCapPtr == NULL || !cJSON_IsArray(osCapPtr)) {
181         PRINT_ERR("get \"os\" array failed, osCapPtr = %p\n", osCapPtr);
182         ret = -1;
183         goto FREE_CONTEXT_OUT;
184     }
185     osCapSize = cJSON_GetArraySize(osCapPtr);
186     if (osCapSize < 0) {
187         PRINT_ERR("get \"os\" array size failed\n");
188         ret = -1;
189         goto FREE_CONTEXT_OUT;
190     }
191     // 2, to save osSysCaptype & osSysCapLength
192     convertedBufLen += (2 * sizeof(uint16_t) + osCapSize * SINGLE_FEAT_LENGTH);
193 
194     privateCapPtr = cJSON_GetObjectItem(cjsonObjectPtr, "private");
195     if (privateCapPtr != NULL && cJSON_IsArray(privateCapPtr)) {
196         privateCapSize = cJSON_GetArraySize(privateCapPtr);
197         // 2, to save privateSysCaptype & privateSysCapLength
198         convertedBufLen += (2 * sizeof(uint16_t) * !!privateCapSize +
199             privateCapSize * SINGLE_FEAT_LENGTH);
200     } else if (privateCapPtr == NULL) {
201         privateCapSize = 0;
202     } else {
203         PRINT_ERR("get \"private\" array failed, privateCapPtr = %p\n", privateCapPtr);
204         ret = -1;
205         goto FREE_CONTEXT_OUT;
206     }
207 
208     convertedBuffer = (char *)malloc(convertedBufLen);
209 
210     (void)memset_s(convertedBuffer, convertedBufLen, 0, convertedBufLen);
211 
212     headPtr = (PCIDHead *)convertedBuffer;
213     cjsonObjectPtr = cJSON_GetObjectItem(cjsonObjectRoot, "api_version");
214     if (cjsonObjectPtr == NULL || !cJSON_IsNumber(cjsonObjectPtr)) {
215         PRINT_ERR("get \"api_version\" failed, cjsonObjectPtr = %p\n", cjsonObjectPtr);
216         ret = -1;
217         goto FREE_CONVERT_OUT;
218     }
219     headPtr->apiVersion = HtonsInter((uint16_t)cjsonObjectPtr->valueint);
220     headPtr->apiVersionType = 0;
221 
222     cjsonObjectPtr = cJSON_GetObjectItem(cjsonObjectRoot, "system_type");
223     if (cjsonObjectPtr == NULL || !cJSON_IsString(cjsonObjectPtr)) {
224         PRINT_ERR("get \"system_type\" failed, cjsonObjectPtr = %p\n", cjsonObjectPtr);
225         ret = -1;
226         goto FREE_CONVERT_OUT;
227     }
228     systemType = cjsonObjectPtr->valuestring;
229     headPtr->systemType = !strcmp(systemType, "mini") ? 0b001 :
230                           (!strcmp(systemType, "small") ? 0b010 :
231                           (!strcmp(systemType, "standard") ? 0b100 : 0));
232     if (headPtr->systemType == 0) {
233         PRINT_ERR("\"system_type\" is invaild, systemType = \"%s\"\n", systemType);
234         ret = -1;
235         goto FREE_CONVERT_OUT;
236     }
237 
238     cjsonObjectPtr = cJSON_GetObjectItem(cjsonObjectRoot, "manufacturer_id");
239     if (cjsonObjectPtr == NULL || !cJSON_IsNumber(cjsonObjectPtr)) {
240         PRINT_ERR("get \"manufacturer_id\" failed, cjsonObjectPtr = %p\n", cjsonObjectPtr);
241         ret = -1;
242         goto FREE_CONVERT_OUT;
243     }
244     headPtr->manufacturerID = HtonlInter((uint32_t)cjsonObjectPtr->valueint);
245 
246     fillTmpPtr = convertedBuffer + sizeof(PCIDHead);
247 
248     *(uint16_t *)fillTmpPtr = HtonsInter(0); // 0, SysCap Type, 0: osCap
249     fillTmpPtr += sizeof(uint16_t);
250     // fill osCap Length
251     *(uint16_t *)fillTmpPtr = HtonsInter((uint16_t)(osCapSize * SINGLE_FEAT_LENGTH));
252     fillTmpPtr += sizeof(uint16_t);
253     for (int32_t i = 0; i < osCapSize; i++) {
254         arrayItemPtr = cJSON_GetArrayItem(osCapPtr, i);
255         char *pointPos = strchr(arrayItemPtr->valuestring, '.');
256         if (pointPos == NULL) {
257             PRINT_ERR("context of \"os\" array is invaild\n");
258             ret = -1;
259             goto FREE_CONVERT_OUT;
260         }
261         ret = strncmp(arrayItemPtr->valuestring, "SystemCapability.", pointPos - arrayItemPtr->valuestring + 1);
262         if (ret != 0) {
263             PRINT_ERR("context of \"os\" array is invaild\n");
264             ret = -1;
265             goto FREE_CONVERT_OUT;
266         }
267 
268         ret = memcpy_s(fillTmpPtr, SINGLE_FEAT_LENGTH, pointPos + 1, strlen(pointPos + 1));
269         if (ret != 0) {
270             PRINT_ERR("context of \"os\" array is invaild\n");
271             ret = -1;
272             goto FREE_CONVERT_OUT;
273         }
274         fillTmpPtr += SINGLE_FEAT_LENGTH;
275     }
276 
277     if (privateCapSize != 0) {
278         *(uint16_t *)fillTmpPtr = HtonsInter(1); // 1, SysCap Type, 1: privateCap
279         fillTmpPtr += sizeof(uint16_t);
280         // fill privateCap Length
281         *(uint16_t *)fillTmpPtr = HtonsInter((uint16_t)(privateCapSize * SINGLE_FEAT_LENGTH));
282         fillTmpPtr += sizeof(uint16_t);
283         for (int32_t i = 0; i < privateCapSize; i++) {
284             arrayItemPtr = cJSON_GetArrayItem(privateCapPtr, i);
285             char *pointPos = strchr(arrayItemPtr->valuestring, '.');
286             if (pointPos == NULL) {
287                 PRINT_ERR("context of \"private\" array is invaild\n");
288                 ret = -1;
289                 goto FREE_CONVERT_OUT;
290             }
291             ret = strncmp(arrayItemPtr->valuestring, "SystemCapability.", pointPos - arrayItemPtr->valuestring + 1);
292             if (ret != 0) {
293                 PRINT_ERR("context of \"private\" array is invaild\n");
294                 ret = -1;
295                 goto FREE_CONVERT_OUT;
296             }
297 
298             ret = memcpy_s(fillTmpPtr, SINGLE_FEAT_LENGTH, pointPos + 1, strlen(pointPos + 1));
299             if (ret != 0) {
300                 PRINT_ERR("context of \"private\" array is invaild\n");
301                 ret = -1;
302                 goto FREE_CONVERT_OUT;
303             }
304             fillTmpPtr += SINGLE_FEAT_LENGTH;
305         }
306     }
307 
308     cjsonObjectPtr = cJSON_GetObjectItem(cjsonObjectRoot, "product");
309     if (cjsonObjectPtr == NULL || !cJSON_IsString(cjsonObjectPtr)) {
310         PRINT_ERR("get \"product\" failed, cjsonObjectPtr = %p\n", cjsonObjectPtr);
311         ret = -1;
312         goto FREE_CONVERT_OUT;
313     }
314 
315     ret = strncpy_s(productName, NAME_MAX, cjsonObjectPtr->valuestring, strlen(cjsonObjectPtr->valuestring));
316     if (ret != 0) {
317         PRINT_ERR("strncpy_s failed, source string:%s, len = %d, errno = %d\n",
318                   cjsonObjectPtr->valuestring, (int32_t)strlen(cjsonObjectPtr->valuestring), errno);
319         ret = -1;
320         goto FREE_CONVERT_OUT;
321     }
322 
323     ret = strncat_s(productName, NAME_MAX, ".sc", 4); // 4. '.' 's' 'c' '\0'
324     if (ret != 0) {
325         PRINT_ERR("strncat_s failed, (%s, %d, \".sc\", 4), errno = %d\n", productName, NAME_MAX, errno);
326         ret = -1;
327         goto FREE_CONVERT_OUT;
328     }
329 
330     productName[NAME_MAX - 1] = '\0';
331     ret = ConvertedContextSaveAsFile(outDirPath, productName, convertedBuffer, convertedBufLen);
332     if (ret != 0) {
333         PRINT_ERR("ConvertedContextSaveAsFile failed, outDirPath:%s, filename:%s\n", outDirPath, productName);
334         ret = -1;
335         goto FREE_CONVERT_OUT;
336     }
337     ret = 0;
338 
339 FREE_CONVERT_OUT:
340     free(convertedBuffer);
341 FREE_CONTEXT_OUT:
342     FreeContextBuffer(contextBuffer);
343     return ret;
344 }
345 
PCIDDecode(char * inputFile,char * outDirPath)346 int32_t PCIDDecode(char *inputFile, char *outDirPath)
347 {
348     int32_t ret;
349     char *contextBuffer = NULL;
350     char *contextBufferTail = NULL;
351     uint32_t bufferLen;
352     char *convertedBuffer = NULL;
353     uint16_t sysCaptype, sysCapLength;
354     PCIDHead *headPtr = NULL;
355     char *osCapArrayPtr = NULL;
356     char *privateCapArrayPtr = NULL;
357     cJSON *cjsonObjectRoot = NULL;
358     cJSON *sysCapObjectPtr = NULL;
359     cJSON *capVectorPtr = NULL;
360     char productName[NAME_MAX] = {0};
361     char *inputFileName = basename(inputFile);
362     uint16_t inputFileNameLen = strlen(inputFileName);
363     char *pointPos = strchr(inputFileName, '.');
364     uint16_t productNameLen = pointPos ? (pointPos - inputFileName) : inputFileNameLen;
365 
366     ret = strncpy_s(productName, NAME_MAX, inputFileName, productNameLen);
367     if (ret != 0) {
368         PRINT_ERR("strncpy_s failed, source string:%s, len = %d\n", inputFileName, productNameLen);
369         return -1;
370     }
371     productName[NAME_MAX - 1] = '\0';
372 
373     ret = GetFileContext(inputFile, &contextBuffer, &bufferLen);
374     if (ret != 0) {
375         PRINT_ERR("GetFileContext failed, input file : %s\n", inputFile);
376         return -1;
377     }
378 
379     contextBufferTail = contextBuffer + bufferLen;
380     // 2, to save osSysCaptype & osSysCapLength
381     osCapArrayPtr = contextBuffer + sizeof(PCIDHead) + 2 * sizeof(uint16_t);
382     if (contextBufferTail <= osCapArrayPtr) {
383         PRINT_ERR("prase file failed, format is invaild, input file : %s\n", inputFile);
384         ret = -1;
385         goto FREE_CONTEXT_OUT;
386     }
387     headPtr = (PCIDHead *)contextBuffer;
388     if (headPtr->apiVersionType != 0) {
389         PRINT_ERR("prase file failed, apiVersionType is invaild, input file : %s\n", inputFile);
390         ret = -1;
391         goto FREE_CONTEXT_OUT;
392     }
393 
394     char *systemType = headPtr->systemType == 0b001 ? "mini" :
395                        (headPtr->systemType == 0b010 ? "small" :
396                        (headPtr->systemType == 0b100 ? "standard" : NULL));
397     if (systemType == NULL) {
398         PRINT_ERR("prase file failed, systemType is invaild, %d\n", headPtr->systemType);
399         ret = -1;
400         goto FREE_CONTEXT_OUT;
401     }
402 
403     sysCaptype = NtohsInter(*(uint16_t *)(osCapArrayPtr - 2 * sizeof(uint16_t))); // 2, for type & length
404     if (sysCaptype != 0) {
405         PRINT_ERR("prase file failed, sysCaptype is invaild, %d\n", sysCaptype);
406         ret = -1;
407         goto FREE_CONTEXT_OUT;
408     }
409 
410     sysCapLength = NtohsInter(*(uint16_t *)(osCapArrayPtr - sizeof(uint16_t)));
411     if (contextBufferTail < osCapArrayPtr + sysCapLength) {
412         PRINT_ERR("prase file(%s) failed\n", inputFile);
413         ret = -1;
414         goto FREE_CONTEXT_OUT;
415     }
416     sysCapObjectPtr = cJSON_CreateObject();
417     if (sysCapObjectPtr == NULL) {
418         PRINT_ERR("cJSON_CreateObject failed\n");
419         ret = -1;
420         goto FREE_CONTEXT_OUT;
421     }
422     capVectorPtr = cJSON_CreateArray();
423     if (capVectorPtr == NULL) {
424         PRINT_ERR("cJSON_CreateArray failed\n");
425         ret = -1;
426         goto FREE_SYSCAP_OUT;
427     }
428     for (int32_t i = 0; i < (sysCapLength / SINGLE_FEAT_LENGTH); i++) {
429         if (*(osCapArrayPtr + (i + 1) * SINGLE_FEAT_LENGTH - 1) != '\0') {
430             PRINT_ERR("prase file failed, format is invaild, input file : %s\n", inputFile);
431             ret = -1;
432             goto FREE_VECTOR_OUT;
433         }
434         char buffer[SINGLE_FEAT_LENGTH + 17] = "SystemCapability."; // 17, sizeof "SystemCapability."
435 
436         ret = strncat_s(buffer, sizeof(buffer), osCapArrayPtr + i * SINGLE_FEAT_LENGTH, SINGLE_FEAT_LENGTH);
437         if (ret != 0) {
438             PRINT_ERR("strncat_s failed, (%s, %d, %s, %d)\n",
439                       buffer, (int32_t)sizeof(buffer), osCapArrayPtr + i * SINGLE_FEAT_LENGTH, SINGLE_FEAT_LENGTH);
440             ret = -1;
441             goto FREE_CONVERT_OUT;
442         }
443         if (!cJSON_AddItemToArray(capVectorPtr, cJSON_CreateString(buffer))) {
444             PRINT_ERR("cJSON_AddItemToArray or cJSON_CreateString failed\n");
445             ret = -1;
446             goto FREE_VECTOR_OUT;
447         }
448     }
449     if (!cJSON_AddItemToObject(sysCapObjectPtr, "os", capVectorPtr)) {
450         PRINT_ERR("cJSON_AddItemToObject failed\n");
451         ret = -1;
452         goto FREE_VECTOR_OUT;
453     }
454     capVectorPtr = NULL;
455     privateCapArrayPtr = osCapArrayPtr + sysCapLength + 2 * sizeof(uint16_t); // 2, for type & length
456     if (contextBufferTail >= privateCapArrayPtr) {
457         sysCaptype = NtohsInter(*(uint16_t *)(privateCapArrayPtr - 2 * sizeof(uint16_t))); // 2, for type & length
458         if (sysCaptype != 1) {
459             PRINT_ERR("prase file failed, format is invaild, input file : %s\n", inputFile);
460             ret = -1;
461             goto FREE_SYSCAP_OUT;
462         }
463         sysCapLength = NtohsInter(*(uint16_t *)(privateCapArrayPtr - sizeof(uint16_t)));
464         if (contextBufferTail < privateCapArrayPtr + sysCapLength) {
465             PRINT_ERR("prase file failed, format is invaild, input file : %s\n", inputFile);
466             ret = -1;
467             goto FREE_SYSCAP_OUT;
468         }
469 
470         capVectorPtr = cJSON_CreateArray();
471         if (capVectorPtr == NULL) {
472             PRINT_ERR("cJSON_CreateArray failed\n");
473             ret = -1;
474             goto FREE_SYSCAP_OUT;
475         }
476 
477         for (int32_t i = 0; i < (sysCapLength / SINGLE_FEAT_LENGTH); i++) {
478             if (*(privateCapArrayPtr + (i + 1) * SINGLE_FEAT_LENGTH - 1) != '\0') {
479                 PRINT_ERR("prase file failed, format is invaild, input file : %s\n", inputFile);
480                 ret = -1;
481                 goto FREE_VECTOR_OUT;
482             }
483 
484             char buffer[SINGLE_FEAT_LENGTH + 17] = "SystemCapability."; // 17, sizeof "SystemCapability."
485 
486             ret = strncat_s(buffer, sizeof(buffer), privateCapArrayPtr + i * SINGLE_FEAT_LENGTH, SINGLE_FEAT_LENGTH);
487             if (ret != 0) {
488                 PRINT_ERR("strncat_s failed, (%s, %d, %s, %d)\n", buffer,
489                           (int32_t)sizeof(buffer), privateCapArrayPtr + i * SINGLE_FEAT_LENGTH, SINGLE_FEAT_LENGTH);
490                 ret = -1;
491                 goto FREE_CONVERT_OUT;
492             }
493 
494             if (!cJSON_AddItemToArray(capVectorPtr, cJSON_CreateString(buffer))) {
495                 PRINT_ERR("cJSON_AddItemToArray or cJSON_CreateString failed\n");
496                 ret = -1;
497                 goto FREE_VECTOR_OUT;
498             }
499         }
500         if (!cJSON_AddItemToObject(sysCapObjectPtr, "private", capVectorPtr)) {
501             PRINT_ERR("cJSON_AddItemToObject failed\n");
502             ret = -1;
503             goto FREE_VECTOR_OUT;
504         }
505         capVectorPtr = NULL;
506     }
507 
508     cjsonObjectRoot = cJSON_CreateObject();
509     if (cjsonObjectRoot == NULL) {
510         PRINT_ERR("cJSON_CreateObject failed\n");
511         ret = -1;
512         goto FREE_SYSCAP_OUT;
513     }
514     if (!cJSON_AddStringToObject(cjsonObjectRoot, "product", productName)) {
515         PRINT_ERR("cJSON_AddStringToObject failed\n");
516         ret = -1;
517         goto FREE_ROOT_OUT;
518     }
519     if (!cJSON_AddNumberToObject(cjsonObjectRoot, "api_version", NtohsInter(headPtr->apiVersion))) {
520         PRINT_ERR("cJSON_AddNumberToObject failed\n");
521         ret = -1;
522         goto FREE_ROOT_OUT;
523     }
524     if (!cJSON_AddNumberToObject(cjsonObjectRoot, "manufacturer_id", NtohlInter(headPtr->manufacturerID))) {
525         PRINT_ERR("cJSON_AddNumberToObject failed\n");
526         ret = -1;
527         goto FREE_ROOT_OUT;
528     }
529     if (!cJSON_AddStringToObject(cjsonObjectRoot, "system_type", systemType)) {
530         PRINT_ERR("cJSON_AddStringToObject failed\n");
531         ret = -1;
532         goto FREE_ROOT_OUT;
533     }
534     if (!cJSON_AddItemToObject(cjsonObjectRoot, "syscap", sysCapObjectPtr)) {
535         PRINT_ERR("cJSON_AddItemToObject failed\n");
536         ret = -1;
537         goto FREE_ROOT_OUT;
538     }
539     sysCapObjectPtr = NULL;
540     convertedBuffer = cJSON_Print(cjsonObjectRoot);
541 
542     ret = strncat_s(productName, NAME_MAX, ".json", 6); // 6. '.' 'j' 's' 'o' 'n' '\0'
543     if (ret != 0) {
544         PRINT_ERR("strncat_s failed, (%s, %d, .json, 6), errno = %d\n", productName, NAME_MAX, errno);
545         goto FREE_CONVERT_OUT;
546     }
547 
548     productName[NAME_MAX - 1] = '\0';
549     ret = ConvertedContextSaveAsFile(outDirPath, productName, convertedBuffer, strlen(convertedBuffer));
550     if (ret != 0) {
551         PRINT_ERR("ConvertedContextSaveAsFile failed, outDirPath:%s, filename:%s\n", outDirPath, productName);
552         goto FREE_CONVERT_OUT;
553     }
554 
555 FREE_CONVERT_OUT:
556     free(convertedBuffer);
557 FREE_ROOT_OUT:
558     cJSON_Delete(cjsonObjectRoot);
559 FREE_VECTOR_OUT:
560     cJSON_Delete(capVectorPtr);
561 FREE_SYSCAP_OUT:
562     cJSON_Delete(sysCapObjectPtr);
563 FREE_CONTEXT_OUT:
564     FreeContextBuffer(contextBuffer);
565     return ret;
566 }
567 
RPCIDEncode(char * inputFile,char * outDirPath)568 int32_t RPCIDEncode(char *inputFile, char *outDirPath)
569 {
570     int32_t ret;
571     char *contextBuffer = NULL;
572     uint32_t bufferLen;
573     char *convertedBuffer = NULL;
574     uint32_t convertedBufLen = sizeof(RPCIDHead);
575     int32_t sysCapSize;
576     RPCIDHead *headPtr = NULL;
577     char *fillTmpPtr = NULL;
578     cJSON *cjsonObjectRoot = NULL;
579     cJSON *apiVerItem = NULL;
580     cJSON *sysCapPtr = NULL;
581     cJSON *arrayItemPtr = NULL;
582 
583     ret = GetFileContext(inputFile, &contextBuffer, &bufferLen);
584     if (ret != 0) {
585         PRINT_ERR("GetFileContext failed, input file : %s\n", inputFile);
586         return ret;
587     }
588 
589     cjsonObjectRoot = cJSON_ParseWithLength(contextBuffer, bufferLen);
590     if (cjsonObjectRoot == NULL) {
591         PRINT_ERR("cJSON_Parse failed, context buffer is:\n%s\n", contextBuffer);
592         ret = -1;
593         goto FREE_CONTEXT_OUT;
594     }
595 
596     sysCapPtr = cJSON_GetObjectItem(cjsonObjectRoot, "syscap");
597     if (sysCapPtr == NULL || !cJSON_IsArray(sysCapPtr)) {
598         PRINT_ERR("get \"syscap\" object failed, sysCapPtr = %p\n", sysCapPtr);
599         ret = -1;
600         goto FREE_CONTEXT_OUT;
601     }
602 
603     sysCapSize = cJSON_GetArraySize(sysCapPtr);
604     if (sysCapSize < 0) {
605         PRINT_ERR("get \"syscap\" array size failed\n");
606         ret = -1;
607         goto FREE_CONTEXT_OUT;
608     }
609     // 2, to save SysCaptype & SysCapLength
610     convertedBufLen += (2 * sizeof(uint16_t) + sysCapSize * SINGLE_FEAT_LENGTH);
611 
612     convertedBuffer = (char *)malloc(convertedBufLen);
613     (void)memset_s(convertedBuffer, convertedBufLen, 0, convertedBufLen);
614 
615     headPtr = (RPCIDHead *)convertedBuffer;
616     apiVerItem = cJSON_GetObjectItem(cjsonObjectRoot, "api_version");
617     if (apiVerItem == NULL || !cJSON_IsNumber(apiVerItem)) {
618         PRINT_ERR("get \"api_version\" failed, apiVerItem = %p\n", apiVerItem);
619         ret = -1;
620         goto FREE_CONVERT_OUT;
621     }
622     headPtr->apiVersion = HtonsInter((uint16_t)apiVerItem->valueint);
623     headPtr->apiVersionType = 1;
624 
625     fillTmpPtr = convertedBuffer + sizeof(RPCIDHead);
626 
627     *(uint16_t *)fillTmpPtr = HtonsInter(2); // 2, SysCap Type, 2: request Cap
628     fillTmpPtr += sizeof(uint16_t);
629     // fill osCap Length
630     *(uint16_t *)fillTmpPtr = HtonsInter((uint16_t)(sysCapSize * SINGLE_FEAT_LENGTH));
631     fillTmpPtr += sizeof(uint16_t);
632     for (int32_t i = 0; i < sysCapSize; i++) {
633         arrayItemPtr = cJSON_GetArrayItem(sysCapPtr, i);
634         char *pointPos = strchr(arrayItemPtr->valuestring, '.');
635         if (pointPos == NULL) {
636             PRINT_ERR("context of \"syscap\" array is invaild\n");
637             ret = -1;
638             goto FREE_CONVERT_OUT;
639         }
640         ret = strncmp(arrayItemPtr->valuestring, "SystemCapability.", pointPos - arrayItemPtr->valuestring + 1);
641         if (ret != 0) {
642             PRINT_ERR("context of \"syscap\" array is invaild\n");
643             ret = -1;
644             goto FREE_CONVERT_OUT;
645         }
646 
647         ret = memcpy_s(fillTmpPtr, SINGLE_FEAT_LENGTH, pointPos + 1, strlen(pointPos + 1));
648         if (ret != 0) {
649             PRINT_ERR("context of \"syscap\" array is invaild\n");
650             ret = -1;
651             goto FREE_CONVERT_OUT;
652         }
653         fillTmpPtr += SINGLE_FEAT_LENGTH;
654     }
655 
656     ret = ConvertedContextSaveAsFile(outDirPath, "rpcid.sc", convertedBuffer, convertedBufLen);
657     if (ret != 0) {
658         PRINT_ERR("ConvertedContextSaveAsFile failed, outDirPath:%s, filename:rpcid.sc\n", outDirPath);
659         goto FREE_CONVERT_OUT;
660     }
661 
662 FREE_CONVERT_OUT:
663     free(convertedBuffer);
664 FREE_CONTEXT_OUT:
665     FreeContextBuffer(contextBuffer);
666     return ret;
667 }
668 
RPCIDDecode(char * inputFile,char * outDirPath)669 int32_t RPCIDDecode(char *inputFile, char *outDirPath)
670 {
671     uint32_t ret;
672     char *contextBuffer = NULL;
673     char *contextBufferTail = NULL;
674     uint32_t bufferLen;
675     char *convertedBuffer = NULL;
676     uint16_t sysCaptype, sysCapLength;
677     RPCIDHead *headPtr = NULL;
678     char *sysCapArrayPtr = NULL;
679     cJSON *cjsonObjectRoot = NULL;
680     cJSON *sysCapObjectPtr = NULL;
681 
682     ret = GetFileContext(inputFile, &contextBuffer, &bufferLen);
683     if (ret != 0) {
684         PRINT_ERR("GetFileContext failed, input file : %s\n", inputFile);
685         return -1;
686     }
687 
688     contextBufferTail = contextBuffer + bufferLen;
689     // 2, to save osSysCaptype & osSysCapLength
690     sysCapArrayPtr = contextBuffer + sizeof(RPCIDHead) + 2 * sizeof(uint16_t);
691     if (contextBufferTail <= sysCapArrayPtr) {
692         PRINT_ERR("prase file failed, format is invaild, input file : %s\n", inputFile);
693         ret = -1;
694         goto FREE_CONTEXT_OUT;
695     }
696     headPtr = (RPCIDHead *)contextBuffer;
697     if (headPtr->apiVersionType != 1) {
698         PRINT_ERR("prase file failed, format is invaild, input file : %s\n", inputFile);
699         ret = -1;
700         goto FREE_CONTEXT_OUT;
701     }
702 
703     sysCaptype = NtohsInter(*(uint16_t *)(sysCapArrayPtr - 2 * sizeof(uint16_t))); // 2, for type & length
704     if (sysCaptype != 2) { // 2, app syscap type
705         PRINT_ERR("prase file failed, format is invaild, input file : %s\n", inputFile);
706         ret = -1;
707         goto FREE_CONTEXT_OUT;
708     }
709 
710     sysCapLength = NtohsInter(*(uint16_t *)(sysCapArrayPtr - sizeof(uint16_t)));
711     if (contextBufferTail < sysCapArrayPtr + sysCapLength) {
712         PRINT_ERR("prase file failed, format is invaild, input file : %s\n", inputFile);
713         ret = -1;
714         goto FREE_CONTEXT_OUT;
715     }
716 
717     sysCapObjectPtr = cJSON_CreateArray();
718     if (sysCapObjectPtr == NULL) {
719         PRINT_ERR("cJSON_CreateArray failed\n");
720         ret = -1;
721         goto FREE_CONTEXT_OUT;
722     }
723     for (int32_t i = 0; i < (sysCapLength / SINGLE_FEAT_LENGTH); i++) {
724         if (*(sysCapArrayPtr + (i + 1) * SINGLE_FEAT_LENGTH - 1) != '\0') {
725             PRINT_ERR("prase file failed, format is invaild, input file : %s\n", inputFile);
726             ret = -1;
727             goto FREE_SYSCAP_OUT;
728         }
729         char buffer[SINGLE_FEAT_LENGTH + 17] = "SystemCapability."; // 17, sizeof "SystemCapability."
730 
731         ret = strncat_s(buffer, sizeof(buffer), sysCapArrayPtr + i * SINGLE_FEAT_LENGTH, SINGLE_FEAT_LENGTH);
732         if (ret != 0) {
733             PRINT_ERR("strncat_s failed, (%s, %d, %s, %d)\n",
734                       buffer, (int32_t)sizeof(buffer), sysCapArrayPtr + i * SINGLE_FEAT_LENGTH, SINGLE_FEAT_LENGTH);
735             ret = -1;
736             goto FREE_SYSCAP_OUT;
737         }
738         if (!cJSON_AddItemToArray(sysCapObjectPtr, cJSON_CreateString(buffer))) {
739             PRINT_ERR("cJSON_AddItemToArray or cJSON_CreateString failed\n");
740             ret = -1;
741             goto FREE_SYSCAP_OUT;
742         }
743     }
744 
745     cjsonObjectRoot = cJSON_CreateObject();
746     if (cjsonObjectRoot == NULL) {
747         PRINT_ERR("cJSON_CreateObject failed\n");
748         ret = -1;
749         goto FREE_SYSCAP_OUT;
750     }
751     if (!cJSON_AddNumberToObject(cjsonObjectRoot, "api_version", NtohsInter(headPtr->apiVersion))) {
752         PRINT_ERR("cJSON_AddNumberToObject failed\n");
753         ret = -1;
754         goto FREE_ROOT_OUT;
755     }
756     if (!cJSON_AddItemToObject(cjsonObjectRoot, "syscap", sysCapObjectPtr)) {
757         PRINT_ERR("cJSON_AddNumberToObject failed\n");
758         ret = -1;
759         goto FREE_ROOT_OUT;
760     }
761     sysCapObjectPtr = NULL;
762 
763     convertedBuffer = cJSON_Print(cjsonObjectRoot);
764 
765     ret = ConvertedContextSaveAsFile(outDirPath, "rpcid.json", convertedBuffer, strlen(convertedBuffer));
766     if (ret != 0) {
767         PRINT_ERR("ConvertedContextSaveAsFile failed, outDirPath:%s, filename:rpcid.json\n", outDirPath);
768         goto FREE_CONVERT_OUT;
769     }
770 
771 FREE_CONVERT_OUT:
772     free(convertedBuffer);
773 FREE_ROOT_OUT:
774     cJSON_Delete(cjsonObjectRoot);
775 FREE_SYSCAP_OUT:
776     cJSON_Delete(sysCapObjectPtr);
777 FREE_CONTEXT_OUT:
778     FreeContextBuffer(contextBuffer);
779     return ret;
780 }
781