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