blob: 6aa0b877e444249ea532775e7b136cbbbc5bbf1e [file] [log] [blame]
Lawrence Tang2800cd82022-07-05 16:08:20 +01001/**
2 * Describes functions for converting ARM CPER sections from binary and JSON format
3 * into an intermediate format.
Ed Tanousfedd4572024-07-12 13:56:00 -07004 *
Lawrence Tang2800cd82022-07-05 16:08:20 +01005 * Author: Lawrence.Tang@arm.com
6 **/
7
8#include <stdio.h>
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -08009#include <string.h>
Lawrence Tang5202bbb2022-08-12 14:54:36 +010010#include <json.h>
Thu Nguyene42fb482024-10-15 14:43:11 +000011#include <libcper/base64.h>
12#include <libcper/Cper.h>
13#include <libcper/cper-utils.h>
14#include <libcper/sections/cper-section-arm.h>
Lawrence Tang2800cd82022-07-05 16:08:20 +010015
Lawrence Tang3d0e4f22022-07-05 17:17:41 +010016//Private pre-definitions.
Lawrence Tange407b4c2022-07-21 13:54:01 +010017json_object *
18cper_arm_error_info_to_ir(EFI_ARM_ERROR_INFORMATION_ENTRY *error_info);
19json_object *
20cper_arm_processor_context_to_ir(EFI_ARM_CONTEXT_INFORMATION_HEADER *header,
21 void **cur_pos);
22json_object *
23cper_arm_cache_tlb_error_to_ir(EFI_ARM_CACHE_ERROR_STRUCTURE *cache_tlb_error,
24 EFI_ARM_ERROR_INFORMATION_ENTRY *error_info);
25json_object *cper_arm_bus_error_to_ir(EFI_ARM_BUS_ERROR_STRUCTURE *bus_error);
26json_object *cper_arm_misc_register_array_to_ir(
27 EFI_ARM_MISC_CONTEXT_REGISTER *misc_register);
28void ir_arm_error_info_to_cper(json_object *error_info, FILE *out);
29void ir_arm_context_info_to_cper(json_object *context_info, FILE *out);
30void ir_arm_error_cache_tlb_info_to_cper(
31 json_object *error_information,
32 EFI_ARM_CACHE_ERROR_STRUCTURE *error_info_cper);
33void ir_arm_error_bus_info_to_cper(json_object *error_information,
34 EFI_ARM_BUS_ERROR_STRUCTURE *error_info_cper);
35void ir_arm_aarch32_gpr_to_cper(json_object *registers, FILE *out);
36void ir_arm_aarch32_el1_to_cper(json_object *registers, FILE *out);
37void ir_arm_aarch32_el2_to_cper(json_object *registers, FILE *out);
38void ir_arm_aarch32_secure_to_cper(json_object *registers, FILE *out);
39void ir_arm_aarch64_gpr_to_cper(json_object *registers, FILE *out);
40void ir_arm_aarch64_el1_to_cper(json_object *registers, FILE *out);
41void ir_arm_aarch64_el2_to_cper(json_object *registers, FILE *out);
42void ir_arm_aarch64_el3_to_cper(json_object *registers, FILE *out);
43void ir_arm_misc_registers_to_cper(json_object *registers, FILE *out);
John Chungf8fc7052024-05-03 20:05:29 +080044void ir_arm_unknown_register_to_cper(json_object *registers, FILE *out);
Lawrence Tang3d0e4f22022-07-05 17:17:41 +010045
Lawrence Tang2800cd82022-07-05 16:08:20 +010046//Converts the given processor-generic CPER section into JSON IR.
Ed Tanous12dbd4f2025-03-08 19:05:01 -080047json_object *cper_section_arm_to_ir(const UINT8 *section, UINT32 size)
Lawrence Tang2800cd82022-07-05 16:08:20 +010048{
Ed Tanous12dbd4f2025-03-08 19:05:01 -080049 if (size < sizeof(EFI_ARM_ERROR_RECORD)) {
50 return NULL;
51 }
Lawrence Tange407b4c2022-07-21 13:54:01 +010052 EFI_ARM_ERROR_RECORD *record = (EFI_ARM_ERROR_RECORD *)section;
53 json_object *section_ir = json_object_new_object();
Lawrence Tang2800cd82022-07-05 16:08:20 +010054
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -080055 //Length of ValidationBits from spec
56 ValidationTypes ui64Type = { UINT_64T,
57 .value.ui64 = record->ValidFields };
Lawrence Tang2800cd82022-07-05 16:08:20 +010058
Lawrence Tange407b4c2022-07-21 13:54:01 +010059 //Number of error info and context info structures, and length.
60 json_object_object_add(section_ir, "errorInfoNum",
61 json_object_new_int(record->ErrInfoNum));
62 json_object_object_add(section_ir, "contextInfoNum",
63 json_object_new_int(record->ContextInfoNum));
64 json_object_object_add(section_ir, "sectionLength",
65 json_object_new_uint64(record->SectionLength));
Lawrence Tang2800cd82022-07-05 16:08:20 +010066
Lawrence Tange407b4c2022-07-21 13:54:01 +010067 //Error affinity.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -080068 if (isvalid_prop_to_ir(&ui64Type, 1)) {
69 json_object *error_affinity = json_object_new_object();
70 json_object_object_add(
71 error_affinity, "value",
72 json_object_new_int(record->ErrorAffinityLevel));
73 json_object_object_add(
74 error_affinity, "type",
75 json_object_new_string(record->ErrorAffinityLevel < 4 ?
76 "Vendor Defined" :
77 "Reserved"));
78 json_object_object_add(section_ir, "errorAffinity",
79 error_affinity);
80 }
Lawrence Tang2800cd82022-07-05 16:08:20 +010081
Lawrence Tange407b4c2022-07-21 13:54:01 +010082 //Processor ID (MPIDR_EL1) and chip ID (MIDR_EL1).
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -080083 if (isvalid_prop_to_ir(&ui64Type, 0)) {
84 uint64_t mpidr_eli1 = record->MPIDR_EL1;
85 uint64_t sock;
86 json_object_object_add(section_ir, "mpidrEl1",
87 json_object_new_uint64(mpidr_eli1));
88
89 //Arm Processor socket info dependes on mpidr_eli1
90 sock = (mpidr_eli1 & ARM_SOCK_MASK) >> 32;
91 json_object_object_add(section_ir, "affinity3",
92 json_object_new_uint64(sock));
93 }
Aushim Nagarkatti17bc66a2024-11-25 13:47:35 -080094
Lawrence Tange407b4c2022-07-21 13:54:01 +010095 json_object_object_add(section_ir, "midrEl1",
96 json_object_new_uint64(record->MIDR_EL1));
Lawrence Tang2800cd82022-07-05 16:08:20 +010097
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -080098 if (isvalid_prop_to_ir(&ui64Type, 2)) {
99 //Whether the processor is running, and the state of it if so.
100 json_object_object_add(
101 section_ir, "running",
102 json_object_new_boolean(record->RunningState & 0x1));
103 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100104 if (!(record->RunningState >> 31)) {
105 //Bit 32 of running state is on, so PSCI state information is included.
106 //This can't be made human readable, as it is unknown whether this will be the pre-PSCI 1.0 format
107 //or the newer Extended StateID format.
108 json_object_object_add(
109 section_ir, "psciState",
110 json_object_new_uint64(record->PsciState));
111 }
Lawrence Tang7f21db62022-07-06 11:09:39 +0100112
Lawrence Tange407b4c2022-07-21 13:54:01 +0100113 //Processor error structures.
114 json_object *error_info_array = json_object_new_array();
115 EFI_ARM_ERROR_INFORMATION_ENTRY *cur_error =
116 (EFI_ARM_ERROR_INFORMATION_ENTRY *)(record + 1);
117 for (int i = 0; i < record->ErrInfoNum; i++) {
118 json_object_array_add(error_info_array,
119 cper_arm_error_info_to_ir(cur_error));
120 cur_error++;
121 }
122 json_object_object_add(section_ir, "errorInfo", error_info_array);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100123
Lawrence Tange407b4c2022-07-21 13:54:01 +0100124 //Processor context structures.
125 //The current position is moved within the processing, as it is a dynamic size structure.
John Chungf8fc7052024-05-03 20:05:29 +0800126 uint8_t *cur_pos = (uint8_t *)cur_error;
Lawrence Tange407b4c2022-07-21 13:54:01 +0100127 json_object *context_info_array = json_object_new_array();
128 for (int i = 0; i < record->ContextInfoNum; i++) {
129 EFI_ARM_CONTEXT_INFORMATION_HEADER *header =
130 (EFI_ARM_CONTEXT_INFORMATION_HEADER *)cur_pos;
131 json_object *processor_context =
John Chungf8fc7052024-05-03 20:05:29 +0800132 cper_arm_processor_context_to_ir(header,
133 (void **)&cur_pos);
Lawrence Tange407b4c2022-07-21 13:54:01 +0100134 json_object_array_add(context_info_array, processor_context);
135 }
136 json_object_object_add(section_ir, "contextInfo", context_info_array);
Lawrence Tangd7e8ca32022-07-07 10:25:53 +0100137
Lawrence Tange407b4c2022-07-21 13:54:01 +0100138 //Is there any vendor-specific information following?
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800139 if (isvalid_prop_to_ir(&ui64Type, 3)) {
140 if (cur_pos < (uint8_t *)section + record->SectionLength) {
141 json_object *vendor_specific = json_object_new_object();
142 size_t input_size = (uint8_t *)section +
143 record->SectionLength - cur_pos;
144 int32_t encoded_len = 0;
145 char *encoded = base64_encode(cur_pos, input_size,
146 &encoded_len);
147 if (encoded == NULL) {
148 printf("base64 encode of vendorSpecificInfo failed\n");
149 return NULL;
150 }
151 json_object_object_add(vendor_specific, "data",
152 json_object_new_string_len(
153 encoded, encoded_len));
154 free(encoded);
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700155
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800156 json_object_object_add(section_ir, "vendorSpecificInfo",
157 vendor_specific);
158 } else {
159 printf("vendorSpecificInfo is marked valid but not present in binary\n");
160 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100161 }
162
163 return section_ir;
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100164}
165
166//Converts a single ARM Process Error Information structure into JSON IR.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100167json_object *
168cper_arm_error_info_to_ir(EFI_ARM_ERROR_INFORMATION_ENTRY *error_info)
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100169{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100170 json_object *error_info_ir = json_object_new_object();
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100171
Lawrence Tange407b4c2022-07-21 13:54:01 +0100172 //Version, length.
173 json_object_object_add(error_info_ir, "version",
174 json_object_new_int(error_info->Version));
175 json_object_object_add(error_info_ir, "length",
176 json_object_new_int(error_info->Length));
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100177
Lawrence Tange407b4c2022-07-21 13:54:01 +0100178 //Validation bitfield.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800179 ValidationTypes ui16Type = { UINT_16T,
180 .value.ui16 = error_info->ValidationBits };
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100181
Lawrence Tange407b4c2022-07-21 13:54:01 +0100182 //The type of error information in this log.
183 json_object *error_type = integer_to_readable_pair(
184 error_info->Type, 4, ARM_ERROR_INFO_ENTRY_INFO_TYPES_KEYS,
185 ARM_ERROR_INFO_ENTRY_INFO_TYPES_VALUES, "Unknown (Reserved)");
186 json_object_object_add(error_info_ir, "errorType", error_type);
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100187
Lawrence Tange407b4c2022-07-21 13:54:01 +0100188 //Multiple error count.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800189 if (isvalid_prop_to_ir(&ui16Type, 0)) {
190 json_object *multiple_error = json_object_new_object();
191 json_object_object_add(
192 multiple_error, "value",
193 json_object_new_int(error_info->MultipleError));
194 json_object_object_add(
195 multiple_error, "type",
196 json_object_new_string(error_info->MultipleError < 1 ?
197 "Single Error" :
198 "Multiple Errors"));
199 json_object_object_add(error_info_ir, "multipleError",
200 multiple_error);
201 }
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100202
Lawrence Tange407b4c2022-07-21 13:54:01 +0100203 //Flags.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800204 if (isvalid_prop_to_ir(&ui16Type, 1)) {
205 json_object *flags = bitfield_to_ir(
206 error_info->Flags, 4, ARM_ERROR_INFO_ENTRY_FLAGS_NAMES);
207 json_object_object_add(error_info_ir, "flags", flags);
208 }
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100209
Lawrence Tange407b4c2022-07-21 13:54:01 +0100210 //Error information, split by type.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800211 if (isvalid_prop_to_ir(&ui16Type, 2)) {
212 json_object *error_subinfo = NULL;
213 switch (error_info->Type) {
214 case ARM_ERROR_INFORMATION_TYPE_CACHE: //Cache
215 case ARM_ERROR_INFORMATION_TYPE_TLB: //TLB
216 error_subinfo = cper_arm_cache_tlb_error_to_ir(
217 (EFI_ARM_CACHE_ERROR_STRUCTURE *)&error_info
218 ->ErrorInformation,
219 error_info);
220 break;
221 case ARM_ERROR_INFORMATION_TYPE_BUS: //Bus
222 error_subinfo = cper_arm_bus_error_to_ir(
223 (EFI_ARM_BUS_ERROR_STRUCTURE *)&error_info
224 ->ErrorInformation);
225 break;
Lawrence Tang71570a22022-07-14 11:45:28 +0100226
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800227 default:
228 //Unknown/microarch, will not support.
229 break;
230 }
231 json_object_object_add(error_info_ir, "errorInformation",
232 error_subinfo);
Lawrence Tange407b4c2022-07-21 13:54:01 +0100233 }
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100234
Lawrence Tange407b4c2022-07-21 13:54:01 +0100235 //Virtual fault address, physical fault address.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800236 if (isvalid_prop_to_ir(&ui16Type, 3)) {
237 json_object_object_add(
238 error_info_ir, "virtualFaultAddress",
239 json_object_new_uint64(
240 error_info->VirtualFaultAddress));
241 }
242 if (isvalid_prop_to_ir(&ui16Type, 4)) {
243 json_object_object_add(
244 error_info_ir, "physicalFaultAddress",
245 json_object_new_uint64(
246 error_info->PhysicalFaultAddress));
247 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100248
249 return error_info_ir;
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100250}
251
Lawrence Tang7f21db62022-07-06 11:09:39 +0100252//Converts a single ARM cache/TLB error information structure into JSON IR format.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100253json_object *
254cper_arm_cache_tlb_error_to_ir(EFI_ARM_CACHE_ERROR_STRUCTURE *cache_tlb_error,
255 EFI_ARM_ERROR_INFORMATION_ENTRY *error_info)
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100256{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100257 json_object *cache_tlb_error_ir = json_object_new_object();
Aushim Nagarkatti5b793002024-09-26 17:07:30 -0700258 json_object *cache_tlb_prop = json_object_new_object();
259 char *cache_tlb_propname;
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100260
Lawrence Tange407b4c2022-07-21 13:54:01 +0100261 //Validation bitfield.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800262 ValidationTypes ui64Type = {
263 UINT_64T, .value.ui64 = cache_tlb_error->ValidationBits
264 };
Lawrence Tang7f21db62022-07-06 11:09:39 +0100265
Lawrence Tange407b4c2022-07-21 13:54:01 +0100266 //Transaction type.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800267 if (isvalid_prop_to_ir(&ui64Type, 0)) {
268 json_object *transaction_type = integer_to_readable_pair(
269 cache_tlb_error->TransactionType, 3,
270 ARM_ERROR_TRANSACTION_TYPES_KEYS,
271 ARM_ERROR_TRANSACTION_TYPES_VALUES,
272 "Unknown (Reserved)");
273 json_object_object_add(cache_tlb_error_ir, "transactionType",
274 transaction_type);
275 }
Lawrence Tang7f21db62022-07-06 11:09:39 +0100276
Lawrence Tange407b4c2022-07-21 13:54:01 +0100277 //Operation.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800278 bool cacheErrorFlag = 1;
Lawrence Tange407b4c2022-07-21 13:54:01 +0100279 if (error_info->Type == 0) {
Aushim Nagarkatti5b793002024-09-26 17:07:30 -0700280 cache_tlb_propname = "cacheError";
Lawrence Tange407b4c2022-07-21 13:54:01 +0100281 } else {
282 //TLB operation.
Aushim Nagarkatti5b793002024-09-26 17:07:30 -0700283 cache_tlb_propname = "tlbError";
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800284 cacheErrorFlag = 0;
Lawrence Tange407b4c2022-07-21 13:54:01 +0100285 }
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800286
287 if (isvalid_prop_to_ir(&ui64Type, 1)) {
288 json_object *operation;
289
290 if (cacheErrorFlag) {
291 //Cache operation.
292 operation = integer_to_readable_pair(
293 cache_tlb_error->Operation, 11,
294 ARM_CACHE_BUS_OPERATION_TYPES_KEYS,
295 ARM_CACHE_BUS_OPERATION_TYPES_VALUES,
296 "Unknown (Reserved)");
297 } else {
298 operation = integer_to_readable_pair(
299 cache_tlb_error->Operation, 9,
300 ARM_TLB_OPERATION_TYPES_KEYS,
301 ARM_TLB_OPERATION_TYPES_VALUES,
302 "Unknown (Reserved)");
303 }
304 json_object_object_add(cache_tlb_error_ir, "operation",
305 operation);
306 }
Lawrence Tang7f21db62022-07-06 11:09:39 +0100307
Lawrence Tange407b4c2022-07-21 13:54:01 +0100308 //Miscellaneous remaining fields.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800309 if (isvalid_prop_to_ir(&ui64Type, 2)) {
310 json_object_object_add(
311 cache_tlb_error_ir, "level",
312 json_object_new_int(cache_tlb_error->Level));
313 }
314 if (isvalid_prop_to_ir(&ui64Type, 3)) {
315 json_object_object_add(
316 cache_tlb_error_ir, "processorContextCorrupt",
317 json_object_new_boolean(
318 cache_tlb_error->ProcessorContextCorrupt));
319 }
320 if (isvalid_prop_to_ir(&ui64Type, 4)) {
321 json_object_object_add(
322 cache_tlb_error_ir, "corrected",
323 json_object_new_boolean(cache_tlb_error->Corrected));
324 }
325 if (isvalid_prop_to_ir(&ui64Type, 5)) {
326 json_object_object_add(
327 cache_tlb_error_ir, "precisePC",
328 json_object_new_boolean(cache_tlb_error->PrecisePC));
329 }
330 if (isvalid_prop_to_ir(&ui64Type, 6)) {
331 json_object_object_add(cache_tlb_error_ir, "restartablePC",
332 json_object_new_boolean(
333 cache_tlb_error->RestartablePC));
334 }
Aushim Nagarkatti5b793002024-09-26 17:07:30 -0700335
336 json_object_object_add(cache_tlb_prop, cache_tlb_propname,
337 cache_tlb_error_ir);
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800338
Aushim Nagarkatti5b793002024-09-26 17:07:30 -0700339 return cache_tlb_prop;
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100340}
341
342//Converts a single ARM bus error information structure into JSON IR format.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100343json_object *cper_arm_bus_error_to_ir(EFI_ARM_BUS_ERROR_STRUCTURE *bus_error)
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100344{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100345 json_object *bus_error_ir = json_object_new_object();
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800346 json_object *bus_prop = json_object_new_object();
347 char *bus_propname = "busError";
Lawrence Tang7f21db62022-07-06 11:09:39 +0100348
Lawrence Tange407b4c2022-07-21 13:54:01 +0100349 //Validation bits.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800350 ValidationTypes ui64Type = { UINT_64T,
351 .value.ui64 = bus_error->ValidationBits };
Lawrence Tang7f21db62022-07-06 11:09:39 +0100352
Lawrence Tange407b4c2022-07-21 13:54:01 +0100353 //Transaction type.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800354 if (isvalid_prop_to_ir(&ui64Type, 0)) {
355 json_object *transaction_type = integer_to_readable_pair(
356 bus_error->TransactionType, 3,
357 ARM_ERROR_TRANSACTION_TYPES_KEYS,
358 ARM_ERROR_TRANSACTION_TYPES_VALUES,
359 "Unknown (Reserved)");
360 json_object_object_add(bus_error_ir, "transactionType",
361 transaction_type);
362 }
Lawrence Tang7f21db62022-07-06 11:09:39 +0100363
Lawrence Tange407b4c2022-07-21 13:54:01 +0100364 //Operation.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800365 if (isvalid_prop_to_ir(&ui64Type, 1)) {
366 json_object *operation = integer_to_readable_pair(
367 bus_error->Operation, 7,
368 ARM_CACHE_BUS_OPERATION_TYPES_KEYS,
369 ARM_CACHE_BUS_OPERATION_TYPES_VALUES,
370 "Unknown (Reserved)");
371 json_object_object_add(bus_error_ir, "operation", operation);
372 }
Lawrence Tang7f21db62022-07-06 11:09:39 +0100373
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800374 if (isvalid_prop_to_ir(&ui64Type, 2)) {
375 //Affinity level of bus error, + miscellaneous fields.
376 json_object_object_add(bus_error_ir, "level",
377 json_object_new_int(bus_error->Level));
378 }
379 if (isvalid_prop_to_ir(&ui64Type, 3)) {
380 json_object_object_add(
381 bus_error_ir, "processorContextCorrupt",
382 json_object_new_boolean(
383 bus_error->ProcessorContextCorrupt));
384 }
385 if (isvalid_prop_to_ir(&ui64Type, 4)) {
386 json_object_object_add(
387 bus_error_ir, "corrected",
388 json_object_new_boolean(bus_error->Corrected));
389 }
390 if (isvalid_prop_to_ir(&ui64Type, 5)) {
391 json_object_object_add(
392 bus_error_ir, "precisePC",
393 json_object_new_boolean(bus_error->PrecisePC));
394 }
395 if (isvalid_prop_to_ir(&ui64Type, 6)) {
396 json_object_object_add(
397 bus_error_ir, "restartablePC",
398 json_object_new_boolean(bus_error->RestartablePC));
399 }
Lawrence Tang7f21db62022-07-06 11:09:39 +0100400
Lawrence Tange407b4c2022-07-21 13:54:01 +0100401 //Participation type.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800402 if (isvalid_prop_to_ir(&ui64Type, 7)) {
403 json_object *participation_type = integer_to_readable_pair(
404 bus_error->ParticipationType, 4,
405 ARM_BUS_PARTICIPATION_TYPES_KEYS,
406 ARM_BUS_PARTICIPATION_TYPES_VALUES, "Unknown");
407 json_object_object_add(bus_error_ir, "participationType",
408 participation_type);
409 }
410 if (isvalid_prop_to_ir(&ui64Type, 8)) {
411 json_object_object_add(
412 bus_error_ir, "timedOut",
413 json_object_new_boolean(bus_error->TimeOut));
414 }
Lawrence Tang7f21db62022-07-06 11:09:39 +0100415
Lawrence Tange407b4c2022-07-21 13:54:01 +0100416 //Address space.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800417 if (isvalid_prop_to_ir(&ui64Type, 9)) {
418 json_object *address_space = integer_to_readable_pair(
419 bus_error->AddressSpace, 3,
420 ARM_BUS_ADDRESS_SPACE_TYPES_KEYS,
421 ARM_BUS_ADDRESS_SPACE_TYPES_VALUES, "Unknown");
422 json_object_object_add(bus_error_ir, "addressSpace",
423 address_space);
424 }
Lawrence Tang7f21db62022-07-06 11:09:39 +0100425
Lawrence Tange407b4c2022-07-21 13:54:01 +0100426 //Memory access attributes.
427 //todo: find the specification of these in the ARM ARM
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800428 if (isvalid_prop_to_ir(&ui64Type, 10)) {
429 json_object_object_add(
430 bus_error_ir, "memoryAttributes",
431 json_object_new_int(
432 bus_error->MemoryAddressAttributes));
433 }
Lawrence Tang7f21db62022-07-06 11:09:39 +0100434
Lawrence Tange407b4c2022-07-21 13:54:01 +0100435 //Access Mode
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800436 if (isvalid_prop_to_ir(&ui64Type, 8)) {
437 json_object *access_mode = json_object_new_object();
438 json_object_object_add(
439 access_mode, "value",
440 json_object_new_int(bus_error->AccessMode));
441 json_object_object_add(
442 access_mode, "name",
443 json_object_new_string(bus_error->AccessMode == 0 ?
444 "Secure" :
445 "Normal"));
446 json_object_object_add(bus_error_ir, "accessMode", access_mode);
447 }
448 json_object_object_add(bus_prop, bus_propname, bus_error_ir);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100449
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800450 return bus_prop;
Lawrence Tang7f21db62022-07-06 11:09:39 +0100451}
452
453//Converts a single ARM processor context block into JSON IR.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100454json_object *
455cper_arm_processor_context_to_ir(EFI_ARM_CONTEXT_INFORMATION_HEADER *header,
456 void **cur_pos)
Lawrence Tang7f21db62022-07-06 11:09:39 +0100457{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100458 json_object *context_ir = json_object_new_object();
Lawrence Tang7f21db62022-07-06 11:09:39 +0100459
Lawrence Tange407b4c2022-07-21 13:54:01 +0100460 //Version.
461 json_object_object_add(context_ir, "version",
462 json_object_new_int(header->Version));
Lawrence Tang71570a22022-07-14 11:45:28 +0100463
Lawrence Tange407b4c2022-07-21 13:54:01 +0100464 //Add the context type.
465 json_object *context_type = integer_to_readable_pair(
466 header->RegisterContextType, 9,
467 ARM_PROCESSOR_INFO_REGISTER_CONTEXT_TYPES_KEYS,
468 ARM_PROCESSOR_INFO_REGISTER_CONTEXT_TYPES_VALUES,
469 "Unknown (Reserved)");
470 json_object_object_add(context_ir, "registerContextType", context_type);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100471
Lawrence Tange407b4c2022-07-21 13:54:01 +0100472 //Register array size (bytes).
473 json_object_object_add(
474 context_ir, "registerArraySize",
475 json_object_new_uint64(header->RegisterArraySize));
Lawrence Tang7f21db62022-07-06 11:09:39 +0100476
Lawrence Tange407b4c2022-07-21 13:54:01 +0100477 //The register array itself.
478 *cur_pos = (void *)(header + 1);
479 json_object *register_array = NULL;
480 switch (header->RegisterContextType) {
481 case EFI_ARM_CONTEXT_TYPE_AARCH32_GPR:
482 register_array = uniform_struct_to_ir(
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800483 (UINT32 *)*cur_pos,
Lawrence Tange407b4c2022-07-21 13:54:01 +0100484 sizeof(EFI_ARM_V8_AARCH32_GPR) / sizeof(UINT32),
485 ARM_AARCH32_GPR_NAMES);
486 break;
487 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL1:
488 register_array = uniform_struct_to_ir(
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800489 (UINT32 *)*cur_pos,
Lawrence Tange407b4c2022-07-21 13:54:01 +0100490 sizeof(EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS) /
491 sizeof(UINT32),
492 ARM_AARCH32_EL1_REGISTER_NAMES);
493 break;
494 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL2:
495 register_array = uniform_struct_to_ir(
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800496 (UINT32 *)*cur_pos,
Lawrence Tange407b4c2022-07-21 13:54:01 +0100497 sizeof(EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS) /
498 sizeof(UINT32),
499 ARM_AARCH32_EL2_REGISTER_NAMES);
500 break;
501 case EFI_ARM_CONTEXT_TYPE_AARCH32_SECURE:
502 register_array = uniform_struct_to_ir(
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800503 (UINT32 *)*cur_pos,
Lawrence Tange407b4c2022-07-21 13:54:01 +0100504 sizeof(EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS) /
505 sizeof(UINT32),
506 ARM_AARCH32_SECURE_REGISTER_NAMES);
507 break;
508 case EFI_ARM_CONTEXT_TYPE_AARCH64_GPR:
509 register_array = uniform_struct64_to_ir(
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800510 (UINT64 *)*cur_pos,
Lawrence Tange407b4c2022-07-21 13:54:01 +0100511 sizeof(EFI_ARM_V8_AARCH64_GPR) / sizeof(UINT64),
512 ARM_AARCH64_GPR_NAMES);
513 break;
514 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL1:
515 register_array = uniform_struct64_to_ir(
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800516 (UINT64 *)*cur_pos,
Lawrence Tange407b4c2022-07-21 13:54:01 +0100517 sizeof(EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS) /
518 sizeof(UINT64),
519 ARM_AARCH64_EL1_REGISTER_NAMES);
520 break;
521 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL2:
522 register_array = uniform_struct64_to_ir(
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800523 (UINT64 *)*cur_pos,
Lawrence Tange407b4c2022-07-21 13:54:01 +0100524 sizeof(EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS) /
525 sizeof(UINT64),
526 ARM_AARCH64_EL2_REGISTER_NAMES);
527 break;
528 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL3:
529 register_array = uniform_struct64_to_ir(
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800530 (UINT64 *)*cur_pos,
Lawrence Tange407b4c2022-07-21 13:54:01 +0100531 sizeof(EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS) /
532 sizeof(UINT64),
533 ARM_AARCH64_EL3_REGISTER_NAMES);
534 break;
535 case EFI_ARM_CONTEXT_TYPE_MISC:
536 register_array = cper_arm_misc_register_array_to_ir(
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800537 (EFI_ARM_MISC_CONTEXT_REGISTER *)*cur_pos);
Lawrence Tange407b4c2022-07-21 13:54:01 +0100538 break;
539 default:
540 //Unknown register array type, add as base64 data instead.
541 register_array = json_object_new_object();
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700542 int32_t encoded_len = 0;
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800543 char *encoded = base64_encode((UINT8 *)*cur_pos,
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700544 header->RegisterArraySize,
545 &encoded_len);
546 if (encoded == NULL) {
John Chungf8fc7052024-05-03 20:05:29 +0800547 printf("Failed to allocate encode output buffer. \n");
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700548 return NULL;
John Chungf8fc7052024-05-03 20:05:29 +0800549 }
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700550 json_object_object_add(register_array, "data",
551 json_object_new_string_len(encoded,
552 encoded_len));
553 free(encoded);
554
Lawrence Tange407b4c2022-07-21 13:54:01 +0100555 break;
556 }
557 json_object_object_add(context_ir, "registerArray", register_array);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100558
Lawrence Tange407b4c2022-07-21 13:54:01 +0100559 //Set the current position to after the processor context structure.
560 *cur_pos = (UINT8 *)(*cur_pos) + header->RegisterArraySize;
Lawrence Tang7f21db62022-07-06 11:09:39 +0100561
Lawrence Tange407b4c2022-07-21 13:54:01 +0100562 return context_ir;
Lawrence Tang7f21db62022-07-06 11:09:39 +0100563}
564
565//Converts a single CPER ARM miscellaneous register array to JSON IR format.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100566json_object *
567cper_arm_misc_register_array_to_ir(EFI_ARM_MISC_CONTEXT_REGISTER *misc_register)
Lawrence Tang7f21db62022-07-06 11:09:39 +0100568{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100569 json_object *register_array = json_object_new_object();
570 json_object *mrs_encoding = json_object_new_object();
571 json_object_object_add(mrs_encoding, "op2",
572 json_object_new_uint64(misc_register->MrsOp2));
573 json_object_object_add(mrs_encoding, "crm",
574 json_object_new_uint64(misc_register->MrsCrm));
575 json_object_object_add(mrs_encoding, "crn",
576 json_object_new_uint64(misc_register->MrsCrn));
577 json_object_object_add(mrs_encoding, "op1",
578 json_object_new_uint64(misc_register->MrsOp1));
579 json_object_object_add(mrs_encoding, "o0",
580 json_object_new_uint64(misc_register->MrsO0));
581 json_object_object_add(register_array, "mrsEncoding", mrs_encoding);
582 json_object_object_add(register_array, "value",
583 json_object_new_uint64(misc_register->Value));
Lawrence Tang7f21db62022-07-06 11:09:39 +0100584
Lawrence Tange407b4c2022-07-21 13:54:01 +0100585 return register_array;
Lawrence Tang7cd13902022-07-13 16:59:25 +0100586}
587
588//Converts a single CPER-JSON ARM error section into CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100589void ir_section_arm_to_cper(json_object *section, FILE *out)
Lawrence Tang7cd13902022-07-13 16:59:25 +0100590{
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800591 EFI_ARM_ERROR_RECORD section_cper;
592 memset(&section_cper, 0, sizeof(section_cper));
Lawrence Tang7cd13902022-07-13 16:59:25 +0100593
Lawrence Tange407b4c2022-07-21 13:54:01 +0100594 //Validation bits.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800595 struct json_object *obj = NULL;
596 ValidationTypes u32Type = { UINT_32T, .value.ui32 = 0 };
Lawrence Tang7cd13902022-07-13 16:59:25 +0100597
Lawrence Tange407b4c2022-07-21 13:54:01 +0100598 //Count of error/context info structures.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800599 section_cper.ErrInfoNum = json_object_get_int(
Lawrence Tange407b4c2022-07-21 13:54:01 +0100600 json_object_object_get(section, "errorInfoNum"));
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800601 section_cper.ContextInfoNum = json_object_get_int(
Lawrence Tange407b4c2022-07-21 13:54:01 +0100602 json_object_object_get(section, "contextInfoNum"));
Lawrence Tang7cd13902022-07-13 16:59:25 +0100603
Lawrence Tange407b4c2022-07-21 13:54:01 +0100604 //Miscellaneous raw value fields.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800605 section_cper.SectionLength = json_object_get_uint64(
Lawrence Tange407b4c2022-07-21 13:54:01 +0100606 json_object_object_get(section, "sectionLength"));
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800607 if (json_object_object_get_ex(section, "mpidrEl1", &obj)) {
608 section_cper.MPIDR_EL1 = json_object_get_uint64(obj);
609 add_to_valid_bitfield(&u32Type, 0);
610 }
611 if (json_object_object_get_ex(section, "errorAffinity", &obj)) {
612 section_cper.ErrorAffinityLevel = readable_pair_to_integer(obj);
613 add_to_valid_bitfield(&u32Type, 1);
614 }
615 section_cper.MIDR_EL1 = json_object_get_uint64(
Lawrence Tange407b4c2022-07-21 13:54:01 +0100616 json_object_object_get(section, "midrEl1"));
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800617 if (json_object_object_get_ex(section, "running", &obj)) {
618 section_cper.RunningState = json_object_get_boolean(obj);
619 add_to_valid_bitfield(&u32Type, 2);
620 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100621
Lawrence Tange407b4c2022-07-21 13:54:01 +0100622 //Optional PSCI state.
623 json_object *psci_state = json_object_object_get(section, "psciState");
John Chungf8fc7052024-05-03 20:05:29 +0800624 if (psci_state != NULL) {
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800625 section_cper.PsciState = json_object_get_uint64(psci_state);
John Chungf8fc7052024-05-03 20:05:29 +0800626 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100627
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800628 //Validationbits for EFI_ARM_ERROR_RECORD should also consider vendorSpecificInfo
629 bool vendorSpecificPresent =
630 json_object_object_get_ex(section, "vendorSpecificInfo", &obj);
631 json_object *vendor_specific_info = obj;
632 if (vendorSpecificPresent) {
633 add_to_valid_bitfield(&u32Type, 3);
634 }
635
636 section_cper.ValidFields = u32Type.value.ui32;
637
Lawrence Tange407b4c2022-07-21 13:54:01 +0100638 //Flush header to stream.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800639 fwrite(&section_cper, sizeof(section_cper), 1, out);
Lawrence Tang7cd13902022-07-13 16:59:25 +0100640
Lawrence Tange407b4c2022-07-21 13:54:01 +0100641 //Error info structure array.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800642
Lawrence Tange407b4c2022-07-21 13:54:01 +0100643 json_object *error_info = json_object_object_get(section, "errorInfo");
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800644 for (int i = 0; i < section_cper.ErrInfoNum; i++) {
Lawrence Tange407b4c2022-07-21 13:54:01 +0100645 ir_arm_error_info_to_cper(
646 json_object_array_get_idx(error_info, i), out);
John Chungf8fc7052024-05-03 20:05:29 +0800647 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100648
Lawrence Tange407b4c2022-07-21 13:54:01 +0100649 //Context info structure array.
650 json_object *context_info =
651 json_object_object_get(section, "contextInfo");
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800652 for (int i = 0; i < section_cper.ContextInfoNum; i++) {
Lawrence Tange407b4c2022-07-21 13:54:01 +0100653 ir_arm_context_info_to_cper(
654 json_object_array_get_idx(context_info, i), out);
John Chungf8fc7052024-05-03 20:05:29 +0800655 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100656
Lawrence Tange407b4c2022-07-21 13:54:01 +0100657 //Vendor specific error info.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800658 if (vendorSpecificPresent) {
Lawrence Tange407b4c2022-07-21 13:54:01 +0100659 json_object *vendor_info_string =
660 json_object_object_get(vendor_specific_info, "data");
661 int vendor_specific_len =
662 json_object_get_string_len(vendor_info_string);
Lawrence Tang01e3a442022-07-20 15:14:50 +0100663
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700664 int32_t decoded_len = 0;
665
666 UINT8 *decoded = base64_decode(
667 json_object_get_string(vendor_info_string),
668 vendor_specific_len, &decoded_len);
669
670 //Write out to file.
671 fwrite(decoded, decoded_len, 1, out);
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700672 free(decoded);
Lawrence Tange407b4c2022-07-21 13:54:01 +0100673 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100674
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800675 fflush(out);
Lawrence Tang7cd13902022-07-13 16:59:25 +0100676}
677
678//Converts a single ARM error information structure into CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100679void ir_arm_error_info_to_cper(json_object *error_info, FILE *out)
Lawrence Tang7cd13902022-07-13 16:59:25 +0100680{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100681 EFI_ARM_ERROR_INFORMATION_ENTRY error_info_cper;
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800682 memset(&error_info_cper, 0, sizeof(error_info_cper));
683 struct json_object *obj = NULL;
684 ValidationTypes ui16Type = { UINT_16T, .value.ui16 = 0 };
Lawrence Tang7cd13902022-07-13 16:59:25 +0100685
Lawrence Tange407b4c2022-07-21 13:54:01 +0100686 //Version, length.
687 error_info_cper.Version = json_object_get_int(
688 json_object_object_get(error_info, "version"));
689 error_info_cper.Length = json_object_get_int(
690 json_object_object_get(error_info, "length"));
Lawrence Tang7cd13902022-07-13 16:59:25 +0100691
Lawrence Tange407b4c2022-07-21 13:54:01 +0100692 //Type, multiple error.
693 error_info_cper.Type = (UINT8)readable_pair_to_integer(
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800694 json_object_object_get(error_info, "errorType"));
695
696 if (json_object_object_get_ex(error_info, "multipleError", &obj)) {
697 error_info_cper.MultipleError =
698 (UINT16)readable_pair_to_integer(obj);
699 add_to_valid_bitfield(&ui16Type, 0);
700 } else {
701 error_info_cper.MultipleError = 0;
702 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100703
Lawrence Tange407b4c2022-07-21 13:54:01 +0100704 //Flags object.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800705 if (json_object_object_get_ex(error_info, "flags", &obj)) {
706 error_info_cper.Flags = (UINT8)ir_to_bitfield(
707 obj, 4, ARM_ERROR_INFO_ENTRY_FLAGS_NAMES);
708 add_to_valid_bitfield(&ui16Type, 1);
709 } else {
710 error_info_cper.Flags = 0;
711 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100712
Lawrence Tange407b4c2022-07-21 13:54:01 +0100713 //Error information.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800714 if (json_object_object_get_ex(error_info, "errorInformation", &obj)) {
715 json_object *error_info_information = obj;
716 json_object *error_info_prop = NULL;
717 switch (error_info_cper.Type) {
718 case ARM_ERROR_INFORMATION_TYPE_CACHE:
719 error_info_cper.ErrorInformation.Value = 0;
720 error_info_prop = json_object_object_get(
721 error_info_information, "cacheError");
722 ir_arm_error_cache_tlb_info_to_cper(
723 error_info_prop,
724 &error_info_cper.ErrorInformation.CacheError);
725 break;
726 case ARM_ERROR_INFORMATION_TYPE_TLB:
727 error_info_cper.ErrorInformation.Value = 0;
728 error_info_prop = json_object_object_get(
729 error_info_information, "tlbError");
730 ir_arm_error_cache_tlb_info_to_cper(
731 error_info_prop,
732 &error_info_cper.ErrorInformation.CacheError);
733 break;
Aushim Nagarkatti5b793002024-09-26 17:07:30 -0700734
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800735 case ARM_ERROR_INFORMATION_TYPE_BUS:
736 error_info_cper.ErrorInformation.Value = 0;
737 error_info_prop = json_object_object_get(
738 error_info_information, "busError");
739 ir_arm_error_bus_info_to_cper(
740 error_info_prop,
741 &error_info_cper.ErrorInformation.BusError);
742 break;
Lawrence Tang71570a22022-07-14 11:45:28 +0100743
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800744 default:
745 //Unknown error information type.
746 break;
747 }
748 add_to_valid_bitfield(&ui16Type, 2);
Lawrence Tange407b4c2022-07-21 13:54:01 +0100749 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100750
Lawrence Tange407b4c2022-07-21 13:54:01 +0100751 //Virtual/physical fault address.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800752 if (json_object_object_get_ex(error_info, "virtualFaultAddress",
753 &obj)) {
754 error_info_cper.VirtualFaultAddress =
755 json_object_get_uint64(obj);
756 add_to_valid_bitfield(&ui16Type, 3);
757 } else {
758 error_info_cper.VirtualFaultAddress = 0;
759 }
760
761 if (json_object_object_get_ex(error_info, "physicalFaultAddress",
762 &obj)) {
763 error_info_cper.PhysicalFaultAddress =
764 json_object_get_uint64(obj);
765 add_to_valid_bitfield(&ui16Type, 4);
766 } else {
767 error_info_cper.PhysicalFaultAddress = 0;
768 }
769 error_info_cper.ValidationBits = ui16Type.value.ui16;
Lawrence Tang7cd13902022-07-13 16:59:25 +0100770
Lawrence Tange407b4c2022-07-21 13:54:01 +0100771 //Write out to stream.
772 fwrite(&error_info_cper, sizeof(EFI_ARM_ERROR_INFORMATION_ENTRY), 1,
773 out);
Lawrence Tang7cd13902022-07-13 16:59:25 +0100774}
775
Lawrence Tang71570a22022-07-14 11:45:28 +0100776//Converts a single ARM cache/TLB error information structure into a CPER structure.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100777void ir_arm_error_cache_tlb_info_to_cper(
778 json_object *error_information,
779 EFI_ARM_CACHE_ERROR_STRUCTURE *error_info_cper)
Lawrence Tang71570a22022-07-14 11:45:28 +0100780{
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800781 // //Validation bits.
782 ValidationTypes ui64Type = { UINT_64T, .value.ui64 = 0 };
783 struct json_object *obj = NULL;
Lawrence Tang71570a22022-07-14 11:45:28 +0100784
Lawrence Tange407b4c2022-07-21 13:54:01 +0100785 //Miscellaneous value fields.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800786 if (json_object_object_get_ex(error_information, "transactionType",
787 &obj)) {
788 error_info_cper->TransactionType =
789 readable_pair_to_integer(obj);
790 add_to_valid_bitfield(&ui64Type, 0);
791 }
792 if (json_object_object_get_ex(error_information, "operation", &obj)) {
793 error_info_cper->Operation = readable_pair_to_integer(obj);
794 add_to_valid_bitfield(&ui64Type, 1);
795 }
796 if (json_object_object_get_ex(error_information, "level", &obj)) {
797 error_info_cper->Level = json_object_get_uint64(obj);
798 add_to_valid_bitfield(&ui64Type, 2);
799 }
800 if (json_object_object_get_ex(error_information,
801 "processorContextCorrupt", &obj)) {
802 error_info_cper->ProcessorContextCorrupt =
803 json_object_get_boolean(obj);
804 add_to_valid_bitfield(&ui64Type, 3);
805 }
806 if (json_object_object_get_ex(error_information, "corrected", &obj)) {
807 error_info_cper->Corrected = json_object_get_boolean(obj);
808 add_to_valid_bitfield(&ui64Type, 4);
809 }
810 if (json_object_object_get_ex(error_information, "precisePC", &obj)) {
811 error_info_cper->PrecisePC = json_object_get_boolean(obj);
812 add_to_valid_bitfield(&ui64Type, 5);
813 }
814 if (json_object_object_get_ex(error_information, "restartablePC",
815 &obj)) {
816 error_info_cper->RestartablePC = json_object_get_boolean(obj);
817 add_to_valid_bitfield(&ui64Type, 6);
818 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100819 error_info_cper->Reserved = 0;
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800820 error_info_cper->ValidationBits = ui64Type.value.ui64;
Lawrence Tang71570a22022-07-14 11:45:28 +0100821}
822
823//Converts a single ARM bus error information structure into a CPER structure.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100824void ir_arm_error_bus_info_to_cper(json_object *error_information,
825 EFI_ARM_BUS_ERROR_STRUCTURE *error_info_cper)
Lawrence Tang71570a22022-07-14 11:45:28 +0100826{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100827 //Validation bits.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800828 ValidationTypes ui64Type = { UINT_64T, .value.ui64 = 0 };
829 struct json_object *obj = NULL;
830
831 memset(error_info_cper, 0, sizeof(EFI_ARM_BUS_ERROR_STRUCTURE));
Lawrence Tang71570a22022-07-14 11:45:28 +0100832
Lawrence Tange407b4c2022-07-21 13:54:01 +0100833 //Miscellaneous value fields.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800834 if (json_object_object_get_ex(error_information, "transactionType",
835 &obj)) {
836 error_info_cper->TransactionType =
837 readable_pair_to_integer(obj);
838 add_to_valid_bitfield(&ui64Type, 0);
839 } else {
840 error_info_cper->TransactionType = 0;
841 }
842 if (json_object_object_get_ex(error_information, "operation", &obj)) {
843 error_info_cper->Operation = readable_pair_to_integer(obj);
844 add_to_valid_bitfield(&ui64Type, 1);
845 } else {
846 error_info_cper->Operation = 0;
847 }
848 if (json_object_object_get_ex(error_information, "level", &obj)) {
849 error_info_cper->Level = json_object_get_uint64(obj);
850 add_to_valid_bitfield(&ui64Type, 2);
851 } else {
852 error_info_cper->Level = 0;
853 }
854 if (json_object_object_get_ex(error_information,
855 "processorContextCorrupt", &obj)) {
856 error_info_cper->ProcessorContextCorrupt =
857 json_object_get_boolean(obj);
858 add_to_valid_bitfield(&ui64Type, 3);
859 } else {
860 error_info_cper->ProcessorContextCorrupt = 0;
861 }
862 if (json_object_object_get_ex(error_information, "corrected", &obj)) {
863 error_info_cper->Corrected = json_object_get_boolean(obj);
864 add_to_valid_bitfield(&ui64Type, 4);
865 } else {
866 error_info_cper->Corrected = 0;
867 }
868 if (json_object_object_get_ex(error_information, "precisePC", &obj)) {
869 error_info_cper->PrecisePC = json_object_get_boolean(obj);
870 add_to_valid_bitfield(&ui64Type, 5);
871 } else {
872 error_info_cper->PrecisePC = 0;
873 }
874 if (json_object_object_get_ex(error_information, "restartablePC",
875 &obj)) {
876 error_info_cper->RestartablePC = json_object_get_boolean(obj);
877 add_to_valid_bitfield(&ui64Type, 6);
878 } else {
879 error_info_cper->RestartablePC = 0;
880 }
881 if (json_object_object_get_ex(error_information, "participationType",
882 &obj)) {
883 error_info_cper->ParticipationType =
884 readable_pair_to_integer(obj);
885 add_to_valid_bitfield(&ui64Type, 7);
886 } else {
887 error_info_cper->ParticipationType = 0;
888 }
889 if (json_object_object_get_ex(error_information, "timedOut", &obj)) {
890 error_info_cper->TimeOut = json_object_get_boolean(obj);
891 add_to_valid_bitfield(&ui64Type, 8);
892 } else {
893 error_info_cper->TimeOut = 0;
894 }
895 if (json_object_object_get_ex(error_information, "addressSpace",
896 &obj)) {
897 error_info_cper->AddressSpace = readable_pair_to_integer(obj);
898 add_to_valid_bitfield(&ui64Type, 9);
899 } else {
900 error_info_cper->AddressSpace = 0;
901 }
902 if (json_object_object_get_ex(error_information, "accessMode", &obj)) {
903 error_info_cper->AccessMode = readable_pair_to_integer(obj);
904 add_to_valid_bitfield(&ui64Type, 11);
905 } else {
906 error_info_cper->AccessMode = 0;
907 }
908 if (json_object_object_get_ex(error_information, "memoryAttributes",
909 &obj)) {
910 error_info_cper->MemoryAddressAttributes =
911 json_object_get_uint64(obj);
912 add_to_valid_bitfield(&ui64Type, 10);
913 } else {
914 error_info_cper->MemoryAddressAttributes = 0;
915 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100916 error_info_cper->Reserved = 0;
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800917 error_info_cper->ValidationBits = ui64Type.value.ui64;
Lawrence Tang71570a22022-07-14 11:45:28 +0100918}
919
Lawrence Tang7cd13902022-07-13 16:59:25 +0100920//Converts a single ARM context information structure into CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100921void ir_arm_context_info_to_cper(json_object *context_info, FILE *out)
Lawrence Tang7cd13902022-07-13 16:59:25 +0100922{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100923 EFI_ARM_CONTEXT_INFORMATION_HEADER info_header;
Lawrence Tang7cd13902022-07-13 16:59:25 +0100924
Lawrence Tange407b4c2022-07-21 13:54:01 +0100925 //Version, array size, context type.
926 info_header.Version = json_object_get_int(
927 json_object_object_get(context_info, "version"));
928 info_header.RegisterArraySize = json_object_get_int(
929 json_object_object_get(context_info, "registerArraySize"));
930 info_header.RegisterContextType = readable_pair_to_integer(
931 json_object_object_get(context_info, "registerContextType"));
Lawrence Tang71570a22022-07-14 11:45:28 +0100932
Lawrence Tange407b4c2022-07-21 13:54:01 +0100933 //Flush to stream, write the register array itself.
934 fwrite(&info_header, sizeof(EFI_ARM_CONTEXT_INFORMATION_HEADER), 1,
935 out);
936 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100937
Lawrence Tange407b4c2022-07-21 13:54:01 +0100938 json_object *register_array =
939 json_object_object_get(context_info, "registerArray");
940 switch (info_header.RegisterContextType) {
941 case EFI_ARM_CONTEXT_TYPE_AARCH32_GPR:
942 ir_arm_aarch32_gpr_to_cper(register_array, out);
943 break;
944 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL1:
945 ir_arm_aarch32_el1_to_cper(register_array, out);
946 break;
947 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL2:
948 ir_arm_aarch32_el2_to_cper(register_array, out);
949 break;
950 case EFI_ARM_CONTEXT_TYPE_AARCH32_SECURE:
951 ir_arm_aarch32_secure_to_cper(register_array, out);
952 break;
953 case EFI_ARM_CONTEXT_TYPE_AARCH64_GPR:
954 ir_arm_aarch64_gpr_to_cper(register_array, out);
955 break;
956 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL1:
957 ir_arm_aarch64_el1_to_cper(register_array, out);
958 break;
959 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL2:
960 ir_arm_aarch64_el2_to_cper(register_array, out);
961 break;
962 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL3:
963 ir_arm_aarch64_el3_to_cper(register_array, out);
964 break;
965 case EFI_ARM_CONTEXT_TYPE_MISC:
966 ir_arm_misc_registers_to_cper(register_array, out);
967 break;
968 default:
969 //Unknown register structure.
John Chungf8fc7052024-05-03 20:05:29 +0800970 ir_arm_unknown_register_to_cper(register_array, out);
Lawrence Tange407b4c2022-07-21 13:54:01 +0100971 break;
972 }
Lawrence Tang71570a22022-07-14 11:45:28 +0100973}
974
975//Converts a single AARCH32 GPR CPER-JSON object to CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100976void ir_arm_aarch32_gpr_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100977{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100978 //Get uniform register array.
979 EFI_ARM_V8_AARCH32_GPR reg_array;
980 ir_to_uniform_struct(registers, (UINT32 *)&reg_array,
981 sizeof(EFI_ARM_V8_AARCH32_GPR) / sizeof(UINT32),
982 ARM_AARCH32_GPR_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100983
Lawrence Tange407b4c2022-07-21 13:54:01 +0100984 //Flush to stream.
985 fwrite(&reg_array, sizeof(reg_array), 1, out);
986 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100987}
988
989//Converts a single AARCH32 EL1 register set CPER-JSON object to CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100990void ir_arm_aarch32_el1_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100991{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100992 //Get uniform register array.
993 EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS reg_array;
994 ir_to_uniform_struct(registers, (UINT32 *)&reg_array,
995 sizeof(EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS) /
996 sizeof(UINT32),
997 ARM_AARCH32_EL1_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100998
Lawrence Tange407b4c2022-07-21 13:54:01 +0100999 //Flush to stream.
1000 fwrite(&reg_array, sizeof(reg_array), 1, out);
1001 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +01001002}
1003
1004//Converts a single AARCH32 EL2 register set CPER-JSON object to CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +01001005void ir_arm_aarch32_el2_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +01001006{
Lawrence Tange407b4c2022-07-21 13:54:01 +01001007 //Get uniform register array.
1008 EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS reg_array;
1009 ir_to_uniform_struct(registers, (UINT32 *)&reg_array,
1010 sizeof(EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS) /
1011 sizeof(UINT32),
1012 ARM_AARCH32_EL2_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +01001013
Lawrence Tange407b4c2022-07-21 13:54:01 +01001014 //Flush to stream.
1015 fwrite(&reg_array, sizeof(reg_array), 1, out);
1016 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +01001017}
1018
1019//Converts a single AARCH32 secure register set CPER-JSON object to CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +01001020void ir_arm_aarch32_secure_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +01001021{
Lawrence Tange407b4c2022-07-21 13:54:01 +01001022 //Get uniform register array.
1023 EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS reg_array;
1024 ir_to_uniform_struct(registers, (UINT32 *)&reg_array,
1025 sizeof(EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS) /
1026 sizeof(UINT32),
1027 ARM_AARCH32_SECURE_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +01001028
Lawrence Tange407b4c2022-07-21 13:54:01 +01001029 //Flush to stream.
1030 fwrite(&reg_array, sizeof(reg_array), 1, out);
1031 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +01001032}
1033
1034//Converts a single AARCH64 GPR CPER-JSON object to CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +01001035void ir_arm_aarch64_gpr_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +01001036{
Lawrence Tange407b4c2022-07-21 13:54:01 +01001037 //Get uniform register array.
1038 EFI_ARM_V8_AARCH64_GPR reg_array;
1039 ir_to_uniform_struct64(registers, (UINT64 *)&reg_array,
1040 sizeof(EFI_ARM_V8_AARCH64_GPR) / sizeof(UINT64),
1041 ARM_AARCH64_GPR_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +01001042
Lawrence Tange407b4c2022-07-21 13:54:01 +01001043 //Flush to stream.
1044 fwrite(&reg_array, sizeof(reg_array), 1, out);
1045 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +01001046}
1047
1048//Converts a single AARCH64 EL1 register set CPER-JSON object to CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +01001049void ir_arm_aarch64_el1_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +01001050{
Lawrence Tange407b4c2022-07-21 13:54:01 +01001051 //Get uniform register array.
1052 EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS reg_array;
1053 ir_to_uniform_struct64(registers, (UINT64 *)&reg_array,
1054 sizeof(EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS) /
1055 sizeof(UINT64),
1056 ARM_AARCH64_EL1_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +01001057
Lawrence Tange407b4c2022-07-21 13:54:01 +01001058 //Flush to stream.
1059 fwrite(&reg_array, sizeof(reg_array), 1, out);
1060 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +01001061}
1062
1063//Converts a single AARCH64 EL2 register set CPER-JSON object to CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +01001064void ir_arm_aarch64_el2_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +01001065{
Lawrence Tange407b4c2022-07-21 13:54:01 +01001066 //Get uniform register array.
1067 EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS reg_array;
1068 ir_to_uniform_struct64(registers, (UINT64 *)&reg_array,
1069 sizeof(EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS) /
1070 sizeof(UINT64),
1071 ARM_AARCH64_EL2_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +01001072
Lawrence Tange407b4c2022-07-21 13:54:01 +01001073 //Flush to stream.
1074 fwrite(&reg_array, sizeof(reg_array), 1, out);
1075 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +01001076}
1077
1078//Converts a single AARCH64 EL3 register set CPER-JSON object to CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +01001079void ir_arm_aarch64_el3_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +01001080{
Lawrence Tange407b4c2022-07-21 13:54:01 +01001081 //Get uniform register array.
1082 EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS reg_array;
1083 ir_to_uniform_struct64(registers, (UINT64 *)&reg_array,
1084 sizeof(EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS) /
1085 sizeof(UINT64),
1086 ARM_AARCH64_EL3_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +01001087
Lawrence Tange407b4c2022-07-21 13:54:01 +01001088 //Flush to stream.
1089 fwrite(&reg_array, sizeof(reg_array), 1, out);
1090 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +01001091}
1092
1093//Converts a single ARM miscellaneous register set CPER-JSON object to CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +01001094void ir_arm_misc_registers_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +01001095{
Lawrence Tange407b4c2022-07-21 13:54:01 +01001096 EFI_ARM_MISC_CONTEXT_REGISTER reg_array;
Lawrence Tang71570a22022-07-14 11:45:28 +01001097
Lawrence Tange407b4c2022-07-21 13:54:01 +01001098 //MRS encoding information.
1099 json_object *mrs_encoding =
1100 json_object_object_get(registers, "mrsEncoding");
1101 reg_array.MrsOp2 = json_object_get_uint64(
1102 json_object_object_get(mrs_encoding, "op2"));
1103 reg_array.MrsCrm = json_object_get_uint64(
1104 json_object_object_get(mrs_encoding, "crm"));
1105 reg_array.MrsCrn = json_object_get_uint64(
1106 json_object_object_get(mrs_encoding, "crn"));
1107 reg_array.MrsOp1 = json_object_get_uint64(
1108 json_object_object_get(mrs_encoding, "op1"));
1109 reg_array.MrsO0 = json_object_get_uint64(
1110 json_object_object_get(mrs_encoding, "o0"));
Lawrence Tang71570a22022-07-14 11:45:28 +01001111
Lawrence Tange407b4c2022-07-21 13:54:01 +01001112 //Actual register value.
1113 reg_array.Value = json_object_get_uint64(
1114 json_object_object_get(registers, "value"));
Lawrence Tang71570a22022-07-14 11:45:28 +01001115
Lawrence Tange407b4c2022-07-21 13:54:01 +01001116 //Flush to stream.
1117 fwrite(&reg_array, sizeof(reg_array), 1, out);
1118 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +01001119}
1120
1121//Converts a single ARM unknown register CPER-JSON object to CPER binary, outputting to the given stream.
John Chungf8fc7052024-05-03 20:05:29 +08001122void ir_arm_unknown_register_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +01001123{
Lawrence Tange407b4c2022-07-21 13:54:01 +01001124 //Get base64 represented data.
1125 json_object *encoded = json_object_object_get(registers, "data");
Ed Tanousa7d2cdd2024-07-15 11:07:27 -07001126
1127 int32_t decoded_len = 0;
1128
1129 UINT8 *decoded = base64_decode(json_object_get_string(encoded),
1130 json_object_get_string_len(encoded),
1131 &decoded_len);
1132
1133 if (decoded == NULL) {
John Chungf8fc7052024-05-03 20:05:29 +08001134 printf("Failed to allocate decode output buffer. \n");
1135 } else {
John Chungf8fc7052024-05-03 20:05:29 +08001136 //Flush out to stream.
1137 fwrite(&decoded, decoded_len, 1, out);
1138 fflush(out);
1139 free(decoded);
1140 }
1141}