blob: b07c829823e7f0f68129c350dd7d7662c1511d6b [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.
Ed Tanousfedd4572024-07-12 13:56:00 -07004 *
Lawrence Tang2800cd82022-07-05 16:08:20 +01005 * Author: Lawrence.Tang@arm.com
6 **/
7
8#include <stdio.h>
Lawrence Tang5202bbb2022-08-12 14:54:36 +01009#include <json.h>
Thu Nguyene42fb482024-10-15 14:43:11 +000010#include <libcper/base64.h>
11#include <libcper/Cper.h>
12#include <libcper/cper-utils.h>
13#include <libcper/sections/cper-section-arm.h>
Lawrence Tang2800cd82022-07-05 16:08:20 +010014
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).
Aushim Nagarkatti17bc66a2024-11-25 13:47:35 -080076 uint64_t sock;
77 uint64_t mpidr_eli1 = record->MPIDR_EL1;
Lawrence Tange407b4c2022-07-21 13:54:01 +010078 json_object_object_add(section_ir, "mpidrEl1",
Aushim Nagarkatti17bc66a2024-11-25 13:47:35 -080079 json_object_new_uint64(mpidr_eli1));
80 //Arm Processor socket info
81 sock = (mpidr_eli1 & ARM_SOCK_MASK) >> 32;
82 json_object_object_add(section_ir, "affinity3",
83 json_object_new_uint64(sock));
84
Lawrence Tange407b4c2022-07-21 13:54:01 +010085 json_object_object_add(section_ir, "midrEl1",
86 json_object_new_uint64(record->MIDR_EL1));
Lawrence Tang2800cd82022-07-05 16:08:20 +010087
Lawrence Tange407b4c2022-07-21 13:54:01 +010088 //Whether the processor is running, and the state of it if so.
89 json_object_object_add(section_ir, "running",
90 json_object_new_boolean(record->RunningState &
John Chungf8fc7052024-05-03 20:05:29 +080091 0x1));
Lawrence Tange407b4c2022-07-21 13:54:01 +010092 if (!(record->RunningState >> 31)) {
93 //Bit 32 of running state is on, so PSCI state information is included.
94 //This can't be made human readable, as it is unknown whether this will be the pre-PSCI 1.0 format
95 //or the newer Extended StateID format.
96 json_object_object_add(
97 section_ir, "psciState",
98 json_object_new_uint64(record->PsciState));
99 }
Lawrence Tang7f21db62022-07-06 11:09:39 +0100100
Lawrence Tange407b4c2022-07-21 13:54:01 +0100101 //Processor error structures.
102 json_object *error_info_array = json_object_new_array();
103 EFI_ARM_ERROR_INFORMATION_ENTRY *cur_error =
104 (EFI_ARM_ERROR_INFORMATION_ENTRY *)(record + 1);
105 for (int i = 0; i < record->ErrInfoNum; i++) {
106 json_object_array_add(error_info_array,
107 cper_arm_error_info_to_ir(cur_error));
108 cur_error++;
109 }
110 json_object_object_add(section_ir, "errorInfo", error_info_array);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100111
Lawrence Tange407b4c2022-07-21 13:54:01 +0100112 //Processor context structures.
113 //The current position is moved within the processing, as it is a dynamic size structure.
John Chungf8fc7052024-05-03 20:05:29 +0800114 uint8_t *cur_pos = (uint8_t *)cur_error;
Lawrence Tange407b4c2022-07-21 13:54:01 +0100115 json_object *context_info_array = json_object_new_array();
116 for (int i = 0; i < record->ContextInfoNum; i++) {
117 EFI_ARM_CONTEXT_INFORMATION_HEADER *header =
118 (EFI_ARM_CONTEXT_INFORMATION_HEADER *)cur_pos;
119 json_object *processor_context =
John Chungf8fc7052024-05-03 20:05:29 +0800120 cper_arm_processor_context_to_ir(header,
121 (void **)&cur_pos);
Lawrence Tange407b4c2022-07-21 13:54:01 +0100122 json_object_array_add(context_info_array, processor_context);
123 }
124 json_object_object_add(section_ir, "contextInfo", context_info_array);
Lawrence Tangd7e8ca32022-07-07 10:25:53 +0100125
Lawrence Tange407b4c2022-07-21 13:54:01 +0100126 //Is there any vendor-specific information following?
John Chungf8fc7052024-05-03 20:05:29 +0800127 if (cur_pos < (uint8_t *)section + record->SectionLength) {
Lawrence Tange407b4c2022-07-21 13:54:01 +0100128 json_object *vendor_specific = json_object_new_object();
John Chungf8fc7052024-05-03 20:05:29 +0800129 size_t input_size =
130 (uint8_t *)section + record->SectionLength - cur_pos;
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700131 int32_t encoded_len = 0;
132 char *encoded =
133 base64_encode(cur_pos, input_size, &encoded_len);
134 if (encoded == NULL) {
135 return NULL;
John Chungf8fc7052024-05-03 20:05:29 +0800136 }
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700137 json_object_object_add(vendor_specific, "data",
138 json_object_new_string_len(encoded,
139 encoded_len));
140 free(encoded);
141
142 json_object_object_add(section_ir, "vendorSpecificInfo",
143 vendor_specific);
Lawrence Tange407b4c2022-07-21 13:54:01 +0100144 }
145
146 return section_ir;
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100147}
148
149//Converts a single ARM Process Error Information structure into JSON IR.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100150json_object *
151cper_arm_error_info_to_ir(EFI_ARM_ERROR_INFORMATION_ENTRY *error_info)
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100152{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100153 json_object *error_info_ir = json_object_new_object();
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100154
Lawrence Tange407b4c2022-07-21 13:54:01 +0100155 //Version, length.
156 json_object_object_add(error_info_ir, "version",
157 json_object_new_int(error_info->Version));
158 json_object_object_add(error_info_ir, "length",
159 json_object_new_int(error_info->Length));
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100160
Lawrence Tange407b4c2022-07-21 13:54:01 +0100161 //Validation bitfield.
162 json_object *validation =
163 bitfield_to_ir(error_info->ValidationBits, 5,
164 ARM_ERROR_INFO_ENTRY_VALID_BITFIELD_NAMES);
165 json_object_object_add(error_info_ir, "validationBits", validation);
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100166
Lawrence Tange407b4c2022-07-21 13:54:01 +0100167 //The type of error information in this log.
168 json_object *error_type = integer_to_readable_pair(
169 error_info->Type, 4, ARM_ERROR_INFO_ENTRY_INFO_TYPES_KEYS,
170 ARM_ERROR_INFO_ENTRY_INFO_TYPES_VALUES, "Unknown (Reserved)");
171 json_object_object_add(error_info_ir, "errorType", error_type);
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100172
Lawrence Tange407b4c2022-07-21 13:54:01 +0100173 //Multiple error count.
174 json_object *multiple_error = json_object_new_object();
175 json_object_object_add(multiple_error, "value",
176 json_object_new_int(error_info->MultipleError));
177 json_object_object_add(
178 multiple_error, "type",
179 json_object_new_string(error_info->MultipleError < 1 ?
John Chungf8fc7052024-05-03 20:05:29 +0800180 "Single Error" :
181 "Multiple Errors"));
Lawrence Tange407b4c2022-07-21 13:54:01 +0100182 json_object_object_add(error_info_ir, "multipleError", multiple_error);
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100183
Lawrence Tange407b4c2022-07-21 13:54:01 +0100184 //Flags.
185 json_object *flags = bitfield_to_ir(error_info->Flags, 4,
186 ARM_ERROR_INFO_ENTRY_FLAGS_NAMES);
187 json_object_object_add(error_info_ir, "flags", flags);
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100188
Lawrence Tange407b4c2022-07-21 13:54:01 +0100189 //Error information, split by type.
190 json_object *error_subinfo = NULL;
191 switch (error_info->Type) {
192 case ARM_ERROR_INFORMATION_TYPE_CACHE: //Cache
John Chungf8fc7052024-05-03 20:05:29 +0800193 case ARM_ERROR_INFORMATION_TYPE_TLB: //TLB
Lawrence Tange407b4c2022-07-21 13:54:01 +0100194 error_subinfo = cper_arm_cache_tlb_error_to_ir(
195 (EFI_ARM_CACHE_ERROR_STRUCTURE *)&error_info
196 ->ErrorInformation,
197 error_info);
198 break;
199 case ARM_ERROR_INFORMATION_TYPE_BUS: //Bus
200 error_subinfo = cper_arm_bus_error_to_ir(
201 (EFI_ARM_BUS_ERROR_STRUCTURE *)&error_info
202 ->ErrorInformation);
203 break;
Lawrence Tang71570a22022-07-14 11:45:28 +0100204
Lawrence Tange407b4c2022-07-21 13:54:01 +0100205 default:
Aushim Nagarkatti5b793002024-09-26 17:07:30 -0700206 //Unknown/microarch, will not support.
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();
Aushim Nagarkatti5b793002024-09-26 17:07:30 -0700229 json_object *cache_tlb_prop = json_object_new_object();
230 char *cache_tlb_propname;
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100231
Lawrence Tange407b4c2022-07-21 13:54:01 +0100232 //Validation bitfield.
233 json_object *validation =
234 bitfield_to_ir(cache_tlb_error->ValidationBits, 7,
235 ARM_CACHE_TLB_ERROR_VALID_BITFIELD_NAMES);
236 json_object_object_add(cache_tlb_error_ir, "validationBits",
237 validation);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100238
Lawrence Tange407b4c2022-07-21 13:54:01 +0100239 //Transaction type.
240 json_object *transaction_type = integer_to_readable_pair(
241 cache_tlb_error->TransactionType, 3,
242 ARM_ERROR_TRANSACTION_TYPES_KEYS,
243 ARM_ERROR_TRANSACTION_TYPES_VALUES, "Unknown (Reserved)");
244 json_object_object_add(cache_tlb_error_ir, "transactionType",
245 transaction_type);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100246
Lawrence Tange407b4c2022-07-21 13:54:01 +0100247 //Operation.
248 json_object *operation;
249 if (error_info->Type == 0) {
250 //Cache operation.
251 operation = integer_to_readable_pair(
252 cache_tlb_error->Operation, 11,
253 ARM_CACHE_BUS_OPERATION_TYPES_KEYS,
254 ARM_CACHE_BUS_OPERATION_TYPES_VALUES,
255 "Unknown (Reserved)");
Aushim Nagarkatti5b793002024-09-26 17:07:30 -0700256 cache_tlb_propname = "cacheError";
Lawrence Tange407b4c2022-07-21 13:54:01 +0100257 } else {
258 //TLB operation.
259 operation = integer_to_readable_pair(
260 cache_tlb_error->Operation, 9,
261 ARM_TLB_OPERATION_TYPES_KEYS,
262 ARM_TLB_OPERATION_TYPES_VALUES, "Unknown (Reserved)");
Aushim Nagarkatti5b793002024-09-26 17:07:30 -0700263 cache_tlb_propname = "tlbError";
Lawrence Tange407b4c2022-07-21 13:54:01 +0100264 }
265 json_object_object_add(cache_tlb_error_ir, "operation", operation);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100266
Lawrence Tange407b4c2022-07-21 13:54:01 +0100267 //Miscellaneous remaining fields.
268 json_object_object_add(cache_tlb_error_ir, "level",
269 json_object_new_int(cache_tlb_error->Level));
270 json_object_object_add(
271 cache_tlb_error_ir, "processorContextCorrupt",
272 json_object_new_boolean(
273 cache_tlb_error->ProcessorContextCorrupt));
274 json_object_object_add(
275 cache_tlb_error_ir, "corrected",
276 json_object_new_boolean(cache_tlb_error->Corrected));
277 json_object_object_add(
278 cache_tlb_error_ir, "precisePC",
279 json_object_new_boolean(cache_tlb_error->PrecisePC));
280 json_object_object_add(
281 cache_tlb_error_ir, "restartablePC",
282 json_object_new_boolean(cache_tlb_error->RestartablePC));
Aushim Nagarkatti5b793002024-09-26 17:07:30 -0700283
284 json_object_object_add(cache_tlb_prop, cache_tlb_propname,
285 cache_tlb_error_ir);
286 return cache_tlb_prop;
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100287}
288
289//Converts a single ARM bus error information structure into JSON IR format.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100290json_object *cper_arm_bus_error_to_ir(EFI_ARM_BUS_ERROR_STRUCTURE *bus_error)
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100291{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100292 json_object *bus_error_ir = json_object_new_object();
Lawrence Tang7f21db62022-07-06 11:09:39 +0100293
Lawrence Tange407b4c2022-07-21 13:54:01 +0100294 //Validation bits.
295 json_object *validation =
296 bitfield_to_ir(bus_error->ValidationBits, 12,
297 ARM_BUS_ERROR_VALID_BITFIELD_NAMES);
298 json_object_object_add(bus_error_ir, "validationBits", validation);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100299
Lawrence Tange407b4c2022-07-21 13:54:01 +0100300 //Transaction type.
301 json_object *transaction_type = integer_to_readable_pair(
302 bus_error->TransactionType, 3, ARM_ERROR_TRANSACTION_TYPES_KEYS,
303 ARM_ERROR_TRANSACTION_TYPES_VALUES, "Unknown (Reserved)");
304 json_object_object_add(bus_error_ir, "transactionType",
305 transaction_type);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100306
Lawrence Tange407b4c2022-07-21 13:54:01 +0100307 //Operation.
308 json_object *operation = integer_to_readable_pair(
309 bus_error->Operation, 7, ARM_CACHE_BUS_OPERATION_TYPES_KEYS,
310 ARM_CACHE_BUS_OPERATION_TYPES_VALUES, "Unknown (Reserved)");
311 json_object_object_add(bus_error_ir, "operation", operation);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100312
Lawrence Tange407b4c2022-07-21 13:54:01 +0100313 //Affinity level of bus error, + miscellaneous fields.
314 json_object_object_add(bus_error_ir, "level",
315 json_object_new_int(bus_error->Level));
316 json_object_object_add(
317 bus_error_ir, "processorContextCorrupt",
318 json_object_new_boolean(bus_error->ProcessorContextCorrupt));
319 json_object_object_add(bus_error_ir, "corrected",
320 json_object_new_boolean(bus_error->Corrected));
321 json_object_object_add(bus_error_ir, "precisePC",
322 json_object_new_boolean(bus_error->PrecisePC));
323 json_object_object_add(
324 bus_error_ir, "restartablePC",
325 json_object_new_boolean(bus_error->RestartablePC));
326 json_object_object_add(bus_error_ir, "timedOut",
327 json_object_new_boolean(bus_error->TimeOut));
Lawrence Tang7f21db62022-07-06 11:09:39 +0100328
Lawrence Tange407b4c2022-07-21 13:54:01 +0100329 //Participation type.
330 json_object *participation_type = integer_to_readable_pair(
331 bus_error->ParticipationType, 4,
332 ARM_BUS_PARTICIPATION_TYPES_KEYS,
333 ARM_BUS_PARTICIPATION_TYPES_VALUES, "Unknown");
334 json_object_object_add(bus_error_ir, "participationType",
335 participation_type);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100336
Lawrence Tange407b4c2022-07-21 13:54:01 +0100337 //Address space.
338 json_object *address_space = integer_to_readable_pair(
339 bus_error->AddressSpace, 3, ARM_BUS_ADDRESS_SPACE_TYPES_KEYS,
340 ARM_BUS_ADDRESS_SPACE_TYPES_VALUES, "Unknown");
341 json_object_object_add(bus_error_ir, "addressSpace", address_space);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100342
Lawrence Tange407b4c2022-07-21 13:54:01 +0100343 //Memory access attributes.
344 //todo: find the specification of these in the ARM ARM
345 json_object_object_add(
346 bus_error_ir, "memoryAttributes",
347 json_object_new_int(bus_error->MemoryAddressAttributes));
Lawrence Tang7f21db62022-07-06 11:09:39 +0100348
Lawrence Tange407b4c2022-07-21 13:54:01 +0100349 //Access Mode
350 json_object *access_mode = json_object_new_object();
351 json_object_object_add(access_mode, "value",
352 json_object_new_int(bus_error->AccessMode));
353 json_object_object_add(
354 access_mode, "name",
355 json_object_new_string(bus_error->AccessMode == 0 ? "Secure" :
John Chungf8fc7052024-05-03 20:05:29 +0800356 "Normal"));
Lawrence Tange407b4c2022-07-21 13:54:01 +0100357 json_object_object_add(bus_error_ir, "accessMode", access_mode);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100358
Lawrence Tange407b4c2022-07-21 13:54:01 +0100359 return bus_error_ir;
Lawrence Tang7f21db62022-07-06 11:09:39 +0100360}
361
362//Converts a single ARM processor context block into JSON IR.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100363json_object *
364cper_arm_processor_context_to_ir(EFI_ARM_CONTEXT_INFORMATION_HEADER *header,
365 void **cur_pos)
Lawrence Tang7f21db62022-07-06 11:09:39 +0100366{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100367 json_object *context_ir = json_object_new_object();
Lawrence Tang7f21db62022-07-06 11:09:39 +0100368
Lawrence Tange407b4c2022-07-21 13:54:01 +0100369 //Version.
370 json_object_object_add(context_ir, "version",
371 json_object_new_int(header->Version));
Lawrence Tang71570a22022-07-14 11:45:28 +0100372
Lawrence Tange407b4c2022-07-21 13:54:01 +0100373 //Add the context type.
374 json_object *context_type = integer_to_readable_pair(
375 header->RegisterContextType, 9,
376 ARM_PROCESSOR_INFO_REGISTER_CONTEXT_TYPES_KEYS,
377 ARM_PROCESSOR_INFO_REGISTER_CONTEXT_TYPES_VALUES,
378 "Unknown (Reserved)");
379 json_object_object_add(context_ir, "registerContextType", context_type);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100380
Lawrence Tange407b4c2022-07-21 13:54:01 +0100381 //Register array size (bytes).
382 json_object_object_add(
383 context_ir, "registerArraySize",
384 json_object_new_uint64(header->RegisterArraySize));
Lawrence Tang7f21db62022-07-06 11:09:39 +0100385
Lawrence Tange407b4c2022-07-21 13:54:01 +0100386 //The register array itself.
387 *cur_pos = (void *)(header + 1);
388 json_object *register_array = NULL;
389 switch (header->RegisterContextType) {
390 case EFI_ARM_CONTEXT_TYPE_AARCH32_GPR:
391 register_array = uniform_struct_to_ir(
392 (UINT32 *)cur_pos,
393 sizeof(EFI_ARM_V8_AARCH32_GPR) / sizeof(UINT32),
394 ARM_AARCH32_GPR_NAMES);
395 break;
396 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL1:
397 register_array = uniform_struct_to_ir(
398 (UINT32 *)cur_pos,
399 sizeof(EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS) /
400 sizeof(UINT32),
401 ARM_AARCH32_EL1_REGISTER_NAMES);
402 break;
403 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL2:
404 register_array = uniform_struct_to_ir(
405 (UINT32 *)cur_pos,
406 sizeof(EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS) /
407 sizeof(UINT32),
408 ARM_AARCH32_EL2_REGISTER_NAMES);
409 break;
410 case EFI_ARM_CONTEXT_TYPE_AARCH32_SECURE:
411 register_array = uniform_struct_to_ir(
412 (UINT32 *)cur_pos,
413 sizeof(EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS) /
414 sizeof(UINT32),
415 ARM_AARCH32_SECURE_REGISTER_NAMES);
416 break;
417 case EFI_ARM_CONTEXT_TYPE_AARCH64_GPR:
418 register_array = uniform_struct64_to_ir(
419 (UINT64 *)cur_pos,
420 sizeof(EFI_ARM_V8_AARCH64_GPR) / sizeof(UINT64),
421 ARM_AARCH64_GPR_NAMES);
422 break;
423 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL1:
424 register_array = uniform_struct64_to_ir(
425 (UINT64 *)cur_pos,
426 sizeof(EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS) /
427 sizeof(UINT64),
428 ARM_AARCH64_EL1_REGISTER_NAMES);
429 break;
430 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL2:
431 register_array = uniform_struct64_to_ir(
432 (UINT64 *)cur_pos,
433 sizeof(EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS) /
434 sizeof(UINT64),
435 ARM_AARCH64_EL2_REGISTER_NAMES);
436 break;
437 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL3:
438 register_array = uniform_struct64_to_ir(
439 (UINT64 *)cur_pos,
440 sizeof(EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS) /
441 sizeof(UINT64),
442 ARM_AARCH64_EL3_REGISTER_NAMES);
443 break;
444 case EFI_ARM_CONTEXT_TYPE_MISC:
445 register_array = cper_arm_misc_register_array_to_ir(
446 (EFI_ARM_MISC_CONTEXT_REGISTER *)cur_pos);
447 break;
448 default:
449 //Unknown register array type, add as base64 data instead.
450 register_array = json_object_new_object();
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700451 int32_t encoded_len = 0;
452 char *encoded = base64_encode((UINT8 *)cur_pos,
453 header->RegisterArraySize,
454 &encoded_len);
455 if (encoded == NULL) {
John Chungf8fc7052024-05-03 20:05:29 +0800456 printf("Failed to allocate encode output buffer. \n");
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700457 return NULL;
John Chungf8fc7052024-05-03 20:05:29 +0800458 }
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700459 json_object_object_add(register_array, "data",
460 json_object_new_string_len(encoded,
461 encoded_len));
462 free(encoded);
463
Lawrence Tange407b4c2022-07-21 13:54:01 +0100464 break;
465 }
466 json_object_object_add(context_ir, "registerArray", register_array);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100467
Lawrence Tange407b4c2022-07-21 13:54:01 +0100468 //Set the current position to after the processor context structure.
469 *cur_pos = (UINT8 *)(*cur_pos) + header->RegisterArraySize;
Lawrence Tang7f21db62022-07-06 11:09:39 +0100470
Lawrence Tange407b4c2022-07-21 13:54:01 +0100471 return context_ir;
Lawrence Tang7f21db62022-07-06 11:09:39 +0100472}
473
474//Converts a single CPER ARM miscellaneous register array to JSON IR format.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100475json_object *
476cper_arm_misc_register_array_to_ir(EFI_ARM_MISC_CONTEXT_REGISTER *misc_register)
Lawrence Tang7f21db62022-07-06 11:09:39 +0100477{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100478 json_object *register_array = json_object_new_object();
479 json_object *mrs_encoding = json_object_new_object();
480 json_object_object_add(mrs_encoding, "op2",
481 json_object_new_uint64(misc_register->MrsOp2));
482 json_object_object_add(mrs_encoding, "crm",
483 json_object_new_uint64(misc_register->MrsCrm));
484 json_object_object_add(mrs_encoding, "crn",
485 json_object_new_uint64(misc_register->MrsCrn));
486 json_object_object_add(mrs_encoding, "op1",
487 json_object_new_uint64(misc_register->MrsOp1));
488 json_object_object_add(mrs_encoding, "o0",
489 json_object_new_uint64(misc_register->MrsO0));
490 json_object_object_add(register_array, "mrsEncoding", mrs_encoding);
491 json_object_object_add(register_array, "value",
492 json_object_new_uint64(misc_register->Value));
Lawrence Tang7f21db62022-07-06 11:09:39 +0100493
Lawrence Tange407b4c2022-07-21 13:54:01 +0100494 return register_array;
Lawrence Tang7cd13902022-07-13 16:59:25 +0100495}
496
497//Converts a single CPER-JSON ARM error section into CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100498void ir_section_arm_to_cper(json_object *section, FILE *out)
Lawrence Tang7cd13902022-07-13 16:59:25 +0100499{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100500 EFI_ARM_ERROR_RECORD *section_cper =
501 (EFI_ARM_ERROR_RECORD *)calloc(1, sizeof(EFI_ARM_ERROR_RECORD));
Lawrence Tang7cd13902022-07-13 16:59:25 +0100502
Lawrence Tange407b4c2022-07-21 13:54:01 +0100503 //Validation bits.
504 section_cper->ValidFields = ir_to_bitfield(
505 json_object_object_get(section, "validationBits"), 4,
506 ARM_ERROR_VALID_BITFIELD_NAMES);
Lawrence Tang7cd13902022-07-13 16:59:25 +0100507
Lawrence Tange407b4c2022-07-21 13:54:01 +0100508 //Count of error/context info structures.
509 section_cper->ErrInfoNum = json_object_get_int(
510 json_object_object_get(section, "errorInfoNum"));
511 section_cper->ContextInfoNum = json_object_get_int(
512 json_object_object_get(section, "contextInfoNum"));
Lawrence Tang7cd13902022-07-13 16:59:25 +0100513
Lawrence Tange407b4c2022-07-21 13:54:01 +0100514 //Miscellaneous raw value fields.
515 section_cper->SectionLength = json_object_get_uint64(
516 json_object_object_get(section, "sectionLength"));
517 section_cper->ErrorAffinityLevel = readable_pair_to_integer(
518 json_object_object_get(section, "errorAffinity"));
519 section_cper->MPIDR_EL1 = json_object_get_uint64(
520 json_object_object_get(section, "mpidrEl1"));
521 section_cper->MIDR_EL1 = json_object_get_uint64(
522 json_object_object_get(section, "midrEl1"));
523 section_cper->RunningState = json_object_get_boolean(
524 json_object_object_get(section, "running"));
Lawrence Tang7cd13902022-07-13 16:59:25 +0100525
Lawrence Tange407b4c2022-07-21 13:54:01 +0100526 //Optional PSCI state.
527 json_object *psci_state = json_object_object_get(section, "psciState");
John Chungf8fc7052024-05-03 20:05:29 +0800528 if (psci_state != NULL) {
Lawrence Tange407b4c2022-07-21 13:54:01 +0100529 section_cper->PsciState = json_object_get_uint64(psci_state);
John Chungf8fc7052024-05-03 20:05:29 +0800530 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100531
Lawrence Tange407b4c2022-07-21 13:54:01 +0100532 //Flush header to stream.
533 fwrite(section_cper, sizeof(EFI_ARM_ERROR_RECORD), 1, out);
534 fflush(out);
Lawrence Tang7cd13902022-07-13 16:59:25 +0100535
Lawrence Tange407b4c2022-07-21 13:54:01 +0100536 //Error info structure array.
537 json_object *error_info = json_object_object_get(section, "errorInfo");
John Chungf8fc7052024-05-03 20:05:29 +0800538 for (int i = 0; i < section_cper->ErrInfoNum; i++) {
Lawrence Tange407b4c2022-07-21 13:54:01 +0100539 ir_arm_error_info_to_cper(
540 json_object_array_get_idx(error_info, i), out);
John Chungf8fc7052024-05-03 20:05:29 +0800541 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100542
Lawrence Tange407b4c2022-07-21 13:54:01 +0100543 //Context info structure array.
544 json_object *context_info =
545 json_object_object_get(section, "contextInfo");
John Chungf8fc7052024-05-03 20:05:29 +0800546 for (int i = 0; i < section_cper->ContextInfoNum; i++) {
Lawrence Tange407b4c2022-07-21 13:54:01 +0100547 ir_arm_context_info_to_cper(
548 json_object_array_get_idx(context_info, i), out);
John Chungf8fc7052024-05-03 20:05:29 +0800549 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100550
Lawrence Tange407b4c2022-07-21 13:54:01 +0100551 //Vendor specific error info.
552 json_object *vendor_specific_info =
553 json_object_object_get(section, "vendorSpecificInfo");
554 if (vendor_specific_info != NULL) {
555 json_object *vendor_info_string =
556 json_object_object_get(vendor_specific_info, "data");
557 int vendor_specific_len =
558 json_object_get_string_len(vendor_info_string);
Lawrence Tang01e3a442022-07-20 15:14:50 +0100559
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700560 int32_t decoded_len = 0;
561
562 UINT8 *decoded = base64_decode(
563 json_object_get_string(vendor_info_string),
564 vendor_specific_len, &decoded_len);
565
566 //Write out to file.
567 fwrite(decoded, decoded_len, 1, out);
568 fflush(out);
569 free(decoded);
Lawrence Tange407b4c2022-07-21 13:54:01 +0100570 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100571
Lawrence Tange407b4c2022-07-21 13:54:01 +0100572 //Free remaining resources.
573 free(section_cper);
Lawrence Tang7cd13902022-07-13 16:59:25 +0100574}
575
576//Converts a single ARM error information structure into CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100577void ir_arm_error_info_to_cper(json_object *error_info, FILE *out)
Lawrence Tang7cd13902022-07-13 16:59:25 +0100578{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100579 EFI_ARM_ERROR_INFORMATION_ENTRY error_info_cper;
Lawrence Tang7cd13902022-07-13 16:59:25 +0100580
Lawrence Tange407b4c2022-07-21 13:54:01 +0100581 //Version, length.
582 error_info_cper.Version = json_object_get_int(
583 json_object_object_get(error_info, "version"));
584 error_info_cper.Length = json_object_get_int(
585 json_object_object_get(error_info, "length"));
Lawrence Tang7cd13902022-07-13 16:59:25 +0100586
Lawrence Tange407b4c2022-07-21 13:54:01 +0100587 //Validation bits.
588 error_info_cper.ValidationBits = ir_to_bitfield(
589 json_object_object_get(error_info, "validationBits"), 5,
590 ARM_ERROR_INFO_ENTRY_VALID_BITFIELD_NAMES);
Lawrence Tang7cd13902022-07-13 16:59:25 +0100591
Lawrence Tange407b4c2022-07-21 13:54:01 +0100592 //Type, multiple error.
593 error_info_cper.Type = (UINT8)readable_pair_to_integer(
594 json_object_object_get(error_info, "type"));
595 error_info_cper.MultipleError = (UINT16)readable_pair_to_integer(
596 json_object_object_get(error_info, "multipleError"));
Lawrence Tang7cd13902022-07-13 16:59:25 +0100597
Lawrence Tange407b4c2022-07-21 13:54:01 +0100598 //Flags object.
599 error_info_cper.Flags = (UINT8)ir_to_bitfield(
600 json_object_object_get(error_info, "flags"), 4,
601 ARM_ERROR_INFO_ENTRY_FLAGS_NAMES);
Lawrence Tang7cd13902022-07-13 16:59:25 +0100602
Lawrence Tange407b4c2022-07-21 13:54:01 +0100603 //Error information.
604 json_object *error_info_information =
605 json_object_object_get(error_info, "errorInformation");
Aushim Nagarkatti5b793002024-09-26 17:07:30 -0700606 json_object *error_info_prop = NULL;
607
Lawrence Tange407b4c2022-07-21 13:54:01 +0100608 switch (error_info_cper.Type) {
609 case ARM_ERROR_INFORMATION_TYPE_CACHE:
Aushim Nagarkatti5b793002024-09-26 17:07:30 -0700610 error_info_prop = json_object_object_get(error_info_information,
611 "cacheError");
Lawrence Tange407b4c2022-07-21 13:54:01 +0100612 ir_arm_error_cache_tlb_info_to_cper(
Aushim Nagarkatti5b793002024-09-26 17:07:30 -0700613 error_info_prop,
614 &error_info_cper.ErrorInformation.CacheError);
615 break;
616 case ARM_ERROR_INFORMATION_TYPE_TLB:
617 error_info_prop = json_object_object_get(error_info_information,
618 "tlbError");
619 ir_arm_error_cache_tlb_info_to_cper(
620 error_info_prop,
Lawrence Tange407b4c2022-07-21 13:54:01 +0100621 &error_info_cper.ErrorInformation.CacheError);
622 break;
Lawrence Tang71570a22022-07-14 11:45:28 +0100623
Lawrence Tange407b4c2022-07-21 13:54:01 +0100624 case ARM_ERROR_INFORMATION_TYPE_BUS:
625 ir_arm_error_bus_info_to_cper(
626 error_info_information,
627 &error_info_cper.ErrorInformation.BusError);
628 break;
Lawrence Tang71570a22022-07-14 11:45:28 +0100629
Lawrence Tange407b4c2022-07-21 13:54:01 +0100630 default:
631 //Unknown error information type.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100632 break;
633 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100634
Lawrence Tange407b4c2022-07-21 13:54:01 +0100635 //Virtual/physical fault address.
636 error_info_cper.VirtualFaultAddress = json_object_get_uint64(
637 json_object_object_get(error_info, "virtualFaultAddress"));
638 error_info_cper.PhysicalFaultAddress = json_object_get_uint64(
639 json_object_object_get(error_info, "physicalFaultAddress"));
Lawrence Tang7cd13902022-07-13 16:59:25 +0100640
Lawrence Tange407b4c2022-07-21 13:54:01 +0100641 //Write out to stream.
642 fwrite(&error_info_cper, sizeof(EFI_ARM_ERROR_INFORMATION_ENTRY), 1,
643 out);
644 fflush(out);
Lawrence Tang7cd13902022-07-13 16:59:25 +0100645}
646
Lawrence Tang71570a22022-07-14 11:45:28 +0100647//Converts a single ARM cache/TLB error information structure into a CPER structure.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100648void ir_arm_error_cache_tlb_info_to_cper(
649 json_object *error_information,
650 EFI_ARM_CACHE_ERROR_STRUCTURE *error_info_cper)
Lawrence Tang71570a22022-07-14 11:45:28 +0100651{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100652 //Validation bits.
653 error_info_cper->ValidationBits = ir_to_bitfield(
654 json_object_object_get(error_information, "validationBits"), 7,
655 ARM_CACHE_TLB_ERROR_VALID_BITFIELD_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100656
Lawrence Tange407b4c2022-07-21 13:54:01 +0100657 //Miscellaneous value fields.
658 error_info_cper->TransactionType = readable_pair_to_integer(
659 json_object_object_get(error_information, "transactionType"));
660 error_info_cper->Operation = readable_pair_to_integer(
661 json_object_object_get(error_information, "operation"));
662 error_info_cper->Level = json_object_get_uint64(
663 json_object_object_get(error_information, "level"));
664 error_info_cper->ProcessorContextCorrupt = json_object_get_boolean(
665 json_object_object_get(error_information,
666 "processorContextCorrupt"));
667 error_info_cper->Corrected = json_object_get_boolean(
668 json_object_object_get(error_information, "corrected"));
669 error_info_cper->PrecisePC = json_object_get_boolean(
670 json_object_object_get(error_information, "precisePC"));
671 error_info_cper->RestartablePC = json_object_get_boolean(
672 json_object_object_get(error_information, "restartablePC"));
673 error_info_cper->Reserved = 0;
Lawrence Tang71570a22022-07-14 11:45:28 +0100674}
675
676//Converts a single ARM bus error information structure into a CPER structure.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100677void ir_arm_error_bus_info_to_cper(json_object *error_information,
678 EFI_ARM_BUS_ERROR_STRUCTURE *error_info_cper)
Lawrence Tang71570a22022-07-14 11:45:28 +0100679{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100680 //Validation bits.
681 error_info_cper->ValidationBits = ir_to_bitfield(
682 json_object_object_get(error_information, "validationBits"), 7,
683 ARM_BUS_ERROR_VALID_BITFIELD_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100684
Lawrence Tange407b4c2022-07-21 13:54:01 +0100685 //Miscellaneous value fields.
686 error_info_cper->TransactionType = readable_pair_to_integer(
687 json_object_object_get(error_information, "transactionType"));
688 error_info_cper->Operation = readable_pair_to_integer(
689 json_object_object_get(error_information, "operation"));
690 error_info_cper->Level = json_object_get_uint64(
691 json_object_object_get(error_information, "level"));
692 error_info_cper->ProcessorContextCorrupt = json_object_get_boolean(
693 json_object_object_get(error_information,
694 "processorContextCorrupt"));
695 error_info_cper->Corrected = json_object_get_boolean(
696 json_object_object_get(error_information, "corrected"));
697 error_info_cper->PrecisePC = json_object_get_boolean(
698 json_object_object_get(error_information, "precisePC"));
699 error_info_cper->RestartablePC = json_object_get_boolean(
700 json_object_object_get(error_information, "restartablePC"));
701 error_info_cper->ParticipationType = readable_pair_to_integer(
702 json_object_object_get(error_information, "participationType"));
703 error_info_cper->AddressSpace = readable_pair_to_integer(
704 json_object_object_get(error_information, "addressSpace"));
705 error_info_cper->AccessMode = readable_pair_to_integer(
706 json_object_object_get(error_information, "accessMode"));
707 error_info_cper->MemoryAddressAttributes = json_object_get_uint64(
708 json_object_object_get(error_information, "memoryAttributes"));
709 error_info_cper->Reserved = 0;
Lawrence Tang71570a22022-07-14 11:45:28 +0100710}
711
Lawrence Tang7cd13902022-07-13 16:59:25 +0100712//Converts a single ARM context information structure into CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100713void ir_arm_context_info_to_cper(json_object *context_info, FILE *out)
Lawrence Tang7cd13902022-07-13 16:59:25 +0100714{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100715 EFI_ARM_CONTEXT_INFORMATION_HEADER info_header;
Lawrence Tang7cd13902022-07-13 16:59:25 +0100716
Lawrence Tange407b4c2022-07-21 13:54:01 +0100717 //Version, array size, context type.
718 info_header.Version = json_object_get_int(
719 json_object_object_get(context_info, "version"));
720 info_header.RegisterArraySize = json_object_get_int(
721 json_object_object_get(context_info, "registerArraySize"));
722 info_header.RegisterContextType = readable_pair_to_integer(
723 json_object_object_get(context_info, "registerContextType"));
Lawrence Tang71570a22022-07-14 11:45:28 +0100724
Lawrence Tange407b4c2022-07-21 13:54:01 +0100725 //Flush to stream, write the register array itself.
726 fwrite(&info_header, sizeof(EFI_ARM_CONTEXT_INFORMATION_HEADER), 1,
727 out);
728 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100729
Lawrence Tange407b4c2022-07-21 13:54:01 +0100730 json_object *register_array =
731 json_object_object_get(context_info, "registerArray");
732 switch (info_header.RegisterContextType) {
733 case EFI_ARM_CONTEXT_TYPE_AARCH32_GPR:
734 ir_arm_aarch32_gpr_to_cper(register_array, out);
735 break;
736 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL1:
737 ir_arm_aarch32_el1_to_cper(register_array, out);
738 break;
739 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL2:
740 ir_arm_aarch32_el2_to_cper(register_array, out);
741 break;
742 case EFI_ARM_CONTEXT_TYPE_AARCH32_SECURE:
743 ir_arm_aarch32_secure_to_cper(register_array, out);
744 break;
745 case EFI_ARM_CONTEXT_TYPE_AARCH64_GPR:
746 ir_arm_aarch64_gpr_to_cper(register_array, out);
747 break;
748 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL1:
749 ir_arm_aarch64_el1_to_cper(register_array, out);
750 break;
751 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL2:
752 ir_arm_aarch64_el2_to_cper(register_array, out);
753 break;
754 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL3:
755 ir_arm_aarch64_el3_to_cper(register_array, out);
756 break;
757 case EFI_ARM_CONTEXT_TYPE_MISC:
758 ir_arm_misc_registers_to_cper(register_array, out);
759 break;
760 default:
761 //Unknown register structure.
John Chungf8fc7052024-05-03 20:05:29 +0800762 ir_arm_unknown_register_to_cper(register_array, out);
Lawrence Tange407b4c2022-07-21 13:54:01 +0100763 break;
764 }
Lawrence Tang71570a22022-07-14 11:45:28 +0100765}
766
767//Converts a single AARCH32 GPR CPER-JSON object to CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100768void ir_arm_aarch32_gpr_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100769{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100770 //Get uniform register array.
771 EFI_ARM_V8_AARCH32_GPR reg_array;
772 ir_to_uniform_struct(registers, (UINT32 *)&reg_array,
773 sizeof(EFI_ARM_V8_AARCH32_GPR) / sizeof(UINT32),
774 ARM_AARCH32_GPR_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100775
Lawrence Tange407b4c2022-07-21 13:54:01 +0100776 //Flush to stream.
777 fwrite(&reg_array, sizeof(reg_array), 1, out);
778 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100779}
780
781//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 +0100782void ir_arm_aarch32_el1_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100783{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100784 //Get uniform register array.
785 EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS reg_array;
786 ir_to_uniform_struct(registers, (UINT32 *)&reg_array,
787 sizeof(EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS) /
788 sizeof(UINT32),
789 ARM_AARCH32_EL1_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100790
Lawrence Tange407b4c2022-07-21 13:54:01 +0100791 //Flush to stream.
792 fwrite(&reg_array, sizeof(reg_array), 1, out);
793 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100794}
795
796//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 +0100797void ir_arm_aarch32_el2_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100798{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100799 //Get uniform register array.
800 EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS reg_array;
801 ir_to_uniform_struct(registers, (UINT32 *)&reg_array,
802 sizeof(EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS) /
803 sizeof(UINT32),
804 ARM_AARCH32_EL2_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100805
Lawrence Tange407b4c2022-07-21 13:54:01 +0100806 //Flush to stream.
807 fwrite(&reg_array, sizeof(reg_array), 1, out);
808 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100809}
810
811//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 +0100812void ir_arm_aarch32_secure_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100813{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100814 //Get uniform register array.
815 EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS reg_array;
816 ir_to_uniform_struct(registers, (UINT32 *)&reg_array,
817 sizeof(EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS) /
818 sizeof(UINT32),
819 ARM_AARCH32_SECURE_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100820
Lawrence Tange407b4c2022-07-21 13:54:01 +0100821 //Flush to stream.
822 fwrite(&reg_array, sizeof(reg_array), 1, out);
823 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100824}
825
826//Converts a single AARCH64 GPR CPER-JSON object to CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100827void ir_arm_aarch64_gpr_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100828{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100829 //Get uniform register array.
830 EFI_ARM_V8_AARCH64_GPR reg_array;
831 ir_to_uniform_struct64(registers, (UINT64 *)&reg_array,
832 sizeof(EFI_ARM_V8_AARCH64_GPR) / sizeof(UINT64),
833 ARM_AARCH64_GPR_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100834
Lawrence Tange407b4c2022-07-21 13:54:01 +0100835 //Flush to stream.
836 fwrite(&reg_array, sizeof(reg_array), 1, out);
837 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100838}
839
840//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 +0100841void ir_arm_aarch64_el1_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100842{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100843 //Get uniform register array.
844 EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS reg_array;
845 ir_to_uniform_struct64(registers, (UINT64 *)&reg_array,
846 sizeof(EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS) /
847 sizeof(UINT64),
848 ARM_AARCH64_EL1_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100849
Lawrence Tange407b4c2022-07-21 13:54:01 +0100850 //Flush to stream.
851 fwrite(&reg_array, sizeof(reg_array), 1, out);
852 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100853}
854
855//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 +0100856void ir_arm_aarch64_el2_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100857{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100858 //Get uniform register array.
859 EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS reg_array;
860 ir_to_uniform_struct64(registers, (UINT64 *)&reg_array,
861 sizeof(EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS) /
862 sizeof(UINT64),
863 ARM_AARCH64_EL2_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100864
Lawrence Tange407b4c2022-07-21 13:54:01 +0100865 //Flush to stream.
866 fwrite(&reg_array, sizeof(reg_array), 1, out);
867 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100868}
869
870//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 +0100871void ir_arm_aarch64_el3_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100872{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100873 //Get uniform register array.
874 EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS reg_array;
875 ir_to_uniform_struct64(registers, (UINT64 *)&reg_array,
876 sizeof(EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS) /
877 sizeof(UINT64),
878 ARM_AARCH64_EL3_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100879
Lawrence Tange407b4c2022-07-21 13:54:01 +0100880 //Flush to stream.
881 fwrite(&reg_array, sizeof(reg_array), 1, out);
882 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100883}
884
885//Converts a single ARM miscellaneous register set CPER-JSON object to CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100886void ir_arm_misc_registers_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100887{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100888 EFI_ARM_MISC_CONTEXT_REGISTER reg_array;
Lawrence Tang71570a22022-07-14 11:45:28 +0100889
Lawrence Tange407b4c2022-07-21 13:54:01 +0100890 //MRS encoding information.
891 json_object *mrs_encoding =
892 json_object_object_get(registers, "mrsEncoding");
893 reg_array.MrsOp2 = json_object_get_uint64(
894 json_object_object_get(mrs_encoding, "op2"));
895 reg_array.MrsCrm = json_object_get_uint64(
896 json_object_object_get(mrs_encoding, "crm"));
897 reg_array.MrsCrn = json_object_get_uint64(
898 json_object_object_get(mrs_encoding, "crn"));
899 reg_array.MrsOp1 = json_object_get_uint64(
900 json_object_object_get(mrs_encoding, "op1"));
901 reg_array.MrsO0 = json_object_get_uint64(
902 json_object_object_get(mrs_encoding, "o0"));
Lawrence Tang71570a22022-07-14 11:45:28 +0100903
Lawrence Tange407b4c2022-07-21 13:54:01 +0100904 //Actual register value.
905 reg_array.Value = json_object_get_uint64(
906 json_object_object_get(registers, "value"));
Lawrence Tang71570a22022-07-14 11:45:28 +0100907
Lawrence Tange407b4c2022-07-21 13:54:01 +0100908 //Flush to stream.
909 fwrite(&reg_array, sizeof(reg_array), 1, out);
910 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100911}
912
913//Converts a single ARM unknown register CPER-JSON object to CPER binary, outputting to the given stream.
John Chungf8fc7052024-05-03 20:05:29 +0800914void ir_arm_unknown_register_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100915{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100916 //Get base64 represented data.
917 json_object *encoded = json_object_object_get(registers, "data");
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700918
919 int32_t decoded_len = 0;
920
921 UINT8 *decoded = base64_decode(json_object_get_string(encoded),
922 json_object_get_string_len(encoded),
923 &decoded_len);
924
925 if (decoded == NULL) {
John Chungf8fc7052024-05-03 20:05:29 +0800926 printf("Failed to allocate decode output buffer. \n");
927 } else {
John Chungf8fc7052024-05-03 20:05:29 +0800928 //Flush out to stream.
929 fwrite(&decoded, decoded_len, 1, out);
930 fflush(out);
931 free(decoded);
932 }
933}