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 }