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 "base64.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 67 int32_t encoded_len = 0; 68 69 char *encoded = base64_encode((UINT8 *)cur_pos, remaining_len, 70 &encoded_len); 71 if (encoded == NULL) { 72 printf("Failed to allocate encode output buffer. \n"); 73 return NULL; 74 } 75 json_object_object_add(event_log, "data", 76 json_object_new_string_len(encoded, 77 encoded_len)); 78 79 free(encoded); 80 json_object_object_add(section_ir, "cxlComponentEventLog", 81 event_log); 82 } 83 84 return section_ir; 85 } 86 87 //Converts a single given CXL Component CPER-JSON section into CPER binary, outputting to the 88 //given stream. 89 void ir_section_cxl_component_to_cper(json_object *section, FILE *out) 90 { 91 EFI_CXL_COMPONENT_EVENT_HEADER *section_cper = 92 (EFI_CXL_COMPONENT_EVENT_HEADER *)calloc( 93 1, sizeof(EFI_CXL_COMPONENT_EVENT_HEADER)); 94 95 //Length of the structure. 96 section_cper->Length = json_object_get_uint64( 97 json_object_object_get(section, "length")); 98 99 //Validation bits. 100 section_cper->ValidBits = ir_to_bitfield( 101 json_object_object_get(section, "validationBits"), 3, 102 CXL_COMPONENT_ERROR_VALID_BITFIELD_NAMES); 103 104 //Device ID information. 105 json_object *device_id = json_object_object_get(section, "deviceID"); 106 section_cper->DeviceId.VendorId = json_object_get_uint64( 107 json_object_object_get(device_id, "vendorID")); 108 section_cper->DeviceId.DeviceId = json_object_get_uint64( 109 json_object_object_get(device_id, "deviceID")); 110 section_cper->DeviceId.FunctionNumber = json_object_get_uint64( 111 json_object_object_get(device_id, "functionNumber")); 112 section_cper->DeviceId.DeviceNumber = json_object_get_uint64( 113 json_object_object_get(device_id, "deviceNumber")); 114 section_cper->DeviceId.BusNumber = json_object_get_uint64( 115 json_object_object_get(device_id, "busNumber")); 116 section_cper->DeviceId.SegmentNumber = json_object_get_uint64( 117 json_object_object_get(device_id, "segmentNumber")); 118 section_cper->DeviceId.SlotNumber = json_object_get_uint64( 119 json_object_object_get(device_id, "slotNumber")); 120 121 //Device serial number. 122 section_cper->DeviceSerial = json_object_get_uint64( 123 json_object_object_get(section, "deviceSerial")); 124 125 //Write header out to stream. 126 fwrite(section_cper, sizeof(EFI_CXL_COMPONENT_EVENT_HEADER), 1, out); 127 fflush(out); 128 129 //CXL component event log, decoded from base64. 130 json_object *event_log = 131 json_object_object_get(section, "cxlComponentEventLog"); 132 json_object *encoded = json_object_object_get(event_log, "data"); 133 134 int32_t decoded_len = 0; 135 136 UINT8 *decoded = base64_decode(json_object_get_string(encoded), 137 json_object_get_string_len(encoded), 138 &decoded_len); 139 140 if (decoded == NULL) { 141 printf("Failed to allocate decode output buffer. \n"); 142 } else { 143 fwrite(decoded, decoded_len, 1, out); 144 fflush(out); 145 free(decoded); 146 } 147 148 free(section_cper); 149 } 150