blob: cae152b400756d337c86f806ee3dfba7a2b7ba8f [file] [log] [blame]
Lawrence Tangd7e8ca32022-07-07 10:25:53 +01001/**
2 * Describes functions for converting CXL component error CPER sections from binary and JSON format
3 * into an intermediate format.
Ed Tanousfedd4572024-07-12 13:56:00 -07004 *
Lawrence Tangd7e8ca32022-07-07 10:25:53 +01005 * Author: Lawrence.Tang@arm.com
6 **/
7#include <stdio.h>
Lawrence Tang5202bbb2022-08-12 14:54:36 +01008#include <json.h>
Thu Nguyene42fb482024-10-15 14:43:11 +00009#include <libcper/base64.h>
10#include <libcper/Cper.h>
11#include <libcper/cper-utils.h>
12#include <libcper/sections/cper-section-cxl-component.h>
Lawrence Tangd7e8ca32022-07-07 10:25:53 +010013
14//Converts a single CXL component error CPER section into JSON IR.
Ed Tanous12dbd4f2025-03-08 19:05:01 -080015json_object *cper_section_cxl_component_to_ir(const UINT8 *section, UINT32 size)
Lawrence Tangd7e8ca32022-07-07 10:25:53 +010016{
Ed Tanous12dbd4f2025-03-08 19:05:01 -080017 if (size < sizeof(EFI_CXL_COMPONENT_EVENT_HEADER)) {
18 return NULL;
19 }
20
Lawrence Tange407b4c2022-07-21 13:54:01 +010021 EFI_CXL_COMPONENT_EVENT_HEADER *cxl_error =
22 (EFI_CXL_COMPONENT_EVENT_HEADER *)section;
Ed Tanous12dbd4f2025-03-08 19:05:01 -080023 if (cxl_error->Length < sizeof(EFI_CXL_COMPONENT_EVENT_HEADER)) {
24 return NULL;
25 }
26 if (size < cxl_error->Length) {
27 return NULL;
28 }
Lawrence Tange407b4c2022-07-21 13:54:01 +010029 json_object *section_ir = json_object_new_object();
Lawrence Tang27217392022-07-07 11:55:39 +010030
Lawrence Tange407b4c2022-07-21 13:54:01 +010031 //Length (bytes) for the entire structure.
32 json_object_object_add(section_ir, "length",
33 json_object_new_uint64(cxl_error->Length));
Lawrence Tang27217392022-07-07 11:55:39 +010034
Lawrence Tange407b4c2022-07-21 13:54:01 +010035 //Validation bits.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -080036 ValidationTypes ui64Type = { UINT_64T,
37 .value.ui64 = cxl_error->ValidBits };
Lawrence Tang27217392022-07-07 11:55:39 +010038
Lawrence Tange407b4c2022-07-21 13:54:01 +010039 //Device ID.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -080040 if (isvalid_prop_to_ir(&ui64Type, 0)) {
41 json_object *device_id = json_object_new_object();
42 json_object_object_add(
43 device_id, "vendorID",
44 json_object_new_int(cxl_error->DeviceId.VendorId));
45 json_object_object_add(
46 device_id, "deviceID",
47 json_object_new_int(cxl_error->DeviceId.DeviceId));
48 json_object_object_add(
49 device_id, "functionNumber",
50 json_object_new_int(
51 cxl_error->DeviceId.FunctionNumber));
52 json_object_object_add(
53 device_id, "deviceNumber",
54 json_object_new_int(cxl_error->DeviceId.DeviceNumber));
55 json_object_object_add(
56 device_id, "busNumber",
57 json_object_new_int(cxl_error->DeviceId.BusNumber));
58 json_object_object_add(
59 device_id, "segmentNumber",
60 json_object_new_int(cxl_error->DeviceId.SegmentNumber));
61 json_object_object_add(
62 device_id, "slotNumber",
63 json_object_new_int(cxl_error->DeviceId.SlotNumber));
64 json_object_object_add(section_ir, "deviceID", device_id);
65 }
Lawrence Tang27217392022-07-07 11:55:39 +010066
Lawrence Tange407b4c2022-07-21 13:54:01 +010067 //Device serial.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -080068 if (isvalid_prop_to_ir(&ui64Type, 1)) {
69 json_object_object_add(
70 section_ir, "deviceSerial",
71 json_object_new_uint64(cxl_error->DeviceSerial));
72 }
Lawrence Tangd7e8ca32022-07-07 10:25:53 +010073
Lawrence Tange407b4c2022-07-21 13:54:01 +010074 //The specification for this is defined within the CXL Specification Section 8.2.9.1.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -080075 if (isvalid_prop_to_ir(&ui64Type, 2)) {
Ed Tanous12dbd4f2025-03-08 19:05:01 -080076 const UINT8 *cur_pos = (const UINT8 *)(cxl_error + 1);
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -080077 int remaining_len = cxl_error->Length -
78 sizeof(EFI_CXL_COMPONENT_EVENT_HEADER);
79 if (remaining_len > 0) {
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -080080 int32_t encoded_len = 0;
Ed Tanousa7d2cdd2024-07-15 11:07:27 -070081
Ed Tanous12dbd4f2025-03-08 19:05:01 -080082 char *encoded = base64_encode(cur_pos, remaining_len,
83 &encoded_len);
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -080084 if (encoded == NULL) {
85 printf("Failed to allocate encode output buffer. \n");
Ed Tanous12dbd4f2025-03-08 19:05:01 -080086 json_object_put(section_ir);
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -080087 return NULL;
88 }
Ed Tanous12dbd4f2025-03-08 19:05:01 -080089 json_object *event_log = json_object_new_object();
90
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -080091 json_object_object_add(event_log, "data",
92 json_object_new_string_len(
93 encoded, encoded_len));
94
95 free(encoded);
96 json_object_object_add(
97 section_ir, "cxlComponentEventLog", event_log);
John Chungf8fc7052024-05-03 20:05:29 +080098 }
Lawrence Tange407b4c2022-07-21 13:54:01 +010099 }
100
101 return section_ir;
Lawrence Tangaec83902022-07-18 09:41:08 +0100102}
103
104//Converts a single given CXL Component CPER-JSON section into CPER binary, outputting to the
105//given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100106void ir_section_cxl_component_to_cper(json_object *section, FILE *out)
Lawrence Tangaec83902022-07-18 09:41:08 +0100107{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100108 EFI_CXL_COMPONENT_EVENT_HEADER *section_cper =
109 (EFI_CXL_COMPONENT_EVENT_HEADER *)calloc(
110 1, sizeof(EFI_CXL_COMPONENT_EVENT_HEADER));
Lawrence Tangaec83902022-07-18 09:41:08 +0100111
Lawrence Tange407b4c2022-07-21 13:54:01 +0100112 //Length of the structure.
113 section_cper->Length = json_object_get_uint64(
114 json_object_object_get(section, "length"));
Lawrence Tangaec83902022-07-18 09:41:08 +0100115
Lawrence Tange407b4c2022-07-21 13:54:01 +0100116 //Validation bits.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800117 ValidationTypes ui64Type = { UINT_64T, .value.ui64 = 0 };
118 struct json_object *obj = NULL;
Lawrence Tangaec83902022-07-18 09:41:08 +0100119
Lawrence Tange407b4c2022-07-21 13:54:01 +0100120 //Device ID information.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800121 if (json_object_object_get_ex(section, "deviceID", &obj)) {
122 json_object *device_id = obj;
123 section_cper->DeviceId.VendorId = json_object_get_uint64(
124 json_object_object_get(device_id, "vendorID"));
125 section_cper->DeviceId.DeviceId = json_object_get_uint64(
126 json_object_object_get(device_id, "deviceID"));
127 section_cper->DeviceId.FunctionNumber = json_object_get_uint64(
128 json_object_object_get(device_id, "functionNumber"));
129 section_cper->DeviceId.DeviceNumber = json_object_get_uint64(
130 json_object_object_get(device_id, "deviceNumber"));
131 section_cper->DeviceId.BusNumber = json_object_get_uint64(
132 json_object_object_get(device_id, "busNumber"));
133 section_cper->DeviceId.SegmentNumber = json_object_get_uint64(
134 json_object_object_get(device_id, "segmentNumber"));
135 section_cper->DeviceId.SlotNumber = json_object_get_uint64(
136 json_object_object_get(device_id, "slotNumber"));
137 add_to_valid_bitfield(&ui64Type, 0);
138 }
Lawrence Tangaec83902022-07-18 09:41:08 +0100139
Lawrence Tange407b4c2022-07-21 13:54:01 +0100140 //Device serial number.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800141 if (json_object_object_get_ex(section, "deviceSerial", &obj)) {
142 section_cper->DeviceSerial = json_object_get_uint64(obj);
143 add_to_valid_bitfield(&ui64Type, 1);
144 }
145
146 //CXL component event log, decoded from base64.
147 json_object *event_log = NULL;
148 if (json_object_object_get_ex(section, "cxlComponentEventLog", &obj)) {
149 event_log = obj;
150 add_to_valid_bitfield(&ui64Type, 2);
151 }
152 section_cper->ValidBits = ui64Type.value.ui64;
Lawrence Tangaec83902022-07-18 09:41:08 +0100153
Lawrence Tange407b4c2022-07-21 13:54:01 +0100154 //Write header out to stream.
155 fwrite(section_cper, sizeof(EFI_CXL_COMPONENT_EVENT_HEADER), 1, out);
156 fflush(out);
Lawrence Tangaec83902022-07-18 09:41:08 +0100157
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800158 if (event_log != NULL) {
159 json_object *encoded =
160 json_object_object_get(event_log, "data");
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700161
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800162 int32_t decoded_len = 0;
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700163
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800164 UINT8 *decoded = base64_decode(
165 json_object_get_string(encoded),
166 json_object_get_string_len(encoded), &decoded_len);
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700167
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800168 if (decoded == NULL) {
169 printf("Failed to allocate decode output buffer. \n");
170 } else {
171 fwrite(decoded, decoded_len, 1, out);
172 fflush(out);
173 free(decoded);
174 }
John Chungf8fc7052024-05-03 20:05:29 +0800175 }
Lawrence Tangaec83902022-07-18 09:41:08 +0100176
Lawrence Tange407b4c2022-07-21 13:54:01 +0100177 free(section_cper);
John Chungf8fc7052024-05-03 20:05:29 +0800178}