1 /** 2 * Describes functions for converting CXL component error CPER sections from binary and JSON format 3 * into an intermediate format. 4 * 5 * Author: Lawrence.Tang@arm.com 6 **/ 7 #include <stdio.h> 8 #include <json.h> 9 #include "libbase64.h" 10 #include "../edk/Cper.h" 11 #include "../cper-utils.h" 12 #include "cper-section-cxl-component.h" 13 14 //Converts a single CXL component error CPER section into JSON IR. 15 json_object *cper_section_cxl_component_to_ir(void *section) 16 { 17 EFI_CXL_COMPONENT_EVENT_HEADER *cxl_error = 18 (EFI_CXL_COMPONENT_EVENT_HEADER *)section; 19 json_object *section_ir = json_object_new_object(); 20 21 //Length (bytes) for the entire structure. 22 json_object_object_add(section_ir, "length", 23 json_object_new_uint64(cxl_error->Length)); 24 25 //Validation bits. 26 json_object *validation = 27 bitfield_to_ir(cxl_error->ValidBits, 3, 28 CXL_COMPONENT_ERROR_VALID_BITFIELD_NAMES); 29 json_object_object_add(section_ir, "validationBits", validation); 30 31 //Device ID. 32 json_object *device_id = json_object_new_object(); 33 json_object_object_add( 34 device_id, "vendorID", 35 json_object_new_int(cxl_error->DeviceId.VendorId)); 36 json_object_object_add( 37 device_id, "deviceID", 38 json_object_new_int(cxl_error->DeviceId.DeviceId)); 39 json_object_object_add( 40 device_id, "functionNumber", 41 json_object_new_int(cxl_error->DeviceId.FunctionNumber)); 42 json_object_object_add( 43 device_id, "deviceNumber", 44 json_object_new_int(cxl_error->DeviceId.DeviceNumber)); 45 json_object_object_add( 46 device_id, "busNumber", 47 json_object_new_int(cxl_error->DeviceId.BusNumber)); 48 json_object_object_add( 49 device_id, "segmentNumber", 50 json_object_new_int(cxl_error->DeviceId.SegmentNumber)); 51 json_object_object_add( 52 device_id, "slotNumber", 53 json_object_new_int(cxl_error->DeviceId.SlotNumber)); 54 json_object_object_add(section_ir, "deviceID", device_id); 55 56 //Device serial. 57 json_object_object_add(section_ir, "deviceSerial", 58 json_object_new_uint64(cxl_error->DeviceSerial)); 59 60 //The specification for this is defined within the CXL Specification Section 8.2.9.1. 61 const char *cur_pos = (const char *)(cxl_error + 1); 62 int remaining_len = 63 cxl_error->Length - sizeof(EFI_CXL_COMPONENT_EVENT_HEADER); 64 if (remaining_len > 0) { 65 json_object *event_log = json_object_new_object(); 66 char *encoded = malloc(2 * remaining_len); 67 size_t encoded_len = 0; 68 if (!encoded) { 69 printf("Failed to allocate encode output buffer. \n"); 70 } else { 71 base64_encode((const char *)cur_pos, remaining_len, 72 encoded, &encoded_len, 0); 73 json_object_object_add(event_log, "data", 74 json_object_new_string_len( 75 encoded, encoded_len)); 76 77 free(encoded); 78 json_object_object_add( 79 section_ir, "cxlComponentEventLog", event_log); 80 } 81 } 82 83 return section_ir; 84 } 85 86 //Converts a single given CXL Component CPER-JSON section into CPER binary, outputting to the 87 //given stream. 88 void ir_section_cxl_component_to_cper(json_object *section, FILE *out) 89 { 90 EFI_CXL_COMPONENT_EVENT_HEADER *section_cper = 91 (EFI_CXL_COMPONENT_EVENT_HEADER *)calloc( 92 1, sizeof(EFI_CXL_COMPONENT_EVENT_HEADER)); 93 94 //Length of the structure. 95 section_cper->Length = json_object_get_uint64( 96 json_object_object_get(section, "length")); 97 98 //Validation bits. 99 section_cper->ValidBits = ir_to_bitfield( 100 json_object_object_get(section, "validationBits"), 3, 101 CXL_COMPONENT_ERROR_VALID_BITFIELD_NAMES); 102 103 //Device ID information. 104 json_object *device_id = json_object_object_get(section, "deviceID"); 105 section_cper->DeviceId.VendorId = json_object_get_uint64( 106 json_object_object_get(device_id, "vendorID")); 107 section_cper->DeviceId.DeviceId = json_object_get_uint64( 108 json_object_object_get(device_id, "deviceID")); 109 section_cper->DeviceId.FunctionNumber = json_object_get_uint64( 110 json_object_object_get(device_id, "functionNumber")); 111 section_cper->DeviceId.DeviceNumber = json_object_get_uint64( 112 json_object_object_get(device_id, "deviceNumber")); 113 section_cper->DeviceId.BusNumber = json_object_get_uint64( 114 json_object_object_get(device_id, "busNumber")); 115 section_cper->DeviceId.SegmentNumber = json_object_get_uint64( 116 json_object_object_get(device_id, "segmentNumber")); 117 section_cper->DeviceId.SlotNumber = json_object_get_uint64( 118 json_object_object_get(device_id, "slotNumber")); 119 120 //Device serial number. 121 section_cper->DeviceSerial = json_object_get_uint64( 122 json_object_object_get(section, "deviceSerial")); 123 124 //Write header out to stream. 125 fwrite(section_cper, sizeof(EFI_CXL_COMPONENT_EVENT_HEADER), 1, out); 126 fflush(out); 127 128 //CXL component event log, decoded from base64. 129 json_object *event_log = 130 json_object_object_get(section, "cxlComponentEventLog"); 131 json_object *encoded = json_object_object_get(event_log, "data"); 132 char *decoded = malloc(json_object_get_string_len(encoded)); 133 size_t decoded_len = 0; 134 if (!decoded) { 135 printf("Failed to allocate decode output buffer. \n"); 136 } else { 137 base64_decode(json_object_get_string(encoded), 138 json_object_get_string_len(encoded), decoded, 139 &decoded_len, 0); 140 fwrite(decoded, decoded_len, 1, out); 141 fflush(out); 142 free(decoded); 143 } 144 145 free(section_cper); 146 } 147