blob: 31fa9b0271d81ebd87adb42c5e37bdc84d90235e [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 Tanous5aedbb22025-03-05 18:02:34 -080047json_object *cper_section_arm_to_ir(const void *section)
Lawrence Tang2800cd82022-07-05 16:08:20 +010048{
Lawrence Tange407b4c2022-07-21 13:54:01 +010049 EFI_ARM_ERROR_RECORD *record = (EFI_ARM_ERROR_RECORD *)section;
50 json_object *section_ir = json_object_new_object();
Lawrence Tang2800cd82022-07-05 16:08:20 +010051
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -080052 //Length of ValidationBits from spec
53 ValidationTypes ui64Type = { UINT_64T,
54 .value.ui64 = record->ValidFields };
Lawrence Tang2800cd82022-07-05 16:08:20 +010055
Lawrence Tange407b4c2022-07-21 13:54:01 +010056 //Number of error info and context info structures, and length.
57 json_object_object_add(section_ir, "errorInfoNum",
58 json_object_new_int(record->ErrInfoNum));
59 json_object_object_add(section_ir, "contextInfoNum",
60 json_object_new_int(record->ContextInfoNum));
61 json_object_object_add(section_ir, "sectionLength",
62 json_object_new_uint64(record->SectionLength));
Lawrence Tang2800cd82022-07-05 16:08:20 +010063
Lawrence Tange407b4c2022-07-21 13:54:01 +010064 //Error affinity.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -080065 if (isvalid_prop_to_ir(&ui64Type, 1)) {
66 json_object *error_affinity = json_object_new_object();
67 json_object_object_add(
68 error_affinity, "value",
69 json_object_new_int(record->ErrorAffinityLevel));
70 json_object_object_add(
71 error_affinity, "type",
72 json_object_new_string(record->ErrorAffinityLevel < 4 ?
73 "Vendor Defined" :
74 "Reserved"));
75 json_object_object_add(section_ir, "errorAffinity",
76 error_affinity);
77 }
Lawrence Tang2800cd82022-07-05 16:08:20 +010078
Lawrence Tange407b4c2022-07-21 13:54:01 +010079 //Processor ID (MPIDR_EL1) and chip ID (MIDR_EL1).
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -080080 if (isvalid_prop_to_ir(&ui64Type, 0)) {
81 uint64_t mpidr_eli1 = record->MPIDR_EL1;
82 uint64_t sock;
83 json_object_object_add(section_ir, "mpidrEl1",
84 json_object_new_uint64(mpidr_eli1));
85
86 //Arm Processor socket info dependes on mpidr_eli1
87 sock = (mpidr_eli1 & ARM_SOCK_MASK) >> 32;
88 json_object_object_add(section_ir, "affinity3",
89 json_object_new_uint64(sock));
90 }
Aushim Nagarkatti17bc66a2024-11-25 13:47:35 -080091
Lawrence Tange407b4c2022-07-21 13:54:01 +010092 json_object_object_add(section_ir, "midrEl1",
93 json_object_new_uint64(record->MIDR_EL1));
Lawrence Tang2800cd82022-07-05 16:08:20 +010094
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -080095 if (isvalid_prop_to_ir(&ui64Type, 2)) {
96 //Whether the processor is running, and the state of it if so.
97 json_object_object_add(
98 section_ir, "running",
99 json_object_new_boolean(record->RunningState & 0x1));
100 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100101 if (!(record->RunningState >> 31)) {
102 //Bit 32 of running state is on, so PSCI state information is included.
103 //This can't be made human readable, as it is unknown whether this will be the pre-PSCI 1.0 format
104 //or the newer Extended StateID format.
105 json_object_object_add(
106 section_ir, "psciState",
107 json_object_new_uint64(record->PsciState));
108 }
Lawrence Tang7f21db62022-07-06 11:09:39 +0100109
Lawrence Tange407b4c2022-07-21 13:54:01 +0100110 //Processor error structures.
111 json_object *error_info_array = json_object_new_array();
112 EFI_ARM_ERROR_INFORMATION_ENTRY *cur_error =
113 (EFI_ARM_ERROR_INFORMATION_ENTRY *)(record + 1);
114 for (int i = 0; i < record->ErrInfoNum; i++) {
115 json_object_array_add(error_info_array,
116 cper_arm_error_info_to_ir(cur_error));
117 cur_error++;
118 }
119 json_object_object_add(section_ir, "errorInfo", error_info_array);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100120
Lawrence Tange407b4c2022-07-21 13:54:01 +0100121 //Processor context structures.
122 //The current position is moved within the processing, as it is a dynamic size structure.
John Chungf8fc7052024-05-03 20:05:29 +0800123 uint8_t *cur_pos = (uint8_t *)cur_error;
Lawrence Tange407b4c2022-07-21 13:54:01 +0100124 json_object *context_info_array = json_object_new_array();
125 for (int i = 0; i < record->ContextInfoNum; i++) {
126 EFI_ARM_CONTEXT_INFORMATION_HEADER *header =
127 (EFI_ARM_CONTEXT_INFORMATION_HEADER *)cur_pos;
128 json_object *processor_context =
John Chungf8fc7052024-05-03 20:05:29 +0800129 cper_arm_processor_context_to_ir(header,
130 (void **)&cur_pos);
Lawrence Tange407b4c2022-07-21 13:54:01 +0100131 json_object_array_add(context_info_array, processor_context);
132 }
133 json_object_object_add(section_ir, "contextInfo", context_info_array);
Lawrence Tangd7e8ca32022-07-07 10:25:53 +0100134
Lawrence Tange407b4c2022-07-21 13:54:01 +0100135 //Is there any vendor-specific information following?
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800136 if (isvalid_prop_to_ir(&ui64Type, 3)) {
137 if (cur_pos < (uint8_t *)section + record->SectionLength) {
138 json_object *vendor_specific = json_object_new_object();
139 size_t input_size = (uint8_t *)section +
140 record->SectionLength - cur_pos;
141 int32_t encoded_len = 0;
142 char *encoded = base64_encode(cur_pos, input_size,
143 &encoded_len);
144 if (encoded == NULL) {
145 printf("base64 encode of vendorSpecificInfo failed\n");
146 return NULL;
147 }
148 json_object_object_add(vendor_specific, "data",
149 json_object_new_string_len(
150 encoded, encoded_len));
151 free(encoded);
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700152
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800153 json_object_object_add(section_ir, "vendorSpecificInfo",
154 vendor_specific);
155 } else {
156 printf("vendorSpecificInfo is marked valid but not present in binary\n");
157 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100158 }
159
160 return section_ir;
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100161}
162
163//Converts a single ARM Process Error Information structure into JSON IR.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100164json_object *
165cper_arm_error_info_to_ir(EFI_ARM_ERROR_INFORMATION_ENTRY *error_info)
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100166{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100167 json_object *error_info_ir = json_object_new_object();
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100168
Lawrence Tange407b4c2022-07-21 13:54:01 +0100169 //Version, length.
170 json_object_object_add(error_info_ir, "version",
171 json_object_new_int(error_info->Version));
172 json_object_object_add(error_info_ir, "length",
173 json_object_new_int(error_info->Length));
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100174
Lawrence Tange407b4c2022-07-21 13:54:01 +0100175 //Validation bitfield.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800176 ValidationTypes ui16Type = { UINT_16T,
177 .value.ui16 = error_info->ValidationBits };
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100178
Lawrence Tange407b4c2022-07-21 13:54:01 +0100179 //The type of error information in this log.
180 json_object *error_type = integer_to_readable_pair(
181 error_info->Type, 4, ARM_ERROR_INFO_ENTRY_INFO_TYPES_KEYS,
182 ARM_ERROR_INFO_ENTRY_INFO_TYPES_VALUES, "Unknown (Reserved)");
183 json_object_object_add(error_info_ir, "errorType", error_type);
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100184
Lawrence Tange407b4c2022-07-21 13:54:01 +0100185 //Multiple error count.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800186 if (isvalid_prop_to_ir(&ui16Type, 0)) {
187 json_object *multiple_error = json_object_new_object();
188 json_object_object_add(
189 multiple_error, "value",
190 json_object_new_int(error_info->MultipleError));
191 json_object_object_add(
192 multiple_error, "type",
193 json_object_new_string(error_info->MultipleError < 1 ?
194 "Single Error" :
195 "Multiple Errors"));
196 json_object_object_add(error_info_ir, "multipleError",
197 multiple_error);
198 }
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100199
Lawrence Tange407b4c2022-07-21 13:54:01 +0100200 //Flags.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800201 if (isvalid_prop_to_ir(&ui16Type, 1)) {
202 json_object *flags = bitfield_to_ir(
203 error_info->Flags, 4, ARM_ERROR_INFO_ENTRY_FLAGS_NAMES);
204 json_object_object_add(error_info_ir, "flags", flags);
205 }
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100206
Lawrence Tange407b4c2022-07-21 13:54:01 +0100207 //Error information, split by type.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800208 if (isvalid_prop_to_ir(&ui16Type, 2)) {
209 json_object *error_subinfo = NULL;
210 switch (error_info->Type) {
211 case ARM_ERROR_INFORMATION_TYPE_CACHE: //Cache
212 case ARM_ERROR_INFORMATION_TYPE_TLB: //TLB
213 error_subinfo = cper_arm_cache_tlb_error_to_ir(
214 (EFI_ARM_CACHE_ERROR_STRUCTURE *)&error_info
215 ->ErrorInformation,
216 error_info);
217 break;
218 case ARM_ERROR_INFORMATION_TYPE_BUS: //Bus
219 error_subinfo = cper_arm_bus_error_to_ir(
220 (EFI_ARM_BUS_ERROR_STRUCTURE *)&error_info
221 ->ErrorInformation);
222 break;
Lawrence Tang71570a22022-07-14 11:45:28 +0100223
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800224 default:
225 //Unknown/microarch, will not support.
226 break;
227 }
228 json_object_object_add(error_info_ir, "errorInformation",
229 error_subinfo);
Lawrence Tange407b4c2022-07-21 13:54:01 +0100230 }
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100231
Lawrence Tange407b4c2022-07-21 13:54:01 +0100232 //Virtual fault address, physical fault address.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800233 if (isvalid_prop_to_ir(&ui16Type, 3)) {
234 json_object_object_add(
235 error_info_ir, "virtualFaultAddress",
236 json_object_new_uint64(
237 error_info->VirtualFaultAddress));
238 }
239 if (isvalid_prop_to_ir(&ui16Type, 4)) {
240 json_object_object_add(
241 error_info_ir, "physicalFaultAddress",
242 json_object_new_uint64(
243 error_info->PhysicalFaultAddress));
244 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100245
246 return error_info_ir;
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100247}
248
Lawrence Tang7f21db62022-07-06 11:09:39 +0100249//Converts a single ARM cache/TLB error information structure into JSON IR format.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100250json_object *
251cper_arm_cache_tlb_error_to_ir(EFI_ARM_CACHE_ERROR_STRUCTURE *cache_tlb_error,
252 EFI_ARM_ERROR_INFORMATION_ENTRY *error_info)
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100253{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100254 json_object *cache_tlb_error_ir = json_object_new_object();
Aushim Nagarkatti5b793002024-09-26 17:07:30 -0700255 json_object *cache_tlb_prop = json_object_new_object();
256 char *cache_tlb_propname;
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100257
Lawrence Tange407b4c2022-07-21 13:54:01 +0100258 //Validation bitfield.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800259 ValidationTypes ui64Type = {
260 UINT_64T, .value.ui64 = cache_tlb_error->ValidationBits
261 };
Lawrence Tang7f21db62022-07-06 11:09:39 +0100262
Lawrence Tange407b4c2022-07-21 13:54:01 +0100263 //Transaction type.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800264 if (isvalid_prop_to_ir(&ui64Type, 0)) {
265 json_object *transaction_type = integer_to_readable_pair(
266 cache_tlb_error->TransactionType, 3,
267 ARM_ERROR_TRANSACTION_TYPES_KEYS,
268 ARM_ERROR_TRANSACTION_TYPES_VALUES,
269 "Unknown (Reserved)");
270 json_object_object_add(cache_tlb_error_ir, "transactionType",
271 transaction_type);
272 }
Lawrence Tang7f21db62022-07-06 11:09:39 +0100273
Lawrence Tange407b4c2022-07-21 13:54:01 +0100274 //Operation.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800275 bool cacheErrorFlag = 1;
Lawrence Tange407b4c2022-07-21 13:54:01 +0100276 if (error_info->Type == 0) {
Aushim Nagarkatti5b793002024-09-26 17:07:30 -0700277 cache_tlb_propname = "cacheError";
Lawrence Tange407b4c2022-07-21 13:54:01 +0100278 } else {
279 //TLB operation.
Aushim Nagarkatti5b793002024-09-26 17:07:30 -0700280 cache_tlb_propname = "tlbError";
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800281 cacheErrorFlag = 0;
Lawrence Tange407b4c2022-07-21 13:54:01 +0100282 }
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800283
284 if (isvalid_prop_to_ir(&ui64Type, 1)) {
285 json_object *operation;
286
287 if (cacheErrorFlag) {
288 //Cache operation.
289 operation = integer_to_readable_pair(
290 cache_tlb_error->Operation, 11,
291 ARM_CACHE_BUS_OPERATION_TYPES_KEYS,
292 ARM_CACHE_BUS_OPERATION_TYPES_VALUES,
293 "Unknown (Reserved)");
294 } else {
295 operation = integer_to_readable_pair(
296 cache_tlb_error->Operation, 9,
297 ARM_TLB_OPERATION_TYPES_KEYS,
298 ARM_TLB_OPERATION_TYPES_VALUES,
299 "Unknown (Reserved)");
300 }
301 json_object_object_add(cache_tlb_error_ir, "operation",
302 operation);
303 }
Lawrence Tang7f21db62022-07-06 11:09:39 +0100304
Lawrence Tange407b4c2022-07-21 13:54:01 +0100305 //Miscellaneous remaining fields.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800306 if (isvalid_prop_to_ir(&ui64Type, 2)) {
307 json_object_object_add(
308 cache_tlb_error_ir, "level",
309 json_object_new_int(cache_tlb_error->Level));
310 }
311 if (isvalid_prop_to_ir(&ui64Type, 3)) {
312 json_object_object_add(
313 cache_tlb_error_ir, "processorContextCorrupt",
314 json_object_new_boolean(
315 cache_tlb_error->ProcessorContextCorrupt));
316 }
317 if (isvalid_prop_to_ir(&ui64Type, 4)) {
318 json_object_object_add(
319 cache_tlb_error_ir, "corrected",
320 json_object_new_boolean(cache_tlb_error->Corrected));
321 }
322 if (isvalid_prop_to_ir(&ui64Type, 5)) {
323 json_object_object_add(
324 cache_tlb_error_ir, "precisePC",
325 json_object_new_boolean(cache_tlb_error->PrecisePC));
326 }
327 if (isvalid_prop_to_ir(&ui64Type, 6)) {
328 json_object_object_add(cache_tlb_error_ir, "restartablePC",
329 json_object_new_boolean(
330 cache_tlb_error->RestartablePC));
331 }
Aushim Nagarkatti5b793002024-09-26 17:07:30 -0700332
333 json_object_object_add(cache_tlb_prop, cache_tlb_propname,
334 cache_tlb_error_ir);
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800335
Aushim Nagarkatti5b793002024-09-26 17:07:30 -0700336 return cache_tlb_prop;
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100337}
338
339//Converts a single ARM bus error information structure into JSON IR format.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100340json_object *cper_arm_bus_error_to_ir(EFI_ARM_BUS_ERROR_STRUCTURE *bus_error)
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100341{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100342 json_object *bus_error_ir = json_object_new_object();
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800343 json_object *bus_prop = json_object_new_object();
344 char *bus_propname = "busError";
Lawrence Tang7f21db62022-07-06 11:09:39 +0100345
Lawrence Tange407b4c2022-07-21 13:54:01 +0100346 //Validation bits.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800347 ValidationTypes ui64Type = { UINT_64T,
348 .value.ui64 = bus_error->ValidationBits };
Lawrence Tang7f21db62022-07-06 11:09:39 +0100349
Lawrence Tange407b4c2022-07-21 13:54:01 +0100350 //Transaction type.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800351 if (isvalid_prop_to_ir(&ui64Type, 0)) {
352 json_object *transaction_type = integer_to_readable_pair(
353 bus_error->TransactionType, 3,
354 ARM_ERROR_TRANSACTION_TYPES_KEYS,
355 ARM_ERROR_TRANSACTION_TYPES_VALUES,
356 "Unknown (Reserved)");
357 json_object_object_add(bus_error_ir, "transactionType",
358 transaction_type);
359 }
Lawrence Tang7f21db62022-07-06 11:09:39 +0100360
Lawrence Tange407b4c2022-07-21 13:54:01 +0100361 //Operation.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800362 if (isvalid_prop_to_ir(&ui64Type, 1)) {
363 json_object *operation = integer_to_readable_pair(
364 bus_error->Operation, 7,
365 ARM_CACHE_BUS_OPERATION_TYPES_KEYS,
366 ARM_CACHE_BUS_OPERATION_TYPES_VALUES,
367 "Unknown (Reserved)");
368 json_object_object_add(bus_error_ir, "operation", operation);
369 }
Lawrence Tang7f21db62022-07-06 11:09:39 +0100370
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800371 if (isvalid_prop_to_ir(&ui64Type, 2)) {
372 //Affinity level of bus error, + miscellaneous fields.
373 json_object_object_add(bus_error_ir, "level",
374 json_object_new_int(bus_error->Level));
375 }
376 if (isvalid_prop_to_ir(&ui64Type, 3)) {
377 json_object_object_add(
378 bus_error_ir, "processorContextCorrupt",
379 json_object_new_boolean(
380 bus_error->ProcessorContextCorrupt));
381 }
382 if (isvalid_prop_to_ir(&ui64Type, 4)) {
383 json_object_object_add(
384 bus_error_ir, "corrected",
385 json_object_new_boolean(bus_error->Corrected));
386 }
387 if (isvalid_prop_to_ir(&ui64Type, 5)) {
388 json_object_object_add(
389 bus_error_ir, "precisePC",
390 json_object_new_boolean(bus_error->PrecisePC));
391 }
392 if (isvalid_prop_to_ir(&ui64Type, 6)) {
393 json_object_object_add(
394 bus_error_ir, "restartablePC",
395 json_object_new_boolean(bus_error->RestartablePC));
396 }
Lawrence Tang7f21db62022-07-06 11:09:39 +0100397
Lawrence Tange407b4c2022-07-21 13:54:01 +0100398 //Participation type.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800399 if (isvalid_prop_to_ir(&ui64Type, 7)) {
400 json_object *participation_type = integer_to_readable_pair(
401 bus_error->ParticipationType, 4,
402 ARM_BUS_PARTICIPATION_TYPES_KEYS,
403 ARM_BUS_PARTICIPATION_TYPES_VALUES, "Unknown");
404 json_object_object_add(bus_error_ir, "participationType",
405 participation_type);
406 }
407 if (isvalid_prop_to_ir(&ui64Type, 8)) {
408 json_object_object_add(
409 bus_error_ir, "timedOut",
410 json_object_new_boolean(bus_error->TimeOut));
411 }
Lawrence Tang7f21db62022-07-06 11:09:39 +0100412
Lawrence Tange407b4c2022-07-21 13:54:01 +0100413 //Address space.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800414 if (isvalid_prop_to_ir(&ui64Type, 9)) {
415 json_object *address_space = integer_to_readable_pair(
416 bus_error->AddressSpace, 3,
417 ARM_BUS_ADDRESS_SPACE_TYPES_KEYS,
418 ARM_BUS_ADDRESS_SPACE_TYPES_VALUES, "Unknown");
419 json_object_object_add(bus_error_ir, "addressSpace",
420 address_space);
421 }
Lawrence Tang7f21db62022-07-06 11:09:39 +0100422
Lawrence Tange407b4c2022-07-21 13:54:01 +0100423 //Memory access attributes.
424 //todo: find the specification of these in the ARM ARM
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800425 if (isvalid_prop_to_ir(&ui64Type, 10)) {
426 json_object_object_add(
427 bus_error_ir, "memoryAttributes",
428 json_object_new_int(
429 bus_error->MemoryAddressAttributes));
430 }
Lawrence Tang7f21db62022-07-06 11:09:39 +0100431
Lawrence Tange407b4c2022-07-21 13:54:01 +0100432 //Access Mode
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800433 if (isvalid_prop_to_ir(&ui64Type, 8)) {
434 json_object *access_mode = json_object_new_object();
435 json_object_object_add(
436 access_mode, "value",
437 json_object_new_int(bus_error->AccessMode));
438 json_object_object_add(
439 access_mode, "name",
440 json_object_new_string(bus_error->AccessMode == 0 ?
441 "Secure" :
442 "Normal"));
443 json_object_object_add(bus_error_ir, "accessMode", access_mode);
444 }
445 json_object_object_add(bus_prop, bus_propname, bus_error_ir);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100446
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800447 return bus_prop;
Lawrence Tang7f21db62022-07-06 11:09:39 +0100448}
449
450//Converts a single ARM processor context block into JSON IR.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100451json_object *
452cper_arm_processor_context_to_ir(EFI_ARM_CONTEXT_INFORMATION_HEADER *header,
453 void **cur_pos)
Lawrence Tang7f21db62022-07-06 11:09:39 +0100454{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100455 json_object *context_ir = json_object_new_object();
Lawrence Tang7f21db62022-07-06 11:09:39 +0100456
Lawrence Tange407b4c2022-07-21 13:54:01 +0100457 //Version.
458 json_object_object_add(context_ir, "version",
459 json_object_new_int(header->Version));
Lawrence Tang71570a22022-07-14 11:45:28 +0100460
Lawrence Tange407b4c2022-07-21 13:54:01 +0100461 //Add the context type.
462 json_object *context_type = integer_to_readable_pair(
463 header->RegisterContextType, 9,
464 ARM_PROCESSOR_INFO_REGISTER_CONTEXT_TYPES_KEYS,
465 ARM_PROCESSOR_INFO_REGISTER_CONTEXT_TYPES_VALUES,
466 "Unknown (Reserved)");
467 json_object_object_add(context_ir, "registerContextType", context_type);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100468
Lawrence Tange407b4c2022-07-21 13:54:01 +0100469 //Register array size (bytes).
470 json_object_object_add(
471 context_ir, "registerArraySize",
472 json_object_new_uint64(header->RegisterArraySize));
Lawrence Tang7f21db62022-07-06 11:09:39 +0100473
Lawrence Tange407b4c2022-07-21 13:54:01 +0100474 //The register array itself.
475 *cur_pos = (void *)(header + 1);
476 json_object *register_array = NULL;
477 switch (header->RegisterContextType) {
478 case EFI_ARM_CONTEXT_TYPE_AARCH32_GPR:
479 register_array = uniform_struct_to_ir(
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800480 (UINT32 *)*cur_pos,
Lawrence Tange407b4c2022-07-21 13:54:01 +0100481 sizeof(EFI_ARM_V8_AARCH32_GPR) / sizeof(UINT32),
482 ARM_AARCH32_GPR_NAMES);
483 break;
484 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL1:
485 register_array = uniform_struct_to_ir(
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800486 (UINT32 *)*cur_pos,
Lawrence Tange407b4c2022-07-21 13:54:01 +0100487 sizeof(EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS) /
488 sizeof(UINT32),
489 ARM_AARCH32_EL1_REGISTER_NAMES);
490 break;
491 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL2:
492 register_array = uniform_struct_to_ir(
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800493 (UINT32 *)*cur_pos,
Lawrence Tange407b4c2022-07-21 13:54:01 +0100494 sizeof(EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS) /
495 sizeof(UINT32),
496 ARM_AARCH32_EL2_REGISTER_NAMES);
497 break;
498 case EFI_ARM_CONTEXT_TYPE_AARCH32_SECURE:
499 register_array = uniform_struct_to_ir(
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800500 (UINT32 *)*cur_pos,
Lawrence Tange407b4c2022-07-21 13:54:01 +0100501 sizeof(EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS) /
502 sizeof(UINT32),
503 ARM_AARCH32_SECURE_REGISTER_NAMES);
504 break;
505 case EFI_ARM_CONTEXT_TYPE_AARCH64_GPR:
506 register_array = uniform_struct64_to_ir(
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800507 (UINT64 *)*cur_pos,
Lawrence Tange407b4c2022-07-21 13:54:01 +0100508 sizeof(EFI_ARM_V8_AARCH64_GPR) / sizeof(UINT64),
509 ARM_AARCH64_GPR_NAMES);
510 break;
511 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL1:
512 register_array = uniform_struct64_to_ir(
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800513 (UINT64 *)*cur_pos,
Lawrence Tange407b4c2022-07-21 13:54:01 +0100514 sizeof(EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS) /
515 sizeof(UINT64),
516 ARM_AARCH64_EL1_REGISTER_NAMES);
517 break;
518 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL2:
519 register_array = uniform_struct64_to_ir(
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800520 (UINT64 *)*cur_pos,
Lawrence Tange407b4c2022-07-21 13:54:01 +0100521 sizeof(EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS) /
522 sizeof(UINT64),
523 ARM_AARCH64_EL2_REGISTER_NAMES);
524 break;
525 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL3:
526 register_array = uniform_struct64_to_ir(
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800527 (UINT64 *)*cur_pos,
Lawrence Tange407b4c2022-07-21 13:54:01 +0100528 sizeof(EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS) /
529 sizeof(UINT64),
530 ARM_AARCH64_EL3_REGISTER_NAMES);
531 break;
532 case EFI_ARM_CONTEXT_TYPE_MISC:
533 register_array = cper_arm_misc_register_array_to_ir(
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800534 (EFI_ARM_MISC_CONTEXT_REGISTER *)*cur_pos);
Lawrence Tange407b4c2022-07-21 13:54:01 +0100535 break;
536 default:
537 //Unknown register array type, add as base64 data instead.
538 register_array = json_object_new_object();
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700539 int32_t encoded_len = 0;
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800540 char *encoded = base64_encode((UINT8 *)*cur_pos,
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700541 header->RegisterArraySize,
542 &encoded_len);
543 if (encoded == NULL) {
John Chungf8fc7052024-05-03 20:05:29 +0800544 printf("Failed to allocate encode output buffer. \n");
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700545 return NULL;
John Chungf8fc7052024-05-03 20:05:29 +0800546 }
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700547 json_object_object_add(register_array, "data",
548 json_object_new_string_len(encoded,
549 encoded_len));
550 free(encoded);
551
Lawrence Tange407b4c2022-07-21 13:54:01 +0100552 break;
553 }
554 json_object_object_add(context_ir, "registerArray", register_array);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100555
Lawrence Tange407b4c2022-07-21 13:54:01 +0100556 //Set the current position to after the processor context structure.
557 *cur_pos = (UINT8 *)(*cur_pos) + header->RegisterArraySize;
Lawrence Tang7f21db62022-07-06 11:09:39 +0100558
Lawrence Tange407b4c2022-07-21 13:54:01 +0100559 return context_ir;
Lawrence Tang7f21db62022-07-06 11:09:39 +0100560}
561
562//Converts a single CPER ARM miscellaneous register array to JSON IR format.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100563json_object *
564cper_arm_misc_register_array_to_ir(EFI_ARM_MISC_CONTEXT_REGISTER *misc_register)
Lawrence Tang7f21db62022-07-06 11:09:39 +0100565{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100566 json_object *register_array = json_object_new_object();
567 json_object *mrs_encoding = json_object_new_object();
568 json_object_object_add(mrs_encoding, "op2",
569 json_object_new_uint64(misc_register->MrsOp2));
570 json_object_object_add(mrs_encoding, "crm",
571 json_object_new_uint64(misc_register->MrsCrm));
572 json_object_object_add(mrs_encoding, "crn",
573 json_object_new_uint64(misc_register->MrsCrn));
574 json_object_object_add(mrs_encoding, "op1",
575 json_object_new_uint64(misc_register->MrsOp1));
576 json_object_object_add(mrs_encoding, "o0",
577 json_object_new_uint64(misc_register->MrsO0));
578 json_object_object_add(register_array, "mrsEncoding", mrs_encoding);
579 json_object_object_add(register_array, "value",
580 json_object_new_uint64(misc_register->Value));
Lawrence Tang7f21db62022-07-06 11:09:39 +0100581
Lawrence Tange407b4c2022-07-21 13:54:01 +0100582 return register_array;
Lawrence Tang7cd13902022-07-13 16:59:25 +0100583}
584
585//Converts a single CPER-JSON ARM error section into CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100586void ir_section_arm_to_cper(json_object *section, FILE *out)
Lawrence Tang7cd13902022-07-13 16:59:25 +0100587{
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800588 EFI_ARM_ERROR_RECORD section_cper;
589 memset(&section_cper, 0, sizeof(section_cper));
Lawrence Tang7cd13902022-07-13 16:59:25 +0100590
Lawrence Tange407b4c2022-07-21 13:54:01 +0100591 //Validation bits.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800592 struct json_object *obj = NULL;
593 ValidationTypes u32Type = { UINT_32T, .value.ui32 = 0 };
Lawrence Tang7cd13902022-07-13 16:59:25 +0100594
Lawrence Tange407b4c2022-07-21 13:54:01 +0100595 //Count of error/context info structures.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800596 section_cper.ErrInfoNum = json_object_get_int(
Lawrence Tange407b4c2022-07-21 13:54:01 +0100597 json_object_object_get(section, "errorInfoNum"));
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800598 section_cper.ContextInfoNum = json_object_get_int(
Lawrence Tange407b4c2022-07-21 13:54:01 +0100599 json_object_object_get(section, "contextInfoNum"));
Lawrence Tang7cd13902022-07-13 16:59:25 +0100600
Lawrence Tange407b4c2022-07-21 13:54:01 +0100601 //Miscellaneous raw value fields.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800602 section_cper.SectionLength = json_object_get_uint64(
Lawrence Tange407b4c2022-07-21 13:54:01 +0100603 json_object_object_get(section, "sectionLength"));
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800604 if (json_object_object_get_ex(section, "mpidrEl1", &obj)) {
605 section_cper.MPIDR_EL1 = json_object_get_uint64(obj);
606 add_to_valid_bitfield(&u32Type, 0);
607 }
608 if (json_object_object_get_ex(section, "errorAffinity", &obj)) {
609 section_cper.ErrorAffinityLevel = readable_pair_to_integer(obj);
610 add_to_valid_bitfield(&u32Type, 1);
611 }
612 section_cper.MIDR_EL1 = json_object_get_uint64(
Lawrence Tange407b4c2022-07-21 13:54:01 +0100613 json_object_object_get(section, "midrEl1"));
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800614 if (json_object_object_get_ex(section, "running", &obj)) {
615 section_cper.RunningState = json_object_get_boolean(obj);
616 add_to_valid_bitfield(&u32Type, 2);
617 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100618
Lawrence Tange407b4c2022-07-21 13:54:01 +0100619 //Optional PSCI state.
620 json_object *psci_state = json_object_object_get(section, "psciState");
John Chungf8fc7052024-05-03 20:05:29 +0800621 if (psci_state != NULL) {
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800622 section_cper.PsciState = json_object_get_uint64(psci_state);
John Chungf8fc7052024-05-03 20:05:29 +0800623 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100624
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800625 //Validationbits for EFI_ARM_ERROR_RECORD should also consider vendorSpecificInfo
626 bool vendorSpecificPresent =
627 json_object_object_get_ex(section, "vendorSpecificInfo", &obj);
628 json_object *vendor_specific_info = obj;
629 if (vendorSpecificPresent) {
630 add_to_valid_bitfield(&u32Type, 3);
631 }
632
633 section_cper.ValidFields = u32Type.value.ui32;
634
Lawrence Tange407b4c2022-07-21 13:54:01 +0100635 //Flush header to stream.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800636 fwrite(&section_cper, sizeof(section_cper), 1, out);
Lawrence Tang7cd13902022-07-13 16:59:25 +0100637
Lawrence Tange407b4c2022-07-21 13:54:01 +0100638 //Error info structure array.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800639
Lawrence Tange407b4c2022-07-21 13:54:01 +0100640 json_object *error_info = json_object_object_get(section, "errorInfo");
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800641 for (int i = 0; i < section_cper.ErrInfoNum; i++) {
Lawrence Tange407b4c2022-07-21 13:54:01 +0100642 ir_arm_error_info_to_cper(
643 json_object_array_get_idx(error_info, i), out);
John Chungf8fc7052024-05-03 20:05:29 +0800644 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100645
Lawrence Tange407b4c2022-07-21 13:54:01 +0100646 //Context info structure array.
647 json_object *context_info =
648 json_object_object_get(section, "contextInfo");
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800649 for (int i = 0; i < section_cper.ContextInfoNum; i++) {
Lawrence Tange407b4c2022-07-21 13:54:01 +0100650 ir_arm_context_info_to_cper(
651 json_object_array_get_idx(context_info, i), out);
John Chungf8fc7052024-05-03 20:05:29 +0800652 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100653
Lawrence Tange407b4c2022-07-21 13:54:01 +0100654 //Vendor specific error info.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800655 if (vendorSpecificPresent) {
Lawrence Tange407b4c2022-07-21 13:54:01 +0100656 json_object *vendor_info_string =
657 json_object_object_get(vendor_specific_info, "data");
658 int vendor_specific_len =
659 json_object_get_string_len(vendor_info_string);
Lawrence Tang01e3a442022-07-20 15:14:50 +0100660
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700661 int32_t decoded_len = 0;
662
663 UINT8 *decoded = base64_decode(
664 json_object_get_string(vendor_info_string),
665 vendor_specific_len, &decoded_len);
666
667 //Write out to file.
668 fwrite(decoded, decoded_len, 1, out);
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700669 free(decoded);
Lawrence Tange407b4c2022-07-21 13:54:01 +0100670 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100671
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800672 fflush(out);
Lawrence Tang7cd13902022-07-13 16:59:25 +0100673}
674
675//Converts a single ARM error information structure into CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100676void ir_arm_error_info_to_cper(json_object *error_info, FILE *out)
Lawrence Tang7cd13902022-07-13 16:59:25 +0100677{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100678 EFI_ARM_ERROR_INFORMATION_ENTRY error_info_cper;
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800679 memset(&error_info_cper, 0, sizeof(error_info_cper));
680 struct json_object *obj = NULL;
681 ValidationTypes ui16Type = { UINT_16T, .value.ui16 = 0 };
Lawrence Tang7cd13902022-07-13 16:59:25 +0100682
Lawrence Tange407b4c2022-07-21 13:54:01 +0100683 //Version, length.
684 error_info_cper.Version = json_object_get_int(
685 json_object_object_get(error_info, "version"));
686 error_info_cper.Length = json_object_get_int(
687 json_object_object_get(error_info, "length"));
Lawrence Tang7cd13902022-07-13 16:59:25 +0100688
Lawrence Tange407b4c2022-07-21 13:54:01 +0100689 //Type, multiple error.
690 error_info_cper.Type = (UINT8)readable_pair_to_integer(
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800691 json_object_object_get(error_info, "errorType"));
692
693 if (json_object_object_get_ex(error_info, "multipleError", &obj)) {
694 error_info_cper.MultipleError =
695 (UINT16)readable_pair_to_integer(obj);
696 add_to_valid_bitfield(&ui16Type, 0);
697 } else {
698 error_info_cper.MultipleError = 0;
699 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100700
Lawrence Tange407b4c2022-07-21 13:54:01 +0100701 //Flags object.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800702 if (json_object_object_get_ex(error_info, "flags", &obj)) {
703 error_info_cper.Flags = (UINT8)ir_to_bitfield(
704 obj, 4, ARM_ERROR_INFO_ENTRY_FLAGS_NAMES);
705 add_to_valid_bitfield(&ui16Type, 1);
706 } else {
707 error_info_cper.Flags = 0;
708 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100709
Lawrence Tange407b4c2022-07-21 13:54:01 +0100710 //Error information.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800711 if (json_object_object_get_ex(error_info, "errorInformation", &obj)) {
712 json_object *error_info_information = obj;
713 json_object *error_info_prop = NULL;
714 switch (error_info_cper.Type) {
715 case ARM_ERROR_INFORMATION_TYPE_CACHE:
716 error_info_cper.ErrorInformation.Value = 0;
717 error_info_prop = json_object_object_get(
718 error_info_information, "cacheError");
719 ir_arm_error_cache_tlb_info_to_cper(
720 error_info_prop,
721 &error_info_cper.ErrorInformation.CacheError);
722 break;
723 case ARM_ERROR_INFORMATION_TYPE_TLB:
724 error_info_cper.ErrorInformation.Value = 0;
725 error_info_prop = json_object_object_get(
726 error_info_information, "tlbError");
727 ir_arm_error_cache_tlb_info_to_cper(
728 error_info_prop,
729 &error_info_cper.ErrorInformation.CacheError);
730 break;
Aushim Nagarkatti5b793002024-09-26 17:07:30 -0700731
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800732 case ARM_ERROR_INFORMATION_TYPE_BUS:
733 error_info_cper.ErrorInformation.Value = 0;
734 error_info_prop = json_object_object_get(
735 error_info_information, "busError");
736 ir_arm_error_bus_info_to_cper(
737 error_info_prop,
738 &error_info_cper.ErrorInformation.BusError);
739 break;
Lawrence Tang71570a22022-07-14 11:45:28 +0100740
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800741 default:
742 //Unknown error information type.
743 break;
744 }
745 add_to_valid_bitfield(&ui16Type, 2);
Lawrence Tange407b4c2022-07-21 13:54:01 +0100746 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100747
Lawrence Tange407b4c2022-07-21 13:54:01 +0100748 //Virtual/physical fault address.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800749 if (json_object_object_get_ex(error_info, "virtualFaultAddress",
750 &obj)) {
751 error_info_cper.VirtualFaultAddress =
752 json_object_get_uint64(obj);
753 add_to_valid_bitfield(&ui16Type, 3);
754 } else {
755 error_info_cper.VirtualFaultAddress = 0;
756 }
757
758 if (json_object_object_get_ex(error_info, "physicalFaultAddress",
759 &obj)) {
760 error_info_cper.PhysicalFaultAddress =
761 json_object_get_uint64(obj);
762 add_to_valid_bitfield(&ui16Type, 4);
763 } else {
764 error_info_cper.PhysicalFaultAddress = 0;
765 }
766 error_info_cper.ValidationBits = ui16Type.value.ui16;
Lawrence Tang7cd13902022-07-13 16:59:25 +0100767
Lawrence Tange407b4c2022-07-21 13:54:01 +0100768 //Write out to stream.
769 fwrite(&error_info_cper, sizeof(EFI_ARM_ERROR_INFORMATION_ENTRY), 1,
770 out);
Lawrence Tang7cd13902022-07-13 16:59:25 +0100771}
772
Lawrence Tang71570a22022-07-14 11:45:28 +0100773//Converts a single ARM cache/TLB error information structure into a CPER structure.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100774void ir_arm_error_cache_tlb_info_to_cper(
775 json_object *error_information,
776 EFI_ARM_CACHE_ERROR_STRUCTURE *error_info_cper)
Lawrence Tang71570a22022-07-14 11:45:28 +0100777{
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800778 // //Validation bits.
779 ValidationTypes ui64Type = { UINT_64T, .value.ui64 = 0 };
780 struct json_object *obj = NULL;
Lawrence Tang71570a22022-07-14 11:45:28 +0100781
Lawrence Tange407b4c2022-07-21 13:54:01 +0100782 //Miscellaneous value fields.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800783 if (json_object_object_get_ex(error_information, "transactionType",
784 &obj)) {
785 error_info_cper->TransactionType =
786 readable_pair_to_integer(obj);
787 add_to_valid_bitfield(&ui64Type, 0);
788 }
789 if (json_object_object_get_ex(error_information, "operation", &obj)) {
790 error_info_cper->Operation = readable_pair_to_integer(obj);
791 add_to_valid_bitfield(&ui64Type, 1);
792 }
793 if (json_object_object_get_ex(error_information, "level", &obj)) {
794 error_info_cper->Level = json_object_get_uint64(obj);
795 add_to_valid_bitfield(&ui64Type, 2);
796 }
797 if (json_object_object_get_ex(error_information,
798 "processorContextCorrupt", &obj)) {
799 error_info_cper->ProcessorContextCorrupt =
800 json_object_get_boolean(obj);
801 add_to_valid_bitfield(&ui64Type, 3);
802 }
803 if (json_object_object_get_ex(error_information, "corrected", &obj)) {
804 error_info_cper->Corrected = json_object_get_boolean(obj);
805 add_to_valid_bitfield(&ui64Type, 4);
806 }
807 if (json_object_object_get_ex(error_information, "precisePC", &obj)) {
808 error_info_cper->PrecisePC = json_object_get_boolean(obj);
809 add_to_valid_bitfield(&ui64Type, 5);
810 }
811 if (json_object_object_get_ex(error_information, "restartablePC",
812 &obj)) {
813 error_info_cper->RestartablePC = json_object_get_boolean(obj);
814 add_to_valid_bitfield(&ui64Type, 6);
815 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100816 error_info_cper->Reserved = 0;
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800817 error_info_cper->ValidationBits = ui64Type.value.ui64;
Lawrence Tang71570a22022-07-14 11:45:28 +0100818}
819
820//Converts a single ARM bus error information structure into a CPER structure.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100821void ir_arm_error_bus_info_to_cper(json_object *error_information,
822 EFI_ARM_BUS_ERROR_STRUCTURE *error_info_cper)
Lawrence Tang71570a22022-07-14 11:45:28 +0100823{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100824 //Validation bits.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800825 ValidationTypes ui64Type = { UINT_64T, .value.ui64 = 0 };
826 struct json_object *obj = NULL;
827
828 memset(error_info_cper, 0, sizeof(EFI_ARM_BUS_ERROR_STRUCTURE));
Lawrence Tang71570a22022-07-14 11:45:28 +0100829
Lawrence Tange407b4c2022-07-21 13:54:01 +0100830 //Miscellaneous value fields.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800831 if (json_object_object_get_ex(error_information, "transactionType",
832 &obj)) {
833 error_info_cper->TransactionType =
834 readable_pair_to_integer(obj);
835 add_to_valid_bitfield(&ui64Type, 0);
836 } else {
837 error_info_cper->TransactionType = 0;
838 }
839 if (json_object_object_get_ex(error_information, "operation", &obj)) {
840 error_info_cper->Operation = readable_pair_to_integer(obj);
841 add_to_valid_bitfield(&ui64Type, 1);
842 } else {
843 error_info_cper->Operation = 0;
844 }
845 if (json_object_object_get_ex(error_information, "level", &obj)) {
846 error_info_cper->Level = json_object_get_uint64(obj);
847 add_to_valid_bitfield(&ui64Type, 2);
848 } else {
849 error_info_cper->Level = 0;
850 }
851 if (json_object_object_get_ex(error_information,
852 "processorContextCorrupt", &obj)) {
853 error_info_cper->ProcessorContextCorrupt =
854 json_object_get_boolean(obj);
855 add_to_valid_bitfield(&ui64Type, 3);
856 } else {
857 error_info_cper->ProcessorContextCorrupt = 0;
858 }
859 if (json_object_object_get_ex(error_information, "corrected", &obj)) {
860 error_info_cper->Corrected = json_object_get_boolean(obj);
861 add_to_valid_bitfield(&ui64Type, 4);
862 } else {
863 error_info_cper->Corrected = 0;
864 }
865 if (json_object_object_get_ex(error_information, "precisePC", &obj)) {
866 error_info_cper->PrecisePC = json_object_get_boolean(obj);
867 add_to_valid_bitfield(&ui64Type, 5);
868 } else {
869 error_info_cper->PrecisePC = 0;
870 }
871 if (json_object_object_get_ex(error_information, "restartablePC",
872 &obj)) {
873 error_info_cper->RestartablePC = json_object_get_boolean(obj);
874 add_to_valid_bitfield(&ui64Type, 6);
875 } else {
876 error_info_cper->RestartablePC = 0;
877 }
878 if (json_object_object_get_ex(error_information, "participationType",
879 &obj)) {
880 error_info_cper->ParticipationType =
881 readable_pair_to_integer(obj);
882 add_to_valid_bitfield(&ui64Type, 7);
883 } else {
884 error_info_cper->ParticipationType = 0;
885 }
886 if (json_object_object_get_ex(error_information, "timedOut", &obj)) {
887 error_info_cper->TimeOut = json_object_get_boolean(obj);
888 add_to_valid_bitfield(&ui64Type, 8);
889 } else {
890 error_info_cper->TimeOut = 0;
891 }
892 if (json_object_object_get_ex(error_information, "addressSpace",
893 &obj)) {
894 error_info_cper->AddressSpace = readable_pair_to_integer(obj);
895 add_to_valid_bitfield(&ui64Type, 9);
896 } else {
897 error_info_cper->AddressSpace = 0;
898 }
899 if (json_object_object_get_ex(error_information, "accessMode", &obj)) {
900 error_info_cper->AccessMode = readable_pair_to_integer(obj);
901 add_to_valid_bitfield(&ui64Type, 11);
902 } else {
903 error_info_cper->AccessMode = 0;
904 }
905 if (json_object_object_get_ex(error_information, "memoryAttributes",
906 &obj)) {
907 error_info_cper->MemoryAddressAttributes =
908 json_object_get_uint64(obj);
909 add_to_valid_bitfield(&ui64Type, 10);
910 } else {
911 error_info_cper->MemoryAddressAttributes = 0;
912 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100913 error_info_cper->Reserved = 0;
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800914 error_info_cper->ValidationBits = ui64Type.value.ui64;
Lawrence Tang71570a22022-07-14 11:45:28 +0100915}
916
Lawrence Tang7cd13902022-07-13 16:59:25 +0100917//Converts a single ARM context information structure into CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100918void ir_arm_context_info_to_cper(json_object *context_info, FILE *out)
Lawrence Tang7cd13902022-07-13 16:59:25 +0100919{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100920 EFI_ARM_CONTEXT_INFORMATION_HEADER info_header;
Lawrence Tang7cd13902022-07-13 16:59:25 +0100921
Lawrence Tange407b4c2022-07-21 13:54:01 +0100922 //Version, array size, context type.
923 info_header.Version = json_object_get_int(
924 json_object_object_get(context_info, "version"));
925 info_header.RegisterArraySize = json_object_get_int(
926 json_object_object_get(context_info, "registerArraySize"));
927 info_header.RegisterContextType = readable_pair_to_integer(
928 json_object_object_get(context_info, "registerContextType"));
Lawrence Tang71570a22022-07-14 11:45:28 +0100929
Lawrence Tange407b4c2022-07-21 13:54:01 +0100930 //Flush to stream, write the register array itself.
931 fwrite(&info_header, sizeof(EFI_ARM_CONTEXT_INFORMATION_HEADER), 1,
932 out);
933 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100934
Lawrence Tange407b4c2022-07-21 13:54:01 +0100935 json_object *register_array =
936 json_object_object_get(context_info, "registerArray");
937 switch (info_header.RegisterContextType) {
938 case EFI_ARM_CONTEXT_TYPE_AARCH32_GPR:
939 ir_arm_aarch32_gpr_to_cper(register_array, out);
940 break;
941 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL1:
942 ir_arm_aarch32_el1_to_cper(register_array, out);
943 break;
944 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL2:
945 ir_arm_aarch32_el2_to_cper(register_array, out);
946 break;
947 case EFI_ARM_CONTEXT_TYPE_AARCH32_SECURE:
948 ir_arm_aarch32_secure_to_cper(register_array, out);
949 break;
950 case EFI_ARM_CONTEXT_TYPE_AARCH64_GPR:
951 ir_arm_aarch64_gpr_to_cper(register_array, out);
952 break;
953 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL1:
954 ir_arm_aarch64_el1_to_cper(register_array, out);
955 break;
956 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL2:
957 ir_arm_aarch64_el2_to_cper(register_array, out);
958 break;
959 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL3:
960 ir_arm_aarch64_el3_to_cper(register_array, out);
961 break;
962 case EFI_ARM_CONTEXT_TYPE_MISC:
963 ir_arm_misc_registers_to_cper(register_array, out);
964 break;
965 default:
966 //Unknown register structure.
John Chungf8fc7052024-05-03 20:05:29 +0800967 ir_arm_unknown_register_to_cper(register_array, out);
Lawrence Tange407b4c2022-07-21 13:54:01 +0100968 break;
969 }
Lawrence Tang71570a22022-07-14 11:45:28 +0100970}
971
972//Converts a single AARCH32 GPR CPER-JSON object to CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100973void ir_arm_aarch32_gpr_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100974{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100975 //Get uniform register array.
976 EFI_ARM_V8_AARCH32_GPR reg_array;
977 ir_to_uniform_struct(registers, (UINT32 *)&reg_array,
978 sizeof(EFI_ARM_V8_AARCH32_GPR) / sizeof(UINT32),
979 ARM_AARCH32_GPR_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100980
Lawrence Tange407b4c2022-07-21 13:54:01 +0100981 //Flush to stream.
982 fwrite(&reg_array, sizeof(reg_array), 1, out);
983 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100984}
985
986//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 +0100987void ir_arm_aarch32_el1_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100988{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100989 //Get uniform register array.
990 EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS reg_array;
991 ir_to_uniform_struct(registers, (UINT32 *)&reg_array,
992 sizeof(EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS) /
993 sizeof(UINT32),
994 ARM_AARCH32_EL1_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100995
Lawrence Tange407b4c2022-07-21 13:54:01 +0100996 //Flush to stream.
997 fwrite(&reg_array, sizeof(reg_array), 1, out);
998 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100999}
1000
1001//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 +01001002void ir_arm_aarch32_el2_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +01001003{
Lawrence Tange407b4c2022-07-21 13:54:01 +01001004 //Get uniform register array.
1005 EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS reg_array;
1006 ir_to_uniform_struct(registers, (UINT32 *)&reg_array,
1007 sizeof(EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS) /
1008 sizeof(UINT32),
1009 ARM_AARCH32_EL2_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +01001010
Lawrence Tange407b4c2022-07-21 13:54:01 +01001011 //Flush to stream.
1012 fwrite(&reg_array, sizeof(reg_array), 1, out);
1013 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +01001014}
1015
1016//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 +01001017void ir_arm_aarch32_secure_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +01001018{
Lawrence Tange407b4c2022-07-21 13:54:01 +01001019 //Get uniform register array.
1020 EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS reg_array;
1021 ir_to_uniform_struct(registers, (UINT32 *)&reg_array,
1022 sizeof(EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS) /
1023 sizeof(UINT32),
1024 ARM_AARCH32_SECURE_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +01001025
Lawrence Tange407b4c2022-07-21 13:54:01 +01001026 //Flush to stream.
1027 fwrite(&reg_array, sizeof(reg_array), 1, out);
1028 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +01001029}
1030
1031//Converts a single AARCH64 GPR CPER-JSON object to CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +01001032void ir_arm_aarch64_gpr_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +01001033{
Lawrence Tange407b4c2022-07-21 13:54:01 +01001034 //Get uniform register array.
1035 EFI_ARM_V8_AARCH64_GPR reg_array;
1036 ir_to_uniform_struct64(registers, (UINT64 *)&reg_array,
1037 sizeof(EFI_ARM_V8_AARCH64_GPR) / sizeof(UINT64),
1038 ARM_AARCH64_GPR_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +01001039
Lawrence Tange407b4c2022-07-21 13:54:01 +01001040 //Flush to stream.
1041 fwrite(&reg_array, sizeof(reg_array), 1, out);
1042 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +01001043}
1044
1045//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 +01001046void ir_arm_aarch64_el1_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +01001047{
Lawrence Tange407b4c2022-07-21 13:54:01 +01001048 //Get uniform register array.
1049 EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS reg_array;
1050 ir_to_uniform_struct64(registers, (UINT64 *)&reg_array,
1051 sizeof(EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS) /
1052 sizeof(UINT64),
1053 ARM_AARCH64_EL1_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +01001054
Lawrence Tange407b4c2022-07-21 13:54:01 +01001055 //Flush to stream.
1056 fwrite(&reg_array, sizeof(reg_array), 1, out);
1057 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +01001058}
1059
1060//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 +01001061void ir_arm_aarch64_el2_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +01001062{
Lawrence Tange407b4c2022-07-21 13:54:01 +01001063 //Get uniform register array.
1064 EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS reg_array;
1065 ir_to_uniform_struct64(registers, (UINT64 *)&reg_array,
1066 sizeof(EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS) /
1067 sizeof(UINT64),
1068 ARM_AARCH64_EL2_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +01001069
Lawrence Tange407b4c2022-07-21 13:54:01 +01001070 //Flush to stream.
1071 fwrite(&reg_array, sizeof(reg_array), 1, out);
1072 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +01001073}
1074
1075//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 +01001076void ir_arm_aarch64_el3_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +01001077{
Lawrence Tange407b4c2022-07-21 13:54:01 +01001078 //Get uniform register array.
1079 EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS reg_array;
1080 ir_to_uniform_struct64(registers, (UINT64 *)&reg_array,
1081 sizeof(EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS) /
1082 sizeof(UINT64),
1083 ARM_AARCH64_EL3_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +01001084
Lawrence Tange407b4c2022-07-21 13:54:01 +01001085 //Flush to stream.
1086 fwrite(&reg_array, sizeof(reg_array), 1, out);
1087 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +01001088}
1089
1090//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 +01001091void ir_arm_misc_registers_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +01001092{
Lawrence Tange407b4c2022-07-21 13:54:01 +01001093 EFI_ARM_MISC_CONTEXT_REGISTER reg_array;
Lawrence Tang71570a22022-07-14 11:45:28 +01001094
Lawrence Tange407b4c2022-07-21 13:54:01 +01001095 //MRS encoding information.
1096 json_object *mrs_encoding =
1097 json_object_object_get(registers, "mrsEncoding");
1098 reg_array.MrsOp2 = json_object_get_uint64(
1099 json_object_object_get(mrs_encoding, "op2"));
1100 reg_array.MrsCrm = json_object_get_uint64(
1101 json_object_object_get(mrs_encoding, "crm"));
1102 reg_array.MrsCrn = json_object_get_uint64(
1103 json_object_object_get(mrs_encoding, "crn"));
1104 reg_array.MrsOp1 = json_object_get_uint64(
1105 json_object_object_get(mrs_encoding, "op1"));
1106 reg_array.MrsO0 = json_object_get_uint64(
1107 json_object_object_get(mrs_encoding, "o0"));
Lawrence Tang71570a22022-07-14 11:45:28 +01001108
Lawrence Tange407b4c2022-07-21 13:54:01 +01001109 //Actual register value.
1110 reg_array.Value = json_object_get_uint64(
1111 json_object_object_get(registers, "value"));
Lawrence Tang71570a22022-07-14 11:45:28 +01001112
Lawrence Tange407b4c2022-07-21 13:54:01 +01001113 //Flush to stream.
1114 fwrite(&reg_array, sizeof(reg_array), 1, out);
1115 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +01001116}
1117
1118//Converts a single ARM unknown register CPER-JSON object to CPER binary, outputting to the given stream.
John Chungf8fc7052024-05-03 20:05:29 +08001119void ir_arm_unknown_register_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +01001120{
Lawrence Tange407b4c2022-07-21 13:54:01 +01001121 //Get base64 represented data.
1122 json_object *encoded = json_object_object_get(registers, "data");
Ed Tanousa7d2cdd2024-07-15 11:07:27 -07001123
1124 int32_t decoded_len = 0;
1125
1126 UINT8 *decoded = base64_decode(json_object_get_string(encoded),
1127 json_object_get_string_len(encoded),
1128 &decoded_len);
1129
1130 if (decoded == NULL) {
John Chungf8fc7052024-05-03 20:05:29 +08001131 printf("Failed to allocate decode output buffer. \n");
1132 } else {
John Chungf8fc7052024-05-03 20:05:29 +08001133 //Flush out to stream.
1134 fwrite(&decoded, decoded_len, 1, out);
1135 fflush(out);
1136 free(decoded);
1137 }
1138}