blob: 6537f404a6aa044e50bf976afe9b842134d82267 [file] [log] [blame]
Lawrence Tang2800cd82022-07-05 16:08:20 +01001/**
2 * Describes functions for converting ARM CPER sections from binary and JSON format
3 * into an intermediate format.
4 *
5 * Author: Lawrence.Tang@arm.com
6 **/
7
8#include <stdio.h>
Lawrence Tang5202bbb2022-08-12 14:54:36 +01009#include <json.h>
Lawrence Tangd7e8ca32022-07-07 10:25:53 +010010#include "b64.h"
Lawrence Tang2800cd82022-07-05 16:08:20 +010011#include "../edk/Cper.h"
12#include "../cper-utils.h"
13#include "cper-section-arm.h"
14
Lawrence Tang3d0e4f22022-07-05 17:17:41 +010015//Private pre-definitions.
Lawrence Tange407b4c2022-07-21 13:54:01 +010016json_object *
17cper_arm_error_info_to_ir(EFI_ARM_ERROR_INFORMATION_ENTRY *error_info);
18json_object *
19cper_arm_processor_context_to_ir(EFI_ARM_CONTEXT_INFORMATION_HEADER *header,
20 void **cur_pos);
21json_object *
22cper_arm_cache_tlb_error_to_ir(EFI_ARM_CACHE_ERROR_STRUCTURE *cache_tlb_error,
23 EFI_ARM_ERROR_INFORMATION_ENTRY *error_info);
24json_object *cper_arm_bus_error_to_ir(EFI_ARM_BUS_ERROR_STRUCTURE *bus_error);
25json_object *cper_arm_misc_register_array_to_ir(
26 EFI_ARM_MISC_CONTEXT_REGISTER *misc_register);
27void ir_arm_error_info_to_cper(json_object *error_info, FILE *out);
28void ir_arm_context_info_to_cper(json_object *context_info, FILE *out);
29void ir_arm_error_cache_tlb_info_to_cper(
30 json_object *error_information,
31 EFI_ARM_CACHE_ERROR_STRUCTURE *error_info_cper);
32void ir_arm_error_bus_info_to_cper(json_object *error_information,
33 EFI_ARM_BUS_ERROR_STRUCTURE *error_info_cper);
34void ir_arm_aarch32_gpr_to_cper(json_object *registers, FILE *out);
35void ir_arm_aarch32_el1_to_cper(json_object *registers, FILE *out);
36void ir_arm_aarch32_el2_to_cper(json_object *registers, FILE *out);
37void ir_arm_aarch32_secure_to_cper(json_object *registers, FILE *out);
38void ir_arm_aarch64_gpr_to_cper(json_object *registers, FILE *out);
39void ir_arm_aarch64_el1_to_cper(json_object *registers, FILE *out);
40void ir_arm_aarch64_el2_to_cper(json_object *registers, FILE *out);
41void ir_arm_aarch64_el3_to_cper(json_object *registers, FILE *out);
42void ir_arm_misc_registers_to_cper(json_object *registers, FILE *out);
43void ir_arm_unknown_register_to_cper(json_object *registers,
44 EFI_ARM_CONTEXT_INFORMATION_HEADER *header,
45 FILE *out);
Lawrence Tang3d0e4f22022-07-05 17:17:41 +010046
Lawrence Tang2800cd82022-07-05 16:08:20 +010047//Converts the given processor-generic CPER section into JSON IR.
Lawrence Tange407b4c2022-07-21 13:54:01 +010048json_object *cper_section_arm_to_ir(void *section,
49 EFI_ERROR_SECTION_DESCRIPTOR *descriptor)
Lawrence Tang2800cd82022-07-05 16:08:20 +010050{
Lawrence Tange407b4c2022-07-21 13:54:01 +010051 EFI_ARM_ERROR_RECORD *record = (EFI_ARM_ERROR_RECORD *)section;
52 json_object *section_ir = json_object_new_object();
Lawrence Tang2800cd82022-07-05 16:08:20 +010053
Lawrence Tange407b4c2022-07-21 13:54:01 +010054 //Validation bits.
55 json_object *validation = bitfield_to_ir(
56 record->ValidFields, 4, ARM_ERROR_VALID_BITFIELD_NAMES);
57 json_object_object_add(section_ir, "validationBits", validation);
Lawrence Tang2800cd82022-07-05 16:08:20 +010058
Lawrence Tange407b4c2022-07-21 13:54:01 +010059 //Number of error info and context info structures, and length.
60 json_object_object_add(section_ir, "errorInfoNum",
61 json_object_new_int(record->ErrInfoNum));
62 json_object_object_add(section_ir, "contextInfoNum",
63 json_object_new_int(record->ContextInfoNum));
64 json_object_object_add(section_ir, "sectionLength",
65 json_object_new_uint64(record->SectionLength));
Lawrence Tang2800cd82022-07-05 16:08:20 +010066
Lawrence Tange407b4c2022-07-21 13:54:01 +010067 //Error affinity.
68 json_object *error_affinity = json_object_new_object();
69 json_object_object_add(error_affinity, "value",
70 json_object_new_int(record->ErrorAffinityLevel));
71 json_object_object_add(
72 error_affinity, "type",
73 json_object_new_string(record->ErrorAffinityLevel < 4 ?
74 "Vendor Defined" :
75 "Reserved"));
76 json_object_object_add(section_ir, "errorAffinity", error_affinity);
Lawrence Tang2800cd82022-07-05 16:08:20 +010077
Lawrence Tange407b4c2022-07-21 13:54:01 +010078 //Processor ID (MPIDR_EL1) and chip ID (MIDR_EL1).
79 json_object_object_add(section_ir, "mpidrEl1",
80 json_object_new_uint64(record->MPIDR_EL1));
81 json_object_object_add(section_ir, "midrEl1",
82 json_object_new_uint64(record->MIDR_EL1));
Lawrence Tang2800cd82022-07-05 16:08:20 +010083
Lawrence Tange407b4c2022-07-21 13:54:01 +010084 //Whether the processor is running, and the state of it if so.
85 json_object_object_add(section_ir, "running",
86 json_object_new_boolean(record->RunningState &
87 0b1));
88 if (!(record->RunningState >> 31)) {
89 //Bit 32 of running state is on, so PSCI state information is included.
90 //This can't be made human readable, as it is unknown whether this will be the pre-PSCI 1.0 format
91 //or the newer Extended StateID format.
92 json_object_object_add(
93 section_ir, "psciState",
94 json_object_new_uint64(record->PsciState));
95 }
Lawrence Tang7f21db62022-07-06 11:09:39 +010096
Lawrence Tange407b4c2022-07-21 13:54:01 +010097 //Processor error structures.
98 json_object *error_info_array = json_object_new_array();
99 EFI_ARM_ERROR_INFORMATION_ENTRY *cur_error =
100 (EFI_ARM_ERROR_INFORMATION_ENTRY *)(record + 1);
101 for (int i = 0; i < record->ErrInfoNum; i++) {
102 json_object_array_add(error_info_array,
103 cper_arm_error_info_to_ir(cur_error));
104 cur_error++;
105 }
106 json_object_object_add(section_ir, "errorInfo", error_info_array);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100107
Lawrence Tange407b4c2022-07-21 13:54:01 +0100108 //Processor context structures.
109 //The current position is moved within the processing, as it is a dynamic size structure.
110 void *cur_pos = (void *)cur_error;
111 json_object *context_info_array = json_object_new_array();
112 for (int i = 0; i < record->ContextInfoNum; i++) {
113 EFI_ARM_CONTEXT_INFORMATION_HEADER *header =
114 (EFI_ARM_CONTEXT_INFORMATION_HEADER *)cur_pos;
115 json_object *processor_context =
116 cper_arm_processor_context_to_ir(header, &cur_pos);
117 json_object_array_add(context_info_array, processor_context);
118 }
119 json_object_object_add(section_ir, "contextInfo", context_info_array);
Lawrence Tangd7e8ca32022-07-07 10:25:53 +0100120
Lawrence Tange407b4c2022-07-21 13:54:01 +0100121 //Is there any vendor-specific information following?
122 if (cur_pos < section + record->SectionLength) {
123 json_object *vendor_specific = json_object_new_object();
124 char *encoded =
125 b64_encode((unsigned char *)cur_pos,
126 section + record->SectionLength - cur_pos);
127 json_object_object_add(vendor_specific, "data",
128 json_object_new_string(encoded));
129 free(encoded);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100130
Lawrence Tange407b4c2022-07-21 13:54:01 +0100131 json_object_object_add(section_ir, "vendorSpecificInfo",
132 vendor_specific);
133 }
134
135 return section_ir;
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100136}
137
138//Converts a single ARM Process Error Information structure into JSON IR.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100139json_object *
140cper_arm_error_info_to_ir(EFI_ARM_ERROR_INFORMATION_ENTRY *error_info)
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100141{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100142 json_object *error_info_ir = json_object_new_object();
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100143
Lawrence Tange407b4c2022-07-21 13:54:01 +0100144 //Version, length.
145 json_object_object_add(error_info_ir, "version",
146 json_object_new_int(error_info->Version));
147 json_object_object_add(error_info_ir, "length",
148 json_object_new_int(error_info->Length));
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100149
Lawrence Tange407b4c2022-07-21 13:54:01 +0100150 //Validation bitfield.
151 json_object *validation =
152 bitfield_to_ir(error_info->ValidationBits, 5,
153 ARM_ERROR_INFO_ENTRY_VALID_BITFIELD_NAMES);
154 json_object_object_add(error_info_ir, "validationBits", validation);
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100155
Lawrence Tange407b4c2022-07-21 13:54:01 +0100156 //The type of error information in this log.
157 json_object *error_type = integer_to_readable_pair(
158 error_info->Type, 4, ARM_ERROR_INFO_ENTRY_INFO_TYPES_KEYS,
159 ARM_ERROR_INFO_ENTRY_INFO_TYPES_VALUES, "Unknown (Reserved)");
160 json_object_object_add(error_info_ir, "errorType", error_type);
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100161
Lawrence Tange407b4c2022-07-21 13:54:01 +0100162 //Multiple error count.
163 json_object *multiple_error = json_object_new_object();
164 json_object_object_add(multiple_error, "value",
165 json_object_new_int(error_info->MultipleError));
166 json_object_object_add(
167 multiple_error, "type",
168 json_object_new_string(error_info->MultipleError < 1 ?
169 "Single Error" :
170 "Multiple Errors"));
171 json_object_object_add(error_info_ir, "multipleError", multiple_error);
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100172
Lawrence Tange407b4c2022-07-21 13:54:01 +0100173 //Flags.
174 json_object *flags = bitfield_to_ir(error_info->Flags, 4,
175 ARM_ERROR_INFO_ENTRY_FLAGS_NAMES);
176 json_object_object_add(error_info_ir, "flags", flags);
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100177
Lawrence Tange407b4c2022-07-21 13:54:01 +0100178 //Error information, split by type.
179 json_object *error_subinfo = NULL;
180 switch (error_info->Type) {
181 case ARM_ERROR_INFORMATION_TYPE_CACHE: //Cache
182 case ARM_ERROR_INFORMATION_TYPE_TLB: //TLB
183 error_subinfo = cper_arm_cache_tlb_error_to_ir(
184 (EFI_ARM_CACHE_ERROR_STRUCTURE *)&error_info
185 ->ErrorInformation,
186 error_info);
187 break;
188 case ARM_ERROR_INFORMATION_TYPE_BUS: //Bus
189 error_subinfo = cper_arm_bus_error_to_ir(
190 (EFI_ARM_BUS_ERROR_STRUCTURE *)&error_info
191 ->ErrorInformation);
192 break;
Lawrence Tang71570a22022-07-14 11:45:28 +0100193
Lawrence Tange407b4c2022-07-21 13:54:01 +0100194 default:
195 //Unknown/microarch, so can't be made readable. Simply dump as a uint64 data object.
196 error_subinfo = json_object_new_object();
197 json_object_object_add(
198 error_subinfo, "data",
199 json_object_new_uint64(
200 *((UINT64 *)&error_info->ErrorInformation)));
201 break;
202 }
203 json_object_object_add(error_info_ir, "errorInformation",
204 error_subinfo);
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100205
Lawrence Tange407b4c2022-07-21 13:54:01 +0100206 //Virtual fault address, physical fault address.
207 json_object_object_add(
208 error_info_ir, "virtualFaultAddress",
209 json_object_new_uint64(error_info->VirtualFaultAddress));
210 json_object_object_add(
211 error_info_ir, "physicalFaultAddress",
212 json_object_new_uint64(error_info->PhysicalFaultAddress));
213
214 return error_info_ir;
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100215}
216
Lawrence Tang7f21db62022-07-06 11:09:39 +0100217//Converts a single ARM cache/TLB error information structure into JSON IR format.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100218json_object *
219cper_arm_cache_tlb_error_to_ir(EFI_ARM_CACHE_ERROR_STRUCTURE *cache_tlb_error,
220 EFI_ARM_ERROR_INFORMATION_ENTRY *error_info)
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100221{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100222 json_object *cache_tlb_error_ir = json_object_new_object();
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100223
Lawrence Tange407b4c2022-07-21 13:54:01 +0100224 //Validation bitfield.
225 json_object *validation =
226 bitfield_to_ir(cache_tlb_error->ValidationBits, 7,
227 ARM_CACHE_TLB_ERROR_VALID_BITFIELD_NAMES);
228 json_object_object_add(cache_tlb_error_ir, "validationBits",
229 validation);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100230
Lawrence Tange407b4c2022-07-21 13:54:01 +0100231 //Transaction type.
232 json_object *transaction_type = integer_to_readable_pair(
233 cache_tlb_error->TransactionType, 3,
234 ARM_ERROR_TRANSACTION_TYPES_KEYS,
235 ARM_ERROR_TRANSACTION_TYPES_VALUES, "Unknown (Reserved)");
236 json_object_object_add(cache_tlb_error_ir, "transactionType",
237 transaction_type);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100238
Lawrence Tange407b4c2022-07-21 13:54:01 +0100239 //Operation.
240 json_object *operation;
241 if (error_info->Type == 0) {
242 //Cache operation.
243 operation = integer_to_readable_pair(
244 cache_tlb_error->Operation, 11,
245 ARM_CACHE_BUS_OPERATION_TYPES_KEYS,
246 ARM_CACHE_BUS_OPERATION_TYPES_VALUES,
247 "Unknown (Reserved)");
248 } else {
249 //TLB operation.
250 operation = integer_to_readable_pair(
251 cache_tlb_error->Operation, 9,
252 ARM_TLB_OPERATION_TYPES_KEYS,
253 ARM_TLB_OPERATION_TYPES_VALUES, "Unknown (Reserved)");
254 }
255 json_object_object_add(cache_tlb_error_ir, "operation", operation);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100256
Lawrence Tange407b4c2022-07-21 13:54:01 +0100257 //Miscellaneous remaining fields.
258 json_object_object_add(cache_tlb_error_ir, "level",
259 json_object_new_int(cache_tlb_error->Level));
260 json_object_object_add(
261 cache_tlb_error_ir, "processorContextCorrupt",
262 json_object_new_boolean(
263 cache_tlb_error->ProcessorContextCorrupt));
264 json_object_object_add(
265 cache_tlb_error_ir, "corrected",
266 json_object_new_boolean(cache_tlb_error->Corrected));
267 json_object_object_add(
268 cache_tlb_error_ir, "precisePC",
269 json_object_new_boolean(cache_tlb_error->PrecisePC));
270 json_object_object_add(
271 cache_tlb_error_ir, "restartablePC",
272 json_object_new_boolean(cache_tlb_error->RestartablePC));
273 return cache_tlb_error_ir;
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100274}
275
276//Converts a single ARM bus error information structure into JSON IR format.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100277json_object *cper_arm_bus_error_to_ir(EFI_ARM_BUS_ERROR_STRUCTURE *bus_error)
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100278{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100279 json_object *bus_error_ir = json_object_new_object();
Lawrence Tang7f21db62022-07-06 11:09:39 +0100280
Lawrence Tange407b4c2022-07-21 13:54:01 +0100281 //Validation bits.
282 json_object *validation =
283 bitfield_to_ir(bus_error->ValidationBits, 12,
284 ARM_BUS_ERROR_VALID_BITFIELD_NAMES);
285 json_object_object_add(bus_error_ir, "validationBits", validation);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100286
Lawrence Tange407b4c2022-07-21 13:54:01 +0100287 //Transaction type.
288 json_object *transaction_type = integer_to_readable_pair(
289 bus_error->TransactionType, 3, ARM_ERROR_TRANSACTION_TYPES_KEYS,
290 ARM_ERROR_TRANSACTION_TYPES_VALUES, "Unknown (Reserved)");
291 json_object_object_add(bus_error_ir, "transactionType",
292 transaction_type);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100293
Lawrence Tange407b4c2022-07-21 13:54:01 +0100294 //Operation.
295 json_object *operation = integer_to_readable_pair(
296 bus_error->Operation, 7, ARM_CACHE_BUS_OPERATION_TYPES_KEYS,
297 ARM_CACHE_BUS_OPERATION_TYPES_VALUES, "Unknown (Reserved)");
298 json_object_object_add(bus_error_ir, "operation", operation);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100299
Lawrence Tange407b4c2022-07-21 13:54:01 +0100300 //Affinity level of bus error, + miscellaneous fields.
301 json_object_object_add(bus_error_ir, "level",
302 json_object_new_int(bus_error->Level));
303 json_object_object_add(
304 bus_error_ir, "processorContextCorrupt",
305 json_object_new_boolean(bus_error->ProcessorContextCorrupt));
306 json_object_object_add(bus_error_ir, "corrected",
307 json_object_new_boolean(bus_error->Corrected));
308 json_object_object_add(bus_error_ir, "precisePC",
309 json_object_new_boolean(bus_error->PrecisePC));
310 json_object_object_add(
311 bus_error_ir, "restartablePC",
312 json_object_new_boolean(bus_error->RestartablePC));
313 json_object_object_add(bus_error_ir, "timedOut",
314 json_object_new_boolean(bus_error->TimeOut));
Lawrence Tang7f21db62022-07-06 11:09:39 +0100315
Lawrence Tange407b4c2022-07-21 13:54:01 +0100316 //Participation type.
317 json_object *participation_type = integer_to_readable_pair(
318 bus_error->ParticipationType, 4,
319 ARM_BUS_PARTICIPATION_TYPES_KEYS,
320 ARM_BUS_PARTICIPATION_TYPES_VALUES, "Unknown");
321 json_object_object_add(bus_error_ir, "participationType",
322 participation_type);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100323
Lawrence Tange407b4c2022-07-21 13:54:01 +0100324 //Address space.
325 json_object *address_space = integer_to_readable_pair(
326 bus_error->AddressSpace, 3, ARM_BUS_ADDRESS_SPACE_TYPES_KEYS,
327 ARM_BUS_ADDRESS_SPACE_TYPES_VALUES, "Unknown");
328 json_object_object_add(bus_error_ir, "addressSpace", address_space);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100329
Lawrence Tange407b4c2022-07-21 13:54:01 +0100330 //Memory access attributes.
331 //todo: find the specification of these in the ARM ARM
332 json_object_object_add(
333 bus_error_ir, "memoryAttributes",
334 json_object_new_int(bus_error->MemoryAddressAttributes));
Lawrence Tang7f21db62022-07-06 11:09:39 +0100335
Lawrence Tange407b4c2022-07-21 13:54:01 +0100336 //Access Mode
337 json_object *access_mode = json_object_new_object();
338 json_object_object_add(access_mode, "value",
339 json_object_new_int(bus_error->AccessMode));
340 json_object_object_add(
341 access_mode, "name",
342 json_object_new_string(bus_error->AccessMode == 0 ? "Secure" :
343 "Normal"));
344 json_object_object_add(bus_error_ir, "accessMode", access_mode);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100345
Lawrence Tange407b4c2022-07-21 13:54:01 +0100346 return bus_error_ir;
Lawrence Tang7f21db62022-07-06 11:09:39 +0100347}
348
349//Converts a single ARM processor context block into JSON IR.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100350json_object *
351cper_arm_processor_context_to_ir(EFI_ARM_CONTEXT_INFORMATION_HEADER *header,
352 void **cur_pos)
Lawrence Tang7f21db62022-07-06 11:09:39 +0100353{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100354 json_object *context_ir = json_object_new_object();
Lawrence Tang7f21db62022-07-06 11:09:39 +0100355
Lawrence Tange407b4c2022-07-21 13:54:01 +0100356 //Version.
357 json_object_object_add(context_ir, "version",
358 json_object_new_int(header->Version));
Lawrence Tang71570a22022-07-14 11:45:28 +0100359
Lawrence Tange407b4c2022-07-21 13:54:01 +0100360 //Add the context type.
361 json_object *context_type = integer_to_readable_pair(
362 header->RegisterContextType, 9,
363 ARM_PROCESSOR_INFO_REGISTER_CONTEXT_TYPES_KEYS,
364 ARM_PROCESSOR_INFO_REGISTER_CONTEXT_TYPES_VALUES,
365 "Unknown (Reserved)");
366 json_object_object_add(context_ir, "registerContextType", context_type);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100367
Lawrence Tange407b4c2022-07-21 13:54:01 +0100368 //Register array size (bytes).
369 json_object_object_add(
370 context_ir, "registerArraySize",
371 json_object_new_uint64(header->RegisterArraySize));
Lawrence Tang7f21db62022-07-06 11:09:39 +0100372
Lawrence Tange407b4c2022-07-21 13:54:01 +0100373 //The register array itself.
374 *cur_pos = (void *)(header + 1);
375 json_object *register_array = NULL;
376 switch (header->RegisterContextType) {
377 case EFI_ARM_CONTEXT_TYPE_AARCH32_GPR:
378 register_array = uniform_struct_to_ir(
379 (UINT32 *)cur_pos,
380 sizeof(EFI_ARM_V8_AARCH32_GPR) / sizeof(UINT32),
381 ARM_AARCH32_GPR_NAMES);
382 break;
383 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL1:
384 register_array = uniform_struct_to_ir(
385 (UINT32 *)cur_pos,
386 sizeof(EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS) /
387 sizeof(UINT32),
388 ARM_AARCH32_EL1_REGISTER_NAMES);
389 break;
390 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL2:
391 register_array = uniform_struct_to_ir(
392 (UINT32 *)cur_pos,
393 sizeof(EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS) /
394 sizeof(UINT32),
395 ARM_AARCH32_EL2_REGISTER_NAMES);
396 break;
397 case EFI_ARM_CONTEXT_TYPE_AARCH32_SECURE:
398 register_array = uniform_struct_to_ir(
399 (UINT32 *)cur_pos,
400 sizeof(EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS) /
401 sizeof(UINT32),
402 ARM_AARCH32_SECURE_REGISTER_NAMES);
403 break;
404 case EFI_ARM_CONTEXT_TYPE_AARCH64_GPR:
405 register_array = uniform_struct64_to_ir(
406 (UINT64 *)cur_pos,
407 sizeof(EFI_ARM_V8_AARCH64_GPR) / sizeof(UINT64),
408 ARM_AARCH64_GPR_NAMES);
409 break;
410 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL1:
411 register_array = uniform_struct64_to_ir(
412 (UINT64 *)cur_pos,
413 sizeof(EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS) /
414 sizeof(UINT64),
415 ARM_AARCH64_EL1_REGISTER_NAMES);
416 break;
417 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL2:
418 register_array = uniform_struct64_to_ir(
419 (UINT64 *)cur_pos,
420 sizeof(EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS) /
421 sizeof(UINT64),
422 ARM_AARCH64_EL2_REGISTER_NAMES);
423 break;
424 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL3:
425 register_array = uniform_struct64_to_ir(
426 (UINT64 *)cur_pos,
427 sizeof(EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS) /
428 sizeof(UINT64),
429 ARM_AARCH64_EL3_REGISTER_NAMES);
430 break;
431 case EFI_ARM_CONTEXT_TYPE_MISC:
432 register_array = cper_arm_misc_register_array_to_ir(
433 (EFI_ARM_MISC_CONTEXT_REGISTER *)cur_pos);
434 break;
435 default:
436 //Unknown register array type, add as base64 data instead.
437 register_array = json_object_new_object();
438 char *encoded = b64_encode((unsigned char *)cur_pos,
439 header->RegisterArraySize);
440 json_object_object_add(register_array, "data",
441 json_object_new_string(encoded));
442 free(encoded);
443 break;
444 }
445 json_object_object_add(context_ir, "registerArray", register_array);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100446
Lawrence Tange407b4c2022-07-21 13:54:01 +0100447 //Set the current position to after the processor context structure.
448 *cur_pos = (UINT8 *)(*cur_pos) + header->RegisterArraySize;
Lawrence Tang7f21db62022-07-06 11:09:39 +0100449
Lawrence Tange407b4c2022-07-21 13:54:01 +0100450 return context_ir;
Lawrence Tang7f21db62022-07-06 11:09:39 +0100451}
452
453//Converts a single CPER ARM miscellaneous register array to JSON IR format.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100454json_object *
455cper_arm_misc_register_array_to_ir(EFI_ARM_MISC_CONTEXT_REGISTER *misc_register)
Lawrence Tang7f21db62022-07-06 11:09:39 +0100456{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100457 json_object *register_array = json_object_new_object();
458 json_object *mrs_encoding = json_object_new_object();
459 json_object_object_add(mrs_encoding, "op2",
460 json_object_new_uint64(misc_register->MrsOp2));
461 json_object_object_add(mrs_encoding, "crm",
462 json_object_new_uint64(misc_register->MrsCrm));
463 json_object_object_add(mrs_encoding, "crn",
464 json_object_new_uint64(misc_register->MrsCrn));
465 json_object_object_add(mrs_encoding, "op1",
466 json_object_new_uint64(misc_register->MrsOp1));
467 json_object_object_add(mrs_encoding, "o0",
468 json_object_new_uint64(misc_register->MrsO0));
469 json_object_object_add(register_array, "mrsEncoding", mrs_encoding);
470 json_object_object_add(register_array, "value",
471 json_object_new_uint64(misc_register->Value));
Lawrence Tang7f21db62022-07-06 11:09:39 +0100472
Lawrence Tange407b4c2022-07-21 13:54:01 +0100473 return register_array;
Lawrence Tang7cd13902022-07-13 16:59:25 +0100474}
475
476//Converts a single CPER-JSON ARM error section into CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100477void ir_section_arm_to_cper(json_object *section, FILE *out)
Lawrence Tang7cd13902022-07-13 16:59:25 +0100478{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100479 EFI_ARM_ERROR_RECORD *section_cper =
480 (EFI_ARM_ERROR_RECORD *)calloc(1, sizeof(EFI_ARM_ERROR_RECORD));
481 long starting_stream_pos = ftell(out);
Lawrence Tang7cd13902022-07-13 16:59:25 +0100482
Lawrence Tange407b4c2022-07-21 13:54:01 +0100483 //Validation bits.
484 section_cper->ValidFields = ir_to_bitfield(
485 json_object_object_get(section, "validationBits"), 4,
486 ARM_ERROR_VALID_BITFIELD_NAMES);
Lawrence Tang7cd13902022-07-13 16:59:25 +0100487
Lawrence Tange407b4c2022-07-21 13:54:01 +0100488 //Count of error/context info structures.
489 section_cper->ErrInfoNum = json_object_get_int(
490 json_object_object_get(section, "errorInfoNum"));
491 section_cper->ContextInfoNum = json_object_get_int(
492 json_object_object_get(section, "contextInfoNum"));
Lawrence Tang7cd13902022-07-13 16:59:25 +0100493
Lawrence Tange407b4c2022-07-21 13:54:01 +0100494 //Miscellaneous raw value fields.
495 section_cper->SectionLength = json_object_get_uint64(
496 json_object_object_get(section, "sectionLength"));
497 section_cper->ErrorAffinityLevel = readable_pair_to_integer(
498 json_object_object_get(section, "errorAffinity"));
499 section_cper->MPIDR_EL1 = json_object_get_uint64(
500 json_object_object_get(section, "mpidrEl1"));
501 section_cper->MIDR_EL1 = json_object_get_uint64(
502 json_object_object_get(section, "midrEl1"));
503 section_cper->RunningState = json_object_get_boolean(
504 json_object_object_get(section, "running"));
Lawrence Tang7cd13902022-07-13 16:59:25 +0100505
Lawrence Tange407b4c2022-07-21 13:54:01 +0100506 //Optional PSCI state.
507 json_object *psci_state = json_object_object_get(section, "psciState");
508 if (psci_state != NULL)
509 section_cper->PsciState = json_object_get_uint64(psci_state);
Lawrence Tang7cd13902022-07-13 16:59:25 +0100510
Lawrence Tange407b4c2022-07-21 13:54:01 +0100511 //Flush header to stream.
512 fwrite(section_cper, sizeof(EFI_ARM_ERROR_RECORD), 1, out);
513 fflush(out);
Lawrence Tang7cd13902022-07-13 16:59:25 +0100514
Lawrence Tange407b4c2022-07-21 13:54:01 +0100515 //Error info structure array.
516 json_object *error_info = json_object_object_get(section, "errorInfo");
517 for (int i = 0; i < section_cper->ErrInfoNum; i++)
518 ir_arm_error_info_to_cper(
519 json_object_array_get_idx(error_info, i), out);
Lawrence Tang7cd13902022-07-13 16:59:25 +0100520
Lawrence Tange407b4c2022-07-21 13:54:01 +0100521 //Context info structure array.
522 json_object *context_info =
523 json_object_object_get(section, "contextInfo");
524 for (int i = 0; i < section_cper->ContextInfoNum; i++)
525 ir_arm_context_info_to_cper(
526 json_object_array_get_idx(context_info, i), out);
Lawrence Tang7cd13902022-07-13 16:59:25 +0100527
Lawrence Tange407b4c2022-07-21 13:54:01 +0100528 //Vendor specific error info.
529 json_object *vendor_specific_info =
530 json_object_object_get(section, "vendorSpecificInfo");
531 if (vendor_specific_info != NULL) {
532 json_object *vendor_info_string =
533 json_object_object_get(vendor_specific_info, "data");
534 int vendor_specific_len =
535 json_object_get_string_len(vendor_info_string);
536 UINT8 *decoded =
537 b64_decode(json_object_get_string(vendor_info_string),
538 vendor_specific_len);
Lawrence Tang01e3a442022-07-20 15:14:50 +0100539
Lawrence Tange407b4c2022-07-21 13:54:01 +0100540 //Write out to file.
541 long cur_stream_pos = ftell(out);
542 fwrite(decoded,
543 starting_stream_pos + section_cper->SectionLength -
544 cur_stream_pos,
545 1, out);
546 fflush(out);
547 free(decoded);
548 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100549
Lawrence Tange407b4c2022-07-21 13:54:01 +0100550 //Free remaining resources.
551 free(section_cper);
Lawrence Tang7cd13902022-07-13 16:59:25 +0100552}
553
554//Converts a single ARM error information structure into CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100555void ir_arm_error_info_to_cper(json_object *error_info, FILE *out)
Lawrence Tang7cd13902022-07-13 16:59:25 +0100556{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100557 EFI_ARM_ERROR_INFORMATION_ENTRY error_info_cper;
Lawrence Tang7cd13902022-07-13 16:59:25 +0100558
Lawrence Tange407b4c2022-07-21 13:54:01 +0100559 //Version, length.
560 error_info_cper.Version = json_object_get_int(
561 json_object_object_get(error_info, "version"));
562 error_info_cper.Length = json_object_get_int(
563 json_object_object_get(error_info, "length"));
Lawrence Tang7cd13902022-07-13 16:59:25 +0100564
Lawrence Tange407b4c2022-07-21 13:54:01 +0100565 //Validation bits.
566 error_info_cper.ValidationBits = ir_to_bitfield(
567 json_object_object_get(error_info, "validationBits"), 5,
568 ARM_ERROR_INFO_ENTRY_VALID_BITFIELD_NAMES);
Lawrence Tang7cd13902022-07-13 16:59:25 +0100569
Lawrence Tange407b4c2022-07-21 13:54:01 +0100570 //Type, multiple error.
571 error_info_cper.Type = (UINT8)readable_pair_to_integer(
572 json_object_object_get(error_info, "type"));
573 error_info_cper.MultipleError = (UINT16)readable_pair_to_integer(
574 json_object_object_get(error_info, "multipleError"));
Lawrence Tang7cd13902022-07-13 16:59:25 +0100575
Lawrence Tange407b4c2022-07-21 13:54:01 +0100576 //Flags object.
577 error_info_cper.Flags = (UINT8)ir_to_bitfield(
578 json_object_object_get(error_info, "flags"), 4,
579 ARM_ERROR_INFO_ENTRY_FLAGS_NAMES);
Lawrence Tang7cd13902022-07-13 16:59:25 +0100580
Lawrence Tange407b4c2022-07-21 13:54:01 +0100581 //Error information.
582 json_object *error_info_information =
583 json_object_object_get(error_info, "errorInformation");
584 switch (error_info_cper.Type) {
585 case ARM_ERROR_INFORMATION_TYPE_CACHE:
586 case ARM_ERROR_INFORMATION_TYPE_TLB:
587 ir_arm_error_cache_tlb_info_to_cper(
588 error_info_information,
589 &error_info_cper.ErrorInformation.CacheError);
590 break;
Lawrence Tang71570a22022-07-14 11:45:28 +0100591
Lawrence Tange407b4c2022-07-21 13:54:01 +0100592 case ARM_ERROR_INFORMATION_TYPE_BUS:
593 ir_arm_error_bus_info_to_cper(
594 error_info_information,
595 &error_info_cper.ErrorInformation.BusError);
596 break;
Lawrence Tang71570a22022-07-14 11:45:28 +0100597
Lawrence Tange407b4c2022-07-21 13:54:01 +0100598 default:
599 //Unknown error information type.
600 *((UINT64 *)&error_info_cper.ErrorInformation) =
601 json_object_get_uint64(json_object_object_get(
602 error_info_information, "data"));
603 break;
604 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100605
Lawrence Tange407b4c2022-07-21 13:54:01 +0100606 //Virtual/physical fault address.
607 error_info_cper.VirtualFaultAddress = json_object_get_uint64(
608 json_object_object_get(error_info, "virtualFaultAddress"));
609 error_info_cper.PhysicalFaultAddress = json_object_get_uint64(
610 json_object_object_get(error_info, "physicalFaultAddress"));
Lawrence Tang7cd13902022-07-13 16:59:25 +0100611
Lawrence Tange407b4c2022-07-21 13:54:01 +0100612 //Write out to stream.
613 fwrite(&error_info_cper, sizeof(EFI_ARM_ERROR_INFORMATION_ENTRY), 1,
614 out);
615 fflush(out);
Lawrence Tang7cd13902022-07-13 16:59:25 +0100616}
617
Lawrence Tang71570a22022-07-14 11:45:28 +0100618//Converts a single ARM cache/TLB error information structure into a CPER structure.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100619void ir_arm_error_cache_tlb_info_to_cper(
620 json_object *error_information,
621 EFI_ARM_CACHE_ERROR_STRUCTURE *error_info_cper)
Lawrence Tang71570a22022-07-14 11:45:28 +0100622{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100623 //Validation bits.
624 error_info_cper->ValidationBits = ir_to_bitfield(
625 json_object_object_get(error_information, "validationBits"), 7,
626 ARM_CACHE_TLB_ERROR_VALID_BITFIELD_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100627
Lawrence Tange407b4c2022-07-21 13:54:01 +0100628 //Miscellaneous value fields.
629 error_info_cper->TransactionType = readable_pair_to_integer(
630 json_object_object_get(error_information, "transactionType"));
631 error_info_cper->Operation = readable_pair_to_integer(
632 json_object_object_get(error_information, "operation"));
633 error_info_cper->Level = json_object_get_uint64(
634 json_object_object_get(error_information, "level"));
635 error_info_cper->ProcessorContextCorrupt = json_object_get_boolean(
636 json_object_object_get(error_information,
637 "processorContextCorrupt"));
638 error_info_cper->Corrected = json_object_get_boolean(
639 json_object_object_get(error_information, "corrected"));
640 error_info_cper->PrecisePC = json_object_get_boolean(
641 json_object_object_get(error_information, "precisePC"));
642 error_info_cper->RestartablePC = json_object_get_boolean(
643 json_object_object_get(error_information, "restartablePC"));
644 error_info_cper->Reserved = 0;
Lawrence Tang71570a22022-07-14 11:45:28 +0100645}
646
647//Converts a single ARM bus error information structure into a CPER structure.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100648void ir_arm_error_bus_info_to_cper(json_object *error_information,
649 EFI_ARM_BUS_ERROR_STRUCTURE *error_info_cper)
Lawrence Tang71570a22022-07-14 11:45:28 +0100650{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100651 //Validation bits.
652 error_info_cper->ValidationBits = ir_to_bitfield(
653 json_object_object_get(error_information, "validationBits"), 7,
654 ARM_BUS_ERROR_VALID_BITFIELD_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100655
Lawrence Tange407b4c2022-07-21 13:54:01 +0100656 //Miscellaneous value fields.
657 error_info_cper->TransactionType = readable_pair_to_integer(
658 json_object_object_get(error_information, "transactionType"));
659 error_info_cper->Operation = readable_pair_to_integer(
660 json_object_object_get(error_information, "operation"));
661 error_info_cper->Level = json_object_get_uint64(
662 json_object_object_get(error_information, "level"));
663 error_info_cper->ProcessorContextCorrupt = json_object_get_boolean(
664 json_object_object_get(error_information,
665 "processorContextCorrupt"));
666 error_info_cper->Corrected = json_object_get_boolean(
667 json_object_object_get(error_information, "corrected"));
668 error_info_cper->PrecisePC = json_object_get_boolean(
669 json_object_object_get(error_information, "precisePC"));
670 error_info_cper->RestartablePC = json_object_get_boolean(
671 json_object_object_get(error_information, "restartablePC"));
672 error_info_cper->ParticipationType = readable_pair_to_integer(
673 json_object_object_get(error_information, "participationType"));
674 error_info_cper->AddressSpace = readable_pair_to_integer(
675 json_object_object_get(error_information, "addressSpace"));
676 error_info_cper->AccessMode = readable_pair_to_integer(
677 json_object_object_get(error_information, "accessMode"));
678 error_info_cper->MemoryAddressAttributes = json_object_get_uint64(
679 json_object_object_get(error_information, "memoryAttributes"));
680 error_info_cper->Reserved = 0;
Lawrence Tang71570a22022-07-14 11:45:28 +0100681}
682
Lawrence Tang7cd13902022-07-13 16:59:25 +0100683//Converts a single ARM context information structure into CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100684void ir_arm_context_info_to_cper(json_object *context_info, FILE *out)
Lawrence Tang7cd13902022-07-13 16:59:25 +0100685{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100686 EFI_ARM_CONTEXT_INFORMATION_HEADER info_header;
Lawrence Tang7cd13902022-07-13 16:59:25 +0100687
Lawrence Tange407b4c2022-07-21 13:54:01 +0100688 //Version, array size, context type.
689 info_header.Version = json_object_get_int(
690 json_object_object_get(context_info, "version"));
691 info_header.RegisterArraySize = json_object_get_int(
692 json_object_object_get(context_info, "registerArraySize"));
693 info_header.RegisterContextType = readable_pair_to_integer(
694 json_object_object_get(context_info, "registerContextType"));
Lawrence Tang71570a22022-07-14 11:45:28 +0100695
Lawrence Tange407b4c2022-07-21 13:54:01 +0100696 //Flush to stream, write the register array itself.
697 fwrite(&info_header, sizeof(EFI_ARM_CONTEXT_INFORMATION_HEADER), 1,
698 out);
699 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100700
Lawrence Tange407b4c2022-07-21 13:54:01 +0100701 json_object *register_array =
702 json_object_object_get(context_info, "registerArray");
703 switch (info_header.RegisterContextType) {
704 case EFI_ARM_CONTEXT_TYPE_AARCH32_GPR:
705 ir_arm_aarch32_gpr_to_cper(register_array, out);
706 break;
707 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL1:
708 ir_arm_aarch32_el1_to_cper(register_array, out);
709 break;
710 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL2:
711 ir_arm_aarch32_el2_to_cper(register_array, out);
712 break;
713 case EFI_ARM_CONTEXT_TYPE_AARCH32_SECURE:
714 ir_arm_aarch32_secure_to_cper(register_array, out);
715 break;
716 case EFI_ARM_CONTEXT_TYPE_AARCH64_GPR:
717 ir_arm_aarch64_gpr_to_cper(register_array, out);
718 break;
719 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL1:
720 ir_arm_aarch64_el1_to_cper(register_array, out);
721 break;
722 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL2:
723 ir_arm_aarch64_el2_to_cper(register_array, out);
724 break;
725 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL3:
726 ir_arm_aarch64_el3_to_cper(register_array, out);
727 break;
728 case EFI_ARM_CONTEXT_TYPE_MISC:
729 ir_arm_misc_registers_to_cper(register_array, out);
730 break;
731 default:
732 //Unknown register structure.
733 ir_arm_unknown_register_to_cper(register_array, &info_header,
734 out);
735 break;
736 }
Lawrence Tang71570a22022-07-14 11:45:28 +0100737}
738
739//Converts a single AARCH32 GPR CPER-JSON object to CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100740void ir_arm_aarch32_gpr_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100741{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100742 //Get uniform register array.
743 EFI_ARM_V8_AARCH32_GPR reg_array;
744 ir_to_uniform_struct(registers, (UINT32 *)&reg_array,
745 sizeof(EFI_ARM_V8_AARCH32_GPR) / sizeof(UINT32),
746 ARM_AARCH32_GPR_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100747
Lawrence Tange407b4c2022-07-21 13:54:01 +0100748 //Flush to stream.
749 fwrite(&reg_array, sizeof(reg_array), 1, out);
750 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100751}
752
753//Converts a single AARCH32 EL1 register set CPER-JSON object to CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100754void ir_arm_aarch32_el1_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100755{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100756 //Get uniform register array.
757 EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS reg_array;
758 ir_to_uniform_struct(registers, (UINT32 *)&reg_array,
759 sizeof(EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS) /
760 sizeof(UINT32),
761 ARM_AARCH32_EL1_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100762
Lawrence Tange407b4c2022-07-21 13:54:01 +0100763 //Flush to stream.
764 fwrite(&reg_array, sizeof(reg_array), 1, out);
765 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100766}
767
768//Converts a single AARCH32 EL2 register set CPER-JSON object to CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100769void ir_arm_aarch32_el2_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100770{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100771 //Get uniform register array.
772 EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS reg_array;
773 ir_to_uniform_struct(registers, (UINT32 *)&reg_array,
774 sizeof(EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS) /
775 sizeof(UINT32),
776 ARM_AARCH32_EL2_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100777
Lawrence Tange407b4c2022-07-21 13:54:01 +0100778 //Flush to stream.
779 fwrite(&reg_array, sizeof(reg_array), 1, out);
780 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100781}
782
783//Converts a single AARCH32 secure register set CPER-JSON object to CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100784void ir_arm_aarch32_secure_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100785{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100786 //Get uniform register array.
787 EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS reg_array;
788 ir_to_uniform_struct(registers, (UINT32 *)&reg_array,
789 sizeof(EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS) /
790 sizeof(UINT32),
791 ARM_AARCH32_SECURE_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100792
Lawrence Tange407b4c2022-07-21 13:54:01 +0100793 //Flush to stream.
794 fwrite(&reg_array, sizeof(reg_array), 1, out);
795 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100796}
797
798//Converts a single AARCH64 GPR CPER-JSON object to CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100799void ir_arm_aarch64_gpr_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100800{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100801 //Get uniform register array.
802 EFI_ARM_V8_AARCH64_GPR reg_array;
803 ir_to_uniform_struct64(registers, (UINT64 *)&reg_array,
804 sizeof(EFI_ARM_V8_AARCH64_GPR) / sizeof(UINT64),
805 ARM_AARCH64_GPR_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100806
Lawrence Tange407b4c2022-07-21 13:54:01 +0100807 //Flush to stream.
808 fwrite(&reg_array, sizeof(reg_array), 1, out);
809 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100810}
811
812//Converts a single AARCH64 EL1 register set CPER-JSON object to CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100813void ir_arm_aarch64_el1_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100814{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100815 //Get uniform register array.
816 EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS reg_array;
817 ir_to_uniform_struct64(registers, (UINT64 *)&reg_array,
818 sizeof(EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS) /
819 sizeof(UINT64),
820 ARM_AARCH64_EL1_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100821
Lawrence Tange407b4c2022-07-21 13:54:01 +0100822 //Flush to stream.
823 fwrite(&reg_array, sizeof(reg_array), 1, out);
824 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100825}
826
827//Converts a single AARCH64 EL2 register set CPER-JSON object to CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100828void ir_arm_aarch64_el2_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100829{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100830 //Get uniform register array.
831 EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS reg_array;
832 ir_to_uniform_struct64(registers, (UINT64 *)&reg_array,
833 sizeof(EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS) /
834 sizeof(UINT64),
835 ARM_AARCH64_EL2_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100836
Lawrence Tange407b4c2022-07-21 13:54:01 +0100837 //Flush to stream.
838 fwrite(&reg_array, sizeof(reg_array), 1, out);
839 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100840}
841
842//Converts a single AARCH64 EL3 register set CPER-JSON object to CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100843void ir_arm_aarch64_el3_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100844{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100845 //Get uniform register array.
846 EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS reg_array;
847 ir_to_uniform_struct64(registers, (UINT64 *)&reg_array,
848 sizeof(EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS) /
849 sizeof(UINT64),
850 ARM_AARCH64_EL3_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100851
Lawrence Tange407b4c2022-07-21 13:54:01 +0100852 //Flush to stream.
853 fwrite(&reg_array, sizeof(reg_array), 1, out);
854 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100855}
856
857//Converts a single ARM miscellaneous register set CPER-JSON object to CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100858void ir_arm_misc_registers_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100859{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100860 EFI_ARM_MISC_CONTEXT_REGISTER reg_array;
Lawrence Tang71570a22022-07-14 11:45:28 +0100861
Lawrence Tange407b4c2022-07-21 13:54:01 +0100862 //MRS encoding information.
863 json_object *mrs_encoding =
864 json_object_object_get(registers, "mrsEncoding");
865 reg_array.MrsOp2 = json_object_get_uint64(
866 json_object_object_get(mrs_encoding, "op2"));
867 reg_array.MrsCrm = json_object_get_uint64(
868 json_object_object_get(mrs_encoding, "crm"));
869 reg_array.MrsCrn = json_object_get_uint64(
870 json_object_object_get(mrs_encoding, "crn"));
871 reg_array.MrsOp1 = json_object_get_uint64(
872 json_object_object_get(mrs_encoding, "op1"));
873 reg_array.MrsO0 = json_object_get_uint64(
874 json_object_object_get(mrs_encoding, "o0"));
Lawrence Tang71570a22022-07-14 11:45:28 +0100875
Lawrence Tange407b4c2022-07-21 13:54:01 +0100876 //Actual register value.
877 reg_array.Value = json_object_get_uint64(
878 json_object_object_get(registers, "value"));
Lawrence Tang71570a22022-07-14 11:45:28 +0100879
Lawrence Tange407b4c2022-07-21 13:54:01 +0100880 //Flush to stream.
881 fwrite(&reg_array, sizeof(reg_array), 1, out);
882 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100883}
884
885//Converts a single ARM unknown register CPER-JSON object to CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100886void ir_arm_unknown_register_to_cper(json_object *registers,
887 EFI_ARM_CONTEXT_INFORMATION_HEADER *header,
888 FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100889{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100890 //Get base64 represented data.
891 json_object *encoded = json_object_object_get(registers, "data");
892 UINT8 *decoded = b64_decode(json_object_get_string(encoded),
893 json_object_get_string_len(encoded));
Lawrence Tang71570a22022-07-14 11:45:28 +0100894
Lawrence Tange407b4c2022-07-21 13:54:01 +0100895 //Flush out to stream.
896 fwrite(&decoded, header->RegisterArraySize, 1, out);
897 fflush(out);
898 free(decoded);
Lawrence Tang2800cd82022-07-05 16:08:20 +0100899}