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 "b64.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 * 16 cper_section_cxl_component_to_ir(void *section, 17 EFI_ERROR_SECTION_DESCRIPTOR *descriptor) 18 { 19 EFI_CXL_COMPONENT_EVENT_HEADER *cxl_error = 20 (EFI_CXL_COMPONENT_EVENT_HEADER *)section; 21 json_object *section_ir = json_object_new_object(); 22 23 //Length (bytes) for the entire structure. 24 json_object_object_add(section_ir, "length", 25 json_object_new_uint64(cxl_error->Length)); 26 27 //Validation bits. 28 json_object *validation = 29 bitfield_to_ir(cxl_error->ValidBits, 3, 30 CXL_COMPONENT_ERROR_VALID_BITFIELD_NAMES); 31 json_object_object_add(section_ir, "validationBits", validation); 32 33 //Device ID. 34 json_object *device_id = json_object_new_object(); 35 json_object_object_add( 36 device_id, "vendorID", 37 json_object_new_int(cxl_error->DeviceId.VendorId)); 38 json_object_object_add( 39 device_id, "deviceID", 40 json_object_new_int(cxl_error->DeviceId.DeviceId)); 41 json_object_object_add( 42 device_id, "functionNumber", 43 json_object_new_int(cxl_error->DeviceId.FunctionNumber)); 44 json_object_object_add( 45 device_id, "deviceNumber", 46 json_object_new_int(cxl_error->DeviceId.DeviceNumber)); 47 json_object_object_add( 48 device_id, "busNumber", 49 json_object_new_int(cxl_error->DeviceId.BusNumber)); 50 json_object_object_add( 51 device_id, "segmentNumber", 52 json_object_new_int(cxl_error->DeviceId.SegmentNumber)); 53 json_object_object_add( 54 device_id, "slotNumber", 55 json_object_new_int(cxl_error->DeviceId.SlotNumber)); 56 json_object_object_add(section_ir, "deviceID", device_id); 57 58 //Device serial. 59 json_object_object_add(section_ir, "deviceSerial", 60 json_object_new_uint64(cxl_error->DeviceSerial)); 61 62 //The specification for this is defined within the CXL Specification Section 8.2.9.1. 63 unsigned char *cur_pos = (unsigned char *)(cxl_error + 1); 64 int remaining_len = cxl_error->Length - sizeof(cxl_error); 65 if (remaining_len > 0) { 66 json_object *event_log = json_object_new_object(); 67 char *encoded = b64_encode(cur_pos, remaining_len); 68 json_object_object_add(event_log, "data", 69 json_object_new_string(encoded)); 70 free(encoded); 71 json_object_object_add(section_ir, "cxlComponentEventLog", 72 event_log); 73 } 74 75 return section_ir; 76 } 77 78 //Converts a single given CXL Component CPER-JSON section into CPER binary, outputting to the 79 //given stream. 80 void ir_section_cxl_component_to_cper(json_object *section, FILE *out) 81 { 82 EFI_CXL_COMPONENT_EVENT_HEADER *section_cper = 83 (EFI_CXL_COMPONENT_EVENT_HEADER *)calloc( 84 1, sizeof(EFI_CXL_COMPONENT_EVENT_HEADER)); 85 86 //Length of the structure. 87 section_cper->Length = json_object_get_uint64( 88 json_object_object_get(section, "length")); 89 90 //Validation bits. 91 section_cper->ValidBits = ir_to_bitfield( 92 json_object_object_get(section, "validationBits"), 3, 93 CXL_COMPONENT_ERROR_VALID_BITFIELD_NAMES); 94 95 //Device ID information. 96 json_object *device_id = json_object_object_get(section, "deviceID"); 97 section_cper->DeviceId.VendorId = json_object_get_uint64( 98 json_object_object_get(device_id, "vendorID")); 99 section_cper->DeviceId.DeviceId = json_object_get_uint64( 100 json_object_object_get(device_id, "deviceID")); 101 section_cper->DeviceId.FunctionNumber = json_object_get_uint64( 102 json_object_object_get(device_id, "functionNumber")); 103 section_cper->DeviceId.DeviceNumber = json_object_get_uint64( 104 json_object_object_get(device_id, "deviceNumber")); 105 section_cper->DeviceId.BusNumber = json_object_get_uint64( 106 json_object_object_get(device_id, "busNumber")); 107 section_cper->DeviceId.SegmentNumber = json_object_get_uint64( 108 json_object_object_get(device_id, "segmentNumber")); 109 section_cper->DeviceId.SlotNumber = json_object_get_uint64( 110 json_object_object_get(device_id, "slotNumber")); 111 112 //Device serial number. 113 section_cper->DeviceSerial = json_object_get_uint64( 114 json_object_object_get(section, "deviceSerial")); 115 116 //Write header out to stream. 117 fwrite(section_cper, sizeof(EFI_CXL_COMPONENT_EVENT_HEADER), 1, out); 118 fflush(out); 119 120 //CXL component event log, decoded from base64. 121 json_object *event_log = 122 json_object_object_get(section, "cxlComponentEventLog"); 123 json_object *encoded = json_object_object_get(event_log, "data"); 124 int log_length = 125 section_cper->Length - sizeof(EFI_CXL_COMPONENT_EVENT_HEADER); 126 char *decoded = b64_decode(json_object_get_string(encoded), 127 json_object_get_string_len(encoded)); 128 fwrite(decoded, log_length, 1, out); 129 fflush(out); 130 free(decoded); 131 132 free(section_cper); 133 }