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