1864c0da9SLawrence Tang /** 2864c0da9SLawrence Tang * Describes functions for converting CCIX PER log CPER sections from binary and JSON format 3864c0da9SLawrence Tang * into an intermediate format. 4864c0da9SLawrence Tang * 5864c0da9SLawrence Tang * Author: Lawrence.Tang@arm.com 6864c0da9SLawrence Tang **/ 7864c0da9SLawrence Tang #include <stdio.h> 8205dd1d7SLawrence Tang #include <string.h> 95202bbb4SLawrence Tang #include <json.h> 10*f8fc7052SJohn Chung #include "libbase64.h" 11864c0da9SLawrence Tang #include "../edk/Cper.h" 12864c0da9SLawrence Tang #include "../cper-utils.h" 13864c0da9SLawrence Tang #include "cper-section-ccix-per.h" 14864c0da9SLawrence Tang 15864c0da9SLawrence Tang //Converts a single CCIX PER log CPER section into JSON IR. 16*f8fc7052SJohn Chung json_object *cper_section_ccix_per_to_ir(void *section) 17864c0da9SLawrence Tang { 18864c0da9SLawrence Tang EFI_CCIX_PER_LOG_DATA *ccix_error = (EFI_CCIX_PER_LOG_DATA *)section; 19864c0da9SLawrence Tang json_object *section_ir = json_object_new_object(); 20864c0da9SLawrence Tang 21864c0da9SLawrence Tang //Length (bytes) for the entire structure. 22e407b4c8SLawrence Tang json_object_object_add(section_ir, "length", 23e407b4c8SLawrence Tang json_object_new_uint64(ccix_error->Length)); 24864c0da9SLawrence Tang 25864c0da9SLawrence Tang //Validation bits. 26e407b4c8SLawrence Tang json_object *validation = bitfield_to_ir( 27e407b4c8SLawrence Tang ccix_error->ValidBits, 3, CCIX_PER_ERROR_VALID_BITFIELD_NAMES); 28864c0da9SLawrence Tang json_object_object_add(section_ir, "validationBits", validation); 29864c0da9SLawrence Tang 30864c0da9SLawrence Tang //CCIX source/port IDs. 31e407b4c8SLawrence Tang json_object_object_add(section_ir, "ccixSourceID", 32e407b4c8SLawrence Tang json_object_new_int(ccix_error->CcixSourceId)); 33e407b4c8SLawrence Tang json_object_object_add(section_ir, "ccixPortID", 34e407b4c8SLawrence Tang json_object_new_int(ccix_error->CcixPortId)); 35864c0da9SLawrence Tang 36864c0da9SLawrence Tang //CCIX PER Log. 372721739aSLawrence Tang //This is formatted as described in Section 7.3.2 of CCIX Base Specification (Rev 1.0). 38*f8fc7052SJohn Chung const char *cur_pos = (const char *)(ccix_error + 1); 39e407b4c8SLawrence Tang int remaining_length = 40e407b4c8SLawrence Tang ccix_error->Length - sizeof(EFI_CCIX_PER_LOG_DATA); 41e407b4c8SLawrence Tang if (remaining_length > 0) { 42*f8fc7052SJohn Chung char *encoded = malloc(2 * remaining_length); 43*f8fc7052SJohn Chung size_t encoded_len = 0; 44*f8fc7052SJohn Chung if (!encoded) { 45*f8fc7052SJohn Chung printf("Failed to allocate encode output buffer. \n"); 46*f8fc7052SJohn Chung } else { 47*f8fc7052SJohn Chung base64_encode((const char *)cur_pos, remaining_length, 48*f8fc7052SJohn Chung encoded, &encoded_len, 0); 49e407b4c8SLawrence Tang json_object_object_add(section_ir, "ccixPERLog", 50*f8fc7052SJohn Chung json_object_new_string_len( 51*f8fc7052SJohn Chung encoded, encoded_len)); 522721739aSLawrence Tang free(encoded); 532721739aSLawrence Tang } 54*f8fc7052SJohn Chung } 55864c0da9SLawrence Tang 56864c0da9SLawrence Tang return section_ir; 57864c0da9SLawrence Tang } 58205dd1d7SLawrence Tang 59205dd1d7SLawrence Tang //Converts a single CCIX PER CPER-JSON section into CPER binary, outputting to the given stream. 60205dd1d7SLawrence Tang void ir_section_ccix_per_to_cper(json_object *section, FILE *out) 61205dd1d7SLawrence Tang { 62e407b4c8SLawrence Tang EFI_CCIX_PER_LOG_DATA *section_cper = (EFI_CCIX_PER_LOG_DATA *)calloc( 63e407b4c8SLawrence Tang 1, sizeof(EFI_CCIX_PER_LOG_DATA)); 64205dd1d7SLawrence Tang 65205dd1d7SLawrence Tang //Length. 66e407b4c8SLawrence Tang section_cper->Length = json_object_get_uint64( 67e407b4c8SLawrence Tang json_object_object_get(section, "length")); 68205dd1d7SLawrence Tang 69205dd1d7SLawrence Tang //Validation bits. 70e407b4c8SLawrence Tang section_cper->ValidBits = ir_to_bitfield( 71e407b4c8SLawrence Tang json_object_object_get(section, "validationBits"), 3, 72e407b4c8SLawrence Tang CCIX_PER_ERROR_VALID_BITFIELD_NAMES); 73205dd1d7SLawrence Tang 74205dd1d7SLawrence Tang //CCIX source/port IDs. 75e407b4c8SLawrence Tang section_cper->CcixSourceId = (UINT8)json_object_get_int( 76e407b4c8SLawrence Tang json_object_object_get(section, "ccixSourceID")); 77e407b4c8SLawrence Tang section_cper->CcixPortId = (UINT8)json_object_get_int( 78e407b4c8SLawrence Tang json_object_object_get(section, "ccixPortID")); 79205dd1d7SLawrence Tang 80205dd1d7SLawrence Tang //Write header out to stream. 813ab351feSLawrence Tang fwrite(section_cper, sizeof(EFI_CCIX_PER_LOG_DATA), 1, out); 82205dd1d7SLawrence Tang fflush(out); 83205dd1d7SLawrence Tang 84205dd1d7SLawrence Tang //Write CCIX PER log itself to stream. 85205dd1d7SLawrence Tang json_object *encoded = json_object_object_get(section, "ccixPERLog"); 86*f8fc7052SJohn Chung char *decoded = malloc(json_object_get_string_len(encoded)); 87*f8fc7052SJohn Chung size_t decoded_len = 0; 88*f8fc7052SJohn Chung if (!decoded) { 89*f8fc7052SJohn Chung printf("Failed to allocate decode output buffer. \n"); 90*f8fc7052SJohn Chung } else { 91*f8fc7052SJohn Chung base64_decode(json_object_get_string(encoded), 92*f8fc7052SJohn Chung json_object_get_string_len(encoded), decoded, 93*f8fc7052SJohn Chung &decoded_len, 0); 94*f8fc7052SJohn Chung fwrite(decoded, decoded_len, 1, out); 95205dd1d7SLawrence Tang fflush(out); 96*f8fc7052SJohn Chung } 97205dd1d7SLawrence Tang 98205dd1d7SLawrence Tang //Free resources. 99205dd1d7SLawrence Tang free(decoded); 100205dd1d7SLawrence Tang free(section_cper); 101205dd1d7SLawrence Tang } 102