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 <string.h>
10 #include <json.h>
11 #include <libcper/base64.h>
12 #include <libcper/Cper.h>
13 #include <libcper/cper-utils.h>
14 #include <libcper/sections/cper-section-arm.h>
15 #include <libcper/log.h>
16
17 //Private pre-definitions.
18 json_object *
19 cper_arm_error_info_to_ir(EFI_ARM_ERROR_INFORMATION_ENTRY *error_info);
20 json_object *
21 cper_arm_processor_context_to_ir(EFI_ARM_CONTEXT_INFORMATION_HEADER *header,
22 const UINT8 **cur_pos, UINT32 *remaining_size);
23 json_object *
24 cper_arm_cache_tlb_error_to_ir(EFI_ARM_CACHE_ERROR_STRUCTURE *cache_tlb_error,
25 EFI_ARM_ERROR_INFORMATION_ENTRY *error_info);
26 json_object *cper_arm_bus_error_to_ir(EFI_ARM_BUS_ERROR_STRUCTURE *bus_error);
27 json_object *cper_arm_misc_register_array_to_ir(
28 EFI_ARM_MISC_CONTEXT_REGISTER *misc_register);
29 void ir_arm_error_info_to_cper(json_object *error_info, FILE *out);
30 void ir_arm_context_info_to_cper(json_object *context_info, FILE *out);
31 void ir_arm_error_cache_tlb_info_to_cper(
32 json_object *error_information,
33 EFI_ARM_CACHE_ERROR_STRUCTURE *error_info_cper);
34 void ir_arm_error_bus_info_to_cper(json_object *error_information,
35 EFI_ARM_BUS_ERROR_STRUCTURE *error_info_cper);
36 void ir_arm_aarch32_gpr_to_cper(json_object *registers, FILE *out);
37 void ir_arm_aarch32_el1_to_cper(json_object *registers, FILE *out);
38 void ir_arm_aarch32_el2_to_cper(json_object *registers, FILE *out);
39 void ir_arm_aarch32_secure_to_cper(json_object *registers, FILE *out);
40 void ir_arm_aarch64_gpr_to_cper(json_object *registers, FILE *out);
41 void ir_arm_aarch64_el1_to_cper(json_object *registers, FILE *out);
42 void ir_arm_aarch64_el2_to_cper(json_object *registers, FILE *out);
43 void ir_arm_aarch64_el3_to_cper(json_object *registers, FILE *out);
44 void ir_arm_misc_registers_to_cper(json_object *registers, FILE *out);
45 void ir_arm_unknown_register_to_cper(json_object *registers, FILE *out);
46
47 //Converts the given processor-generic CPER section into JSON IR.
cper_section_arm_to_ir(const UINT8 * section,UINT32 size)48 json_object *cper_section_arm_to_ir(const UINT8 *section, UINT32 size)
49 {
50 const UINT8 *cur_pos = section;
51 UINT32 remaining_size = size;
52
53 if (remaining_size < sizeof(EFI_ARM_ERROR_RECORD)) {
54 return NULL;
55 }
56 EFI_ARM_ERROR_RECORD *record = (EFI_ARM_ERROR_RECORD *)cur_pos;
57 cur_pos += sizeof(EFI_ARM_ERROR_RECORD);
58 remaining_size -= sizeof(EFI_ARM_ERROR_RECORD);
59 json_object *section_ir = json_object_new_object();
60
61 //Length of ValidationBits from spec
62 ValidationTypes ui64Type = { UINT_64T,
63 .value.ui64 = record->ValidFields };
64
65 //Number of error info and context info structures, and length.
66 json_object_object_add(section_ir, "errorInfoNum",
67 json_object_new_int(record->ErrInfoNum));
68 json_object_object_add(section_ir, "contextInfoNum",
69 json_object_new_int(record->ContextInfoNum));
70 json_object_object_add(section_ir, "sectionLength",
71 json_object_new_uint64(record->SectionLength));
72
73 //Error affinity.
74 if (isvalid_prop_to_ir(&ui64Type, 1)) {
75 json_object *error_affinity = json_object_new_object();
76 json_object_object_add(
77 error_affinity, "value",
78 json_object_new_int(record->ErrorAffinityLevel));
79 json_object_object_add(
80 error_affinity, "type",
81 json_object_new_string(record->ErrorAffinityLevel < 4 ?
82 "Vendor Defined" :
83 "Reserved"));
84 json_object_object_add(section_ir, "errorAffinity",
85 error_affinity);
86 }
87
88 //Processor ID (MPIDR_EL1) and chip ID (MIDR_EL1).
89 if (isvalid_prop_to_ir(&ui64Type, 0)) {
90 uint64_t mpidr_eli1 = record->MPIDR_EL1;
91 uint64_t sock;
92 json_object_object_add(section_ir, "mpidrEl1",
93 json_object_new_uint64(mpidr_eli1));
94
95 //Arm Processor socket info dependes on mpidr_eli1
96 sock = (mpidr_eli1 & ARM_SOCK_MASK) >> 32;
97 json_object_object_add(section_ir, "affinity3",
98 json_object_new_uint64(sock));
99 }
100
101 json_object_object_add(section_ir, "midrEl1",
102 json_object_new_uint64(record->MIDR_EL1));
103
104 if (isvalid_prop_to_ir(&ui64Type, 2)) {
105 //Whether the processor is running, and the state of it if so.
106 json_object_object_add(
107 section_ir, "running",
108 json_object_new_boolean(record->RunningState & 0x1));
109 }
110 if (!(record->RunningState >> 31)) {
111 //Bit 32 of running state is on, so PSCI state information is included.
112 //This can't be made human readable, as it is unknown whether this will be the pre-PSCI 1.0 format
113 //or the newer Extended StateID format.
114 json_object_object_add(
115 section_ir, "psciState",
116 json_object_new_uint64(record->PsciState));
117 }
118
119 //Processor error structures.
120 json_object *error_info_array = json_object_new_array();
121 EFI_ARM_ERROR_INFORMATION_ENTRY *cur_error =
122 (EFI_ARM_ERROR_INFORMATION_ENTRY *)(record + 1);
123 if (remaining_size <
124 (record->ErrInfoNum * sizeof(EFI_ARM_ERROR_INFORMATION_ENTRY))) {
125 json_object_put(error_info_array);
126 json_object_put(section_ir);
127 cper_print_log(
128 "Invalid CPER file: Invalid processor error info num.\n");
129 return NULL;
130 }
131 for (int i = 0; i < record->ErrInfoNum; i++) {
132 json_object_array_add(error_info_array,
133 cper_arm_error_info_to_ir(cur_error));
134 cur_error++;
135 }
136
137 cur_pos += (UINT32)(record->ErrInfoNum *
138 sizeof(EFI_ARM_ERROR_INFORMATION_ENTRY));
139 remaining_size -= (UINT32)(record->ErrInfoNum *
140 sizeof(EFI_ARM_ERROR_INFORMATION_ENTRY));
141
142 json_object_object_add(section_ir, "errorInfo", error_info_array);
143
144 //Processor context structures.
145 //The current position is moved within the processing, as it is a dynamic size structure.
146 json_object *context_info_array = json_object_new_array();
147 for (int i = 0; i < record->ContextInfoNum; i++) {
148 if (remaining_size <
149 sizeof(EFI_ARM_CONTEXT_INFORMATION_HEADER)) {
150 json_object_put(context_info_array);
151 json_object_put(section_ir);
152 cper_print_log(
153 "Invalid CPER file: Invalid processor context info num.\n");
154 return NULL;
155 }
156 EFI_ARM_CONTEXT_INFORMATION_HEADER *header =
157 (EFI_ARM_CONTEXT_INFORMATION_HEADER *)cur_pos;
158
159 cur_pos += sizeof(EFI_ARM_CONTEXT_INFORMATION_HEADER);
160 remaining_size -= sizeof(EFI_ARM_CONTEXT_INFORMATION_HEADER);
161 json_object *processor_context =
162 cper_arm_processor_context_to_ir(header, &cur_pos,
163 &remaining_size);
164 if (processor_context == NULL) {
165 json_object_put(context_info_array);
166 json_object_put(section_ir);
167 cper_print_log(
168 "Invalid CPER file: Invalid processor context info num.\n");
169 return NULL;
170 }
171 json_object_array_add(context_info_array, processor_context);
172 }
173 json_object_object_add(section_ir, "contextInfo", context_info_array);
174
175 //Is there any vendor-specific information following?
176 if (isvalid_prop_to_ir(&ui64Type, 3)) {
177 if (cur_pos < (uint8_t *)section + record->SectionLength) {
178 json_object *vendor_specific = json_object_new_object();
179 size_t input_size = (uint8_t *)section +
180 record->SectionLength - cur_pos;
181 if (remaining_size < input_size) {
182 json_object_put(vendor_specific);
183 json_object_put(section_ir);
184 cper_print_log(
185 "Invalid CPER file: Invalid vendor-specific info length.\n");
186 return NULL;
187 }
188 int32_t encoded_len = 0;
189 char *encoded = base64_encode(cur_pos, input_size,
190 &encoded_len);
191 if (encoded == NULL) {
192 json_object_put(vendor_specific);
193 json_object_put(section_ir);
194 cper_print_log(
195 "base64 encode of vendorSpecificInfo failed\n");
196 return NULL;
197 }
198 json_object_object_add(vendor_specific, "data",
199 json_object_new_string_len(
200 encoded, encoded_len));
201 free(encoded);
202
203 json_object_object_add(section_ir, "vendorSpecificInfo",
204 vendor_specific);
205 } else {
206 cper_print_log(
207 "vendorSpecificInfo is marked valid but not present in binary\n");
208 }
209 }
210
211 return section_ir;
212 }
213
214 //Converts a single ARM Process Error Information structure into JSON IR.
215 json_object *
cper_arm_error_info_to_ir(EFI_ARM_ERROR_INFORMATION_ENTRY * error_info)216 cper_arm_error_info_to_ir(EFI_ARM_ERROR_INFORMATION_ENTRY *error_info)
217 {
218 json_object *error_info_ir = json_object_new_object();
219
220 //Version, length.
221 json_object_object_add(error_info_ir, "version",
222 json_object_new_int(error_info->Version));
223 json_object_object_add(error_info_ir, "length",
224 json_object_new_int(error_info->Length));
225
226 //Validation bitfield.
227 ValidationTypes ui16Type = { UINT_16T,
228 .value.ui16 = error_info->ValidationBits };
229
230 //The type of error information in this log.
231 json_object *error_type = integer_to_readable_pair(
232 error_info->Type, 4, ARM_ERROR_INFO_ENTRY_INFO_TYPES_KEYS,
233 ARM_ERROR_INFO_ENTRY_INFO_TYPES_VALUES, "Unknown (Reserved)");
234 json_object_object_add(error_info_ir, "errorType", error_type);
235
236 //Multiple error count.
237 if (isvalid_prop_to_ir(&ui16Type, 0)) {
238 json_object *multiple_error = json_object_new_object();
239 json_object_object_add(
240 multiple_error, "value",
241 json_object_new_int(error_info->MultipleError));
242 json_object_object_add(
243 multiple_error, "type",
244 json_object_new_string(error_info->MultipleError < 1 ?
245 "Single Error" :
246 "Multiple Errors"));
247 json_object_object_add(error_info_ir, "multipleError",
248 multiple_error);
249 }
250
251 //Flags.
252 if (isvalid_prop_to_ir(&ui16Type, 1)) {
253 json_object *flags = bitfield_to_ir(
254 error_info->Flags, 4, ARM_ERROR_INFO_ENTRY_FLAGS_NAMES);
255 json_object_object_add(error_info_ir, "flags", flags);
256 }
257
258 //Error information, split by type.
259 if (isvalid_prop_to_ir(&ui16Type, 2)) {
260 json_object *error_subinfo = NULL;
261 switch (error_info->Type) {
262 case ARM_ERROR_INFORMATION_TYPE_CACHE: //Cache
263 case ARM_ERROR_INFORMATION_TYPE_TLB: //TLB
264 error_subinfo = cper_arm_cache_tlb_error_to_ir(
265 (EFI_ARM_CACHE_ERROR_STRUCTURE *)&error_info
266 ->ErrorInformation,
267 error_info);
268 break;
269 case ARM_ERROR_INFORMATION_TYPE_BUS: //Bus
270 error_subinfo = cper_arm_bus_error_to_ir(
271 (EFI_ARM_BUS_ERROR_STRUCTURE *)&error_info
272 ->ErrorInformation);
273 break;
274
275 default:
276 //Unknown/microarch, will not support.
277 break;
278 }
279 if (error_subinfo != NULL) {
280 json_object_object_add(error_info_ir,
281 "errorInformation",
282 error_subinfo);
283 }
284 }
285
286 //Virtual fault address, physical fault address.
287 if (isvalid_prop_to_ir(&ui16Type, 3)) {
288 json_object_object_add(
289 error_info_ir, "virtualFaultAddress",
290 json_object_new_uint64(
291 error_info->VirtualFaultAddress));
292 }
293 if (isvalid_prop_to_ir(&ui16Type, 4)) {
294 json_object_object_add(
295 error_info_ir, "physicalFaultAddress",
296 json_object_new_uint64(
297 error_info->PhysicalFaultAddress));
298 }
299
300 return error_info_ir;
301 }
302
303 //Converts a single ARM cache/TLB error information structure into JSON IR format.
304 json_object *
cper_arm_cache_tlb_error_to_ir(EFI_ARM_CACHE_ERROR_STRUCTURE * cache_tlb_error,EFI_ARM_ERROR_INFORMATION_ENTRY * error_info)305 cper_arm_cache_tlb_error_to_ir(EFI_ARM_CACHE_ERROR_STRUCTURE *cache_tlb_error,
306 EFI_ARM_ERROR_INFORMATION_ENTRY *error_info)
307 {
308 json_object *cache_tlb_error_ir = json_object_new_object();
309 json_object *cache_tlb_prop = json_object_new_object();
310 char *cache_tlb_propname;
311
312 //Validation bitfield.
313 ValidationTypes ui64Type = {
314 UINT_64T, .value.ui64 = cache_tlb_error->ValidationBits
315 };
316
317 //Transaction type.
318 if (isvalid_prop_to_ir(&ui64Type, 0)) {
319 json_object *transaction_type = integer_to_readable_pair(
320 cache_tlb_error->TransactionType, 3,
321 ARM_ERROR_TRANSACTION_TYPES_KEYS,
322 ARM_ERROR_TRANSACTION_TYPES_VALUES,
323 "Unknown (Reserved)");
324 json_object_object_add(cache_tlb_error_ir, "transactionType",
325 transaction_type);
326 }
327
328 //Operation.
329 bool cacheErrorFlag = 1;
330 if (error_info->Type == 0) {
331 cache_tlb_propname = "cacheError";
332 } else {
333 //TLB operation.
334 cache_tlb_propname = "tlbError";
335 cacheErrorFlag = 0;
336 }
337
338 if (isvalid_prop_to_ir(&ui64Type, 1)) {
339 json_object *operation;
340
341 if (cacheErrorFlag) {
342 //Cache operation.
343 operation = integer_to_readable_pair(
344 cache_tlb_error->Operation, 11,
345 ARM_CACHE_BUS_OPERATION_TYPES_KEYS,
346 ARM_CACHE_BUS_OPERATION_TYPES_VALUES,
347 "Unknown (Reserved)");
348 } else {
349 operation = integer_to_readable_pair(
350 cache_tlb_error->Operation, 9,
351 ARM_TLB_OPERATION_TYPES_KEYS,
352 ARM_TLB_OPERATION_TYPES_VALUES,
353 "Unknown (Reserved)");
354 }
355 json_object_object_add(cache_tlb_error_ir, "operation",
356 operation);
357 }
358
359 //Miscellaneous remaining fields.
360 if (isvalid_prop_to_ir(&ui64Type, 2)) {
361 json_object_object_add(
362 cache_tlb_error_ir, "level",
363 json_object_new_int(cache_tlb_error->Level));
364 }
365 if (isvalid_prop_to_ir(&ui64Type, 3)) {
366 json_object_object_add(
367 cache_tlb_error_ir, "processorContextCorrupt",
368 json_object_new_boolean(
369 cache_tlb_error->ProcessorContextCorrupt));
370 }
371 if (isvalid_prop_to_ir(&ui64Type, 4)) {
372 json_object_object_add(
373 cache_tlb_error_ir, "corrected",
374 json_object_new_boolean(cache_tlb_error->Corrected));
375 }
376 if (isvalid_prop_to_ir(&ui64Type, 5)) {
377 json_object_object_add(
378 cache_tlb_error_ir, "precisePC",
379 json_object_new_boolean(cache_tlb_error->PrecisePC));
380 }
381 if (isvalid_prop_to_ir(&ui64Type, 6)) {
382 json_object_object_add(cache_tlb_error_ir, "restartablePC",
383 json_object_new_boolean(
384 cache_tlb_error->RestartablePC));
385 }
386
387 json_object_object_add(cache_tlb_prop, cache_tlb_propname,
388 cache_tlb_error_ir);
389
390 return cache_tlb_prop;
391 }
392
393 //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)394 json_object *cper_arm_bus_error_to_ir(EFI_ARM_BUS_ERROR_STRUCTURE *bus_error)
395 {
396 json_object *bus_error_ir = json_object_new_object();
397 json_object *bus_prop = json_object_new_object();
398 char *bus_propname = "busError";
399
400 //Validation bits.
401 ValidationTypes ui64Type = { UINT_64T,
402 .value.ui64 = bus_error->ValidationBits };
403
404 //Transaction type.
405 if (isvalid_prop_to_ir(&ui64Type, 0)) {
406 json_object *transaction_type = integer_to_readable_pair(
407 bus_error->TransactionType, 3,
408 ARM_ERROR_TRANSACTION_TYPES_KEYS,
409 ARM_ERROR_TRANSACTION_TYPES_VALUES,
410 "Unknown (Reserved)");
411 json_object_object_add(bus_error_ir, "transactionType",
412 transaction_type);
413 }
414
415 //Operation.
416 if (isvalid_prop_to_ir(&ui64Type, 1)) {
417 json_object *operation = integer_to_readable_pair(
418 bus_error->Operation, 7,
419 ARM_CACHE_BUS_OPERATION_TYPES_KEYS,
420 ARM_CACHE_BUS_OPERATION_TYPES_VALUES,
421 "Unknown (Reserved)");
422 json_object_object_add(bus_error_ir, "operation", operation);
423 }
424
425 if (isvalid_prop_to_ir(&ui64Type, 2)) {
426 //Affinity level of bus error, + miscellaneous fields.
427 json_object_object_add(bus_error_ir, "level",
428 json_object_new_int(bus_error->Level));
429 }
430 if (isvalid_prop_to_ir(&ui64Type, 3)) {
431 json_object_object_add(
432 bus_error_ir, "processorContextCorrupt",
433 json_object_new_boolean(
434 bus_error->ProcessorContextCorrupt));
435 }
436 if (isvalid_prop_to_ir(&ui64Type, 4)) {
437 json_object_object_add(
438 bus_error_ir, "corrected",
439 json_object_new_boolean(bus_error->Corrected));
440 }
441 if (isvalid_prop_to_ir(&ui64Type, 5)) {
442 json_object_object_add(
443 bus_error_ir, "precisePC",
444 json_object_new_boolean(bus_error->PrecisePC));
445 }
446 if (isvalid_prop_to_ir(&ui64Type, 6)) {
447 json_object_object_add(
448 bus_error_ir, "restartablePC",
449 json_object_new_boolean(bus_error->RestartablePC));
450 }
451
452 //Participation type.
453 if (isvalid_prop_to_ir(&ui64Type, 7)) {
454 json_object *participation_type = integer_to_readable_pair(
455 bus_error->ParticipationType, 4,
456 ARM_BUS_PARTICIPATION_TYPES_KEYS,
457 ARM_BUS_PARTICIPATION_TYPES_VALUES, "Unknown");
458 json_object_object_add(bus_error_ir, "participationType",
459 participation_type);
460 }
461 if (isvalid_prop_to_ir(&ui64Type, 8)) {
462 json_object_object_add(
463 bus_error_ir, "timedOut",
464 json_object_new_boolean(bus_error->TimeOut));
465 }
466
467 //Address space.
468 if (isvalid_prop_to_ir(&ui64Type, 9)) {
469 json_object *address_space = integer_to_readable_pair(
470 bus_error->AddressSpace, 3,
471 ARM_BUS_ADDRESS_SPACE_TYPES_KEYS,
472 ARM_BUS_ADDRESS_SPACE_TYPES_VALUES, "Unknown");
473 json_object_object_add(bus_error_ir, "addressSpace",
474 address_space);
475 }
476
477 //Memory access attributes.
478 //todo: find the specification of these in the ARM ARM
479 if (isvalid_prop_to_ir(&ui64Type, 10)) {
480 json_object_object_add(
481 bus_error_ir, "memoryAttributes",
482 json_object_new_int(
483 bus_error->MemoryAddressAttributes));
484 }
485
486 //Access Mode
487 if (isvalid_prop_to_ir(&ui64Type, 8)) {
488 json_object *access_mode = json_object_new_object();
489 json_object_object_add(
490 access_mode, "value",
491 json_object_new_int(bus_error->AccessMode));
492 json_object_object_add(
493 access_mode, "name",
494 json_object_new_string(bus_error->AccessMode == 0 ?
495 "Secure" :
496 "Normal"));
497 json_object_object_add(bus_error_ir, "accessMode", access_mode);
498 }
499 json_object_object_add(bus_prop, bus_propname, bus_error_ir);
500
501 return bus_prop;
502 }
503
504 //Converts a single ARM processor context block into JSON IR.
505 json_object *
cper_arm_processor_context_to_ir(EFI_ARM_CONTEXT_INFORMATION_HEADER * header,const UINT8 ** cur_pos,UINT32 * remaining_size)506 cper_arm_processor_context_to_ir(EFI_ARM_CONTEXT_INFORMATION_HEADER *header,
507 const UINT8 **cur_pos, UINT32 *remaining_size)
508 {
509 if (header->RegisterArraySize > *remaining_size) {
510 cper_print_log(
511 "Invalid CPER file: Invalid processor context info num.\n");
512 return NULL;
513 }
514
515 json_object *context_ir = json_object_new_object();
516
517 //Version.
518 json_object_object_add(context_ir, "version",
519 json_object_new_int(header->Version));
520
521 //Add the context type.
522 json_object *context_type = integer_to_readable_pair(
523 header->RegisterContextType,
524 ARM_PROCESSOR_INFO_REGISTER_CONTEXT_TYPES_COUNT,
525 ARM_PROCESSOR_INFO_REGISTER_CONTEXT_TYPES_KEYS,
526 ARM_PROCESSOR_INFO_REGISTER_CONTEXT_TYPES_VALUES,
527 "Unknown (Reserved)");
528 json_object_object_add(context_ir, "registerContextType", context_type);
529
530 //Register array size (bytes).
531 json_object_object_add(
532 context_ir, "registerArraySize",
533 json_object_new_uint64(header->RegisterArraySize));
534
535 //The register array itself.
536 json_object *register_array = NULL;
537 switch (header->RegisterContextType) {
538 case EFI_ARM_CONTEXT_TYPE_AARCH32_GPR:
539 if (*remaining_size < sizeof(EFI_ARM_V8_AARCH32_GPR)) {
540 cper_print_log(
541 "Invalid CPER file: Invalid processor context info num.\n");
542 goto fail;
543 }
544 if (header->RegisterArraySize <
545 sizeof(EFI_ARM_V8_AARCH32_GPR)) {
546 cper_print_log(
547 "Invalid CPER file: Not enough bytes for aarch32 gpr\n");
548 goto fail;
549 }
550 register_array = uniform_struct_to_ir(
551 (UINT32 *)*cur_pos,
552 sizeof(EFI_ARM_V8_AARCH32_GPR) / sizeof(UINT32),
553 ARM_AARCH32_GPR_NAMES);
554 break;
555 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL1:
556 if (*remaining_size <
557 sizeof(EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS)) {
558 cper_print_log(
559 "Invalid CPER file: Invalid processor context info num.\n");
560 goto fail;
561 }
562 if (header->RegisterArraySize <
563 sizeof(EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS)) {
564 cper_print_log(
565 "Invalid CPER file: Not enough bytes for aarch32 el1\n");
566 goto fail;
567 }
568 register_array = uniform_struct_to_ir(
569 (UINT32 *)*cur_pos,
570 sizeof(EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS) /
571 sizeof(UINT32),
572 ARM_AARCH32_EL1_REGISTER_NAMES);
573 break;
574 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL2:
575 if (*remaining_size <
576 sizeof(EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS)) {
577 cper_print_log(
578 "Invalid CPER file: Invalid processor context info num.\n");
579 goto fail;
580 }
581 if (header->RegisterArraySize <
582 sizeof(EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS)) {
583 cper_print_log(
584 "Invalid CPER file: Not enough bytes for aarch32 el2\n");
585 goto fail;
586 }
587 register_array = uniform_struct_to_ir(
588 (UINT32 *)*cur_pos,
589 sizeof(EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS) /
590 sizeof(UINT32),
591 ARM_AARCH32_EL2_REGISTER_NAMES);
592
593 break;
594 case EFI_ARM_CONTEXT_TYPE_AARCH32_SECURE:
595 if (*remaining_size <
596 sizeof(EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS)) {
597 json_object_put(context_ir);
598 cper_print_log(
599 "Invalid CPER file: Invalid processor context info num.\n");
600 return NULL;
601 }
602 if (header->RegisterArraySize <
603 sizeof(EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS)) {
604 cper_print_log(
605 "Invalid CPER file: Not enough bytes for aarch32 secure\n");
606 goto fail;
607 }
608 register_array = uniform_struct_to_ir(
609 (UINT32 *)*cur_pos,
610 sizeof(EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS) /
611 sizeof(UINT32),
612 ARM_AARCH32_SECURE_REGISTER_NAMES);
613 break;
614 case EFI_ARM_CONTEXT_TYPE_AARCH64_GPR:
615 if (*remaining_size < sizeof(EFI_ARM_V8_AARCH64_GPR)) {
616 cper_print_log(
617 "Invalid CPER file: Invalid processor context info num.\n");
618 goto fail;
619 }
620 if (header->RegisterArraySize <
621 sizeof(EFI_ARM_V8_AARCH64_GPR)) {
622 cper_print_log(
623 "Invalid CPER file: Not enough bytes for aarch64 gpr\n");
624 goto fail;
625 }
626 register_array = uniform_struct64_to_ir(
627 (UINT64 *)*cur_pos,
628 sizeof(EFI_ARM_V8_AARCH64_GPR) / sizeof(UINT64),
629 ARM_AARCH64_GPR_NAMES);
630 break;
631 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL1:
632 if (*remaining_size <
633 sizeof(EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS)) {
634 cper_print_log(
635 "Invalid CPER file: Invalid processor context info num.\n");
636 goto fail;
637 }
638 if (header->RegisterArraySize <
639 sizeof(EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS)) {
640 cper_print_log(
641 "Invalid CPER file: Not enough bytes for aarch64 el1\n");
642 goto fail;
643 }
644 register_array = uniform_struct64_to_ir(
645 (UINT64 *)*cur_pos,
646 sizeof(EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS) /
647 sizeof(UINT64),
648 ARM_AARCH64_EL1_REGISTER_NAMES);
649 break;
650 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL2:
651 if (*remaining_size <
652 sizeof(EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS)) {
653 cper_print_log(
654 "Invalid CPER file: Invalid processor context info num.\n");
655 goto fail;
656 }
657 if (header->RegisterArraySize <
658 sizeof(EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS)) {
659 cper_print_log(
660 "Invalid CPER file: Not enough bytes for aarch64 el2\n");
661 goto fail;
662 }
663 register_array = uniform_struct64_to_ir(
664 (UINT64 *)*cur_pos,
665 sizeof(EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS) /
666 sizeof(UINT64),
667 ARM_AARCH64_EL2_REGISTER_NAMES);
668 break;
669 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL3:
670 if (*remaining_size <
671 sizeof(EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS)) {
672 cper_print_log(
673 "Invalid CPER file: Invalid processor context info num.\n");
674 goto fail;
675 }
676 if (header->RegisterArraySize <
677 sizeof(EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS)) {
678 cper_print_log(
679 "Invalid CPER file: Not enough bytes for aarch64 el3\n");
680 goto fail;
681 }
682 register_array = uniform_struct64_to_ir(
683 (UINT64 *)*cur_pos,
684 sizeof(EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS) /
685 sizeof(UINT64),
686 ARM_AARCH64_EL3_REGISTER_NAMES);
687 break;
688 case EFI_ARM_CONTEXT_TYPE_MISC:
689 if (*remaining_size < sizeof(EFI_ARM_MISC_CONTEXT_REGISTER)) {
690 cper_print_log(
691 "Invalid CPER file: Invalid processor context info num.\n");
692 goto fail;
693 }
694 if (header->RegisterArraySize <
695 sizeof(EFI_ARM_MISC_CONTEXT_REGISTER)) {
696 cper_print_log(
697 "Invalid CPER file: Not enough bytes for misc\n");
698 goto fail;
699 }
700 register_array = cper_arm_misc_register_array_to_ir(
701 (EFI_ARM_MISC_CONTEXT_REGISTER *)*cur_pos);
702 break;
703 default:
704 if (*remaining_size < header->RegisterArraySize) {
705 cper_print_log(
706 "Invalid CPER file: Invalid processor context info num.\n");
707 goto fail;
708 }
709 //Unknown register array type, add as base64 data instead.
710 int32_t encoded_len = 0;
711 char *encoded = base64_encode((UINT8 *)*cur_pos,
712 header->RegisterArraySize,
713 &encoded_len);
714 if (encoded == NULL) {
715 goto fail;
716 }
717 register_array = json_object_new_object();
718 json_object_object_add(register_array, "data",
719 json_object_new_string_len(encoded,
720 encoded_len));
721 free(encoded);
722
723 break;
724 }
725 json_object_object_add(context_ir, "registerArray", register_array);
726
727 //Set the current position to after the processor context structure.
728 *cur_pos = (UINT8 *)(*cur_pos) + header->RegisterArraySize;
729 *remaining_size -= header->RegisterArraySize;
730
731 return context_ir;
732
733 fail:
734 json_object_put(context_ir);
735 return NULL;
736 }
737
738 //Converts a single CPER ARM miscellaneous register array to JSON IR format.
739 json_object *
cper_arm_misc_register_array_to_ir(EFI_ARM_MISC_CONTEXT_REGISTER * misc_register)740 cper_arm_misc_register_array_to_ir(EFI_ARM_MISC_CONTEXT_REGISTER *misc_register)
741 {
742 json_object *register_array = json_object_new_object();
743 json_object *mrs_encoding = json_object_new_object();
744 json_object_object_add(mrs_encoding, "op2",
745 json_object_new_uint64(misc_register->MrsOp2));
746 json_object_object_add(mrs_encoding, "crm",
747 json_object_new_uint64(misc_register->MrsCrm));
748 json_object_object_add(mrs_encoding, "crn",
749 json_object_new_uint64(misc_register->MrsCrn));
750 json_object_object_add(mrs_encoding, "op1",
751 json_object_new_uint64(misc_register->MrsOp1));
752 json_object_object_add(mrs_encoding, "o0",
753 json_object_new_uint64(misc_register->MrsO0));
754 json_object_object_add(register_array, "mrsEncoding", mrs_encoding);
755 json_object_object_add(register_array, "value",
756 json_object_new_uint64(misc_register->Value));
757
758 return register_array;
759 }
760
761 //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)762 void ir_section_arm_to_cper(json_object *section, FILE *out)
763 {
764 EFI_ARM_ERROR_RECORD section_cper;
765 memset(§ion_cper, 0, sizeof(section_cper));
766
767 //Validation bits.
768 struct json_object *obj = NULL;
769 ValidationTypes u32Type = { UINT_32T, .value.ui32 = 0 };
770
771 //Count of error/context info structures.
772 section_cper.ErrInfoNum = json_object_get_int(
773 json_object_object_get(section, "errorInfoNum"));
774 section_cper.ContextInfoNum = json_object_get_int(
775 json_object_object_get(section, "contextInfoNum"));
776
777 //Miscellaneous raw value fields.
778 section_cper.SectionLength = json_object_get_uint64(
779 json_object_object_get(section, "sectionLength"));
780 if (json_object_object_get_ex(section, "mpidrEl1", &obj)) {
781 section_cper.MPIDR_EL1 = json_object_get_uint64(obj);
782 add_to_valid_bitfield(&u32Type, 0);
783 }
784 if (json_object_object_get_ex(section, "errorAffinity", &obj)) {
785 section_cper.ErrorAffinityLevel = readable_pair_to_integer(obj);
786 add_to_valid_bitfield(&u32Type, 1);
787 }
788 section_cper.MIDR_EL1 = json_object_get_uint64(
789 json_object_object_get(section, "midrEl1"));
790 if (json_object_object_get_ex(section, "running", &obj)) {
791 section_cper.RunningState = json_object_get_boolean(obj);
792 add_to_valid_bitfield(&u32Type, 2);
793 }
794
795 //Optional PSCI state.
796 json_object *psci_state = json_object_object_get(section, "psciState");
797 if (psci_state != NULL) {
798 section_cper.PsciState = json_object_get_uint64(psci_state);
799 }
800
801 //Validationbits for EFI_ARM_ERROR_RECORD should also consider vendorSpecificInfo
802 bool vendorSpecificPresent =
803 json_object_object_get_ex(section, "vendorSpecificInfo", &obj);
804 json_object *vendor_specific_info = obj;
805 if (vendorSpecificPresent) {
806 add_to_valid_bitfield(&u32Type, 3);
807 }
808
809 section_cper.ValidFields = u32Type.value.ui32;
810
811 //Flush header to stream.
812 fwrite(§ion_cper, sizeof(section_cper), 1, out);
813
814 //Error info structure array.
815
816 json_object *error_info = json_object_object_get(section, "errorInfo");
817 for (int i = 0; i < section_cper.ErrInfoNum; i++) {
818 ir_arm_error_info_to_cper(
819 json_object_array_get_idx(error_info, i), out);
820 }
821
822 //Context info structure array.
823 json_object *context_info =
824 json_object_object_get(section, "contextInfo");
825 for (int i = 0; i < section_cper.ContextInfoNum; i++) {
826 ir_arm_context_info_to_cper(
827 json_object_array_get_idx(context_info, i), out);
828 }
829
830 //Vendor specific error info.
831 if (vendorSpecificPresent) {
832 json_object *vendor_info_string =
833 json_object_object_get(vendor_specific_info, "data");
834 int vendor_specific_len =
835 json_object_get_string_len(vendor_info_string);
836
837 int32_t decoded_len = 0;
838
839 UINT8 *decoded = base64_decode(
840 json_object_get_string(vendor_info_string),
841 vendor_specific_len, &decoded_len);
842
843 //Write out to file.
844 fwrite(decoded, decoded_len, 1, out);
845 free(decoded);
846 }
847
848 fflush(out);
849 }
850
851 //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)852 void ir_arm_error_info_to_cper(json_object *error_info, FILE *out)
853 {
854 EFI_ARM_ERROR_INFORMATION_ENTRY error_info_cper;
855 memset(&error_info_cper, 0, sizeof(error_info_cper));
856 struct json_object *obj = NULL;
857 ValidationTypes ui16Type = { UINT_16T, .value.ui16 = 0 };
858
859 //Version, length.
860 error_info_cper.Version = json_object_get_int(
861 json_object_object_get(error_info, "version"));
862 error_info_cper.Length = json_object_get_int(
863 json_object_object_get(error_info, "length"));
864
865 //Type, multiple error.
866 error_info_cper.Type = (UINT8)readable_pair_to_integer(
867 json_object_object_get(error_info, "errorType"));
868
869 if (json_object_object_get_ex(error_info, "multipleError", &obj)) {
870 error_info_cper.MultipleError =
871 (UINT16)readable_pair_to_integer(obj);
872 add_to_valid_bitfield(&ui16Type, 0);
873 } else {
874 error_info_cper.MultipleError = 0;
875 }
876
877 //Flags object.
878 if (json_object_object_get_ex(error_info, "flags", &obj)) {
879 error_info_cper.Flags = (UINT8)ir_to_bitfield(
880 obj, 4, ARM_ERROR_INFO_ENTRY_FLAGS_NAMES);
881 add_to_valid_bitfield(&ui16Type, 1);
882 } else {
883 error_info_cper.Flags = 0;
884 }
885
886 //Error information.
887 if (json_object_object_get_ex(error_info, "errorInformation", &obj)) {
888 json_object *error_info_information = obj;
889 json_object *error_info_prop = NULL;
890 switch (error_info_cper.Type) {
891 case ARM_ERROR_INFORMATION_TYPE_CACHE:
892 error_info_cper.ErrorInformation.Value = 0;
893 error_info_prop = json_object_object_get(
894 error_info_information, "cacheError");
895 ir_arm_error_cache_tlb_info_to_cper(
896 error_info_prop,
897 &error_info_cper.ErrorInformation.CacheError);
898 break;
899 case ARM_ERROR_INFORMATION_TYPE_TLB:
900 error_info_cper.ErrorInformation.Value = 0;
901 error_info_prop = json_object_object_get(
902 error_info_information, "tlbError");
903 ir_arm_error_cache_tlb_info_to_cper(
904 error_info_prop,
905 &error_info_cper.ErrorInformation.CacheError);
906 break;
907
908 case ARM_ERROR_INFORMATION_TYPE_BUS:
909 error_info_cper.ErrorInformation.Value = 0;
910 error_info_prop = json_object_object_get(
911 error_info_information, "busError");
912 ir_arm_error_bus_info_to_cper(
913 error_info_prop,
914 &error_info_cper.ErrorInformation.BusError);
915 break;
916
917 default:
918 //Unknown error information type.
919 break;
920 }
921 add_to_valid_bitfield(&ui16Type, 2);
922 }
923
924 //Virtual/physical fault address.
925 if (json_object_object_get_ex(error_info, "virtualFaultAddress",
926 &obj)) {
927 error_info_cper.VirtualFaultAddress =
928 json_object_get_uint64(obj);
929 add_to_valid_bitfield(&ui16Type, 3);
930 } else {
931 error_info_cper.VirtualFaultAddress = 0;
932 }
933
934 if (json_object_object_get_ex(error_info, "physicalFaultAddress",
935 &obj)) {
936 error_info_cper.PhysicalFaultAddress =
937 json_object_get_uint64(obj);
938 add_to_valid_bitfield(&ui16Type, 4);
939 } else {
940 error_info_cper.PhysicalFaultAddress = 0;
941 }
942 error_info_cper.ValidationBits = ui16Type.value.ui16;
943
944 //Write out to stream.
945 fwrite(&error_info_cper, sizeof(EFI_ARM_ERROR_INFORMATION_ENTRY), 1,
946 out);
947 }
948
949 //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)950 void ir_arm_error_cache_tlb_info_to_cper(
951 json_object *error_information,
952 EFI_ARM_CACHE_ERROR_STRUCTURE *error_info_cper)
953 {
954 // //Validation bits.
955 ValidationTypes ui64Type = { UINT_64T, .value.ui64 = 0 };
956 struct json_object *obj = NULL;
957
958 //Miscellaneous value fields.
959 if (json_object_object_get_ex(error_information, "transactionType",
960 &obj)) {
961 error_info_cper->TransactionType =
962 readable_pair_to_integer(obj);
963 add_to_valid_bitfield(&ui64Type, 0);
964 }
965 if (json_object_object_get_ex(error_information, "operation", &obj)) {
966 error_info_cper->Operation = readable_pair_to_integer(obj);
967 add_to_valid_bitfield(&ui64Type, 1);
968 }
969 if (json_object_object_get_ex(error_information, "level", &obj)) {
970 error_info_cper->Level = json_object_get_uint64(obj);
971 add_to_valid_bitfield(&ui64Type, 2);
972 }
973 if (json_object_object_get_ex(error_information,
974 "processorContextCorrupt", &obj)) {
975 error_info_cper->ProcessorContextCorrupt =
976 json_object_get_boolean(obj);
977 add_to_valid_bitfield(&ui64Type, 3);
978 }
979 if (json_object_object_get_ex(error_information, "corrected", &obj)) {
980 error_info_cper->Corrected = json_object_get_boolean(obj);
981 add_to_valid_bitfield(&ui64Type, 4);
982 }
983 if (json_object_object_get_ex(error_information, "precisePC", &obj)) {
984 error_info_cper->PrecisePC = json_object_get_boolean(obj);
985 add_to_valid_bitfield(&ui64Type, 5);
986 }
987 if (json_object_object_get_ex(error_information, "restartablePC",
988 &obj)) {
989 error_info_cper->RestartablePC = json_object_get_boolean(obj);
990 add_to_valid_bitfield(&ui64Type, 6);
991 }
992 error_info_cper->Reserved = 0;
993 error_info_cper->ValidationBits = ui64Type.value.ui64;
994 }
995
996 //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)997 void ir_arm_error_bus_info_to_cper(json_object *error_information,
998 EFI_ARM_BUS_ERROR_STRUCTURE *error_info_cper)
999 {
1000 //Validation bits.
1001 ValidationTypes ui64Type = { UINT_64T, .value.ui64 = 0 };
1002 struct json_object *obj = NULL;
1003
1004 memset(error_info_cper, 0, sizeof(EFI_ARM_BUS_ERROR_STRUCTURE));
1005
1006 //Miscellaneous value fields.
1007 if (json_object_object_get_ex(error_information, "transactionType",
1008 &obj)) {
1009 error_info_cper->TransactionType =
1010 readable_pair_to_integer(obj);
1011 add_to_valid_bitfield(&ui64Type, 0);
1012 } else {
1013 error_info_cper->TransactionType = 0;
1014 }
1015 if (json_object_object_get_ex(error_information, "operation", &obj)) {
1016 error_info_cper->Operation = readable_pair_to_integer(obj);
1017 add_to_valid_bitfield(&ui64Type, 1);
1018 } else {
1019 error_info_cper->Operation = 0;
1020 }
1021 if (json_object_object_get_ex(error_information, "level", &obj)) {
1022 error_info_cper->Level = json_object_get_uint64(obj);
1023 add_to_valid_bitfield(&ui64Type, 2);
1024 } else {
1025 error_info_cper->Level = 0;
1026 }
1027 if (json_object_object_get_ex(error_information,
1028 "processorContextCorrupt", &obj)) {
1029 error_info_cper->ProcessorContextCorrupt =
1030 json_object_get_boolean(obj);
1031 add_to_valid_bitfield(&ui64Type, 3);
1032 } else {
1033 error_info_cper->ProcessorContextCorrupt = 0;
1034 }
1035 if (json_object_object_get_ex(error_information, "corrected", &obj)) {
1036 error_info_cper->Corrected = json_object_get_boolean(obj);
1037 add_to_valid_bitfield(&ui64Type, 4);
1038 } else {
1039 error_info_cper->Corrected = 0;
1040 }
1041 if (json_object_object_get_ex(error_information, "precisePC", &obj)) {
1042 error_info_cper->PrecisePC = json_object_get_boolean(obj);
1043 add_to_valid_bitfield(&ui64Type, 5);
1044 } else {
1045 error_info_cper->PrecisePC = 0;
1046 }
1047 if (json_object_object_get_ex(error_information, "restartablePC",
1048 &obj)) {
1049 error_info_cper->RestartablePC = json_object_get_boolean(obj);
1050 add_to_valid_bitfield(&ui64Type, 6);
1051 } else {
1052 error_info_cper->RestartablePC = 0;
1053 }
1054 if (json_object_object_get_ex(error_information, "participationType",
1055 &obj)) {
1056 error_info_cper->ParticipationType =
1057 readable_pair_to_integer(obj);
1058 add_to_valid_bitfield(&ui64Type, 7);
1059 } else {
1060 error_info_cper->ParticipationType = 0;
1061 }
1062 if (json_object_object_get_ex(error_information, "timedOut", &obj)) {
1063 error_info_cper->TimeOut = json_object_get_boolean(obj);
1064 add_to_valid_bitfield(&ui64Type, 8);
1065 } else {
1066 error_info_cper->TimeOut = 0;
1067 }
1068 if (json_object_object_get_ex(error_information, "addressSpace",
1069 &obj)) {
1070 error_info_cper->AddressSpace = readable_pair_to_integer(obj);
1071 add_to_valid_bitfield(&ui64Type, 9);
1072 } else {
1073 error_info_cper->AddressSpace = 0;
1074 }
1075 if (json_object_object_get_ex(error_information, "accessMode", &obj)) {
1076 error_info_cper->AccessMode = readable_pair_to_integer(obj);
1077 add_to_valid_bitfield(&ui64Type, 11);
1078 } else {
1079 error_info_cper->AccessMode = 0;
1080 }
1081 if (json_object_object_get_ex(error_information, "memoryAttributes",
1082 &obj)) {
1083 error_info_cper->MemoryAddressAttributes =
1084 json_object_get_uint64(obj);
1085 add_to_valid_bitfield(&ui64Type, 10);
1086 } else {
1087 error_info_cper->MemoryAddressAttributes = 0;
1088 }
1089 error_info_cper->Reserved = 0;
1090 error_info_cper->ValidationBits = ui64Type.value.ui64;
1091 }
1092
1093 //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)1094 void ir_arm_context_info_to_cper(json_object *context_info, FILE *out)
1095 {
1096 EFI_ARM_CONTEXT_INFORMATION_HEADER info_header;
1097
1098 //Version, array size, context type.
1099 info_header.Version = json_object_get_int(
1100 json_object_object_get(context_info, "version"));
1101 info_header.RegisterArraySize = json_object_get_int(
1102 json_object_object_get(context_info, "registerArraySize"));
1103 info_header.RegisterContextType = readable_pair_to_integer(
1104 json_object_object_get(context_info, "registerContextType"));
1105
1106 //Flush to stream, write the register array itself.
1107 fwrite(&info_header, sizeof(EFI_ARM_CONTEXT_INFORMATION_HEADER), 1,
1108 out);
1109 fflush(out);
1110
1111 json_object *register_array =
1112 json_object_object_get(context_info, "registerArray");
1113 switch (info_header.RegisterContextType) {
1114 case EFI_ARM_CONTEXT_TYPE_AARCH32_GPR:
1115 ir_arm_aarch32_gpr_to_cper(register_array, out);
1116 break;
1117 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL1:
1118 ir_arm_aarch32_el1_to_cper(register_array, out);
1119 break;
1120 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL2:
1121 ir_arm_aarch32_el2_to_cper(register_array, out);
1122 break;
1123 case EFI_ARM_CONTEXT_TYPE_AARCH32_SECURE:
1124 ir_arm_aarch32_secure_to_cper(register_array, out);
1125 break;
1126 case EFI_ARM_CONTEXT_TYPE_AARCH64_GPR:
1127 ir_arm_aarch64_gpr_to_cper(register_array, out);
1128 break;
1129 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL1:
1130 ir_arm_aarch64_el1_to_cper(register_array, out);
1131 break;
1132 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL2:
1133 ir_arm_aarch64_el2_to_cper(register_array, out);
1134 break;
1135 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL3:
1136 ir_arm_aarch64_el3_to_cper(register_array, out);
1137 break;
1138 case EFI_ARM_CONTEXT_TYPE_MISC:
1139 ir_arm_misc_registers_to_cper(register_array, out);
1140 break;
1141 default:
1142 //Unknown register structure.
1143 ir_arm_unknown_register_to_cper(register_array, out);
1144 break;
1145 }
1146 }
1147
1148 //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)1149 void ir_arm_aarch32_gpr_to_cper(json_object *registers, FILE *out)
1150 {
1151 //Get uniform register array.
1152 EFI_ARM_V8_AARCH32_GPR reg_array;
1153 ir_to_uniform_struct(registers, (UINT32 *)®_array,
1154 sizeof(EFI_ARM_V8_AARCH32_GPR) / sizeof(UINT32),
1155 ARM_AARCH32_GPR_NAMES);
1156
1157 //Flush to stream.
1158 fwrite(®_array, sizeof(reg_array), 1, out);
1159 fflush(out);
1160 }
1161
1162 //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)1163 void ir_arm_aarch32_el1_to_cper(json_object *registers, FILE *out)
1164 {
1165 //Get uniform register array.
1166 EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS reg_array;
1167 ir_to_uniform_struct(registers, (UINT32 *)®_array,
1168 sizeof(EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS) /
1169 sizeof(UINT32),
1170 ARM_AARCH32_EL1_REGISTER_NAMES);
1171
1172 //Flush to stream.
1173 fwrite(®_array, sizeof(reg_array), 1, out);
1174 fflush(out);
1175 }
1176
1177 //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)1178 void ir_arm_aarch32_el2_to_cper(json_object *registers, FILE *out)
1179 {
1180 //Get uniform register array.
1181 EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS reg_array;
1182 ir_to_uniform_struct(registers, (UINT32 *)®_array,
1183 sizeof(EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS) /
1184 sizeof(UINT32),
1185 ARM_AARCH32_EL2_REGISTER_NAMES);
1186
1187 //Flush to stream.
1188 fwrite(®_array, sizeof(reg_array), 1, out);
1189 fflush(out);
1190 }
1191
1192 //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)1193 void ir_arm_aarch32_secure_to_cper(json_object *registers, FILE *out)
1194 {
1195 //Get uniform register array.
1196 EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS reg_array;
1197 ir_to_uniform_struct(registers, (UINT32 *)®_array,
1198 sizeof(EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS) /
1199 sizeof(UINT32),
1200 ARM_AARCH32_SECURE_REGISTER_NAMES);
1201
1202 //Flush to stream.
1203 fwrite(®_array, sizeof(reg_array), 1, out);
1204 fflush(out);
1205 }
1206
1207 //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)1208 void ir_arm_aarch64_gpr_to_cper(json_object *registers, FILE *out)
1209 {
1210 //Get uniform register array.
1211 EFI_ARM_V8_AARCH64_GPR reg_array;
1212 ir_to_uniform_struct64(registers, (UINT64 *)®_array,
1213 sizeof(EFI_ARM_V8_AARCH64_GPR) / sizeof(UINT64),
1214 ARM_AARCH64_GPR_NAMES);
1215
1216 //Flush to stream.
1217 fwrite(®_array, sizeof(reg_array), 1, out);
1218 fflush(out);
1219 }
1220
1221 //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)1222 void ir_arm_aarch64_el1_to_cper(json_object *registers, FILE *out)
1223 {
1224 //Get uniform register array.
1225 EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS reg_array;
1226 ir_to_uniform_struct64(registers, (UINT64 *)®_array,
1227 sizeof(EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS) /
1228 sizeof(UINT64),
1229 ARM_AARCH64_EL1_REGISTER_NAMES);
1230
1231 //Flush to stream.
1232 fwrite(®_array, sizeof(reg_array), 1, out);
1233 fflush(out);
1234 }
1235
1236 //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)1237 void ir_arm_aarch64_el2_to_cper(json_object *registers, FILE *out)
1238 {
1239 //Get uniform register array.
1240 EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS reg_array;
1241 ir_to_uniform_struct64(registers, (UINT64 *)®_array,
1242 sizeof(EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS) /
1243 sizeof(UINT64),
1244 ARM_AARCH64_EL2_REGISTER_NAMES);
1245
1246 //Flush to stream.
1247 fwrite(®_array, sizeof(reg_array), 1, out);
1248 fflush(out);
1249 }
1250
1251 //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)1252 void ir_arm_aarch64_el3_to_cper(json_object *registers, FILE *out)
1253 {
1254 //Get uniform register array.
1255 EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS reg_array;
1256 ir_to_uniform_struct64(registers, (UINT64 *)®_array,
1257 sizeof(EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS) /
1258 sizeof(UINT64),
1259 ARM_AARCH64_EL3_REGISTER_NAMES);
1260
1261 //Flush to stream.
1262 fwrite(®_array, sizeof(reg_array), 1, out);
1263 fflush(out);
1264 }
1265
1266 //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)1267 void ir_arm_misc_registers_to_cper(json_object *registers, FILE *out)
1268 {
1269 EFI_ARM_MISC_CONTEXT_REGISTER reg_array;
1270
1271 //MRS encoding information.
1272 json_object *mrs_encoding =
1273 json_object_object_get(registers, "mrsEncoding");
1274 reg_array.MrsOp2 = json_object_get_uint64(
1275 json_object_object_get(mrs_encoding, "op2"));
1276 reg_array.MrsCrm = json_object_get_uint64(
1277 json_object_object_get(mrs_encoding, "crm"));
1278 reg_array.MrsCrn = json_object_get_uint64(
1279 json_object_object_get(mrs_encoding, "crn"));
1280 reg_array.MrsOp1 = json_object_get_uint64(
1281 json_object_object_get(mrs_encoding, "op1"));
1282 reg_array.MrsO0 = json_object_get_uint64(
1283 json_object_object_get(mrs_encoding, "o0"));
1284
1285 //Actual register value.
1286 reg_array.Value = json_object_get_uint64(
1287 json_object_object_get(registers, "value"));
1288
1289 //Flush to stream.
1290 fwrite(®_array, sizeof(reg_array), 1, out);
1291 fflush(out);
1292 }
1293
1294 //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)1295 void ir_arm_unknown_register_to_cper(json_object *registers, FILE *out)
1296 {
1297 //Get base64 represented data.
1298 json_object *encoded = json_object_object_get(registers, "data");
1299
1300 int32_t decoded_len = 0;
1301
1302 UINT8 *decoded = base64_decode(json_object_get_string(encoded),
1303 json_object_get_string_len(encoded),
1304 &decoded_len);
1305
1306 if (decoded == NULL) {
1307 cper_print_log("Failed to allocate decode output buffer. \n");
1308 } else {
1309 //Flush out to stream.
1310 fwrite(&decoded, decoded_len, 1, out);
1311 fflush(out);
1312 free(decoded);
1313 }
1314 }
1315