1 /**
2 * Describes functions for converting ARM CPER sections from binary and JSON format
3 * into an intermediate format.
4 *
5 * Author: Lawrence.Tang@arm.com
6 **/
7
8 #include <stdio.h>
9 #include <json.h>
10 #include "base64.h"
11 #include "Cper.h"
12 #include "../cper-utils.h"
13 #include "cper-section-arm.h"
14
15 //Private pre-definitions.
16 json_object *
17 cper_arm_error_info_to_ir(EFI_ARM_ERROR_INFORMATION_ENTRY *error_info);
18 json_object *
19 cper_arm_processor_context_to_ir(EFI_ARM_CONTEXT_INFORMATION_HEADER *header,
20 void **cur_pos);
21 json_object *
22 cper_arm_cache_tlb_error_to_ir(EFI_ARM_CACHE_ERROR_STRUCTURE *cache_tlb_error,
23 EFI_ARM_ERROR_INFORMATION_ENTRY *error_info);
24 json_object *cper_arm_bus_error_to_ir(EFI_ARM_BUS_ERROR_STRUCTURE *bus_error);
25 json_object *cper_arm_misc_register_array_to_ir(
26 EFI_ARM_MISC_CONTEXT_REGISTER *misc_register);
27 void ir_arm_error_info_to_cper(json_object *error_info, FILE *out);
28 void ir_arm_context_info_to_cper(json_object *context_info, FILE *out);
29 void ir_arm_error_cache_tlb_info_to_cper(
30 json_object *error_information,
31 EFI_ARM_CACHE_ERROR_STRUCTURE *error_info_cper);
32 void ir_arm_error_bus_info_to_cper(json_object *error_information,
33 EFI_ARM_BUS_ERROR_STRUCTURE *error_info_cper);
34 void ir_arm_aarch32_gpr_to_cper(json_object *registers, FILE *out);
35 void ir_arm_aarch32_el1_to_cper(json_object *registers, FILE *out);
36 void ir_arm_aarch32_el2_to_cper(json_object *registers, FILE *out);
37 void ir_arm_aarch32_secure_to_cper(json_object *registers, FILE *out);
38 void ir_arm_aarch64_gpr_to_cper(json_object *registers, FILE *out);
39 void ir_arm_aarch64_el1_to_cper(json_object *registers, FILE *out);
40 void ir_arm_aarch64_el2_to_cper(json_object *registers, FILE *out);
41 void ir_arm_aarch64_el3_to_cper(json_object *registers, FILE *out);
42 void ir_arm_misc_registers_to_cper(json_object *registers, FILE *out);
43 void ir_arm_unknown_register_to_cper(json_object *registers, FILE *out);
44
45 //Converts the given processor-generic CPER section into JSON IR.
cper_section_arm_to_ir(void * section)46 json_object *cper_section_arm_to_ir(void *section)
47 {
48 EFI_ARM_ERROR_RECORD *record = (EFI_ARM_ERROR_RECORD *)section;
49 json_object *section_ir = json_object_new_object();
50
51 //Validation bits.
52 json_object *validation = bitfield_to_ir(
53 record->ValidFields, 4, ARM_ERROR_VALID_BITFIELD_NAMES);
54 json_object_object_add(section_ir, "validationBits", validation);
55
56 //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));
63
64 //Error affinity.
65 json_object *error_affinity = json_object_new_object();
66 json_object_object_add(error_affinity, "value",
67 json_object_new_int(record->ErrorAffinityLevel));
68 json_object_object_add(
69 error_affinity, "type",
70 json_object_new_string(record->ErrorAffinityLevel < 4 ?
71 "Vendor Defined" :
72 "Reserved"));
73 json_object_object_add(section_ir, "errorAffinity", error_affinity);
74
75 //Processor ID (MPIDR_EL1) and chip ID (MIDR_EL1).
76 json_object_object_add(section_ir, "mpidrEl1",
77 json_object_new_uint64(record->MPIDR_EL1));
78 json_object_object_add(section_ir, "midrEl1",
79 json_object_new_uint64(record->MIDR_EL1));
80
81 //Whether the processor is running, and the state of it if so.
82 json_object_object_add(section_ir, "running",
83 json_object_new_boolean(record->RunningState &
84 0x1));
85 if (!(record->RunningState >> 31)) {
86 //Bit 32 of running state is on, so PSCI state information is included.
87 //This can't be made human readable, as it is unknown whether this will be the pre-PSCI 1.0 format
88 //or the newer Extended StateID format.
89 json_object_object_add(
90 section_ir, "psciState",
91 json_object_new_uint64(record->PsciState));
92 }
93
94 //Processor error structures.
95 json_object *error_info_array = json_object_new_array();
96 EFI_ARM_ERROR_INFORMATION_ENTRY *cur_error =
97 (EFI_ARM_ERROR_INFORMATION_ENTRY *)(record + 1);
98 for (int i = 0; i < record->ErrInfoNum; i++) {
99 json_object_array_add(error_info_array,
100 cper_arm_error_info_to_ir(cur_error));
101 cur_error++;
102 }
103 json_object_object_add(section_ir, "errorInfo", error_info_array);
104
105 //Processor context structures.
106 //The current position is moved within the processing, as it is a dynamic size structure.
107 uint8_t *cur_pos = (uint8_t *)cur_error;
108 json_object *context_info_array = json_object_new_array();
109 for (int i = 0; i < record->ContextInfoNum; i++) {
110 EFI_ARM_CONTEXT_INFORMATION_HEADER *header =
111 (EFI_ARM_CONTEXT_INFORMATION_HEADER *)cur_pos;
112 json_object *processor_context =
113 cper_arm_processor_context_to_ir(header,
114 (void **)&cur_pos);
115 json_object_array_add(context_info_array, processor_context);
116 }
117 json_object_object_add(section_ir, "contextInfo", context_info_array);
118
119 //Is there any vendor-specific information following?
120 if (cur_pos < (uint8_t *)section + record->SectionLength) {
121 json_object *vendor_specific = json_object_new_object();
122 size_t input_size =
123 (uint8_t *)section + record->SectionLength - cur_pos;
124 int32_t encoded_len = 0;
125 char *encoded =
126 base64_encode(cur_pos, input_size, &encoded_len);
127 if (encoded == NULL) {
128 return NULL;
129 }
130 json_object_object_add(vendor_specific, "data",
131 json_object_new_string_len(encoded,
132 encoded_len));
133 free(encoded);
134
135 json_object_object_add(section_ir, "vendorSpecificInfo",
136 vendor_specific);
137 }
138
139 return section_ir;
140 }
141
142 //Converts a single ARM Process Error Information structure into JSON IR.
143 json_object *
cper_arm_error_info_to_ir(EFI_ARM_ERROR_INFORMATION_ENTRY * error_info)144 cper_arm_error_info_to_ir(EFI_ARM_ERROR_INFORMATION_ENTRY *error_info)
145 {
146 json_object *error_info_ir = json_object_new_object();
147
148 //Version, length.
149 json_object_object_add(error_info_ir, "version",
150 json_object_new_int(error_info->Version));
151 json_object_object_add(error_info_ir, "length",
152 json_object_new_int(error_info->Length));
153
154 //Validation bitfield.
155 json_object *validation =
156 bitfield_to_ir(error_info->ValidationBits, 5,
157 ARM_ERROR_INFO_ENTRY_VALID_BITFIELD_NAMES);
158 json_object_object_add(error_info_ir, "validationBits", validation);
159
160 //The type of error information in this log.
161 json_object *error_type = integer_to_readable_pair(
162 error_info->Type, 4, ARM_ERROR_INFO_ENTRY_INFO_TYPES_KEYS,
163 ARM_ERROR_INFO_ENTRY_INFO_TYPES_VALUES, "Unknown (Reserved)");
164 json_object_object_add(error_info_ir, "errorType", error_type);
165
166 //Multiple error count.
167 json_object *multiple_error = json_object_new_object();
168 json_object_object_add(multiple_error, "value",
169 json_object_new_int(error_info->MultipleError));
170 json_object_object_add(
171 multiple_error, "type",
172 json_object_new_string(error_info->MultipleError < 1 ?
173 "Single Error" :
174 "Multiple Errors"));
175 json_object_object_add(error_info_ir, "multipleError", multiple_error);
176
177 //Flags.
178 json_object *flags = bitfield_to_ir(error_info->Flags, 4,
179 ARM_ERROR_INFO_ENTRY_FLAGS_NAMES);
180 json_object_object_add(error_info_ir, "flags", flags);
181
182 //Error information, split by type.
183 json_object *error_subinfo = NULL;
184 switch (error_info->Type) {
185 case ARM_ERROR_INFORMATION_TYPE_CACHE: //Cache
186 case ARM_ERROR_INFORMATION_TYPE_TLB: //TLB
187 error_subinfo = cper_arm_cache_tlb_error_to_ir(
188 (EFI_ARM_CACHE_ERROR_STRUCTURE *)&error_info
189 ->ErrorInformation,
190 error_info);
191 break;
192 case ARM_ERROR_INFORMATION_TYPE_BUS: //Bus
193 error_subinfo = cper_arm_bus_error_to_ir(
194 (EFI_ARM_BUS_ERROR_STRUCTURE *)&error_info
195 ->ErrorInformation);
196 break;
197
198 default:
199 //Unknown/microarch, will not support.
200 break;
201 }
202 json_object_object_add(error_info_ir, "errorInformation",
203 error_subinfo);
204
205 //Virtual fault address, physical fault address.
206 json_object_object_add(
207 error_info_ir, "virtualFaultAddress",
208 json_object_new_uint64(error_info->VirtualFaultAddress));
209 json_object_object_add(
210 error_info_ir, "physicalFaultAddress",
211 json_object_new_uint64(error_info->PhysicalFaultAddress));
212
213 return error_info_ir;
214 }
215
216 //Converts a single ARM cache/TLB error information structure into JSON IR format.
217 json_object *
cper_arm_cache_tlb_error_to_ir(EFI_ARM_CACHE_ERROR_STRUCTURE * cache_tlb_error,EFI_ARM_ERROR_INFORMATION_ENTRY * error_info)218 cper_arm_cache_tlb_error_to_ir(EFI_ARM_CACHE_ERROR_STRUCTURE *cache_tlb_error,
219 EFI_ARM_ERROR_INFORMATION_ENTRY *error_info)
220 {
221 json_object *cache_tlb_error_ir = json_object_new_object();
222 json_object *cache_tlb_prop = json_object_new_object();
223 char *cache_tlb_propname;
224
225 //Validation bitfield.
226 json_object *validation =
227 bitfield_to_ir(cache_tlb_error->ValidationBits, 7,
228 ARM_CACHE_TLB_ERROR_VALID_BITFIELD_NAMES);
229 json_object_object_add(cache_tlb_error_ir, "validationBits",
230 validation);
231
232 //Transaction type.
233 json_object *transaction_type = integer_to_readable_pair(
234 cache_tlb_error->TransactionType, 3,
235 ARM_ERROR_TRANSACTION_TYPES_KEYS,
236 ARM_ERROR_TRANSACTION_TYPES_VALUES, "Unknown (Reserved)");
237 json_object_object_add(cache_tlb_error_ir, "transactionType",
238 transaction_type);
239
240 //Operation.
241 json_object *operation;
242 if (error_info->Type == 0) {
243 //Cache operation.
244 operation = integer_to_readable_pair(
245 cache_tlb_error->Operation, 11,
246 ARM_CACHE_BUS_OPERATION_TYPES_KEYS,
247 ARM_CACHE_BUS_OPERATION_TYPES_VALUES,
248 "Unknown (Reserved)");
249 cache_tlb_propname = "cacheError";
250 } else {
251 //TLB operation.
252 operation = integer_to_readable_pair(
253 cache_tlb_error->Operation, 9,
254 ARM_TLB_OPERATION_TYPES_KEYS,
255 ARM_TLB_OPERATION_TYPES_VALUES, "Unknown (Reserved)");
256 cache_tlb_propname = "tlbError";
257 }
258 json_object_object_add(cache_tlb_error_ir, "operation", operation);
259
260 //Miscellaneous remaining fields.
261 json_object_object_add(cache_tlb_error_ir, "level",
262 json_object_new_int(cache_tlb_error->Level));
263 json_object_object_add(
264 cache_tlb_error_ir, "processorContextCorrupt",
265 json_object_new_boolean(
266 cache_tlb_error->ProcessorContextCorrupt));
267 json_object_object_add(
268 cache_tlb_error_ir, "corrected",
269 json_object_new_boolean(cache_tlb_error->Corrected));
270 json_object_object_add(
271 cache_tlb_error_ir, "precisePC",
272 json_object_new_boolean(cache_tlb_error->PrecisePC));
273 json_object_object_add(
274 cache_tlb_error_ir, "restartablePC",
275 json_object_new_boolean(cache_tlb_error->RestartablePC));
276
277 json_object_object_add(cache_tlb_prop, cache_tlb_propname,
278 cache_tlb_error_ir);
279 return cache_tlb_prop;
280 }
281
282 //Converts a single ARM bus error information structure into JSON IR format.
cper_arm_bus_error_to_ir(EFI_ARM_BUS_ERROR_STRUCTURE * bus_error)283 json_object *cper_arm_bus_error_to_ir(EFI_ARM_BUS_ERROR_STRUCTURE *bus_error)
284 {
285 json_object *bus_error_ir = json_object_new_object();
286
287 //Validation bits.
288 json_object *validation =
289 bitfield_to_ir(bus_error->ValidationBits, 12,
290 ARM_BUS_ERROR_VALID_BITFIELD_NAMES);
291 json_object_object_add(bus_error_ir, "validationBits", validation);
292
293 //Transaction type.
294 json_object *transaction_type = integer_to_readable_pair(
295 bus_error->TransactionType, 3, ARM_ERROR_TRANSACTION_TYPES_KEYS,
296 ARM_ERROR_TRANSACTION_TYPES_VALUES, "Unknown (Reserved)");
297 json_object_object_add(bus_error_ir, "transactionType",
298 transaction_type);
299
300 //Operation.
301 json_object *operation = integer_to_readable_pair(
302 bus_error->Operation, 7, ARM_CACHE_BUS_OPERATION_TYPES_KEYS,
303 ARM_CACHE_BUS_OPERATION_TYPES_VALUES, "Unknown (Reserved)");
304 json_object_object_add(bus_error_ir, "operation", operation);
305
306 //Affinity level of bus error, + miscellaneous fields.
307 json_object_object_add(bus_error_ir, "level",
308 json_object_new_int(bus_error->Level));
309 json_object_object_add(
310 bus_error_ir, "processorContextCorrupt",
311 json_object_new_boolean(bus_error->ProcessorContextCorrupt));
312 json_object_object_add(bus_error_ir, "corrected",
313 json_object_new_boolean(bus_error->Corrected));
314 json_object_object_add(bus_error_ir, "precisePC",
315 json_object_new_boolean(bus_error->PrecisePC));
316 json_object_object_add(
317 bus_error_ir, "restartablePC",
318 json_object_new_boolean(bus_error->RestartablePC));
319 json_object_object_add(bus_error_ir, "timedOut",
320 json_object_new_boolean(bus_error->TimeOut));
321
322 //Participation type.
323 json_object *participation_type = integer_to_readable_pair(
324 bus_error->ParticipationType, 4,
325 ARM_BUS_PARTICIPATION_TYPES_KEYS,
326 ARM_BUS_PARTICIPATION_TYPES_VALUES, "Unknown");
327 json_object_object_add(bus_error_ir, "participationType",
328 participation_type);
329
330 //Address space.
331 json_object *address_space = integer_to_readable_pair(
332 bus_error->AddressSpace, 3, ARM_BUS_ADDRESS_SPACE_TYPES_KEYS,
333 ARM_BUS_ADDRESS_SPACE_TYPES_VALUES, "Unknown");
334 json_object_object_add(bus_error_ir, "addressSpace", address_space);
335
336 //Memory access attributes.
337 //todo: find the specification of these in the ARM ARM
338 json_object_object_add(
339 bus_error_ir, "memoryAttributes",
340 json_object_new_int(bus_error->MemoryAddressAttributes));
341
342 //Access Mode
343 json_object *access_mode = json_object_new_object();
344 json_object_object_add(access_mode, "value",
345 json_object_new_int(bus_error->AccessMode));
346 json_object_object_add(
347 access_mode, "name",
348 json_object_new_string(bus_error->AccessMode == 0 ? "Secure" :
349 "Normal"));
350 json_object_object_add(bus_error_ir, "accessMode", access_mode);
351
352 return bus_error_ir;
353 }
354
355 //Converts a single ARM processor context block into JSON IR.
356 json_object *
cper_arm_processor_context_to_ir(EFI_ARM_CONTEXT_INFORMATION_HEADER * header,void ** cur_pos)357 cper_arm_processor_context_to_ir(EFI_ARM_CONTEXT_INFORMATION_HEADER *header,
358 void **cur_pos)
359 {
360 json_object *context_ir = json_object_new_object();
361
362 //Version.
363 json_object_object_add(context_ir, "version",
364 json_object_new_int(header->Version));
365
366 //Add the context type.
367 json_object *context_type = integer_to_readable_pair(
368 header->RegisterContextType, 9,
369 ARM_PROCESSOR_INFO_REGISTER_CONTEXT_TYPES_KEYS,
370 ARM_PROCESSOR_INFO_REGISTER_CONTEXT_TYPES_VALUES,
371 "Unknown (Reserved)");
372 json_object_object_add(context_ir, "registerContextType", context_type);
373
374 //Register array size (bytes).
375 json_object_object_add(
376 context_ir, "registerArraySize",
377 json_object_new_uint64(header->RegisterArraySize));
378
379 //The register array itself.
380 *cur_pos = (void *)(header + 1);
381 json_object *register_array = NULL;
382 switch (header->RegisterContextType) {
383 case EFI_ARM_CONTEXT_TYPE_AARCH32_GPR:
384 register_array = uniform_struct_to_ir(
385 (UINT32 *)cur_pos,
386 sizeof(EFI_ARM_V8_AARCH32_GPR) / sizeof(UINT32),
387 ARM_AARCH32_GPR_NAMES);
388 break;
389 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL1:
390 register_array = uniform_struct_to_ir(
391 (UINT32 *)cur_pos,
392 sizeof(EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS) /
393 sizeof(UINT32),
394 ARM_AARCH32_EL1_REGISTER_NAMES);
395 break;
396 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL2:
397 register_array = uniform_struct_to_ir(
398 (UINT32 *)cur_pos,
399 sizeof(EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS) /
400 sizeof(UINT32),
401 ARM_AARCH32_EL2_REGISTER_NAMES);
402 break;
403 case EFI_ARM_CONTEXT_TYPE_AARCH32_SECURE:
404 register_array = uniform_struct_to_ir(
405 (UINT32 *)cur_pos,
406 sizeof(EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS) /
407 sizeof(UINT32),
408 ARM_AARCH32_SECURE_REGISTER_NAMES);
409 break;
410 case EFI_ARM_CONTEXT_TYPE_AARCH64_GPR:
411 register_array = uniform_struct64_to_ir(
412 (UINT64 *)cur_pos,
413 sizeof(EFI_ARM_V8_AARCH64_GPR) / sizeof(UINT64),
414 ARM_AARCH64_GPR_NAMES);
415 break;
416 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL1:
417 register_array = uniform_struct64_to_ir(
418 (UINT64 *)cur_pos,
419 sizeof(EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS) /
420 sizeof(UINT64),
421 ARM_AARCH64_EL1_REGISTER_NAMES);
422 break;
423 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL2:
424 register_array = uniform_struct64_to_ir(
425 (UINT64 *)cur_pos,
426 sizeof(EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS) /
427 sizeof(UINT64),
428 ARM_AARCH64_EL2_REGISTER_NAMES);
429 break;
430 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL3:
431 register_array = uniform_struct64_to_ir(
432 (UINT64 *)cur_pos,
433 sizeof(EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS) /
434 sizeof(UINT64),
435 ARM_AARCH64_EL3_REGISTER_NAMES);
436 break;
437 case EFI_ARM_CONTEXT_TYPE_MISC:
438 register_array = cper_arm_misc_register_array_to_ir(
439 (EFI_ARM_MISC_CONTEXT_REGISTER *)cur_pos);
440 break;
441 default:
442 //Unknown register array type, add as base64 data instead.
443 register_array = json_object_new_object();
444 int32_t encoded_len = 0;
445 char *encoded = base64_encode((UINT8 *)cur_pos,
446 header->RegisterArraySize,
447 &encoded_len);
448 if (encoded == NULL) {
449 printf("Failed to allocate encode output buffer. \n");
450 return NULL;
451 }
452 json_object_object_add(register_array, "data",
453 json_object_new_string_len(encoded,
454 encoded_len));
455 free(encoded);
456
457 break;
458 }
459 json_object_object_add(context_ir, "registerArray", register_array);
460
461 //Set the current position to after the processor context structure.
462 *cur_pos = (UINT8 *)(*cur_pos) + header->RegisterArraySize;
463
464 return context_ir;
465 }
466
467 //Converts a single CPER ARM miscellaneous register array to JSON IR format.
468 json_object *
cper_arm_misc_register_array_to_ir(EFI_ARM_MISC_CONTEXT_REGISTER * misc_register)469 cper_arm_misc_register_array_to_ir(EFI_ARM_MISC_CONTEXT_REGISTER *misc_register)
470 {
471 json_object *register_array = json_object_new_object();
472 json_object *mrs_encoding = json_object_new_object();
473 json_object_object_add(mrs_encoding, "op2",
474 json_object_new_uint64(misc_register->MrsOp2));
475 json_object_object_add(mrs_encoding, "crm",
476 json_object_new_uint64(misc_register->MrsCrm));
477 json_object_object_add(mrs_encoding, "crn",
478 json_object_new_uint64(misc_register->MrsCrn));
479 json_object_object_add(mrs_encoding, "op1",
480 json_object_new_uint64(misc_register->MrsOp1));
481 json_object_object_add(mrs_encoding, "o0",
482 json_object_new_uint64(misc_register->MrsO0));
483 json_object_object_add(register_array, "mrsEncoding", mrs_encoding);
484 json_object_object_add(register_array, "value",
485 json_object_new_uint64(misc_register->Value));
486
487 return register_array;
488 }
489
490 //Converts a single CPER-JSON ARM error section into CPER binary, outputting to the given stream.
ir_section_arm_to_cper(json_object * section,FILE * out)491 void ir_section_arm_to_cper(json_object *section, FILE *out)
492 {
493 EFI_ARM_ERROR_RECORD *section_cper =
494 (EFI_ARM_ERROR_RECORD *)calloc(1, sizeof(EFI_ARM_ERROR_RECORD));
495
496 //Validation bits.
497 section_cper->ValidFields = ir_to_bitfield(
498 json_object_object_get(section, "validationBits"), 4,
499 ARM_ERROR_VALID_BITFIELD_NAMES);
500
501 //Count of error/context info structures.
502 section_cper->ErrInfoNum = json_object_get_int(
503 json_object_object_get(section, "errorInfoNum"));
504 section_cper->ContextInfoNum = json_object_get_int(
505 json_object_object_get(section, "contextInfoNum"));
506
507 //Miscellaneous raw value fields.
508 section_cper->SectionLength = json_object_get_uint64(
509 json_object_object_get(section, "sectionLength"));
510 section_cper->ErrorAffinityLevel = readable_pair_to_integer(
511 json_object_object_get(section, "errorAffinity"));
512 section_cper->MPIDR_EL1 = json_object_get_uint64(
513 json_object_object_get(section, "mpidrEl1"));
514 section_cper->MIDR_EL1 = json_object_get_uint64(
515 json_object_object_get(section, "midrEl1"));
516 section_cper->RunningState = json_object_get_boolean(
517 json_object_object_get(section, "running"));
518
519 //Optional PSCI state.
520 json_object *psci_state = json_object_object_get(section, "psciState");
521 if (psci_state != NULL) {
522 section_cper->PsciState = json_object_get_uint64(psci_state);
523 }
524
525 //Flush header to stream.
526 fwrite(section_cper, sizeof(EFI_ARM_ERROR_RECORD), 1, out);
527 fflush(out);
528
529 //Error info structure array.
530 json_object *error_info = json_object_object_get(section, "errorInfo");
531 for (int i = 0; i < section_cper->ErrInfoNum; i++) {
532 ir_arm_error_info_to_cper(
533 json_object_array_get_idx(error_info, i), out);
534 }
535
536 //Context info structure array.
537 json_object *context_info =
538 json_object_object_get(section, "contextInfo");
539 for (int i = 0; i < section_cper->ContextInfoNum; i++) {
540 ir_arm_context_info_to_cper(
541 json_object_array_get_idx(context_info, i), out);
542 }
543
544 //Vendor specific error info.
545 json_object *vendor_specific_info =
546 json_object_object_get(section, "vendorSpecificInfo");
547 if (vendor_specific_info != NULL) {
548 json_object *vendor_info_string =
549 json_object_object_get(vendor_specific_info, "data");
550 int vendor_specific_len =
551 json_object_get_string_len(vendor_info_string);
552
553 int32_t decoded_len = 0;
554
555 UINT8 *decoded = base64_decode(
556 json_object_get_string(vendor_info_string),
557 vendor_specific_len, &decoded_len);
558
559 //Write out to file.
560 fwrite(decoded, decoded_len, 1, out);
561 fflush(out);
562 free(decoded);
563 }
564
565 //Free remaining resources.
566 free(section_cper);
567 }
568
569 //Converts a single ARM error information structure into CPER binary, outputting to the given stream.
ir_arm_error_info_to_cper(json_object * error_info,FILE * out)570 void ir_arm_error_info_to_cper(json_object *error_info, FILE *out)
571 {
572 EFI_ARM_ERROR_INFORMATION_ENTRY error_info_cper;
573
574 //Version, length.
575 error_info_cper.Version = json_object_get_int(
576 json_object_object_get(error_info, "version"));
577 error_info_cper.Length = json_object_get_int(
578 json_object_object_get(error_info, "length"));
579
580 //Validation bits.
581 error_info_cper.ValidationBits = ir_to_bitfield(
582 json_object_object_get(error_info, "validationBits"), 5,
583 ARM_ERROR_INFO_ENTRY_VALID_BITFIELD_NAMES);
584
585 //Type, multiple error.
586 error_info_cper.Type = (UINT8)readable_pair_to_integer(
587 json_object_object_get(error_info, "type"));
588 error_info_cper.MultipleError = (UINT16)readable_pair_to_integer(
589 json_object_object_get(error_info, "multipleError"));
590
591 //Flags object.
592 error_info_cper.Flags = (UINT8)ir_to_bitfield(
593 json_object_object_get(error_info, "flags"), 4,
594 ARM_ERROR_INFO_ENTRY_FLAGS_NAMES);
595
596 //Error information.
597 json_object *error_info_information =
598 json_object_object_get(error_info, "errorInformation");
599 json_object *error_info_prop = NULL;
600
601 switch (error_info_cper.Type) {
602 case ARM_ERROR_INFORMATION_TYPE_CACHE:
603 error_info_prop = json_object_object_get(error_info_information,
604 "cacheError");
605 ir_arm_error_cache_tlb_info_to_cper(
606 error_info_prop,
607 &error_info_cper.ErrorInformation.CacheError);
608 break;
609 case ARM_ERROR_INFORMATION_TYPE_TLB:
610 error_info_prop = json_object_object_get(error_info_information,
611 "tlbError");
612 ir_arm_error_cache_tlb_info_to_cper(
613 error_info_prop,
614 &error_info_cper.ErrorInformation.CacheError);
615 break;
616
617 case ARM_ERROR_INFORMATION_TYPE_BUS:
618 ir_arm_error_bus_info_to_cper(
619 error_info_information,
620 &error_info_cper.ErrorInformation.BusError);
621 break;
622
623 default:
624 //Unknown error information type.
625 break;
626 }
627
628 //Virtual/physical fault address.
629 error_info_cper.VirtualFaultAddress = json_object_get_uint64(
630 json_object_object_get(error_info, "virtualFaultAddress"));
631 error_info_cper.PhysicalFaultAddress = json_object_get_uint64(
632 json_object_object_get(error_info, "physicalFaultAddress"));
633
634 //Write out to stream.
635 fwrite(&error_info_cper, sizeof(EFI_ARM_ERROR_INFORMATION_ENTRY), 1,
636 out);
637 fflush(out);
638 }
639
640 //Converts a single ARM cache/TLB error information structure into a CPER structure.
ir_arm_error_cache_tlb_info_to_cper(json_object * error_information,EFI_ARM_CACHE_ERROR_STRUCTURE * error_info_cper)641 void ir_arm_error_cache_tlb_info_to_cper(
642 json_object *error_information,
643 EFI_ARM_CACHE_ERROR_STRUCTURE *error_info_cper)
644 {
645 //Validation bits.
646 error_info_cper->ValidationBits = ir_to_bitfield(
647 json_object_object_get(error_information, "validationBits"), 7,
648 ARM_CACHE_TLB_ERROR_VALID_BITFIELD_NAMES);
649
650 //Miscellaneous value fields.
651 error_info_cper->TransactionType = readable_pair_to_integer(
652 json_object_object_get(error_information, "transactionType"));
653 error_info_cper->Operation = readable_pair_to_integer(
654 json_object_object_get(error_information, "operation"));
655 error_info_cper->Level = json_object_get_uint64(
656 json_object_object_get(error_information, "level"));
657 error_info_cper->ProcessorContextCorrupt = json_object_get_boolean(
658 json_object_object_get(error_information,
659 "processorContextCorrupt"));
660 error_info_cper->Corrected = json_object_get_boolean(
661 json_object_object_get(error_information, "corrected"));
662 error_info_cper->PrecisePC = json_object_get_boolean(
663 json_object_object_get(error_information, "precisePC"));
664 error_info_cper->RestartablePC = json_object_get_boolean(
665 json_object_object_get(error_information, "restartablePC"));
666 error_info_cper->Reserved = 0;
667 }
668
669 //Converts a single ARM bus error information structure into a CPER structure.
ir_arm_error_bus_info_to_cper(json_object * error_information,EFI_ARM_BUS_ERROR_STRUCTURE * error_info_cper)670 void ir_arm_error_bus_info_to_cper(json_object *error_information,
671 EFI_ARM_BUS_ERROR_STRUCTURE *error_info_cper)
672 {
673 //Validation bits.
674 error_info_cper->ValidationBits = ir_to_bitfield(
675 json_object_object_get(error_information, "validationBits"), 7,
676 ARM_BUS_ERROR_VALID_BITFIELD_NAMES);
677
678 //Miscellaneous value fields.
679 error_info_cper->TransactionType = readable_pair_to_integer(
680 json_object_object_get(error_information, "transactionType"));
681 error_info_cper->Operation = readable_pair_to_integer(
682 json_object_object_get(error_information, "operation"));
683 error_info_cper->Level = json_object_get_uint64(
684 json_object_object_get(error_information, "level"));
685 error_info_cper->ProcessorContextCorrupt = json_object_get_boolean(
686 json_object_object_get(error_information,
687 "processorContextCorrupt"));
688 error_info_cper->Corrected = json_object_get_boolean(
689 json_object_object_get(error_information, "corrected"));
690 error_info_cper->PrecisePC = json_object_get_boolean(
691 json_object_object_get(error_information, "precisePC"));
692 error_info_cper->RestartablePC = json_object_get_boolean(
693 json_object_object_get(error_information, "restartablePC"));
694 error_info_cper->ParticipationType = readable_pair_to_integer(
695 json_object_object_get(error_information, "participationType"));
696 error_info_cper->AddressSpace = readable_pair_to_integer(
697 json_object_object_get(error_information, "addressSpace"));
698 error_info_cper->AccessMode = readable_pair_to_integer(
699 json_object_object_get(error_information, "accessMode"));
700 error_info_cper->MemoryAddressAttributes = json_object_get_uint64(
701 json_object_object_get(error_information, "memoryAttributes"));
702 error_info_cper->Reserved = 0;
703 }
704
705 //Converts a single ARM context information structure into CPER binary, outputting to the given stream.
ir_arm_context_info_to_cper(json_object * context_info,FILE * out)706 void ir_arm_context_info_to_cper(json_object *context_info, FILE *out)
707 {
708 EFI_ARM_CONTEXT_INFORMATION_HEADER info_header;
709
710 //Version, array size, context type.
711 info_header.Version = json_object_get_int(
712 json_object_object_get(context_info, "version"));
713 info_header.RegisterArraySize = json_object_get_int(
714 json_object_object_get(context_info, "registerArraySize"));
715 info_header.RegisterContextType = readable_pair_to_integer(
716 json_object_object_get(context_info, "registerContextType"));
717
718 //Flush to stream, write the register array itself.
719 fwrite(&info_header, sizeof(EFI_ARM_CONTEXT_INFORMATION_HEADER), 1,
720 out);
721 fflush(out);
722
723 json_object *register_array =
724 json_object_object_get(context_info, "registerArray");
725 switch (info_header.RegisterContextType) {
726 case EFI_ARM_CONTEXT_TYPE_AARCH32_GPR:
727 ir_arm_aarch32_gpr_to_cper(register_array, out);
728 break;
729 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL1:
730 ir_arm_aarch32_el1_to_cper(register_array, out);
731 break;
732 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL2:
733 ir_arm_aarch32_el2_to_cper(register_array, out);
734 break;
735 case EFI_ARM_CONTEXT_TYPE_AARCH32_SECURE:
736 ir_arm_aarch32_secure_to_cper(register_array, out);
737 break;
738 case EFI_ARM_CONTEXT_TYPE_AARCH64_GPR:
739 ir_arm_aarch64_gpr_to_cper(register_array, out);
740 break;
741 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL1:
742 ir_arm_aarch64_el1_to_cper(register_array, out);
743 break;
744 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL2:
745 ir_arm_aarch64_el2_to_cper(register_array, out);
746 break;
747 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL3:
748 ir_arm_aarch64_el3_to_cper(register_array, out);
749 break;
750 case EFI_ARM_CONTEXT_TYPE_MISC:
751 ir_arm_misc_registers_to_cper(register_array, out);
752 break;
753 default:
754 //Unknown register structure.
755 ir_arm_unknown_register_to_cper(register_array, out);
756 break;
757 }
758 }
759
760 //Converts a single AARCH32 GPR CPER-JSON object to CPER binary, outputting to the given stream.
ir_arm_aarch32_gpr_to_cper(json_object * registers,FILE * out)761 void ir_arm_aarch32_gpr_to_cper(json_object *registers, FILE *out)
762 {
763 //Get uniform register array.
764 EFI_ARM_V8_AARCH32_GPR reg_array;
765 ir_to_uniform_struct(registers, (UINT32 *)®_array,
766 sizeof(EFI_ARM_V8_AARCH32_GPR) / sizeof(UINT32),
767 ARM_AARCH32_GPR_NAMES);
768
769 //Flush to stream.
770 fwrite(®_array, sizeof(reg_array), 1, out);
771 fflush(out);
772 }
773
774 //Converts a single AARCH32 EL1 register set CPER-JSON object to CPER binary, outputting to the given stream.
ir_arm_aarch32_el1_to_cper(json_object * registers,FILE * out)775 void ir_arm_aarch32_el1_to_cper(json_object *registers, FILE *out)
776 {
777 //Get uniform register array.
778 EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS reg_array;
779 ir_to_uniform_struct(registers, (UINT32 *)®_array,
780 sizeof(EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS) /
781 sizeof(UINT32),
782 ARM_AARCH32_EL1_REGISTER_NAMES);
783
784 //Flush to stream.
785 fwrite(®_array, sizeof(reg_array), 1, out);
786 fflush(out);
787 }
788
789 //Converts a single AARCH32 EL2 register set CPER-JSON object to CPER binary, outputting to the given stream.
ir_arm_aarch32_el2_to_cper(json_object * registers,FILE * out)790 void ir_arm_aarch32_el2_to_cper(json_object *registers, FILE *out)
791 {
792 //Get uniform register array.
793 EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS reg_array;
794 ir_to_uniform_struct(registers, (UINT32 *)®_array,
795 sizeof(EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS) /
796 sizeof(UINT32),
797 ARM_AARCH32_EL2_REGISTER_NAMES);
798
799 //Flush to stream.
800 fwrite(®_array, sizeof(reg_array), 1, out);
801 fflush(out);
802 }
803
804 //Converts a single AARCH32 secure register set CPER-JSON object to CPER binary, outputting to the given stream.
ir_arm_aarch32_secure_to_cper(json_object * registers,FILE * out)805 void ir_arm_aarch32_secure_to_cper(json_object *registers, FILE *out)
806 {
807 //Get uniform register array.
808 EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS reg_array;
809 ir_to_uniform_struct(registers, (UINT32 *)®_array,
810 sizeof(EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS) /
811 sizeof(UINT32),
812 ARM_AARCH32_SECURE_REGISTER_NAMES);
813
814 //Flush to stream.
815 fwrite(®_array, sizeof(reg_array), 1, out);
816 fflush(out);
817 }
818
819 //Converts a single AARCH64 GPR CPER-JSON object to CPER binary, outputting to the given stream.
ir_arm_aarch64_gpr_to_cper(json_object * registers,FILE * out)820 void ir_arm_aarch64_gpr_to_cper(json_object *registers, FILE *out)
821 {
822 //Get uniform register array.
823 EFI_ARM_V8_AARCH64_GPR reg_array;
824 ir_to_uniform_struct64(registers, (UINT64 *)®_array,
825 sizeof(EFI_ARM_V8_AARCH64_GPR) / sizeof(UINT64),
826 ARM_AARCH64_GPR_NAMES);
827
828 //Flush to stream.
829 fwrite(®_array, sizeof(reg_array), 1, out);
830 fflush(out);
831 }
832
833 //Converts a single AARCH64 EL1 register set CPER-JSON object to CPER binary, outputting to the given stream.
ir_arm_aarch64_el1_to_cper(json_object * registers,FILE * out)834 void ir_arm_aarch64_el1_to_cper(json_object *registers, FILE *out)
835 {
836 //Get uniform register array.
837 EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS reg_array;
838 ir_to_uniform_struct64(registers, (UINT64 *)®_array,
839 sizeof(EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS) /
840 sizeof(UINT64),
841 ARM_AARCH64_EL1_REGISTER_NAMES);
842
843 //Flush to stream.
844 fwrite(®_array, sizeof(reg_array), 1, out);
845 fflush(out);
846 }
847
848 //Converts a single AARCH64 EL2 register set CPER-JSON object to CPER binary, outputting to the given stream.
ir_arm_aarch64_el2_to_cper(json_object * registers,FILE * out)849 void ir_arm_aarch64_el2_to_cper(json_object *registers, FILE *out)
850 {
851 //Get uniform register array.
852 EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS reg_array;
853 ir_to_uniform_struct64(registers, (UINT64 *)®_array,
854 sizeof(EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS) /
855 sizeof(UINT64),
856 ARM_AARCH64_EL2_REGISTER_NAMES);
857
858 //Flush to stream.
859 fwrite(®_array, sizeof(reg_array), 1, out);
860 fflush(out);
861 }
862
863 //Converts a single AARCH64 EL3 register set CPER-JSON object to CPER binary, outputting to the given stream.
ir_arm_aarch64_el3_to_cper(json_object * registers,FILE * out)864 void ir_arm_aarch64_el3_to_cper(json_object *registers, FILE *out)
865 {
866 //Get uniform register array.
867 EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS reg_array;
868 ir_to_uniform_struct64(registers, (UINT64 *)®_array,
869 sizeof(EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS) /
870 sizeof(UINT64),
871 ARM_AARCH64_EL3_REGISTER_NAMES);
872
873 //Flush to stream.
874 fwrite(®_array, sizeof(reg_array), 1, out);
875 fflush(out);
876 }
877
878 //Converts a single ARM miscellaneous register set CPER-JSON object to CPER binary, outputting to the given stream.
ir_arm_misc_registers_to_cper(json_object * registers,FILE * out)879 void ir_arm_misc_registers_to_cper(json_object *registers, FILE *out)
880 {
881 EFI_ARM_MISC_CONTEXT_REGISTER reg_array;
882
883 //MRS encoding information.
884 json_object *mrs_encoding =
885 json_object_object_get(registers, "mrsEncoding");
886 reg_array.MrsOp2 = json_object_get_uint64(
887 json_object_object_get(mrs_encoding, "op2"));
888 reg_array.MrsCrm = json_object_get_uint64(
889 json_object_object_get(mrs_encoding, "crm"));
890 reg_array.MrsCrn = json_object_get_uint64(
891 json_object_object_get(mrs_encoding, "crn"));
892 reg_array.MrsOp1 = json_object_get_uint64(
893 json_object_object_get(mrs_encoding, "op1"));
894 reg_array.MrsO0 = json_object_get_uint64(
895 json_object_object_get(mrs_encoding, "o0"));
896
897 //Actual register value.
898 reg_array.Value = json_object_get_uint64(
899 json_object_object_get(registers, "value"));
900
901 //Flush to stream.
902 fwrite(®_array, sizeof(reg_array), 1, out);
903 fflush(out);
904 }
905
906 //Converts a single ARM unknown register CPER-JSON object to CPER binary, outputting to the given stream.
ir_arm_unknown_register_to_cper(json_object * registers,FILE * out)907 void ir_arm_unknown_register_to_cper(json_object *registers, FILE *out)
908 {
909 //Get base64 represented data.
910 json_object *encoded = json_object_object_get(registers, "data");
911
912 int32_t decoded_len = 0;
913
914 UINT8 *decoded = base64_decode(json_object_get_string(encoded),
915 json_object_get_string_len(encoded),
916 &decoded_len);
917
918 if (decoded == NULL) {
919 printf("Failed to allocate decode output buffer. \n");
920 } else {
921 //Flush out to stream.
922 fwrite(&decoded, decoded_len, 1, out);
923 fflush(out);
924 free(decoded);
925 }
926 }
927