blob: 988a5c9e84024aebbbb72832cf51dcb60e5aea87 [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(
John Chung0b9c9402024-05-22 22:52:55 +0800206 error_info->ErrorInformation.Value));
Lawrence Tange407b4c2022-07-21 13:54:01 +0100207 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.
John Chung0b9c9402024-05-22 22:52:55 +0800618 error_info_cper.ErrorInformation.Value = json_object_get_uint64(
619 json_object_object_get(error_info_information, "data"));
Lawrence Tange407b4c2022-07-21 13:54:01 +0100620 break;
621 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100622
Lawrence Tange407b4c2022-07-21 13:54:01 +0100623 //Virtual/physical fault address.
624 error_info_cper.VirtualFaultAddress = json_object_get_uint64(
625 json_object_object_get(error_info, "virtualFaultAddress"));
626 error_info_cper.PhysicalFaultAddress = json_object_get_uint64(
627 json_object_object_get(error_info, "physicalFaultAddress"));
Lawrence Tang7cd13902022-07-13 16:59:25 +0100628
Lawrence Tange407b4c2022-07-21 13:54:01 +0100629 //Write out to stream.
630 fwrite(&error_info_cper, sizeof(EFI_ARM_ERROR_INFORMATION_ENTRY), 1,
631 out);
632 fflush(out);
Lawrence Tang7cd13902022-07-13 16:59:25 +0100633}
634
Lawrence Tang71570a22022-07-14 11:45:28 +0100635//Converts a single ARM cache/TLB error information structure into a CPER structure.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100636void ir_arm_error_cache_tlb_info_to_cper(
637 json_object *error_information,
638 EFI_ARM_CACHE_ERROR_STRUCTURE *error_info_cper)
Lawrence Tang71570a22022-07-14 11:45:28 +0100639{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100640 //Validation bits.
641 error_info_cper->ValidationBits = ir_to_bitfield(
642 json_object_object_get(error_information, "validationBits"), 7,
643 ARM_CACHE_TLB_ERROR_VALID_BITFIELD_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100644
Lawrence Tange407b4c2022-07-21 13:54:01 +0100645 //Miscellaneous value fields.
646 error_info_cper->TransactionType = readable_pair_to_integer(
647 json_object_object_get(error_information, "transactionType"));
648 error_info_cper->Operation = readable_pair_to_integer(
649 json_object_object_get(error_information, "operation"));
650 error_info_cper->Level = json_object_get_uint64(
651 json_object_object_get(error_information, "level"));
652 error_info_cper->ProcessorContextCorrupt = json_object_get_boolean(
653 json_object_object_get(error_information,
654 "processorContextCorrupt"));
655 error_info_cper->Corrected = json_object_get_boolean(
656 json_object_object_get(error_information, "corrected"));
657 error_info_cper->PrecisePC = json_object_get_boolean(
658 json_object_object_get(error_information, "precisePC"));
659 error_info_cper->RestartablePC = json_object_get_boolean(
660 json_object_object_get(error_information, "restartablePC"));
661 error_info_cper->Reserved = 0;
Lawrence Tang71570a22022-07-14 11:45:28 +0100662}
663
664//Converts a single ARM bus error information structure into a CPER structure.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100665void ir_arm_error_bus_info_to_cper(json_object *error_information,
666 EFI_ARM_BUS_ERROR_STRUCTURE *error_info_cper)
Lawrence Tang71570a22022-07-14 11:45:28 +0100667{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100668 //Validation bits.
669 error_info_cper->ValidationBits = ir_to_bitfield(
670 json_object_object_get(error_information, "validationBits"), 7,
671 ARM_BUS_ERROR_VALID_BITFIELD_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100672
Lawrence Tange407b4c2022-07-21 13:54:01 +0100673 //Miscellaneous value fields.
674 error_info_cper->TransactionType = readable_pair_to_integer(
675 json_object_object_get(error_information, "transactionType"));
676 error_info_cper->Operation = readable_pair_to_integer(
677 json_object_object_get(error_information, "operation"));
678 error_info_cper->Level = json_object_get_uint64(
679 json_object_object_get(error_information, "level"));
680 error_info_cper->ProcessorContextCorrupt = json_object_get_boolean(
681 json_object_object_get(error_information,
682 "processorContextCorrupt"));
683 error_info_cper->Corrected = json_object_get_boolean(
684 json_object_object_get(error_information, "corrected"));
685 error_info_cper->PrecisePC = json_object_get_boolean(
686 json_object_object_get(error_information, "precisePC"));
687 error_info_cper->RestartablePC = json_object_get_boolean(
688 json_object_object_get(error_information, "restartablePC"));
689 error_info_cper->ParticipationType = readable_pair_to_integer(
690 json_object_object_get(error_information, "participationType"));
691 error_info_cper->AddressSpace = readable_pair_to_integer(
692 json_object_object_get(error_information, "addressSpace"));
693 error_info_cper->AccessMode = readable_pair_to_integer(
694 json_object_object_get(error_information, "accessMode"));
695 error_info_cper->MemoryAddressAttributes = json_object_get_uint64(
696 json_object_object_get(error_information, "memoryAttributes"));
697 error_info_cper->Reserved = 0;
Lawrence Tang71570a22022-07-14 11:45:28 +0100698}
699
Lawrence Tang7cd13902022-07-13 16:59:25 +0100700//Converts a single ARM context information structure into CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100701void ir_arm_context_info_to_cper(json_object *context_info, FILE *out)
Lawrence Tang7cd13902022-07-13 16:59:25 +0100702{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100703 EFI_ARM_CONTEXT_INFORMATION_HEADER info_header;
Lawrence Tang7cd13902022-07-13 16:59:25 +0100704
Lawrence Tange407b4c2022-07-21 13:54:01 +0100705 //Version, array size, context type.
706 info_header.Version = json_object_get_int(
707 json_object_object_get(context_info, "version"));
708 info_header.RegisterArraySize = json_object_get_int(
709 json_object_object_get(context_info, "registerArraySize"));
710 info_header.RegisterContextType = readable_pair_to_integer(
711 json_object_object_get(context_info, "registerContextType"));
Lawrence Tang71570a22022-07-14 11:45:28 +0100712
Lawrence Tange407b4c2022-07-21 13:54:01 +0100713 //Flush to stream, write the register array itself.
714 fwrite(&info_header, sizeof(EFI_ARM_CONTEXT_INFORMATION_HEADER), 1,
715 out);
716 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100717
Lawrence Tange407b4c2022-07-21 13:54:01 +0100718 json_object *register_array =
719 json_object_object_get(context_info, "registerArray");
720 switch (info_header.RegisterContextType) {
721 case EFI_ARM_CONTEXT_TYPE_AARCH32_GPR:
722 ir_arm_aarch32_gpr_to_cper(register_array, out);
723 break;
724 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL1:
725 ir_arm_aarch32_el1_to_cper(register_array, out);
726 break;
727 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL2:
728 ir_arm_aarch32_el2_to_cper(register_array, out);
729 break;
730 case EFI_ARM_CONTEXT_TYPE_AARCH32_SECURE:
731 ir_arm_aarch32_secure_to_cper(register_array, out);
732 break;
733 case EFI_ARM_CONTEXT_TYPE_AARCH64_GPR:
734 ir_arm_aarch64_gpr_to_cper(register_array, out);
735 break;
736 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL1:
737 ir_arm_aarch64_el1_to_cper(register_array, out);
738 break;
739 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL2:
740 ir_arm_aarch64_el2_to_cper(register_array, out);
741 break;
742 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL3:
743 ir_arm_aarch64_el3_to_cper(register_array, out);
744 break;
745 case EFI_ARM_CONTEXT_TYPE_MISC:
746 ir_arm_misc_registers_to_cper(register_array, out);
747 break;
748 default:
749 //Unknown register structure.
John Chungf8fc7052024-05-03 20:05:29 +0800750 ir_arm_unknown_register_to_cper(register_array, out);
Lawrence Tange407b4c2022-07-21 13:54:01 +0100751 break;
752 }
Lawrence Tang71570a22022-07-14 11:45:28 +0100753}
754
755//Converts a single AARCH32 GPR CPER-JSON object to CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100756void ir_arm_aarch32_gpr_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100757{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100758 //Get uniform register array.
759 EFI_ARM_V8_AARCH32_GPR reg_array;
760 ir_to_uniform_struct(registers, (UINT32 *)&reg_array,
761 sizeof(EFI_ARM_V8_AARCH32_GPR) / sizeof(UINT32),
762 ARM_AARCH32_GPR_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100763
Lawrence Tange407b4c2022-07-21 13:54:01 +0100764 //Flush to stream.
765 fwrite(&reg_array, sizeof(reg_array), 1, out);
766 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100767}
768
769//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 +0100770void ir_arm_aarch32_el1_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100771{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100772 //Get uniform register array.
773 EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS reg_array;
774 ir_to_uniform_struct(registers, (UINT32 *)&reg_array,
775 sizeof(EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS) /
776 sizeof(UINT32),
777 ARM_AARCH32_EL1_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100778
Lawrence Tange407b4c2022-07-21 13:54:01 +0100779 //Flush to stream.
780 fwrite(&reg_array, sizeof(reg_array), 1, out);
781 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100782}
783
784//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 +0100785void ir_arm_aarch32_el2_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100786{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100787 //Get uniform register array.
788 EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS reg_array;
789 ir_to_uniform_struct(registers, (UINT32 *)&reg_array,
790 sizeof(EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS) /
791 sizeof(UINT32),
792 ARM_AARCH32_EL2_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100793
Lawrence Tange407b4c2022-07-21 13:54:01 +0100794 //Flush to stream.
795 fwrite(&reg_array, sizeof(reg_array), 1, out);
796 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100797}
798
799//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 +0100800void ir_arm_aarch32_secure_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100801{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100802 //Get uniform register array.
803 EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS reg_array;
804 ir_to_uniform_struct(registers, (UINT32 *)&reg_array,
805 sizeof(EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS) /
806 sizeof(UINT32),
807 ARM_AARCH32_SECURE_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100808
Lawrence Tange407b4c2022-07-21 13:54:01 +0100809 //Flush to stream.
810 fwrite(&reg_array, sizeof(reg_array), 1, out);
811 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100812}
813
814//Converts a single AARCH64 GPR CPER-JSON object to CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100815void ir_arm_aarch64_gpr_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100816{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100817 //Get uniform register array.
818 EFI_ARM_V8_AARCH64_GPR reg_array;
819 ir_to_uniform_struct64(registers, (UINT64 *)&reg_array,
820 sizeof(EFI_ARM_V8_AARCH64_GPR) / sizeof(UINT64),
821 ARM_AARCH64_GPR_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100822
Lawrence Tange407b4c2022-07-21 13:54:01 +0100823 //Flush to stream.
824 fwrite(&reg_array, sizeof(reg_array), 1, out);
825 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100826}
827
828//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 +0100829void ir_arm_aarch64_el1_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100830{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100831 //Get uniform register array.
832 EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS reg_array;
833 ir_to_uniform_struct64(registers, (UINT64 *)&reg_array,
834 sizeof(EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS) /
835 sizeof(UINT64),
836 ARM_AARCH64_EL1_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100837
Lawrence Tange407b4c2022-07-21 13:54:01 +0100838 //Flush to stream.
839 fwrite(&reg_array, sizeof(reg_array), 1, out);
840 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100841}
842
843//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 +0100844void ir_arm_aarch64_el2_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100845{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100846 //Get uniform register array.
847 EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS reg_array;
848 ir_to_uniform_struct64(registers, (UINT64 *)&reg_array,
849 sizeof(EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS) /
850 sizeof(UINT64),
851 ARM_AARCH64_EL2_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100852
Lawrence Tange407b4c2022-07-21 13:54:01 +0100853 //Flush to stream.
854 fwrite(&reg_array, sizeof(reg_array), 1, out);
855 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100856}
857
858//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 +0100859void ir_arm_aarch64_el3_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100860{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100861 //Get uniform register array.
862 EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS reg_array;
863 ir_to_uniform_struct64(registers, (UINT64 *)&reg_array,
864 sizeof(EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS) /
865 sizeof(UINT64),
866 ARM_AARCH64_EL3_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100867
Lawrence Tange407b4c2022-07-21 13:54:01 +0100868 //Flush to stream.
869 fwrite(&reg_array, sizeof(reg_array), 1, out);
870 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100871}
872
873//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 +0100874void ir_arm_misc_registers_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100875{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100876 EFI_ARM_MISC_CONTEXT_REGISTER reg_array;
Lawrence Tang71570a22022-07-14 11:45:28 +0100877
Lawrence Tange407b4c2022-07-21 13:54:01 +0100878 //MRS encoding information.
879 json_object *mrs_encoding =
880 json_object_object_get(registers, "mrsEncoding");
881 reg_array.MrsOp2 = json_object_get_uint64(
882 json_object_object_get(mrs_encoding, "op2"));
883 reg_array.MrsCrm = json_object_get_uint64(
884 json_object_object_get(mrs_encoding, "crm"));
885 reg_array.MrsCrn = json_object_get_uint64(
886 json_object_object_get(mrs_encoding, "crn"));
887 reg_array.MrsOp1 = json_object_get_uint64(
888 json_object_object_get(mrs_encoding, "op1"));
889 reg_array.MrsO0 = json_object_get_uint64(
890 json_object_object_get(mrs_encoding, "o0"));
Lawrence Tang71570a22022-07-14 11:45:28 +0100891
Lawrence Tange407b4c2022-07-21 13:54:01 +0100892 //Actual register value.
893 reg_array.Value = json_object_get_uint64(
894 json_object_object_get(registers, "value"));
Lawrence Tang71570a22022-07-14 11:45:28 +0100895
Lawrence Tange407b4c2022-07-21 13:54:01 +0100896 //Flush to stream.
897 fwrite(&reg_array, sizeof(reg_array), 1, out);
898 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100899}
900
901//Converts a single ARM unknown register CPER-JSON object to CPER binary, outputting to the given stream.
John Chungf8fc7052024-05-03 20:05:29 +0800902void ir_arm_unknown_register_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100903{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100904 //Get base64 represented data.
905 json_object *encoded = json_object_object_get(registers, "data");
John Chungf8fc7052024-05-03 20:05:29 +0800906 char *decoded = malloc(json_object_get_string_len(encoded));
907 size_t decoded_len = 0;
908 if (!decoded) {
909 printf("Failed to allocate decode output buffer. \n");
910 } else {
911 base64_decode(json_object_get_string(encoded),
912 json_object_get_string_len(encoded), decoded,
913 &decoded_len, 0);
Lawrence Tang71570a22022-07-14 11:45:28 +0100914
John Chungf8fc7052024-05-03 20:05:29 +0800915 //Flush out to stream.
916 fwrite(&decoded, decoded_len, 1, out);
917 fflush(out);
918 free(decoded);
919 }
920}