blob: e0f7cb531fcd7e8865ddc7976daea87d416f1cc6 [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>
John Chungf8fc7052024-05-03 20:05:29 +080010#include "libbase64.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);
John Chungf8fc7052024-05-03 20:05:29 +080043void ir_arm_unknown_register_to_cper(json_object *registers, FILE *out);
Lawrence Tang3d0e4f22022-07-05 17:17:41 +010044
Lawrence Tang2800cd82022-07-05 16:08:20 +010045//Converts the given processor-generic CPER section into JSON IR.
John Chungf8fc7052024-05-03 20:05:29 +080046json_object *cper_section_arm_to_ir(void *section)
Lawrence Tang2800cd82022-07-05 16:08:20 +010047{
Lawrence Tange407b4c2022-07-21 13:54:01 +010048 EFI_ARM_ERROR_RECORD *record = (EFI_ARM_ERROR_RECORD *)section;
49 json_object *section_ir = json_object_new_object();
Lawrence Tang2800cd82022-07-05 16:08:20 +010050
Lawrence Tange407b4c2022-07-21 13:54:01 +010051 //Validation bits.
52 json_object *validation = bitfield_to_ir(
53 record->ValidFields, 4, ARM_ERROR_VALID_BITFIELD_NAMES);
54 json_object_object_add(section_ir, "validationBits", validation);
Lawrence Tang2800cd82022-07-05 16:08:20 +010055
Lawrence Tange407b4c2022-07-21 13:54:01 +010056 //Number of error info and context info structures, and length.
57 json_object_object_add(section_ir, "errorInfoNum",
58 json_object_new_int(record->ErrInfoNum));
59 json_object_object_add(section_ir, "contextInfoNum",
60 json_object_new_int(record->ContextInfoNum));
61 json_object_object_add(section_ir, "sectionLength",
62 json_object_new_uint64(record->SectionLength));
Lawrence Tang2800cd82022-07-05 16:08:20 +010063
Lawrence Tange407b4c2022-07-21 13:54:01 +010064 //Error affinity.
65 json_object *error_affinity = json_object_new_object();
66 json_object_object_add(error_affinity, "value",
67 json_object_new_int(record->ErrorAffinityLevel));
68 json_object_object_add(
69 error_affinity, "type",
70 json_object_new_string(record->ErrorAffinityLevel < 4 ?
John Chungf8fc7052024-05-03 20:05:29 +080071 "Vendor Defined" :
72 "Reserved"));
Lawrence Tange407b4c2022-07-21 13:54:01 +010073 json_object_object_add(section_ir, "errorAffinity", error_affinity);
Lawrence Tang2800cd82022-07-05 16:08:20 +010074
Lawrence Tange407b4c2022-07-21 13:54:01 +010075 //Processor ID (MPIDR_EL1) and chip ID (MIDR_EL1).
76 json_object_object_add(section_ir, "mpidrEl1",
77 json_object_new_uint64(record->MPIDR_EL1));
78 json_object_object_add(section_ir, "midrEl1",
79 json_object_new_uint64(record->MIDR_EL1));
Lawrence Tang2800cd82022-07-05 16:08:20 +010080
Lawrence Tange407b4c2022-07-21 13:54:01 +010081 //Whether the processor is running, and the state of it if so.
82 json_object_object_add(section_ir, "running",
83 json_object_new_boolean(record->RunningState &
John Chungf8fc7052024-05-03 20:05:29 +080084 0x1));
Lawrence Tange407b4c2022-07-21 13:54:01 +010085 if (!(record->RunningState >> 31)) {
86 //Bit 32 of running state is on, so PSCI state information is included.
87 //This can't be made human readable, as it is unknown whether this will be the pre-PSCI 1.0 format
88 //or the newer Extended StateID format.
89 json_object_object_add(
90 section_ir, "psciState",
91 json_object_new_uint64(record->PsciState));
92 }
Lawrence Tang7f21db62022-07-06 11:09:39 +010093
Lawrence Tange407b4c2022-07-21 13:54:01 +010094 //Processor error structures.
95 json_object *error_info_array = json_object_new_array();
96 EFI_ARM_ERROR_INFORMATION_ENTRY *cur_error =
97 (EFI_ARM_ERROR_INFORMATION_ENTRY *)(record + 1);
98 for (int i = 0; i < record->ErrInfoNum; i++) {
99 json_object_array_add(error_info_array,
100 cper_arm_error_info_to_ir(cur_error));
101 cur_error++;
102 }
103 json_object_object_add(section_ir, "errorInfo", error_info_array);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100104
Lawrence Tange407b4c2022-07-21 13:54:01 +0100105 //Processor context structures.
106 //The current position is moved within the processing, as it is a dynamic size structure.
John Chungf8fc7052024-05-03 20:05:29 +0800107 uint8_t *cur_pos = (uint8_t *)cur_error;
Lawrence Tange407b4c2022-07-21 13:54:01 +0100108 json_object *context_info_array = json_object_new_array();
109 for (int i = 0; i < record->ContextInfoNum; i++) {
110 EFI_ARM_CONTEXT_INFORMATION_HEADER *header =
111 (EFI_ARM_CONTEXT_INFORMATION_HEADER *)cur_pos;
112 json_object *processor_context =
John Chungf8fc7052024-05-03 20:05:29 +0800113 cper_arm_processor_context_to_ir(header,
114 (void **)&cur_pos);
Lawrence Tange407b4c2022-07-21 13:54:01 +0100115 json_object_array_add(context_info_array, processor_context);
116 }
117 json_object_object_add(section_ir, "contextInfo", context_info_array);
Lawrence Tangd7e8ca32022-07-07 10:25:53 +0100118
Lawrence Tange407b4c2022-07-21 13:54:01 +0100119 //Is there any vendor-specific information following?
John Chungf8fc7052024-05-03 20:05:29 +0800120 if (cur_pos < (uint8_t *)section + record->SectionLength) {
Lawrence Tange407b4c2022-07-21 13:54:01 +0100121 json_object *vendor_specific = json_object_new_object();
John Chungf8fc7052024-05-03 20:05:29 +0800122 size_t input_size =
123 (uint8_t *)section + record->SectionLength - cur_pos;
124 char *encoded = malloc(2 * input_size);
125 size_t encoded_len = 0;
126 if (!encoded) {
127 printf("Failed to allocate encode output buffer. \n");
128 } else {
129 base64_encode((const char *)cur_pos, input_size,
130 encoded, &encoded_len, 0);
131 json_object_object_add(vendor_specific, "data",
132 json_object_new_string_len(
133 encoded, encoded_len));
134 free(encoded);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100135
John Chungf8fc7052024-05-03 20:05:29 +0800136 json_object_object_add(section_ir, "vendorSpecificInfo",
137 vendor_specific);
138 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100139 }
140
141 return section_ir;
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100142}
143
144//Converts a single ARM Process Error Information structure into JSON IR.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100145json_object *
146cper_arm_error_info_to_ir(EFI_ARM_ERROR_INFORMATION_ENTRY *error_info)
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100147{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100148 json_object *error_info_ir = json_object_new_object();
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100149
Lawrence Tange407b4c2022-07-21 13:54:01 +0100150 //Version, length.
151 json_object_object_add(error_info_ir, "version",
152 json_object_new_int(error_info->Version));
153 json_object_object_add(error_info_ir, "length",
154 json_object_new_int(error_info->Length));
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100155
Lawrence Tange407b4c2022-07-21 13:54:01 +0100156 //Validation bitfield.
157 json_object *validation =
158 bitfield_to_ir(error_info->ValidationBits, 5,
159 ARM_ERROR_INFO_ENTRY_VALID_BITFIELD_NAMES);
160 json_object_object_add(error_info_ir, "validationBits", validation);
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100161
Lawrence Tange407b4c2022-07-21 13:54:01 +0100162 //The type of error information in this log.
163 json_object *error_type = integer_to_readable_pair(
164 error_info->Type, 4, ARM_ERROR_INFO_ENTRY_INFO_TYPES_KEYS,
165 ARM_ERROR_INFO_ENTRY_INFO_TYPES_VALUES, "Unknown (Reserved)");
166 json_object_object_add(error_info_ir, "errorType", error_type);
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100167
Lawrence Tange407b4c2022-07-21 13:54:01 +0100168 //Multiple error count.
169 json_object *multiple_error = json_object_new_object();
170 json_object_object_add(multiple_error, "value",
171 json_object_new_int(error_info->MultipleError));
172 json_object_object_add(
173 multiple_error, "type",
174 json_object_new_string(error_info->MultipleError < 1 ?
John Chungf8fc7052024-05-03 20:05:29 +0800175 "Single Error" :
176 "Multiple Errors"));
Lawrence Tange407b4c2022-07-21 13:54:01 +0100177 json_object_object_add(error_info_ir, "multipleError", multiple_error);
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100178
Lawrence Tange407b4c2022-07-21 13:54:01 +0100179 //Flags.
180 json_object *flags = bitfield_to_ir(error_info->Flags, 4,
181 ARM_ERROR_INFO_ENTRY_FLAGS_NAMES);
182 json_object_object_add(error_info_ir, "flags", flags);
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100183
Lawrence Tange407b4c2022-07-21 13:54:01 +0100184 //Error information, split by type.
185 json_object *error_subinfo = NULL;
186 switch (error_info->Type) {
187 case ARM_ERROR_INFORMATION_TYPE_CACHE: //Cache
John Chungf8fc7052024-05-03 20:05:29 +0800188 case ARM_ERROR_INFORMATION_TYPE_TLB: //TLB
Lawrence Tange407b4c2022-07-21 13:54:01 +0100189 error_subinfo = cper_arm_cache_tlb_error_to_ir(
190 (EFI_ARM_CACHE_ERROR_STRUCTURE *)&error_info
191 ->ErrorInformation,
192 error_info);
193 break;
194 case ARM_ERROR_INFORMATION_TYPE_BUS: //Bus
195 error_subinfo = cper_arm_bus_error_to_ir(
196 (EFI_ARM_BUS_ERROR_STRUCTURE *)&error_info
197 ->ErrorInformation);
198 break;
Lawrence Tang71570a22022-07-14 11:45:28 +0100199
Lawrence Tange407b4c2022-07-21 13:54:01 +0100200 default:
201 //Unknown/microarch, so can't be made readable. Simply dump as a uint64 data object.
202 error_subinfo = json_object_new_object();
203 json_object_object_add(
204 error_subinfo, "data",
205 json_object_new_uint64(
206 *((UINT64 *)&error_info->ErrorInformation)));
207 break;
208 }
209 json_object_object_add(error_info_ir, "errorInformation",
210 error_subinfo);
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100211
Lawrence Tange407b4c2022-07-21 13:54:01 +0100212 //Virtual fault address, physical fault address.
213 json_object_object_add(
214 error_info_ir, "virtualFaultAddress",
215 json_object_new_uint64(error_info->VirtualFaultAddress));
216 json_object_object_add(
217 error_info_ir, "physicalFaultAddress",
218 json_object_new_uint64(error_info->PhysicalFaultAddress));
219
220 return error_info_ir;
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100221}
222
Lawrence Tang7f21db62022-07-06 11:09:39 +0100223//Converts a single ARM cache/TLB error information structure into JSON IR format.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100224json_object *
225cper_arm_cache_tlb_error_to_ir(EFI_ARM_CACHE_ERROR_STRUCTURE *cache_tlb_error,
226 EFI_ARM_ERROR_INFORMATION_ENTRY *error_info)
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100227{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100228 json_object *cache_tlb_error_ir = json_object_new_object();
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100229
Lawrence Tange407b4c2022-07-21 13:54:01 +0100230 //Validation bitfield.
231 json_object *validation =
232 bitfield_to_ir(cache_tlb_error->ValidationBits, 7,
233 ARM_CACHE_TLB_ERROR_VALID_BITFIELD_NAMES);
234 json_object_object_add(cache_tlb_error_ir, "validationBits",
235 validation);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100236
Lawrence Tange407b4c2022-07-21 13:54:01 +0100237 //Transaction type.
238 json_object *transaction_type = integer_to_readable_pair(
239 cache_tlb_error->TransactionType, 3,
240 ARM_ERROR_TRANSACTION_TYPES_KEYS,
241 ARM_ERROR_TRANSACTION_TYPES_VALUES, "Unknown (Reserved)");
242 json_object_object_add(cache_tlb_error_ir, "transactionType",
243 transaction_type);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100244
Lawrence Tange407b4c2022-07-21 13:54:01 +0100245 //Operation.
246 json_object *operation;
247 if (error_info->Type == 0) {
248 //Cache operation.
249 operation = integer_to_readable_pair(
250 cache_tlb_error->Operation, 11,
251 ARM_CACHE_BUS_OPERATION_TYPES_KEYS,
252 ARM_CACHE_BUS_OPERATION_TYPES_VALUES,
253 "Unknown (Reserved)");
254 } else {
255 //TLB operation.
256 operation = integer_to_readable_pair(
257 cache_tlb_error->Operation, 9,
258 ARM_TLB_OPERATION_TYPES_KEYS,
259 ARM_TLB_OPERATION_TYPES_VALUES, "Unknown (Reserved)");
260 }
261 json_object_object_add(cache_tlb_error_ir, "operation", operation);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100262
Lawrence Tange407b4c2022-07-21 13:54:01 +0100263 //Miscellaneous remaining fields.
264 json_object_object_add(cache_tlb_error_ir, "level",
265 json_object_new_int(cache_tlb_error->Level));
266 json_object_object_add(
267 cache_tlb_error_ir, "processorContextCorrupt",
268 json_object_new_boolean(
269 cache_tlb_error->ProcessorContextCorrupt));
270 json_object_object_add(
271 cache_tlb_error_ir, "corrected",
272 json_object_new_boolean(cache_tlb_error->Corrected));
273 json_object_object_add(
274 cache_tlb_error_ir, "precisePC",
275 json_object_new_boolean(cache_tlb_error->PrecisePC));
276 json_object_object_add(
277 cache_tlb_error_ir, "restartablePC",
278 json_object_new_boolean(cache_tlb_error->RestartablePC));
279 return cache_tlb_error_ir;
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100280}
281
282//Converts a single ARM bus error information structure into JSON IR format.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100283json_object *cper_arm_bus_error_to_ir(EFI_ARM_BUS_ERROR_STRUCTURE *bus_error)
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100284{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100285 json_object *bus_error_ir = json_object_new_object();
Lawrence Tang7f21db62022-07-06 11:09:39 +0100286
Lawrence Tange407b4c2022-07-21 13:54:01 +0100287 //Validation bits.
288 json_object *validation =
289 bitfield_to_ir(bus_error->ValidationBits, 12,
290 ARM_BUS_ERROR_VALID_BITFIELD_NAMES);
291 json_object_object_add(bus_error_ir, "validationBits", validation);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100292
Lawrence Tange407b4c2022-07-21 13:54:01 +0100293 //Transaction type.
294 json_object *transaction_type = integer_to_readable_pair(
295 bus_error->TransactionType, 3, ARM_ERROR_TRANSACTION_TYPES_KEYS,
296 ARM_ERROR_TRANSACTION_TYPES_VALUES, "Unknown (Reserved)");
297 json_object_object_add(bus_error_ir, "transactionType",
298 transaction_type);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100299
Lawrence Tange407b4c2022-07-21 13:54:01 +0100300 //Operation.
301 json_object *operation = integer_to_readable_pair(
302 bus_error->Operation, 7, ARM_CACHE_BUS_OPERATION_TYPES_KEYS,
303 ARM_CACHE_BUS_OPERATION_TYPES_VALUES, "Unknown (Reserved)");
304 json_object_object_add(bus_error_ir, "operation", operation);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100305
Lawrence Tange407b4c2022-07-21 13:54:01 +0100306 //Affinity level of bus error, + miscellaneous fields.
307 json_object_object_add(bus_error_ir, "level",
308 json_object_new_int(bus_error->Level));
309 json_object_object_add(
310 bus_error_ir, "processorContextCorrupt",
311 json_object_new_boolean(bus_error->ProcessorContextCorrupt));
312 json_object_object_add(bus_error_ir, "corrected",
313 json_object_new_boolean(bus_error->Corrected));
314 json_object_object_add(bus_error_ir, "precisePC",
315 json_object_new_boolean(bus_error->PrecisePC));
316 json_object_object_add(
317 bus_error_ir, "restartablePC",
318 json_object_new_boolean(bus_error->RestartablePC));
319 json_object_object_add(bus_error_ir, "timedOut",
320 json_object_new_boolean(bus_error->TimeOut));
Lawrence Tang7f21db62022-07-06 11:09:39 +0100321
Lawrence Tange407b4c2022-07-21 13:54:01 +0100322 //Participation type.
323 json_object *participation_type = integer_to_readable_pair(
324 bus_error->ParticipationType, 4,
325 ARM_BUS_PARTICIPATION_TYPES_KEYS,
326 ARM_BUS_PARTICIPATION_TYPES_VALUES, "Unknown");
327 json_object_object_add(bus_error_ir, "participationType",
328 participation_type);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100329
Lawrence Tange407b4c2022-07-21 13:54:01 +0100330 //Address space.
331 json_object *address_space = integer_to_readable_pair(
332 bus_error->AddressSpace, 3, ARM_BUS_ADDRESS_SPACE_TYPES_KEYS,
333 ARM_BUS_ADDRESS_SPACE_TYPES_VALUES, "Unknown");
334 json_object_object_add(bus_error_ir, "addressSpace", address_space);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100335
Lawrence Tange407b4c2022-07-21 13:54:01 +0100336 //Memory access attributes.
337 //todo: find the specification of these in the ARM ARM
338 json_object_object_add(
339 bus_error_ir, "memoryAttributes",
340 json_object_new_int(bus_error->MemoryAddressAttributes));
Lawrence Tang7f21db62022-07-06 11:09:39 +0100341
Lawrence Tange407b4c2022-07-21 13:54:01 +0100342 //Access Mode
343 json_object *access_mode = json_object_new_object();
344 json_object_object_add(access_mode, "value",
345 json_object_new_int(bus_error->AccessMode));
346 json_object_object_add(
347 access_mode, "name",
348 json_object_new_string(bus_error->AccessMode == 0 ? "Secure" :
John Chungf8fc7052024-05-03 20:05:29 +0800349 "Normal"));
Lawrence Tange407b4c2022-07-21 13:54:01 +0100350 json_object_object_add(bus_error_ir, "accessMode", access_mode);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100351
Lawrence Tange407b4c2022-07-21 13:54:01 +0100352 return bus_error_ir;
Lawrence Tang7f21db62022-07-06 11:09:39 +0100353}
354
355//Converts a single ARM processor context block into JSON IR.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100356json_object *
357cper_arm_processor_context_to_ir(EFI_ARM_CONTEXT_INFORMATION_HEADER *header,
358 void **cur_pos)
Lawrence Tang7f21db62022-07-06 11:09:39 +0100359{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100360 json_object *context_ir = json_object_new_object();
Lawrence Tang7f21db62022-07-06 11:09:39 +0100361
Lawrence Tange407b4c2022-07-21 13:54:01 +0100362 //Version.
363 json_object_object_add(context_ir, "version",
364 json_object_new_int(header->Version));
Lawrence Tang71570a22022-07-14 11:45:28 +0100365
Lawrence Tange407b4c2022-07-21 13:54:01 +0100366 //Add the context type.
367 json_object *context_type = integer_to_readable_pair(
368 header->RegisterContextType, 9,
369 ARM_PROCESSOR_INFO_REGISTER_CONTEXT_TYPES_KEYS,
370 ARM_PROCESSOR_INFO_REGISTER_CONTEXT_TYPES_VALUES,
371 "Unknown (Reserved)");
372 json_object_object_add(context_ir, "registerContextType", context_type);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100373
Lawrence Tange407b4c2022-07-21 13:54:01 +0100374 //Register array size (bytes).
375 json_object_object_add(
376 context_ir, "registerArraySize",
377 json_object_new_uint64(header->RegisterArraySize));
Lawrence Tang7f21db62022-07-06 11:09:39 +0100378
Lawrence Tange407b4c2022-07-21 13:54:01 +0100379 //The register array itself.
380 *cur_pos = (void *)(header + 1);
381 json_object *register_array = NULL;
382 switch (header->RegisterContextType) {
383 case EFI_ARM_CONTEXT_TYPE_AARCH32_GPR:
384 register_array = uniform_struct_to_ir(
385 (UINT32 *)cur_pos,
386 sizeof(EFI_ARM_V8_AARCH32_GPR) / sizeof(UINT32),
387 ARM_AARCH32_GPR_NAMES);
388 break;
389 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL1:
390 register_array = uniform_struct_to_ir(
391 (UINT32 *)cur_pos,
392 sizeof(EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS) /
393 sizeof(UINT32),
394 ARM_AARCH32_EL1_REGISTER_NAMES);
395 break;
396 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL2:
397 register_array = uniform_struct_to_ir(
398 (UINT32 *)cur_pos,
399 sizeof(EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS) /
400 sizeof(UINT32),
401 ARM_AARCH32_EL2_REGISTER_NAMES);
402 break;
403 case EFI_ARM_CONTEXT_TYPE_AARCH32_SECURE:
404 register_array = uniform_struct_to_ir(
405 (UINT32 *)cur_pos,
406 sizeof(EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS) /
407 sizeof(UINT32),
408 ARM_AARCH32_SECURE_REGISTER_NAMES);
409 break;
410 case EFI_ARM_CONTEXT_TYPE_AARCH64_GPR:
411 register_array = uniform_struct64_to_ir(
412 (UINT64 *)cur_pos,
413 sizeof(EFI_ARM_V8_AARCH64_GPR) / sizeof(UINT64),
414 ARM_AARCH64_GPR_NAMES);
415 break;
416 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL1:
417 register_array = uniform_struct64_to_ir(
418 (UINT64 *)cur_pos,
419 sizeof(EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS) /
420 sizeof(UINT64),
421 ARM_AARCH64_EL1_REGISTER_NAMES);
422 break;
423 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL2:
424 register_array = uniform_struct64_to_ir(
425 (UINT64 *)cur_pos,
426 sizeof(EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS) /
427 sizeof(UINT64),
428 ARM_AARCH64_EL2_REGISTER_NAMES);
429 break;
430 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL3:
431 register_array = uniform_struct64_to_ir(
432 (UINT64 *)cur_pos,
433 sizeof(EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS) /
434 sizeof(UINT64),
435 ARM_AARCH64_EL3_REGISTER_NAMES);
436 break;
437 case EFI_ARM_CONTEXT_TYPE_MISC:
438 register_array = cper_arm_misc_register_array_to_ir(
439 (EFI_ARM_MISC_CONTEXT_REGISTER *)cur_pos);
440 break;
441 default:
442 //Unknown register array type, add as base64 data instead.
443 register_array = json_object_new_object();
John Chungf8fc7052024-05-03 20:05:29 +0800444 char *encoded = malloc(2 * header->RegisterArraySize);
445 size_t encoded_len = 0;
446 if (!encoded) {
447 printf("Failed to allocate encode output buffer. \n");
448 } else {
449 base64_encode((const char *)cur_pos,
450 header->RegisterArraySize, encoded,
451 &encoded_len, 0);
452 json_object_object_add(register_array, "data",
453 json_object_new_string_len(
454 encoded, encoded_len));
455 free(encoded);
456 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100457 break;
458 }
459 json_object_object_add(context_ir, "registerArray", register_array);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100460
Lawrence Tange407b4c2022-07-21 13:54:01 +0100461 //Set the current position to after the processor context structure.
462 *cur_pos = (UINT8 *)(*cur_pos) + header->RegisterArraySize;
Lawrence Tang7f21db62022-07-06 11:09:39 +0100463
Lawrence Tange407b4c2022-07-21 13:54:01 +0100464 return context_ir;
Lawrence Tang7f21db62022-07-06 11:09:39 +0100465}
466
467//Converts a single CPER ARM miscellaneous register array to JSON IR format.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100468json_object *
469cper_arm_misc_register_array_to_ir(EFI_ARM_MISC_CONTEXT_REGISTER *misc_register)
Lawrence Tang7f21db62022-07-06 11:09:39 +0100470{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100471 json_object *register_array = json_object_new_object();
472 json_object *mrs_encoding = json_object_new_object();
473 json_object_object_add(mrs_encoding, "op2",
474 json_object_new_uint64(misc_register->MrsOp2));
475 json_object_object_add(mrs_encoding, "crm",
476 json_object_new_uint64(misc_register->MrsCrm));
477 json_object_object_add(mrs_encoding, "crn",
478 json_object_new_uint64(misc_register->MrsCrn));
479 json_object_object_add(mrs_encoding, "op1",
480 json_object_new_uint64(misc_register->MrsOp1));
481 json_object_object_add(mrs_encoding, "o0",
482 json_object_new_uint64(misc_register->MrsO0));
483 json_object_object_add(register_array, "mrsEncoding", mrs_encoding);
484 json_object_object_add(register_array, "value",
485 json_object_new_uint64(misc_register->Value));
Lawrence Tang7f21db62022-07-06 11:09:39 +0100486
Lawrence Tange407b4c2022-07-21 13:54:01 +0100487 return register_array;
Lawrence Tang7cd13902022-07-13 16:59:25 +0100488}
489
490//Converts a single CPER-JSON ARM error section into CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100491void ir_section_arm_to_cper(json_object *section, FILE *out)
Lawrence Tang7cd13902022-07-13 16:59:25 +0100492{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100493 EFI_ARM_ERROR_RECORD *section_cper =
494 (EFI_ARM_ERROR_RECORD *)calloc(1, sizeof(EFI_ARM_ERROR_RECORD));
Lawrence Tang7cd13902022-07-13 16:59:25 +0100495
Lawrence Tange407b4c2022-07-21 13:54:01 +0100496 //Validation bits.
497 section_cper->ValidFields = ir_to_bitfield(
498 json_object_object_get(section, "validationBits"), 4,
499 ARM_ERROR_VALID_BITFIELD_NAMES);
Lawrence Tang7cd13902022-07-13 16:59:25 +0100500
Lawrence Tange407b4c2022-07-21 13:54:01 +0100501 //Count of error/context info structures.
502 section_cper->ErrInfoNum = json_object_get_int(
503 json_object_object_get(section, "errorInfoNum"));
504 section_cper->ContextInfoNum = json_object_get_int(
505 json_object_object_get(section, "contextInfoNum"));
Lawrence Tang7cd13902022-07-13 16:59:25 +0100506
Lawrence Tange407b4c2022-07-21 13:54:01 +0100507 //Miscellaneous raw value fields.
508 section_cper->SectionLength = json_object_get_uint64(
509 json_object_object_get(section, "sectionLength"));
510 section_cper->ErrorAffinityLevel = readable_pair_to_integer(
511 json_object_object_get(section, "errorAffinity"));
512 section_cper->MPIDR_EL1 = json_object_get_uint64(
513 json_object_object_get(section, "mpidrEl1"));
514 section_cper->MIDR_EL1 = json_object_get_uint64(
515 json_object_object_get(section, "midrEl1"));
516 section_cper->RunningState = json_object_get_boolean(
517 json_object_object_get(section, "running"));
Lawrence Tang7cd13902022-07-13 16:59:25 +0100518
Lawrence Tange407b4c2022-07-21 13:54:01 +0100519 //Optional PSCI state.
520 json_object *psci_state = json_object_object_get(section, "psciState");
John Chungf8fc7052024-05-03 20:05:29 +0800521 if (psci_state != NULL) {
Lawrence Tange407b4c2022-07-21 13:54:01 +0100522 section_cper->PsciState = json_object_get_uint64(psci_state);
John Chungf8fc7052024-05-03 20:05:29 +0800523 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100524
Lawrence Tange407b4c2022-07-21 13:54:01 +0100525 //Flush header to stream.
526 fwrite(section_cper, sizeof(EFI_ARM_ERROR_RECORD), 1, out);
527 fflush(out);
Lawrence Tang7cd13902022-07-13 16:59:25 +0100528
Lawrence Tange407b4c2022-07-21 13:54:01 +0100529 //Error info structure array.
530 json_object *error_info = json_object_object_get(section, "errorInfo");
John Chungf8fc7052024-05-03 20:05:29 +0800531 for (int i = 0; i < section_cper->ErrInfoNum; i++) {
Lawrence Tange407b4c2022-07-21 13:54:01 +0100532 ir_arm_error_info_to_cper(
533 json_object_array_get_idx(error_info, i), out);
John Chungf8fc7052024-05-03 20:05:29 +0800534 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100535
Lawrence Tange407b4c2022-07-21 13:54:01 +0100536 //Context info structure array.
537 json_object *context_info =
538 json_object_object_get(section, "contextInfo");
John Chungf8fc7052024-05-03 20:05:29 +0800539 for (int i = 0; i < section_cper->ContextInfoNum; i++) {
Lawrence Tange407b4c2022-07-21 13:54:01 +0100540 ir_arm_context_info_to_cper(
541 json_object_array_get_idx(context_info, i), out);
John Chungf8fc7052024-05-03 20:05:29 +0800542 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100543
Lawrence Tange407b4c2022-07-21 13:54:01 +0100544 //Vendor specific error info.
545 json_object *vendor_specific_info =
546 json_object_object_get(section, "vendorSpecificInfo");
547 if (vendor_specific_info != NULL) {
548 json_object *vendor_info_string =
549 json_object_object_get(vendor_specific_info, "data");
550 int vendor_specific_len =
551 json_object_get_string_len(vendor_info_string);
John Chungf8fc7052024-05-03 20:05:29 +0800552 char *decoded = malloc(vendor_specific_len);
553 size_t decoded_len = 0;
554 if (!decoded) {
555 printf("Failed to allocate decode output buffer. \n");
556 } else {
557 base64_decode(
558 json_object_get_string(vendor_info_string),
559 vendor_specific_len, decoded, &decoded_len, 0);
Lawrence Tang01e3a442022-07-20 15:14:50 +0100560
John Chungf8fc7052024-05-03 20:05:29 +0800561 //Write out to file.
562 fwrite(decoded, decoded_len, 1, out);
563 fflush(out);
564 free(decoded);
565 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100566 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100567
Lawrence Tange407b4c2022-07-21 13:54:01 +0100568 //Free remaining resources.
569 free(section_cper);
Lawrence Tang7cd13902022-07-13 16:59:25 +0100570}
571
572//Converts a single ARM error information structure into CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100573void ir_arm_error_info_to_cper(json_object *error_info, FILE *out)
Lawrence Tang7cd13902022-07-13 16:59:25 +0100574{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100575 EFI_ARM_ERROR_INFORMATION_ENTRY error_info_cper;
Lawrence Tang7cd13902022-07-13 16:59:25 +0100576
Lawrence Tange407b4c2022-07-21 13:54:01 +0100577 //Version, length.
578 error_info_cper.Version = json_object_get_int(
579 json_object_object_get(error_info, "version"));
580 error_info_cper.Length = json_object_get_int(
581 json_object_object_get(error_info, "length"));
Lawrence Tang7cd13902022-07-13 16:59:25 +0100582
Lawrence Tange407b4c2022-07-21 13:54:01 +0100583 //Validation bits.
584 error_info_cper.ValidationBits = ir_to_bitfield(
585 json_object_object_get(error_info, "validationBits"), 5,
586 ARM_ERROR_INFO_ENTRY_VALID_BITFIELD_NAMES);
Lawrence Tang7cd13902022-07-13 16:59:25 +0100587
Lawrence Tange407b4c2022-07-21 13:54:01 +0100588 //Type, multiple error.
589 error_info_cper.Type = (UINT8)readable_pair_to_integer(
590 json_object_object_get(error_info, "type"));
591 error_info_cper.MultipleError = (UINT16)readable_pair_to_integer(
592 json_object_object_get(error_info, "multipleError"));
Lawrence Tang7cd13902022-07-13 16:59:25 +0100593
Lawrence Tange407b4c2022-07-21 13:54:01 +0100594 //Flags object.
595 error_info_cper.Flags = (UINT8)ir_to_bitfield(
596 json_object_object_get(error_info, "flags"), 4,
597 ARM_ERROR_INFO_ENTRY_FLAGS_NAMES);
Lawrence Tang7cd13902022-07-13 16:59:25 +0100598
Lawrence Tange407b4c2022-07-21 13:54:01 +0100599 //Error information.
600 json_object *error_info_information =
601 json_object_object_get(error_info, "errorInformation");
602 switch (error_info_cper.Type) {
603 case ARM_ERROR_INFORMATION_TYPE_CACHE:
604 case ARM_ERROR_INFORMATION_TYPE_TLB:
605 ir_arm_error_cache_tlb_info_to_cper(
606 error_info_information,
607 &error_info_cper.ErrorInformation.CacheError);
608 break;
Lawrence Tang71570a22022-07-14 11:45:28 +0100609
Lawrence Tange407b4c2022-07-21 13:54:01 +0100610 case ARM_ERROR_INFORMATION_TYPE_BUS:
611 ir_arm_error_bus_info_to_cper(
612 error_info_information,
613 &error_info_cper.ErrorInformation.BusError);
614 break;
Lawrence Tang71570a22022-07-14 11:45:28 +0100615
Lawrence Tange407b4c2022-07-21 13:54:01 +0100616 default:
617 //Unknown error information type.
618 *((UINT64 *)&error_info_cper.ErrorInformation) =
619 json_object_get_uint64(json_object_object_get(
620 error_info_information, "data"));
621 break;
622 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100623
Lawrence Tange407b4c2022-07-21 13:54:01 +0100624 //Virtual/physical fault address.
625 error_info_cper.VirtualFaultAddress = json_object_get_uint64(
626 json_object_object_get(error_info, "virtualFaultAddress"));
627 error_info_cper.PhysicalFaultAddress = json_object_get_uint64(
628 json_object_object_get(error_info, "physicalFaultAddress"));
Lawrence Tang7cd13902022-07-13 16:59:25 +0100629
Lawrence Tange407b4c2022-07-21 13:54:01 +0100630 //Write out to stream.
631 fwrite(&error_info_cper, sizeof(EFI_ARM_ERROR_INFORMATION_ENTRY), 1,
632 out);
633 fflush(out);
Lawrence Tang7cd13902022-07-13 16:59:25 +0100634}
635
Lawrence Tang71570a22022-07-14 11:45:28 +0100636//Converts a single ARM cache/TLB error information structure into a CPER structure.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100637void ir_arm_error_cache_tlb_info_to_cper(
638 json_object *error_information,
639 EFI_ARM_CACHE_ERROR_STRUCTURE *error_info_cper)
Lawrence Tang71570a22022-07-14 11:45:28 +0100640{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100641 //Validation bits.
642 error_info_cper->ValidationBits = ir_to_bitfield(
643 json_object_object_get(error_information, "validationBits"), 7,
644 ARM_CACHE_TLB_ERROR_VALID_BITFIELD_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100645
Lawrence Tange407b4c2022-07-21 13:54:01 +0100646 //Miscellaneous value fields.
647 error_info_cper->TransactionType = readable_pair_to_integer(
648 json_object_object_get(error_information, "transactionType"));
649 error_info_cper->Operation = readable_pair_to_integer(
650 json_object_object_get(error_information, "operation"));
651 error_info_cper->Level = json_object_get_uint64(
652 json_object_object_get(error_information, "level"));
653 error_info_cper->ProcessorContextCorrupt = json_object_get_boolean(
654 json_object_object_get(error_information,
655 "processorContextCorrupt"));
656 error_info_cper->Corrected = json_object_get_boolean(
657 json_object_object_get(error_information, "corrected"));
658 error_info_cper->PrecisePC = json_object_get_boolean(
659 json_object_object_get(error_information, "precisePC"));
660 error_info_cper->RestartablePC = json_object_get_boolean(
661 json_object_object_get(error_information, "restartablePC"));
662 error_info_cper->Reserved = 0;
Lawrence Tang71570a22022-07-14 11:45:28 +0100663}
664
665//Converts a single ARM bus error information structure into a CPER structure.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100666void ir_arm_error_bus_info_to_cper(json_object *error_information,
667 EFI_ARM_BUS_ERROR_STRUCTURE *error_info_cper)
Lawrence Tang71570a22022-07-14 11:45:28 +0100668{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100669 //Validation bits.
670 error_info_cper->ValidationBits = ir_to_bitfield(
671 json_object_object_get(error_information, "validationBits"), 7,
672 ARM_BUS_ERROR_VALID_BITFIELD_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100673
Lawrence Tange407b4c2022-07-21 13:54:01 +0100674 //Miscellaneous value fields.
675 error_info_cper->TransactionType = readable_pair_to_integer(
676 json_object_object_get(error_information, "transactionType"));
677 error_info_cper->Operation = readable_pair_to_integer(
678 json_object_object_get(error_information, "operation"));
679 error_info_cper->Level = json_object_get_uint64(
680 json_object_object_get(error_information, "level"));
681 error_info_cper->ProcessorContextCorrupt = json_object_get_boolean(
682 json_object_object_get(error_information,
683 "processorContextCorrupt"));
684 error_info_cper->Corrected = json_object_get_boolean(
685 json_object_object_get(error_information, "corrected"));
686 error_info_cper->PrecisePC = json_object_get_boolean(
687 json_object_object_get(error_information, "precisePC"));
688 error_info_cper->RestartablePC = json_object_get_boolean(
689 json_object_object_get(error_information, "restartablePC"));
690 error_info_cper->ParticipationType = readable_pair_to_integer(
691 json_object_object_get(error_information, "participationType"));
692 error_info_cper->AddressSpace = readable_pair_to_integer(
693 json_object_object_get(error_information, "addressSpace"));
694 error_info_cper->AccessMode = readable_pair_to_integer(
695 json_object_object_get(error_information, "accessMode"));
696 error_info_cper->MemoryAddressAttributes = json_object_get_uint64(
697 json_object_object_get(error_information, "memoryAttributes"));
698 error_info_cper->Reserved = 0;
Lawrence Tang71570a22022-07-14 11:45:28 +0100699}
700
Lawrence Tang7cd13902022-07-13 16:59:25 +0100701//Converts a single ARM context information structure into CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100702void ir_arm_context_info_to_cper(json_object *context_info, FILE *out)
Lawrence Tang7cd13902022-07-13 16:59:25 +0100703{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100704 EFI_ARM_CONTEXT_INFORMATION_HEADER info_header;
Lawrence Tang7cd13902022-07-13 16:59:25 +0100705
Lawrence Tange407b4c2022-07-21 13:54:01 +0100706 //Version, array size, context type.
707 info_header.Version = json_object_get_int(
708 json_object_object_get(context_info, "version"));
709 info_header.RegisterArraySize = json_object_get_int(
710 json_object_object_get(context_info, "registerArraySize"));
711 info_header.RegisterContextType = readable_pair_to_integer(
712 json_object_object_get(context_info, "registerContextType"));
Lawrence Tang71570a22022-07-14 11:45:28 +0100713
Lawrence Tange407b4c2022-07-21 13:54:01 +0100714 //Flush to stream, write the register array itself.
715 fwrite(&info_header, sizeof(EFI_ARM_CONTEXT_INFORMATION_HEADER), 1,
716 out);
717 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100718
Lawrence Tange407b4c2022-07-21 13:54:01 +0100719 json_object *register_array =
720 json_object_object_get(context_info, "registerArray");
721 switch (info_header.RegisterContextType) {
722 case EFI_ARM_CONTEXT_TYPE_AARCH32_GPR:
723 ir_arm_aarch32_gpr_to_cper(register_array, out);
724 break;
725 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL1:
726 ir_arm_aarch32_el1_to_cper(register_array, out);
727 break;
728 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL2:
729 ir_arm_aarch32_el2_to_cper(register_array, out);
730 break;
731 case EFI_ARM_CONTEXT_TYPE_AARCH32_SECURE:
732 ir_arm_aarch32_secure_to_cper(register_array, out);
733 break;
734 case EFI_ARM_CONTEXT_TYPE_AARCH64_GPR:
735 ir_arm_aarch64_gpr_to_cper(register_array, out);
736 break;
737 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL1:
738 ir_arm_aarch64_el1_to_cper(register_array, out);
739 break;
740 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL2:
741 ir_arm_aarch64_el2_to_cper(register_array, out);
742 break;
743 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL3:
744 ir_arm_aarch64_el3_to_cper(register_array, out);
745 break;
746 case EFI_ARM_CONTEXT_TYPE_MISC:
747 ir_arm_misc_registers_to_cper(register_array, out);
748 break;
749 default:
750 //Unknown register structure.
John Chungf8fc7052024-05-03 20:05:29 +0800751 ir_arm_unknown_register_to_cper(register_array, out);
Lawrence Tange407b4c2022-07-21 13:54:01 +0100752 break;
753 }
Lawrence Tang71570a22022-07-14 11:45:28 +0100754}
755
756//Converts a single AARCH32 GPR CPER-JSON object to CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100757void ir_arm_aarch32_gpr_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100758{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100759 //Get uniform register array.
760 EFI_ARM_V8_AARCH32_GPR reg_array;
761 ir_to_uniform_struct(registers, (UINT32 *)&reg_array,
762 sizeof(EFI_ARM_V8_AARCH32_GPR) / sizeof(UINT32),
763 ARM_AARCH32_GPR_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100764
Lawrence Tange407b4c2022-07-21 13:54:01 +0100765 //Flush to stream.
766 fwrite(&reg_array, sizeof(reg_array), 1, out);
767 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100768}
769
770//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 +0100771void ir_arm_aarch32_el1_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100772{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100773 //Get uniform register array.
774 EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS reg_array;
775 ir_to_uniform_struct(registers, (UINT32 *)&reg_array,
776 sizeof(EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS) /
777 sizeof(UINT32),
778 ARM_AARCH32_EL1_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100779
Lawrence Tange407b4c2022-07-21 13:54:01 +0100780 //Flush to stream.
781 fwrite(&reg_array, sizeof(reg_array), 1, out);
782 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100783}
784
785//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 +0100786void ir_arm_aarch32_el2_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100787{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100788 //Get uniform register array.
789 EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS reg_array;
790 ir_to_uniform_struct(registers, (UINT32 *)&reg_array,
791 sizeof(EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS) /
792 sizeof(UINT32),
793 ARM_AARCH32_EL2_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100794
Lawrence Tange407b4c2022-07-21 13:54:01 +0100795 //Flush to stream.
796 fwrite(&reg_array, sizeof(reg_array), 1, out);
797 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100798}
799
800//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 +0100801void ir_arm_aarch32_secure_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100802{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100803 //Get uniform register array.
804 EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS reg_array;
805 ir_to_uniform_struct(registers, (UINT32 *)&reg_array,
806 sizeof(EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS) /
807 sizeof(UINT32),
808 ARM_AARCH32_SECURE_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100809
Lawrence Tange407b4c2022-07-21 13:54:01 +0100810 //Flush to stream.
811 fwrite(&reg_array, sizeof(reg_array), 1, out);
812 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100813}
814
815//Converts a single AARCH64 GPR CPER-JSON object to CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100816void ir_arm_aarch64_gpr_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100817{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100818 //Get uniform register array.
819 EFI_ARM_V8_AARCH64_GPR reg_array;
820 ir_to_uniform_struct64(registers, (UINT64 *)&reg_array,
821 sizeof(EFI_ARM_V8_AARCH64_GPR) / sizeof(UINT64),
822 ARM_AARCH64_GPR_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100823
Lawrence Tange407b4c2022-07-21 13:54:01 +0100824 //Flush to stream.
825 fwrite(&reg_array, sizeof(reg_array), 1, out);
826 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100827}
828
829//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 +0100830void ir_arm_aarch64_el1_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100831{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100832 //Get uniform register array.
833 EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS reg_array;
834 ir_to_uniform_struct64(registers, (UINT64 *)&reg_array,
835 sizeof(EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS) /
836 sizeof(UINT64),
837 ARM_AARCH64_EL1_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100838
Lawrence Tange407b4c2022-07-21 13:54:01 +0100839 //Flush to stream.
840 fwrite(&reg_array, sizeof(reg_array), 1, out);
841 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100842}
843
844//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 +0100845void ir_arm_aarch64_el2_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100846{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100847 //Get uniform register array.
848 EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS reg_array;
849 ir_to_uniform_struct64(registers, (UINT64 *)&reg_array,
850 sizeof(EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS) /
851 sizeof(UINT64),
852 ARM_AARCH64_EL2_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100853
Lawrence Tange407b4c2022-07-21 13:54:01 +0100854 //Flush to stream.
855 fwrite(&reg_array, sizeof(reg_array), 1, out);
856 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100857}
858
859//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 +0100860void ir_arm_aarch64_el3_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100861{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100862 //Get uniform register array.
863 EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS reg_array;
864 ir_to_uniform_struct64(registers, (UINT64 *)&reg_array,
865 sizeof(EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS) /
866 sizeof(UINT64),
867 ARM_AARCH64_EL3_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100868
Lawrence Tange407b4c2022-07-21 13:54:01 +0100869 //Flush to stream.
870 fwrite(&reg_array, sizeof(reg_array), 1, out);
871 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100872}
873
874//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 +0100875void ir_arm_misc_registers_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100876{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100877 EFI_ARM_MISC_CONTEXT_REGISTER reg_array;
Lawrence Tang71570a22022-07-14 11:45:28 +0100878
Lawrence Tange407b4c2022-07-21 13:54:01 +0100879 //MRS encoding information.
880 json_object *mrs_encoding =
881 json_object_object_get(registers, "mrsEncoding");
882 reg_array.MrsOp2 = json_object_get_uint64(
883 json_object_object_get(mrs_encoding, "op2"));
884 reg_array.MrsCrm = json_object_get_uint64(
885 json_object_object_get(mrs_encoding, "crm"));
886 reg_array.MrsCrn = json_object_get_uint64(
887 json_object_object_get(mrs_encoding, "crn"));
888 reg_array.MrsOp1 = json_object_get_uint64(
889 json_object_object_get(mrs_encoding, "op1"));
890 reg_array.MrsO0 = json_object_get_uint64(
891 json_object_object_get(mrs_encoding, "o0"));
Lawrence Tang71570a22022-07-14 11:45:28 +0100892
Lawrence Tange407b4c2022-07-21 13:54:01 +0100893 //Actual register value.
894 reg_array.Value = json_object_get_uint64(
895 json_object_object_get(registers, "value"));
Lawrence Tang71570a22022-07-14 11:45:28 +0100896
Lawrence Tange407b4c2022-07-21 13:54:01 +0100897 //Flush to stream.
898 fwrite(&reg_array, sizeof(reg_array), 1, out);
899 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100900}
901
902//Converts a single ARM unknown register CPER-JSON object to CPER binary, outputting to the given stream.
John Chungf8fc7052024-05-03 20:05:29 +0800903void ir_arm_unknown_register_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100904{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100905 //Get base64 represented data.
906 json_object *encoded = json_object_object_get(registers, "data");
John Chungf8fc7052024-05-03 20:05:29 +0800907 char *decoded = malloc(json_object_get_string_len(encoded));
908 size_t decoded_len = 0;
909 if (!decoded) {
910 printf("Failed to allocate decode output buffer. \n");
911 } else {
912 base64_decode(json_object_get_string(encoded),
913 json_object_get_string_len(encoded), decoded,
914 &decoded_len, 0);
Lawrence Tang71570a22022-07-14 11:45:28 +0100915
John Chungf8fc7052024-05-03 20:05:29 +0800916 //Flush out to stream.
917 fwrite(&decoded, decoded_len, 1, out);
918 fflush(out);
919 free(decoded);
920 }
921}