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