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
16 //Private pre-definitions.
17 json_object *
18 cper_arm_error_info_to_ir(EFI_ARM_ERROR_INFORMATION_ENTRY *error_info);
19 json_object *
20 cper_arm_processor_context_to_ir(EFI_ARM_CONTEXT_INFORMATION_HEADER *header,
21 void **cur_pos);
22 json_object *
23 cper_arm_cache_tlb_error_to_ir(EFI_ARM_CACHE_ERROR_STRUCTURE *cache_tlb_error,
24 EFI_ARM_ERROR_INFORMATION_ENTRY *error_info);
25 json_object *cper_arm_bus_error_to_ir(EFI_ARM_BUS_ERROR_STRUCTURE *bus_error);
26 json_object *cper_arm_misc_register_array_to_ir(
27 EFI_ARM_MISC_CONTEXT_REGISTER *misc_register);
28 void ir_arm_error_info_to_cper(json_object *error_info, FILE *out);
29 void ir_arm_context_info_to_cper(json_object *context_info, FILE *out);
30 void ir_arm_error_cache_tlb_info_to_cper(
31 json_object *error_information,
32 EFI_ARM_CACHE_ERROR_STRUCTURE *error_info_cper);
33 void ir_arm_error_bus_info_to_cper(json_object *error_information,
34 EFI_ARM_BUS_ERROR_STRUCTURE *error_info_cper);
35 void ir_arm_aarch32_gpr_to_cper(json_object *registers, FILE *out);
36 void ir_arm_aarch32_el1_to_cper(json_object *registers, FILE *out);
37 void ir_arm_aarch32_el2_to_cper(json_object *registers, FILE *out);
38 void ir_arm_aarch32_secure_to_cper(json_object *registers, FILE *out);
39 void ir_arm_aarch64_gpr_to_cper(json_object *registers, FILE *out);
40 void ir_arm_aarch64_el1_to_cper(json_object *registers, FILE *out);
41 void ir_arm_aarch64_el2_to_cper(json_object *registers, FILE *out);
42 void ir_arm_aarch64_el3_to_cper(json_object *registers, FILE *out);
43 void ir_arm_misc_registers_to_cper(json_object *registers, FILE *out);
44 void ir_arm_unknown_register_to_cper(json_object *registers, FILE *out);
45
46 //Converts the given processor-generic CPER section into JSON IR.
cper_section_arm_to_ir(void * section)47 json_object *cper_section_arm_to_ir(void *section)
48 {
49 EFI_ARM_ERROR_RECORD *record = (EFI_ARM_ERROR_RECORD *)section;
50 json_object *section_ir = json_object_new_object();
51
52 //Length of ValidationBits from spec
53 ValidationTypes ui64Type = { UINT_64T,
54 .value.ui64 = record->ValidFields };
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 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 }
78
79 //Processor ID (MPIDR_EL1) and chip ID (MIDR_EL1).
80 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 }
91
92 json_object_object_add(section_ir, "midrEl1",
93 json_object_new_uint64(record->MIDR_EL1));
94
95 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 }
101 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 }
109
110 //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);
120
121 //Processor context structures.
122 //The current position is moved within the processing, as it is a dynamic size structure.
123 uint8_t *cur_pos = (uint8_t *)cur_error;
124 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 =
129 cper_arm_processor_context_to_ir(header,
130 (void **)&cur_pos);
131 json_object_array_add(context_info_array, processor_context);
132 }
133 json_object_object_add(section_ir, "contextInfo", context_info_array);
134
135 //Is there any vendor-specific information following?
136 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);
152
153 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 }
158 }
159
160 return section_ir;
161 }
162
163 //Converts a single ARM Process Error Information structure into JSON IR.
164 json_object *
cper_arm_error_info_to_ir(EFI_ARM_ERROR_INFORMATION_ENTRY * error_info)165 cper_arm_error_info_to_ir(EFI_ARM_ERROR_INFORMATION_ENTRY *error_info)
166 {
167 json_object *error_info_ir = json_object_new_object();
168
169 //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));
174
175 //Validation bitfield.
176 ValidationTypes ui16Type = { UINT_16T,
177 .value.ui16 = error_info->ValidationBits };
178
179 //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);
184
185 //Multiple error count.
186 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 }
199
200 //Flags.
201 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 }
206
207 //Error information, split by type.
208 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;
223
224 default:
225 //Unknown/microarch, will not support.
226 break;
227 }
228 json_object_object_add(error_info_ir, "errorInformation",
229 error_subinfo);
230 }
231
232 //Virtual fault address, physical fault address.
233 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 }
245
246 return error_info_ir;
247 }
248
249 //Converts a single ARM cache/TLB error information structure into JSON IR format.
250 json_object *
cper_arm_cache_tlb_error_to_ir(EFI_ARM_CACHE_ERROR_STRUCTURE * cache_tlb_error,EFI_ARM_ERROR_INFORMATION_ENTRY * error_info)251 cper_arm_cache_tlb_error_to_ir(EFI_ARM_CACHE_ERROR_STRUCTURE *cache_tlb_error,
252 EFI_ARM_ERROR_INFORMATION_ENTRY *error_info)
253 {
254 json_object *cache_tlb_error_ir = json_object_new_object();
255 json_object *cache_tlb_prop = json_object_new_object();
256 char *cache_tlb_propname;
257
258 //Validation bitfield.
259 ValidationTypes ui64Type = {
260 UINT_64T, .value.ui64 = cache_tlb_error->ValidationBits
261 };
262
263 //Transaction type.
264 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 }
273
274 //Operation.
275 bool cacheErrorFlag = 1;
276 if (error_info->Type == 0) {
277 cache_tlb_propname = "cacheError";
278 } else {
279 //TLB operation.
280 cache_tlb_propname = "tlbError";
281 cacheErrorFlag = 0;
282 }
283
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 }
304
305 //Miscellaneous remaining fields.
306 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 }
332
333 json_object_object_add(cache_tlb_prop, cache_tlb_propname,
334 cache_tlb_error_ir);
335
336 return cache_tlb_prop;
337 }
338
339 //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)340 json_object *cper_arm_bus_error_to_ir(EFI_ARM_BUS_ERROR_STRUCTURE *bus_error)
341 {
342 json_object *bus_error_ir = json_object_new_object();
343 json_object *bus_prop = json_object_new_object();
344 char *bus_propname = "busError";
345
346 //Validation bits.
347 ValidationTypes ui64Type = { UINT_64T,
348 .value.ui64 = bus_error->ValidationBits };
349
350 //Transaction type.
351 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 }
360
361 //Operation.
362 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 }
370
371 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 }
397
398 //Participation type.
399 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 }
412
413 //Address space.
414 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 }
422
423 //Memory access attributes.
424 //todo: find the specification of these in the ARM ARM
425 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 }
431
432 //Access Mode
433 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);
446
447 return bus_prop;
448 }
449
450 //Converts a single ARM processor context block into JSON IR.
451 json_object *
cper_arm_processor_context_to_ir(EFI_ARM_CONTEXT_INFORMATION_HEADER * header,void ** cur_pos)452 cper_arm_processor_context_to_ir(EFI_ARM_CONTEXT_INFORMATION_HEADER *header,
453 void **cur_pos)
454 {
455 json_object *context_ir = json_object_new_object();
456
457 //Version.
458 json_object_object_add(context_ir, "version",
459 json_object_new_int(header->Version));
460
461 //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);
468
469 //Register array size (bytes).
470 json_object_object_add(
471 context_ir, "registerArraySize",
472 json_object_new_uint64(header->RegisterArraySize));
473
474 //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(
480 (UINT32 *)*cur_pos,
481 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(
486 (UINT32 *)*cur_pos,
487 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(
493 (UINT32 *)*cur_pos,
494 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(
500 (UINT32 *)*cur_pos,
501 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(
507 (UINT64 *)*cur_pos,
508 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(
513 (UINT64 *)*cur_pos,
514 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(
520 (UINT64 *)*cur_pos,
521 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(
527 (UINT64 *)*cur_pos,
528 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(
534 (EFI_ARM_MISC_CONTEXT_REGISTER *)*cur_pos);
535 break;
536 default:
537 //Unknown register array type, add as base64 data instead.
538 register_array = json_object_new_object();
539 int32_t encoded_len = 0;
540 char *encoded = base64_encode((UINT8 *)*cur_pos,
541 header->RegisterArraySize,
542 &encoded_len);
543 if (encoded == NULL) {
544 printf("Failed to allocate encode output buffer. \n");
545 return NULL;
546 }
547 json_object_object_add(register_array, "data",
548 json_object_new_string_len(encoded,
549 encoded_len));
550 free(encoded);
551
552 break;
553 }
554 json_object_object_add(context_ir, "registerArray", register_array);
555
556 //Set the current position to after the processor context structure.
557 *cur_pos = (UINT8 *)(*cur_pos) + header->RegisterArraySize;
558
559 return context_ir;
560 }
561
562 //Converts a single CPER ARM miscellaneous register array to JSON IR format.
563 json_object *
cper_arm_misc_register_array_to_ir(EFI_ARM_MISC_CONTEXT_REGISTER * misc_register)564 cper_arm_misc_register_array_to_ir(EFI_ARM_MISC_CONTEXT_REGISTER *misc_register)
565 {
566 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));
581
582 return register_array;
583 }
584
585 //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)586 void ir_section_arm_to_cper(json_object *section, FILE *out)
587 {
588 EFI_ARM_ERROR_RECORD section_cper;
589 memset(§ion_cper, 0, sizeof(section_cper));
590
591 //Validation bits.
592 struct json_object *obj = NULL;
593 ValidationTypes u32Type = { UINT_32T, .value.ui32 = 0 };
594
595 //Count of error/context info structures.
596 section_cper.ErrInfoNum = json_object_get_int(
597 json_object_object_get(section, "errorInfoNum"));
598 section_cper.ContextInfoNum = json_object_get_int(
599 json_object_object_get(section, "contextInfoNum"));
600
601 //Miscellaneous raw value fields.
602 section_cper.SectionLength = json_object_get_uint64(
603 json_object_object_get(section, "sectionLength"));
604 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(
613 json_object_object_get(section, "midrEl1"));
614 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 }
618
619 //Optional PSCI state.
620 json_object *psci_state = json_object_object_get(section, "psciState");
621 if (psci_state != NULL) {
622 section_cper.PsciState = json_object_get_uint64(psci_state);
623 }
624
625 //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
635 //Flush header to stream.
636 fwrite(§ion_cper, sizeof(section_cper), 1, out);
637
638 //Error info structure array.
639
640 json_object *error_info = json_object_object_get(section, "errorInfo");
641 for (int i = 0; i < section_cper.ErrInfoNum; i++) {
642 ir_arm_error_info_to_cper(
643 json_object_array_get_idx(error_info, i), out);
644 }
645
646 //Context info structure array.
647 json_object *context_info =
648 json_object_object_get(section, "contextInfo");
649 for (int i = 0; i < section_cper.ContextInfoNum; i++) {
650 ir_arm_context_info_to_cper(
651 json_object_array_get_idx(context_info, i), out);
652 }
653
654 //Vendor specific error info.
655 if (vendorSpecificPresent) {
656 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);
660
661 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);
669 free(decoded);
670 }
671
672 fflush(out);
673 }
674
675 //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)676 void ir_arm_error_info_to_cper(json_object *error_info, FILE *out)
677 {
678 EFI_ARM_ERROR_INFORMATION_ENTRY error_info_cper;
679 memset(&error_info_cper, 0, sizeof(error_info_cper));
680 struct json_object *obj = NULL;
681 ValidationTypes ui16Type = { UINT_16T, .value.ui16 = 0 };
682
683 //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"));
688
689 //Type, multiple error.
690 error_info_cper.Type = (UINT8)readable_pair_to_integer(
691 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 }
700
701 //Flags object.
702 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 }
709
710 //Error information.
711 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;
731
732 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;
740
741 default:
742 //Unknown error information type.
743 break;
744 }
745 add_to_valid_bitfield(&ui16Type, 2);
746 }
747
748 //Virtual/physical fault address.
749 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;
767
768 //Write out to stream.
769 fwrite(&error_info_cper, sizeof(EFI_ARM_ERROR_INFORMATION_ENTRY), 1,
770 out);
771 }
772
773 //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)774 void ir_arm_error_cache_tlb_info_to_cper(
775 json_object *error_information,
776 EFI_ARM_CACHE_ERROR_STRUCTURE *error_info_cper)
777 {
778 // //Validation bits.
779 ValidationTypes ui64Type = { UINT_64T, .value.ui64 = 0 };
780 struct json_object *obj = NULL;
781
782 //Miscellaneous value fields.
783 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 }
816 error_info_cper->Reserved = 0;
817 error_info_cper->ValidationBits = ui64Type.value.ui64;
818 }
819
820 //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)821 void ir_arm_error_bus_info_to_cper(json_object *error_information,
822 EFI_ARM_BUS_ERROR_STRUCTURE *error_info_cper)
823 {
824 //Validation bits.
825 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));
829
830 //Miscellaneous value fields.
831 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 }
913 error_info_cper->Reserved = 0;
914 error_info_cper->ValidationBits = ui64Type.value.ui64;
915 }
916
917 //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)918 void ir_arm_context_info_to_cper(json_object *context_info, FILE *out)
919 {
920 EFI_ARM_CONTEXT_INFORMATION_HEADER info_header;
921
922 //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"));
929
930 //Flush to stream, write the register array itself.
931 fwrite(&info_header, sizeof(EFI_ARM_CONTEXT_INFORMATION_HEADER), 1,
932 out);
933 fflush(out);
934
935 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.
967 ir_arm_unknown_register_to_cper(register_array, out);
968 break;
969 }
970 }
971
972 //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)973 void ir_arm_aarch32_gpr_to_cper(json_object *registers, FILE *out)
974 {
975 //Get uniform register array.
976 EFI_ARM_V8_AARCH32_GPR reg_array;
977 ir_to_uniform_struct(registers, (UINT32 *)®_array,
978 sizeof(EFI_ARM_V8_AARCH32_GPR) / sizeof(UINT32),
979 ARM_AARCH32_GPR_NAMES);
980
981 //Flush to stream.
982 fwrite(®_array, sizeof(reg_array), 1, out);
983 fflush(out);
984 }
985
986 //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)987 void ir_arm_aarch32_el1_to_cper(json_object *registers, FILE *out)
988 {
989 //Get uniform register array.
990 EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS reg_array;
991 ir_to_uniform_struct(registers, (UINT32 *)®_array,
992 sizeof(EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS) /
993 sizeof(UINT32),
994 ARM_AARCH32_EL1_REGISTER_NAMES);
995
996 //Flush to stream.
997 fwrite(®_array, sizeof(reg_array), 1, out);
998 fflush(out);
999 }
1000
1001 //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)1002 void ir_arm_aarch32_el2_to_cper(json_object *registers, FILE *out)
1003 {
1004 //Get uniform register array.
1005 EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS reg_array;
1006 ir_to_uniform_struct(registers, (UINT32 *)®_array,
1007 sizeof(EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS) /
1008 sizeof(UINT32),
1009 ARM_AARCH32_EL2_REGISTER_NAMES);
1010
1011 //Flush to stream.
1012 fwrite(®_array, sizeof(reg_array), 1, out);
1013 fflush(out);
1014 }
1015
1016 //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)1017 void ir_arm_aarch32_secure_to_cper(json_object *registers, FILE *out)
1018 {
1019 //Get uniform register array.
1020 EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS reg_array;
1021 ir_to_uniform_struct(registers, (UINT32 *)®_array,
1022 sizeof(EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS) /
1023 sizeof(UINT32),
1024 ARM_AARCH32_SECURE_REGISTER_NAMES);
1025
1026 //Flush to stream.
1027 fwrite(®_array, sizeof(reg_array), 1, out);
1028 fflush(out);
1029 }
1030
1031 //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)1032 void ir_arm_aarch64_gpr_to_cper(json_object *registers, FILE *out)
1033 {
1034 //Get uniform register array.
1035 EFI_ARM_V8_AARCH64_GPR reg_array;
1036 ir_to_uniform_struct64(registers, (UINT64 *)®_array,
1037 sizeof(EFI_ARM_V8_AARCH64_GPR) / sizeof(UINT64),
1038 ARM_AARCH64_GPR_NAMES);
1039
1040 //Flush to stream.
1041 fwrite(®_array, sizeof(reg_array), 1, out);
1042 fflush(out);
1043 }
1044
1045 //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)1046 void ir_arm_aarch64_el1_to_cper(json_object *registers, FILE *out)
1047 {
1048 //Get uniform register array.
1049 EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS reg_array;
1050 ir_to_uniform_struct64(registers, (UINT64 *)®_array,
1051 sizeof(EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS) /
1052 sizeof(UINT64),
1053 ARM_AARCH64_EL1_REGISTER_NAMES);
1054
1055 //Flush to stream.
1056 fwrite(®_array, sizeof(reg_array), 1, out);
1057 fflush(out);
1058 }
1059
1060 //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)1061 void ir_arm_aarch64_el2_to_cper(json_object *registers, FILE *out)
1062 {
1063 //Get uniform register array.
1064 EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS reg_array;
1065 ir_to_uniform_struct64(registers, (UINT64 *)®_array,
1066 sizeof(EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS) /
1067 sizeof(UINT64),
1068 ARM_AARCH64_EL2_REGISTER_NAMES);
1069
1070 //Flush to stream.
1071 fwrite(®_array, sizeof(reg_array), 1, out);
1072 fflush(out);
1073 }
1074
1075 //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)1076 void ir_arm_aarch64_el3_to_cper(json_object *registers, FILE *out)
1077 {
1078 //Get uniform register array.
1079 EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS reg_array;
1080 ir_to_uniform_struct64(registers, (UINT64 *)®_array,
1081 sizeof(EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS) /
1082 sizeof(UINT64),
1083 ARM_AARCH64_EL3_REGISTER_NAMES);
1084
1085 //Flush to stream.
1086 fwrite(®_array, sizeof(reg_array), 1, out);
1087 fflush(out);
1088 }
1089
1090 //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)1091 void ir_arm_misc_registers_to_cper(json_object *registers, FILE *out)
1092 {
1093 EFI_ARM_MISC_CONTEXT_REGISTER reg_array;
1094
1095 //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"));
1108
1109 //Actual register value.
1110 reg_array.Value = json_object_get_uint64(
1111 json_object_object_get(registers, "value"));
1112
1113 //Flush to stream.
1114 fwrite(®_array, sizeof(reg_array), 1, out);
1115 fflush(out);
1116 }
1117
1118 //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)1119 void ir_arm_unknown_register_to_cper(json_object *registers, FILE *out)
1120 {
1121 //Get base64 represented data.
1122 json_object *encoded = json_object_object_get(registers, "data");
1123
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) {
1131 printf("Failed to allocate decode output buffer. \n");
1132 } else {
1133 //Flush out to stream.
1134 fwrite(&decoded, decoded_len, 1, out);
1135 fflush(out);
1136 free(decoded);
1137 }
1138 }
1139