blob: b0b14d1ee56b16ec0d4202d6e941adb51b1ed94d [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>
Ed Tanousa7d2cdd2024-07-15 11:07:27 -070010#include "base64.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;
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700124 int32_t encoded_len = 0;
125 char *encoded =
126 base64_encode(cur_pos, input_size, &encoded_len);
127 if (encoded == NULL) {
128 return NULL;
John Chungf8fc7052024-05-03 20:05:29 +0800129 }
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700130 json_object_object_add(vendor_specific, "data",
131 json_object_new_string_len(encoded,
132 encoded_len));
133 free(encoded);
134
135 json_object_object_add(section_ir, "vendorSpecificInfo",
136 vendor_specific);
Lawrence Tange407b4c2022-07-21 13:54:01 +0100137 }
138
139 return section_ir;
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100140}
141
142//Converts a single ARM Process Error Information structure into JSON IR.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100143json_object *
144cper_arm_error_info_to_ir(EFI_ARM_ERROR_INFORMATION_ENTRY *error_info)
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100145{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100146 json_object *error_info_ir = json_object_new_object();
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100147
Lawrence Tange407b4c2022-07-21 13:54:01 +0100148 //Version, length.
149 json_object_object_add(error_info_ir, "version",
150 json_object_new_int(error_info->Version));
151 json_object_object_add(error_info_ir, "length",
152 json_object_new_int(error_info->Length));
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100153
Lawrence Tange407b4c2022-07-21 13:54:01 +0100154 //Validation bitfield.
155 json_object *validation =
156 bitfield_to_ir(error_info->ValidationBits, 5,
157 ARM_ERROR_INFO_ENTRY_VALID_BITFIELD_NAMES);
158 json_object_object_add(error_info_ir, "validationBits", validation);
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100159
Lawrence Tange407b4c2022-07-21 13:54:01 +0100160 //The type of error information in this log.
161 json_object *error_type = integer_to_readable_pair(
162 error_info->Type, 4, ARM_ERROR_INFO_ENTRY_INFO_TYPES_KEYS,
163 ARM_ERROR_INFO_ENTRY_INFO_TYPES_VALUES, "Unknown (Reserved)");
164 json_object_object_add(error_info_ir, "errorType", error_type);
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100165
Lawrence Tange407b4c2022-07-21 13:54:01 +0100166 //Multiple error count.
167 json_object *multiple_error = json_object_new_object();
168 json_object_object_add(multiple_error, "value",
169 json_object_new_int(error_info->MultipleError));
170 json_object_object_add(
171 multiple_error, "type",
172 json_object_new_string(error_info->MultipleError < 1 ?
John Chungf8fc7052024-05-03 20:05:29 +0800173 "Single Error" :
174 "Multiple Errors"));
Lawrence Tange407b4c2022-07-21 13:54:01 +0100175 json_object_object_add(error_info_ir, "multipleError", multiple_error);
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100176
Lawrence Tange407b4c2022-07-21 13:54:01 +0100177 //Flags.
178 json_object *flags = bitfield_to_ir(error_info->Flags, 4,
179 ARM_ERROR_INFO_ENTRY_FLAGS_NAMES);
180 json_object_object_add(error_info_ir, "flags", flags);
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100181
Lawrence Tange407b4c2022-07-21 13:54:01 +0100182 //Error information, split by type.
183 json_object *error_subinfo = NULL;
184 switch (error_info->Type) {
185 case ARM_ERROR_INFORMATION_TYPE_CACHE: //Cache
John Chungf8fc7052024-05-03 20:05:29 +0800186 case ARM_ERROR_INFORMATION_TYPE_TLB: //TLB
Lawrence Tange407b4c2022-07-21 13:54:01 +0100187 error_subinfo = cper_arm_cache_tlb_error_to_ir(
188 (EFI_ARM_CACHE_ERROR_STRUCTURE *)&error_info
189 ->ErrorInformation,
190 error_info);
191 break;
192 case ARM_ERROR_INFORMATION_TYPE_BUS: //Bus
193 error_subinfo = cper_arm_bus_error_to_ir(
194 (EFI_ARM_BUS_ERROR_STRUCTURE *)&error_info
195 ->ErrorInformation);
196 break;
Lawrence Tang71570a22022-07-14 11:45:28 +0100197
Lawrence Tange407b4c2022-07-21 13:54:01 +0100198 default:
199 //Unknown/microarch, so can't be made readable. Simply dump as a uint64 data object.
200 error_subinfo = json_object_new_object();
201 json_object_object_add(
202 error_subinfo, "data",
203 json_object_new_uint64(
John Chung0b9c9402024-05-22 22:52:55 +0800204 error_info->ErrorInformation.Value));
Lawrence Tange407b4c2022-07-21 13:54:01 +0100205 break;
206 }
207 json_object_object_add(error_info_ir, "errorInformation",
208 error_subinfo);
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100209
Lawrence Tange407b4c2022-07-21 13:54:01 +0100210 //Virtual fault address, physical fault address.
211 json_object_object_add(
212 error_info_ir, "virtualFaultAddress",
213 json_object_new_uint64(error_info->VirtualFaultAddress));
214 json_object_object_add(
215 error_info_ir, "physicalFaultAddress",
216 json_object_new_uint64(error_info->PhysicalFaultAddress));
217
218 return error_info_ir;
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100219}
220
Lawrence Tang7f21db62022-07-06 11:09:39 +0100221//Converts a single ARM cache/TLB error information structure into JSON IR format.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100222json_object *
223cper_arm_cache_tlb_error_to_ir(EFI_ARM_CACHE_ERROR_STRUCTURE *cache_tlb_error,
224 EFI_ARM_ERROR_INFORMATION_ENTRY *error_info)
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100225{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100226 json_object *cache_tlb_error_ir = json_object_new_object();
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100227
Lawrence Tange407b4c2022-07-21 13:54:01 +0100228 //Validation bitfield.
229 json_object *validation =
230 bitfield_to_ir(cache_tlb_error->ValidationBits, 7,
231 ARM_CACHE_TLB_ERROR_VALID_BITFIELD_NAMES);
232 json_object_object_add(cache_tlb_error_ir, "validationBits",
233 validation);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100234
Lawrence Tange407b4c2022-07-21 13:54:01 +0100235 //Transaction type.
236 json_object *transaction_type = integer_to_readable_pair(
237 cache_tlb_error->TransactionType, 3,
238 ARM_ERROR_TRANSACTION_TYPES_KEYS,
239 ARM_ERROR_TRANSACTION_TYPES_VALUES, "Unknown (Reserved)");
240 json_object_object_add(cache_tlb_error_ir, "transactionType",
241 transaction_type);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100242
Lawrence Tange407b4c2022-07-21 13:54:01 +0100243 //Operation.
244 json_object *operation;
245 if (error_info->Type == 0) {
246 //Cache operation.
247 operation = integer_to_readable_pair(
248 cache_tlb_error->Operation, 11,
249 ARM_CACHE_BUS_OPERATION_TYPES_KEYS,
250 ARM_CACHE_BUS_OPERATION_TYPES_VALUES,
251 "Unknown (Reserved)");
252 } else {
253 //TLB operation.
254 operation = integer_to_readable_pair(
255 cache_tlb_error->Operation, 9,
256 ARM_TLB_OPERATION_TYPES_KEYS,
257 ARM_TLB_OPERATION_TYPES_VALUES, "Unknown (Reserved)");
258 }
259 json_object_object_add(cache_tlb_error_ir, "operation", operation);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100260
Lawrence Tange407b4c2022-07-21 13:54:01 +0100261 //Miscellaneous remaining fields.
262 json_object_object_add(cache_tlb_error_ir, "level",
263 json_object_new_int(cache_tlb_error->Level));
264 json_object_object_add(
265 cache_tlb_error_ir, "processorContextCorrupt",
266 json_object_new_boolean(
267 cache_tlb_error->ProcessorContextCorrupt));
268 json_object_object_add(
269 cache_tlb_error_ir, "corrected",
270 json_object_new_boolean(cache_tlb_error->Corrected));
271 json_object_object_add(
272 cache_tlb_error_ir, "precisePC",
273 json_object_new_boolean(cache_tlb_error->PrecisePC));
274 json_object_object_add(
275 cache_tlb_error_ir, "restartablePC",
276 json_object_new_boolean(cache_tlb_error->RestartablePC));
277 return cache_tlb_error_ir;
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100278}
279
280//Converts a single ARM bus error information structure into JSON IR format.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100281json_object *cper_arm_bus_error_to_ir(EFI_ARM_BUS_ERROR_STRUCTURE *bus_error)
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100282{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100283 json_object *bus_error_ir = json_object_new_object();
Lawrence Tang7f21db62022-07-06 11:09:39 +0100284
Lawrence Tange407b4c2022-07-21 13:54:01 +0100285 //Validation bits.
286 json_object *validation =
287 bitfield_to_ir(bus_error->ValidationBits, 12,
288 ARM_BUS_ERROR_VALID_BITFIELD_NAMES);
289 json_object_object_add(bus_error_ir, "validationBits", validation);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100290
Lawrence Tange407b4c2022-07-21 13:54:01 +0100291 //Transaction type.
292 json_object *transaction_type = integer_to_readable_pair(
293 bus_error->TransactionType, 3, ARM_ERROR_TRANSACTION_TYPES_KEYS,
294 ARM_ERROR_TRANSACTION_TYPES_VALUES, "Unknown (Reserved)");
295 json_object_object_add(bus_error_ir, "transactionType",
296 transaction_type);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100297
Lawrence Tange407b4c2022-07-21 13:54:01 +0100298 //Operation.
299 json_object *operation = integer_to_readable_pair(
300 bus_error->Operation, 7, ARM_CACHE_BUS_OPERATION_TYPES_KEYS,
301 ARM_CACHE_BUS_OPERATION_TYPES_VALUES, "Unknown (Reserved)");
302 json_object_object_add(bus_error_ir, "operation", operation);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100303
Lawrence Tange407b4c2022-07-21 13:54:01 +0100304 //Affinity level of bus error, + miscellaneous fields.
305 json_object_object_add(bus_error_ir, "level",
306 json_object_new_int(bus_error->Level));
307 json_object_object_add(
308 bus_error_ir, "processorContextCorrupt",
309 json_object_new_boolean(bus_error->ProcessorContextCorrupt));
310 json_object_object_add(bus_error_ir, "corrected",
311 json_object_new_boolean(bus_error->Corrected));
312 json_object_object_add(bus_error_ir, "precisePC",
313 json_object_new_boolean(bus_error->PrecisePC));
314 json_object_object_add(
315 bus_error_ir, "restartablePC",
316 json_object_new_boolean(bus_error->RestartablePC));
317 json_object_object_add(bus_error_ir, "timedOut",
318 json_object_new_boolean(bus_error->TimeOut));
Lawrence Tang7f21db62022-07-06 11:09:39 +0100319
Lawrence Tange407b4c2022-07-21 13:54:01 +0100320 //Participation type.
321 json_object *participation_type = integer_to_readable_pair(
322 bus_error->ParticipationType, 4,
323 ARM_BUS_PARTICIPATION_TYPES_KEYS,
324 ARM_BUS_PARTICIPATION_TYPES_VALUES, "Unknown");
325 json_object_object_add(bus_error_ir, "participationType",
326 participation_type);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100327
Lawrence Tange407b4c2022-07-21 13:54:01 +0100328 //Address space.
329 json_object *address_space = integer_to_readable_pair(
330 bus_error->AddressSpace, 3, ARM_BUS_ADDRESS_SPACE_TYPES_KEYS,
331 ARM_BUS_ADDRESS_SPACE_TYPES_VALUES, "Unknown");
332 json_object_object_add(bus_error_ir, "addressSpace", address_space);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100333
Lawrence Tange407b4c2022-07-21 13:54:01 +0100334 //Memory access attributes.
335 //todo: find the specification of these in the ARM ARM
336 json_object_object_add(
337 bus_error_ir, "memoryAttributes",
338 json_object_new_int(bus_error->MemoryAddressAttributes));
Lawrence Tang7f21db62022-07-06 11:09:39 +0100339
Lawrence Tange407b4c2022-07-21 13:54:01 +0100340 //Access Mode
341 json_object *access_mode = json_object_new_object();
342 json_object_object_add(access_mode, "value",
343 json_object_new_int(bus_error->AccessMode));
344 json_object_object_add(
345 access_mode, "name",
346 json_object_new_string(bus_error->AccessMode == 0 ? "Secure" :
John Chungf8fc7052024-05-03 20:05:29 +0800347 "Normal"));
Lawrence Tange407b4c2022-07-21 13:54:01 +0100348 json_object_object_add(bus_error_ir, "accessMode", access_mode);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100349
Lawrence Tange407b4c2022-07-21 13:54:01 +0100350 return bus_error_ir;
Lawrence Tang7f21db62022-07-06 11:09:39 +0100351}
352
353//Converts a single ARM processor context block into JSON IR.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100354json_object *
355cper_arm_processor_context_to_ir(EFI_ARM_CONTEXT_INFORMATION_HEADER *header,
356 void **cur_pos)
Lawrence Tang7f21db62022-07-06 11:09:39 +0100357{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100358 json_object *context_ir = json_object_new_object();
Lawrence Tang7f21db62022-07-06 11:09:39 +0100359
Lawrence Tange407b4c2022-07-21 13:54:01 +0100360 //Version.
361 json_object_object_add(context_ir, "version",
362 json_object_new_int(header->Version));
Lawrence Tang71570a22022-07-14 11:45:28 +0100363
Lawrence Tange407b4c2022-07-21 13:54:01 +0100364 //Add the context type.
365 json_object *context_type = integer_to_readable_pair(
366 header->RegisterContextType, 9,
367 ARM_PROCESSOR_INFO_REGISTER_CONTEXT_TYPES_KEYS,
368 ARM_PROCESSOR_INFO_REGISTER_CONTEXT_TYPES_VALUES,
369 "Unknown (Reserved)");
370 json_object_object_add(context_ir, "registerContextType", context_type);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100371
Lawrence Tange407b4c2022-07-21 13:54:01 +0100372 //Register array size (bytes).
373 json_object_object_add(
374 context_ir, "registerArraySize",
375 json_object_new_uint64(header->RegisterArraySize));
Lawrence Tang7f21db62022-07-06 11:09:39 +0100376
Lawrence Tange407b4c2022-07-21 13:54:01 +0100377 //The register array itself.
378 *cur_pos = (void *)(header + 1);
379 json_object *register_array = NULL;
380 switch (header->RegisterContextType) {
381 case EFI_ARM_CONTEXT_TYPE_AARCH32_GPR:
382 register_array = uniform_struct_to_ir(
383 (UINT32 *)cur_pos,
384 sizeof(EFI_ARM_V8_AARCH32_GPR) / sizeof(UINT32),
385 ARM_AARCH32_GPR_NAMES);
386 break;
387 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL1:
388 register_array = uniform_struct_to_ir(
389 (UINT32 *)cur_pos,
390 sizeof(EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS) /
391 sizeof(UINT32),
392 ARM_AARCH32_EL1_REGISTER_NAMES);
393 break;
394 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL2:
395 register_array = uniform_struct_to_ir(
396 (UINT32 *)cur_pos,
397 sizeof(EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS) /
398 sizeof(UINT32),
399 ARM_AARCH32_EL2_REGISTER_NAMES);
400 break;
401 case EFI_ARM_CONTEXT_TYPE_AARCH32_SECURE:
402 register_array = uniform_struct_to_ir(
403 (UINT32 *)cur_pos,
404 sizeof(EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS) /
405 sizeof(UINT32),
406 ARM_AARCH32_SECURE_REGISTER_NAMES);
407 break;
408 case EFI_ARM_CONTEXT_TYPE_AARCH64_GPR:
409 register_array = uniform_struct64_to_ir(
410 (UINT64 *)cur_pos,
411 sizeof(EFI_ARM_V8_AARCH64_GPR) / sizeof(UINT64),
412 ARM_AARCH64_GPR_NAMES);
413 break;
414 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL1:
415 register_array = uniform_struct64_to_ir(
416 (UINT64 *)cur_pos,
417 sizeof(EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS) /
418 sizeof(UINT64),
419 ARM_AARCH64_EL1_REGISTER_NAMES);
420 break;
421 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL2:
422 register_array = uniform_struct64_to_ir(
423 (UINT64 *)cur_pos,
424 sizeof(EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS) /
425 sizeof(UINT64),
426 ARM_AARCH64_EL2_REGISTER_NAMES);
427 break;
428 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL3:
429 register_array = uniform_struct64_to_ir(
430 (UINT64 *)cur_pos,
431 sizeof(EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS) /
432 sizeof(UINT64),
433 ARM_AARCH64_EL3_REGISTER_NAMES);
434 break;
435 case EFI_ARM_CONTEXT_TYPE_MISC:
436 register_array = cper_arm_misc_register_array_to_ir(
437 (EFI_ARM_MISC_CONTEXT_REGISTER *)cur_pos);
438 break;
439 default:
440 //Unknown register array type, add as base64 data instead.
441 register_array = json_object_new_object();
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700442 int32_t encoded_len = 0;
443 char *encoded = base64_encode((UINT8 *)cur_pos,
444 header->RegisterArraySize,
445 &encoded_len);
446 if (encoded == NULL) {
John Chungf8fc7052024-05-03 20:05:29 +0800447 printf("Failed to allocate encode output buffer. \n");
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700448 return NULL;
John Chungf8fc7052024-05-03 20:05:29 +0800449 }
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700450 json_object_object_add(register_array, "data",
451 json_object_new_string_len(encoded,
452 encoded_len));
453 free(encoded);
454
Lawrence Tange407b4c2022-07-21 13:54:01 +0100455 break;
456 }
457 json_object_object_add(context_ir, "registerArray", register_array);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100458
Lawrence Tange407b4c2022-07-21 13:54:01 +0100459 //Set the current position to after the processor context structure.
460 *cur_pos = (UINT8 *)(*cur_pos) + header->RegisterArraySize;
Lawrence Tang7f21db62022-07-06 11:09:39 +0100461
Lawrence Tange407b4c2022-07-21 13:54:01 +0100462 return context_ir;
Lawrence Tang7f21db62022-07-06 11:09:39 +0100463}
464
465//Converts a single CPER ARM miscellaneous register array to JSON IR format.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100466json_object *
467cper_arm_misc_register_array_to_ir(EFI_ARM_MISC_CONTEXT_REGISTER *misc_register)
Lawrence Tang7f21db62022-07-06 11:09:39 +0100468{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100469 json_object *register_array = json_object_new_object();
470 json_object *mrs_encoding = json_object_new_object();
471 json_object_object_add(mrs_encoding, "op2",
472 json_object_new_uint64(misc_register->MrsOp2));
473 json_object_object_add(mrs_encoding, "crm",
474 json_object_new_uint64(misc_register->MrsCrm));
475 json_object_object_add(mrs_encoding, "crn",
476 json_object_new_uint64(misc_register->MrsCrn));
477 json_object_object_add(mrs_encoding, "op1",
478 json_object_new_uint64(misc_register->MrsOp1));
479 json_object_object_add(mrs_encoding, "o0",
480 json_object_new_uint64(misc_register->MrsO0));
481 json_object_object_add(register_array, "mrsEncoding", mrs_encoding);
482 json_object_object_add(register_array, "value",
483 json_object_new_uint64(misc_register->Value));
Lawrence Tang7f21db62022-07-06 11:09:39 +0100484
Lawrence Tange407b4c2022-07-21 13:54:01 +0100485 return register_array;
Lawrence Tang7cd13902022-07-13 16:59:25 +0100486}
487
488//Converts a single CPER-JSON ARM error section into CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100489void ir_section_arm_to_cper(json_object *section, FILE *out)
Lawrence Tang7cd13902022-07-13 16:59:25 +0100490{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100491 EFI_ARM_ERROR_RECORD *section_cper =
492 (EFI_ARM_ERROR_RECORD *)calloc(1, sizeof(EFI_ARM_ERROR_RECORD));
Lawrence Tang7cd13902022-07-13 16:59:25 +0100493
Lawrence Tange407b4c2022-07-21 13:54:01 +0100494 //Validation bits.
495 section_cper->ValidFields = ir_to_bitfield(
496 json_object_object_get(section, "validationBits"), 4,
497 ARM_ERROR_VALID_BITFIELD_NAMES);
Lawrence Tang7cd13902022-07-13 16:59:25 +0100498
Lawrence Tange407b4c2022-07-21 13:54:01 +0100499 //Count of error/context info structures.
500 section_cper->ErrInfoNum = json_object_get_int(
501 json_object_object_get(section, "errorInfoNum"));
502 section_cper->ContextInfoNum = json_object_get_int(
503 json_object_object_get(section, "contextInfoNum"));
Lawrence Tang7cd13902022-07-13 16:59:25 +0100504
Lawrence Tange407b4c2022-07-21 13:54:01 +0100505 //Miscellaneous raw value fields.
506 section_cper->SectionLength = json_object_get_uint64(
507 json_object_object_get(section, "sectionLength"));
508 section_cper->ErrorAffinityLevel = readable_pair_to_integer(
509 json_object_object_get(section, "errorAffinity"));
510 section_cper->MPIDR_EL1 = json_object_get_uint64(
511 json_object_object_get(section, "mpidrEl1"));
512 section_cper->MIDR_EL1 = json_object_get_uint64(
513 json_object_object_get(section, "midrEl1"));
514 section_cper->RunningState = json_object_get_boolean(
515 json_object_object_get(section, "running"));
Lawrence Tang7cd13902022-07-13 16:59:25 +0100516
Lawrence Tange407b4c2022-07-21 13:54:01 +0100517 //Optional PSCI state.
518 json_object *psci_state = json_object_object_get(section, "psciState");
John Chungf8fc7052024-05-03 20:05:29 +0800519 if (psci_state != NULL) {
Lawrence Tange407b4c2022-07-21 13:54:01 +0100520 section_cper->PsciState = json_object_get_uint64(psci_state);
John Chungf8fc7052024-05-03 20:05:29 +0800521 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100522
Lawrence Tange407b4c2022-07-21 13:54:01 +0100523 //Flush header to stream.
524 fwrite(section_cper, sizeof(EFI_ARM_ERROR_RECORD), 1, out);
525 fflush(out);
Lawrence Tang7cd13902022-07-13 16:59:25 +0100526
Lawrence Tange407b4c2022-07-21 13:54:01 +0100527 //Error info structure array.
528 json_object *error_info = json_object_object_get(section, "errorInfo");
John Chungf8fc7052024-05-03 20:05:29 +0800529 for (int i = 0; i < section_cper->ErrInfoNum; i++) {
Lawrence Tange407b4c2022-07-21 13:54:01 +0100530 ir_arm_error_info_to_cper(
531 json_object_array_get_idx(error_info, i), out);
John Chungf8fc7052024-05-03 20:05:29 +0800532 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100533
Lawrence Tange407b4c2022-07-21 13:54:01 +0100534 //Context info structure array.
535 json_object *context_info =
536 json_object_object_get(section, "contextInfo");
John Chungf8fc7052024-05-03 20:05:29 +0800537 for (int i = 0; i < section_cper->ContextInfoNum; i++) {
Lawrence Tange407b4c2022-07-21 13:54:01 +0100538 ir_arm_context_info_to_cper(
539 json_object_array_get_idx(context_info, i), out);
John Chungf8fc7052024-05-03 20:05:29 +0800540 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100541
Lawrence Tange407b4c2022-07-21 13:54:01 +0100542 //Vendor specific error info.
543 json_object *vendor_specific_info =
544 json_object_object_get(section, "vendorSpecificInfo");
545 if (vendor_specific_info != NULL) {
546 json_object *vendor_info_string =
547 json_object_object_get(vendor_specific_info, "data");
548 int vendor_specific_len =
549 json_object_get_string_len(vendor_info_string);
Lawrence Tang01e3a442022-07-20 15:14:50 +0100550
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700551 int32_t decoded_len = 0;
552
553 UINT8 *decoded = base64_decode(
554 json_object_get_string(vendor_info_string),
555 vendor_specific_len, &decoded_len);
556
557 //Write out to file.
558 fwrite(decoded, decoded_len, 1, out);
559 fflush(out);
560 free(decoded);
Lawrence Tange407b4c2022-07-21 13:54:01 +0100561 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100562
Lawrence Tange407b4c2022-07-21 13:54:01 +0100563 //Free remaining resources.
564 free(section_cper);
Lawrence Tang7cd13902022-07-13 16:59:25 +0100565}
566
567//Converts a single ARM error information structure into CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100568void ir_arm_error_info_to_cper(json_object *error_info, FILE *out)
Lawrence Tang7cd13902022-07-13 16:59:25 +0100569{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100570 EFI_ARM_ERROR_INFORMATION_ENTRY error_info_cper;
Lawrence Tang7cd13902022-07-13 16:59:25 +0100571
Lawrence Tange407b4c2022-07-21 13:54:01 +0100572 //Version, length.
573 error_info_cper.Version = json_object_get_int(
574 json_object_object_get(error_info, "version"));
575 error_info_cper.Length = json_object_get_int(
576 json_object_object_get(error_info, "length"));
Lawrence Tang7cd13902022-07-13 16:59:25 +0100577
Lawrence Tange407b4c2022-07-21 13:54:01 +0100578 //Validation bits.
579 error_info_cper.ValidationBits = ir_to_bitfield(
580 json_object_object_get(error_info, "validationBits"), 5,
581 ARM_ERROR_INFO_ENTRY_VALID_BITFIELD_NAMES);
Lawrence Tang7cd13902022-07-13 16:59:25 +0100582
Lawrence Tange407b4c2022-07-21 13:54:01 +0100583 //Type, multiple error.
584 error_info_cper.Type = (UINT8)readable_pair_to_integer(
585 json_object_object_get(error_info, "type"));
586 error_info_cper.MultipleError = (UINT16)readable_pair_to_integer(
587 json_object_object_get(error_info, "multipleError"));
Lawrence Tang7cd13902022-07-13 16:59:25 +0100588
Lawrence Tange407b4c2022-07-21 13:54:01 +0100589 //Flags object.
590 error_info_cper.Flags = (UINT8)ir_to_bitfield(
591 json_object_object_get(error_info, "flags"), 4,
592 ARM_ERROR_INFO_ENTRY_FLAGS_NAMES);
Lawrence Tang7cd13902022-07-13 16:59:25 +0100593
Lawrence Tange407b4c2022-07-21 13:54:01 +0100594 //Error information.
595 json_object *error_info_information =
596 json_object_object_get(error_info, "errorInformation");
597 switch (error_info_cper.Type) {
598 case ARM_ERROR_INFORMATION_TYPE_CACHE:
599 case ARM_ERROR_INFORMATION_TYPE_TLB:
600 ir_arm_error_cache_tlb_info_to_cper(
601 error_info_information,
602 &error_info_cper.ErrorInformation.CacheError);
603 break;
Lawrence Tang71570a22022-07-14 11:45:28 +0100604
Lawrence Tange407b4c2022-07-21 13:54:01 +0100605 case ARM_ERROR_INFORMATION_TYPE_BUS:
606 ir_arm_error_bus_info_to_cper(
607 error_info_information,
608 &error_info_cper.ErrorInformation.BusError);
609 break;
Lawrence Tang71570a22022-07-14 11:45:28 +0100610
Lawrence Tange407b4c2022-07-21 13:54:01 +0100611 default:
612 //Unknown error information type.
John Chung0b9c9402024-05-22 22:52:55 +0800613 error_info_cper.ErrorInformation.Value = json_object_get_uint64(
614 json_object_object_get(error_info_information, "data"));
Lawrence Tange407b4c2022-07-21 13:54:01 +0100615 break;
616 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100617
Lawrence Tange407b4c2022-07-21 13:54:01 +0100618 //Virtual/physical fault address.
619 error_info_cper.VirtualFaultAddress = json_object_get_uint64(
620 json_object_object_get(error_info, "virtualFaultAddress"));
621 error_info_cper.PhysicalFaultAddress = json_object_get_uint64(
622 json_object_object_get(error_info, "physicalFaultAddress"));
Lawrence Tang7cd13902022-07-13 16:59:25 +0100623
Lawrence Tange407b4c2022-07-21 13:54:01 +0100624 //Write out to stream.
625 fwrite(&error_info_cper, sizeof(EFI_ARM_ERROR_INFORMATION_ENTRY), 1,
626 out);
627 fflush(out);
Lawrence Tang7cd13902022-07-13 16:59:25 +0100628}
629
Lawrence Tang71570a22022-07-14 11:45:28 +0100630//Converts a single ARM cache/TLB error information structure into a CPER structure.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100631void ir_arm_error_cache_tlb_info_to_cper(
632 json_object *error_information,
633 EFI_ARM_CACHE_ERROR_STRUCTURE *error_info_cper)
Lawrence Tang71570a22022-07-14 11:45:28 +0100634{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100635 //Validation bits.
636 error_info_cper->ValidationBits = ir_to_bitfield(
637 json_object_object_get(error_information, "validationBits"), 7,
638 ARM_CACHE_TLB_ERROR_VALID_BITFIELD_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100639
Lawrence Tange407b4c2022-07-21 13:54:01 +0100640 //Miscellaneous value fields.
641 error_info_cper->TransactionType = readable_pair_to_integer(
642 json_object_object_get(error_information, "transactionType"));
643 error_info_cper->Operation = readable_pair_to_integer(
644 json_object_object_get(error_information, "operation"));
645 error_info_cper->Level = json_object_get_uint64(
646 json_object_object_get(error_information, "level"));
647 error_info_cper->ProcessorContextCorrupt = json_object_get_boolean(
648 json_object_object_get(error_information,
649 "processorContextCorrupt"));
650 error_info_cper->Corrected = json_object_get_boolean(
651 json_object_object_get(error_information, "corrected"));
652 error_info_cper->PrecisePC = json_object_get_boolean(
653 json_object_object_get(error_information, "precisePC"));
654 error_info_cper->RestartablePC = json_object_get_boolean(
655 json_object_object_get(error_information, "restartablePC"));
656 error_info_cper->Reserved = 0;
Lawrence Tang71570a22022-07-14 11:45:28 +0100657}
658
659//Converts a single ARM bus error information structure into a CPER structure.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100660void ir_arm_error_bus_info_to_cper(json_object *error_information,
661 EFI_ARM_BUS_ERROR_STRUCTURE *error_info_cper)
Lawrence Tang71570a22022-07-14 11:45:28 +0100662{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100663 //Validation bits.
664 error_info_cper->ValidationBits = ir_to_bitfield(
665 json_object_object_get(error_information, "validationBits"), 7,
666 ARM_BUS_ERROR_VALID_BITFIELD_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100667
Lawrence Tange407b4c2022-07-21 13:54:01 +0100668 //Miscellaneous value fields.
669 error_info_cper->TransactionType = readable_pair_to_integer(
670 json_object_object_get(error_information, "transactionType"));
671 error_info_cper->Operation = readable_pair_to_integer(
672 json_object_object_get(error_information, "operation"));
673 error_info_cper->Level = json_object_get_uint64(
674 json_object_object_get(error_information, "level"));
675 error_info_cper->ProcessorContextCorrupt = json_object_get_boolean(
676 json_object_object_get(error_information,
677 "processorContextCorrupt"));
678 error_info_cper->Corrected = json_object_get_boolean(
679 json_object_object_get(error_information, "corrected"));
680 error_info_cper->PrecisePC = json_object_get_boolean(
681 json_object_object_get(error_information, "precisePC"));
682 error_info_cper->RestartablePC = json_object_get_boolean(
683 json_object_object_get(error_information, "restartablePC"));
684 error_info_cper->ParticipationType = readable_pair_to_integer(
685 json_object_object_get(error_information, "participationType"));
686 error_info_cper->AddressSpace = readable_pair_to_integer(
687 json_object_object_get(error_information, "addressSpace"));
688 error_info_cper->AccessMode = readable_pair_to_integer(
689 json_object_object_get(error_information, "accessMode"));
690 error_info_cper->MemoryAddressAttributes = json_object_get_uint64(
691 json_object_object_get(error_information, "memoryAttributes"));
692 error_info_cper->Reserved = 0;
Lawrence Tang71570a22022-07-14 11:45:28 +0100693}
694
Lawrence Tang7cd13902022-07-13 16:59:25 +0100695//Converts a single ARM context information structure into CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100696void ir_arm_context_info_to_cper(json_object *context_info, FILE *out)
Lawrence Tang7cd13902022-07-13 16:59:25 +0100697{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100698 EFI_ARM_CONTEXT_INFORMATION_HEADER info_header;
Lawrence Tang7cd13902022-07-13 16:59:25 +0100699
Lawrence Tange407b4c2022-07-21 13:54:01 +0100700 //Version, array size, context type.
701 info_header.Version = json_object_get_int(
702 json_object_object_get(context_info, "version"));
703 info_header.RegisterArraySize = json_object_get_int(
704 json_object_object_get(context_info, "registerArraySize"));
705 info_header.RegisterContextType = readable_pair_to_integer(
706 json_object_object_get(context_info, "registerContextType"));
Lawrence Tang71570a22022-07-14 11:45:28 +0100707
Lawrence Tange407b4c2022-07-21 13:54:01 +0100708 //Flush to stream, write the register array itself.
709 fwrite(&info_header, sizeof(EFI_ARM_CONTEXT_INFORMATION_HEADER), 1,
710 out);
711 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100712
Lawrence Tange407b4c2022-07-21 13:54:01 +0100713 json_object *register_array =
714 json_object_object_get(context_info, "registerArray");
715 switch (info_header.RegisterContextType) {
716 case EFI_ARM_CONTEXT_TYPE_AARCH32_GPR:
717 ir_arm_aarch32_gpr_to_cper(register_array, out);
718 break;
719 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL1:
720 ir_arm_aarch32_el1_to_cper(register_array, out);
721 break;
722 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL2:
723 ir_arm_aarch32_el2_to_cper(register_array, out);
724 break;
725 case EFI_ARM_CONTEXT_TYPE_AARCH32_SECURE:
726 ir_arm_aarch32_secure_to_cper(register_array, out);
727 break;
728 case EFI_ARM_CONTEXT_TYPE_AARCH64_GPR:
729 ir_arm_aarch64_gpr_to_cper(register_array, out);
730 break;
731 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL1:
732 ir_arm_aarch64_el1_to_cper(register_array, out);
733 break;
734 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL2:
735 ir_arm_aarch64_el2_to_cper(register_array, out);
736 break;
737 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL3:
738 ir_arm_aarch64_el3_to_cper(register_array, out);
739 break;
740 case EFI_ARM_CONTEXT_TYPE_MISC:
741 ir_arm_misc_registers_to_cper(register_array, out);
742 break;
743 default:
744 //Unknown register structure.
John Chungf8fc7052024-05-03 20:05:29 +0800745 ir_arm_unknown_register_to_cper(register_array, out);
Lawrence Tange407b4c2022-07-21 13:54:01 +0100746 break;
747 }
Lawrence Tang71570a22022-07-14 11:45:28 +0100748}
749
750//Converts a single AARCH32 GPR CPER-JSON object to CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100751void ir_arm_aarch32_gpr_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100752{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100753 //Get uniform register array.
754 EFI_ARM_V8_AARCH32_GPR reg_array;
755 ir_to_uniform_struct(registers, (UINT32 *)&reg_array,
756 sizeof(EFI_ARM_V8_AARCH32_GPR) / sizeof(UINT32),
757 ARM_AARCH32_GPR_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100758
Lawrence Tange407b4c2022-07-21 13:54:01 +0100759 //Flush to stream.
760 fwrite(&reg_array, sizeof(reg_array), 1, out);
761 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100762}
763
764//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 +0100765void ir_arm_aarch32_el1_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100766{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100767 //Get uniform register array.
768 EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS reg_array;
769 ir_to_uniform_struct(registers, (UINT32 *)&reg_array,
770 sizeof(EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS) /
771 sizeof(UINT32),
772 ARM_AARCH32_EL1_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100773
Lawrence Tange407b4c2022-07-21 13:54:01 +0100774 //Flush to stream.
775 fwrite(&reg_array, sizeof(reg_array), 1, out);
776 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100777}
778
779//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 +0100780void ir_arm_aarch32_el2_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100781{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100782 //Get uniform register array.
783 EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS reg_array;
784 ir_to_uniform_struct(registers, (UINT32 *)&reg_array,
785 sizeof(EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS) /
786 sizeof(UINT32),
787 ARM_AARCH32_EL2_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100788
Lawrence Tange407b4c2022-07-21 13:54:01 +0100789 //Flush to stream.
790 fwrite(&reg_array, sizeof(reg_array), 1, out);
791 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100792}
793
794//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 +0100795void ir_arm_aarch32_secure_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100796{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100797 //Get uniform register array.
798 EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS reg_array;
799 ir_to_uniform_struct(registers, (UINT32 *)&reg_array,
800 sizeof(EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS) /
801 sizeof(UINT32),
802 ARM_AARCH32_SECURE_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100803
Lawrence Tange407b4c2022-07-21 13:54:01 +0100804 //Flush to stream.
805 fwrite(&reg_array, sizeof(reg_array), 1, out);
806 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100807}
808
809//Converts a single AARCH64 GPR CPER-JSON object to CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100810void ir_arm_aarch64_gpr_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100811{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100812 //Get uniform register array.
813 EFI_ARM_V8_AARCH64_GPR reg_array;
814 ir_to_uniform_struct64(registers, (UINT64 *)&reg_array,
815 sizeof(EFI_ARM_V8_AARCH64_GPR) / sizeof(UINT64),
816 ARM_AARCH64_GPR_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100817
Lawrence Tange407b4c2022-07-21 13:54:01 +0100818 //Flush to stream.
819 fwrite(&reg_array, sizeof(reg_array), 1, out);
820 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100821}
822
823//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 +0100824void ir_arm_aarch64_el1_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100825{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100826 //Get uniform register array.
827 EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS reg_array;
828 ir_to_uniform_struct64(registers, (UINT64 *)&reg_array,
829 sizeof(EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS) /
830 sizeof(UINT64),
831 ARM_AARCH64_EL1_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100832
Lawrence Tange407b4c2022-07-21 13:54:01 +0100833 //Flush to stream.
834 fwrite(&reg_array, sizeof(reg_array), 1, out);
835 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100836}
837
838//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 +0100839void ir_arm_aarch64_el2_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100840{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100841 //Get uniform register array.
842 EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS reg_array;
843 ir_to_uniform_struct64(registers, (UINT64 *)&reg_array,
844 sizeof(EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS) /
845 sizeof(UINT64),
846 ARM_AARCH64_EL2_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100847
Lawrence Tange407b4c2022-07-21 13:54:01 +0100848 //Flush to stream.
849 fwrite(&reg_array, sizeof(reg_array), 1, out);
850 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100851}
852
853//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 +0100854void ir_arm_aarch64_el3_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100855{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100856 //Get uniform register array.
857 EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS reg_array;
858 ir_to_uniform_struct64(registers, (UINT64 *)&reg_array,
859 sizeof(EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS) /
860 sizeof(UINT64),
861 ARM_AARCH64_EL3_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100862
Lawrence Tange407b4c2022-07-21 13:54:01 +0100863 //Flush to stream.
864 fwrite(&reg_array, sizeof(reg_array), 1, out);
865 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100866}
867
868//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 +0100869void ir_arm_misc_registers_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100870{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100871 EFI_ARM_MISC_CONTEXT_REGISTER reg_array;
Lawrence Tang71570a22022-07-14 11:45:28 +0100872
Lawrence Tange407b4c2022-07-21 13:54:01 +0100873 //MRS encoding information.
874 json_object *mrs_encoding =
875 json_object_object_get(registers, "mrsEncoding");
876 reg_array.MrsOp2 = json_object_get_uint64(
877 json_object_object_get(mrs_encoding, "op2"));
878 reg_array.MrsCrm = json_object_get_uint64(
879 json_object_object_get(mrs_encoding, "crm"));
880 reg_array.MrsCrn = json_object_get_uint64(
881 json_object_object_get(mrs_encoding, "crn"));
882 reg_array.MrsOp1 = json_object_get_uint64(
883 json_object_object_get(mrs_encoding, "op1"));
884 reg_array.MrsO0 = json_object_get_uint64(
885 json_object_object_get(mrs_encoding, "o0"));
Lawrence Tang71570a22022-07-14 11:45:28 +0100886
Lawrence Tange407b4c2022-07-21 13:54:01 +0100887 //Actual register value.
888 reg_array.Value = json_object_get_uint64(
889 json_object_object_get(registers, "value"));
Lawrence Tang71570a22022-07-14 11:45:28 +0100890
Lawrence Tange407b4c2022-07-21 13:54:01 +0100891 //Flush to stream.
892 fwrite(&reg_array, sizeof(reg_array), 1, out);
893 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100894}
895
896//Converts a single ARM unknown register CPER-JSON object to CPER binary, outputting to the given stream.
John Chungf8fc7052024-05-03 20:05:29 +0800897void ir_arm_unknown_register_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100898{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100899 //Get base64 represented data.
900 json_object *encoded = json_object_object_get(registers, "data");
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700901
902 int32_t decoded_len = 0;
903
904 UINT8 *decoded = base64_decode(json_object_get_string(encoded),
905 json_object_get_string_len(encoded),
906 &decoded_len);
907
908 if (decoded == NULL) {
John Chungf8fc7052024-05-03 20:05:29 +0800909 printf("Failed to allocate decode output buffer. \n");
910 } else {
John Chungf8fc7052024-05-03 20:05:29 +0800911 //Flush out to stream.
912 fwrite(&decoded, decoded_len, 1, out);
913 fflush(out);
914 free(decoded);
915 }
916}