blob: f915b28124fe215638976a4de056374fd3f80103 [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.
John Chungf8fc7052024-05-03 20:05:29 +080015json_object *cper_section_cxl_component_to_ir(void *section)
Lawrence Tangd7e8ca32022-07-07 10:25:53 +010016{
Lawrence Tange407b4c2022-07-21 13:54:01 +010017 EFI_CXL_COMPONENT_EVENT_HEADER *cxl_error =
18 (EFI_CXL_COMPONENT_EVENT_HEADER *)section;
19 json_object *section_ir = json_object_new_object();
Lawrence Tang27217392022-07-07 11:55:39 +010020
Lawrence Tange407b4c2022-07-21 13:54:01 +010021 //Length (bytes) for the entire structure.
22 json_object_object_add(section_ir, "length",
23 json_object_new_uint64(cxl_error->Length));
Lawrence Tang27217392022-07-07 11:55:39 +010024
Lawrence Tange407b4c2022-07-21 13:54:01 +010025 //Validation bits.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -080026 ValidationTypes ui64Type = { UINT_64T,
27 .value.ui64 = cxl_error->ValidBits };
Lawrence Tang27217392022-07-07 11:55:39 +010028
Lawrence Tange407b4c2022-07-21 13:54:01 +010029 //Device ID.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -080030 if (isvalid_prop_to_ir(&ui64Type, 0)) {
31 json_object *device_id = json_object_new_object();
32 json_object_object_add(
33 device_id, "vendorID",
34 json_object_new_int(cxl_error->DeviceId.VendorId));
35 json_object_object_add(
36 device_id, "deviceID",
37 json_object_new_int(cxl_error->DeviceId.DeviceId));
38 json_object_object_add(
39 device_id, "functionNumber",
40 json_object_new_int(
41 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 }
Lawrence Tang27217392022-07-07 11:55:39 +010056
Lawrence Tange407b4c2022-07-21 13:54:01 +010057 //Device serial.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -080058 if (isvalid_prop_to_ir(&ui64Type, 1)) {
59 json_object_object_add(
60 section_ir, "deviceSerial",
61 json_object_new_uint64(cxl_error->DeviceSerial));
62 }
Lawrence Tangd7e8ca32022-07-07 10:25:53 +010063
Lawrence Tange407b4c2022-07-21 13:54:01 +010064 //The specification for this is defined within the CXL Specification Section 8.2.9.1.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -080065 if (isvalid_prop_to_ir(&ui64Type, 2)) {
66 const char *cur_pos = (const char *)(cxl_error + 1);
67 int remaining_len = cxl_error->Length -
68 sizeof(EFI_CXL_COMPONENT_EVENT_HEADER);
69 if (remaining_len > 0) {
70 json_object *event_log = json_object_new_object();
John Chungf8fc7052024-05-03 20:05:29 +080071
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -080072 int32_t encoded_len = 0;
Ed Tanousa7d2cdd2024-07-15 11:07:27 -070073
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -080074 char *encoded = base64_encode(
75 (UINT8 *)cur_pos, remaining_len, &encoded_len);
76 if (encoded == NULL) {
77 printf("Failed to allocate encode output buffer. \n");
78 return NULL;
79 }
80 json_object_object_add(event_log, "data",
81 json_object_new_string_len(
82 encoded, encoded_len));
83
84 free(encoded);
85 json_object_object_add(
86 section_ir, "cxlComponentEventLog", event_log);
John Chungf8fc7052024-05-03 20:05:29 +080087 }
Lawrence Tange407b4c2022-07-21 13:54:01 +010088 }
89
90 return section_ir;
Lawrence Tangaec83902022-07-18 09:41:08 +010091}
92
93//Converts a single given CXL Component CPER-JSON section into CPER binary, outputting to the
94//given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +010095void ir_section_cxl_component_to_cper(json_object *section, FILE *out)
Lawrence Tangaec83902022-07-18 09:41:08 +010096{
Lawrence Tange407b4c2022-07-21 13:54:01 +010097 EFI_CXL_COMPONENT_EVENT_HEADER *section_cper =
98 (EFI_CXL_COMPONENT_EVENT_HEADER *)calloc(
99 1, sizeof(EFI_CXL_COMPONENT_EVENT_HEADER));
Lawrence Tangaec83902022-07-18 09:41:08 +0100100
Lawrence Tange407b4c2022-07-21 13:54:01 +0100101 //Length of the structure.
102 section_cper->Length = json_object_get_uint64(
103 json_object_object_get(section, "length"));
Lawrence Tangaec83902022-07-18 09:41:08 +0100104
Lawrence Tange407b4c2022-07-21 13:54:01 +0100105 //Validation bits.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800106 ValidationTypes ui64Type = { UINT_64T, .value.ui64 = 0 };
107 struct json_object *obj = NULL;
Lawrence Tangaec83902022-07-18 09:41:08 +0100108
Lawrence Tange407b4c2022-07-21 13:54:01 +0100109 //Device ID information.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800110 if (json_object_object_get_ex(section, "deviceID", &obj)) {
111 json_object *device_id = obj;
112 section_cper->DeviceId.VendorId = json_object_get_uint64(
113 json_object_object_get(device_id, "vendorID"));
114 section_cper->DeviceId.DeviceId = json_object_get_uint64(
115 json_object_object_get(device_id, "deviceID"));
116 section_cper->DeviceId.FunctionNumber = json_object_get_uint64(
117 json_object_object_get(device_id, "functionNumber"));
118 section_cper->DeviceId.DeviceNumber = json_object_get_uint64(
119 json_object_object_get(device_id, "deviceNumber"));
120 section_cper->DeviceId.BusNumber = json_object_get_uint64(
121 json_object_object_get(device_id, "busNumber"));
122 section_cper->DeviceId.SegmentNumber = json_object_get_uint64(
123 json_object_object_get(device_id, "segmentNumber"));
124 section_cper->DeviceId.SlotNumber = json_object_get_uint64(
125 json_object_object_get(device_id, "slotNumber"));
126 add_to_valid_bitfield(&ui64Type, 0);
127 }
Lawrence Tangaec83902022-07-18 09:41:08 +0100128
Lawrence Tange407b4c2022-07-21 13:54:01 +0100129 //Device serial number.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800130 if (json_object_object_get_ex(section, "deviceSerial", &obj)) {
131 section_cper->DeviceSerial = json_object_get_uint64(obj);
132 add_to_valid_bitfield(&ui64Type, 1);
133 }
134
135 //CXL component event log, decoded from base64.
136 json_object *event_log = NULL;
137 if (json_object_object_get_ex(section, "cxlComponentEventLog", &obj)) {
138 event_log = obj;
139 add_to_valid_bitfield(&ui64Type, 2);
140 }
141 section_cper->ValidBits = ui64Type.value.ui64;
Lawrence Tangaec83902022-07-18 09:41:08 +0100142
Lawrence Tange407b4c2022-07-21 13:54:01 +0100143 //Write header out to stream.
144 fwrite(section_cper, sizeof(EFI_CXL_COMPONENT_EVENT_HEADER), 1, out);
145 fflush(out);
Lawrence Tangaec83902022-07-18 09:41:08 +0100146
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800147 if (event_log != NULL) {
148 json_object *encoded =
149 json_object_object_get(event_log, "data");
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700150
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800151 int32_t decoded_len = 0;
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700152
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800153 UINT8 *decoded = base64_decode(
154 json_object_get_string(encoded),
155 json_object_get_string_len(encoded), &decoded_len);
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700156
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800157 if (decoded == NULL) {
158 printf("Failed to allocate decode output buffer. \n");
159 } else {
160 fwrite(decoded, decoded_len, 1, out);
161 fflush(out);
162 free(decoded);
163 }
John Chungf8fc7052024-05-03 20:05:29 +0800164 }
Lawrence Tangaec83902022-07-18 09:41:08 +0100165
Lawrence Tange407b4c2022-07-21 13:54:01 +0100166 free(section_cper);
John Chungf8fc7052024-05-03 20:05:29 +0800167}